Skip to content

Commit 64694ed

Browse files
jfrog-agentic-release-bot[bot]sankerrcursoragent
authored
[patch] agent-hooks v0.12.1: Add Codex SessionStart support (#29)
* [patch] chore: sync modules to v0.12.1 * Add Agent Package Resolution SessionStart hook assembly Co-authored-by: Cursor <cursoragent@cursor.com> * Align Verify and Recovery wording with Claude plugin README. Drop the routing-mode qualifier on jf rt ping and the modules/ recovery row so the two plugin READMEs stay in lockstep. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: jfrog-skills-release-bot[bot] <276080306+jfrog-skills-release-bot[bot]@users.noreply.github.com> Co-authored-by: Roee Sanker <roees@jfrog.com> Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 16da934 commit 64694ed

46 files changed

Lines changed: 9961 additions & 7 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.codex-plugin/plugin.json‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "jfrog",
3-
"version": "0.1.9",
3+
"version": "0.1.10",
44
"description": "JFrog skills and the JFrog MCP server for Codex \u2014 interact with the JFrog Platform.",
55
"author": {
66
"name": "JFrog",
@@ -14,10 +14,12 @@
1414
"codex",
1515
"plugin",
1616
"skills",
17-
"mcp"
17+
"mcp",
18+
"package-resolution"
1819
],
1920
"skills": "./skills/",
2021
"mcpServers": "./.mcp.json",
22+
"hooks": "./hooks/hooks.json",
2123
"interface": {
2224
"displayName": "JFrog",
2325
"shortDescription": "JFrog Platform skills for Codex",
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"repo": "JFROG/jfrog-agent-hooks",
3+
"pin": "jfrog-agent-hooks/v0.12.1",
4+
"paths": [
5+
"modules"
6+
]
7+
}

‎.github/scripts/sync-modules.mjs‎

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#!/usr/bin/env node
2+
// Vendors modules bundle from jfrog-agent-hooks into this plugin.
3+
//
4+
// Usage:
5+
// JFROG_AGENT_HOOKS_PATH=/path/to/jfrog-agent-hooks node .github/scripts/sync-modules.mjs
6+
//
7+
// Defaults JFROG_AGENT_HOOKS_PATH to ../jfrog-agent-hooks (sibling clone).
8+
// Reads paths from sync-modules-vendor.json.
9+
10+
import { promises as fs } from "node:fs";
11+
import path from "node:path";
12+
import { fileURLToPath } from "node:url";
13+
14+
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
15+
const repoRoot = path.resolve(scriptDir, "..", "..");
16+
const vendorPath = path.join(scriptDir, "sync-modules-vendor.json");
17+
18+
async function fileExists(p) {
19+
try {
20+
await fs.access(p);
21+
return true;
22+
} catch {
23+
return false;
24+
}
25+
}
26+
27+
async function copyPath(fromDir, toDir, relativePath) {
28+
const from = path.join(fromDir, relativePath);
29+
const to = path.join(toDir, relativePath);
30+
if (!(await fileExists(from))) {
31+
throw new Error(`path missing in upstream: ${relativePath}`);
32+
}
33+
await fs.rm(to, { recursive: true, force: true });
34+
await fs.mkdir(path.dirname(to), { recursive: true });
35+
await fs.cp(from, to, { recursive: true });
36+
console.log(` ${relativePath} -> ${path.relative(process.cwd(), to)}`);
37+
}
38+
39+
async function main() {
40+
const vendor = JSON.parse(await fs.readFile(vendorPath, "utf8"));
41+
const paths = vendor.paths;
42+
if (!Array.isArray(paths) || paths.length === 0) {
43+
throw new Error(`${vendorPath} must define a non-empty paths array`);
44+
}
45+
46+
const hooksRoot =
47+
process.env.JFROG_AGENT_HOOKS_PATH?.trim() ||
48+
path.resolve(repoRoot, "..", "jfrog-agent-hooks");
49+
50+
if (!(await fileExists(hooksRoot))) {
51+
throw new Error(
52+
`jfrog-agent-hooks not found at ${hooksRoot}. Set JFROG_AGENT_HOOKS_PATH.`,
53+
);
54+
}
55+
56+
const destPrefix = (vendor.dest_prefix ?? "").replace(/^\/+|\/+$/g, "");
57+
const destRoot = destPrefix ? path.join(repoRoot, destPrefix) : repoRoot;
58+
59+
console.log(`--- sync from ${hooksRoot} (pin: ${vendor.pin ?? "local"}) ---`);
60+
for (const rel of paths) {
61+
await copyPath(hooksRoot, destRoot, rel);
62+
}
63+
console.log("done.");
64+
}
65+
66+
await main();

‎README.md‎

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ The JFrog plugin provides the following capabilities, grouped by component:
1212
| **MCP** | JFrog MCP server | Bundled `jfrog` MCP server ([`.mcp.json`](.mcp.json)) at `https://<JFROG_PLATFORM_URL>/mcp`; this server signs in via OAuth (`codex mcp login jfrog`), so it needs no API key. |
1313
| **Skill** | JFrog Platform | Interact with Artifactory repositories, builds, permissions, users, access tokens, projects, release bundles, and platform administration via the JFrog CLI and REST/GraphQL APIs. Also covers security audits, CVE lookups, and Advanced Security exposure queries. |
1414
| **Skill** | Package curation | Check whether npm, Maven, PyPI, Go, and other packages are safe, curated, or allowed, then download them through Artifactory remote caches or curation-aware package managers. |
15+
| **Hook + Skill** | Agent Package Resolution (Preview) | Automatically route packages installed by the AI agent through your organization's JFrog Artifactory, keeping agent-driven installs inside your Curation, Xray, and governance perimeter. |
1516
| **Skill** | Agent Guard | Codex manages MCPs through the JFrog Agent Guard. Through the Agent Guard you can discover, install, configure, update, and remove MCP servers from the JFrog AI Catalog approved for your project, and authenticate to remote HTTP MCPs via OAuth, API key, or bearer token. |
1617

1718
---
@@ -41,7 +42,10 @@ codex plugin marketplace add jfrog/codex-plugin
4142
codex plugin add jfrog@codex-plugin
4243
```
4344

44-
Browse installed plugins in the Codex TUI with `/plugins`.
45+
Browse installed plugins in the Codex TUI with `/plugins`. Installing the plugin
46+
does **not** trust the SessionStart hook — restart Codex, run `/hooks`, and
47+
trust the JFrog Package Resolution command. ChatGPT **web** does not run hook
48+
scripts.
4549

4650
### Local development
4751

@@ -116,9 +120,13 @@ restarting Codex, confirm:
116120
JFrog skills appear. See [Discovering and invoking skills](#discovering-and-invoking-skills).
117121
3. **MCP server is connected** — run `codex mcp list` and confirm `jfrog` is
118122
connected (after `codex mcp login jfrog`).
123+
4. **SessionStart hook is trusted** — `/hooks` lists the JFrog Package Resolution
124+
command as trusted. Without that, Agent Package Resolution does not inject.
125+
5. `jf rt ping` — succeeds against your configured server.
119126

120127
If any check fails, see [Recovery](#recovery). Setting MCP environment variables
121-
by hand does not repair a failed initialization — re-run `jfrog-init` instead.
128+
by hand does not repair a failed MCP initialization — re-run `jfrog-init`
129+
instead. An untrusted SessionStart hook is a `/hooks` step, not an init failure.
122130

123131
---
124132

@@ -130,6 +138,23 @@ by hand does not repair a failed initialization — re-run `jfrog-init` instead.
130138
| `jfrog-init` stopped at CLI/auth | Follow the skill prompt (`jf config add`, web login, or token path), then **re-run `jfrog-init`**. | Skip init and only export env vars. |
131139
| Placeholder still in `.mcp.json` | Set the host in `<install-path>/.mcp.json`, run `codex mcp login jfrog`, restart Codex. | Reinstall the plugin when only the host placeholder is wrong. |
132140
| Plugin not listed | Re-run `codex plugin add jfrog@codex-plugin` outside Codex, then restart Codex. | Run install commands from inside the Codex TUI. |
141+
| `/hooks` shows the Package Resolution command as untrusted, or no Artifactory routing in a new session | Restart Codex, open `/hooks`, and trust the exact command. A later change to the hook definition requires trust again. | Assume `codex plugin add` approved the hook. Do not use `--dangerously-bypass-hook-trust` as the normal path. |
142+
| ChatGPT web never routes installs | Use Codex CLI or the ChatGPT desktop Codex surface. | Expect hook scripts to run on ChatGPT web. |
143+
144+
---
145+
146+
## Agent Package Resolution (Preview)
147+
148+
> **Preview Notice:** This feature is in preview and licensed under the Apache License 2.0. For clarity: This software is provided "as-is" without warranty of any kind, and without support obligations or service level commitments. Behavior, APIs, conventions, and structure may change without notice between releases. JFrog makes no guarantees of backward compatibility during the preview release cycle. Use in production environments is at your own risk.
149+
150+
The plugin can now automatically route the packages your AI agent installs (npm, PyPI, Maven, Go, Docker, Helm, and NuGet) through your organization's JFrog Artifactory instead of public registries. This keeps agent-driven dependency installs inside your organization's governance perimeter.
151+
152+
Agent Package Resolution is in preview. The shipped template enables it with empty repository bindings (nothing is routed until Consent Enable or an admin adds `defaultGlobalRepos`). To get started:
153+
154+
- **Users:** see the [User Guide](docs/package-resolution-user-guide.md).
155+
- **Admins:** see the [Admin Guide](docs/package-resolution-admin-guide.md).
156+
157+
Installing the plugin does not skip `/hooks` trust. ChatGPT **web** does not run the SessionStart hook.
133158

134159
---
135160

@@ -170,6 +195,16 @@ If a newly installed skill doesn't show up, restart Codex so it re-scans plugins
170195
| "Is this Maven package approved for use?" | Checks curation entitlement and policy for the requested package. |
171196
| "Download `requests` via JFrog." | Resolves the package through an Artifactory remote cache or curation-aware package manager. |
172197

198+
### Agent Package Resolution
199+
200+
When Agent Package Resolution is enabled and configured, no special prompt syntax is required. Ask the agent to install or use a package as you normally would, and the plugin routes supported package operations through your organization's Artifactory.
201+
202+
| Ask the agent… | What happens |
203+
| -------------------------------------- | ------------------------------------------------------------------------ |
204+
| "Add `lodash` to this project." | Resolves the npm package through the configured Artifactory repository. |
205+
| "Add Excel file import to this app." | The agent selects a suitable package and resolves it through the configured Artifactory repository. |
206+
| "Pull the `alpine` Docker image." | Pulls the image through the configured Artifactory Docker repository. |
207+
173208
### MCP server management (Agent Guard)
174209

175210
| Ask the agent… | What happens |
@@ -221,6 +256,19 @@ To pull a newer upstream release into this repo:
221256

222257
See [`VENDOR.md`](VENDOR.md) for the full picture.
223258

259+
### Updating the vendored modules
260+
261+
The `modules/` tree is vendored from GHE `jfrog-agent-hooks` at the pin in
262+
[`.github/scripts/sync-modules-vendor.json`](.github/scripts/sync-modules-vendor.json).
263+
Automated `chore/sync-modules-v*` PRs replace that tree. To refresh locally:
264+
265+
```bash
266+
JFROG_AGENT_HOOKS_PATH=/path/to/jfrog-agent-hooks node .github/scripts/sync-modules.mjs
267+
```
268+
269+
Do not hand-edit files under `modules/`. `hooks/hooks.json` is owned by this
270+
repo and is not part of the vendor slice.
271+
224272
---
225273

226274
## Releasing

‎VENDOR.md‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,26 @@ node scripts/sync-skills.mjs
3232
```
3333

3434
The script reads its sibling [`sync-skills-vendor.json`](scripts/sync-skills-vendor.json), downloads the pinned upstream tarball from `codeload.github.com`, and replaces the directories listed in `paths` (today: `skills/`).
35+
36+
---
37+
38+
# Vendored modules
39+
40+
The `modules/` bundle is vendored from **jfrog-agent-hooks** (GHE) and committed to `main`.
41+
42+
| | |
43+
| --- | --- |
44+
| **Repository** | `github.jfrog.info/JFROG/jfrog-agent-hooks` |
45+
| **Pinned release** | see `pin` in [`.github/scripts/sync-modules-vendor.json`](.github/scripts/sync-modules-vendor.json) |
46+
47+
The bundle contains harness runners (`core/`, `*-session-start.mjs`), the `package-resolution/` capability, and `assets/agents-default-conf.json`. Automated sync PRs (`chore/sync-modules-v*`) update this tree on each `jfrog-agent-hooks` release.
48+
49+
`hooks/hooks.json` is **not** part of the vendor slice. Sync replaces `modules/` only; this plugin owns the Codex SessionStart assembly (APR only — no Agent Guard / MCP-align scripts).
50+
51+
## Refreshing modules
52+
53+
```bash
54+
JFROG_AGENT_HOOKS_PATH=/path/to/jfrog-agent-hooks node .github/scripts/sync-modules.mjs
55+
```
56+
57+
The script reads `paths` from `sync-modules-vendor.json` (today: `["modules"]`) and replaces the whole `modules/` tree. After a local refresh, stamp `PKG_VERSION` and the pin with the official copy script if you are matching a Sync Plugins drop. A hand refresh copies bytes only; it does not bump plugin versions.

0 commit comments

Comments
 (0)