@ken-jo/agent-connector 0.2.0 → 0.3.1

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.
Files changed (84) hide show
  1. package/README.md +13 -2
  2. package/dist/{chunk-AKJGNTU3.js → chunk-3RBLIHPZ.js} +21 -21
  3. package/dist/chunk-3RBLIHPZ.js.map +1 -0
  4. package/dist/chunk-G5CQHVQG.js +511 -0
  5. package/dist/chunk-G5CQHVQG.js.map +1 -0
  6. package/dist/chunk-KMAKDD3Z.js +3010 -0
  7. package/dist/chunk-KMAKDD3Z.js.map +1 -0
  8. package/dist/{chunk-KHO5WNTP.js → chunk-KVAAFYRR.js} +18 -2
  9. package/dist/chunk-KVAAFYRR.js.map +1 -0
  10. package/dist/{chunk-O2SBA5KR.js → chunk-NJU275US.js} +9 -9
  11. package/dist/{chunk-WCETQWWK.js → chunk-OP4KBXUO.js} +1 -17
  12. package/dist/chunk-OP4KBXUO.js.map +1 -0
  13. package/dist/{package-O63K4S7T.js → chunk-WNREHWKL.js} +20 -114
  14. package/dist/chunk-WNREHWKL.js.map +1 -0
  15. package/dist/{chunk-4ML7SZ7R.js → chunk-ZAM4M7LI.js} +7 -7
  16. package/dist/cli/sdk.js +1 -1
  17. package/dist/cli.js +1 -1
  18. package/dist/{detect-JK7T46N6.js → detect-U3E7NVNW.js} +3 -3
  19. package/dist/{doctor-62BHIXOR.js → doctor-DZTWED4O.js} +35 -5
  20. package/dist/doctor-DZTWED4O.js.map +1 -0
  21. package/dist/{hook-AC7APC66.js → hook-EVY7LOUQ.js} +6 -6
  22. package/dist/{install-DMW2C7SV.js → install-OWAS5UIE.js} +31 -7
  23. package/dist/install-OWAS5UIE.js.map +1 -0
  24. package/dist/kilo-PKAJCWPX.js +852 -0
  25. package/dist/kilo-PKAJCWPX.js.map +1 -0
  26. package/dist/{kilo-cli-2RNODHWY.js → kilo-cli-QWUVXG2O.js} +157 -6
  27. package/dist/kilo-cli-QWUVXG2O.js.map +1 -0
  28. package/dist/{kimi-Q5RG7CYT.js → kimi-EVD7YKXS.js} +79 -4
  29. package/dist/kimi-EVD7YKXS.js.map +1 -0
  30. package/dist/{kiro-EKTRW424.js → kiro-UQRY6EIO.js} +68 -3
  31. package/dist/kiro-UQRY6EIO.js.map +1 -0
  32. package/dist/{leaderboard-R5HRJHNU.js → leaderboard-CSWHI4UY.js} +2 -2
  33. package/dist/package-WFOS4QVU.js +130 -0
  34. package/dist/package-WFOS4QVU.js.map +1 -0
  35. package/dist/{pi-SJPIL4VE.js → pi-WMTUX6ES.js} +102 -23
  36. package/dist/pi-WMTUX6ES.js.map +1 -0
  37. package/dist/{qwen-code-IFCM6BJY.js → qwen-code-MRRIUQ3P.js} +78 -5
  38. package/dist/qwen-code-MRRIUQ3P.js.map +1 -0
  39. package/dist/runtime/index.js +4 -4
  40. package/dist/{serve-LFOUSZAD.js → serve-3C2VFPAY.js} +6 -6
  41. package/dist/{status-M7JLZVLC.js → status-MKQYX5MW.js} +16 -7
  42. package/dist/status-MKQYX5MW.js.map +1 -0
  43. package/dist/{telemetry-3NVEXPYX.js → telemetry-3DN6XGYB.js} +2 -2
  44. package/dist/uninstall-WG6PFWF3.js +162 -0
  45. package/dist/uninstall-WG6PFWF3.js.map +1 -0
  46. package/dist/{upgrade-76BQZBMA.js → upgrade-32NC2RKI.js} +26 -8
  47. package/dist/upgrade-32NC2RKI.js.map +1 -0
  48. package/dist/{usage-G3GSCX23.js → usage-CJOM2WQM.js} +2 -2
  49. package/dist/{usage-event-QUTMNBS5.js → usage-event-472X3DOY.js} +5 -5
  50. package/dist/{warp-LLOSXR7A.js → warp-X6MB67NT.js} +81 -3
  51. package/dist/warp-X6MB67NT.js.map +1 -0
  52. package/dist/{zed-HYOITK7F.js → zed-NTCYW4V2.js} +68 -3
  53. package/dist/zed-NTCYW4V2.js.map +1 -0
  54. package/package.json +1 -1
  55. package/dist/chunk-AKJGNTU3.js.map +0 -1
  56. package/dist/chunk-KHO5WNTP.js.map +0 -1
  57. package/dist/chunk-WCETQWWK.js.map +0 -1
  58. package/dist/chunk-Z2BVYKZL.js +0 -369
  59. package/dist/chunk-Z2BVYKZL.js.map +0 -1
  60. package/dist/doctor-62BHIXOR.js.map +0 -1
  61. package/dist/install-DMW2C7SV.js.map +0 -1
  62. package/dist/kilo-ISR5FBBJ.js +0 -408
  63. package/dist/kilo-ISR5FBBJ.js.map +0 -1
  64. package/dist/kilo-cli-2RNODHWY.js.map +0 -1
  65. package/dist/kimi-Q5RG7CYT.js.map +0 -1
  66. package/dist/kiro-EKTRW424.js.map +0 -1
  67. package/dist/package-O63K4S7T.js.map +0 -1
  68. package/dist/pi-SJPIL4VE.js.map +0 -1
  69. package/dist/qwen-code-IFCM6BJY.js.map +0 -1
  70. package/dist/status-M7JLZVLC.js.map +0 -1
  71. package/dist/uninstall-H6FGMIHN.js +0 -73
  72. package/dist/uninstall-H6FGMIHN.js.map +0 -1
  73. package/dist/upgrade-76BQZBMA.js.map +0 -1
  74. package/dist/warp-LLOSXR7A.js.map +0 -1
  75. package/dist/zed-HYOITK7F.js.map +0 -1
  76. /package/dist/{chunk-O2SBA5KR.js.map → chunk-NJU275US.js.map} +0 -0
  77. /package/dist/{chunk-4ML7SZ7R.js.map → chunk-ZAM4M7LI.js.map} +0 -0
  78. /package/dist/{detect-JK7T46N6.js.map → detect-U3E7NVNW.js.map} +0 -0
  79. /package/dist/{hook-AC7APC66.js.map → hook-EVY7LOUQ.js.map} +0 -0
  80. /package/dist/{leaderboard-R5HRJHNU.js.map → leaderboard-CSWHI4UY.js.map} +0 -0
  81. /package/dist/{serve-LFOUSZAD.js.map → serve-3C2VFPAY.js.map} +0 -0
  82. /package/dist/{telemetry-3NVEXPYX.js.map → telemetry-3DN6XGYB.js.map} +0 -0
  83. /package/dist/{usage-G3GSCX23.js.map → usage-CJOM2WQM.js.map} +0 -0
  84. /package/dist/{usage-event-QUTMNBS5.js.map → usage-event-472X3DOY.js.map} +0 -0
