Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/scripts/sync-modules-vendor.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"repo": "github.jfrog.info/JFROG/jfrog-agent-hooks",
"pin": "master",
"dest_prefix": "plugins/jfrog",
"paths": [
"modules"
]
}
66 changes: 66 additions & 0 deletions .github/scripts/sync-modules.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/usr/bin/env node
// Vendors modules bundle from jfrog-agent-hooks into plugins/jfrog/.
//
// Usage:
// JFROG_AGENT_HOOKS_PATH=/path/to/jfrog-agent-hooks node .github/scripts/sync-modules.mjs
//
// Defaults JFROG_AGENT_HOOKS_PATH to ../jfrog-agent-hooks (sibling clone).
// Reads paths from sync-modules-vendor.json.

import { promises as fs } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";

const scriptDir = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = path.resolve(scriptDir, "..", "..");
const vendorPath = path.join(scriptDir, "sync-modules-vendor.json");

async function fileExists(p) {
try {
await fs.access(p);
return true;
} catch {
return false;
}
}

async function copyPath(fromDir, toDir, relativePath) {
const from = path.join(fromDir, relativePath);
const to = path.join(toDir, relativePath);
if (!(await fileExists(from))) {
throw new Error(`path missing in upstream: ${relativePath}`);
}
await fs.rm(to, { recursive: true, force: true });
await fs.mkdir(path.dirname(to), { recursive: true });
await fs.cp(from, to, { recursive: true });
console.log(` ${relativePath} -> ${path.relative(process.cwd(), to)}`);
}

async function main() {
const vendor = JSON.parse(await fs.readFile(vendorPath, "utf8"));
const paths = vendor.paths;
if (!Array.isArray(paths) || paths.length === 0) {
throw new Error(`${vendorPath} must define a non-empty paths array`);
}

const hooksRoot =
process.env.JFROG_AGENT_HOOKS_PATH?.trim() ||
path.resolve(repoRoot, "..", "jfrog-agent-hooks");

if (!(await fileExists(hooksRoot))) {
throw new Error(
`jfrog-agent-hooks not found at ${hooksRoot}. Set JFROG_AGENT_HOOKS_PATH.`,
);
}

const destPrefix = (vendor.dest_prefix ?? "").replace(/^\/+|\/+$/g, "");
const destRoot = destPrefix ? path.join(repoRoot, destPrefix) : repoRoot;

console.log(`--- sync from ${hooksRoot} (pin: ${vendor.pin ?? "local"}) ---`);
for (const rel of paths) {
await copyPath(hooksRoot, destRoot, rel);
}
console.log("done.");
}

await main();
21 changes: 21 additions & 0 deletions VENDOR.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,24 @@ node .github/scripts/sync-skills.mjs
```

The script reads its sibling `sync-skills-vendor.json`, downloads the pinned upstream tarball from `codeload.github.com`, and replaces the directories listed in `paths` (today: `skills/`) under `plugins/jfrog/`.

---

# Vendored modules

The `plugins/jfrog/modules/` bundle is vendored from **jfrog-agent-hooks** (GHE) and committed to `main`.

| | |
| --- | --- |
| **Repository** | `github.jfrog.info/JFROG/jfrog-agent-hooks` |
| **Pinned release** | see `pin` in [`.github/scripts/sync-modules-vendor.json`](.github/scripts/sync-modules-vendor.json) |

The bundle contains harness runners (`core/`, `cursor-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.

## Refreshing modules

```bash
JFROG_AGENT_HOOKS_PATH=/path/to/jfrog-agent-hooks node .github/scripts/sync-modules.mjs
```

The script reads `paths` from `sync-modules-vendor.json` (today: `["modules"]`) and replaces the whole `plugins/jfrog/modules/` tree.
3 changes: 2 additions & 1 deletion plugins/jfrog/.cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "jfrog",
"displayName": "JFrog Platform",
"version": "0.5.4",
"description": "JFrog Platform integration with MCP, security skills, supply-chain best practices, and JFrog Agent Guard governance for adding, removing, and listing MCP servers.",
"description": "JFrog Platform integration with MCP, security skills, Agent Package Resolution, supply-chain best practices, and JFrog Agent Guard governance for adding, removing, and listing MCP servers.",
"author": {
"name": "JFrog",
"email": "devrel@jfrog.com"
Expand All @@ -15,6 +15,7 @@
"security",
"mcp",
"agent-guard",
"package-resolution",
"supply-chain",
"devops",
"artifacts",
Expand Down
4 changes: 4 additions & 0 deletions plugins/jfrog/hooks/hooks.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
"version": 1,
"hooks": {
"sessionStart": [
{
"command": "node \"./modules/cursor-session-start.mjs\" package-resolution",
"timeout": 7
},
{
"command": "node \"./scripts/inject-instructions.mjs\"",
"timeout": 7
Expand Down
Loading