@ken-jo/agent-connector 0.4.99 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -7
- package/dist/{action-5OEM3QC4.js → action-LEYTHNIU.js} +2 -2
- package/dist/{audit-BO7JQYIH.js → audit-HPKCUCES.js} +2 -2
- package/dist/{chunk-BV5WK6VQ.js → chunk-T5AI3AW3.js} +18 -18
- package/dist/chunk-T5AI3AW3.js.map +1 -0
- package/dist/{chunk-N4STCQGP.js → chunk-U2XJWG7N.js} +448 -70
- package/dist/chunk-U2XJWG7N.js.map +1 -0
- package/dist/{chunk-KLZBRNFP.js → chunk-WZMSSIDN.js} +51 -34
- package/dist/chunk-WZMSSIDN.js.map +1 -0
- package/dist/cli/sdk.js +1 -1
- package/dist/cli.js +1 -1
- package/dist/{detect-ALP4G7WG.js → detect-USP5JMWM.js} +2 -2
- package/dist/{doctor-YEQWCWZJ.js → doctor-VSW5KHBM.js} +4 -4
- package/dist/{hook-F63I3SD5.js → hook-QRW3ON6C.js} +2 -2
- package/dist/{install-23WRRFBY.js → install-ASTAUZKB.js} +4 -4
- package/dist/{leaderboard-YBD3IKC2.js → leaderboard-3XSVSGAJ.js} +2 -2
- package/dist/{package-TAUTPP7Z.js → package-VWBPHCLA.js} +20 -12
- package/dist/package-VWBPHCLA.js.map +1 -0
- package/dist/{serve-6MDLRQS2.js → serve-IQGHE4SJ.js} +2 -2
- package/dist/{status-IUP75XHP.js → status-BVLY6XDL.js} +2 -2
- package/dist/{telemetry-X4PLZEDB.js → telemetry-UU4SHJ23.js} +2 -2
- package/dist/{uninstall-BSIJ4QXN.js → uninstall-WI5YLDCT.js} +4 -4
- package/dist/{upgrade-ZSICU3NE.js → upgrade-L45BTG6X.js} +4 -4
- package/dist/{usage-EQUNVSCT.js → usage-K3NQTAJP.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-BV5WK6VQ.js.map +0 -1
- package/dist/chunk-KLZBRNFP.js.map +0 -1
- package/dist/chunk-N4STCQGP.js.map +0 -1
- package/dist/package-TAUTPP7Z.js.map +0 -1
- /package/dist/{action-5OEM3QC4.js.map → action-LEYTHNIU.js.map} +0 -0
- /package/dist/{audit-BO7JQYIH.js.map → audit-HPKCUCES.js.map} +0 -0
- /package/dist/{detect-ALP4G7WG.js.map → detect-USP5JMWM.js.map} +0 -0
- /package/dist/{doctor-YEQWCWZJ.js.map → doctor-VSW5KHBM.js.map} +0 -0
- /package/dist/{hook-F63I3SD5.js.map → hook-QRW3ON6C.js.map} +0 -0
- /package/dist/{install-23WRRFBY.js.map → install-ASTAUZKB.js.map} +0 -0
- /package/dist/{leaderboard-YBD3IKC2.js.map → leaderboard-3XSVSGAJ.js.map} +0 -0
- /package/dist/{serve-6MDLRQS2.js.map → serve-IQGHE4SJ.js.map} +0 -0
- /package/dist/{status-IUP75XHP.js.map → status-BVLY6XDL.js.map} +0 -0
- /package/dist/{telemetry-X4PLZEDB.js.map → telemetry-UU4SHJ23.js.map} +0 -0
- /package/dist/{uninstall-BSIJ4QXN.js.map → uninstall-WI5YLDCT.js.map} +0 -0
- /package/dist/{upgrade-ZSICU3NE.js.map → upgrade-L45BTG6X.js.map} +0 -0
- /package/dist/{usage-EQUNVSCT.js.map → usage-K3NQTAJP.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/package.ts","../src/core/package-formats/claude-family.ts","../src/core/package-formats/shared.ts","../src/core/package-formats/cursor.ts","../src/core/package-formats/gemini.ts","../src/core/package-formats/agy.ts","../src/core/package-formats/kimi.ts","../src/core/package-formats/npm.ts","../src/core/package-formats/agent-plugin.ts","../src/core/package-formats/mcp-server.ts","../src/core/package-formats/mcpb.ts"],"sourcesContent":["/**\n * core/package — emit a marketplace/extension-installable connector bundle.\n *\n * Turns a {@link ResolvedConnector} into a self-contained plugin/extension bundle\n * for ANY of the emit-feasible plugin/marketplace formats the agent ecosystem\n * supports. The format-specific emitters live under `package-formats/<family>.ts`,\n * each conforming to the shared {@link FormatEmitter} signature; this module is\n * the single, consistent dispatch over them.\n *\n * Supported formats (PackageFormat):\n * • agent-plugin — Agent Plugins 1.0.0 (agent-plugins.org), the DEFAULT and\n * the single source of truth for every spec-speaking host:\n * Codex, GitHub Copilot CLI, VS Code / JetBrains Copilot,\n * Kiro, Hermes, Cursor, OpenClaw, … (plugin.json + mcp.json\n * + skills/ + per-client extension namespaces; NO absolute\n * path embedded — a portable launcher resolves the runtime)\n * • claude-plugin — Claude Code / omp / openclaw (`.claude-plugin/` manifest)\n * • factory-plugin — droid `.factory-plugin/` (droids/, mcp.json) variant\n * • gemini-extension — Gemini CLI extension (gemini-extension.json + TOML commands)\n * • qwen-extension — Qwen Code extension (qwen-extension.json + Markdown commands)\n * • agy-plugin — Antigravity CLI/IDE (root plugin.json + mcp_config.json)\n * • cursor-plugin — Cursor (.cursor-plugin/ + pointer fields + marketplace.json)\n * • kimi-plugin — Kimi (skills + MCP only; hooks/commands/subagents dropped)\n * • npm-plugin — opencode / kilo-cli / pi (publishable npm package + bridge)\n *\n * Retired formats (LEGACY_FORMAT_ALIASES): `codex-plugin` and `copilot-plugin`\n * were per-host copies of the claude-plugin tree with a different manifest dir\n * or --host stamp. Both hosts read the Agent Plugins bundle natively, so the\n * names now resolve to `agent-plugin` (with a deprecation note) instead of\n * emitting a second, drifting layout.\n *\n * The command / skill / subagent markdown is rendered through the SAME shared\n * claude-code renderers the live adapters write with (where the target uses\n * markdown), hooks via buildHomeBinHookCommand, and MCP via buildServeWrapperCommand\n * with `--host <platform>` — so telemetry-wrap + the universal home-bin pointer\n * carry through every bundle exactly as an `agent-connector install` would.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\n\nimport type { PlatformId, ResolvedConnector } from \"./types.js\";\nimport { homeBinPath as defaultHomeBinPath } from \"./paths.js\";\nimport type { EmitContext, FormatEmitter, PackageResult } from \"./package-formats/shared.js\";\nimport { emitClaudePlugin, emitFactoryPlugin } from \"./package-formats/claude-family.js\";\nimport { emitCursorPlugin } from \"./package-formats/cursor.js\";\nimport {\n emitGeminiExtension,\n emitQwenExtension,\n} from \"./package-formats/gemini.js\";\nimport { emitAgyPlugin } from \"./package-formats/agy.js\";\nimport { emitKimiPlugin } from \"./package-formats/kimi.js\";\nimport { emitNpmPlugin } from \"./package-formats/npm.js\";\nimport { emitAgentPlugin } from \"./package-formats/agent-plugin.js\";\nimport { emitMcpServerJson } from \"./package-formats/mcp-server.js\";\nimport { emitMcpbBundle } from \"./package-formats/mcpb.js\";\n\nexport type { PackageResult } from \"./package-formats/shared.js\";\n\n/** Every packaging format `package` can emit. */\nexport type PackageFormat =\n // The portable Agent Plugins 1.0.0 package (agent-plugins.org) — one bundle\n // every conforming client installs; no host restamp, no absolute path.\n | \"agent-plugin\"\n | \"claude-plugin\"\n | \"factory-plugin\"\n | \"gemini-extension\"\n | \"qwen-extension\"\n | \"agy-plugin\"\n | \"cursor-plugin\"\n | \"kimi-plugin\"\n | \"npm-plugin\"\n // Official MCP standard artifacts (describe the dev's REAL upstream server,\n // not our serve wrapper; require `publish` metadata, so they are opt-in and\n // excluded from `--format all`).\n | \"mcp-server-json\"\n | \"mcpb\";\n\n/** The format `package` emits when none is requested. */\nexport const DEFAULT_PACKAGE_FORMAT: PackageFormat = \"agent-plugin\";\n\n/**\n * Retired format names → the format that replaced them. Accepted everywhere a\n * format name is parsed so existing scripts keep working; callers surface the\n * deprecation via {@link resolvePackageFormat}.\n */\nexport const LEGACY_FORMAT_ALIASES: Readonly<Record<string, PackageFormat>> = {\n \"codex-plugin\": \"agent-plugin\",\n \"copilot-plugin\": \"agent-plugin\",\n};\n\n/** The single consistent dispatch map: format → emitter. */\nconst EMITTERS: Record<PackageFormat, FormatEmitter> = {\n \"agent-plugin\": emitAgentPlugin,\n \"claude-plugin\": emitClaudePlugin,\n \"factory-plugin\": emitFactoryPlugin,\n \"gemini-extension\": emitGeminiExtension,\n \"qwen-extension\": emitQwenExtension,\n \"agy-plugin\": emitAgyPlugin,\n \"cursor-plugin\": emitCursorPlugin,\n \"kimi-plugin\": emitKimiPlugin,\n \"npm-plugin\": emitNpmPlugin,\n \"mcp-server-json\": emitMcpServerJson,\n mcpb: emitMcpbBundle,\n};\n\n/** All formats, in a stable, documented order. */\nexport const ALL_FORMATS: readonly PackageFormat[] = [\n \"agent-plugin\",\n \"claude-plugin\",\n \"factory-plugin\",\n \"gemini-extension\",\n \"qwen-extension\",\n \"agy-plugin\",\n \"cursor-plugin\",\n \"kimi-plugin\",\n \"npm-plugin\",\n \"mcp-server-json\",\n \"mcpb\",\n] as const;\n\n/**\n * The formats `--format all` emits — the host plugin/marketplace bundles that\n * work for ANY connector. The official MCP standard artifacts (mcp-server-json,\n * and the MCPB bundle) are deliberately EXCLUDED: they require `publish`\n * metadata (a namespace the dev owns, their published package) and would error\n * for a connector that has not opted into publishing, so they are emitted only\n * when requested explicitly by name.\n */\nexport const FEASIBLE_FORMATS: readonly PackageFormat[] = [\n \"agent-plugin\",\n \"claude-plugin\",\n \"factory-plugin\",\n \"gemini-extension\",\n \"qwen-extension\",\n \"agy-plugin\",\n \"cursor-plugin\",\n \"kimi-plugin\",\n \"npm-plugin\",\n] as const;\n\n/** Type guard: is `s` a supported {@link PackageFormat}? */\nexport function isPackageFormat(s: string): s is PackageFormat {\n return Object.prototype.hasOwnProperty.call(EMITTERS, s);\n}\n\n/**\n * Resolve a user-supplied format name: a live format returns itself; a retired\n * alias returns its replacement plus a deprecation message; anything else\n * returns null.\n */\nexport function resolvePackageFormat(\n s: string,\n): { format: PackageFormat; deprecation?: string } | null {\n if (isPackageFormat(s)) return { format: s };\n const replacement = Object.prototype.hasOwnProperty.call(LEGACY_FORMAT_ALIASES, s)\n ? LEGACY_FORMAT_ALIASES[s]\n : undefined;\n if (replacement === undefined) return null;\n return {\n format: replacement,\n deprecation: `--format ${s} is retired — emitting ${replacement} instead (the Agent Plugins 1.0.0 bundle both Codex and GitHub Copilot install natively)`,\n };\n}\n\nexport interface PackageOptions {\n /** Directory the bundle is written under (the format root). */\n outDir: string;\n /** Output format. Defaults to {@link DEFAULT_PACKAGE_FORMAT} (agent-plugin). */\n format?: PackageFormat;\n /**\n * Absolute path to agent-connector's stable home-bin that hooks + the MCP\n * serve-wrapper point at. Defaults to {@link defaultHomeBinPath}.\n */\n homeBinPath?: string;\n /** Compute the file list without writing anything. */\n dryRun?: boolean;\n /**\n * The host the bundle is being staged FOR, when known (the marketplace\n * drivers pass their platform). Host-agnostic formats stamp `--host` from it\n * for telemetry attribution; omitted for a shared-distribution `package`.\n */\n hostHint?: PlatformId;\n}\n\n/**\n * Host-bundle formats whose hooks/MCP entries embed the ABSOLUTE home-bin path\n * of the machine that ran `package`. They install fine locally, but on another\n * machine/user the baked path points at nothing — so every emit carries a note.\n * (agent-plugin ships a portable launcher, npm-plugin resolves the CLI by name,\n * mcp-server-json/mcpb describe the dev's real upstream server — none of those\n * embed a local path in their portable surfaces.)\n */\nconst HOME_BIN_EMBED_FORMATS: ReadonlySet<PackageFormat> = new Set([\n \"claude-plugin\",\n \"factory-plugin\",\n \"gemini-extension\",\n \"qwen-extension\",\n \"agy-plugin\",\n \"cursor-plugin\",\n \"kimi-plugin\",\n]);\n\n/**\n * Emit a bundle for `connector` in a single `format` (default agent-plugin).\n *\n * Writes (or, for dryRun, only enumerates) the bundle under `opts.outDir`.\n * Returns the absolute file list, the plugin root dir, an optional marketplace\n * path, and optional drop notes (for lossy formats like kimi-plugin).\n */\nexport function packageConnector(\n connector: ResolvedConnector,\n opts: PackageOptions,\n): PackageResult {\n const format = opts.format ?? DEFAULT_PACKAGE_FORMAT;\n const emitter = EMITTERS[format];\n if (!emitter) {\n throw new Error(`unsupported package format: ${format}`);\n }\n\n const ctx: EmitContext = {\n outDir: resolve(opts.outDir),\n homeBinPath: opts.homeBinPath ?? defaultHomeBinPath(),\n dryRun: opts.dryRun ?? false,\n };\n if (opts.hostHint !== undefined) ctx.hostHint = opts.hostHint;\n const result = emitter(connector, ctx);\n if (HOME_BIN_EMBED_FORMATS.has(format)) {\n const note =\n `bundle embeds this machine's agent-connector launcher path (${ctx.homeBinPath}) — ` +\n \"valid for LOCAL install; for a shared marketplace, consumers need agent-connector \" +\n \"at the same home path (run `agent-connector upgrade` there) or re-run `package` per machine\";\n result.notes = [...(result.notes ?? []), note];\n }\n return result;\n}\n\n/** One entry in a multi-format ({@link packageConnectorAll}) emit. */\nexport interface MultiPackageResult {\n format: PackageFormat;\n result: PackageResult;\n}\n\n/**\n * Emit EVERY feasible format, each into its own `<outDir>/<format>/` subdir, so a\n * single `package --format all` produces the whole matrix without collisions.\n */\nexport function packageConnectorAll(\n connector: ResolvedConnector,\n opts: { outDir: string; homeBinPath?: string; dryRun?: boolean },\n): MultiPackageResult[] {\n const base = resolve(opts.outDir);\n const homeBin = opts.homeBinPath ?? defaultHomeBinPath();\n const dryRun = opts.dryRun ?? false;\n return FEASIBLE_FORMATS.map((format) => ({\n format,\n result: packageConnector(connector, {\n outDir: resolve(base, format),\n format,\n homeBinPath: homeBin,\n dryRun,\n }),\n }));\n}\n\n/**\n * Per-format MANUAL install commands (the accurate two-step add+install where\n * applicable). Lives in core (not the CLI) so both `package`'s printed\n * instructions and the marketplace method's skip-warn records for non-drivable\n * hosts quote the SAME commands — one copy, no drift.\n */\nexport function installInstructions(\n format: PackageFormat,\n id: string,\n outDir: string,\n): string[] {\n switch (format) {\n case \"agent-plugin\":\n return [\n `copilot plugin marketplace add ${outDir} && copilot plugin install ${id}@agent-connector`,\n `codex plugin marketplace add ${outDir} && codex plugin add ${id}@agent-connector`,\n `(share: push ${join(outDir, id)} to a git repo, then VS Code → \"Chat: Install Plugin From Source\" <repo url>;`,\n ` Kiro / Hermes / Cursor / other clients: https://agent-plugins.org/compatible-clients)`,\n ];\n case \"claude-plugin\":\n return [\n `/plugin marketplace add ${outDir}`,\n `/plugin install ${id}@agent-connector`,\n `(CLI: claude plugin marketplace add ${outDir} && claude plugin install ${id}@agent-connector)`,\n ];\n case \"factory-plugin\":\n return [\n `droid plugin marketplace add ${outDir}`,\n `droid plugin install ${id}@agent-connector`,\n ];\n case \"gemini-extension\":\n return [`gemini extensions install ${join(outDir, id)}`];\n case \"qwen-extension\":\n return [`qwen extensions install ${join(outDir, id)}`];\n case \"agy-plugin\":\n return [\n `agy plugin install ${join(outDir, id)}`,\n `(validate: agy plugin validate ${join(outDir, id)})`,\n ];\n case \"cursor-plugin\":\n return [\n `link ${join(outDir, id)} into ~/.cursor/plugins/local/${id}/ then Developer: Reload Window`,\n `(or publish ${outDir} as a Cursor marketplace repo)`,\n ];\n case \"kimi-plugin\":\n return [`kimi plugin install ${join(outDir, id)}`];\n case \"npm-plugin\":\n return [\n `npm publish ${join(outDir, id)} (then: opencode plugin install <pkg> | kilo plugin <pkg> | pi install npm:<pkg>)`,\n ];\n case \"mcp-server-json\":\n return [\n `mcp-publisher login <github|dns|http> (prove ownership of your namespace once)`,\n `cd ${outDir} && mcp-publisher publish (uploads server.json to the official MCP Registry)`,\n ];\n case \"mcpb\":\n return [\n `vendor your built server under ${join(outDir, \"server\")}/ (see the emitted README)`,\n `npx @anthropic-ai/mcpb pack ${outDir} (then optionally: mcpb sign)`,\n ];\n default:\n return [];\n }\n}\n\n/** Read + parse a JSON file (used by callers/tests). Returns null on absence/parse error. */\nexport function readPackagedJson<T = unknown>(path: string): T | null {\n if (!existsSync(path)) return null;\n try {\n return JSON.parse(readFileSync(path, \"utf8\")) as T;\n } catch {\n return null;\n }\n}\n","/**\n * core/package-formats/claude-family — the claude-plugin emitter + its\n * manifest-rename sibling factory-plugin.\n *\n * Both share ONE component tree (commands/ agents-or-droids/ skills/<n>/\n * SKILL.md + hooks/hooks.json + an MCP json) and differ only in:\n * • the manifest DIR + filename (.claude-plugin/ | .factory-plugin/)\n * • the subagent dir name (agents/ vs droids/ for factory)\n * • the MCP filename (.mcp.json vs mcp.json for factory)\n * • the manifest extra fields (claude adds $schema; factory pins version+author)\n * • the marketplace catalog shape (claude object-owner; factory git-repo catalog)\n * • the platform stamped into hooks/MCP (--host, so telemetry routes per host)\n *\n * The former codex-plugin / copilot-plugin siblings (a `.codex-plugin/` manifest\n * rename and a `--host copilot-cli` restamp of this tree) are retired: both\n * hosts read the Agent Plugins 1.0.0 bundle natively, so `agent-plugin` is\n * their single source of truth (see package-formats/agent-plugin.ts).\n *\n * The command / skill / subagent markdown is rendered through the SAME shared\n * claude-code renderers the live adapter writes with, so an installed plugin and\n * an `agent-connector install` produce byte-identical content files. Hooks use\n * the universal home-bin command (telemetry-routed) and the MCP entry is\n * serve-wrapped with `--host <platform>` so telemetry carries through.\n */\n\nimport { join } from \"node:path\";\n\nimport type { PlatformId, ResolvedConnector } from \"../types.js\";\nimport {\n renderCommandMd,\n renderSkillMd,\n renderSubagentMd,\n} from \"../../adapters/claude-code/render.js\";\nimport {\n buildClaudeHooksJson,\n buildMcpEntry,\n createEmitter,\n json,\n resolveWithin,\n type EmitContext,\n type FormatEmitter,\n type PackageResult,\n} from \"./shared.js\";\n\n/** Per-variant layout + manifest knobs for a Claude-family bundle. */\ninterface ClaudeFamilySpec {\n /** Host platform stamped into the serve-wrapper + hook command (--host). */\n platformId: PlatformId;\n /** Manifest directory under the plugin root (e.g. \".claude-plugin\"). */\n manifestDir: string;\n /** Subagent directory name (claude: \"agents\"; factory: \"droids\"). */\n subagentDir: string;\n /** MCP filename at the plugin root (claude: \".mcp.json\"; factory: \"mcp.json\"). */\n mcpFile: string;\n /** Add `$schema` to plugin.json (claude only). */\n schemaUrl?: string;\n /** Always carry a version in plugin.json, defaulting placeholder to \"0.0.1\" (factory requires it). */\n requireVersion?: boolean;\n /** Always carry an `author` object in plugin.json (factory pins it). */\n alwaysAuthor?: boolean;\n /**\n * Where to write the marketplace catalog, relative to outDir, and which shape.\n * \"claude\": <outDir>/.claude-plugin/marketplace.json (object owner).\n * \"factory\":<outDir>/marketplace.json (git-repo catalog at the repo root).\n */\n marketplace: { dir: string | null; file: string; shape: \"claude\" | \"factory\" };\n}\n\nconst SPECS: Record<string, ClaudeFamilySpec> = {\n \"claude-plugin\": {\n platformId: \"claude-code\",\n manifestDir: \".claude-plugin\",\n subagentDir: \"agents\",\n mcpFile: \".mcp.json\",\n schemaUrl: \"https://json.schemastore.org/claude-code-plugin-manifest.json\",\n marketplace: { dir: \".claude-plugin\", file: \"marketplace.json\", shape: \"claude\" },\n },\n \"factory-plugin\": {\n platformId: \"droid\",\n manifestDir: \".factory-plugin\",\n subagentDir: \"droids\",\n mcpFile: \"mcp.json\",\n requireVersion: true,\n alwaysAuthor: true,\n // droid marketplaces are Git-repo catalogs; the catalog sits at the repo root.\n marketplace: { dir: null, file: \"marketplace.json\", shape: \"factory\" },\n },\n};\n\n/** Build the plugin manifest for a Claude-family variant. */\nfunction buildManifest(\n connector: ResolvedConnector,\n spec: ClaudeFamilySpec,\n): Record<string, unknown> {\n const manifest: Record<string, unknown> = {};\n if (spec.schemaUrl) manifest.$schema = spec.schemaUrl;\n manifest.name = connector.id;\n manifest.description = `${connector.displayName} — connector emitted by agent-connector`;\n\n const hasRealVersion = connector.version && connector.version !== \"0.0.0\";\n if (hasRealVersion) {\n manifest.version = connector.version;\n } else if (spec.requireVersion) {\n // factory requires a semver version; supply a sane default when unpinned.\n manifest.version = \"0.0.1\";\n }\n // Attribute the bundle to the connector developer when they declared an\n // author (publish.author); the framework name is only the fallback.\n if (spec.alwaysAuthor) {\n manifest.author = { name: connector.publish?.author?.name ?? \"agent-connector\" };\n }\n return manifest;\n}\n\n/** Build the marketplace catalog for a Claude-family variant. */\nfunction buildMarketplace(connector: ResolvedConnector): Record<string, unknown> {\n // Both the claude object-owner catalog and the droid git-repo catalog\n // use the same minimal { name, owner, plugins:[{name,source,description}] }\n // shape — droid reads source as a path relative to the marketplace repo root.\n // The catalog NAME stays \"agent-connector\" (the printed install instructions\n // `<id>@agent-connector` key on it); the OWNER is the developer when known.\n return {\n name: \"agent-connector\",\n owner: { name: connector.publish?.author?.name ?? \"agent-connector\" },\n plugins: [\n {\n name: connector.id,\n source: `./${connector.id}`,\n description: `${connector.displayName} — connector emitted by agent-connector`,\n },\n ],\n };\n}\n\n/** Emit a Claude-family bundle (claude-plugin | factory-plugin). */\nfunction emitClaudeFamily(\n connector: ResolvedConnector,\n ctx: EmitContext,\n format: keyof typeof SPECS,\n): PackageResult {\n const spec = SPECS[format];\n if (!spec) throw new Error(`unknown claude-family format: ${format}`);\n\n const { emit, files } = createEmitter(ctx.dryRun);\n const pluginDir = join(ctx.outDir, connector.id);\n\n // ── plugin.json (the ONLY file inside the manifest dir) ───────────────────\n emit(\n join(pluginDir, spec.manifestDir, \"plugin.json\"),\n json(buildManifest(connector, spec)),\n );\n\n // ── commands/<name>.md ────────────────────────────────────────────────────\n for (const cmd of connector.commands) {\n emit(join(pluginDir, \"commands\", `${cmd.name}.md`), renderCommandMd(cmd));\n }\n\n // ── agents|droids/<name>.md ───────────────────────────────────────────────\n for (const agent of connector.subagents) {\n emit(\n join(pluginDir, spec.subagentDir, `${agent.name}.md`),\n renderSubagentMd(agent),\n );\n }\n\n // ── skills/<name>/SKILL.md (+ resources) ──────────────────────────────────\n for (const skill of connector.skills) {\n const skillDir = join(pluginDir, \"skills\", skill.name);\n emit(join(skillDir, \"SKILL.md\"), renderSkillMd(skill));\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\n const target = resolveWithin(skillDir, rel);\n if (target === null) continue; // never write outside the skill dir\n emit(target, contents);\n }\n }\n\n // ── hooks/hooks.json (mapped events only) ─────────────────────────────────\n const hooksJson = buildClaudeHooksJson(connector, ctx.homeBinPath, spec.platformId);\n if (hooksJson) emit(join(pluginDir, \"hooks\", \"hooks.json\"), json(hooksJson));\n\n // ── MCP json (serve-wrapped stdio server) ─────────────────────────────────\n const mcp = buildMcpEntry(connector, ctx.homeBinPath, spec.platformId);\n if (mcp) {\n emit(\n join(pluginDir, spec.mcpFile),\n json({ mcpServers: { [mcp.serverName]: mcp.entry } }),\n );\n }\n\n // ── marketplace catalog ───────────────────────────────────────────────────\n const marketplacePath = spec.marketplace.dir\n ? join(ctx.outDir, spec.marketplace.dir, spec.marketplace.file)\n : join(ctx.outDir, spec.marketplace.file);\n emit(marketplacePath, json(buildMarketplace(connector)));\n\n return { files, pluginDir, marketplacePath };\n}\n\nexport const emitClaudePlugin: FormatEmitter = (connector, ctx) =>\n emitClaudeFamily(connector, ctx, \"claude-plugin\");\n\nexport const emitFactoryPlugin: FormatEmitter = (connector, ctx) =>\n emitClaudeFamily(connector, ctx, \"factory-plugin\");\n","/**\n * core/package-formats/shared — the common emitter contract + helpers every\n * format family is built on.\n *\n * A format emitter is a pure function conforming to {@link FormatEmitter}: it\n * takes a {@link ResolvedConnector} plus an {@link EmitContext} ({outDir,\n * homeBinPath, dryRun}) and either writes the bundle (dryRun=false) or only\n * enumerates the files it WOULD write (dryRun=true), returning a\n * {@link PackageResult} ({pluginDir, files[], marketplacePath?, notes?}).\n *\n * Everything below is shared across families so each emitter file is just the\n * format-specific manifest + layout, never a re-implementation of file writing,\n * JSON serialization, traversal-safe resource placement, the home-bin hooks\n * block, or the serve-wrapper MCP entry. Reusing these keeps telemetry-wrap +\n * the universal home-bin hook command byte-identical to the live adapters.\n */\n\nimport { dirname, relative, resolve, sep } from \"node:path\";\nimport { writeFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\n\nimport type {\n HookEventName,\n PlatformId,\n ResolvedConnector,\n} from \"../types.js\";\nimport { ensureDir, firstSymlinkInPath } from \"../paths.js\";\nimport {\n buildHomeBinHookCommand,\n buildServeWrapperCommand,\n shouldWrapForTelemetry,\n} from \"../spawn.js\";\n\n/** Inputs every format emitter receives. */\nexport interface EmitContext {\n /** Directory the bundle is written under (the format root). */\n outDir: string;\n /** Absolute path to agent-connector's stable home-bin (hooks + serve wrapper point here). */\n homeBinPath: string;\n /** Enumerate the file list without writing anything. */\n dryRun: boolean;\n /**\n * The host this bundle is being staged FOR, when known (the marketplace\n * drivers stage into a per-host root). Host-agnostic formats (agent-plugin)\n * use it to stamp `--host` for telemetry attribution; a shared-distribution\n * `package` run leaves it undefined and the runtime detects the host.\n */\n hostHint?: PlatformId;\n}\n\n/** The framework's own npm package name (what bundles depend on / fall back to). */\nexport const AGENT_CONNECTOR_PACKAGE_NAME = \"@ken-jo/agent-connector\";\n\n/**\n * The caret range of the framework version that emitted the bundle\n * (`^<version>`), read from this package's own package.json; `*` when it\n * cannot be resolved (e.g. an unusual bundler layout).\n */\nexport function resolveFrameworkDependencyRange(): string {\n const req = createRequire(import.meta.url);\n for (const rel of [\"../../../package.json\", \"../../package.json\", \"../package.json\"]) {\n try {\n const pkg = req(rel) as { name?: string; version?: string };\n if (\n pkg.name === AGENT_CONNECTOR_PACKAGE_NAME &&\n typeof pkg.version === \"string\" &&\n /^\\d+\\.\\d+\\.\\d+/.test(pkg.version)\n ) {\n return `^${pkg.version}`;\n }\n } catch {\n /* keep walking */\n }\n }\n return \"*\";\n}\n\n/** What every format emitter returns. */\nexport interface PackageResult {\n /** Absolute paths of every file the bundle comprises (written, or planned for dryRun). */\n files: string[];\n /** Absolute path to the plugin/extension root directory. */\n pluginDir: string;\n /** Absolute path to the emitted marketplace catalog, when the format has one. */\n marketplacePath?: string;\n /**\n * Human-readable notes about surfaces the format intentionally DROPS (e.g.\n * Kimi ignores hooks/commands/subagents). The CLI surfaces these so a lossy\n * bundle is never silent. Empty when nothing was dropped.\n */\n notes?: string[];\n}\n\n/** The shared signature every `package-formats/<family>.ts` exports. */\nexport type FormatEmitter = (\n connector: ResolvedConnector,\n ctx: EmitContext,\n) => PackageResult;\n\n/** A small file-collecting writer bound to one emit run (honors dryRun). */\nexport interface Emitter {\n /** Write `contents` to `path` (skipped under dryRun) and record it. */\n emit(path: string, contents: string): void;\n /** The accumulated absolute file list (in emit order). */\n readonly files: string[];\n}\n\n/** Build a dryRun-aware {@link Emitter} that records every (would-be) write. */\nexport function createEmitter(dryRun: boolean): Emitter {\n const files: string[] = [];\n return {\n files,\n emit(path: string, contents: string): void {\n if (!dryRun) {\n const symlink = firstSymlinkInPath(path);\n if (symlink !== null) {\n throw new Error(`refusing to emit through symbolic link: ${path} (${symlink})`);\n }\n ensureDir(dirname(path));\n writeFileSync(path, contents, \"utf8\");\n }\n files.push(path);\n },\n };\n}\n\n/** Pretty-print a value as 2-space JSON with a trailing newline. */\nexport function json(value: unknown): string {\n return `${JSON.stringify(value, null, 2)}\\n`;\n}\n\n/**\n * Resolve a skill-resource relative key against `baseDir`, returning the\n * absolute target ONLY when it stays inside the dir (defense-in-depth — config\n * validation already rejects traversal, but never trust input). Null otherwise.\n */\nexport function resolveWithin(baseDir: string, rel: string): string | null {\n const base = resolve(baseDir);\n const target = resolve(base, rel);\n if (target === base) return null;\n const rind = relative(base, target);\n if (rind === \"\" || rind.startsWith(\"..\") || resolve(base, rind) !== target) {\n return null;\n }\n if (rind === \"..\" || rind.startsWith(`..${sep}`)) return null;\n return target;\n}\n\n/** Pass env through unchanged when present, else undefined (drops empty objects). */\nexport function renderEnv(\n env: Record<string, string> | undefined,\n): Record<string, string> | undefined {\n if (!env || Object.keys(env).length === 0) return undefined;\n return { ...env };\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Hooks — the Claude-shaped hooks.json block, shared by every format whose\n// hooks file mirrors Claude Code's `{ type:\"command\", command:\"<string>\" }`.\n// ─────────────────────────────────────────────────────────────────────────\n\n/** Claude event names a Claude-style plugin's hooks.json may key on. */\nexport const CLAUDE_MAPPED_EVENTS: ReadonlySet<HookEventName> =\n new Set<HookEventName>([\n \"PreToolUse\",\n \"PostToolUse\",\n \"PreCompact\",\n \"SessionStart\",\n \"SessionEnd\",\n \"UserPromptSubmit\",\n \"Stop\",\n \"Notification\",\n \"PermissionRequest\",\n \"PostToolUseFailure\",\n \"SubagentStart\",\n \"SubagentStop\",\n \"PostCompact\",\n ]);\n\n/** A single hooks.json entry (identical in shape to a settings.json hooks block). */\nexport interface PluginHookEntry {\n matcher?: string;\n hooks: Array<{ type: \"command\"; command: string }>;\n}\n\n/**\n * Build the Claude-shaped hooks.json body for the MAPPED events the connector\n * declares. Each command is the SAME single-string home-bin form the live\n * adapters write (via buildHomeBinHookCommand). `platformId` lets a format point\n * the hook at the right host (e.g. \"cursor\", \"claude-code\"). Returns null when\n * the connector declares no mapped events.\n */\nexport function buildClaudeHooksJson(\n connector: ResolvedConnector,\n homeBin: string,\n platformId: PlatformId,\n): { hooks: Record<string, PluginHookEntry[]> } | null {\n const events = connector.hookEvents.filter((e) => CLAUDE_MAPPED_EVENTS.has(e));\n if (events.length === 0) return null;\n\n const hooks: Record<string, PluginHookEntry[]> = {};\n for (const event of events) {\n const matcher = connector.hooks[event]?.matcher ?? \"\";\n const command = {\n type: \"command\" as const,\n command: buildHomeBinHookCommand(homeBin, platformId, event, connector.id),\n };\n hooks[event] = [matcher ? { matcher, hooks: [command] } : { hooks: [command] }];\n }\n return { hooks };\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// MCP — the serve-wrapped stdio server entry, shared by every format whose MCP\n// file carries a launchable { command, args, env?, cwd? } (the Claude .mcp.json\n// dialect). Remote/non-stdio servers are out of scope for a launchable bundle.\n// ─────────────────────────────────────────────────────────────────────────\n\n/** Native MCP server entry shape a Claude-dialect mcpServers map accepts. */\nexport interface PluginMcpEntry {\n command: string;\n args: string[];\n env?: Record<string, string>;\n cwd?: string;\n}\n\n/**\n * Render the connector's ServerDef into a serve-wrapped MCP entry for\n * `platformId`, so per-tool telemetry carries through the bundle exactly as the\n * live adapter's install does. Returns null when there is no stdio command to\n * launch (remote / server-less connectors). The returned `serverName` is the\n * connector id (the conventional single-server key).\n */\nexport function buildMcpEntry(\n connector: ResolvedConnector,\n homeBin: string,\n platformId: PlatformId,\n): { serverName: string; entry: PluginMcpEntry } | null {\n const server = connector.server;\n if (!server) return null;\n // A launchable bundle entry can only carry stdio servers; remote (http/sse/ws)\n // servers register a URL elsewhere, out of scope for the bundled plugin.\n if (server.transport !== \"stdio\") return null;\n\n const realCommand = server.command ?? \"\";\n if (realCommand === \"\") return null;\n const realArgs = [...(server.args ?? [])];\n\n let entry: PluginMcpEntry;\n if (shouldWrapForTelemetry(server, connector.telemetry)) {\n const wrapped = buildServeWrapperCommand(\n homeBin,\n connector.id,\n realCommand,\n realArgs,\n undefined,\n platformId,\n );\n entry = { command: wrapped.command, args: wrapped.args };\n } else {\n entry = { command: realCommand, args: realArgs };\n }\n\n const env = renderEnv(server.env);\n if (env) entry.env = env;\n if (server.cwd) entry.cwd = server.cwd;\n\n return { serverName: connector.id, entry };\n}\n","/**\n * core/package-formats/cursor — the `cursor-plugin` emitter.\n *\n * Cursor's bundle is near-isomorphic to claude-plugin: manifest at\n * `.cursor-plugin/plugin.json` (only `name` required) with the surface fields\n * declared as POINTERS (\"skills\":\"./skills/\", \"hooks\":\"./hooks/hooks.json\",\n * \"mcpServers\":\"./mcp.json\") so a validator/IDE finds each dir; components live\n * at the plugin root: commands/<n>.md, agents/<n>.md, skills/<n>/SKILL.md,\n * mcp.json, hooks/hooks.json. A multi-plugin repo adds .cursor-plugin/\n * marketplace.json { name, owner:{name,email?}, plugins:[{name,source,description}] }.\n *\n * Markdown reuses the shared claude-code renderers (Cursor reads the same md +\n * frontmatter command/agent/skill documents). MCP uses the shared serve-wrap\n * builder with --host cursor so serve-wrapper telemetry carries through. Hooks\n * use Cursor's OWN flat hooks.json shape (NOT the Claude shape) via the cursor\n * install adapter's shared event-map + version — see buildCursorHooksJson.\n *\n * (Cursor also supports `rules/*.mdc`, but a connector declares no rules surface,\n * so no rules/ dir is emitted and the manifest omits the `rules` pointer.)\n */\n\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport type { HookEventName, PlatformId, ResolvedConnector } from \"../types.js\";\nimport {\n renderCommandMd,\n renderSkillMd,\n renderSubagentMd,\n} from \"../../adapters/claude-code/render.js\";\nimport {\n CURSOR_EVENT_MAP,\n CURSOR_HOOKS_VERSION,\n} from \"../../adapters/cursor/index.js\";\nimport { buildHomeBinHookCommand } from \"../spawn.js\";\nimport {\n buildMcpEntry,\n createEmitter,\n json,\n resolveWithin,\n type EmitContext,\n type FormatEmitter,\n type PackageResult,\n} from \"./shared.js\";\n\nconst PLATFORM: PlatformId = \"cursor\";\n\n/** A single Cursor native hook entry — a FLAT command object (matcher optional). */\ninterface CursorHookEntry {\n command: string;\n matcher?: string;\n}\n\n/**\n * Build Cursor's native hooks.json body for the connector's declared events.\n *\n * Unlike the Claude shape (PascalCase keys, nested `{ matcher?, hooks:[{type,\n * command}] }`, no version), Cursor reads `{ version, hooks: { <cursorEvent>:\n * [ { command, matcher? } ] } }` — lower-camel native keys, FLAT command\n * entries, and a top-level version stamp. The event-map + version are imported\n * from the cursor INSTALL adapter (the repo authority on Cursor's schema) so a\n * packaged bundle and a live install can never diverge: only the events Cursor\n * actually maps are emitted, with the exact keys/version the adapter writes.\n *\n * The home-bin command STRING is the same single-string form the install\n * adapter writes (buildHomeBinHookCommand); only the envelope shape differs.\n *\n * Scope: this operates on the connector-level declared `hookEvents` only. Per-\n * platform override state (`platforms.cursor.hooks: false` / `nativeHooks`) is\n * intentionally NOT applied — a portable package bundle is platform-agnostic,\n * matching the Claude-family emitters. The consistency test covers the no-\n * override case (bundle bytes === a vanilla install).\n * Returns null when the connector declares no Cursor-mapped events.\n */\nfunction buildCursorHooksJson(\n connector: ResolvedConnector,\n homeBin: string,\n): { version: number; hooks: Record<string, CursorHookEntry[]> } | null {\n const hooks: Record<string, CursorHookEntry[]> = {};\n for (const event of connector.hookEvents) {\n const cursorEvent = CURSOR_EVENT_MAP[event as HookEventName];\n if (cursorEvent === undefined) continue; // no Cursor equivalent — skipped\n const command = buildHomeBinHookCommand(homeBin, PLATFORM, event, connector.id);\n const matcher = connector.hooks[event]?.matcher ?? \"\";\n hooks[cursorEvent] = [matcher ? { command, matcher } : { command }];\n }\n if (Object.keys(hooks).length === 0) return null;\n return { version: CURSOR_HOOKS_VERSION, hooks };\n}\n\n/** Build .cursor-plugin/plugin.json with pointer surface fields for what exists. */\nfunction buildManifest(\n connector: ResolvedConnector,\n has: { commands: boolean; agents: boolean; skills: boolean; hooks: boolean; mcp: boolean },\n): Record<string, unknown> {\n const manifest: Record<string, unknown> = {\n name: connector.id,\n description: `${connector.displayName} — connector emitted by agent-connector`,\n };\n if (connector.version && connector.version !== \"0.0.0\") {\n manifest.version = connector.version;\n }\n // Pointer fields: only declare a surface that actually ships in the bundle.\n if (has.commands) manifest.commands = \"./commands/\";\n if (has.agents) manifest.agents = \"./agents/\";\n if (has.skills) manifest.skills = \"./skills/\";\n if (has.hooks) manifest.hooks = \"./hooks/hooks.json\";\n if (has.mcp) manifest.mcpServers = \"./mcp.json\";\n return manifest;\n}\n\n/** Build .cursor-plugin/marketplace.json (owner object carries name; email optional). */\nfunction buildMarketplace(connector: ResolvedConnector): Record<string, unknown> {\n // Catalog NAME stays \"agent-connector\" (install instructions key on it); the\n // OWNER is the connector developer when publish.author is declared.\n return {\n name: \"agent-connector\",\n owner: { name: connector.publish?.author?.name ?? \"agent-connector\" },\n plugins: [\n {\n name: connector.id,\n source: `./${connector.id}`,\n description: `${connector.displayName} — connector emitted by agent-connector`,\n },\n ],\n };\n}\n\nexport const emitCursorPlugin: FormatEmitter = (\n connector: ResolvedConnector,\n ctx: EmitContext,\n): PackageResult => {\n const { emit, files } = createEmitter(ctx.dryRun);\n const pluginDir = join(ctx.outDir, connector.id);\n\n const hooksJson = buildCursorHooksJson(connector, ctx.homeBinPath);\n const mcp = buildMcpEntry(connector, ctx.homeBinPath, PLATFORM);\n\n const has = {\n commands: connector.commands.length > 0,\n agents: connector.subagents.length > 0,\n skills: connector.skills.length > 0,\n hooks: hooksJson !== null,\n mcp: mcp !== null,\n };\n\n // ── .cursor-plugin/plugin.json (ONLY file under .cursor-plugin/) ───────────\n emit(\n join(pluginDir, \".cursor-plugin\", \"plugin.json\"),\n json(buildManifest(connector, has)),\n );\n\n // ── commands/<name>.md ────────────────────────────────────────────────────\n for (const cmd of connector.commands) {\n emit(join(pluginDir, \"commands\", `${cmd.name}.md`), renderCommandMd(cmd));\n }\n\n // ── agents/<name>.md ──────────────────────────────────────────────────────\n for (const agent of connector.subagents) {\n emit(join(pluginDir, \"agents\", `${agent.name}.md`), renderSubagentMd(agent));\n }\n\n // ── skills/<name>/SKILL.md (+ resources) ──────────────────────────────────\n for (const skill of connector.skills) {\n const skillDir = join(pluginDir, \"skills\", skill.name);\n emit(join(skillDir, \"SKILL.md\"), renderSkillMd(skill));\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\n const target = resolveWithin(skillDir, rel);\n if (target === null) continue;\n emit(target, contents);\n }\n }\n\n // ── hooks/hooks.json ──────────────────────────────────────────────────────\n if (hooksJson) emit(join(pluginDir, \"hooks\", \"hooks.json\"), json(hooksJson));\n\n // ── mcp.json (Cursor's MCP filename, no leading dot) ──────────────────────\n if (mcp) {\n emit(\n join(pluginDir, \"mcp.json\"),\n json({ mcpServers: { [mcp.serverName]: mcp.entry } }),\n );\n }\n\n // ── .cursor-plugin/marketplace.json ───────────────────────────────────────\n const marketplacePath = join(ctx.outDir, \".cursor-plugin\", \"marketplace.json\");\n emit(marketplacePath, json(buildMarketplace(connector)));\n\n return { files, pluginDir, marketplacePath };\n};\n\n/** True when a local install of this plugin already exists (used by the CLI hint). */\nexport function cursorLocalInstallExists(name: string, home: string): boolean {\n return existsSync(join(home, \".cursor\", \"plugins\", \"local\", name));\n}\n","/**\n * core/package-formats/gemini — the `gemini-extension` emitter + its `qwen-extension`\n * variant.\n *\n * A Gemini CLI extension is a directory with `gemini-extension.json` at its root\n * carrying `{ name, version, description, mcpServers, contextFileName }` plus the\n * component dirs: commands/<n>.toml (slash commands), skills/<n>/SKILL.md,\n * agents/<n>.md, hooks/hooks.json, and a GEMINI.md context file. UNLIKE the\n * Claude family, MCP is declared INLINE in the manifest's `mcpServers` map (not a\n * separate .mcp.json) — we still serve-wrap it so telemetry carries through.\n *\n * Qwen Code is a Gemini-CLI fork with its own `qwen-extension.json` (same shape)\n * but two differences captured here: commands are MARKDOWN (commands/<n>.md) not\n * TOML, and the context file is QWEN.md.\n *\n * Commands render to Gemini's native TOML `{ description, prompt }` (the same\n * shape the live gemini-cli adapter writes); skills/subagents reuse the shared\n * claude-code renderers (Gemini/Qwen read the same SKILL.md + md+frontmatter).\n * Hooks use the universal home-bin command; the MCP entry is serve-wrapped with\n * --host gemini-cli | qwen-code.\n */\n\nimport { join } from \"node:path\";\n\nimport type { CommandDef, PlatformId, ResolvedConnector } from \"../types.js\";\nimport { writeTomlString } from \"../toml.js\";\nimport {\n renderCommandMd,\n renderSkillMd,\n renderSubagentMd,\n} from \"../../adapters/claude-code/render.js\";\nimport {\n buildClaudeHooksJson,\n buildMcpEntry,\n createEmitter,\n json,\n resolveWithin,\n type EmitContext,\n type FormatEmitter,\n type PackageResult,\n} from \"./shared.js\";\n\n/** Per-variant knobs for a Gemini-family extension. */\ninterface GeminiFamilySpec {\n platformId: PlatformId;\n /** Manifest filename at the extension root. */\n manifestFile: string;\n /** Context file name (GEMINI.md | QWEN.md). */\n contextFile: string;\n /** Command file format: TOML (gemini) or Markdown (qwen). */\n commandFormat: \"toml\" | \"md\";\n}\n\nconst SPECS: Record<string, GeminiFamilySpec> = {\n \"gemini-extension\": {\n platformId: \"gemini-cli\",\n manifestFile: \"gemini-extension.json\",\n contextFile: \"GEMINI.md\",\n commandFormat: \"toml\",\n },\n \"qwen-extension\": {\n platformId: \"qwen-code\",\n manifestFile: \"qwen-extension.json\",\n contextFile: \"QWEN.md\",\n commandFormat: \"md\",\n },\n};\n\n/** Render a command to Gemini's native TOML `{ description, prompt }`. */\nfunction renderCommandToml(cmd: CommandDef): string {\n const obj: Record<string, unknown> = {};\n if (cmd.description !== undefined) obj.description = cmd.description;\n obj.prompt = cmd.prompt;\n return writeTomlString(obj);\n}\n\n/** Build gemini-extension.json | qwen-extension.json (with optional inline mcpServers). */\nfunction buildManifest(\n connector: ResolvedConnector,\n spec: GeminiFamilySpec,\n homeBin: string,\n): Record<string, unknown> {\n const manifest: Record<string, unknown> = {\n name: connector.id,\n // gemini requires a version; default a placeholder to a real semver.\n version:\n connector.version && connector.version !== \"0.0.0\"\n ? connector.version\n : \"0.0.1\",\n description: `${connector.displayName} — connector emitted by agent-connector`,\n };\n\n const mcp = buildMcpEntry(connector, homeBin, spec.platformId);\n if (mcp) {\n manifest.mcpServers = { [mcp.serverName]: mcp.entry };\n }\n manifest.contextFileName = spec.contextFile;\n return manifest;\n}\n\nfunction emitGeminiFamily(\n connector: ResolvedConnector,\n ctx: EmitContext,\n format: keyof typeof SPECS,\n): PackageResult {\n const spec = SPECS[format];\n if (!spec) throw new Error(`unknown gemini-family format: ${format}`);\n\n const { emit, files } = createEmitter(ctx.dryRun);\n const pluginDir = join(ctx.outDir, connector.id);\n\n // ── gemini-extension.json | qwen-extension.json (MCP is inline here) ──────\n emit(\n join(pluginDir, spec.manifestFile),\n json(buildManifest(connector, spec, ctx.homeBinPath)),\n );\n\n // ── context file (GEMINI.md | QWEN.md) ────────────────────────────────────\n emit(\n join(pluginDir, spec.contextFile),\n `# ${connector.displayName}\\n\\nConnector context emitted by agent-connector.\\n`,\n );\n\n // ── commands/<name>.{toml|md} ─────────────────────────────────────────────\n for (const cmd of connector.commands) {\n if (spec.commandFormat === \"toml\") {\n emit(join(pluginDir, \"commands\", `${cmd.name}.toml`), renderCommandToml(cmd));\n } else {\n emit(join(pluginDir, \"commands\", `${cmd.name}.md`), renderCommandMd(cmd));\n }\n }\n\n // ── agents/<name>.md ──────────────────────────────────────────────────────\n for (const agent of connector.subagents) {\n emit(join(pluginDir, \"agents\", `${agent.name}.md`), renderSubagentMd(agent));\n }\n\n // ── skills/<name>/SKILL.md (+ resources) ──────────────────────────────────\n for (const skill of connector.skills) {\n const skillDir = join(pluginDir, \"skills\", skill.name);\n emit(join(skillDir, \"SKILL.md\"), renderSkillMd(skill));\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\n const target = resolveWithin(skillDir, rel);\n if (target === null) continue;\n emit(target, contents);\n }\n }\n\n // ── hooks/hooks.json ──────────────────────────────────────────────────────\n const hooksJson = buildClaudeHooksJson(connector, ctx.homeBinPath, spec.platformId);\n if (hooksJson) emit(join(pluginDir, \"hooks\", \"hooks.json\"), json(hooksJson));\n\n // A Gemini/Qwen extension has no separate marketplace catalog (it installs by\n // URL/path); marketplacePath is left undefined.\n return { files, pluginDir };\n}\n\nexport const emitGeminiExtension: FormatEmitter = (connector, ctx) =>\n emitGeminiFamily(connector, ctx, \"gemini-extension\");\n\nexport const emitQwenExtension: FormatEmitter = (connector, ctx) =>\n emitGeminiFamily(connector, ctx, \"qwen-extension\");\n","/**\n * core/package-formats/agy — the `agy plugin` bundle emitter (Antigravity CLI +\n * Antigravity IDE, which share the bundle).\n *\n * Live-confirmed layout (`agy plugin validate`):\n * • REQUIRED root `plugin.json` marker { name, version, description } — its\n * absence is the one hard error the validator reports.\n * • MCP MUST be a SEPARATE `mcp_config.json` { mcpServers:{...} } — an inline\n * `mcpServers` in plugin.json is NOT picked up. (This is the one structural\n * difference from the Claude family.)\n * • hooks.json at the BUNDLE ROOT keyed { hooks:{ <Event>:[{matcher,hooks:[{type,command}]}] } }\n * — agy 1.0.7 NEVER reads hooks/hooks.json: validate+install report\n * \"hooks: skipped (not found)\" and copy the file unprocessed. The root\n * location was fix-proven live (\"hooks: 1 processed\", components +hooks).\n * • skills/<n>/SKILL.md, agents/<n>.md, commands/<n>.md (commands are converted\n * to skills on validate — still emitted as Markdown command files).\n *\n * Markdown reuses the shared claude-code renderers; hooks use the universal\n * home-bin command; the MCP entry is serve-wrapped with --host antigravity-cli so\n * telemetry carries through. No marketplace catalog ships in the bundle (agy\n * installs by target / plugin@marketplace).\n */\n\nimport { join } from \"node:path\";\n\nimport type { PlatformId, ResolvedConnector } from \"../types.js\";\nimport {\n renderCommandMd,\n renderSkillMd,\n renderSubagentMd,\n} from \"../../adapters/claude-code/render.js\";\nimport {\n buildClaudeHooksJson,\n buildMcpEntry,\n createEmitter,\n json,\n resolveWithin,\n type EmitContext,\n type FormatEmitter,\n type PackageResult,\n} from \"./shared.js\";\n\nconst PLATFORM: PlatformId = \"antigravity-cli\";\n\n/** Build the required root plugin.json marker. */\nfunction buildManifest(connector: ResolvedConnector): Record<string, unknown> {\n return {\n name: connector.id,\n // agy expects a version on the marker; default a placeholder to a real semver.\n version:\n connector.version && connector.version !== \"0.0.0\"\n ? connector.version\n : \"0.0.1\",\n description: `${connector.displayName} — connector emitted by agent-connector`,\n };\n}\n\nexport const emitAgyPlugin: FormatEmitter = (\n connector: ResolvedConnector,\n ctx: EmitContext,\n): PackageResult => {\n const { emit, files } = createEmitter(ctx.dryRun);\n const pluginDir = join(ctx.outDir, connector.id);\n\n // ── plugin.json (REQUIRED root marker) ────────────────────────────────────\n emit(join(pluginDir, \"plugin.json\"), json(buildManifest(connector)));\n\n // ── commands/<name>.md (validator converts these to skills) ───────────────\n for (const cmd of connector.commands) {\n emit(join(pluginDir, \"commands\", `${cmd.name}.md`), renderCommandMd(cmd));\n }\n\n // ── agents/<name>.md ──────────────────────────────────────────────────────\n for (const agent of connector.subagents) {\n emit(join(pluginDir, \"agents\", `${agent.name}.md`), renderSubagentMd(agent));\n }\n\n // ── skills/<name>/SKILL.md (+ resources) ──────────────────────────────────\n for (const skill of connector.skills) {\n const skillDir = join(pluginDir, \"skills\", skill.name);\n emit(join(skillDir, \"SKILL.md\"), renderSkillMd(skill));\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\n const target = resolveWithin(skillDir, rel);\n if (target === null) continue;\n emit(target, contents);\n }\n }\n\n // ── hooks.json (bundle ROOT — agy silently ignores hooks/hooks.json) ──────\n const hooksJson = buildClaudeHooksJson(connector, ctx.homeBinPath, PLATFORM);\n if (hooksJson) emit(join(pluginDir, \"hooks.json\"), json(hooksJson));\n\n // ── mcp_config.json (SEPARATE file — inline mcpServers is NOT read by agy) ─\n const mcp = buildMcpEntry(connector, ctx.homeBinPath, PLATFORM);\n if (mcp) {\n emit(\n join(pluginDir, \"mcp_config.json\"),\n json({ mcpServers: { [mcp.serverName]: mcp.entry } }),\n );\n }\n\n return { files, pluginDir };\n};\n","/**\n * core/package-formats/kimi — the `kimi-plugin` emitter (skills + MCP ONLY).\n *\n * A Kimi plugin is a directory whose manifest is `kimi.plugin.json` at the root\n * carrying { name, version, description, skills, mcpServers }. Kimi plugins carry\n * exactly TWO functional surfaces:\n * • skills/<n>/SKILL.md (declared via the `skills` pointer)\n * • mcpServers (a standard MCP map, stdio + http)\n *\n * Kimi EXPLICITLY ignores `tools`, `commands`, `hooks`, `apps`, `inject`,\n * `configFile` (they surface as diagnostics). So when the connector declares\n * commands, subagents, or hooks, those surfaces are DROPPED — and a note is\n * returned so the lossy bundle is never silent. The MCP entry is still\n * serve-wrapped with --host kimi so telemetry carries through; hooks are NOT\n * emitted because Kimi has no hooks surface.\n */\n\nimport { join } from \"node:path\";\n\nimport type { PlatformId, ResolvedConnector } from \"../types.js\";\nimport { renderSkillMd } from \"../../adapters/claude-code/render.js\";\nimport {\n buildMcpEntry,\n createEmitter,\n json,\n resolveWithin,\n type EmitContext,\n type FormatEmitter,\n type PackageResult,\n} from \"./shared.js\";\n\nconst PLATFORM: PlatformId = \"kimi\";\n\n/** Build kimi.plugin.json (skills pointer + inline mcpServers when present). */\nfunction buildManifest(\n connector: ResolvedConnector,\n hasSkills: boolean,\n homeBin: string,\n): Record<string, unknown> {\n const manifest: Record<string, unknown> = {\n name: connector.id,\n version:\n connector.version && connector.version !== \"0.0.0\"\n ? connector.version\n : \"0.0.1\",\n description: `${connector.displayName} — connector emitted by agent-connector`,\n };\n if (hasSkills) manifest.skills = \"./skills/\";\n const mcp = buildMcpEntry(connector, homeBin, PLATFORM);\n if (mcp) manifest.mcpServers = { [mcp.serverName]: mcp.entry };\n return manifest;\n}\n\nexport const emitKimiPlugin: FormatEmitter = (\n connector: ResolvedConnector,\n ctx: EmitContext,\n): PackageResult => {\n const { emit, files } = createEmitter(ctx.dryRun);\n const pluginDir = join(ctx.outDir, connector.id);\n const notes: string[] = [];\n\n const hasSkills = connector.skills.length > 0;\n\n // ── kimi.plugin.json (root manifest; MCP inline; hooks/commands ignored) ──\n emit(join(pluginDir, \"kimi.plugin.json\"), json(buildManifest(connector, hasSkills, ctx.homeBinPath)));\n\n // ── skills/<name>/SKILL.md (+ resources) ──────────────────────────────────\n for (const skill of connector.skills) {\n const skillDir = join(pluginDir, \"skills\", skill.name);\n emit(join(skillDir, \"SKILL.md\"), renderSkillMd(skill));\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\n const target = resolveWithin(skillDir, rel);\n if (target === null) continue;\n emit(target, contents);\n }\n }\n\n // ── Surfaces Kimi cannot carry → DROPPED, with an explicit note ───────────\n if (connector.commands.length > 0) {\n notes.push(\n `kimi-plugin: dropped ${connector.commands.length} command(s) — Kimi plugins ignore commands`,\n );\n }\n if (connector.subagents.length > 0) {\n notes.push(\n `kimi-plugin: dropped ${connector.subagents.length} subagent(s) — Kimi plugins ignore subagents`,\n );\n }\n if (connector.hookEvents.length > 0) {\n notes.push(\n `kimi-plugin: dropped ${connector.hookEvents.length} hook event(s) — Kimi plugins ignore hooks`,\n );\n }\n\n return { files, pluginDir, ...(notes.length > 0 ? { notes } : {}) };\n};\n","/**\n * core/package-formats/npm — the `npm-plugin` emitter (opencode + kilo-cli + pi).\n *\n * This is the one genuinely NET-NEW artifact: a publishable npm package whose\n * default export is a plugin module. It is emitted ONLY in its clean form — a\n * real package.json + an ESM `index.js` bridge — never a\n * half-baked stub. The surface limit (documented, and returned as notes) is\n * inherent to the opencode/kilo plugin contract: ONLY hook code rides inside the\n * npm package; commands/skills/subagents are native host dirs and MCP is a\n * config key, so they do NOT ride inside the published module.\n *\n * Layout:\n * <outDir>/<id>/\n * ├── package.json (type:module, exports \".\", keywords incl. \"opencode-plugin\"\n * │ + \"pi-package\", engines.node)\n * ├── index.js (default-export plugin fn; bridges each declared hook event\n * │ to `<homeBin> hook opencode <event> --connector <id>`)\n * ├── skills/<n>/SKILL.md (pi packages DO bundle skills; opencode ignores them)\n * └── README.md\n *\n * The bridge shells out to the framework runtime bundled as this plugin's npm\n * dependency, then falls back to a PATH `agent-connector` binary for hand-built\n * bundles. The SAME universal json-stdio dispatcher every other host uses serves\n * the npm host too. (MCP wrapping is NOT inlined here: opencode's MCP is the\n * opencode.json \"mcp\" key, out of band for the npm package; a note records this.)\n */\n\nimport { join } from \"node:path\";\n\nimport type { HookEventName, ResolvedConnector } from \"../types.js\";\nimport { renderSkillMd } from \"../../adapters/claude-code/render.js\";\nimport {\n AGENT_CONNECTOR_PACKAGE_NAME,\n createEmitter,\n json,\n resolveFrameworkDependencyRange,\n resolveWithin,\n type EmitContext,\n type FormatEmitter,\n type PackageResult,\n} from \"./shared.js\";\n\n/** OpenCode event keys this connector can bridge (PreToolUse/PostToolUse/SessionStart). */\nconst EVENT_TO_OPENCODE: Partial<Record<HookEventName, string>> = {\n PreToolUse: \"tool.execute.before\",\n PostToolUse: \"tool.execute.after\",\n SessionStart: \"experimental.chat.system.transform\",\n};\n\n/** Build the publishable package.json for an opencode/kilo/pi plugin package. */\nfunction buildPackageJson(connector: ResolvedConnector): Record<string, unknown> {\n // Use an opencode- name prefix (the discovery-confirmed convention) so the\n // package is discoverable; keywords cover opencode + pi-package.\n const pkgName = connector.id.startsWith(\"opencode-\")\n ? connector.id\n : `opencode-${connector.id}`;\n const version =\n connector.version && connector.version !== \"0.0.0\" ? connector.version : \"0.0.1\";\n const pkg: Record<string, unknown> = {\n name: pkgName,\n version,\n description: `${connector.displayName} — connector emitted by agent-connector`,\n type: \"module\",\n main: \"index.js\",\n exports: { \".\": \"./index.js\" },\n keywords: [\"opencode\", \"opencode-plugin\", \"pi-package\", \"agent-connector\"],\n dependencies: { [AGENT_CONNECTOR_PACKAGE_NAME]: resolveFrameworkDependencyRange() },\n // pi reads skills/prompts/themes/extensions from the package.json \"pi\" key.\n pi: { extensions: [\"./index.js\"], skills: [\"./skills\"] },\n engines: { node: \">=18.17\", opencode: \">=1.0.0\" },\n // NOTE: no hardcoded license — this is the DEVELOPER'S publishable package\n // and agent-connector has no authority to license it. The emitter returns a\n // note telling the dev to set license (and author) before `npm publish`.\n };\n if (connector.publish?.author?.name) {\n pkg.author = connector.publish.author.name;\n }\n return pkg;\n}\n\n/** Compose the self-contained ESM plugin bridge (default-export plugin fn). */\nfunction buildIndexJs(connector: ResolvedConnector): string {\n const frameworkPackageName = JSON.stringify(AGENT_CONNECTOR_PACKAGE_NAME);\n const connectorId = JSON.stringify(connector.id);\n\n const events = connector.hookEvents.filter(\n (e): e is HookEventName => EVENT_TO_OPENCODE[e] !== undefined,\n );\n const has = (e: HookEventName): boolean => events.includes(e);\n\n const header = `/**\n * AUTO-GENERATED by agent-connector — DO NOT EDIT.\n *\n * Publishable OpenCode/Kilo/Pi plugin for connector ${connector.id}. It imports\n * no public framework APIs: every hook invocation shells out to the bundled\n * framework runtime's universal entrypoint and JSON-parses the normalized response.\n * Fail-open: any bridge error degrades to \"allow\".\n */\nimport { execFileSync, execSync } from \"node:child_process\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join } from \"node:path\";\n\nconst FRAMEWORK_PACKAGE_NAME = ${frameworkPackageName};\nconst CONNECTOR_ID = ${connectorId};\nconst require = createRequire(import.meta.url);\n\nfunction resolveBridgeCommand() {\n try {\n const pkgJson = require.resolve(FRAMEWORK_PACKAGE_NAME + \"/package.json\");\n return { command: process.execPath, prefix: [join(dirname(pkgJson), \"dist\", \"cli.js\")] };\n } catch {\n return { command: \"agent-connector\", prefix: [] };\n }\n}\n\nconst BRIDGE_COMMAND = resolveBridgeCommand();\n\nfunction bridge(event, payload) {\n try {\n // Prefer the runtime bundled as this plugin's dependency. The bare\n // agent-connector command is only a recovery fallback for hand-built bundles.\n const args = [...BRIDGE_COMMAND.prefix, \"hook\", \"opencode\", event, \"--connector\", CONNECTOR_ID];\n const opts = { input: JSON.stringify(payload), encoding: \"utf8\" };\n const stdout =\n process.platform === \"win32\" && BRIDGE_COMMAND.command === \"agent-connector\"\n ? execSync([BRIDGE_COMMAND.command, ...args].map((a) => '\"' + a + '\"').join(\" \"), opts)\n : execFileSync(BRIDGE_COMMAND.command, args, opts);\n const text = (stdout || \"\").trim();\n if (text === \"\") return { decision: \"allow\" };\n return JSON.parse(text);\n } catch {\n return null;\n }\n}\n`;\n\n const handlers: string[] = [];\n if (has(\"PreToolUse\")) {\n handlers.push(` \"tool.execute.before\": async (input, output) => {\n const res = bridge(\"PreToolUse\", {\n toolName: input.tool ?? \"\",\n toolInput: (output && output.args) ?? {},\n sessionId: input.sessionID ?? \"\",\n projectDir: PROJECT_DIR,\n });\n if (!res) return;\n if (res.decision === \"deny\" || res.decision === \"ask\") {\n throw new Error(res.reason || \"Blocked by ${connector.id}\");\n }\n if (res.updatedInput && output && output.args) Object.assign(output.args, res.updatedInput);\n },`);\n }\n if (has(\"PostToolUse\")) {\n handlers.push(` \"tool.execute.after\": async (input, output) => {\n const res = bridge(\"PostToolUse\", {\n toolName: input.tool ?? \"\",\n toolInput: input.args ?? {},\n toolOutput: output ? output.output : undefined,\n sessionId: input.sessionID ?? \"\",\n projectDir: PROJECT_DIR,\n });\n if (!res) return;\n if (typeof res.updatedOutput === \"string\" && output) output.output = res.updatedOutput;\n },`);\n }\n if (has(\"SessionStart\")) {\n handlers.push(` \"experimental.chat.system.transform\": async (input, output) => {\n const res = bridge(\"SessionStart\", {\n sessionId: (input && input.sessionID) ?? \"\",\n projectDir: PROJECT_DIR,\n });\n if (!res) return;\n if (res.additionalContext && output && Array.isArray(output.system)) {\n output.system.splice(1, 0, res.additionalContext);\n }\n },`);\n }\n\n const factory = `\nexport default async function (ctx) {\n const PROJECT_DIR =\n (ctx && (ctx.directory || (ctx.worktree && ctx.worktree.path))) || process.cwd();\n return {\n${handlers.join(\"\\n\")}\n };\n}\n`;\n return header + factory;\n}\n\nexport const emitNpmPlugin: FormatEmitter = (\n connector: ResolvedConnector,\n ctx: EmitContext,\n): PackageResult => {\n const { emit, files } = createEmitter(ctx.dryRun);\n const pluginDir = join(ctx.outDir, connector.id);\n const notes: string[] = [];\n\n // ── package.json (publishable) ────────────────────────────────────────────\n emit(join(pluginDir, \"package.json\"), json(buildPackageJson(connector)));\n\n // ── index.js (the default-export plugin bridge) ───────────────────────────\n emit(join(pluginDir, \"index.js\"), buildIndexJs(connector));\n\n // ── skills/<name>/SKILL.md (+ resources) — pi bundles skills ──────────────\n for (const skill of connector.skills) {\n const skillDir = join(pluginDir, \"skills\", skill.name);\n emit(join(skillDir, \"SKILL.md\"), renderSkillMd(skill));\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\n const target = resolveWithin(skillDir, rel);\n if (target === null) continue;\n emit(target, contents);\n }\n }\n\n // ── README.md ─────────────────────────────────────────────────────────────\n emit(\n join(pluginDir, \"README.md\"),\n `# ${connector.displayName}\\n\\nOpenCode / Kilo / Pi plugin package emitted by agent-connector.\\n\\n` +\n \"Install with `opencode plugin install <pkg>` / `kilo plugin <pkg>` / `pi install <pkg>`.\\n\\n\" +\n \"Local install (no npm publish needed — live-verified on opencode 1.17.0 / kilo 7.3.16):\\n\" +\n \"`opencode plugin --global file:///<abs-dir>` or `kilo plugin --global file:///<abs-dir>`\\n\" +\n \"(bare absolute paths work too; the entry lands in the config `plugin` array —\\n\" +\n \"there is no uninstall verb, remove it by editing that array).\\n\\n\" +\n \"## Prerequisite\\n\\n\" +\n \"The generated package depends on `@ken-jo/agent-connector` and hooks resolve that\\n\" +\n \"local runtime first. A global `agent-connector` binary is only a recovery fallback\\n\" +\n \"for hand-built bundles; hooks silently no-op, fail-open, if neither runtime exists.\\n\\n\" +\n \"## Before you publish\\n\\n\" +\n \"The emitted package.json carries **no `license` and no `author`** unless your\\n\" +\n \"connector declared `publish.author` — set them to YOUR terms before `npm publish`.\\n\",\n );\n\n notes.push(\n \"npm-plugin: hooks resolve the bundled @ken-jo/agent-connector dependency first; a global agent-connector binary is only a recovery fallback, and hooks silently fail-open without either runtime\",\n );\n notes.push(\n \"npm-plugin: set license/author in the emitted package.json before `npm publish` — agent-connector does not license your plugin for you\",\n );\n\n // Surface the inherent limits of the npm-plugin contract.\n if (connector.commands.length > 0) {\n notes.push(\n `npm-plugin: ${connector.commands.length} command(s) NOT bundled — opencode/kilo commands are native host dirs`,\n );\n }\n if (connector.subagents.length > 0) {\n notes.push(\n `npm-plugin: ${connector.subagents.length} subagent(s) NOT bundled — opencode/kilo subagents are native host dirs`,\n );\n }\n if (connector.server) {\n notes.push(\n `npm-plugin: MCP server NOT bundled inside the package — register it via the opencode.json \"mcp\" key`,\n );\n }\n\n return { files, pluginDir, ...(notes.length > 0 ? { notes } : {}) };\n};\n","/**\n * core/package-formats/agent-plugin — the `agent-plugin` emitter: an\n * **Agent Plugins 1.0.0** package (https://agent-plugins.org — the Vercel-led\n * open spec co-maintained with AWS, Cursor, GitHub, Microsoft and OpenAI).\n *\n * This is the SINGLE SOURCE OF TRUTH bundle for every host that speaks the\n * spec. One directory, installed through each client's own plugin flow:\n * • Codex / ChatGPT — root plugin.json is Codex's preferred manifest\n * (codex-rs/utils/plugins: `find_plugin_manifest_path`\n * checks it before `.codex-plugin/`); hooks arrive via\n * the `com.openai` extension namespace. The codex\n * marketplace driver stages THIS bundle (live-verified\n * 0.149: `plugin marketplace add` + `plugin add`).\n * • GitHub Copilot CLI / VS Code / JetBrains Copilot — hooks, agents and\n * commands ride in `com.github.copilot/`; the copilot\n * driver stages THIS bundle (live-verified CLI 1.0.80),\n * and VS Code auto-imports what the CLI installed.\n * • Kiro, Hermes, Cursor, OpenClaw, … — portable skills + MCP.\n * Hosts that do not speak the spec (Claude Code, Antigravity, Gemini CLI, Qwen\n * Code, Droid, Kimi, OpenCode/Kilo/Pi) keep their native formats.\n *\n * Layout (spec §4–§8):\n * <outDir>/<id>/\n * ├── plugin.json REQUIRED manifest — closed schema:\n * │ $schema (const) + name (slug) + optional\n * │ version/description/author/extensions\n * ├── mcp.json portable MCP servers: stdio |\n * │ streamable-http | sse (closed variants)\n * ├── bin/agent-connector.mjs PORTABLE LAUNCHER (see below)\n * ├── skills/<n>/SKILL.md (+res) Agent Skills (agentskills.io) — immediate\n * │ children of skills/ only (§6.1)\n * ├── com.github.copilot/ CLIENT EXTENSION namespaces (§8.2): hooks,\n * │ ├── hooks/hooks.json commands and subagents are NOT portable v1\n * │ ├── commands/<n>.md components, so each client that documents a\n * │ └── agents/<n>.agent.md namespace gets its own copy (CLIENT_NAMESPACES);\n * ├── com.openai/hooks/hooks.json clients ignore namespaces they do not own\n * └── README.md install notes\n * <outDir>/.claude-plugin/marketplace.json local catalogs so the two-step\n * <outDir>/.agents/plugins/marketplace.json copilot / codex `marketplace add\n * <outDir>` + install still works\n *\n * THE LAUNCHER — why the bundle never embeds a machine path (§7.2.1):\n * `command` MUST be ONE executable token — a bare name resolved by the\n * platform's search rules, or a plugin-relative `./…` path. An absolute path\n * is NON-conformant, and a fatal schema violation makes the client reject the\n * WHOLE plugin (§5.2). So instead of baking `~/.agent-connector/bin/...` in,\n * the bundle ships `bin/agent-connector.mjs`, launched as\n * `node ${PLUGIN_ROOT}/bin/agent-connector.mjs …` (`${PLUGIN_ROOT}` expansion\n * in args is spec-mandated, §7.2.3; `node` is the one bare dependency the\n * framework already has). At run time it resolves the framework runtime in a\n * fixed order — the stable home binary (present on any machine that ran a\n * branded `install`), then `agent-connector` on PATH (a global install), then\n * `npx @ken-jo/agent-connector@^<range>` — so the SAME bundle works for a\n * local marketplace install AND for shared distribution, and the runtime stays\n * the one home binary (R1).\n *\n * Hooks are client-namespace content, outside the spec's path rules, so each\n * namespace uses the command form its client documents: Copilot / VS Code\n * expand `${PLUGIN_ROOT}` in hook commands → the launcher; Codex documents no\n * root token for hook commands → the SAME absolute home-bin command the\n * native codex-plugin bundle always carried (staged locally by the driver).\n *\n * Other conformance rules honored: `cwd` MUST be `./…`, `${PLUGIN_ROOT}…` or\n * `${PLUGIN_DATA}…`; env keys `PLUGIN_ROOT` / `PLUGIN_DATA` are reserved.\n * Non-conformant values are dropped with a note rather than emitted invalid.\n *\n * Remote servers ARE carried (the only bundle format that does): an `http`\n * transport maps to `streamable-http`, `sse` to the legacy `sse` variant; `ws`\n * has no spec analog and is dropped with a note. The remote URL/headers pass\n * through verbatim (the spec forbids placeholder expansion there).\n */\n\nimport { join } from \"node:path\";\n\nimport type { PlatformId, ResolvedConnector, ServerDef } from \"../types.js\";\nimport {\n renderCommandMd,\n renderSkillMd,\n renderSubagentMd,\n} from \"../../adapters/claude-code/render.js\";\nimport { buildHomeBinHookCommand, shouldWrapForTelemetry } from \"../spawn.js\";\nimport {\n AGENT_CONNECTOR_PACKAGE_NAME,\n CLAUDE_MAPPED_EVENTS,\n createEmitter,\n json,\n renderEnv,\n resolveFrameworkDependencyRange,\n resolveWithin,\n type EmitContext,\n type FormatEmitter,\n type PackageResult,\n type PluginHookEntry,\n} from \"./shared.js\";\n\n/** Canonical Agent Plugins 1.0.0 manifest schema id (plugin.json `$schema`, const). */\nexport const AGENT_PLUGIN_SCHEMA =\n \"https://agent-plugins.org/schemas/1.0.0/plugin.schema.json\";\n/** Canonical Agent Plugins 1.0.0 MCP schema id (mcp.json `$schema`, const). */\nexport const AGENT_PLUGIN_MCP_SCHEMA =\n \"https://agent-plugins.org/schemas/1.0.0/mcp.schema.json\";\n/** Spec version this emitter targets (drives both `$schema` ids). */\nexport const AGENT_PLUGIN_SPEC_VERSION = \"1.0.0\";\n\n/** Plugin-relative path of the portable launcher the MCP entry + hooks run. */\nexport const AGENT_PLUGIN_LAUNCHER = \"bin/agent-connector.mjs\";\n\n/** The catalog name every emitted marketplace.json carries (`<id>@agent-connector`). */\nconst CATALOG_NAME = \"agent-connector\";\n\n/**\n * How a client namespace's hook commands reach the framework runtime.\n * \"plugin-root-launcher\" — `node \"${PLUGIN_ROOT}/bin/agent-connector.mjs\" hook …`\n * (clients that expand `${PLUGIN_ROOT}` in hook commands)\n * \"home-bin\" — `\"<homeBinPath>\" hook …` (the universal home-bin\n * command; clients with no documented root token)\n */\nexport type HookCommandStyle = \"plugin-root-launcher\" | \"home-bin\";\n\n/**\n * A client extension namespace (§8.2) this emitter populates. Hooks, commands\n * and subagents are client-specific, so ONE bundle carries a copy per client\n * that documents a namespace; every other client ignores dirs it does not own.\n */\nexport interface ClientNamespace {\n /** Reverse-domain directory name at the plugin root. */\n readonly namespace: string;\n /** Human-readable client name for notes/README. */\n readonly label: string;\n /** Default `--host` stamp for this namespace's hooks (telemetry attribution). */\n readonly platform: PlatformId;\n /**\n * Every PlatformId that reads this namespace. A staging `hostHint` matching\n * one of these restamps the hooks for that exact host.\n */\n readonly readers: readonly PlatformId[];\n /** Hook command form this client documents. */\n readonly hookStyle: HookCommandStyle;\n /** Subagent file name inside `<ns>/agents/` (null: client reads no agents dir). */\n readonly agentFile: ((name: string) => string) | null;\n /** Command file name inside `<ns>/commands/` (null: client reads no commands dir). */\n readonly commandFile: ((name: string) => string) | null;\n /**\n * Manifest `extensions[<namespace>]` entry the client needs to find the\n * namespace files (Codex resolves hooks from its extension object). Null when\n * the client discovers the directory by convention.\n */\n readonly manifestExtension: ((paths: { hooks?: string }) => Record<string, unknown>) | null;\n}\n\n/**\n * Documented client namespaces — the data every namespace-specific behavior is\n * driven from. Extend this table as more clients document theirs.\n *\n * com.github.copilot — VS Code docs: `com.github.copilot/hooks/hooks.json`\n * (hooks) and `com.github.copilot/agents/<n>.agent.md` (custom agents), also\n * read by Copilot CLI and the Copilot app; commands mirror the Copilot-native\n * plugin layout. `${PLUGIN_ROOT}` is expanded in hook commands.\n * com.openai — Codex (codex-rs/core-plugins/agent_plugin_manifest.rs): the\n * `extensions[\"com.openai\"]` object is parsed as a Codex plugin manifest\n * overlay whose `hooks` path resolves relative to the plugin root; the\n * namespace directory holds the hooks file. Codex reads no agents/commands.\n */\nexport const CLIENT_NAMESPACES: readonly ClientNamespace[] = [\n {\n namespace: \"com.github.copilot\",\n label: \"GitHub Copilot (CLI, VS Code, JetBrains)\",\n platform: \"copilot-cli\",\n readers: [\"copilot-cli\", \"vscode-copilot\", \"jetbrains-copilot\"],\n hookStyle: \"plugin-root-launcher\",\n agentFile: (name) => `${name}.agent.md`,\n commandFile: (name) => `${name}.md`,\n manifestExtension: null,\n },\n {\n namespace: \"com.openai\",\n label: \"Codex / ChatGPT\",\n platform: \"codex\",\n readers: [\"codex\"],\n hookStyle: \"home-bin\",\n agentFile: null,\n commandFile: null,\n manifestExtension: ({ hooks }) => (hooks ? { hooks } : {}),\n },\n];\n\n/** Reserved runtime variables a plugin cannot set (§9). */\nconst RESERVED_ENV_KEYS = new Set([\"PLUGIN_ROOT\", \"PLUGIN_DATA\"]);\n\n/**\n * Coerce a connector id into a spec-conformant plugin `name` (§5.5):\n * 1–64 chars, `[a-z0-9]` with `-`/`.` separators, alphanumeric at both ends,\n * never `--` or `..`. Connector ids are already kebab-case, so this is a\n * defensive normalization, not a rename.\n */\nexport function toAgentPluginName(id: string): string {\n let name = id\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9.-]+/g, \"-\")\n .replace(/-{2,}/g, \"-\")\n .replace(/\\.{2,}/g, \".\")\n .replace(/(?:-\\.|\\.-)+/g, \"-\")\n .replace(/^[^a-z0-9]+|[^a-z0-9]+$/g, \"\");\n if (name.length > 64) {\n name = name.slice(0, 64).replace(/[^a-z0-9]+$/g, \"\");\n }\n return name.length > 0 ? name : \"connector\";\n}\n\n/** True when `cwd` has one of the three forms the spec permits (§7.2.1). */\nfunction isConformantCwd(cwd: string): boolean {\n return (\n cwd.startsWith(\"./\") ||\n cwd === \"${PLUGIN_ROOT}\" ||\n cwd.startsWith(\"${PLUGIN_ROOT}/\") ||\n cwd === \"${PLUGIN_DATA}\" ||\n cwd.startsWith(\"${PLUGIN_DATA}/\")\n );\n}\n\n/** True when a stdio `command` is a bare name or a plugin-relative `./` path. */\nfunction isConformantCommand(command: string): boolean {\n if (command.startsWith(\"./\")) return true;\n // A bare executable name carries no path separators.\n return !command.includes(\"/\") && !command.includes(\"\\\\\");\n}\n\n/** A stdio server entry (spec `stdioServer` variant). */\ninterface StdioServerEntry {\n type: \"stdio\";\n command: string;\n args?: string[];\n env?: Record<string, string>;\n cwd?: string;\n}\n\n/** A remote server entry (spec `streamableHttpServer` | `sseServer` variants). */\ninterface RemoteServerEntry {\n type: \"streamable-http\" | \"sse\";\n url: string;\n headers?: Record<string, string>;\n}\n\ntype ServerEntry = StdioServerEntry | RemoteServerEntry;\n\n/** The launcher path as the spec's root token spells it (expanded in args + hook commands). */\nconst LAUNCHER_AT_ROOT = `\\${PLUGIN_ROOT}/${AGENT_PLUGIN_LAUNCHER}`;\n\n/** The hook command for one namespace, in the style that client documents. */\nfunction hookCommand(\n style: HookCommandStyle,\n homeBin: string,\n platform: PlatformId,\n event: string,\n connectorId: string,\n): string {\n if (style === \"home-bin\") {\n return buildHomeBinHookCommand(homeBin, platform, event, connectorId);\n }\n return `node \"${LAUNCHER_AT_ROOT}\" hook ${platform} ${event} --connector ${connectorId}`;\n}\n\n/**\n * Render the connector's server into a spec-conformant mcp.json entry, or null\n * when nothing portable can be emitted. Drops (with notes) rather than emitting\n * a value a conforming client would reject.\n */\nfunction buildServerEntry(\n connector: ResolvedConnector,\n hostHint: PlatformId | undefined,\n notes: string[],\n): { serverName: string; entry: ServerEntry; wrapped: boolean } | null {\n const server: ServerDef | undefined = connector.server;\n if (!server) return null;\n const serverName = connector.id;\n\n if (server.transport === \"stdio\") {\n const realCommand = server.command ?? \"\";\n if (realCommand === \"\") return null;\n const realArgs = [...(server.args ?? [])];\n\n let entry: StdioServerEntry;\n let wrapped = false;\n if (shouldWrapForTelemetry(server, connector.telemetry)) {\n const flags = [\"serve\", \"--connector\", connector.id];\n if (hostHint !== undefined) flags.push(\"--host\", hostHint);\n entry = {\n type: \"stdio\",\n command: \"node\",\n args: [LAUNCHER_AT_ROOT, ...flags, \"--\", realCommand, ...realArgs],\n };\n wrapped = true;\n } else {\n entry = { type: \"stdio\", command: realCommand };\n if (realArgs.length > 0) entry.args = realArgs;\n if (!isConformantCommand(realCommand)) {\n notes.push(\n `agent-plugin: server command \"${realCommand}\" is neither a bare executable name nor a plugin-relative ./ path — conforming clients may reject it (spec §7.2.1)`,\n );\n }\n }\n\n const env = renderEnv(server.env);\n if (env) {\n const kept: Record<string, string> = {};\n for (const [key, value] of Object.entries(env)) {\n if (RESERVED_ENV_KEYS.has(key)) {\n notes.push(\n `agent-plugin: dropped env \"${key}\" — PLUGIN_ROOT / PLUGIN_DATA are reserved runtime variables a plugin cannot set`,\n );\n continue;\n }\n kept[key] = value;\n }\n if (Object.keys(kept).length > 0) entry.env = kept;\n }\n\n if (server.cwd) {\n if (isConformantCwd(server.cwd)) {\n entry.cwd = server.cwd;\n } else {\n notes.push(\n `agent-plugin: dropped cwd \"${server.cwd}\" — must be ./-relative, \\${PLUGIN_ROOT}… or \\${PLUGIN_DATA}… (the plugin root is used instead)`,\n );\n }\n }\n return { serverName, entry, wrapped };\n }\n\n const url = server.url ?? \"\";\n if (url === \"\") return null;\n\n if (server.transport === \"ws\") {\n notes.push(\n `agent-plugin: dropped the \"ws\" server — Agent Plugins 1.0.0 defines only stdio, streamable-http and (legacy) sse transports`,\n );\n return null;\n }\n\n const entry: RemoteServerEntry = {\n type: server.transport === \"sse\" ? \"sse\" : \"streamable-http\",\n url,\n };\n const headers = renderEnv(server.headers);\n if (headers) entry.headers = headers;\n if (server.auth) {\n notes.push(\n `agent-plugin: the server's \\`auth\\` block is not portable — Agent Plugins carries only literal HTTP headers; the client handles authentication`,\n );\n }\n if (!/^https:\\/\\//i.test(url) && !/^http:\\/\\/(localhost|127\\.\\d+\\.\\d+\\.\\d+|\\[::1\\])(?:[:/]|$)/i.test(url)) {\n notes.push(\n `agent-plugin: remote url \"${url}\" is not HTTPS — the spec requires HTTPS for non-loopback endpoints`,\n );\n }\n return { serverName, entry, wrapped: false };\n}\n\n/** Build the Claude-shaped hooks.json for one client namespace, stamped for `platform`. */\nfunction buildNamespaceHooks(\n connector: ResolvedConnector,\n ns: ClientNamespace,\n platform: PlatformId,\n homeBin: string,\n): { hooks: Record<string, PluginHookEntry[]> } | null {\n const events = connector.hookEvents.filter((e) => CLAUDE_MAPPED_EVENTS.has(e));\n if (events.length === 0) return null;\n const hooks: Record<string, PluginHookEntry[]> = {};\n for (const event of events) {\n const matcher = connector.hooks[event]?.matcher ?? \"\";\n const command = {\n type: \"command\" as const,\n command: hookCommand(ns.hookStyle, homeBin, platform, event, connector.id),\n };\n hooks[event] = [matcher ? { matcher, hooks: [command] } : { hooks: [command] }];\n }\n return { hooks };\n}\n\n/** Build plugin.json — every field the closed schema permits that we can populate. */\nfunction buildManifest(\n connector: ResolvedConnector,\n extensions: Record<string, Record<string, unknown>>,\n): Record<string, unknown> {\n const manifest: Record<string, unknown> = {\n $schema: AGENT_PLUGIN_SCHEMA,\n name: toAgentPluginName(connector.id),\n };\n if (connector.version && connector.version !== \"0.0.0\") {\n manifest.version = connector.version;\n }\n manifest.description = `${connector.displayName} — connector emitted by agent-connector`;\n const author = connector.publish?.author;\n if (author?.name) {\n const a: Record<string, string> = { name: author.name };\n if (author.email) a.email = author.email;\n if (author.url) a.url = author.url;\n manifest.author = a;\n }\n if (Object.keys(extensions).length > 0) manifest.extensions = extensions;\n return manifest;\n}\n\n/**\n * Source of `bin/agent-connector.mjs`. Self-contained ESM, no framework\n * imports: it only locates the runtime and re-executes it with inherited stdio\n * (the MCP stdio proxy and hook JSON pass straight through). Resolution order\n * is fixed and documented in the module header.\n */\nexport function renderLauncher(): string {\n const range = resolveFrameworkDependencyRange();\n const spec = range === \"*\" ? AGENT_CONNECTOR_PACKAGE_NAME : `${AGENT_CONNECTOR_PACKAGE_NAME}@${range}`;\n return `#!/usr/bin/env node\n/**\n * AUTO-GENERATED by agent-connector — DO NOT EDIT.\n *\n * Portable launcher for the agent-connector runtime. Agent Plugins packages\n * must not embed absolute paths, so this file resolves the runtime at run time:\n * 1. $AGENT_CONNECTOR_HOME_BIN (explicit override)\n * 2. <$AGENT_CONNECTOR_DATA_DIR | ~/.agent-connector>/bin/agent-connector (the stable home binary)\n * 3. \\`agent-connector\\` on PATH (a global install)\n * 4. npx -y ${spec} (network; last resort)\n * stdio is inherited so the MCP stdio proxy and hook JSON pass straight through.\n */\nimport { spawn } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { delimiter, join } from \"node:path\";\n\nconst win = process.platform === \"win32\";\nconst argv = process.argv.slice(2);\n\nfunction onPath(name) {\n const exts = win ? [\".cmd\", \".exe\", \".bat\", \"\"] : [\"\"];\n for (const dir of (process.env.PATH ?? \"\").split(delimiter)) {\n if (!dir) continue;\n for (const ext of exts) {\n const candidate = join(dir, name + ext);\n if (existsSync(candidate)) return candidate;\n }\n }\n return null;\n}\n\nconst dataRoot = process.env.AGENT_CONNECTOR_DATA_DIR || join(homedir(), \".agent-connector\");\nconst homeBin = join(dataRoot, \"bin\", win ? \"agent-connector.cmd\" : \"agent-connector\");\nconst explicit = process.env.AGENT_CONNECTOR_HOME_BIN;\n\nlet command;\nlet args;\nconst local = [explicit, homeBin].find((p) => p && existsSync(p)) ?? onPath(\"agent-connector\");\nif (local) {\n command = local;\n args = argv;\n} else {\n command = win ? \"npx.cmd\" : \"npx\";\n args = [\"-y\", ${JSON.stringify(spec)}, ...argv];\n}\n\n// .cmd/.bat wrappers need the shell on Windows; everything else spawns directly.\nconst shell = win && /\\\\.(cmd|bat)$/i.test(command);\nconst child = spawn(command, args, { stdio: \"inherit\", windowsHide: true, shell });\nfor (const signal of [\"SIGINT\", \"SIGTERM\", \"SIGHUP\"]) {\n process.on(signal, () => child.kill(signal));\n}\nchild.on(\"error\", (err) => {\n process.stderr.write(\\`agent-connector launcher: cannot start \\${command}: \\${err.message}\\\\n\\`);\n process.exit(1);\n});\nchild.on(\"exit\", (code, signal) => {\n if (signal) process.kill(process.pid, signal);\n process.exit(code ?? 1);\n});\n`;\n}\n\n/** The minimal object-owner catalog claude/copilot/codex all read. */\nfunction buildCatalog(connector: ResolvedConnector): Record<string, unknown> {\n return {\n name: CATALOG_NAME,\n owner: { name: connector.publish?.author?.name ?? CATALOG_NAME },\n plugins: [\n {\n name: connector.id,\n source: `./${connector.id}`,\n description: `${connector.displayName} — connector emitted by agent-connector`,\n },\n ],\n };\n}\n\n/** The bundle README: what is inside + how a consumer installs it. */\nfunction buildReadme(\n connector: ResolvedConnector,\n has: { mcp: boolean; skills: boolean; namespaces: ClientNamespace[]; launcher: boolean },\n): string {\n const lines: string[] = [\n `# ${connector.displayName} — Agent Plugin`,\n \"\",\n `An [Agent Plugins ${AGENT_PLUGIN_SPEC_VERSION}](https://agent-plugins.org) package for the`,\n `\\`${connector.id}\\` connector, emitted by agent-connector.`,\n \"\",\n \"## Contents\",\n \"\",\n \"- `plugin.json` — the plugin manifest\",\n ];\n if (has.mcp) lines.push(\"- `mcp.json` — the MCP server entry\");\n if (has.skills) lines.push(\"- `skills/<name>/SKILL.md` — Agent Skills\");\n for (const ns of has.namespaces) {\n lines.push(\n `- \\`${ns.namespace}/\\` — client extension namespace for ${ns.label} (other clients ignore it)`,\n );\n }\n if (has.launcher) {\n lines.push(\n `- \\`${AGENT_PLUGIN_LAUNCHER}\\` — portable launcher that locates the agent-connector runtime (home binary → PATH → npx) so per-tool token telemetry carries through without any absolute path in the bundle`,\n );\n }\n lines.push(\n \"\",\n \"## Install\",\n \"\",\n \"Locally, the directory ABOVE this one is a marketplace root — register it and\",\n `install by name: \\`copilot plugin marketplace add <root> && copilot plugin install ${connector.id}@${CATALOG_NAME}\\``,\n `or \\`codex plugin marketplace add <root> && codex plugin add ${connector.id}@${CATALOG_NAME}\\`.`,\n \"\",\n \"To share it, push this directory to a git repository and install it from\",\n \"source with your client's plugin flow — in VS Code run **Chat: Install Plugin\",\n \"From Source** from the Command Palette and enter the repository URL. Every\",\n \"Agent Plugins client has an equivalent: https://agent-plugins.org/compatible-clients\",\n \"\",\n );\n return lines.join(\"\\n\");\n}\n\n/**\n * Parse an Agent Plugins manifest (a root plugin.json carrying the AP `$schema`).\n * Returns null for anything else, so callers can use it as the format marker.\n */\nexport function readAgentPluginManifest(\n manifestJson: string,\n): { name?: string; version?: string; description?: string } | null {\n try {\n const parsed = JSON.parse(manifestJson) as Record<string, unknown>;\n if (parsed.$schema !== AGENT_PLUGIN_SCHEMA) return null;\n return parsed as { name?: string; version?: string; description?: string };\n } catch {\n return null;\n }\n}\n\nexport const emitAgentPlugin: FormatEmitter = (\n connector: ResolvedConnector,\n ctx: EmitContext,\n): PackageResult => {\n const { emit, files } = createEmitter(ctx.dryRun);\n const pluginDir = join(ctx.outDir, connector.id);\n const notes: string[] = [];\n const hostHint = ctx.hostHint;\n\n // ── client extension namespaces (non-portable surfaces, one copy each) ────\n // Computed first: Codex needs the hooks path inside the manifest.\n const hasHooks = connector.hookEvents.some((e) => CLAUDE_MAPPED_EVENTS.has(e));\n const populated: ClientNamespace[] = [];\n const extensions: Record<string, Record<string, unknown>> = {};\n const namespaceFiles: Array<{ path: string; contents: string }> = [];\n let launcherHooks = false;\n let homeBinHooks = false;\n for (const ns of CLIENT_NAMESPACES) {\n const extDir = join(pluginDir, ns.namespace);\n const platform =\n hostHint !== undefined && ns.readers.includes(hostHint) ? hostHint : ns.platform;\n const hooksRel = `${ns.namespace}/hooks/hooks.json`;\n let wrote = false;\n const hooksJson = hasHooks ? buildNamespaceHooks(connector, ns, platform, ctx.homeBinPath) : null;\n if (hooksJson) {\n namespaceFiles.push({ path: join(extDir, \"hooks\", \"hooks.json\"), contents: json(hooksJson) });\n if (ns.hookStyle === \"plugin-root-launcher\") launcherHooks = true;\n else homeBinHooks = true;\n wrote = true;\n }\n if (ns.commandFile) {\n for (const cmd of connector.commands) {\n namespaceFiles.push({\n path: join(extDir, \"commands\", ns.commandFile(cmd.name)),\n contents: renderCommandMd(cmd),\n });\n wrote = true;\n }\n }\n if (ns.agentFile) {\n for (const agent of connector.subagents) {\n namespaceFiles.push({\n path: join(extDir, \"agents\", ns.agentFile(agent.name)),\n contents: renderSubagentMd(agent),\n });\n wrote = true;\n }\n }\n if (!wrote) continue;\n populated.push(ns);\n if (ns.manifestExtension) {\n const ext = ns.manifestExtension({ hooks: hooksJson ? `./${hooksRel}` : undefined });\n if (Object.keys(ext).length > 0) extensions[ns.namespace] = ext;\n }\n }\n\n // ── plugin.json (REQUIRED, at the plugin root) ────────────────────────────\n emit(join(pluginDir, \"plugin.json\"), json(buildManifest(connector, extensions)));\n\n // ── mcp.json (portable stdio | streamable-http | sse) ─────────────────────\n const mcp = buildServerEntry(connector, hostHint, notes);\n if (mcp) {\n emit(\n join(pluginDir, \"mcp.json\"),\n json({\n $schema: AGENT_PLUGIN_MCP_SCHEMA,\n mcpServers: { [mcp.serverName]: mcp.entry },\n }),\n );\n }\n\n // ── skills/<name>/SKILL.md (+ resources) — Agent Skills, immediate children ─\n for (const skill of connector.skills) {\n const skillDir = join(pluginDir, \"skills\", skill.name);\n emit(join(skillDir, \"SKILL.md\"), renderSkillMd(skill));\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\n const target = resolveWithin(skillDir, rel);\n if (target === null) continue; // never write outside the skill dir\n emit(target, contents);\n }\n }\n\n // ── <namespace>/… ─────────────────────────────────────────────────────────\n for (const f of namespaceFiles) emit(f.path, f.contents);\n if (populated.length > 0) {\n notes.push(\n `agent-plugin: hooks/commands/subagents are not portable Agent Plugins 1.0 components — emitted under the ${populated\n .map((ns) => `${ns.namespace}/`)\n .join(\", \")} client extension namespace(s); clients ignore namespaces they do not own`,\n );\n }\n\n // ── bin/agent-connector.mjs — the portable launcher ───────────────────────\n const launcher = launcherHooks || (mcp !== null && mcp.wrapped);\n if (launcher) {\n emit(join(pluginDir, AGENT_PLUGIN_LAUNCHER), renderLauncher());\n notes.push(\n `agent-plugin: the MCP entry${launcherHooks ? \" and Copilot hooks\" : \"\"} run through the bundled launcher ${AGENT_PLUGIN_LAUNCHER} (no absolute path — resolves the home binary, then PATH, then npx ${AGENT_CONNECTOR_PACKAGE_NAME})`,\n );\n }\n if (homeBinHooks) {\n notes.push(\n `agent-plugin: com.openai/ hooks call this machine's agent-connector launcher (${ctx.homeBinPath}) — Codex documents no plugin-root token for hook commands; valid for a local install, re-run \\`package\\` per machine to share`,\n );\n }\n\n // ── README.md ─────────────────────────────────────────────────────────────\n emit(\n join(pluginDir, \"README.md\"),\n buildReadme(connector, {\n mcp: mcp !== null,\n skills: connector.skills.length > 0,\n namespaces: populated,\n launcher,\n }),\n );\n\n // ── local marketplace catalogs (outDir level, outside the plugin) ─────────\n // The same object-owner catalog at both documented locations, so\n // `copilot plugin marketplace add <outDir>` and `codex plugin marketplace add\n // <outDir>` (which REJECTS a `.codex-plugin/` catalog) both resolve `./<id>`.\n const catalog = json(buildCatalog(connector));\n const marketplacePath = join(ctx.outDir, \".claude-plugin\", \"marketplace.json\");\n emit(marketplacePath, catalog);\n emit(join(ctx.outDir, \".agents\", \"plugins\", \"marketplace.json\"), catalog);\n\n const result: PackageResult = { files, pluginDir, marketplacePath };\n if (notes.length > 0) result.notes = notes;\n return result;\n};\n","/**\n * core/package-formats/mcp-server — emit an official MCP Registry `server.json`.\n *\n * Unlike the host plugin/marketplace bundles, server.json is a DISCOVERY +\n * PUBLISH artifact: it describes the developer's REAL upstream MCP server (what\n * a registry installer runs DIRECTLY), so it must NOT carry agent-connector's\n * `serve` telemetry wrapper. It is emitted from the connector's `publish`\n * metadata (the namespace the dev proved ownership of + their published package)\n * and conforms to the pinned 2025-12-11 schema:\n * • name = `${publish.registryNamespace}/${connector.id}` (one '/', regex-checked)\n * • version = concrete SemVer (ranges are rejected by the registry)\n * • stdio → packages[] { registryType:\"npm\", identifier:<dev pkg>, transport:{type:\"stdio\"} }\n * • remote → remotes[] { type:\"streamable-http\"|\"sse\", url, headers }\n * • token env vars are marked isSecret.\n *\n * agent-connector EMITS a conformant server.json; the dev runs the publish-time\n * ownership proof + upload themselves with the official `mcp-publisher` CLI.\n */\n\nimport { resolve } from \"node:path\";\n\nimport type { ResolvedConnector, ServerDef } from \"../types.js\";\nimport {\n MCP_SERVER_SCHEMA_URL,\n NPM_REGISTRY_BASE_URL,\n REGISTRY_NAME_RE,\n isConcreteSemver,\n isPlaceholderVersion,\n registryTransportType,\n} from \"../mcp-standard.js\";\nimport type { EmitContext, FormatEmitter, PackageResult } from \"./shared.js\";\nimport { createEmitter, json } from \"./shared.js\";\n\n/** A server.json KeyValueInput (environmentVariables[] / headers[] entry). */\ninterface KeyValueInput {\n name: string;\n isSecret?: boolean;\n isRequired?: boolean;\n}\n\n/** Build environmentVariables[] from a stdio ServerDef, marking the bearer token secret. */\nfunction buildEnvVars(server: ServerDef): KeyValueInput[] {\n const vars: KeyValueInput[] = [];\n const byName = new Map<string, KeyValueInput>();\n for (const key of Object.keys(server.env ?? {})) {\n const v: KeyValueInput = { name: key };\n vars.push(v);\n byName.set(key, v);\n }\n if (server.auth?.type === \"bearerEnv\" && server.auth.bearerEnvVar) {\n const name = server.auth.bearerEnvVar;\n const existing = byName.get(name);\n if (existing) {\n existing.isSecret = true;\n existing.isRequired = true;\n } else {\n vars.push({ name, isSecret: true, isRequired: true });\n }\n }\n return vars;\n}\n\n/** Build the conformant server.json object (throws a clear error on missing inputs). */\nfunction buildServerJson(\n connector: ResolvedConnector,\n notes: string[],\n): Record<string, unknown> {\n const publish = connector.publish ?? {};\n\n if (!publish.registryNamespace) {\n throw new Error(\n 'package --format mcp-server-json needs publish.registryNamespace — a reverse-DNS ' +\n 'namespace you OWN (e.g. \"io.github.<your-handle>\" or \"com.<your-domain>\"). ' +\n \"agent-connector never publishes under a namespace it owns; set it in your connector config.\",\n );\n }\n const name = `${publish.registryNamespace}/${connector.id}`;\n if (!REGISTRY_NAME_RE.test(name)) {\n throw new Error(\n `server.json name \"${name}\" must match ${REGISTRY_NAME_RE} (exactly one \"/\").`,\n );\n }\n if (!isConcreteSemver(connector.version)) {\n throw new Error(\n `server.json version must be a concrete SemVer (the registry rejects ranges); got \"${connector.version}\".`,\n );\n }\n if (isPlaceholderVersion(connector.version)) {\n notes.push(\n 'version is the unset placeholder \"0.0.0\" — set a real version before publishing to the registry.',\n );\n }\n\n const out: Record<string, unknown> = {\n $schema: MCP_SERVER_SCHEMA_URL,\n name,\n description: connector.displayName,\n version: connector.version,\n };\n\n const server = connector.server;\n if (!server) {\n notes.push(\n \"connector declares no server — emitted server.json carries neither packages nor remotes \" +\n \"(a hooks/commands-only connector is not a registry server).\",\n );\n return out;\n }\n\n const tt = registryTransportType(server.transport);\n if (tt === null) {\n notes.push(\n `transport \"${server.transport}\" is not an MCP spec transport and cannot be represented in ` +\n \"server.json; emitted server metadata without a package/remote entry.\",\n );\n return out;\n }\n\n if (server.transport === \"stdio\") {\n if (!publish.packageName) {\n throw new Error(\n \"package --format mcp-server-json needs publish.packageName — your REAL published npm \" +\n 'package that runs the MCP server (e.g. \"@acme/acme-db-mcp\"). The registry runs that ' +\n \"package directly, not agent-connector's serve wrapper.\",\n );\n }\n const pkg: Record<string, unknown> = {\n registryType: \"npm\",\n registryBaseUrl: publish.registryBaseUrl ?? NPM_REGISTRY_BASE_URL,\n identifier: publish.packageName,\n version: connector.version,\n transport: { type: \"stdio\" },\n };\n const envVars = buildEnvVars(server);\n if (envVars.length > 0) pkg.environmentVariables = envVars;\n out.packages = [pkg];\n } else {\n // streamable-http | sse → remotes[]\n const remote: Record<string, unknown> = { type: tt, url: server.url };\n const headers = Object.keys(server.headers ?? {}).map((k): KeyValueInput => ({ name: k }));\n if (headers.length > 0) remote.headers = headers;\n if (server.auth && server.auth.type !== \"none\") {\n notes.push(\n `remote server uses auth \"${server.auth.type}\" — add the credential header (isSecret) to ` +\n \"the emitted remotes[].headers before publishing.\",\n );\n }\n out.remotes = [remote];\n }\n\n return out;\n}\n\n/** Emit a registry-conformant server.json for `connector` into ctx.outDir. */\nexport const emitMcpServerJson: FormatEmitter = (\n connector: ResolvedConnector,\n ctx: EmitContext,\n): PackageResult => {\n const emitter = createEmitter(ctx.dryRun);\n const notes: string[] = [];\n const serverJson = buildServerJson(connector, notes);\n const path = resolve(ctx.outDir, \"server.json\");\n emitter.emit(path, json(serverJson));\n return {\n files: emitter.files,\n pluginDir: ctx.outDir,\n ...(notes.length > 0 ? { notes } : {}),\n };\n};\n","/**\n * core/package-formats/mcpb — emit an MCPB (.mcpb, formerly DXT) bundle manifest.\n *\n * MCPB is the official cross-client one-click LOCAL-install bundle (Claude\n * Desktop + any MCPB host). A real .mcpb is a SELF-CONTAINED zip (manifest.json\n * + the server + vendored node_modules), which agent-connector cannot assemble\n * at emit time — we do not have the developer's built server tree. So, per the\n * conformance analysis, we emit a CONFORMANT manifest.json describing a\n * self-contained node bundle (NOT an out-of-spec `npx` command-reference, which\n * would assume network + node on PATH at launch and break offline/signing) plus\n * a packaging RECIPE, and leave the `mcpb pack`/`mcpb sign` to the developer —\n * mirroring how server.json defers the publish-time ownership proof.\n *\n * Secrets (the bearer token / sensitive env) are routed through `user_config`\n * (sensitive:true) and referenced as `${user_config.<key>}` in mcp_config.env,\n * so credentials are collected by the host keychain, never inlined.\n */\n\nimport { resolve } from \"node:path\";\n\nimport type { ResolvedConnector, ServerDef } from \"../types.js\";\nimport {\n MCPB_MANIFEST_VERSION,\n isConcreteSemver,\n isPlaceholderVersion,\n} from \"../mcp-standard.js\";\nimport type { EmitContext, FormatEmitter, PackageResult } from \"./shared.js\";\nimport { createEmitter, json } from \"./shared.js\";\n\n/** \"ACME_DB_TOKEN\" → \"Acme Db Token\" for a user_config field title. */\nfunction titleize(s: string): string {\n return s\n .toLowerCase()\n .split(/[_-]+/)\n .filter(Boolean)\n .map((w) => w[0]!.toUpperCase() + w.slice(1))\n .join(\" \");\n}\n\n/** The names of env vars that hold secrets (the bearer token). */\nfunction secretEnvNames(server: ServerDef): Set<string> {\n const names = new Set<string>();\n if (server.auth?.type === \"bearerEnv\" && server.auth.bearerEnvVar) {\n names.add(server.auth.bearerEnvVar);\n }\n return names;\n}\n\nfunction recipeReadme(connector: ResolvedConnector): string {\n return `# ${connector.displayName} — MCPB bundle\n\n\\`agent-connector package --format mcpb\\` emitted the conformant **manifest.json**\n(manifest_version ${MCPB_MANIFEST_VERSION}) for this connector. It does NOT build\nthe \\`.mcpb\\` zip — that step vendors your server and is yours to run, so the\nbundle stays self-contained and signable.\n\n## Finish the bundle\n\n1. Put your built, self-contained MCP server at \\`server/index.js\\`\n (the manifest's \\`entry_point\\` / \\`mcp_config\\`).\n2. Vendor production dependencies into the bundle:\n\n \\`\\`\\`bash\n cd server && npm install --omit=dev && cd ..\n \\`\\`\\`\n\n3. Pack (and optionally sign) with the official MCPB CLI:\n\n \\`\\`\\`bash\n npx @anthropic-ai/mcpb pack . # → ${connector.id}.mcpb\n npx @anthropic-ai/mcpb sign ${connector.id}.mcpb\n \\`\\`\\`\n\nThe resulting \\`.mcpb\\` installs one-click into Claude Desktop and any MCPB host.\nSecrets are declared under \\`user_config\\` and collected by the host keychain at\ninstall time — never inline them in the manifest.\n`;\n}\n\n/** Emit a conformant MCPB manifest.json + packaging recipe for `connector`. */\nexport const emitMcpbBundle: FormatEmitter = (\n connector: ResolvedConnector,\n ctx: EmitContext,\n): PackageResult => {\n const publish = connector.publish ?? {};\n if (!publish.author?.name) {\n throw new Error(\n \"package --format mcpb needs publish.author.name — the MCPB manifest requires an author.\",\n );\n }\n if (!isConcreteSemver(connector.version)) {\n throw new Error(\n `mcpb manifest version must be a concrete SemVer; got \"${connector.version}\".`,\n );\n }\n\n const server = connector.server;\n if (!server) {\n throw new Error(\"package --format mcpb needs a server (an MCPB bundle packages an MCP server).\");\n }\n if (server.transport !== \"stdio\") {\n throw new Error(\n `package --format mcpb supports stdio servers; \"${server.transport}\" is a remote server — ` +\n \"publish it via the registry (--format mcp-server-json) instead.\",\n );\n }\n\n const notes: string[] = [];\n if (isPlaceholderVersion(connector.version)) {\n notes.push('version is the unset placeholder \"0.0.0\" — set a real version before packing.');\n }\n\n // Route secret env vars through user_config; pass the rest through verbatim.\n const secrets = secretEnvNames(server);\n const env: Record<string, string> = {};\n const userConfig: Record<string, Record<string, unknown>> = {};\n for (const [k, v] of Object.entries(server.env ?? {})) {\n if (secrets.has(k)) {\n const key = k.toLowerCase();\n userConfig[key] = {\n type: \"string\",\n title: titleize(k),\n description: `Value for ${k}`,\n sensitive: true,\n required: true,\n };\n env[k] = `\\${user_config.${key}}`;\n } else {\n env[k] = v;\n }\n }\n // A bearer-token env not already present in server.env still needs a field.\n for (const name of secrets) {\n if (!(name in env)) {\n const key = name.toLowerCase();\n userConfig[key] = {\n type: \"string\",\n title: titleize(name),\n description: `Value for ${name}`,\n sensitive: true,\n required: true,\n };\n env[name] = `\\${user_config.${key}}`;\n }\n }\n\n const author: Record<string, string> = { name: publish.author.name };\n if (publish.author.email) author.email = publish.author.email;\n if (publish.author.url) author.url = publish.author.url;\n\n const mcpConfig: Record<string, unknown> = {\n command: \"node\",\n args: [\"${__dirname}/server/index.js\"],\n };\n if (Object.keys(env).length > 0) mcpConfig.env = env;\n\n const manifest: Record<string, unknown> = {\n manifest_version: MCPB_MANIFEST_VERSION,\n name: connector.id,\n version: connector.version,\n description: connector.displayName,\n author,\n server: {\n type: \"node\",\n entry_point: \"server/index.js\",\n mcp_config: mcpConfig,\n },\n };\n if (Object.keys(userConfig).length > 0) manifest.user_config = userConfig;\n\n // If the dev's real command is not node-ish, the node template needs adjusting.\n if (server.command && !/\\b(node|npx)\\b/.test(server.command)) {\n notes.push(\n `your server command is \"${server.command}\" — the emitted manifest assumes a node ` +\n \"server (server.type:node); adjust server.type/entry_point for your runtime (python|binary).\",\n );\n }\n notes.push(\n \"emitted manifest.json + README recipe; this format does NOT build the .mcpb zip. \" +\n \"Place your self-contained server at server/index.js, vendor deps, then run `mcpb pack` (see README).\",\n );\n\n const emitter = createEmitter(ctx.dryRun);\n emitter.emit(resolve(ctx.outDir, \"manifest.json\"), json(manifest));\n emitter.emit(resolve(ctx.outDir, \"README.md\"), recipeReadme(connector));\n return { files: emitter.files, pluginDir: ctx.outDir, notes };\n};\n"],"mappings":"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","names":["existsSync","join","resolve","join","buildManifest","buildMarketplace","join","join","SPECS","buildManifest","join","join","PLATFORM","buildManifest","join","join","PLATFORM","buildManifest","join","join","join","join","entry","buildManifest","join","resolve","resolve","resolve","resolve","resolve","join"]}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
installInstructions,
|
|
4
|
-
packageConnector
|
|
5
|
-
|
|
4
|
+
packageConnector,
|
|
5
|
+
readAgentPluginManifest
|
|
6
|
+
} from "./chunk-U2XJWG7N.js";
|
|
6
7
|
import {
|
|
7
8
|
MARKETPLACE_NAME,
|
|
8
9
|
agyPluginInstalled,
|
|
@@ -1011,6 +1012,7 @@ var claudeDriver = {
|
|
|
1011
1012
|
import { existsSync as existsSync4, readdirSync as readdirSync3, readFileSync as readFileSync2, rmSync as rmSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
1012
1013
|
import { dirname as dirname3, join as join4 } from "path";
|
|
1013
1014
|
var PLATFORM2 = "codex";
|
|
1015
|
+
var FORMAT = "agent-plugin";
|
|
1014
1016
|
function codexBinary() {
|
|
1015
1017
|
return findOnPath("codex");
|
|
1016
1018
|
}
|
|
@@ -1029,12 +1031,17 @@ function failDetail2(step, r) {
|
|
|
1029
1031
|
const line = firstLine(r.stderr) || firstLine(r.stdout);
|
|
1030
1032
|
return `${step} exited ${r.code}${line ? `: ${line}` : ""}`;
|
|
1031
1033
|
}
|
|
1034
|
+
function stagedManifest(stagingRoot, name) {
|
|
1035
|
+
try {
|
|
1036
|
+
return readAgentPluginManifest(readFileSync2(join4(stagingRoot, name, "plugin.json"), "utf8"));
|
|
1037
|
+
} catch {
|
|
1038
|
+
return null;
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1032
1041
|
function stagedCodexPlugins(stagingRoot) {
|
|
1033
1042
|
if (!existsSync4(stagingRoot)) return [];
|
|
1034
1043
|
try {
|
|
1035
|
-
return readdirSync3(stagingRoot).filter(
|
|
1036
|
-
(name) => existsSync4(join4(stagingRoot, name, ".codex-plugin", "plugin.json"))
|
|
1037
|
-
).sort();
|
|
1044
|
+
return readdirSync3(stagingRoot).filter((name) => stagedManifest(stagingRoot, name) !== null).sort();
|
|
1038
1045
|
} catch {
|
|
1039
1046
|
return [];
|
|
1040
1047
|
}
|
|
@@ -1045,14 +1052,8 @@ function codexCatalogPath(stagingRoot) {
|
|
|
1045
1052
|
function regenerateCodexCatalog(stagingRoot, changes) {
|
|
1046
1053
|
const catalogPath = codexCatalogPath(stagingRoot);
|
|
1047
1054
|
const plugins = stagedCodexPlugins(stagingRoot).map((name) => {
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
const manifest = JSON.parse(
|
|
1051
|
-
readFileSync2(join4(stagingRoot, name, ".codex-plugin", "plugin.json"), "utf8")
|
|
1052
|
-
);
|
|
1053
|
-
if (typeof manifest.description === "string") description = manifest.description;
|
|
1054
|
-
} catch {
|
|
1055
|
-
}
|
|
1055
|
+
const manifest = stagedManifest(stagingRoot, name);
|
|
1056
|
+
const description = typeof manifest?.description === "string" ? manifest.description : `${name} \u2014 connector emitted by agent-connector`;
|
|
1056
1057
|
return { name, source: `./${name}`, description };
|
|
1057
1058
|
});
|
|
1058
1059
|
const catalog = { name: MARKETPLACE_NAME, owner: { name: MARKETPLACE_NAME }, plugins };
|
|
@@ -1077,12 +1078,16 @@ function stageCodexBundle(connector, changes) {
|
|
|
1077
1078
|
const stagingRoot = codexStagingRoot();
|
|
1078
1079
|
const pluginDir = join4(stagingRoot, connector.id);
|
|
1079
1080
|
const existed = existsSync4(pluginDir);
|
|
1080
|
-
const result = packageConnector(connector, {
|
|
1081
|
+
const result = packageConnector(connector, {
|
|
1082
|
+
outDir: stagingRoot,
|
|
1083
|
+
format: FORMAT,
|
|
1084
|
+
hostHint: PLATFORM2
|
|
1085
|
+
});
|
|
1081
1086
|
changes.push({
|
|
1082
1087
|
platform: PLATFORM2,
|
|
1083
1088
|
action: existed ? "update" : "create",
|
|
1084
1089
|
path: pluginDir,
|
|
1085
|
-
detail: `staged marketplace bundle (${result.files.length} files,
|
|
1090
|
+
detail: `staged marketplace bundle (${result.files.length} files, ${FORMAT})`
|
|
1086
1091
|
});
|
|
1087
1092
|
regenerateCodexCatalog(stagingRoot, changes);
|
|
1088
1093
|
return { pluginDir, contentHash: hashDirectory(pluginDir) };
|
|
@@ -1220,7 +1225,7 @@ async function driveMarketplaceRemove(stagingRoot) {
|
|
|
1220
1225
|
}
|
|
1221
1226
|
var codexDriver = {
|
|
1222
1227
|
platform: PLATFORM2,
|
|
1223
|
-
format:
|
|
1228
|
+
format: FORMAT,
|
|
1224
1229
|
binary: codexBinary,
|
|
1225
1230
|
stagingRoot: codexStagingRoot,
|
|
1226
1231
|
pluginDir(id) {
|
|
@@ -1312,6 +1317,7 @@ var codexDriver = {
|
|
|
1312
1317
|
import { existsSync as existsSync5, readdirSync as readdirSync4, readFileSync as readFileSync3, rmSync as rmSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
1313
1318
|
import { dirname as dirname4, join as join5 } from "path";
|
|
1314
1319
|
var PLATFORM3 = "copilot-cli";
|
|
1320
|
+
var FORMAT2 = "agent-plugin";
|
|
1315
1321
|
function copilotBinary() {
|
|
1316
1322
|
return findOnPath("copilot");
|
|
1317
1323
|
}
|
|
@@ -1330,12 +1336,17 @@ function failDetail3(step, r) {
|
|
|
1330
1336
|
const line = firstLine(r.stderr) || firstLine(r.stdout);
|
|
1331
1337
|
return `${step} exited ${r.code}${line ? `: ${line}` : ""}`;
|
|
1332
1338
|
}
|
|
1339
|
+
function stagedManifest2(stagingRoot, name) {
|
|
1340
|
+
try {
|
|
1341
|
+
return readAgentPluginManifest(readFileSync3(join5(stagingRoot, name, "plugin.json"), "utf8"));
|
|
1342
|
+
} catch {
|
|
1343
|
+
return null;
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1333
1346
|
function stagedCopilotPlugins(stagingRoot) {
|
|
1334
1347
|
if (!existsSync5(stagingRoot)) return [];
|
|
1335
1348
|
try {
|
|
1336
|
-
return readdirSync4(stagingRoot).filter(
|
|
1337
|
-
(name) => existsSync5(join5(stagingRoot, name, ".claude-plugin", "plugin.json"))
|
|
1338
|
-
).sort();
|
|
1349
|
+
return readdirSync4(stagingRoot).filter((name) => stagedManifest2(stagingRoot, name) !== null).sort();
|
|
1339
1350
|
} catch {
|
|
1340
1351
|
return [];
|
|
1341
1352
|
}
|
|
@@ -1346,14 +1357,8 @@ function copilotCatalogPath(stagingRoot) {
|
|
|
1346
1357
|
function regenerateCopilotCatalog(stagingRoot, changes) {
|
|
1347
1358
|
const catalogPath = copilotCatalogPath(stagingRoot);
|
|
1348
1359
|
const plugins = stagedCopilotPlugins(stagingRoot).map((name) => {
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
const manifest = JSON.parse(
|
|
1352
|
-
readFileSync3(join5(stagingRoot, name, ".claude-plugin", "plugin.json"), "utf8")
|
|
1353
|
-
);
|
|
1354
|
-
if (typeof manifest.description === "string") description = manifest.description;
|
|
1355
|
-
} catch {
|
|
1356
|
-
}
|
|
1360
|
+
const manifest = stagedManifest2(stagingRoot, name);
|
|
1361
|
+
const description = typeof manifest?.description === "string" ? manifest.description : `${name} \u2014 connector emitted by agent-connector`;
|
|
1357
1362
|
return { name, source: `./${name}`, description };
|
|
1358
1363
|
});
|
|
1359
1364
|
const catalog = { name: MARKETPLACE_NAME, owner: { name: MARKETPLACE_NAME }, plugins };
|
|
@@ -1378,12 +1383,16 @@ function stageCopilotBundle(connector, changes) {
|
|
|
1378
1383
|
const stagingRoot = copilotStagingRoot();
|
|
1379
1384
|
const pluginDir = join5(stagingRoot, connector.id);
|
|
1380
1385
|
const existed = existsSync5(pluginDir);
|
|
1381
|
-
const result = packageConnector(connector, {
|
|
1386
|
+
const result = packageConnector(connector, {
|
|
1387
|
+
outDir: stagingRoot,
|
|
1388
|
+
format: FORMAT2,
|
|
1389
|
+
hostHint: PLATFORM3
|
|
1390
|
+
});
|
|
1382
1391
|
changes.push({
|
|
1383
1392
|
platform: PLATFORM3,
|
|
1384
1393
|
action: existed ? "update" : "create",
|
|
1385
1394
|
path: pluginDir,
|
|
1386
|
-
detail: `staged marketplace bundle (${result.files.length} files,
|
|
1395
|
+
detail: `staged marketplace bundle (${result.files.length} files, ${FORMAT2})`
|
|
1387
1396
|
});
|
|
1388
1397
|
regenerateCopilotCatalog(stagingRoot, changes);
|
|
1389
1398
|
return { pluginDir, contentHash: hashDirectory(pluginDir) };
|
|
@@ -1521,7 +1530,7 @@ async function driveMarketplaceRemove2(stagingRoot) {
|
|
|
1521
1530
|
}
|
|
1522
1531
|
var copilotDriver = {
|
|
1523
1532
|
platform: PLATFORM3,
|
|
1524
|
-
format:
|
|
1533
|
+
format: FORMAT2,
|
|
1525
1534
|
binary: copilotBinary,
|
|
1526
1535
|
stagingRoot: copilotStagingRoot,
|
|
1527
1536
|
pluginDir(id) {
|
|
@@ -2813,20 +2822,28 @@ function parseUninstallMethod(value) {
|
|
|
2813
2822
|
}
|
|
2814
2823
|
var MARKETPLACE_FORMAT_BY_PLATFORM = {
|
|
2815
2824
|
"claude-code": "claude-plugin",
|
|
2816
|
-
|
|
2817
|
-
|
|
2825
|
+
// Agent Plugins 1.0.0 (agent-plugins.org) — the ONE bundle every
|
|
2826
|
+
// spec-speaking host installs. codex + copilot-cli are driven (catalog
|
|
2827
|
+
// drivers stage this bundle); the rest get the bundle + manual install hint.
|
|
2828
|
+
codex: "agent-plugin",
|
|
2829
|
+
"copilot-cli": "agent-plugin",
|
|
2830
|
+
"vscode-copilot": "agent-plugin",
|
|
2831
|
+
"jetbrains-copilot": "agent-plugin",
|
|
2832
|
+
kiro: "agent-plugin",
|
|
2833
|
+
hermes: "agent-plugin",
|
|
2818
2834
|
droid: "factory-plugin",
|
|
2819
2835
|
"gemini-cli": "gemini-extension",
|
|
2820
2836
|
"qwen-code": "qwen-extension",
|
|
2821
2837
|
antigravity: "agy-plugin",
|
|
2822
2838
|
"antigravity-cli": "agy-plugin",
|
|
2839
|
+
// Cursor + OpenClaw read Agent Plugins bundles too, but their own docs say the
|
|
2840
|
+
// client-specific format is the one that carries hooks/commands — keep it.
|
|
2823
2841
|
cursor: "cursor-plugin",
|
|
2824
2842
|
kimi: "kimi-plugin",
|
|
2825
2843
|
opencode: "npm-plugin",
|
|
2826
2844
|
kilo: "npm-plugin",
|
|
2827
2845
|
"kilo-cli": "npm-plugin",
|
|
2828
2846
|
pi: "npm-plugin",
|
|
2829
|
-
"vscode-copilot": "claude-plugin",
|
|
2830
2847
|
openclaw: "claude-plugin",
|
|
2831
2848
|
omp: "claude-plugin"
|
|
2832
2849
|
};
|
|
@@ -3396,4 +3413,4 @@ export {
|
|
|
3396
3413
|
upgradeViaMarketplace,
|
|
3397
3414
|
marketplaceDoctorChecks
|
|
3398
3415
|
};
|
|
3399
|
-
//# sourceMappingURL=chunk-
|
|
3416
|
+
//# sourceMappingURL=chunk-WZMSSIDN.js.map
|