package/README.md CHANGED
@@ -14,7 +14,7 @@
14
14
  ![install verified](https://img.shields.io/badge/install%20verified-29%2F29-22c55e)
15
15
  ![headless runtime](https://img.shields.io/badge/headless%20runtime-10%20CLIs%20activated-22c55e)
16
16
  ![marketplace](https://img.shields.io/badge/package-9%20marketplace%20formats-2563eb)
17
- ![tests](https://img.shields.io/badge/tests-1263%20passing-22c55e)
17
+ ![tests](https://img.shields.io/badge/tests-1483%20passing-22c55e)
18
18
 
19
19
  ## Who this is for
20
20
 
@@ -102,7 +102,7 @@ installed into an isolated environment for every adapter and inspected on disk:
102
102
  - **Clean uninstall + `--purge`.** Every installed surface reverses; `--purge`
103
103
  deregisters the connector record and tears down the home binary when no
104
104
  connectors remain (29 / 29).
105
- - **1263 tests passing** · `tsc` clean · build green.
105
+ - **1483 tests passing** · `tsc` clean · build green.
106
106
 
107
107
  The 0.2.0 additions — the `memory` surface, the `nativeHooks` passthrough, and
108
108
  `configPatch` — went through the same bar: dogfooded against real connector
@@ -260,6 +260,17 @@ Same one definition, your choice of distribution:
260
260
 
261
261
  - **Direct install** (above) — `install` writes each host's native MCP + plugin/
262
262
  extension config in place; no per-platform marketplace submission or review.
263
+ - **Marketplace install** — `install --method marketplace` drives the host's own
264
+ plugin flow end-to-end for **10 hosts**: Claude Code, Codex, OpenCode, Kilo
265
+ (CLI + ext), Antigravity (CLI + IDE) — live-verified on Linux, Windows, and
266
+ macOS — plus Droid and Qwen Code (driver shipped, pending a live host) and
267
+ Gemini CLI (legacy — sunsetting toward Antigravity; driver kept for existing
268
+ installs). It stages the bundle, registers a local marketplace where the host
269
+ has one, then runs the host's plugin-install verb (or, for npm-plugin hosts,
270
+ writes a local `file://` entry); headless and idempotent. `uninstall --method
271
+ auto` reverses whichever method is installed, a guard refuses installing the
272
+ same connector by BOTH methods, and `doctor` checks registration drift. Other
273
+ marketplace-format hosts print the exact manual commands.
263
274
  - **Marketplace package** — `agent-connector package` turns the connector into a
264
275
  marketplace/extension bundle (manifest + bundled commands, agents, skills,
265
276
  hooks, MCP) for **9 host formats** (plus 2 official MCP standard artifacts —
@@ -73,35 +73,35 @@ function renderInstallResult(result, verb) {
73
73
  return lines.join("\n");
74
74
  }
75
75
  var COMMANDS = {
76
- detect: () => import("./detect-JK7T46N6.js"),
77
- install: () => import("./install-DMW2C7SV.js"),
78
- uninstall: () => import("./uninstall-H6FGMIHN.js"),
76
+ detect: () => import("./detect-U3E7NVNW.js"),
77
+ install: () => import("./install-OWAS5UIE.js"),
78
+ uninstall: () => import("./uninstall-WG6PFWF3.js"),
79
79
  // `upgrade` is the single "bring everything current" verb (re-render host
80
80
  // config + refresh the home pointer + managed channel guidance). `sync` and
81
81
  // `update` are kept as back-compat aliases that route to the same module so
82
82
  // existing scripts/docs keep working without a second concept to learn.
83
- upgrade: () => import("./upgrade-76BQZBMA.js"),
84
- sync: () => import("./upgrade-76BQZBMA.js"),
85
- update: () => import("./upgrade-76BQZBMA.js"),
86
- package: () => import("./package-O63K4S7T.js"),
87
- doctor: () => import("./doctor-62BHIXOR.js"),
88
- status: () => import("./status-M7JLZVLC.js"),
89
- telemetry: () => import("./telemetry-3NVEXPYX.js"),
90
- usage: () => import("./usage-G3GSCX23.js"),
91
- leaderboard: () => import("./leaderboard-R5HRJHNU.js"),
92
- hook: () => import("./hook-AC7APC66.js"),
93
- serve: () => import("./serve-LFOUSZAD.js"),
83
+ upgrade: () => import("./upgrade-32NC2RKI.js"),
84
+ sync: () => import("./upgrade-32NC2RKI.js"),
85
+ update: () => import("./upgrade-32NC2RKI.js"),
86
+ package: () => import("./package-WFOS4QVU.js"),
87
+ doctor: () => import("./doctor-DZTWED4O.js"),
88
+ status: () => import("./status-MKQYX5MW.js"),
89
+ telemetry: () => import("./telemetry-3DN6XGYB.js"),
90
+ usage: () => import("./usage-CJOM2WQM.js"),
91
+ leaderboard: () => import("./leaderboard-CSWHI4UY.js"),
92
+ hook: () => import("./hook-EVY7LOUQ.js"),
93
+ serve: () => import("./serve-3C2VFPAY.js"),
94
94
  // Hidden (omitted from USAGE): the opt-in host-native turn-usage entrypoint an
95
95
  // AfterModel / PostInvocation hook points at. Always exits 0; records a
96
96
  // distinct `model_turn` row. See cli/commands/usage-event.ts.
97
- "usage-event": () => import("./usage-event-QUTMNBS5.js")
97
+ "usage-event": () => import("./usage-event-472X3DOY.js")
98
98
  };
99
99
  var DEFAULT_PROGRAM_NAME = "agent-connector";
100
100
  var COMMAND_USAGE = {
101
101
  detect: "detect [--json] [--project <dir>]",
102
- install: "install [--connector <path>] [--scope user|project] [--targets a,b] [--project <dir>] [--dry-run] [--force]",
103
- uninstall: "uninstall [--connector <path>] [--connector-id <id>] [--scope user|project] [--targets a,b] [--project <dir>] [--dry-run] [--purge]",
104
- upgrade: "upgrade [--channel stable|latest] [--connector <path>] [--scope user|project] [--targets a,b] [--project <dir>] [--dry-run]",
102
+ install: "install [--method direct|marketplace] [--connector <path>] [--scope user|project] [--targets a,b] [--project <dir>] [--dry-run] [--force]",
103
+ uninstall: "uninstall [--method auto|direct|marketplace] [--connector <path>] [--connector-id <id>] [--scope user|project] [--targets a,b] [--project <dir>] [--dry-run] [--purge]",
104
+ upgrade: "upgrade [--method direct|marketplace] [--channel stable|latest] [--connector <path>] [--scope user|project] [--targets a,b] [--project <dir>] [--dry-run]",
105
105
  sync: "sync \u2014 alias of upgrade (see `upgrade --help`)",
106
106
  update: "update \u2014 alias of upgrade (see `upgrade --help`)",
107
107
  package: "package [--connector <path>] [--format <fmt>|all] [--out <dir>] [--project <dir>] [--dry-run]",
@@ -120,8 +120,8 @@ usage: ${programName} <command> [flags]
120
120
 
121
121
  commands:
122
122
  detect List the AI-agent platforms installed on this machine.
123
- install Deploy a connector across its target platforms.
124
- uninstall Remove a connector's MCP + hook registrations.
123
+ install Deploy a connector across its target platforms (--method direct writes host config; --method marketplace drives the host's plugin install).
124
+ uninstall Remove a connector's registrations (--method auto reverses whichever method is actually installed).
125
125
  upgrade Bring everything current: re-render host config + heal the home pointer + managed update guidance (alias: update, sync).
126
126
  package Emit a marketplace/extension bundle (9 host formats, or the standard artifacts mcp-server-json | mcpb).
127
127
  doctor Health-check every detected platform; non-zero exit on any failure.
@@ -188,4 +188,4 @@ export {
188
188
  renderInstallResult,
189
189
  main
190
190
  };
191
- //# sourceMappingURL=chunk-AKJGNTU3.js.map
191
+ //# sourceMappingURL=chunk-3RBLIHPZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/app.ts"],"sourcesContent":["/**\n * cli/app — shared CLI helpers + command dispatch (NO side effects).\n *\n * Command modules import the shared helpers (print, fail, parse-flags,\n * renderInstallResult) from here, and main() dispatches the first positional to a\n * command module.\n * This module never auto-runs — `cli/index.ts` is the thin bin entry that calls\n * `main()`. Keeping the auto-run out of here is what prevents a dispatch recursion\n * (a command module importing a helper must not re-trigger the program) and makes\n * it robust to bundler entry-splitting (the old import.meta.url entry-guard broke\n * once tsup hoisted this code into a shared chunk).\n */\n\nimport { createRequire } from \"node:module\";\n\nimport type {\n ChangeRecord,\n InstallResult,\n InstallScope,\n PlatformId,\n} from \"../core/types.js\";\n\n// ─────────────────────────────────────────────────────────────────────────\n// Shared helpers (imported by the command modules)\n// ─────────────────────────────────────────────────────────────────────────\n\n/** Print a line to stdout (machine-readable payloads must stay on stdout). */\nexport function print(line: string): void {\n process.stdout.write(`${line}\\n`);\n}\n\n/**\n * The brand active for THIS invocation. main() sets it from\n * {@link MainOptions.programName} before dispatch, so error messages printed by\n * command modules via {@link fail} read as the embedding tool (e.g. `acme-db:`)\n * instead of always `agent-connector:`.\n */\nlet activeProgramName = \"agent-connector\";\n\n/** Print an error to stderr (branded) and return a non-zero exit code (default 2). */\nexport function fail(message: string, code = 2): number {\n process.stderr.write(`${activeProgramName}: ${message}\\n`);\n return code;\n}\n\n/**\n * Resolve agent-connector's own package version at runtime. Works from both the\n * bundled dist layout (dist/*.js → ../package.json) and the src layout under\n * tsx/vitest (src/cli/ → ../../package.json); the name check guards against\n * accidentally reading some other package.json on the walk.\n */\nexport function resolveOwnVersion(): 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 (pkg.name === \"@ken-jo/agent-connector\" && typeof pkg.version === \"string\") {\n return pkg.version;\n }\n } catch {\n /* keep walking */\n }\n }\n return \"0.0.0\";\n}\n\n/** Parse a --scope value the CLI accepts (user|project) into an InstallScope. */\nexport function parseScope(value: string | undefined): InstallScope | null {\n if (value === \"user\" || value === \"project\") return value;\n return null;\n}\n\n/**\n * Parse a comma-separated --targets value into PlatformId[]. Returns undefined\n * when the flag is absent/empty so callers can fall back to connector/detection.\n */\nexport function parseTargets(value: string | undefined): PlatformId[] | undefined {\n if (value == null || value.trim() === \"\") return undefined;\n const ids = value\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => s !== \"\") as PlatformId[];\n return ids.length > 0 ? ids : undefined;\n}\n\nconst ACTION_GLYPH: Record<ChangeRecord[\"action\"], string> = {\n create: \"+\",\n update: \"~\",\n remove: \"-\",\n skip: \"=\",\n warn: \"!\",\n};\n\n/**\n * Render an InstallResult as a readable diff: one line per ChangeRecord (glyph,\n * platform, detail, path) followed by any warnings and a summary tally. Used by\n * install / upgrade / uninstall.\n */\nexport function renderInstallResult(\n result: InstallResult,\n verb: \"install\" | \"upgrade\" | \"uninstall\",\n): string {\n const lines: string[] = [];\n const mode = result.dryRun ? \" (dry-run — nothing written)\" : \"\";\n lines.push(`${verb} \"${result.connectorId}\"${mode}`);\n\n if (result.changes.length === 0) {\n lines.push(\" (no changes)\");\n } else {\n for (const c of result.changes) {\n const glyph = ACTION_GLYPH[c.action];\n const where = c.path ? ` ${c.path}` : \"\";\n lines.push(` ${glyph} [${c.platform}] ${c.action}: ${c.detail}${where}`);\n }\n }\n\n if (result.warnings.length > 0) {\n lines.push(\"\");\n lines.push(\"warnings:\");\n for (const w of result.warnings) lines.push(` ! ${w}`);\n }\n\n const tally = result.changes.reduce<Record<ChangeRecord[\"action\"], number>>(\n (acc, c) => {\n acc[c.action] += 1;\n return acc;\n },\n { create: 0, update: 0, remove: 0, skip: 0, warn: 0 },\n );\n lines.push(\"\");\n lines.push(\n `summary: ${tally.create} created, ${tally.update} updated, ` +\n `${tally.remove} removed, ${tally.skip} skipped, ${tally.warn} warning(s)`,\n );\n\n return lines.join(\"\\n\");\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Command dispatch\n// ─────────────────────────────────────────────────────────────────────────\n\n/** A command module: takes the post-command argv slice, returns an exit code. */\ntype CommandModule = { run: (argv: string[]) => Promise<number> | number };\n\n/** Lazy command loaders — keyed by the first positional. Imported on demand. */\nconst COMMANDS: Record<string, () => Promise<CommandModule>> = {\n detect: () => import(\"./commands/detect.js\"),\n install: () => import(\"./commands/install.js\"),\n uninstall: () => import(\"./commands/uninstall.js\"),\n // `upgrade` is the single \"bring everything current\" verb (re-render host\n // config + refresh the home pointer + managed channel guidance). `sync` and\n // `update` are kept as back-compat aliases that route to the same module so\n // existing scripts/docs keep working without a second concept to learn.\n upgrade: () => import(\"./commands/upgrade.js\"),\n sync: () => import(\"./commands/upgrade.js\"),\n update: () => import(\"./commands/upgrade.js\"),\n package: () => import(\"./commands/package.js\"),\n doctor: () => import(\"./commands/doctor.js\"),\n status: () => import(\"./commands/status.js\"),\n telemetry: () => import(\"./commands/telemetry.js\"),\n usage: () => import(\"./commands/usage.js\"),\n leaderboard: () => import(\"./commands/leaderboard.js\"),\n hook: () => import(\"./commands/hook.js\"),\n serve: () => import(\"./commands/serve.js\"),\n // Hidden (omitted from USAGE): the opt-in host-native turn-usage entrypoint an\n // AfterModel / PostInvocation hook points at. Always exits 0; records a\n // distinct `model_turn` row. See cli/commands/usage-event.ts.\n \"usage-event\": () => import(\"./commands/usage-event.js\"),\n};\n\n/** Default program name; an embedding SDK CLI overrides it via {@link MainOptions}. */\nexport const DEFAULT_PROGRAM_NAME = \"agent-connector\";\n\n/**\n * One-line usage signature per command — the single central copy behind\n * `<command> --help` and the friendly bad-flag error. Command modules use\n * node:util parseArgs (strict), which THROWS on an unknown flag; without the\n * dispatcher-level handling in {@link main}, `agent-connector install --help`\n * would die with a raw ERR_PARSE_ARGS stack trace — the very invocation the\n * root help tells users to run.\n */\nconst COMMAND_USAGE: Record<string, string> = {\n detect: \"detect [--json] [--project <dir>]\",\n install:\n \"install [--method direct|marketplace] [--connector <path>] [--scope user|project] [--targets a,b] [--project <dir>] [--dry-run] [--force]\",\n uninstall:\n \"uninstall [--method auto|direct|marketplace] [--connector <path>] [--connector-id <id>] [--scope user|project] [--targets a,b] [--project <dir>] [--dry-run] [--purge]\",\n upgrade:\n \"upgrade [--method direct|marketplace] [--channel stable|latest] [--connector <path>] [--scope user|project] [--targets a,b] [--project <dir>] [--dry-run]\",\n sync: \"sync — alias of upgrade (see `upgrade --help`)\",\n update: \"update — alias of upgrade (see `upgrade --help`)\",\n package:\n \"package [--connector <path>] [--format <fmt>|all] [--out <dir>] [--project <dir>] [--dry-run]\",\n doctor:\n \"doctor [--targets a,b] [--connector <path>] [--scope user|project] [--project <dir>] [--probe] [--json]\",\n status: \"status [--connector <path>] [--scope user|project] [--project <dir>] [--json]\",\n telemetry:\n \"telemetry report|export|leaderboard [--by <dim>] [--since <dur>] [--connector <id>] [--scope <slice>] [--format csv|json] [--out <file>] [--json]\",\n usage:\n \"usage report|export|leaderboard [--by <dim>] [--since <dur>] [--platform <id>] [--format csv|json] [--out <file>] [--json]\",\n leaderboard: \"leaderboard [--since <dur>] [--connector <id>] [--scope <slice>] [--json]\",\n hook: \"hook <platform> <event> --connector <id> (internal — host hook configs point here)\",\n serve:\n \"serve --connector <id> [--scope user|project] [--host <platformId>] -- <command> [args...] (internal — host MCP entries point here)\",\n};\n\n/**\n * Build the top-level usage string for a given program name. The brand replaces\n * \"agent-connector\" in the title, the `usage:` line, and the per-command help\n * footer so an embedded CLI (e.g. `acme-db`) reads as its own tool.\n */\nfunction buildUsage(programName: string): string {\n return `${programName} — write your MCP server + hooks once, install everywhere.\n\nusage: ${programName} <command> [flags]\n\ncommands:\n detect List the AI-agent platforms installed on this machine.\n install Deploy a connector across its target platforms (--method direct writes host config; --method marketplace drives the host's plugin install).\n uninstall Remove a connector's registrations (--method auto reverses whichever method is actually installed).\n upgrade Bring everything current: re-render host config + heal the home pointer + managed update guidance (alias: update, sync).\n package Emit a marketplace/extension bundle (9 host formats, or the standard artifacts mcp-server-json | mcpb).\n doctor Health-check every detected platform; non-zero exit on any failure.\n status Light install-state summary: which connectors are present on which hosts (always exits 0).\n telemetry Inspect local per-tool token telemetry (report | export | leaderboard).\n usage Inspect host-native token usage from agent CLI logs (report | export | leaderboard).\n leaderboard Three leaderboards: 🔌 MCP/plugin (mcp-self) + 🖥️ host/user (host-scan-logs) + 🛰️ host-native turns (host-native-live) — never summed.\n hook Universal json-stdio hook entrypoint (hosts call this).\n serve Telemetry-wrapping MCP stdio proxy (wraps a real server command).\n\nRun \\`${programName} <command> --help\\` for command-specific flags.`;\n}\n\n/** Options accepted by {@link main}. */\nexport interface MainOptions {\n /**\n * The brand shown in usage/help text. Defaults to {@link DEFAULT_PROGRAM_NAME}.\n * An embedding SDK CLI (see cli/sdk.ts) passes its own bin name so every\n * subcommand's help reads as the developer's tool.\n */\n programName?: string;\n}\n\nexport async function main(argv: string[], opts: MainOptions = {}): Promise<number> {\n const programName = opts.programName ?? DEFAULT_PROGRAM_NAME;\n activeProgramName = programName; // brand every fail() in this invocation\n const usage = buildUsage(programName);\n const command = argv[0];\n\n if (command == null || command === \"--help\" || command === \"-h\" || command === \"help\") {\n print(usage);\n return command == null ? 1 : 0;\n }\n if (command === \"--version\" || command === \"-v\") {\n print(`${programName} ${resolveOwnVersion()}`);\n return 0;\n }\n\n const loader = COMMANDS[command];\n if (!loader) {\n process.stderr.write(`${programName}: unknown command \"${command}\"\\n\\n`);\n process.stderr.write(`${usage}\\n`);\n return 2;\n }\n\n // Per-command help: no command module defines a --help flag (strict parseArgs\n // would throw on it), so answer it centrally from COMMAND_USAGE.\n const rest = argv.slice(1);\n if (rest.includes(\"--help\") || rest.includes(\"-h\")) {\n const sig = COMMAND_USAGE[command];\n if (sig) {\n print(`usage: ${programName} ${sig}`);\n return 0;\n }\n }\n\n const mod = await loader();\n try {\n return await mod.run(rest);\n } catch (err) {\n // Friendly bad-flag errors: strict parseArgs throws ERR_PARSE_ARGS_* for an\n // unknown/malformed option — print the message + the usage line instead of\n // letting a raw stack trace reach the user. Everything else still rethrows\n // (the bin entry reports those as fatal).\n const code = (err as { code?: string }).code;\n if (typeof code === \"string\" && code.startsWith(\"ERR_PARSE_ARGS\")) {\n const message = err instanceof Error ? err.message : String(err);\n const sig = COMMAND_USAGE[command];\n if (sig) process.stderr.write(`usage: ${programName} ${sig}\\n`);\n return fail(message);\n }\n throw err;\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,511 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ connectorDir,
4
+ connectorsDir,
5
+ dataRoot,
6
+ ensureDir
7
+ } from "./chunk-TRQKHP7D.js";
8
+
9
+ // src/core/marketplace-state.ts
10
+ import { createHash } from "crypto";
11
+ import {
12
+ existsSync,
13
+ readdirSync,
14
+ readFileSync,
15
+ realpathSync,
16
+ rmSync,
17
+ statSync,
18
+ writeFileSync
19
+ } from "fs";
20
+ import { homedir } from "os";
21
+ import { dirname, join, relative, resolve } from "path";
22
+ import { fileURLToPath } from "url";
23
+ import TOML from "@iarna/toml";
24
+ var MARKETPLACE_NAME = "agent-connector";
25
+ function marketplaceInstallsPath(connectorId) {
26
+ return join(connectorDir(connectorId), "marketplace-installs.json");
27
+ }
28
+ function readMarketplaceInstalls(connectorId) {
29
+ try {
30
+ const raw = readFileSync(marketplaceInstallsPath(connectorId), "utf8");
31
+ const parsed = JSON.parse(raw);
32
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
33
+ return parsed;
34
+ }
35
+ } catch {
36
+ }
37
+ return {};
38
+ }
39
+ function writeMarketplaceInstalls(connectorId, installs) {
40
+ const path = marketplaceInstallsPath(connectorId);
41
+ if (Object.keys(installs).length === 0) {
42
+ rmSync(path, { force: true });
43
+ return;
44
+ }
45
+ ensureDir(dirname(path));
46
+ writeFileSync(path, `${JSON.stringify(installs, null, 2)}
47
+ `, "utf8");
48
+ }
49
+ function connectorHasMarketplaceRecords(connectorId) {
50
+ return Object.keys(readMarketplaceInstalls(connectorId)).length > 0;
51
+ }
52
+ function anyMarketplaceRecordsRemain(excludeConnectorId) {
53
+ const dir = connectorsDir();
54
+ if (!existsSync(dir)) return false;
55
+ let entries;
56
+ try {
57
+ entries = readdirSync(dir);
58
+ } catch {
59
+ return false;
60
+ }
61
+ return entries.some(
62
+ (id) => id !== excludeConnectorId && connectorHasMarketplaceRecords(id)
63
+ );
64
+ }
65
+ function marketplaceRoot() {
66
+ return join(dataRoot(), "marketplace");
67
+ }
68
+ function claudeStagingRoot() {
69
+ return join(marketplaceRoot(), "claude");
70
+ }
71
+ function codexStagingRoot() {
72
+ return join(marketplaceRoot(), "codex");
73
+ }
74
+ function agyStagingRoot() {
75
+ return join(marketplaceRoot(), "agy");
76
+ }
77
+ function geminiStagingRoot() {
78
+ return join(marketplaceRoot(), "gemini");
79
+ }
80
+ function qwenStagingRoot() {
81
+ return join(marketplaceRoot(), "qwen");
82
+ }
83
+ function droidStagingRoot() {
84
+ return join(marketplaceRoot(), "droid");
85
+ }
86
+ function npmStagingRoot() {
87
+ return join(marketplaceRoot(), "npm");
88
+ }
89
+ function claudeConfigDir() {
90
+ const override = process.env.CLAUDE_CONFIG_DIR;
91
+ if (override && override.trim() !== "") return resolve(override);
92
+ return join(homedir(), ".claude");
93
+ }
94
+ function claudePluginKey(connectorId) {
95
+ return `${connectorId}@${MARKETPLACE_NAME}`;
96
+ }
97
+ function readJsonFile(path) {
98
+ try {
99
+ const parsed = JSON.parse(readFileSync(path, "utf8"));
100
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
101
+ return parsed;
102
+ }
103
+ } catch {
104
+ }
105
+ return null;
106
+ }
107
+ function readClaudeInstalledPlugins() {
108
+ const file = join(claudeConfigDir(), "plugins", "installed_plugins.json");
109
+ const parsed = readJsonFile(file);
110
+ const plugins = parsed?.plugins;
111
+ if (plugins && typeof plugins === "object" && !Array.isArray(plugins)) {
112
+ return plugins;
113
+ }
114
+ return null;
115
+ }
116
+ function claudePluginInstalled(connectorId) {
117
+ const plugins = readClaudeInstalledPlugins();
118
+ if (!plugins) return false;
119
+ const entry = plugins[claudePluginKey(connectorId)];
120
+ return Array.isArray(entry) ? entry.length > 0 : entry != null;
121
+ }
122
+ function anyClaudeAgentConnectorPlugins() {
123
+ const plugins = readClaudeInstalledPlugins();
124
+ if (!plugins) return false;
125
+ return Object.entries(plugins).some(
126
+ ([key, entry]) => key.endsWith(`@${MARKETPLACE_NAME}`) && (Array.isArray(entry) ? entry.length > 0 : entry != null)
127
+ );
128
+ }
129
+ function claudeKnownMarketplacePath(name) {
130
+ const file = join(claudeConfigDir(), "plugins", "known_marketplaces.json");
131
+ const parsed = readJsonFile(file);
132
+ const entry = parsed?.[name];
133
+ if (!entry || typeof entry !== "object") return null;
134
+ const e = entry;
135
+ if (typeof e.installLocation === "string") return e.installLocation;
136
+ const sourcePath = e.source?.path;
137
+ return typeof sourcePath === "string" ? sourcePath : null;
138
+ }
139
+ function codexConfigHome() {
140
+ const env = process.env.CODEX_HOME;
141
+ if (env && env.trim() !== "") {
142
+ if (env.startsWith("~")) return join(homedir(), env.replace(/^~[/\\]?/, ""));
143
+ return resolve(env);
144
+ }
145
+ return join(homedir(), ".codex");
146
+ }
147
+ function codexPluginKey(connectorId) {
148
+ return `${connectorId}@${MARKETPLACE_NAME}`;
149
+ }
150
+ function readCodexConfig() {
151
+ const file = join(codexConfigHome(), "config.toml");
152
+ try {
153
+ return TOML.parse(readFileSync(file, "utf8"));
154
+ } catch {
155
+ return {};
156
+ }
157
+ }
158
+ function codexPluginInstalled(connectorId) {
159
+ const cfg = readCodexConfig();
160
+ const plugins = cfg["plugins"];
161
+ if (!plugins || typeof plugins !== "object" || Array.isArray(plugins)) return false;
162
+ return codexPluginKey(connectorId) in plugins;
163
+ }
164
+ function anyCodexAgentConnectorPlugins() {
165
+ const cfg = readCodexConfig();
166
+ const plugins = cfg["plugins"];
167
+ if (!plugins || typeof plugins !== "object" || Array.isArray(plugins)) return false;
168
+ return Object.keys(plugins).some(
169
+ (k) => k.endsWith(`@${MARKETPLACE_NAME}`)
170
+ );
171
+ }
172
+ function codexMarketplaceSource(name) {
173
+ const cfg = readCodexConfig();
174
+ const marketplaces = cfg["marketplaces"];
175
+ if (!marketplaces || typeof marketplaces !== "object" || Array.isArray(marketplaces)) {
176
+ return null;
177
+ }
178
+ const entry = marketplaces[name];
179
+ if (!entry || typeof entry !== "object") return null;
180
+ const source = entry.source;
181
+ return typeof source === "string" ? source : null;
182
+ }
183
+ function factorySettingsPath() {
184
+ return join(homedir(), ".factory", "settings.json");
185
+ }
186
+ function droidPluginKey(connectorId) {
187
+ return `${connectorId}@${MARKETPLACE_NAME}`;
188
+ }
189
+ function readDroidEnabledPlugins() {
190
+ const parsed = readJsonFile(factorySettingsPath());
191
+ const plugins = parsed?.enabledPlugins;
192
+ if (plugins && typeof plugins === "object" && !Array.isArray(plugins)) {
193
+ return plugins;
194
+ }
195
+ return null;
196
+ }
197
+ function droidPluginInstalled(connectorId) {
198
+ const plugins = readDroidEnabledPlugins();
199
+ if (!plugins) return false;
200
+ return plugins[droidPluginKey(connectorId)] === true;
201
+ }
202
+ function anyDroidAgentConnectorPlugins() {
203
+ const plugins = readDroidEnabledPlugins();
204
+ if (!plugins) return false;
205
+ return Object.entries(plugins).some(
206
+ ([key, value]) => key.endsWith(`@${MARKETPLACE_NAME}`) && value === true
207
+ );
208
+ }
209
+ function droidMarketplaceSource(name) {
210
+ const parsed = readJsonFile(factorySettingsPath());
211
+ const known = parsed?.extraKnownMarketplaces;
212
+ if (!known || typeof known !== "object" || Array.isArray(known)) return null;
213
+ const entry = known[name];
214
+ if (entry == null) return null;
215
+ if (typeof entry === "string") return entry;
216
+ if (typeof entry === "object" && !Array.isArray(entry)) {
217
+ const e = entry;
218
+ if (typeof e.source === "string") return e.source;
219
+ if (typeof e.path === "string") return e.path;
220
+ }
221
+ return null;
222
+ }
223
+ function agyConfigDir() {
224
+ return join(homedir(), ".gemini", "config");
225
+ }
226
+ function agyPluginsDir() {
227
+ return join(agyConfigDir(), "plugins");
228
+ }
229
+ function agyImportManifestPaths() {
230
+ return [
231
+ join(agyConfigDir(), "import_manifest.json"),
232
+ // win32 location
233
+ join(agyPluginsDir(), "import_manifest.json")
234
+ // posix location
235
+ ];
236
+ }
237
+ function agyPluginInstalled(connectorId) {
238
+ for (const manifest of agyImportManifestPaths()) {
239
+ try {
240
+ const parsed = JSON.parse(readFileSync(manifest, "utf8"));
241
+ const imports = parsed.imports;
242
+ if (Array.isArray(imports) && imports.some(
243
+ (e) => e != null && typeof e === "object" && e.name === connectorId
244
+ )) {
245
+ return true;
246
+ }
247
+ } catch {
248
+ }
249
+ }
250
+ return existsSync(join(agyPluginsDir(), connectorId, "plugin.json"));
251
+ }
252
+ function geminiConfigDir() {
253
+ return join(homedir(), ".gemini");
254
+ }
255
+ function geminiExtensionInstalled(connectorId) {
256
+ return existsSync(
257
+ join(geminiConfigDir(), "extensions", connectorId, "gemini-extension.json")
258
+ );
259
+ }
260
+ function qwenConfigDir() {
261
+ return join(homedir(), ".qwen");
262
+ }
263
+ function qwenExtensionInstalled(connectorId) {
264
+ return existsSync(
265
+ join(qwenConfigDir(), "extensions", connectorId, "qwen-extension.json")
266
+ );
267
+ }
268
+ function xdgConfigHome() {
269
+ const xdg = process.env.XDG_CONFIG_HOME;
270
+ return xdg && xdg.trim() !== "" ? resolve(xdg) : join(homedir(), ".config");
271
+ }
272
+ function opencodeConfigDir() {
273
+ return join(xdgConfigHome(), "opencode");
274
+ }
275
+ function kiloConfigDir() {
276
+ return join(xdgConfigHome(), "kilo");
277
+ }
278
+ function npmConfigCandidates(platform) {
279
+ return platform === "opencode" ? ["opencode.jsonc", "opencode.json", "config.json"] : ["opencode.json"];
280
+ }
281
+ function npmConfigDir(platform) {
282
+ return platform === "opencode" ? opencodeConfigDir() : kiloConfigDir();
283
+ }
284
+ function npmConfigFilePath(platform) {
285
+ const dir = npmConfigDir(platform);
286
+ const candidates = npmConfigCandidates(platform);
287
+ for (const name of candidates) {
288
+ if (existsSync(join(dir, name))) return join(dir, name);
289
+ }
290
+ return join(dir, candidates[0]);
291
+ }
292
+ function stripFileScheme(entry) {
293
+ let s = entry;
294
+ if (s.startsWith("file://localhost/")) s = s.slice("file://localhost".length);
295
+ else if (s.startsWith("file://")) s = s.slice("file://".length);
296
+ return s;
297
+ }
298
+ function stripJsoncComments(text) {
299
+ let out = "";
300
+ let inString = false;
301
+ let inLine = false;
302
+ let inBlock = false;
303
+ for (let i = 0; i < text.length; i++) {
304
+ const c = text[i];
305
+ const next = i + 1 < text.length ? text[i + 1] : "";
306
+ if (inLine) {
307
+ if (c === "\n") {
308
+ inLine = false;
309
+ out += c;
310
+ }
311
+ continue;
312
+ }
313
+ if (inBlock) {
314
+ if (c === "*" && next === "/") {
315
+ inBlock = false;
316
+ i++;
317
+ }
318
+ continue;
319
+ }
320
+ if (inString) {
321
+ out += c;
322
+ if (c === "\\") {
323
+ if (next !== "") {
324
+ out += next;
325
+ i++;
326
+ }
327
+ } else if (c === '"') {
328
+ inString = false;
329
+ }
330
+ continue;
331
+ }
332
+ if (c === '"') {
333
+ inString = true;
334
+ out += c;
335
+ continue;
336
+ }
337
+ if (c === "/" && next === "/") {
338
+ inLine = true;
339
+ i++;
340
+ continue;
341
+ }
342
+ if (c === "/" && next === "*") {
343
+ inBlock = true;
344
+ i++;
345
+ continue;
346
+ }
347
+ out += c;
348
+ }
349
+ return out;
350
+ }
351
+ function parseJsonc(text) {
352
+ try {
353
+ const parsed = JSON.parse(stripJsoncComments(text));
354
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
355
+ return parsed;
356
+ }
357
+ } catch {
358
+ }
359
+ return null;
360
+ }
361
+ function readNpmConfig(platform) {
362
+ const file = npmConfigFilePath(platform);
363
+ try {
364
+ return parseJsonc(readFileSync(file, "utf8"));
365
+ } catch {
366
+ return null;
367
+ }
368
+ }
369
+ function npmEntryToPath(entry) {
370
+ if (/^file:\/\//i.test(entry)) {
371
+ try {
372
+ return fileURLToPath(entry);
373
+ } catch {
374
+ }
375
+ }
376
+ return stripFileScheme(entry);
377
+ }
378
+ function npmPathEquals(a, b) {
379
+ const norm = (p) => {
380
+ let s;
381
+ try {
382
+ s = realpathSync.native(p);
383
+ } catch {
384
+ s = resolve(p);
385
+ }
386
+ return process.platform === "win32" ? s.toLowerCase() : s;
387
+ };
388
+ return norm(a) === norm(b);
389
+ }
390
+ function npmPluginArrayEntry(platform, connectorId) {
391
+ const cfg = readNpmConfig(platform);
392
+ if (!cfg) return null;
393
+ const arr = cfg["plugin"];
394
+ if (!Array.isArray(arr)) return null;
395
+ const target = join(npmStagingRoot(), connectorId);
396
+ for (const raw of arr) {
397
+ if (typeof raw !== "string") continue;
398
+ if (npmPathEquals(npmEntryToPath(raw), target)) return raw;
399
+ }
400
+ return null;
401
+ }
402
+ function npmPluginInstalled(platform, connectorId) {
403
+ return npmPluginArrayEntry(platform, connectorId) != null;
404
+ }
405
+ function marketplaceEvidence(connectorId, platform) {
406
+ if (readMarketplaceInstalls(connectorId)[platform]) {
407
+ return "recorded in marketplace-installs.json";
408
+ }
409
+ switch (platform) {
410
+ case "claude-code":
411
+ if (claudePluginInstalled(connectorId)) {
412
+ return `${claudePluginKey(connectorId)} listed in Claude's installed_plugins.json`;
413
+ }
414
+ return null;
415
+ case "gemini-cli":
416
+ return geminiExtensionInstalled(connectorId) ? `extension ${connectorId} listed in Gemini's extensions store` : null;
417
+ case "qwen-code":
418
+ return qwenExtensionInstalled(connectorId) ? `extension ${connectorId} listed in Qwen's extensions store` : null;
419
+ case "droid":
420
+ return droidPluginInstalled(connectorId) ? `${droidPluginKey(connectorId)} enabled in droid's settings.json` : null;
421
+ case "antigravity":
422
+ case "antigravity-cli": {
423
+ const dir = join(homedir(), ".gemini", "config", "plugins", connectorId);
424
+ return existsSync(dir) ? `plugin dir ${dir} exists` : null;
425
+ }
426
+ case "opencode":
427
+ case "kilo":
428
+ case "kilo-cli":
429
+ return npmPluginInstalled(platform, connectorId) ? `${connectorId} listed in ${platform}'s config plugin array` : null;
430
+ case "codex": {
431
+ const codexHome = process.env.CODEX_HOME && process.env.CODEX_HOME.trim() !== "" ? resolve(process.env.CODEX_HOME) : join(homedir(), ".codex");
432
+ const dir = join(codexHome, "plugins", "cache", MARKETPLACE_NAME, connectorId);
433
+ return existsSync(dir) ? `codex plugin cache ${dir} exists` : null;
434
+ }
435
+ default:
436
+ return null;
437
+ }
438
+ }
439
+ function hashDirectory(dir) {
440
+ if (!existsSync(dir)) return "";
441
+ const files = [];
442
+ const walk = (d) => {
443
+ let entries;
444
+ try {
445
+ entries = readdirSync(d);
446
+ } catch {
447
+ return;
448
+ }
449
+ for (const name of entries.sort()) {
450
+ const full = join(d, name);
451
+ let st;
452
+ try {
453
+ st = statSync(full);
454
+ } catch {
455
+ continue;
456
+ }
457
+ if (st.isDirectory()) walk(full);
458
+ else if (st.isFile()) files.push(full);
459
+ }
460
+ };
461
+ walk(dir);
462
+ const hash = createHash("sha256");
463
+ for (const file of files.sort()) {
464
+ hash.update(relative(dir, file).split("\\").join("/"));
465
+ hash.update("\0");
466
+ try {
467
+ hash.update(readFileSync(file));
468
+ } catch {
469
+ }
470
+ hash.update("\0");
471
+ }
472
+ return hash.digest("hex");
473
+ }
474
+
475
+ export {
476
+ MARKETPLACE_NAME,
477
+ readMarketplaceInstalls,
478
+ writeMarketplaceInstalls,
479
+ connectorHasMarketplaceRecords,
480
+ anyMarketplaceRecordsRemain,
481
+ marketplaceRoot,
482
+ claudeStagingRoot,
483
+ codexStagingRoot,
484
+ agyStagingRoot,
485
+ geminiStagingRoot,
486
+ qwenStagingRoot,
487
+ droidStagingRoot,
488
+ npmStagingRoot,
489
+ claudePluginKey,
490
+ claudePluginInstalled,
491
+ anyClaudeAgentConnectorPlugins,
492
+ claudeKnownMarketplacePath,
493
+ codexPluginKey,
494
+ codexPluginInstalled,
495
+ anyCodexAgentConnectorPlugins,
496
+ codexMarketplaceSource,
497
+ droidPluginKey,
498
+ droidPluginInstalled,
499
+ anyDroidAgentConnectorPlugins,
500
+ droidMarketplaceSource,
501
+ agyPluginInstalled,
502
+ geminiExtensionInstalled,
503
+ qwenExtensionInstalled,
504
+ npmConfigFilePath,
505
+ readNpmConfig,
506
+ npmPluginArrayEntry,
507
+ npmPluginInstalled,
508
+ marketplaceEvidence,
509
+ hashDirectory
510
+ };
511
+ //# sourceMappingURL=chunk-G5CQHVQG.js.map