@ken-jo/agent-connector 0.3.0 → 0.4.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 +188 -20
- package/dist/action-PLZW5BGX.js +54 -0
- package/dist/action-PLZW5BGX.js.map +1 -0
- package/dist/{amp-YGV66GJT.js → amp-B524U6LO.js} +81 -5
- package/dist/amp-B524U6LO.js.map +1 -0
- package/dist/{antigravity-7IBYFO6P.js → antigravity-ANDKF3K7.js} +4 -4
- package/dist/{antigravity-cli-JEOUP2VN.js → antigravity-cli-LLRPDDOT.js} +4 -4
- package/dist/chunk-22Y24V7O.js +21 -0
- package/dist/chunk-22Y24V7O.js.map +1 -0
- package/dist/chunk-3PFFTFCU.js +190 -0
- package/dist/chunk-3PFFTFCU.js.map +1 -0
- package/dist/{chunk-SCVBYSF7.js → chunk-6XHB6BE3.js} +1 -1
- package/dist/chunk-76FUSVIA.js +43 -0
- package/dist/chunk-76FUSVIA.js.map +1 -0
- package/dist/{chunk-GSGDG2BV.js → chunk-ADTHT2FN.js} +109 -16
- package/dist/chunk-ADTHT2FN.js.map +1 -0
- package/dist/{chunk-ZAM4M7LI.js → chunk-BHUCB6LY.js} +135 -296
- package/dist/chunk-BHUCB6LY.js.map +1 -0
- package/dist/{chunk-MEH7GC7R.js → chunk-BXGFUENQ.js} +20 -3
- package/dist/chunk-BXGFUENQ.js.map +1 -0
- package/dist/chunk-CIRDOY2V.js +351 -0
- package/dist/chunk-CIRDOY2V.js.map +1 -0
- package/dist/{chunk-QADSG2JY.js → chunk-G3ER4SY5.js} +1152 -106
- package/dist/chunk-G3ER4SY5.js.map +1 -0
- package/dist/{chunk-44HUXXC6.js → chunk-G5CQHVQG.js} +232 -5
- package/dist/chunk-G5CQHVQG.js.map +1 -0
- package/dist/{chunk-PD4VFEBY.js → chunk-IW77FFNX.js} +39 -1
- package/dist/chunk-IW77FFNX.js.map +1 -0
- package/dist/chunk-J3D5W5T2.js +83 -0
- package/dist/chunk-J3D5W5T2.js.map +1 -0
- package/dist/{openclaw-UZ5BMCGQ.js → chunk-KGGBNKI4.js} +125 -33
- package/dist/chunk-KGGBNKI4.js.map +1 -0
- package/dist/{chunk-3JCRUROU.js → chunk-KGJWE6A2.js} +13 -4
- package/dist/chunk-KGJWE6A2.js.map +1 -0
- package/dist/{chunk-DS3LUFVN.js → chunk-KGXDYGNJ.js} +26 -16
- package/dist/chunk-KGXDYGNJ.js.map +1 -0
- package/dist/{chunk-KVAAFYRR.js → chunk-KHO5WNTP.js} +2 -18
- package/dist/chunk-KHO5WNTP.js.map +1 -0
- package/dist/{chunk-KQSNDFBN.js → chunk-LL4OBGRU.js} +3 -3
- package/dist/{chunk-WNREHWKL.js → chunk-MAH6QQTO.js} +3 -3
- package/dist/{claude-code-4275HQU4.js → claude-code-MLWS7CW6.js} +180 -28
- package/dist/claude-code-MLWS7CW6.js.map +1 -0
- package/dist/cli/sdk.js +4 -3
- package/dist/cli/sdk.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/{codebuff-LE3KBZGM.js → codebuff-SH2S3QAN.js} +102 -5
- package/dist/codebuff-SH2S3QAN.js.map +1 -0
- package/dist/{codex-4BY2ZJIW.js → codex-BXA4FIF4.js} +3 -3
- package/dist/{copilot-cli-IPISKO3V.js → copilot-cli-ROIBTTDT.js} +3 -3
- package/dist/{crush-X3E25EQG.js → crush-QLEFLHUC.js} +3 -3
- package/dist/{cursor-UH3W622V.js → cursor-ASJPWZ4R.js} +6 -3
- package/dist/cursor-ASJPWZ4R.js.map +1 -0
- package/dist/{detect-MNDHGLSV.js → detect-ZIIS55LD.js} +4 -3
- package/dist/{detect-MNDHGLSV.js.map → detect-ZIIS55LD.js.map} +1 -1
- package/dist/{doctor-N5KZDD55.js → doctor-TJUGSQ5C.js} +17 -13
- package/dist/doctor-TJUGSQ5C.js.map +1 -0
- package/dist/{droid-T5VBRXZF.js → droid-NCSS3B5Y.js} +170 -4
- package/dist/droid-NCSS3B5Y.js.map +1 -0
- package/dist/{gemini-cli-ZSUK55UA.js → gemini-cli-SLVWLXJW.js} +3 -3
- package/dist/{goose-M3RR3CZG.js → goose-PBA7KTE5.js} +100 -5
- package/dist/goose-PBA7KTE5.js.map +1 -0
- package/dist/{hermes-CUNKIAR5.js → hermes-ONDCECP2.js} +3 -3
- package/dist/{hook-7LUOKIXH.js → hook-OU522ABV.js} +12 -9
- package/dist/{hook-7LUOKIXH.js.map → hook-OU522ABV.js.map} +1 -1
- package/dist/index.d.ts +71 -3
- package/dist/index.js +22 -3
- package/dist/{install-TQTT4F3I.js → install-UDCBL7HP.js} +12 -10
- package/dist/{install-TQTT4F3I.js.map → install-UDCBL7HP.js.map} +1 -1
- package/dist/introspect-DuZSPSHB.d.ts +53 -0
- package/dist/{jetbrains-copilot-C3HDGGML.js → jetbrains-copilot-YABZ3HFA.js} +3 -3
- package/dist/{kilo-PKAJCWPX.js → kilo-F3ZDZKCT.js} +3 -3
- package/dist/{kilo-cli-QWUVXG2O.js → kilo-cli-3HWPWBY4.js} +3 -3
- package/dist/{kimi-EVD7YKXS.js → kimi-NV72FVAO.js} +3 -3
- package/dist/{kiro-UQRY6EIO.js → kiro-C5W6AGDR.js} +3 -3
- package/dist/{leaderboard-MUJ7DURM.js → leaderboard-TIBVONVT.js} +3 -3
- package/dist/mimo-code-IMM5YM3M.js +754 -0
- package/dist/mimo-code-IMM5YM3M.js.map +1 -0
- package/dist/{mux-5CI5FP2W.js → mux-DSSH4AFS.js} +3 -3
- package/dist/nemoclaw-3EVNKD3I.js +58 -0
- package/dist/nemoclaw-3EVNKD3I.js.map +1 -0
- package/dist/{omp-AXA7XY22.js → omp-Z6FRNDPN.js} +3 -3
- package/dist/openclaw-7G437NT7.js +18 -0
- package/dist/openclaw-7G437NT7.js.map +1 -0
- package/dist/{opencode-NZBRLJN3.js → opencode-Q6KBSAKW.js} +3 -3
- package/dist/{package-SYPA5POO.js → package-RMPN57YZ.js} +7 -6
- package/dist/{package-SYPA5POO.js.map → package-RMPN57YZ.js.map} +1 -1
- package/dist/{pi-WMTUX6ES.js → pi-LZT6WWAZ.js} +2 -2
- package/dist/{qwen-code-MRRIUQ3P.js → qwen-code-WQBKRPWJ.js} +3 -3
- package/dist/{roo-code-NI5UU6JB.js → roo-code-GWSNU3OW.js} +137 -4
- package/dist/roo-code-GWSNU3OW.js.map +1 -0
- package/dist/runtime/index.d.ts +96 -2
- package/dist/runtime/index.js +18 -10
- package/dist/sdk/index.d.ts +52 -0
- package/dist/sdk/index.js +81 -0
- package/dist/sdk/index.js.map +1 -0
- package/dist/sdk/test.d.ts +74 -0
- package/dist/sdk/test.js +291 -0
- package/dist/sdk/test.js.map +1 -0
- package/dist/{serve-XJOSA7BY.js → serve-D3GO36UT.js} +12 -9
- package/dist/{serve-XJOSA7BY.js.map → serve-D3GO36UT.js.map} +1 -1
- package/dist/{status-DYSS6BOR.js → status-KOSKCETC.js} +10 -8
- package/dist/{status-DYSS6BOR.js.map → status-KOSKCETC.js.map} +1 -1
- package/dist/statusline-ZNTCL5YC.js +59 -0
- package/dist/statusline-ZNTCL5YC.js.map +1 -0
- package/dist/{telemetry-IJ4GP2Q3.js → telemetry-XIKUUGTQ.js} +5 -4
- package/dist/{telemetry-IJ4GP2Q3.js.map → telemetry-XIKUUGTQ.js.map} +1 -1
- package/dist/{trae-CQC72RHH.js → trae-NWT3TMSZ.js} +99 -5
- package/dist/trae-NWT3TMSZ.js.map +1 -0
- package/dist/{types-CNigfEuR.d.ts → types-BEKsAium.d.ts} +268 -6
- package/dist/{uninstall-3DXIBRCV.js → uninstall-2LBLQVFA.js} +12 -10
- package/dist/{uninstall-3DXIBRCV.js.map → uninstall-2LBLQVFA.js.map} +1 -1
- package/dist/{upgrade-GJEB3ITY.js → upgrade-ZC2S7VRN.js} +12 -10
- package/dist/{upgrade-GJEB3ITY.js.map → upgrade-ZC2S7VRN.js.map} +1 -1
- package/dist/{usage-2BJLM3GJ.js → usage-E2A4O2CY.js} +3 -3
- package/dist/{usage-event-472X3DOY.js → usage-event-JKMC4QC4.js} +11 -8
- package/dist/{usage-event-472X3DOY.js.map → usage-event-JKMC4QC4.js.map} +1 -1
- package/dist/{vscode-copilot-4RVRTCKV.js → vscode-copilot-ALV45XF6.js} +3 -3
- package/dist/{warp-X6MB67NT.js → warp-H6IX4U3J.js} +3 -3
- package/dist/{zed-NTCYW4V2.js → zed-RH34TNSW.js} +3 -3
- package/package.json +9 -1
- package/dist/amp-YGV66GJT.js.map +0 -1
- package/dist/chunk-3JCRUROU.js.map +0 -1
- package/dist/chunk-44HUXXC6.js.map +0 -1
- package/dist/chunk-DS3LUFVN.js.map +0 -1
- package/dist/chunk-GSGDG2BV.js.map +0 -1
- package/dist/chunk-KVAAFYRR.js.map +0 -1
- package/dist/chunk-MEH7GC7R.js.map +0 -1
- package/dist/chunk-NJU275US.js +0 -238
- package/dist/chunk-NJU275US.js.map +0 -1
- package/dist/chunk-PD4VFEBY.js.map +0 -1
- package/dist/chunk-QADSG2JY.js.map +0 -1
- package/dist/chunk-ZAM4M7LI.js.map +0 -1
- package/dist/claude-code-4275HQU4.js.map +0 -1
- package/dist/codebuff-LE3KBZGM.js.map +0 -1
- package/dist/cursor-UH3W622V.js.map +0 -1
- package/dist/doctor-N5KZDD55.js.map +0 -1
- package/dist/droid-T5VBRXZF.js.map +0 -1
- package/dist/goose-M3RR3CZG.js.map +0 -1
- package/dist/openclaw-UZ5BMCGQ.js.map +0 -1
- package/dist/roo-code-NI5UU6JB.js.map +0 -1
- package/dist/trae-CQC72RHH.js.map +0 -1
- /package/dist/{antigravity-7IBYFO6P.js.map → antigravity-ANDKF3K7.js.map} +0 -0
- /package/dist/{antigravity-cli-JEOUP2VN.js.map → antigravity-cli-LLRPDDOT.js.map} +0 -0
- /package/dist/{chunk-SCVBYSF7.js.map → chunk-6XHB6BE3.js.map} +0 -0
- /package/dist/{chunk-KQSNDFBN.js.map → chunk-LL4OBGRU.js.map} +0 -0
- /package/dist/{chunk-WNREHWKL.js.map → chunk-MAH6QQTO.js.map} +0 -0
- /package/dist/{codex-4BY2ZJIW.js.map → codex-BXA4FIF4.js.map} +0 -0
- /package/dist/{copilot-cli-IPISKO3V.js.map → copilot-cli-ROIBTTDT.js.map} +0 -0
- /package/dist/{crush-X3E25EQG.js.map → crush-QLEFLHUC.js.map} +0 -0
- /package/dist/{gemini-cli-ZSUK55UA.js.map → gemini-cli-SLVWLXJW.js.map} +0 -0
- /package/dist/{hermes-CUNKIAR5.js.map → hermes-ONDCECP2.js.map} +0 -0
- /package/dist/{jetbrains-copilot-C3HDGGML.js.map → jetbrains-copilot-YABZ3HFA.js.map} +0 -0
- /package/dist/{kilo-PKAJCWPX.js.map → kilo-F3ZDZKCT.js.map} +0 -0
- /package/dist/{kilo-cli-QWUVXG2O.js.map → kilo-cli-3HWPWBY4.js.map} +0 -0
- /package/dist/{kimi-EVD7YKXS.js.map → kimi-NV72FVAO.js.map} +0 -0
- /package/dist/{kiro-UQRY6EIO.js.map → kiro-C5W6AGDR.js.map} +0 -0
- /package/dist/{leaderboard-MUJ7DURM.js.map → leaderboard-TIBVONVT.js.map} +0 -0
- /package/dist/{mux-5CI5FP2W.js.map → mux-DSSH4AFS.js.map} +0 -0
- /package/dist/{omp-AXA7XY22.js.map → omp-Z6FRNDPN.js.map} +0 -0
- /package/dist/{opencode-NZBRLJN3.js.map → opencode-Q6KBSAKW.js.map} +0 -0
- /package/dist/{pi-WMTUX6ES.js.map → pi-LZT6WWAZ.js.map} +0 -0
- /package/dist/{qwen-code-MRRIUQ3P.js.map → qwen-code-WQBKRPWJ.js.map} +0 -0
- /package/dist/{usage-2BJLM3GJ.js.map → usage-E2A4O2CY.js.map} +0 -0
- /package/dist/{vscode-copilot-4RVRTCKV.js.map → vscode-copilot-ALV45XF6.js.map} +0 -0
- /package/dist/{warp-X6MB67NT.js.map → warp-H6IX4U3J.js.map} +0 -0
- /package/dist/{zed-NTCYW4V2.js.map → zed-RH34TNSW.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/load-connector.ts"],"sourcesContent":["/**\n * core/load-connector — discover, load, and register connector definitions.\n *\n * Responsibilities:\n * 1. Locate the developer's `agent-connector.config.{mjs,js,json}` by walking\n * upward from a start directory (the project root convention).\n * 2. Load a config from a path into a LIVE ResolvedConnector (with handlers).\n * 3. Register a connector by persisting SERIALIZABLE metadata (no functions)\n * to `connectorDir(id)/connector.json`, pointing at the source module so\n * live handlers can be re-imported at runtime from a stable record.\n *\n * Why split live vs. serialized? Hook handlers are functions and cannot survive\n * JSON. The registry stores only what JSON can hold plus an absolute\n * `modulePath`; the runtime re-imports that module to recover the live handlers.\n */\n\nimport { existsSync, readdirSync, readFileSync, realpathSync, rmSync, writeFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nimport type {\n CommandDef,\n HookEventName,\n InstallScope,\n MemoryDef,\n PlatformId,\n PlatformOverride,\n ResolvedConnector,\n ServerDef,\n SkillDef,\n SubagentDef,\n} from \"./types.js\";\nimport { defineConnector } from \"./define-connector.js\";\nimport { connectorDir, connectorsDir, ensureDir } from \"./paths.js\";\n\n/** Candidate config filenames, in resolution-precedence order. */\nconst CONFIG_FILENAMES = [\n \"agent-connector.config.mjs\",\n \"agent-connector.config.js\",\n \"agent-connector.config.json\",\n] as const;\n\n/**\n * The serializable subset of a connector persisted to `connector.json`.\n * Hook handler functions are intentionally absent — only the absolute\n * `modulePath` is stored so the live ResolvedConnector can be re-imported.\n */\nexport interface RegisteredMeta {\n id: string;\n displayName: string;\n version: string;\n /** Absolute path to the source module that produced this connector. */\n modulePath: string;\n telemetry: ResolvedConnector[\"telemetry\"];\n /** Canonical event names the connector handles (handlers themselves stripped). */\n hookEvents: HookEventName[];\n hasServer: boolean;\n server: ServerDef | null;\n /**\n * Content surfaces (commands/skills/subagents). These are JSON-serializable\n * (no functions) so they persist cleanly and let uninstall locate the files\n * to remove even when the source module is gone.\n */\n commands: CommandDef[];\n skills: SkillDef[];\n subagents: SubagentDef[];\n /**\n * Memory entries (managed-block content surface). Plain content, persisted\n * whole so uninstall normally has the full entry list even when the source\n * module is gone (the marker prefix-scan is the fallback beyond that).\n */\n memory: MemoryDef[];\n targets: ResolvedConnector[\"targets\"];\n /** Per-platform overrides with any hook handler functions stripped. */\n platforms: Partial<Record<PlatformId, PlatformOverride>>;\n /**\n * The install scope this connector was registered under, persisted so the\n * runtime entrypoints (hook/statusline/action) can recover it cheaply (sync)\n * and stamp it onto the HostCtx/event — scope is an install-time property the\n * runtime otherwise has no access to. OPTIONAL: absent for an ad-hoc register\n * that passed no scope, or a record written before this field existed.\n * This is the install's RUN-WIDE DEFAULT scope; it can differ from the\n * effective per-host scope when a `platforms[host].scope` override is set (the\n * record is keyed by connector id only and holds no per-host scope map).\n */\n scope?: InstallScope;\n}\n\n/**\n * Search `startDir` and each ancestor for a connector config file. Returns the\n * absolute path to the first match (filesystem-root-stopping), or null.\n */\nexport function findConnectorConfig(startDir: string): string | null {\n let dir = resolve(startDir);\n // Walk upward until `dirname(dir) === dir` (filesystem root).\n for (;;) {\n for (const name of CONFIG_FILENAMES) {\n const candidate = join(dir, name);\n if (existsSync(candidate)) return candidate;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\n/** True if a value already looks like a ResolvedConnector (vs. a raw config). */\nfunction isResolvedConnector(value: unknown): value is ResolvedConnector {\n return (\n typeof value === \"object\" &&\n value !== null &&\n Array.isArray((value as { hookEvents?: unknown }).hookEvents)\n );\n}\n\n/**\n * Load a connector from an absolute or relative path.\n * - `.json` → JSON.parse, then defineConnector().\n * - `.mjs` / `.js` → dynamic import (via pathToFileURL, Windows-safe),\n * take the default export. If it already looks like a\n * ResolvedConnector use it as-is; otherwise treat it as\n * a ConnectorConfig and run it through defineConnector().\n * Returns the live connector plus the absolute module path it came from.\n */\nexport async function loadConnectorFromPath(\n path: string,\n): Promise<{ connector: ResolvedConnector; modulePath: string }> {\n let modulePath = isAbsolute(path) ? path : resolve(path);\n // Canonicalize before building the file:// URL for dynamic import. On Windows a\n // short (8.3) temp path like C:\\Users\\RUNNER~1\\...\\x.mjs round-trips the \"~\" as\n // %7E and fails to load; realpathSync.native expands it to the real long path.\n // It also resolves symlinked temp roots (e.g. macOS /var -> /private/var).\n // If the file does not exist yet, fall through with the resolve()'d path so the\n // subsequent read/import throws the real not-found error.\n try {\n modulePath = realpathSync.native(modulePath);\n } catch {\n /* keep the resolve()'d path */\n }\n\n if (modulePath.endsWith(\".json\")) {\n const text = readFileSync(modulePath, \"utf8\");\n const config = JSON.parse(text) as unknown;\n const connector = defineConnector(config as Parameters<typeof defineConnector>[0]);\n return { connector, modulePath };\n }\n\n // .mjs / .js — dynamic ESM import. pathToFileURL keeps Windows paths valid.\n const mod = (await import(pathToFileURL(modulePath).href)) as {\n default?: unknown;\n };\n const exported = mod.default;\n if (exported == null) {\n throw new Error(\n `Connector module has no default export: ${modulePath}`,\n );\n }\n const connector = isResolvedConnector(exported)\n ? exported\n : defineConnector(exported as Parameters<typeof defineConnector>[0]);\n return { connector, modulePath };\n}\n\n/**\n * Strip any function-valued `hooks` from per-platform overrides so the result\n * is JSON-serializable. A boolean `hooks` override is preserved; an object\n * override is dropped (it can only carry handler functions, which are not\n * serializable). `nativeHooks` declarations are persisted HANDLER-LESS (event\n * name + matcher only) so meta-based inspection (doctor / health checks / the\n * hook CLI) can still see WHICH native events were declared — the live handlers\n * are re-imported from `modulePath` at runtime, exactly like normalized hooks.\n * Everything else on the override is kept verbatim — notably `configPatch`\n * declarations, which are pure JSON (key/value/reason/docsUrl, no functions)\n * and persist WHOLE so uninstall/doctor can reason about them even when the\n * source module is gone.\n */\nfunction serializablePlatforms(\n platforms: Partial<Record<PlatformId, PlatformOverride>>,\n): Partial<Record<PlatformId, PlatformOverride>> {\n const out: Partial<Record<PlatformId, PlatformOverride>> = {};\n for (const [id, override] of Object.entries(platforms) as [\n PlatformId,\n PlatformOverride | undefined,\n ][]) {\n if (!override) continue;\n const { hooks, nativeHooks, ...rest } = override;\n const clean: PlatformOverride = { ...rest };\n // Keep only a boolean hooks flag; object hooks carry handler functions.\n if (typeof hooks === \"boolean\") clean.hooks = hooks;\n if (nativeHooks && typeof nativeHooks === \"object\") {\n const stripped: Record<string, { matcher?: string }> = {};\n for (const [event, def] of Object.entries(nativeHooks)) {\n stripped[event] =\n typeof def?.matcher === \"string\" ? { matcher: def.matcher } : {};\n }\n // Cast: the persisted record deliberately omits the (non-serializable)\n // handler; consumers of meta-derived connectors never dispatch handlers.\n clean.nativeHooks = stripped as PlatformOverride[\"nativeHooks\"];\n }\n out[id] = clean;\n }\n return out;\n}\n\n/**\n * Persist a connector's serializable metadata to `connectorDir(id)/connector.json`.\n * Handlers are NOT serialized — they are re-imported from `modulePath` at runtime.\n * The optional `scope` (the install scope the caller deployed under) is persisted\n * so the runtime entrypoints can recover it and stamp it onto the HostCtx/event.\n * Returns the absolute path of the written record.\n */\nexport function registerConnector(\n connector: ResolvedConnector,\n modulePath: string,\n scope?: InstallScope,\n): string {\n const meta: RegisteredMeta = {\n id: connector.id,\n displayName: connector.displayName,\n version: connector.version,\n modulePath: resolve(modulePath),\n telemetry: connector.telemetry,\n hookEvents: connector.hookEvents,\n hasServer: !!connector.server,\n server: connector.server ?? null,\n commands: connector.commands,\n skills: connector.skills,\n subagents: connector.subagents,\n memory: connector.memory,\n targets: connector.targets,\n platforms: serializablePlatforms(connector.platforms),\n // Persist the install scope when the caller supplied one (the installer\n // passes its install scope). Omitted from the record when undefined so an\n // ad-hoc register stays minimal and round-trips as \"no scope known\".\n ...(scope !== undefined ? { scope } : {}),\n };\n\n const dir = connectorDir(connector.id);\n ensureDir(dir);\n const outPath = join(dir, \"connector.json\");\n writeFileSync(outPath, `${JSON.stringify(meta, null, 2)}\\n`, \"utf8\");\n return outPath;\n}\n\n/**\n * Deregister a connector by removing its DATA-dir record directory\n * (`connectorDir(id)`) recursively. This is the inverse of {@link registerConnector}:\n * registerConnector writes `connectorDir(id)/connector.json`, but per-target\n * uninstall only strips host-native registrations — it never removes this record,\n * leaving an orphan behind. Best-effort + guarded: returns the directory path and\n * whether it existed before removal.\n */\nexport function deregisterConnector(id: string): {\n removed: boolean;\n path: string;\n} {\n const dir = connectorDir(id);\n const existed = existsSync(dir);\n if (existed) rmSync(dir, { recursive: true, force: true });\n return { removed: existed, path: dir };\n}\n\n/**\n * Read the registered metadata record for `id`, or null if not registered or\n * the record is unreadable/corrupt.\n */\nexport function readRegisteredMeta(id: string): RegisteredMeta | null {\n const recordPath = join(connectorDir(id), \"connector.json\");\n if (!existsSync(recordPath)) return null;\n try {\n return JSON.parse(readFileSync(recordPath, \"utf8\")) as RegisteredMeta;\n } catch {\n return null;\n }\n}\n\n/**\n * Load the LIVE ResolvedConnector (with hook handlers) for a registered id by\n * re-importing its source module. Throws a clear error when the connector is\n * not registered or its source module no longer resolves to it.\n */\nexport async function loadRegisteredConnector(\n id: string,\n): Promise<ResolvedConnector> {\n const meta = readRegisteredMeta(id);\n if (!meta) {\n throw new Error(\n `Connector \"${id}\" is not registered (no record at ${join(connectorDir(id), \"connector.json\")}). ` +\n `Run an install/register step first.`,\n );\n }\n if (!meta.modulePath || !existsSync(meta.modulePath)) {\n throw new Error(\n `Connector \"${id}\" record points at a missing module: ${meta.modulePath}`,\n );\n }\n const { connector } = await loadConnectorFromPath(meta.modulePath);\n return connector;\n}\n\n/**\n * Build a handler-less ResolvedConnector from stored metadata. Suitable for\n * inspection/doctor where live hook handlers are not needed (and where the\n * source module may even be gone). `hooks` is empty; `hookEvents` is preserved.\n */\nexport function connectorFromMeta(meta: RegisteredMeta): ResolvedConnector {\n return {\n id: meta.id,\n displayName: meta.displayName,\n version: meta.version,\n ...(meta.server ? { server: meta.server } : {}),\n hooks: {},\n hookEvents: meta.hookEvents ?? [],\n telemetry: meta.telemetry,\n commands: meta.commands ?? [],\n skills: meta.skills ?? [],\n subagents: meta.subagents ?? [],\n memory: meta.memory ?? [],\n // Actions carry live `run` handlers, so they are NOT serialized into the\n // record (like the statusline render). A handler-less meta-derived connector\n // gets [] — inspection/uninstall never dispatch action handlers, and the\n // BaseAdapter action default already tolerates an empty list.\n actions: [],\n platforms: meta.platforms ?? {},\n targets: meta.targets,\n };\n}\n\n/**\n * List every registered connector as a handler-less ResolvedConnector (read\n * from `connectorsDir()`). Used by doctor to health-check what is actually\n * installed, rather than guessing from the local working directory.\n */\nexport function listRegisteredConnectors(): ResolvedConnector[] {\n const dir = connectorsDir();\n if (!existsSync(dir)) return [];\n const out: ResolvedConnector[] = [];\n for (const entry of readdirSync(dir)) {\n const meta = readRegisteredMeta(entry);\n if (meta) out.push(connectorFromMeta(meta));\n }\n return out;\n}\n"],"mappings":"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","names":["connector"]}
|
|
@@ -73,28 +73,36 @@ function renderInstallResult(result, verb) {
|
|
|
73
73
|
return lines.join("\n");
|
|
74
74
|
}
|
|
75
75
|
var COMMANDS = {
|
|
76
|
-
detect: () => import("./detect-
|
|
77
|
-
install: () => import("./install-
|
|
78
|
-
uninstall: () => import("./uninstall-
|
|
76
|
+
detect: () => import("./detect-ZIIS55LD.js"),
|
|
77
|
+
install: () => import("./install-UDCBL7HP.js"),
|
|
78
|
+
uninstall: () => import("./uninstall-2LBLQVFA.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-
|
|
84
|
-
sync: () => import("./upgrade-
|
|
85
|
-
update: () => import("./upgrade-
|
|
86
|
-
package: () => import("./package-
|
|
87
|
-
doctor: () => import("./doctor-
|
|
88
|
-
status: () => import("./status-
|
|
89
|
-
telemetry: () => import("./telemetry-
|
|
90
|
-
usage: () => import("./usage-
|
|
91
|
-
leaderboard: () => import("./leaderboard-
|
|
92
|
-
hook: () => import("./hook-
|
|
93
|
-
|
|
83
|
+
upgrade: () => import("./upgrade-ZC2S7VRN.js"),
|
|
84
|
+
sync: () => import("./upgrade-ZC2S7VRN.js"),
|
|
85
|
+
update: () => import("./upgrade-ZC2S7VRN.js"),
|
|
86
|
+
package: () => import("./package-RMPN57YZ.js"),
|
|
87
|
+
doctor: () => import("./doctor-TJUGSQ5C.js"),
|
|
88
|
+
status: () => import("./status-KOSKCETC.js"),
|
|
89
|
+
telemetry: () => import("./telemetry-XIKUUGTQ.js"),
|
|
90
|
+
usage: () => import("./usage-E2A4O2CY.js"),
|
|
91
|
+
leaderboard: () => import("./leaderboard-TIBVONVT.js"),
|
|
92
|
+
hook: () => import("./hook-OU522ABV.js"),
|
|
93
|
+
// Internal (omitted from USAGE): the statusline (HUD) entrypoint a host's
|
|
94
|
+
// status line config points at. Fail-safe: always exits 0 with at most a
|
|
95
|
+
// rendered line. See cli/commands/statusline.ts.
|
|
96
|
+
statusline: () => import("./statusline-ZNTCL5YC.js"),
|
|
97
|
+
// Internal (omitted from USAGE): the user-invokable action entrypoint a future
|
|
98
|
+
// host affordance points at. USER-TRIGGERED: surfaces errors (exit 1 + stderr),
|
|
99
|
+
// unlike the fail-open hook / fail-safe statusline. See cli/commands/action.ts.
|
|
100
|
+
action: () => import("./action-PLZW5BGX.js"),
|
|
101
|
+
serve: () => import("./serve-D3GO36UT.js"),
|
|
94
102
|
// Hidden (omitted from USAGE): the opt-in host-native turn-usage entrypoint an
|
|
95
103
|
// AfterModel / PostInvocation hook points at. Always exits 0; records a
|
|
96
104
|
// distinct `model_turn` row. See cli/commands/usage-event.ts.
|
|
97
|
-
"usage-event": () => import("./usage-event-
|
|
105
|
+
"usage-event": () => import("./usage-event-JKMC4QC4.js")
|
|
98
106
|
};
|
|
99
107
|
var DEFAULT_PROGRAM_NAME = "agent-connector";
|
|
100
108
|
var COMMAND_USAGE = {
|
|
@@ -111,6 +119,8 @@ var COMMAND_USAGE = {
|
|
|
111
119
|
usage: "usage report|export|leaderboard [--by <dim>] [--since <dur>] [--platform <id>] [--format csv|json] [--out <file>] [--json]",
|
|
112
120
|
leaderboard: "leaderboard [--since <dur>] [--connector <id>] [--scope <slice>] [--json]",
|
|
113
121
|
hook: "hook <platform> <event> --connector <id> (internal \u2014 host hook configs point here)",
|
|
122
|
+
statusline: "statusline <platform> --connector <id> (internal \u2014 host status line configs point here)",
|
|
123
|
+
action: "action <platform> <actionId> --connector <id> (internal \u2014 host action affordances point here)",
|
|
114
124
|
serve: "serve --connector <id> [--scope user|project] [--host <platformId>] -- <command> [args...] (internal \u2014 host MCP entries point here)"
|
|
115
125
|
};
|
|
116
126
|
function buildUsage(programName) {
|
|
@@ -188,4 +198,4 @@ export {
|
|
|
188
198
|
renderInstallResult,
|
|
189
199
|
main
|
|
190
200
|
};
|
|
191
|
-
//# sourceMappingURL=chunk-
|
|
201
|
+
//# sourceMappingURL=chunk-KGXDYGNJ.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 // Internal (omitted from USAGE): the statusline (HUD) entrypoint a host's\n // status line config points at. Fail-safe: always exits 0 with at most a\n // rendered line. See cli/commands/statusline.ts.\n statusline: () => import(\"./commands/statusline.js\"),\n // Internal (omitted from USAGE): the user-invokable action entrypoint a future\n // host affordance points at. USER-TRIGGERED: surfaces errors (exit 1 + stderr),\n // unlike the fail-open hook / fail-safe statusline. See cli/commands/action.ts.\n action: () => import(\"./commands/action.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 statusline:\n \"statusline <platform> --connector <id> (internal — host status line configs point here)\",\n action:\n \"action <platform> <actionId> --connector <id> (internal — host action affordances 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":[]}
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
resolveSpawnCommand
|
|
4
|
-
} from "./chunk-MEH7GC7R.js";
|
|
5
2
|
|
|
6
3
|
// src/core/logger.ts
|
|
7
4
|
var ORDER = {
|
|
@@ -27,20 +24,7 @@ var log = {
|
|
|
27
24
|
debug: (...args) => emit("debug", args)
|
|
28
25
|
};
|
|
29
26
|
|
|
30
|
-
// src/core/spawn-child.ts
|
|
31
|
-
import { spawn } from "child_process";
|
|
32
|
-
function winQuoteArg(s) {
|
|
33
|
-
return `"${s.replace(/"/g, '""')}"`;
|
|
34
|
-
}
|
|
35
|
-
function spawnChild(command, args, options) {
|
|
36
|
-
const resolved = resolveSpawnCommand(command);
|
|
37
|
-
if (!resolved.needsShell) return spawn(resolved.file, args, options);
|
|
38
|
-
const line = [resolved.file, ...args].map(winQuoteArg).join(" ");
|
|
39
|
-
return spawn(line, { ...options, shell: true });
|
|
40
|
-
}
|
|
41
|
-
|
|
42
27
|
export {
|
|
43
|
-
log
|
|
44
|
-
spawnChild
|
|
28
|
+
log
|
|
45
29
|
};
|
|
46
|
-
//# sourceMappingURL=chunk-
|
|
30
|
+
//# sourceMappingURL=chunk-KHO5WNTP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/logger.ts"],"sourcesContent":["/**\n * core/logger — minimal leveled logger. Writes human output to stderr so stdout\n * stays clean for machine-readable payloads (hook replies, --json output).\n */\n\nexport type LogLevel = \"silent\" | \"error\" | \"warn\" | \"info\" | \"debug\";\n\nconst ORDER: Record<LogLevel, number> = {\n silent: 0,\n error: 1,\n warn: 2,\n info: 3,\n debug: 4,\n};\n\nfunction currentLevel(): LogLevel {\n const env = (process.env.AGENT_CONNECTOR_LOG ?? \"info\").toLowerCase();\n return (env in ORDER ? env : \"info\") as LogLevel;\n}\n\nfunction emit(level: Exclude<LogLevel, \"silent\">, args: unknown[]): void {\n if (ORDER[currentLevel()] < ORDER[level]) return;\n const prefix = { error: \"✗\", warn: \"!\", info: \"›\", debug: \"·\" }[level];\n // eslint-disable-next-line no-console\n console.error(prefix, ...args);\n}\n\nexport const log = {\n error: (...args: unknown[]) => emit(\"error\", args),\n warn: (...args: unknown[]) => emit(\"warn\", args),\n info: (...args: unknown[]) => emit(\"info\", args),\n debug: (...args: unknown[]) => emit(\"debug\", args),\n};\n"],"mappings":";;;AAOA,IAAM,QAAkC;AAAA,EACtC,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AACT;AAEA,SAAS,eAAyB;AAChC,QAAM,OAAO,QAAQ,IAAI,uBAAuB,QAAQ,YAAY;AACpE,SAAQ,OAAO,QAAQ,MAAM;AAC/B;AAEA,SAAS,KAAK,OAAoC,MAAuB;AACvE,MAAI,MAAM,aAAa,CAAC,IAAI,MAAM,KAAK,EAAG;AAC1C,QAAM,SAAS,EAAE,OAAO,UAAK,MAAM,KAAK,MAAM,UAAK,OAAO,OAAI,EAAE,KAAK;AAErE,UAAQ,MAAM,QAAQ,GAAG,IAAI;AAC/B;AAEO,IAAM,MAAM;AAAA,EACjB,OAAO,IAAI,SAAoB,KAAK,SAAS,IAAI;AAAA,EACjD,MAAM,IAAI,SAAoB,KAAK,QAAQ,IAAI;AAAA,EAC/C,MAAM,IAAI,SAAoB,KAAK,QAAQ,IAAI;AAAA,EAC/C,OAAO,IAAI,SAAoB,KAAK,SAAS,IAAI;AACnD;","names":[]}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-DBQMX75U.js";
|
|
5
5
|
import {
|
|
6
6
|
BaseAdapter
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-IW77FFNX.js";
|
|
8
8
|
import {
|
|
9
9
|
buildHomeBinHookCommand,
|
|
10
10
|
buildServeWrapperCommand,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
isHostNativeUsageEnabled,
|
|
14
14
|
isUsageEventCommand,
|
|
15
15
|
shouldWrapForTelemetry
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-BXGFUENQ.js";
|
|
17
17
|
|
|
18
18
|
// src/adapters/antigravity/index.ts
|
|
19
19
|
import { existsSync } from "fs";
|
|
@@ -710,4 +710,4 @@ export {
|
|
|
710
710
|
adapter,
|
|
711
711
|
antigravity_default
|
|
712
712
|
};
|
|
713
|
-
//# sourceMappingURL=chunk-
|
|
713
|
+
//# sourceMappingURL=chunk-LL4OBGRU.js.map
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
isConcreteSemver,
|
|
8
8
|
isPlaceholderVersion,
|
|
9
9
|
registryTransportType
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-ADTHT2FN.js";
|
|
11
11
|
import {
|
|
12
12
|
writeTomlString
|
|
13
13
|
} from "./chunk-OPXAP3AC.js";
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
buildHomeBinHookCommand,
|
|
21
21
|
buildServeWrapperCommand,
|
|
22
22
|
shouldWrapForTelemetry
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-BXGFUENQ.js";
|
|
24
24
|
import {
|
|
25
25
|
ensureDir,
|
|
26
26
|
homeBinPath
|
|
@@ -1040,4 +1040,4 @@ export {
|
|
|
1040
1040
|
packageConnectorAll,
|
|
1041
1041
|
installInstructions
|
|
1042
1042
|
};
|
|
1043
|
-
//# sourceMappingURL=chunk-
|
|
1043
|
+
//# sourceMappingURL=chunk-MAH6QQTO.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
readRegisteredMeta
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-KGJWE6A2.js";
|
|
5
5
|
import {
|
|
6
6
|
addLedgerOwner,
|
|
7
7
|
configPatchManualEdit,
|
|
@@ -17,14 +17,15 @@ import {
|
|
|
17
17
|
loadConfigPatchLedger,
|
|
18
18
|
removeLedgerOwner,
|
|
19
19
|
saveConfigPatchLedger
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-ADTHT2FN.js";
|
|
21
|
+
import "./chunk-3PFFTFCU.js";
|
|
21
22
|
import {
|
|
22
23
|
resolveEnvRefsDeep,
|
|
23
24
|
rewriteEnvRefs
|
|
24
25
|
} from "./chunk-DBQMX75U.js";
|
|
25
26
|
import {
|
|
26
27
|
BaseAdapter
|
|
27
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-IW77FFNX.js";
|
|
28
29
|
import {
|
|
29
30
|
renderCommandMd,
|
|
30
31
|
renderSkillMd,
|
|
@@ -32,10 +33,12 @@ import {
|
|
|
32
33
|
} from "./chunk-7L6ITC4T.js";
|
|
33
34
|
import {
|
|
34
35
|
buildHomeBinHookCommand,
|
|
36
|
+
buildHomeBinStatuslineCommand,
|
|
35
37
|
buildServeWrapperCommand,
|
|
36
38
|
isHomeBinHookCommand,
|
|
39
|
+
isHomeBinStatuslineCommand,
|
|
37
40
|
shouldWrapForTelemetry
|
|
38
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-BXGFUENQ.js";
|
|
39
42
|
import {
|
|
40
43
|
linesOutsideFences,
|
|
41
44
|
listManagedBlocks,
|
|
@@ -80,6 +83,7 @@ function toolResponseToString(value) {
|
|
|
80
83
|
// src/adapters/claude-code/index.ts
|
|
81
84
|
var HOST = "claude-code";
|
|
82
85
|
var MCP_ROOT_KEY = "mcpServers";
|
|
86
|
+
var STATUSLINE_KEY = "statusLine";
|
|
83
87
|
var CLAUDE_AGENTS_IMPORT_BLOCK_ID = "_shared/claude-agents-import";
|
|
84
88
|
var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
85
89
|
id = HOST;
|
|
@@ -112,6 +116,11 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
112
116
|
// (set-if-absent leaf keys in settings.json, refcounted ownership ledger,
|
|
113
117
|
// sensitive-key denylist — see SENSITIVE_KEY_RULES below).
|
|
114
118
|
supportsConfigPatch: true,
|
|
119
|
+
// Statusline surface: claude-code is the ONLY v1 host. installStatusline
|
|
120
|
+
// wires settings.json.statusLine = {type:"command", command:<home-bin
|
|
121
|
+
// statusline cmd>} through the SAME set-if-absent ownership ledger as
|
|
122
|
+
// configPatch (never clobbers a statusLine agent-connector does not own).
|
|
123
|
+
supportsStatusline: true,
|
|
115
124
|
transports: ["stdio", "http"],
|
|
116
125
|
// Content surfaces: Claude Code is the reference implementation for all three.
|
|
117
126
|
supportsCommands: true,
|
|
@@ -374,6 +383,20 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
374
383
|
{ platform: this.id, action: "skip", detail: "connector declares no configPatch entries" }
|
|
375
384
|
];
|
|
376
385
|
}
|
|
386
|
+
return this.applyConfigPatches(ctx, patches);
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* The shared set-if-absent / ownership-ledger apply loop behind BOTH
|
|
390
|
+
* {@link installConfigPatches} and {@link installStatusline}. Routing the
|
|
391
|
+
* statusline through the EXACT same path is how a connector's statusLine
|
|
392
|
+
* inherits the configPatch contract verbatim: never clobber a statusLine
|
|
393
|
+
* agent-connector does not own (skip-warn), record prior state + owner,
|
|
394
|
+
* refcounted across connectors, reversible by uninstallConfigPatches.
|
|
395
|
+
*/
|
|
396
|
+
applyConfigPatches(ctx, patches, opts = {}) {
|
|
397
|
+
const surfaceLabel = opts.surfaceLabel ?? "configPatch";
|
|
398
|
+
const internal = surfaceLabel !== "configPatch";
|
|
399
|
+
const { connector } = ctx;
|
|
377
400
|
const filePath = this.getPatchableConfigPath(ctx);
|
|
378
401
|
if (this.isPresentButUnparseable(filePath)) {
|
|
379
402
|
return [
|
|
@@ -409,14 +432,16 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
409
432
|
});
|
|
410
433
|
continue;
|
|
411
434
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
435
|
+
if (!internal) {
|
|
436
|
+
const namespace = configPatchNamespaceViolation(patch.key);
|
|
437
|
+
if (namespace) {
|
|
438
|
+
changes.push({
|
|
439
|
+
platform: this.id,
|
|
440
|
+
action: "warn",
|
|
441
|
+
detail: `configPatch refused: ${namespace}`
|
|
442
|
+
});
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
420
445
|
}
|
|
421
446
|
const sensitive = claudeSensitiveKeyViolation(patch.key);
|
|
422
447
|
if (sensitive) {
|
|
@@ -436,7 +461,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
436
461
|
platform: this.id,
|
|
437
462
|
action: "warn",
|
|
438
463
|
path: filePath,
|
|
439
|
-
detail:
|
|
464
|
+
detail: `${surfaceLabel} ${patch.key} skipped: "${leaf.atPath}" exists but is not an object \u2014 ${configPatchManualEdit(patch)}`
|
|
440
465
|
});
|
|
441
466
|
continue;
|
|
442
467
|
}
|
|
@@ -462,7 +487,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
462
487
|
platform: this.id,
|
|
463
488
|
action: "create",
|
|
464
489
|
path: filePath,
|
|
465
|
-
detail:
|
|
490
|
+
detail: `${surfaceLabel} ${patch.key}: <absent> \u2192 ${describeJsonValue(desired)} (${patch.reason})`
|
|
466
491
|
});
|
|
467
492
|
continue;
|
|
468
493
|
}
|
|
@@ -471,7 +496,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
471
496
|
platform: this.id,
|
|
472
497
|
action: "warn",
|
|
473
498
|
path: filePath,
|
|
474
|
-
detail:
|
|
499
|
+
detail: `${surfaceLabel} ${patch.key} skipped: already set to ${describeJsonValue(leaf.value)} (not created by agent-connector; desired ${describeJsonValue(desired)}) \u2014 ` + configPatchManualEdit(patch)
|
|
475
500
|
});
|
|
476
501
|
continue;
|
|
477
502
|
}
|
|
@@ -480,7 +505,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
480
505
|
platform: this.id,
|
|
481
506
|
action: "warn",
|
|
482
507
|
path: filePath,
|
|
483
|
-
detail:
|
|
508
|
+
detail: `${surfaceLabel} ${patch.key}: value changed since install (current ${describeJsonValue(leaf.value)}, wrote ${describeJsonValue(entry.writtenValue)}); leaving in place \u2014 ${configPatchManualEdit(patch)}`
|
|
484
509
|
});
|
|
485
510
|
continue;
|
|
486
511
|
}
|
|
@@ -492,14 +517,14 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
492
517
|
platform: this.id,
|
|
493
518
|
action: "skip",
|
|
494
519
|
path: filePath,
|
|
495
|
-
detail:
|
|
520
|
+
detail: `${surfaceLabel} ${patch.key} already installed; registered as co-owner (co-owned with ${owners.join(", ")})`
|
|
496
521
|
});
|
|
497
522
|
} else {
|
|
498
523
|
changes.push({
|
|
499
524
|
platform: this.id,
|
|
500
525
|
action: "skip",
|
|
501
526
|
path: filePath,
|
|
502
|
-
detail:
|
|
527
|
+
detail: `${surfaceLabel} ${patch.key} already installed`
|
|
503
528
|
});
|
|
504
529
|
}
|
|
505
530
|
continue;
|
|
@@ -508,7 +533,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
508
533
|
platform: this.id,
|
|
509
534
|
action: "warn",
|
|
510
535
|
path: filePath,
|
|
511
|
-
detail:
|
|
536
|
+
detail: `${surfaceLabel} ${patch.key} skipped: already owned by ${entry.owners.map((o) => o.connectorId).join(", ")} with a different value (current ${describeJsonValue(leaf.value)}, desired ${describeJsonValue(desired)}) \u2014 ` + configPatchManualEdit(patch)
|
|
512
537
|
});
|
|
513
538
|
}
|
|
514
539
|
if (fileMutated) this.writeJson(filePath, settings, ctx.dryRun);
|
|
@@ -518,7 +543,9 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
518
543
|
uninstallConfigPatches(ctx) {
|
|
519
544
|
const connectorId = ctx.connector.id;
|
|
520
545
|
const ledger = loadConfigPatchLedger(ctx.dataRoot);
|
|
521
|
-
const owned = ledgerEntriesOwnedBy(ledger, HOST, connectorId)
|
|
546
|
+
const owned = ledgerEntriesOwnedBy(ledger, HOST, connectorId).filter(
|
|
547
|
+
(e) => e.key !== STATUSLINE_KEY
|
|
548
|
+
);
|
|
522
549
|
const declared = ctx.connector.platforms[HOST]?.configPatch ?? [];
|
|
523
550
|
const changes = [];
|
|
524
551
|
const ownedKeys = new Set(owned.map((e) => e.key));
|
|
@@ -532,6 +559,20 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
532
559
|
}
|
|
533
560
|
}
|
|
534
561
|
if (owned.length === 0) return changes;
|
|
562
|
+
changes.push(...this.releaseOwnedConfigPatches(ctx, ledger, owned));
|
|
563
|
+
return changes;
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* The shared last-owner-verified release loop behind BOTH
|
|
567
|
+
* {@link uninstallConfigPatches} and {@link uninstallStatusline}: for each
|
|
568
|
+
* already-selected owned ledger entry, drop this connector's ownership and
|
|
569
|
+
* remove the key ONLY when last-owner ∧ value-unchanged ∧ prior-absent (else
|
|
570
|
+
* skip-warn + leave the key). Saves the ledger when it mutated.
|
|
571
|
+
*/
|
|
572
|
+
releaseOwnedConfigPatches(ctx, ledger, owned, opts = {}) {
|
|
573
|
+
const surfaceLabel = opts.surfaceLabel ?? "configPatch";
|
|
574
|
+
const connectorId = ctx.connector.id;
|
|
575
|
+
const changes = [];
|
|
535
576
|
let ledgerMutated = false;
|
|
536
577
|
const backedUp = /* @__PURE__ */ new Set();
|
|
537
578
|
const byFile = /* @__PURE__ */ new Map();
|
|
@@ -552,7 +593,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
552
593
|
platform: this.id,
|
|
553
594
|
action: "skip",
|
|
554
595
|
path: filePath,
|
|
555
|
-
detail:
|
|
596
|
+
detail: `${surfaceLabel} ${entry.key} retained: still owned by ${entry.owners.map((o) => o.connectorId).join(", ")}`
|
|
556
597
|
});
|
|
557
598
|
continue;
|
|
558
599
|
}
|
|
@@ -562,7 +603,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
562
603
|
platform: this.id,
|
|
563
604
|
action: "warn",
|
|
564
605
|
path: filePath,
|
|
565
|
-
detail:
|
|
606
|
+
detail: `${surfaceLabel} ${entry.key}: ${filePath} is not parseable; key left in place (ownership released)`
|
|
566
607
|
});
|
|
567
608
|
continue;
|
|
568
609
|
}
|
|
@@ -571,7 +612,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
571
612
|
platform: this.id,
|
|
572
613
|
action: "skip",
|
|
573
614
|
path: filePath,
|
|
574
|
-
detail:
|
|
615
|
+
detail: `${surfaceLabel} ${entry.key} already absent (no settings file); ownership record dropped`
|
|
575
616
|
});
|
|
576
617
|
continue;
|
|
577
618
|
}
|
|
@@ -581,7 +622,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
581
622
|
platform: this.id,
|
|
582
623
|
action: "skip",
|
|
583
624
|
path: filePath,
|
|
584
|
-
detail:
|
|
625
|
+
detail: `${surfaceLabel} ${entry.key} already absent; ownership record dropped`
|
|
585
626
|
});
|
|
586
627
|
continue;
|
|
587
628
|
}
|
|
@@ -590,7 +631,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
590
631
|
platform: this.id,
|
|
591
632
|
action: "warn",
|
|
592
633
|
path: filePath,
|
|
593
|
-
detail:
|
|
634
|
+
detail: `${surfaceLabel} ${entry.key}: value changed since install (current ${describeJsonValue(leaf.value)}, wrote ${describeJsonValue(entry.writtenValue)}); left in place`
|
|
594
635
|
});
|
|
595
636
|
continue;
|
|
596
637
|
}
|
|
@@ -612,7 +653,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
612
653
|
platform: this.id,
|
|
613
654
|
action: "remove",
|
|
614
655
|
path: filePath,
|
|
615
|
-
detail:
|
|
656
|
+
detail: `${surfaceLabel} ${entry.key} removed (was ${describeJsonValue(entry.writtenValue)})`
|
|
616
657
|
});
|
|
617
658
|
}
|
|
618
659
|
if (fileMutated && settings) this.writeJson(filePath, settings, ctx.dryRun);
|
|
@@ -620,6 +661,91 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
620
661
|
if (ledgerMutated && !ctx.dryRun) saveConfigPatchLedger(ctx.dataRoot, ledger);
|
|
621
662
|
return changes;
|
|
622
663
|
}
|
|
664
|
+
// ── Statusline surface (a HUD/status line) ────────────────────────────────
|
|
665
|
+
// Wires settings.json.statusLine = { type:"command", command:<home-bin
|
|
666
|
+
// statusline cmd> } through the SAME ownership ledger as configPatch: a
|
|
667
|
+
// synthetic ConfigPatchDef routed through applyConfigPatches, so the statusLine
|
|
668
|
+
// inherits the full set-if-absent contract verbatim — never clobbers a
|
|
669
|
+
// statusLine agent-connector does not own (skip-warn), records prior state +
|
|
670
|
+
// owner, reversible. The home-bin command makes the host exec
|
|
671
|
+
// `<homeBin> statusline claude-code --connector <id>` for every status refresh,
|
|
672
|
+
// which re-imports the connector module and renders the line (runtime/
|
|
673
|
+
// statusline-entrypoint). No telemetry in v1.
|
|
674
|
+
/** The synthetic statusLine configPatch this connector would write. */
|
|
675
|
+
statuslineConfigPatch(ctx) {
|
|
676
|
+
const command = buildHomeBinStatuslineCommand(ctx.homeBinPath, HOST, ctx.connector.id);
|
|
677
|
+
return {
|
|
678
|
+
key: STATUSLINE_KEY,
|
|
679
|
+
value: { type: "command", command },
|
|
680
|
+
reason: "agent-connector statusline surface"
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
installStatusline(ctx) {
|
|
684
|
+
const { connector } = ctx;
|
|
685
|
+
if (connector.statusline == null) {
|
|
686
|
+
return [{ platform: this.id, action: "skip", detail: "connector declares no statusline" }];
|
|
687
|
+
}
|
|
688
|
+
if (connector.platforms[HOST]?.statusline === false) {
|
|
689
|
+
return [{ platform: this.id, action: "skip", detail: "statusline disabled for claude-code" }];
|
|
690
|
+
}
|
|
691
|
+
return this.applyConfigPatches(ctx, [this.statuslineConfigPatch(ctx)], {
|
|
692
|
+
surfaceLabel: "statusline"
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
uninstallStatusline(ctx) {
|
|
696
|
+
const ledger = loadConfigPatchLedger(ctx.dataRoot);
|
|
697
|
+
const owned = ledgerEntriesOwnedBy(ledger, HOST, ctx.connector.id).filter(
|
|
698
|
+
(e) => e.key === STATUSLINE_KEY
|
|
699
|
+
);
|
|
700
|
+
if (owned.length === 0) {
|
|
701
|
+
return [
|
|
702
|
+
{
|
|
703
|
+
platform: this.id,
|
|
704
|
+
action: "skip",
|
|
705
|
+
detail: "statusline: no ownership recorded; left untouched"
|
|
706
|
+
}
|
|
707
|
+
];
|
|
708
|
+
}
|
|
709
|
+
return this.releaseOwnedConfigPatches(ctx, ledger, owned, {
|
|
710
|
+
surfaceLabel: "statusline"
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* Parse Claude Code's statusLine stdin JSON into the normalized
|
|
715
|
+
* {@link StatuslineContext}. Claude pipes a JSON object to the statusLine
|
|
716
|
+
* command on stdin (model, workspace, cost, etc.); fields the payload omits
|
|
717
|
+
* stay undefined. `raw` keeps the verbatim payload (incl. `version`).
|
|
718
|
+
*/
|
|
719
|
+
parseStatusInput(raw) {
|
|
720
|
+
const input = raw ?? {};
|
|
721
|
+
const model = {};
|
|
722
|
+
if (typeof input.model?.id === "string") model.id = input.model.id;
|
|
723
|
+
if (typeof input.model?.display_name === "string") {
|
|
724
|
+
model.displayName = input.model.display_name;
|
|
725
|
+
}
|
|
726
|
+
const cwd = typeof input.cwd === "string" ? input.cwd : typeof input.workspace?.current_dir === "string" ? input.workspace.current_dir : void 0;
|
|
727
|
+
const ctx = {
|
|
728
|
+
host: HOST,
|
|
729
|
+
capabilities: this.capabilities,
|
|
730
|
+
raw
|
|
731
|
+
};
|
|
732
|
+
if (typeof input.session_id === "string" && input.session_id !== "") {
|
|
733
|
+
ctx.sessionId = input.session_id;
|
|
734
|
+
}
|
|
735
|
+
if (cwd !== void 0) ctx.cwd = cwd;
|
|
736
|
+
if (model.id !== void 0 || model.displayName !== void 0) ctx.model = model;
|
|
737
|
+
if (typeof input.cost?.total_cost_usd === "number") {
|
|
738
|
+
ctx.cost = { totalUsd: input.cost.total_cost_usd };
|
|
739
|
+
}
|
|
740
|
+
if (typeof input.transcript_path === "string") {
|
|
741
|
+
ctx.transcriptPath = input.transcript_path;
|
|
742
|
+
}
|
|
743
|
+
return ctx;
|
|
744
|
+
}
|
|
745
|
+
/** Format the rendered status line into Claude's native reply: stdout = line, exit 0. */
|
|
746
|
+
formatStatusOutput(rendered) {
|
|
747
|
+
return { exitCode: 0, stdout: rendered };
|
|
748
|
+
}
|
|
623
749
|
/**
|
|
624
750
|
* Back up ONE exact file (the ledger-recorded patch target, which may belong
|
|
625
751
|
* to a different scope than the current ctx) into the standard backups dir.
|
|
@@ -651,7 +777,9 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
651
777
|
const results = [];
|
|
652
778
|
const ledger = loadConfigPatchLedger(ctx.dataRoot);
|
|
653
779
|
const connectorId = ctx.connector.id;
|
|
654
|
-
const platformEntries = ledger.entries.filter(
|
|
780
|
+
const platformEntries = ledger.entries.filter(
|
|
781
|
+
(e) => e.platform === this.id && e.key !== STATUSLINE_KEY
|
|
782
|
+
);
|
|
655
783
|
for (const entry of platformEntries) {
|
|
656
784
|
const ownedByThis = entry.owners.some((o) => o.connectorId === connectorId);
|
|
657
785
|
if (!ownedByThis) {
|
|
@@ -1144,6 +1272,30 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
|
|
|
1144
1272
|
check: () => existsSync(p) ? { status: "OK", detail: p } : { status: "FAIL", detail: `not found: ${p}` }
|
|
1145
1273
|
});
|
|
1146
1274
|
}
|
|
1275
|
+
const statuslineLedgerOwned = ledgerEntriesOwnedBy(
|
|
1276
|
+
loadConfigPatchLedger(ctx.dataRoot),
|
|
1277
|
+
HOST,
|
|
1278
|
+
connectorId
|
|
1279
|
+
).some((e) => e.key === STATUSLINE_KEY);
|
|
1280
|
+
if ((ctx.connector.statusline != null || statuslineLedgerOwned) && ctx.connector.platforms[HOST]?.statusline !== false) {
|
|
1281
|
+
checks.push({
|
|
1282
|
+
name: `${this.name}: statusline wired`,
|
|
1283
|
+
check: () => {
|
|
1284
|
+
const settings = this.readJson(settingsPath);
|
|
1285
|
+
const command = settings?.statusLine?.command;
|
|
1286
|
+
if (command === void 0) {
|
|
1287
|
+
return { status: "FAIL", detail: `statusLine not set in ${settingsPath}` };
|
|
1288
|
+
}
|
|
1289
|
+
if (typeof command === "string" && isHomeBinStatuslineCommand(command, homeBin, connectorId)) {
|
|
1290
|
+
return { status: "OK", detail: "statusLine command present" };
|
|
1291
|
+
}
|
|
1292
|
+
return {
|
|
1293
|
+
status: "FAIL",
|
|
1294
|
+
detail: `statusLine in ${settingsPath} is not agent-connector's (left untouched)`
|
|
1295
|
+
};
|
|
1296
|
+
}
|
|
1297
|
+
});
|
|
1298
|
+
}
|
|
1147
1299
|
return checks;
|
|
1148
1300
|
}
|
|
1149
1301
|
// ── Runtime: parse Claude stdin JSON → normalized event ──────────────────
|
|
@@ -1429,4 +1581,4 @@ export {
|
|
|
1429
1581
|
claudeSensitiveKeyViolation,
|
|
1430
1582
|
claude_code_default as default
|
|
1431
1583
|
};
|
|
1432
|
-
//# sourceMappingURL=claude-code-
|
|
1584
|
+
//# sourceMappingURL=claude-code-MLWS7CW6.js.map
|