@ken-jo/agent-connector 0.3.1 → 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.
Files changed (163) hide show
  1. package/README.md +178 -14
  2. package/dist/action-PLZW5BGX.js +54 -0
  3. package/dist/action-PLZW5BGX.js.map +1 -0
  4. package/dist/{amp-YGV66GJT.js → amp-B524U6LO.js} +81 -5
  5. package/dist/amp-B524U6LO.js.map +1 -0
  6. package/dist/{antigravity-7IBYFO6P.js → antigravity-ANDKF3K7.js} +4 -4
  7. package/dist/{antigravity-cli-JEOUP2VN.js → antigravity-cli-LLRPDDOT.js} +4 -4
  8. package/dist/chunk-22Y24V7O.js +21 -0
  9. package/dist/chunk-22Y24V7O.js.map +1 -0
  10. package/dist/chunk-3PFFTFCU.js +190 -0
  11. package/dist/chunk-3PFFTFCU.js.map +1 -0
  12. package/dist/{chunk-SCVBYSF7.js → chunk-6XHB6BE3.js} +1 -1
  13. package/dist/chunk-76FUSVIA.js +43 -0
  14. package/dist/chunk-76FUSVIA.js.map +1 -0
  15. package/dist/{chunk-GSGDG2BV.js → chunk-ADTHT2FN.js} +109 -16
  16. package/dist/chunk-ADTHT2FN.js.map +1 -0
  17. package/dist/{chunk-ZAM4M7LI.js → chunk-BHUCB6LY.js} +135 -296
  18. package/dist/chunk-BHUCB6LY.js.map +1 -0
  19. package/dist/{chunk-MEH7GC7R.js → chunk-BXGFUENQ.js} +20 -3
  20. package/dist/chunk-BXGFUENQ.js.map +1 -0
  21. package/dist/chunk-CIRDOY2V.js +351 -0
  22. package/dist/chunk-CIRDOY2V.js.map +1 -0
  23. package/dist/{chunk-KMAKDD3Z.js → chunk-G3ER4SY5.js} +37 -12
  24. package/dist/chunk-G3ER4SY5.js.map +1 -0
  25. package/dist/{chunk-PD4VFEBY.js → chunk-IW77FFNX.js} +39 -1
  26. package/dist/chunk-IW77FFNX.js.map +1 -0
  27. package/dist/chunk-J3D5W5T2.js +83 -0
  28. package/dist/chunk-J3D5W5T2.js.map +1 -0
  29. package/dist/{openclaw-UZ5BMCGQ.js → chunk-KGGBNKI4.js} +125 -33
  30. package/dist/chunk-KGGBNKI4.js.map +1 -0
  31. package/dist/{chunk-3JCRUROU.js → chunk-KGJWE6A2.js} +13 -4
  32. package/dist/chunk-KGJWE6A2.js.map +1 -0
  33. package/dist/{chunk-3RBLIHPZ.js → chunk-KGXDYGNJ.js} +26 -16
  34. package/dist/chunk-KGXDYGNJ.js.map +1 -0
  35. package/dist/{chunk-KVAAFYRR.js → chunk-KHO5WNTP.js} +2 -18
  36. package/dist/chunk-KHO5WNTP.js.map +1 -0
  37. package/dist/{chunk-KQSNDFBN.js → chunk-LL4OBGRU.js} +3 -3
  38. package/dist/{chunk-WNREHWKL.js → chunk-MAH6QQTO.js} +3 -3
  39. package/dist/{claude-code-4275HQU4.js → claude-code-MLWS7CW6.js} +180 -28
  40. package/dist/claude-code-MLWS7CW6.js.map +1 -0
  41. package/dist/cli/sdk.js +4 -3
  42. package/dist/cli/sdk.js.map +1 -1
  43. package/dist/cli.js +1 -1
  44. package/dist/{codebuff-LE3KBZGM.js → codebuff-SH2S3QAN.js} +102 -5
  45. package/dist/codebuff-SH2S3QAN.js.map +1 -0
  46. package/dist/{codex-4BY2ZJIW.js → codex-BXA4FIF4.js} +3 -3
  47. package/dist/{copilot-cli-IPISKO3V.js → copilot-cli-ROIBTTDT.js} +3 -3
  48. package/dist/{crush-X3E25EQG.js → crush-QLEFLHUC.js} +3 -3
  49. package/dist/{cursor-UH3W622V.js → cursor-ASJPWZ4R.js} +6 -3
  50. package/dist/cursor-ASJPWZ4R.js.map +1 -0
  51. package/dist/{detect-U3E7NVNW.js → detect-ZIIS55LD.js} +4 -3
  52. package/dist/{detect-U3E7NVNW.js.map → detect-ZIIS55LD.js.map} +1 -1
  53. package/dist/{doctor-DZTWED4O.js → doctor-TJUGSQ5C.js} +16 -12
  54. package/dist/doctor-TJUGSQ5C.js.map +1 -0
  55. package/dist/{droid-T5VBRXZF.js → droid-NCSS3B5Y.js} +170 -4
  56. package/dist/droid-NCSS3B5Y.js.map +1 -0
  57. package/dist/{gemini-cli-ZSUK55UA.js → gemini-cli-SLVWLXJW.js} +3 -3
  58. package/dist/{goose-M3RR3CZG.js → goose-PBA7KTE5.js} +100 -5
  59. package/dist/goose-PBA7KTE5.js.map +1 -0
  60. package/dist/{hermes-CUNKIAR5.js → hermes-ONDCECP2.js} +3 -3
  61. package/dist/{hook-EVY7LOUQ.js → hook-OU522ABV.js} +12 -9
  62. package/dist/{hook-EVY7LOUQ.js.map → hook-OU522ABV.js.map} +1 -1
  63. package/dist/index.d.ts +71 -3
  64. package/dist/index.js +22 -3
  65. package/dist/{install-OWAS5UIE.js → install-UDCBL7HP.js} +11 -9
  66. package/dist/{install-OWAS5UIE.js.map → install-UDCBL7HP.js.map} +1 -1
  67. package/dist/introspect-DuZSPSHB.d.ts +53 -0
  68. package/dist/{jetbrains-copilot-C3HDGGML.js → jetbrains-copilot-YABZ3HFA.js} +3 -3
  69. package/dist/{kilo-PKAJCWPX.js → kilo-F3ZDZKCT.js} +3 -3
  70. package/dist/{kilo-cli-QWUVXG2O.js → kilo-cli-3HWPWBY4.js} +3 -3
  71. package/dist/{kimi-EVD7YKXS.js → kimi-NV72FVAO.js} +3 -3
  72. package/dist/{kiro-UQRY6EIO.js → kiro-C5W6AGDR.js} +3 -3
  73. package/dist/{leaderboard-CSWHI4UY.js → leaderboard-TIBVONVT.js} +3 -3
  74. package/dist/mimo-code-IMM5YM3M.js +754 -0
  75. package/dist/mimo-code-IMM5YM3M.js.map +1 -0
  76. package/dist/{mux-5CI5FP2W.js → mux-DSSH4AFS.js} +3 -3
  77. package/dist/nemoclaw-3EVNKD3I.js +58 -0
  78. package/dist/nemoclaw-3EVNKD3I.js.map +1 -0
  79. package/dist/{omp-AXA7XY22.js → omp-Z6FRNDPN.js} +3 -3
  80. package/dist/openclaw-7G437NT7.js +18 -0
  81. package/dist/openclaw-7G437NT7.js.map +1 -0
  82. package/dist/{opencode-NZBRLJN3.js → opencode-Q6KBSAKW.js} +3 -3
  83. package/dist/{package-WFOS4QVU.js → package-RMPN57YZ.js} +7 -6
  84. package/dist/{package-WFOS4QVU.js.map → package-RMPN57YZ.js.map} +1 -1
  85. package/dist/{pi-WMTUX6ES.js → pi-LZT6WWAZ.js} +2 -2
  86. package/dist/{qwen-code-MRRIUQ3P.js → qwen-code-WQBKRPWJ.js} +3 -3
  87. package/dist/{roo-code-NI5UU6JB.js → roo-code-GWSNU3OW.js} +137 -4
  88. package/dist/roo-code-GWSNU3OW.js.map +1 -0
  89. package/dist/runtime/index.d.ts +96 -2
  90. package/dist/runtime/index.js +18 -10
  91. package/dist/sdk/index.d.ts +52 -0
  92. package/dist/sdk/index.js +81 -0
  93. package/dist/sdk/index.js.map +1 -0
  94. package/dist/sdk/test.d.ts +74 -0
  95. package/dist/sdk/test.js +291 -0
  96. package/dist/sdk/test.js.map +1 -0
  97. package/dist/{serve-3C2VFPAY.js → serve-D3GO36UT.js} +12 -9
  98. package/dist/{serve-3C2VFPAY.js.map → serve-D3GO36UT.js.map} +1 -1
  99. package/dist/{status-MKQYX5MW.js → status-KOSKCETC.js} +9 -7
  100. package/dist/{status-MKQYX5MW.js.map → status-KOSKCETC.js.map} +1 -1
  101. package/dist/statusline-ZNTCL5YC.js +59 -0
  102. package/dist/statusline-ZNTCL5YC.js.map +1 -0
  103. package/dist/{telemetry-3DN6XGYB.js → telemetry-XIKUUGTQ.js} +5 -4
  104. package/dist/{telemetry-3DN6XGYB.js.map → telemetry-XIKUUGTQ.js.map} +1 -1
  105. package/dist/{trae-CQC72RHH.js → trae-NWT3TMSZ.js} +99 -5
  106. package/dist/trae-NWT3TMSZ.js.map +1 -0
  107. package/dist/{types-CNigfEuR.d.ts → types-BEKsAium.d.ts} +268 -6
  108. package/dist/{uninstall-WG6PFWF3.js → uninstall-2LBLQVFA.js} +11 -9
  109. package/dist/{uninstall-WG6PFWF3.js.map → uninstall-2LBLQVFA.js.map} +1 -1
  110. package/dist/{upgrade-32NC2RKI.js → upgrade-ZC2S7VRN.js} +11 -9
  111. package/dist/{upgrade-32NC2RKI.js.map → upgrade-ZC2S7VRN.js.map} +1 -1
  112. package/dist/{usage-CJOM2WQM.js → usage-E2A4O2CY.js} +3 -3
  113. package/dist/{usage-event-472X3DOY.js → usage-event-JKMC4QC4.js} +11 -8
  114. package/dist/{usage-event-472X3DOY.js.map → usage-event-JKMC4QC4.js.map} +1 -1
  115. package/dist/{vscode-copilot-4RVRTCKV.js → vscode-copilot-ALV45XF6.js} +3 -3
  116. package/dist/{warp-X6MB67NT.js → warp-H6IX4U3J.js} +3 -3
  117. package/dist/{zed-NTCYW4V2.js → zed-RH34TNSW.js} +3 -3
  118. package/package.json +9 -1
  119. package/dist/amp-YGV66GJT.js.map +0 -1
  120. package/dist/chunk-3JCRUROU.js.map +0 -1
  121. package/dist/chunk-3RBLIHPZ.js.map +0 -1
  122. package/dist/chunk-GSGDG2BV.js.map +0 -1
  123. package/dist/chunk-KMAKDD3Z.js.map +0 -1
  124. package/dist/chunk-KVAAFYRR.js.map +0 -1
  125. package/dist/chunk-MEH7GC7R.js.map +0 -1
  126. package/dist/chunk-NJU275US.js +0 -238
  127. package/dist/chunk-NJU275US.js.map +0 -1
  128. package/dist/chunk-PD4VFEBY.js.map +0 -1
  129. package/dist/chunk-ZAM4M7LI.js.map +0 -1
  130. package/dist/claude-code-4275HQU4.js.map +0 -1
  131. package/dist/codebuff-LE3KBZGM.js.map +0 -1
  132. package/dist/cursor-UH3W622V.js.map +0 -1
  133. package/dist/doctor-DZTWED4O.js.map +0 -1
  134. package/dist/droid-T5VBRXZF.js.map +0 -1
  135. package/dist/goose-M3RR3CZG.js.map +0 -1
  136. package/dist/openclaw-UZ5BMCGQ.js.map +0 -1
  137. package/dist/roo-code-NI5UU6JB.js.map +0 -1
  138. package/dist/trae-CQC72RHH.js.map +0 -1
  139. /package/dist/{antigravity-7IBYFO6P.js.map → antigravity-ANDKF3K7.js.map} +0 -0
  140. /package/dist/{antigravity-cli-JEOUP2VN.js.map → antigravity-cli-LLRPDDOT.js.map} +0 -0
  141. /package/dist/{chunk-SCVBYSF7.js.map → chunk-6XHB6BE3.js.map} +0 -0
  142. /package/dist/{chunk-KQSNDFBN.js.map → chunk-LL4OBGRU.js.map} +0 -0
  143. /package/dist/{chunk-WNREHWKL.js.map → chunk-MAH6QQTO.js.map} +0 -0
  144. /package/dist/{codex-4BY2ZJIW.js.map → codex-BXA4FIF4.js.map} +0 -0
  145. /package/dist/{copilot-cli-IPISKO3V.js.map → copilot-cli-ROIBTTDT.js.map} +0 -0
  146. /package/dist/{crush-X3E25EQG.js.map → crush-QLEFLHUC.js.map} +0 -0
  147. /package/dist/{gemini-cli-ZSUK55UA.js.map → gemini-cli-SLVWLXJW.js.map} +0 -0
  148. /package/dist/{hermes-CUNKIAR5.js.map → hermes-ONDCECP2.js.map} +0 -0
  149. /package/dist/{jetbrains-copilot-C3HDGGML.js.map → jetbrains-copilot-YABZ3HFA.js.map} +0 -0
  150. /package/dist/{kilo-PKAJCWPX.js.map → kilo-F3ZDZKCT.js.map} +0 -0
  151. /package/dist/{kilo-cli-QWUVXG2O.js.map → kilo-cli-3HWPWBY4.js.map} +0 -0
  152. /package/dist/{kimi-EVD7YKXS.js.map → kimi-NV72FVAO.js.map} +0 -0
  153. /package/dist/{kiro-UQRY6EIO.js.map → kiro-C5W6AGDR.js.map} +0 -0
  154. /package/dist/{leaderboard-CSWHI4UY.js.map → leaderboard-TIBVONVT.js.map} +0 -0
  155. /package/dist/{mux-5CI5FP2W.js.map → mux-DSSH4AFS.js.map} +0 -0
  156. /package/dist/{omp-AXA7XY22.js.map → omp-Z6FRNDPN.js.map} +0 -0
  157. /package/dist/{opencode-NZBRLJN3.js.map → opencode-Q6KBSAKW.js.map} +0 -0
  158. /package/dist/{pi-WMTUX6ES.js.map → pi-LZT6WWAZ.js.map} +0 -0
  159. /package/dist/{qwen-code-MRRIUQ3P.js.map → qwen-code-WQBKRPWJ.js.map} +0 -0
  160. /package/dist/{usage-CJOM2WQM.js.map → usage-E2A4O2CY.js.map} +0 -0
  161. /package/dist/{vscode-copilot-4RVRTCKV.js.map → vscode-copilot-ALV45XF6.js.map} +0 -0
  162. /package/dist/{warp-X6MB67NT.js.map → warp-H6IX4U3J.js.map} +0 -0
  163. /package/dist/{zed-NTCYW4V2.js.map → zed-RH34TNSW.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/claude-code/index.ts","../src/adapters/claude-code/wire.ts"],"sourcesContent":["/**\n * adapters/claude-code — Claude Code platform adapter for agent-connector.\n *\n * Generalized from context-mode's proven 15-platform Claude adapter: the served\n * identity is now `ctx.connector` (not a hardcoded \"context-mode\"), and every\n * hook command points at the single stable home binary\n * (`buildHomeBinHookCommand`) so one framework update propagates everywhere.\n *\n * Claude Code is a json-stdio host:\n * - MCP servers: user scope → ~/.claude.json (\"mcpServers\"); project scope →\n * <projectDir>/.mcp.json (\"mcpServers\").\n * - Hooks: <configDir>/settings.json under \"hooks\", keyed by event name, each\n * value an array of { matcher, hooks:[{ type:\"command\", command }] }.\n * - Reply: a `hookSpecificOutput` object (allow|deny|ask + reason,\n * additionalContext, updatedInput) on stdout with exit 0.\n */\n\nimport { copyFileSync, existsSync, lstatSync, readFileSync, realpathSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, dirname, join } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport type { Adapter, HookReply, InstallContext, MemoryTarget, NormalizedEvent } from \"../spi.js\";\nimport type {\n ChangeRecord,\n CommandDef,\n ConfigPatchDef,\n DetectedPlatform,\n DiagnosticResult,\n HealthCheck,\n HookEventName,\n HookParadigm,\n HookResponse,\n JsonValue,\n NotificationEvent,\n PermissionRequestEvent,\n PlatformCapabilities,\n PlatformId,\n PostToolUseEvent,\n PostToolUseFailureEvent,\n PreCompactEvent,\n PreToolUseEvent,\n SessionEndEvent,\n SessionStartEvent,\n ServerDef,\n SkillDef,\n StatuslineContext,\n StopEvent,\n SubagentDef,\n SubagentStartEvent,\n SubagentStopEvent,\n Transport,\n UserPromptSubmitEvent,\n} from \"../../core/types.js\";\nimport { resolveEnvRefsDeep, rewriteEnvRefs } from \"../../core/interpolate.js\";\nimport {\n buildHomeBinHookCommand,\n buildHomeBinStatuslineCommand,\n buildServeWrapperCommand,\n isHomeBinHookCommand,\n isHomeBinStatuslineCommand,\n shouldWrapForTelemetry,\n} from \"../../core/spawn.js\";\nimport {\n type ConfigPatchLedgerEntry,\n addLedgerOwner,\n configPatchManualEdit,\n configPatchNamespaceViolation,\n createLedgerEntry,\n describeJsonValue,\n dropLedgerEntry,\n findLedgerEntry,\n hashJsonValue,\n isValidConfigPatchKey,\n jsonDeepEquals,\n ledgerEntriesOwnedBy,\n loadConfigPatchLedger,\n removeLedgerOwner,\n saveConfigPatchLedger,\n} from \"../../core/config-patch-ledger.js\";\nimport { readRegisteredMeta } from \"../../core/load-connector.js\";\nimport {\n linesOutsideFences,\n listManagedBlocks,\n loadMemoryLedger,\n recordMemoryTarget,\n removeBlocksFromText,\n removeManagedBlocksFile,\n saveMemoryLedger,\n upsertManagedBlockFile,\n} from \"../../core/managed-block.js\";\nimport { backupsDir, ensureDir } from \"../../core/paths.js\";\nimport {\n type ClaudeHookEvent,\n type ClaudeWireInput,\n extractSessionId,\n toolResponseToString,\n} from \"./wire.js\";\nimport { renderCommandMd, renderSkillMd, renderSubagentMd } from \"./render.js\";\n\nconst HOST: PlatformId = \"claude-code\";\nconst MCP_ROOT_KEY = \"mcpServers\";\n\n/**\n * settings.json leaf key the statusline surface owns. Wired through the SAME\n * set-if-absent ownership ledger as configPatch (it is NOT on the configPatch\n * sensitive-key denylist — verified — and is a single top-level leaf), so a\n * non-AC statusLine is never clobbered.\n */\nconst STATUSLINE_KEY = \"statusLine\";\n\n/**\n * Reserved blockId of the SHARED `@AGENTS.md` import bridge in CLAUDE.md\n * (agents-import mode). The `_shared/` prefix cannot collide with a connector\n * blockId (connector ids match ^[a-z0-9][a-z0-9-]*$), and the bridge is\n * refcounted namespace-wide: it is removed only when the LAST agent-connector\n * block leaves the sibling AGENTS.md.\n */\nconst CLAUDE_AGENTS_IMPORT_BLOCK_ID = \"_shared/claude-agents-import\";\n\n/** A single hook registration entry as Claude Code stores it in settings.json. */\ninterface ClaudeHookEntry {\n matcher: string;\n hooks: Array<{ type: \"command\"; command: string }>;\n}\n\n/** Native MCP server entry shapes Claude Code accepts under `mcpServers`. */\ninterface ClaudeStdioServer {\n type: \"stdio\";\n command: string;\n args: string[];\n env?: Record<string, string>;\n cwd?: string;\n}\ninterface ClaudeHttpServer {\n type: \"http\";\n url: string;\n headers?: Record<string, string>;\n}\n\n/**\n * Claude Code statusLine command stdin payload (the documented status-line hook\n * input). Every field optional — a refresh only carries what the host knows.\n * `version` and any unmodeled fields stay in StatuslineContext.raw.\n */\ninterface ClaudeStatuslineInput {\n session_id?: string;\n transcript_path?: string;\n cwd?: string;\n version?: string;\n model?: { id?: string; display_name?: string };\n workspace?: { current_dir?: string; project_dir?: string };\n cost?: { total_cost_usd?: number };\n}\n\nexport class ClaudeCodeAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"Claude Code\";\n readonly paradigm: HookParadigm = \"json-stdio\";\n\n readonly capabilities: PlatformCapabilities = {\n preToolUse: true,\n postToolUse: true,\n preCompact: true,\n sessionStart: true,\n sessionEnd: true,\n userPromptSubmit: true,\n stop: true,\n notification: true,\n // Newer events — Claude Code is the reference host for all four.\n permissionRequest: true,\n postToolUseFailure: true,\n subagentStart: true,\n subagentStop: true,\n // Claude Code can rewrite PreToolUse input (updatedInput) but does NOT let a\n // PostToolUse hook rewrite already-emitted tool output.\n canModifyArgs: true,\n canModifyOutput: false,\n canInjectSessionContext: true,\n // Native passthrough hooks: settings.json hook keys are free-form event\n // names, so any host event (TaskCreated, TeammateIdle, WorktreeCreate, …)\n // declared under platforms[\"claude-code\"].nativeHooks installs verbatim.\n supportsNativeHooks: true,\n // Declarative host-config key patches: claude-code is the ONLY v1 host\n // (set-if-absent leaf keys in settings.json, refcounted ownership ledger,\n // sensitive-key denylist — see SENSITIVE_KEY_RULES below).\n supportsConfigPatch: true,\n // Statusline surface: claude-code is the ONLY v1 host. installStatusline\n // wires settings.json.statusLine = {type:\"command\", command:<home-bin\n // statusline cmd>} through the SAME set-if-absent ownership ledger as\n // configPatch (never clobbers a statusLine agent-connector does not own).\n supportsStatusline: true,\n transports: [\"stdio\", \"http\"],\n // Content surfaces: Claude Code is the reference implementation for all three.\n supportsCommands: true,\n supportsSkills: true,\n supportsSubagents: true,\n // Memory surface — EXCEPTION host: Claude Code reads CLAUDE.md, NOT\n // AGENTS.md (docs are explicit; no AGENTS.md support through v2.1.172), so\n // memoryTargets/installMemory below override the base AGENTS.md default.\n supportsMemory: true,\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userDir = join(homedir(), \".claude\");\n const userSettings = join(userDir, \"settings.json\");\n const userServers = join(homedir(), \".claude.json\");\n const projectServers = join(projectDir, \".mcp.json\");\n const userInstalled =\n existsSync(userDir) || existsSync(userSettings) || existsSync(userServers);\n const projInstalled = existsSync(projectServers);\n const installed = userInstalled || projInstalled;\n // Report the scope/path/reason for the marker that actually matched, so a\n // project-only install isn't misreported as a (non-existent) user install.\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\n const configPath = scope === \"project\" ? projectServers : userSettings;\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath,\n scope,\n reason: installed\n ? scope === \"project\"\n ? `found project Claude Code config at ${projectServers}`\n : `found Claude Code config under ${userDir}`\n : `no Claude Code config at ${userDir}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n getConfigDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".claude\")\n : join(homedir(), \".claude\");\n }\n\n getServerConfigPath(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".mcp.json\")\n : join(homedir(), \".claude.json\");\n }\n\n getHookConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"settings.json\");\n }\n\n // ── MCP server install / uninstall ───────────────────────────────────────\n\n installServer(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const override = connector.platforms[HOST]?.server;\n if (!connector.server || override === false) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: connector.server\n ? \"server registration disabled for claude-code\"\n : \"connector declares no MCP server\",\n },\n ];\n }\n\n // Shallow-merge any per-platform server override into the base ServerDef.\n const server: ServerDef =\n override && typeof override === \"object\"\n ? { ...connector.server, ...override }\n : connector.server;\n\n const serverPath = this.getServerConfigPath(ctx);\n const entry = this.renderServerEntry(ctx, server);\n\n return [\n this.upsertServerInJson(serverPath, MCP_ROOT_KEY, connector.id, entry, ctx.dryRun),\n ];\n }\n\n uninstallServer(ctx: InstallContext): ChangeRecord[] {\n const serverPath = this.getServerConfigPath(ctx);\n return [\n this.removeServerFromJson(serverPath, MCP_ROOT_KEY, ctx.connector.id, ctx.dryRun),\n ];\n }\n\n /** Render a normalized ServerDef into Claude Code's native mcpServers entry. */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): ClaudeStdioServer | ClaudeHttpServer {\n const transport: Transport = server.transport;\n\n if (transport === \"stdio\") {\n let command = server.command ?? \"\";\n let args = [...(server.args ?? [])];\n\n // Transparent telemetry wrapping: route the real command through\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\n if (shouldWrapForTelemetry(server, ctx.connector.telemetry)) {\n const wrapped = buildServeWrapperCommand(\n ctx.homeBinPath,\n ctx.connector.id,\n command,\n args,\n ctx.scope,\n this.id,\n );\n command = wrapped.command;\n args = wrapped.args;\n }\n\n const entry: ClaudeStdioServer = { type: \"stdio\", command, args };\n const env = this.renderEnv(server.env);\n if (env) entry.env = env;\n if (server.cwd) entry.cwd = resolveEnvRefsDeep(server.cwd);\n return entry;\n }\n\n // http (and any other remote transport we surface) — Claude registers a URL.\n const entry: ClaudeHttpServer = {\n type: \"http\",\n url: rewriteEnvRefs(server.url ?? \"\", claudeEnvToken),\n };\n if (server.headers) {\n entry.headers = this.renderEnv(server.headers) ?? {};\n }\n return entry;\n }\n\n /**\n * Render env/header values. Claude Code supports its own `${VAR}` native\n * interpolation, so translate `${env:VAR}` refs to that native token rather\n * than baking secrets into the file. Literals pass through unchanged.\n */\n private renderEnv(\n env: Record<string, string> | undefined,\n ): Record<string, string> | undefined {\n if (!env || Object.keys(env).length === 0) return undefined;\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(env)) {\n out[k] = rewriteEnvRefs(v, claudeEnvToken);\n }\n return out;\n }\n\n // ── Hook install / uninstall ─────────────────────────────────────────────\n\n installHooks(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const override = connector.platforms[HOST];\n\n // `hooks: false` disables only the NORMALIZED hooks. nativeHooks is a\n // sibling, explicitly claude-code-scoped declaration on the same override —\n // it installs regardless (the dev wrote both keys on the same object).\n const normalizedEvents = override?.hooks === false ? [] : connector.hookEvents;\n const nativeHooks = override?.nativeHooks ?? {};\n const nativeEvents = Object.keys(nativeHooks);\n\n if (normalizedEvents.length === 0 && nativeEvents.length === 0) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail:\n override?.hooks === false\n ? \"hooks disabled for claude-code\"\n : \"connector declares no hooks\",\n },\n ];\n }\n\n const settingsPath = this.getHookConfigPath(ctx);\n const settings = this.readJson<Record<string, unknown>>(settingsPath) ?? {};\n const hooks = (settings.hooks ??= {}) as Record<string, ClaudeHookEntry[]>;\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n // One pass over normalized + NATIVE events: native event-name keys are\n // written VERBATIM (e.g. \"TaskCreated\"), matcher from the def, and the\n // exact same home-bin command shape — so uninstall/doctor/telemetry treat\n // both identically.\n const pending: Array<{ event: string; matcher: string }> = [\n ...normalizedEvents.map((event) => ({\n event: event as string,\n matcher: connector.hooks[event]?.matcher ?? \"\",\n })),\n ...nativeEvents.map((event) => ({\n event,\n matcher: nativeHooks[event]?.matcher ?? \"\",\n })),\n ];\n\n for (const { event, matcher } of pending) {\n const command = buildHomeBinHookCommand(ctx.homeBinPath, HOST, event, connector.id);\n const entry: ClaudeHookEntry = {\n matcher,\n hooks: [{ type: \"command\", command }],\n };\n\n const bucket = (hooks[event] ??= []);\n const existingIdx = bucket.findIndex((e) => this.entryHasCommand(e, command));\n\n if (existingIdx >= 0) {\n if (JSON.stringify(bucket[existingIdx]) === JSON.stringify(entry)) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: settingsPath,\n detail: `hooks.${event} already registered`,\n });\n continue;\n }\n bucket[existingIdx] = entry;\n changes.push({\n platform: this.id,\n action: \"update\",\n path: settingsPath,\n detail: `hooks.${event}`,\n });\n } else {\n bucket.push(entry);\n changes.push({\n platform: this.id,\n action: \"create\",\n path: settingsPath,\n detail: `hooks.${event}`,\n });\n }\n mutated = true;\n }\n\n if (mutated) this.writeJson(settingsPath, settings, ctx.dryRun);\n return changes;\n }\n\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n const settingsPath = this.getHookConfigPath(ctx);\n const settings = this.readJson<Record<string, unknown>>(settingsPath);\n const hooks = settings?.hooks as Record<string, ClaudeHookEntry[]> | undefined;\n if (!settings || !hooks) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: settingsPath,\n detail: \"no hooks section present\",\n },\n ];\n }\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const event of Object.keys(hooks)) {\n const bucket = hooks[event];\n if (!Array.isArray(bucket)) continue;\n\n // Strip our hook command from each entry; drop entries left empty.\n const next: ClaudeHookEntry[] = [];\n let removed = 0;\n for (const e of bucket) {\n const innerBefore = e.hooks?.length ?? 0;\n const inner = (e.hooks ?? []).filter(\n (h) => !this.isOurCommand(h.command, ctx),\n );\n removed += innerBefore - inner.length;\n if (inner.length > 0) next.push({ matcher: e.matcher ?? \"\", hooks: inner });\n }\n\n if (removed > 0) {\n if (next.length > 0) hooks[event] = next;\n else delete hooks[event];\n changes.push({\n platform: this.id,\n action: \"remove\",\n path: settingsPath,\n detail: `hooks.${event} (${removed})`,\n });\n mutated = true;\n }\n }\n\n if (mutated) this.writeJson(settingsPath, settings, ctx.dryRun);\n if (changes.length === 0) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: settingsPath,\n detail: \"no matching hook entries\",\n });\n }\n return changes;\n }\n\n private entryHasCommand(entry: ClaudeHookEntry, command: string): boolean {\n return (entry.hooks ?? []).some((h) => h.command === command);\n }\n\n // ── Declarative host-config key patches (configPatch) ────────────────────\n // FIXED semantics (docs/ARCHITECTURE.md §4): set-if-absent on a single\n // dotted LEAF key of settings.json, skip-warn on ANY conflict (present key,\n // non-object intermediate, drift), refcounted ownership in the persisted\n // ledger at <dataRoot>/state/config-patches.json. Reuses the adapter's\n // existing whole-file settings.json JSON IO (the same handling the hook\n // install performs on this exact file) — Claude Code itself rewrites this\n // file, so format preservation is a non-issue here. NOTE for future hosts:\n // VS Code JSONC needs jsonc-parser modify/applyEdits and Codex TOML needs an\n // anchored edit — core/toml.ts's round-trip is BANNED for configPatch.\n\n /** The ONLY file configPatch may touch on claude-code: settings.json at scope. */\n getPatchableConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"settings.json\");\n }\n\n override installConfigPatches(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const patches = connector.platforms[HOST]?.configPatch ?? [];\n if (patches.length === 0) {\n return [\n { platform: this.id, action: \"skip\", detail: \"connector declares no configPatch entries\" },\n ];\n }\n return this.applyConfigPatches(ctx, patches);\n }\n\n /**\n * The shared set-if-absent / ownership-ledger apply loop behind BOTH\n * {@link installConfigPatches} and {@link installStatusline}. Routing the\n * statusline through the EXACT same path is how a connector's statusLine\n * inherits the configPatch contract verbatim: never clobber a statusLine\n * agent-connector does not own (skip-warn), record prior state + owner,\n * refcounted across connectors, reversible by uninstallConfigPatches.\n */\n private applyConfigPatches(\n ctx: InstallContext,\n patches: ConfigPatchDef[],\n opts: { surfaceLabel?: \"configPatch\" | \"statusline\" } = {},\n ): ChangeRecord[] {\n // The user-facing surface name in every ChangeRecord.detail. \"statusline\"\n // routes the AC-modeled statusLine key through this loop INTERNALLY — that\n // key is namespace-reserved against raw configPatch, so the internal path\n // bypasses the namespace guard (the surface, not a smuggled patch, owns it).\n const surfaceLabel = opts.surfaceLabel ?? \"configPatch\";\n const internal = surfaceLabel !== \"configPatch\";\n const { connector } = ctx;\n const filePath = this.getPatchableConfigPath(ctx);\n // OVERWRITE GUARD (upsertServerInJson precedent): never round-trip a\n // present-but-unparseable settings file into `{}`.\n if (this.isPresentButUnparseable(filePath)) {\n return [\n {\n platform: this.id,\n action: \"warn\",\n path: filePath,\n detail: `existing ${filePath} is not parseable; configPatch left unapplied (back it up / fix it, then re-run)`,\n },\n ];\n }\n const settings = this.readJson<Record<string, unknown>>(filePath) ?? {};\n if (typeof settings !== \"object\" || Array.isArray(settings)) {\n return [\n {\n platform: this.id,\n action: \"warn\",\n path: filePath,\n detail: `existing ${filePath} is not a JSON object; configPatch left unapplied`,\n },\n ];\n }\n\n const ledger = loadConfigPatchLedger(ctx.dataRoot);\n const changes: ChangeRecord[] = [];\n let fileMutated = false;\n let ledgerMutated = false;\n\n for (const patch of patches) {\n // Defense in depth: re-validate grammar + AC-namespace here (a connector\n // loaded from raw meta/JSON must not bypass defineConnector's checks).\n if (!isValidConfigPatchKey(patch.key)) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n detail:\n `configPatch ${JSON.stringify(patch.key)} refused: not a dotted leaf path ` +\n `(segments must match [A-Za-z0-9_-]+; no array indices)`,\n });\n continue;\n }\n // The statusline surface intentionally models the (now namespace-reserved)\n // statusLine key, so its internal patches skip this guard.\n if (!internal) {\n const namespace = configPatchNamespaceViolation(patch.key);\n if (namespace) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n detail: `configPatch refused: ${namespace}`,\n });\n continue;\n }\n }\n // SENSITIVE-KEY DENYLIST — hard refuse, no override flag in v1.\n const sensitive = claudeSensitiveKeyViolation(patch.key);\n if (sensitive) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n detail:\n `configPatch ${patch.key} refused: matches the claude-code sensitive-key ` +\n `denylist (${sensitive}); security-relevant keys are never patched`,\n });\n continue;\n }\n\n // `${env:VAR}` refs resolve at install time, matching server-entry behavior.\n const desired = resolveEnvRefsDeep(patch.value) as JsonValue;\n const segments = patch.key.split(\".\");\n const leaf = readJsonLeaf(settings, segments);\n const entry = findLedgerEntry(ledger, HOST, filePath, patch.key);\n\n if (leaf.kind === \"blocked\") {\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: filePath,\n detail:\n `${surfaceLabel} ${patch.key} skipped: \"${leaf.atPath}\" exists but is not an ` +\n `object — ${configPatchManualEdit(patch)}`,\n });\n continue;\n }\n\n if (leaf.kind === \"absent\") {\n // SET-IF-ABSENT: the one write path. Intermediates created only as needed.\n writeJsonLeaf(settings, segments, desired);\n fileMutated = true;\n if (entry) {\n // Stale ledger row (key was deleted out from under us): re-assert the\n // value, keep existing owners (they still rely on the key existing),\n // and record what was actually (re)written.\n entry.writtenValue = desired;\n entry.writtenValueHash = hashJsonValue(desired);\n addLedgerOwner(entry, connector.id, connector.version);\n } else {\n createLedgerEntry(ledger, {\n platform: HOST,\n file: filePath,\n key: patch.key,\n value: desired,\n connectorId: connector.id,\n connectorVersion: connector.version,\n });\n }\n ledgerMutated = true;\n changes.push({\n platform: this.id,\n action: \"create\",\n path: filePath,\n detail: `${surfaceLabel} ${patch.key}: <absent> → ${describeJsonValue(desired)} (${patch.reason})`,\n });\n continue;\n }\n\n // Key PRESENT — never overwrite; the only question is ownership/refcount.\n if (!entry) {\n // User- (or other-tool-) owned. No ownership is taken even when values\n // happen to match — uninstall must never delete a key we did not create.\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: filePath,\n detail:\n `${surfaceLabel} ${patch.key} skipped: already set to ${describeJsonValue(leaf.value)} ` +\n `(not created by agent-connector; desired ${describeJsonValue(desired)}) — ` +\n configPatchManualEdit(patch),\n });\n continue;\n }\n\n if (!jsonDeepEquals(leaf.value, entry.writtenValue)) {\n // DRIFT: the user edited the value after we wrote it. Never revert —\n // sync re-asserts only ABSENT keys.\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: filePath,\n detail:\n `${surfaceLabel} ${patch.key}: value changed since install ` +\n `(current ${describeJsonValue(leaf.value)}, wrote ${describeJsonValue(entry.writtenValue)}); ` +\n `leaving in place — ${configPatchManualEdit(patch)}`,\n });\n continue;\n }\n\n if (jsonDeepEquals(desired, leaf.value)) {\n // Same value we own: register as co-owner (refcount++) or plain\n // idempotent skip when this connector is already an owner.\n const owners = entry.owners.map((o) => o.connectorId);\n if (addLedgerOwner(entry, connector.id, connector.version)) {\n ledgerMutated = true;\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: filePath,\n detail: `${surfaceLabel} ${patch.key} already installed; registered as co-owner (co-owned with ${owners.join(\", \")})`,\n });\n } else {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: filePath,\n detail: `${surfaceLabel} ${patch.key} already installed`,\n });\n }\n continue;\n }\n\n // FIRST-WRITER-WINS: another connector owns this key with a different value.\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: filePath,\n detail:\n `${surfaceLabel} ${patch.key} skipped: already owned by ${entry.owners\n .map((o) => o.connectorId)\n .join(\", \")} with a different value ` +\n `(current ${describeJsonValue(leaf.value)}, desired ${describeJsonValue(desired)}) — ` +\n configPatchManualEdit(patch),\n });\n }\n\n if (fileMutated) this.writeJson(filePath, settings, ctx.dryRun);\n if (ledgerMutated && !ctx.dryRun) saveConfigPatchLedger(ctx.dataRoot, ledger);\n return changes;\n }\n\n override uninstallConfigPatches(ctx: InstallContext): ChangeRecord[] {\n const connectorId = ctx.connector.id;\n const ledger = loadConfigPatchLedger(ctx.dataRoot);\n // Keyed off the LEDGER (not the declaration): releases ownership for every\n // file/scope this connector ever patched, even when the uninstall context\n // is a minimal synthetic connector or the scope flag differs from install.\n // EXCLUDE the statusLine key — that surface releases via uninstallStatusline\n // (the installer runs both), so this never double-processes the same row.\n const owned = ledgerEntriesOwnedBy(ledger, HOST, connectorId).filter(\n (e) => e.key !== STATUSLINE_KEY,\n );\n const declared = ctx.connector.platforms[HOST]?.configPatch ?? [];\n const changes: ChangeRecord[] = [];\n\n // Declared patches with NO ownership record anywhere: never delete a key\n // we did not create (rule 1) — explicit skip so the outcome is never silent.\n const ownedKeys = new Set(owned.map((e) => e.key));\n for (const patch of declared) {\n if (!ownedKeys.has(patch.key)) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n detail: `configPatch ${patch.key}: no ownership recorded; left untouched`,\n });\n }\n }\n if (owned.length === 0) return changes;\n changes.push(...this.releaseOwnedConfigPatches(ctx, ledger, owned));\n return changes;\n }\n\n /**\n * The shared last-owner-verified release loop behind BOTH\n * {@link uninstallConfigPatches} and {@link uninstallStatusline}: for each\n * already-selected owned ledger entry, drop this connector's ownership and\n * remove the key ONLY when last-owner ∧ value-unchanged ∧ prior-absent (else\n * skip-warn + leave the key). Saves the ledger when it mutated.\n */\n private releaseOwnedConfigPatches(\n ctx: InstallContext,\n ledger: ReturnType<typeof loadConfigPatchLedger>,\n owned: ConfigPatchLedgerEntry[],\n opts: { surfaceLabel?: \"configPatch\" | \"statusline\" } = {},\n ): ChangeRecord[] {\n const surfaceLabel = opts.surfaceLabel ?? \"configPatch\";\n const connectorId = ctx.connector.id;\n const changes: ChangeRecord[] = [];\n let ledgerMutated = false;\n const backedUp = new Set<string>();\n\n // Group by file (entries may span scopes/files).\n const byFile = new Map<string, ConfigPatchLedgerEntry[]>();\n for (const entry of owned) {\n const bucket = byFile.get(entry.file) ?? [];\n bucket.push(entry);\n byFile.set(entry.file, bucket);\n }\n\n for (const [filePath, entries] of byFile) {\n const unparseable = this.isPresentButUnparseable(filePath);\n const settings = unparseable\n ? null\n : this.readJson<Record<string, unknown>>(filePath);\n let fileMutated = false;\n\n for (const entry of entries) {\n const { lastOwner } = removeLedgerOwner(entry, connectorId);\n ledgerMutated = true;\n\n if (!lastOwner) {\n // The shared-flag case: A uninstalls, B still relies on the key.\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: filePath,\n detail: `${surfaceLabel} ${entry.key} retained: still owned by ${entry.owners\n .map((o) => o.connectorId)\n .join(\", \")}`,\n });\n continue;\n }\n\n // Last owner out → the ledger row is dropped on every branch below;\n // the KEY is removed only on the fully-verified branch.\n dropLedgerEntry(ledger, entry);\n\n if (unparseable) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: filePath,\n detail: `${surfaceLabel} ${entry.key}: ${filePath} is not parseable; key left in place (ownership released)`,\n });\n continue;\n }\n if (!settings || typeof settings !== \"object\" || Array.isArray(settings)) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: filePath,\n detail: `${surfaceLabel} ${entry.key} already absent (no settings file); ownership record dropped`,\n });\n continue;\n }\n const leaf = readJsonLeaf(settings, entry.key.split(\".\"));\n if (leaf.kind !== \"present\") {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: filePath,\n detail: `${surfaceLabel} ${entry.key} already absent; ownership record dropped`,\n });\n continue;\n }\n if (entry.prior?.present !== false || !jsonDeepEquals(leaf.value, entry.writtenValue)) {\n // User edited the value after install (or the row predates the\n // set-if-absent guarantee): deleting would clobber them. Leave it.\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: filePath,\n detail:\n `${surfaceLabel} ${entry.key}: value changed since install ` +\n `(current ${describeJsonValue(leaf.value)}, wrote ${describeJsonValue(entry.writtenValue)}); ` +\n `left in place`,\n });\n continue;\n }\n\n // VERIFIED: last owner + current === writtenValue + prior was absent.\n // Back up the exact file before its first mutation, then delete the\n // leaf key (intermediate objects we created are left in place).\n if (!ctx.dryRun && !backedUp.has(filePath) && existsSync(filePath)) {\n const backup = this.backupFileForConfigPatch(filePath);\n backedUp.add(filePath);\n if (backup) {\n changes.push({\n platform: this.id,\n action: \"create\",\n path: backup,\n detail: \"backed up settings before configPatch removal\",\n });\n }\n }\n deleteJsonLeaf(settings, entry.key.split(\".\"));\n fileMutated = true;\n changes.push({\n platform: this.id,\n action: \"remove\",\n path: filePath,\n detail: `${surfaceLabel} ${entry.key} removed (was ${describeJsonValue(entry.writtenValue)})`,\n });\n }\n\n if (fileMutated && settings) this.writeJson(filePath, settings, ctx.dryRun);\n }\n\n if (ledgerMutated && !ctx.dryRun) saveConfigPatchLedger(ctx.dataRoot, ledger);\n return changes;\n }\n\n // ── Statusline surface (a HUD/status line) ────────────────────────────────\n // Wires settings.json.statusLine = { type:\"command\", command:<home-bin\n // statusline cmd> } through the SAME ownership ledger as configPatch: a\n // synthetic ConfigPatchDef routed through applyConfigPatches, so the statusLine\n // inherits the full set-if-absent contract verbatim — never clobbers a\n // statusLine agent-connector does not own (skip-warn), records prior state +\n // owner, reversible. The home-bin command makes the host exec\n // `<homeBin> statusline claude-code --connector <id>` for every status refresh,\n // which re-imports the connector module and renders the line (runtime/\n // statusline-entrypoint). No telemetry in v1.\n\n /** The synthetic statusLine configPatch this connector would write. */\n private statuslineConfigPatch(ctx: InstallContext): ConfigPatchDef {\n const command = buildHomeBinStatuslineCommand(ctx.homeBinPath, HOST, ctx.connector.id);\n return {\n key: STATUSLINE_KEY,\n value: { type: \"command\", command },\n reason: \"agent-connector statusline surface\",\n };\n }\n\n override installStatusline(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.statusline == null) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no statusline\" }];\n }\n if (connector.platforms[HOST]?.statusline === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"statusline disabled for claude-code\" }];\n }\n // Reuse the configPatch apply path (set-if-absent, ownership ledger, skip-warn\n // on any non-AC statusLine). This is the SAME machinery installConfigPatches\n // uses on this exact file, so the ownership semantics are identical — only the\n // surface LABEL differs (statusLine is namespace-reserved against raw\n // configPatch; this internal path bypasses that guard and owns the key).\n return this.applyConfigPatches(ctx, [this.statuslineConfigPatch(ctx)], {\n surfaceLabel: \"statusline\",\n });\n }\n\n override uninstallStatusline(ctx: InstallContext): ChangeRecord[] {\n const ledger = loadConfigPatchLedger(ctx.dataRoot);\n // Release ONLY the statusLine ledger row this connector owns (keyed off the\n // ledger, not the declaration, so an id-only synthetic uninstall still\n // reclaims it). Same last-owner-verified delete as uninstallConfigPatches.\n const owned = ledgerEntriesOwnedBy(ledger, HOST, ctx.connector.id).filter(\n (e) => e.key === STATUSLINE_KEY,\n );\n if (owned.length === 0) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: \"statusline: no ownership recorded; left untouched\",\n },\n ];\n }\n return this.releaseOwnedConfigPatches(ctx, ledger, owned, {\n surfaceLabel: \"statusline\",\n });\n }\n\n /**\n * Parse Claude Code's statusLine stdin JSON into the normalized\n * {@link StatuslineContext}. Claude pipes a JSON object to the statusLine\n * command on stdin (model, workspace, cost, etc.); fields the payload omits\n * stay undefined. `raw` keeps the verbatim payload (incl. `version`).\n */\n parseStatusInput(raw: unknown): StatuslineContext {\n const input = (raw ?? {}) as ClaudeStatuslineInput;\n const model: { id?: string; displayName?: string } = {};\n if (typeof input.model?.id === \"string\") model.id = input.model.id;\n if (typeof input.model?.display_name === \"string\") {\n model.displayName = input.model.display_name;\n }\n const cwd =\n typeof input.cwd === \"string\"\n ? input.cwd\n : typeof input.workspace?.current_dir === \"string\"\n ? input.workspace.current_dir\n : undefined;\n\n const ctx: StatuslineContext = {\n host: HOST,\n capabilities: this.capabilities,\n raw,\n };\n if (typeof input.session_id === \"string\" && input.session_id !== \"\") {\n ctx.sessionId = input.session_id;\n }\n if (cwd !== undefined) ctx.cwd = cwd;\n if (model.id !== undefined || model.displayName !== undefined) ctx.model = model;\n if (typeof input.cost?.total_cost_usd === \"number\") {\n ctx.cost = { totalUsd: input.cost.total_cost_usd };\n }\n if (typeof input.transcript_path === \"string\") {\n ctx.transcriptPath = input.transcript_path;\n }\n return ctx;\n }\n\n /** Format the rendered status line into Claude's native reply: stdout = line, exit 0. */\n formatStatusOutput(rendered: string): HookReply {\n return { exitCode: 0, stdout: rendered };\n }\n\n /**\n * Back up ONE exact file (the ledger-recorded patch target, which may belong\n * to a different scope than the current ctx) into the standard backups dir.\n * Best-effort: a failed copy returns null and the caller proceeds — the\n * removal is already value-verified.\n */\n private backupFileForConfigPatch(filePath: string): string | null {\n try {\n ensureDir(backupsDir());\n const stamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n const dest = join(backupsDir(), `${this.id}-${stamp}-${basename(filePath)}`);\n copyFileSync(filePath, dest);\n return dest;\n } catch {\n return null;\n }\n }\n\n /**\n * Doctor: per-ledger-entry configPatch state for this connector —\n * ok → key present and still exactly what we wrote;\n * drifted → user changed the value (we print the manual edit, NEVER\n * auto-fix — sync re-asserts only absent keys);\n * missing → key deleted by the user; sync will re-assert it;\n * orphaned → ledger row whose owners' connector records are all gone.\n * Plus a re-print of the manual edit for declared patches that hold no\n * ownership (skipped at install).\n */\n private configPatchDiagnostics(ctx: InstallContext): DiagnosticResult[] {\n const results: DiagnosticResult[] = [];\n const ledger = loadConfigPatchLedger(ctx.dataRoot);\n const connectorId = ctx.connector.id;\n // EXCLUDE the statusLine row: it is owned by the statusline surface and gets\n // its own dedicated health check in getHealthChecks. Reporting it here too\n // would double-report the key and (on a user edit) print a bogus configPatch\n // \"drifted\" hint to restore a configPatch the connector never declared.\n const platformEntries = ledger.entries.filter(\n (e) => e.platform === this.id && e.key !== STATUSLINE_KEY,\n );\n\n for (const entry of platformEntries) {\n const ownedByThis = entry.owners.some((o) => o.connectorId === connectorId);\n if (!ownedByThis) {\n // ORPHAN check (global hygiene): every owner's connector record is gone.\n const orphaned =\n entry.owners.length === 0 ||\n entry.owners.every((o) => readRegisteredMeta(o.connectorId) === null);\n if (orphaned) {\n results.push({\n check: `${this.name}: configPatch ${entry.key}`,\n status: \"warn\",\n message:\n `orphaned ledger entry in ${entry.file}: owning connector record(s) ` +\n `gone (${entry.owners.map((o) => o.connectorId).join(\", \") || \"none\"})`,\n fix:\n `re-run \\`agent-connector uninstall <owner-id>\\` to release it, or remove ` +\n `${entry.key} from ${entry.file} manually`,\n });\n }\n continue;\n }\n\n const state = this.configPatchState(entry);\n if (state.kind === \"ok\") {\n results.push({\n check: `${this.name}: configPatch ${entry.key}`,\n status: \"pass\",\n message: `ok — ${entry.key} = ${describeJsonValue(entry.writtenValue)} (${entry.file})`,\n });\n } else if (state.kind === \"missing\") {\n results.push({\n check: `${this.name}: configPatch ${entry.key}`,\n status: \"warn\",\n message: `missing — key deleted from ${entry.file} since install`,\n fix: `agent-connector install (sync) will re-assert it`,\n });\n } else {\n results.push({\n check: `${this.name}: configPatch ${entry.key}`,\n status: \"warn\",\n message:\n `drifted — value changed since install (current ${describeJsonValue(state.current)}, ` +\n `wrote ${describeJsonValue(entry.writtenValue)}); never auto-fixed`,\n fix: `manual edit if wanted: set ${entry.key} = ${describeJsonValue(entry.writtenValue)} in ${entry.file}`,\n });\n }\n }\n\n // Declared-but-unowned patches: re-print the manual edit (the patch was\n // skipped at install — conflict, denylist, or simply not installed yet).\n const declared = ctx.connector.platforms[HOST]?.configPatch ?? [];\n const ownedKeys = new Set(\n ledgerEntriesOwnedBy(ledger, HOST, connectorId).map((e) => e.key),\n );\n for (const patch of declared) {\n if (ownedKeys.has(patch.key)) continue;\n results.push({\n check: `${this.name}: configPatch ${patch.key}`,\n status: \"warn\",\n message: `declared but not owned (skipped at install or not yet installed)`,\n fix: configPatchManualEdit(patch),\n });\n }\n return results;\n }\n\n /** Current on-disk state of one owned ledger entry. */\n private configPatchState(\n entry: ConfigPatchLedgerEntry,\n ): { kind: \"ok\" } | { kind: \"missing\" } | { kind: \"drifted\"; current: JsonValue } {\n const settings = this.readJson<Record<string, unknown>>(entry.file);\n if (!settings || typeof settings !== \"object\" || Array.isArray(settings)) {\n return { kind: \"missing\" };\n }\n const leaf = readJsonLeaf(settings, entry.key.split(\".\"));\n if (leaf.kind !== \"present\") return { kind: \"missing\" };\n if (jsonDeepEquals(leaf.value, entry.writtenValue)) return { kind: \"ok\" };\n return { kind: \"drifted\", current: leaf.value };\n }\n\n override doctor(ctx: InstallContext): DiagnosticResult[] {\n const results = super.doctor(ctx);\n results.push(...this.configPatchDiagnostics(ctx));\n return results;\n }\n\n // ── Content surfaces: commands / skills / subagents ──────────────────────\n // CONTENT-ONLY: pure native-file writers under <configDir>/{commands,skills,\n // agents}. No runtime dispatch, no home-bin pointer, no telemetry wrap. Each\n // method is idempotent (byte-identical → skip) via BaseAdapter.writeContentFile\n // and reversible via removeContentFile. Honors platforms[\"claude-code\"]\n // per-surface false to skip.\n\n private commandsDir(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"commands\");\n }\n private skillsDir(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"skills\");\n }\n private agentsDir(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"agents\");\n }\n\n /** Native command file path: <configDir>/commands/<name>.md. */\n private commandPath(ctx: InstallContext, name: string): string {\n return join(this.commandsDir(ctx), `${name}.md`);\n }\n /** Native skill dir: <configDir>/skills/<name>. */\n private skillDir(ctx: InstallContext, name: string): string {\n return join(this.skillsDir(ctx), name);\n }\n /** Native subagent file path: <configDir>/agents/<name>.md. */\n private subagentPath(ctx: InstallContext, name: string): string {\n return join(this.agentsDir(ctx), `${name}.md`);\n }\n\n // ── Commands ──────────────────────────────────────────────────────────────\n\n override installCommands(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.commands === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"commands disabled for claude-code\" }];\n }\n if (connector.commands.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\n }\n return connector.commands.map((cmd) =>\n this.writeContentFile(\n this.commandPath(ctx, cmd.name),\n this.renderCommand(cmd),\n ctx.dryRun,\n ),\n );\n }\n\n override uninstallCommands(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.commands.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\n }\n return connector.commands.map((cmd) =>\n this.removeContentFile(this.commandPath(ctx, cmd.name), ctx.dryRun),\n );\n }\n\n /** Render a command to md+frontmatter (delegates to the shared renderer). */\n private renderCommand(cmd: CommandDef): string {\n return renderCommandMd(cmd);\n }\n\n // ── Skills ────────────────────────────────────────────────────────────────\n\n override installSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.skills === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"skills disabled for claude-code\" }];\n }\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n changes.push(\n this.writeContentFile(join(dir, \"SKILL.md\"), this.renderSkill(skill), ctx.dryRun),\n );\n // Bundle any resource files beside SKILL.md (relative path → contents).\n // Defense-in-depth: skip+warn on any key that escapes the skill dir\n // (config-time validation already rejects these, but never trust input).\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n detail: `skill resource \"${rel}\" escapes the skill dir; skipped`,\n });\n continue;\n }\n changes.push(this.writeContentFile(target, contents, ctx.dryRun));\n }\n }\n return changes;\n }\n\n override uninstallSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n // Remove only the files we wrote (SKILL.md + declared resources), then the\n // skill dir itself when we own its full contents.\n changes.push(this.removeContentFile(join(dir, \"SKILL.md\"), ctx.dryRun));\n for (const rel of Object.keys(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) continue; // never delete outside the skill dir\n changes.push(this.removeContentFile(target, ctx.dryRun));\n }\n // Only remove the skill dir when WE own its full contents — never rm -rf a\n // dir that still holds user-added / sibling-tool / shared files.\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\n }\n return changes;\n }\n\n /** Render a skill's SKILL.md (delegates to the shared renderer). */\n private renderSkill(skill: SkillDef): string {\n return renderSkillMd(skill);\n }\n\n // ── Subagents ───────────────────────────────────────────────────────────────\n\n override installSubagents(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.subagents === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"subagents disabled for claude-code\" }];\n }\n if (connector.subagents.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\n }\n return connector.subagents.map((agent) =>\n this.writeContentFile(\n this.subagentPath(ctx, agent.name),\n this.renderSubagent(agent),\n ctx.dryRun,\n ),\n );\n }\n\n override uninstallSubagents(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.subagents.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\n }\n return connector.subagents.map((agent) =>\n this.removeContentFile(this.subagentPath(ctx, agent.name), ctx.dryRun),\n );\n }\n\n /** Render a subagent to md+frontmatter (delegates to the shared renderer). */\n private renderSubagent(agent: SubagentDef): string {\n return renderSubagentMd(agent);\n }\n\n // ── Memory surface: CLAUDE.md managed block + AGENTS.md interop ────────────\n // EXCEPTION host. Claude Code reads CLAUDE.md, NOT AGENTS.md (docs verbatim:\n // \"Claude Code reads CLAUDE.md, not AGENTS.md\"; no AGENTS.md support through\n // v2.1.172), so the base AGENTS.md-first default is overridden:\n // - mode \"block\" (default): the managed block goes straight into CLAUDE.md.\n // HTML-comment markers are CORRECT here — Claude strips HTML comments\n // from CLAUDE.md before context injection, so the markers and the\n // do-not-edit notice are INVISIBLE to the model while remaining fully\n // parseable by us for sync/doctor/uninstall.\n // - mode \"agents-import\" (opt-in via platforms[\"claude-code\"].memory.mode):\n // canonical block goes into AGENTS.md, plus a SHARED `@AGENTS.md` import\n // bridge block in CLAUDE.md (Anthropic's documented interop). Opt-in\n // because the import makes Claude read the ENTIRE AGENTS.md — a behavior\n // change agent-connector must not make silently.\n // - AUTO interop: when CLAUDE.md ALREADY imports `@AGENTS.md` (a line\n // outside code fences and outside our own blocks) or IS a symlink\n // resolving to AGENTS.md, the canonical block goes to AGENTS.md and\n // CLAUDE.md is NOT touched — the pre-existing user wiring is never\n // claimed as agent-connector-managed (prevents double-reads and writes\n // \"through\" a symlink). Order-independent: keyed off the import/symlink\n // existing, never off whether the AGENTS.md block was written yet.\n\n /** CLAUDE.md path: project `<projectDir>/CLAUDE.md`, user `~/.claude/CLAUDE.md`. */\n private claudeMdPath(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \"CLAUDE.md\")\n : join(homedir(), \".claude\", \"CLAUDE.md\");\n }\n\n /** Sibling AGENTS.md at the same scope (agents-import / auto-interop target). */\n private agentsMdPath(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \"AGENTS.md\")\n : join(homedir(), \".claude\", \"AGENTS.md\");\n }\n\n /**\n * True when the user ALREADY wired CLAUDE.md to AGENTS.md themselves:\n * an `@AGENTS.md` import line outside code fences and outside agent-connector\n * managed blocks (our own bridge must not count), or CLAUDE.md being a\n * symlink that resolves to the sibling AGENTS.md.\n */\n private claudeMdWiredToAgentsMd(ctx: InstallContext): boolean {\n const claudeMd = this.claudeMdPath(ctx);\n if (!existsSync(claudeMd)) return false;\n try {\n if (lstatSync(claudeMd).isSymbolicLink()) {\n const agentsMd = this.agentsMdPath(ctx);\n const resolved = realpathSync(claudeMd);\n const agentsResolved = existsSync(agentsMd) ? realpathSync(agentsMd) : agentsMd;\n if (resolved === agentsResolved) return true;\n }\n } catch {\n /* unreadable link — fall through to the content probe */\n }\n let raw: string;\n try {\n raw = readFileSync(claudeMd, \"utf8\");\n } catch {\n return false;\n }\n // Strip every agent-connector managed block first so OUR bridge import is\n // never mistaken for user wiring (idempotence across modes).\n const withoutBlocks = removeBlocksFromText(raw, { blockIdPrefix: \"\" }).text;\n const importRe = /(^|\\s)@(?:AGENTS\\.md|~\\/\\.claude\\/AGENTS\\.md)(\\s|$)/;\n return linesOutsideFences(withoutBlocks).some((line) => importRe.test(line));\n }\n\n /**\n * Effective memory mode for this install:\n * \"user-import\" — the user already wired CLAUDE.md→AGENTS.md (wins over\n * everything; we never write a duplicate or a second import);\n * \"agents-import\" — explicit opt-in via platforms[\"claude-code\"].memory.mode;\n * \"block\" — the default (managed block directly in CLAUDE.md).\n */\n private effectiveMemoryMode(ctx: InstallContext): \"block\" | \"agents-import\" | \"user-import\" {\n if (this.claudeMdWiredToAgentsMd(ctx)) return \"user-import\";\n return this.memoryOverride(ctx)?.mode === \"agents-import\" ? \"agents-import\" : \"block\";\n }\n\n protected override memoryTargets(ctx: InstallContext): MemoryTarget[] {\n // An explicit path override keeps the base resolution (escape hatch wins).\n if (this.memoryOverride(ctx)?.path) return super.memoryTargets(ctx);\n if (ctx.scope !== \"project\" && ctx.scope !== \"user\") return [];\n const mode = this.effectiveMemoryMode(ctx);\n if (mode === \"block\") {\n return [\n {\n path: this.claudeMdPath(ctx),\n reason:\n \"CLAUDE.md (Claude Code reads CLAUDE.md, not AGENTS.md; \" +\n \"HTML-comment markers are stripped from the model's context)\",\n },\n ];\n }\n return [\n {\n path: this.agentsMdPath(ctx),\n reason:\n mode === \"user-import\"\n ? \"AGENTS.md (CLAUDE.md already imports/symlinks it — user wiring respected)\"\n : \"AGENTS.md (agents-import mode; @AGENTS.md bridge managed in CLAUDE.md)\",\n },\n ];\n }\n\n override installMemory(ctx: InstallContext): ChangeRecord[] {\n const changes = super.installMemory(ctx);\n const { connector } = ctx;\n // Bridge management applies only when the generic path actually installed.\n if (connector.platforms[HOST]?.memory === false || (connector.memory ?? []).length === 0) {\n return changes;\n }\n if (ctx.scope !== \"project\" && ctx.scope !== \"user\") return changes;\n if (this.memoryOverride(ctx)?.path) return changes;\n\n const mode = this.effectiveMemoryMode(ctx);\n if (mode === \"user-import\") {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: this.claudeMdPath(ctx),\n detail:\n \"memory: CLAUDE.md already imports AGENTS.md; canonical block in AGENTS.md \" +\n \"suffices (pre-existing user import never claimed as managed)\",\n });\n return changes;\n }\n if (mode !== \"agents-import\") return changes;\n\n // agents-import: ensure the SHARED `@AGENTS.md` bridge block in CLAUDE.md.\n const claudeMd = this.claudeMdPath(ctx);\n const importLine = ctx.scope === \"project\" ? \"@AGENTS.md\" : \"@~/.claude/AGENTS.md\";\n const res = upsertManagedBlockFile(claudeMd, {\n blockId: CLAUDE_AGENTS_IMPORT_BLOCK_ID,\n connectorId: \"_shared\",\n content: importLine,\n notice:\n \"Managed by agent-connector (shared bridge). This import makes Claude Code read \" +\n \"AGENTS.md; it is removed automatically when the last agent-connector block \" +\n \"leaves AGENTS.md.\",\n force: ctx.force ?? false,\n dryRun: ctx.dryRun,\n });\n changes.push({\n platform: this.id,\n action: res.action,\n path: claudeMd,\n detail: `memory: ${res.detail} — @AGENTS.md import bridge (agents-import mode)`,\n });\n if (res.backupPath) {\n changes.push({\n platform: this.id,\n action: \"create\",\n path: res.backupPath,\n detail: \"backed up CLAUDE.md before destructive change\",\n });\n }\n if (res.action !== \"warn\" && !ctx.dryRun) {\n const ledger = loadMemoryLedger(connector.id);\n recordMemoryTarget(ledger, {\n platform: this.id,\n scope: ctx.scope,\n path: claudeMd,\n blockId: CLAUDE_AGENTS_IMPORT_BLOCK_ID,\n createdFile: res.createdFile,\n hash: res.hash,\n });\n saveMemoryLedger(connector.id, ledger);\n }\n return changes;\n }\n\n override uninstallMemory(ctx: InstallContext): ChangeRecord[] {\n // Capture bridge facts BEFORE super prunes this platform's ledger rows.\n const priorRows = loadMemoryLedger(ctx.connector.id).targets.filter(\n (t) => t.platform === this.id && t.blockId === CLAUDE_AGENTS_IMPORT_BLOCK_ID,\n );\n const changes = super.uninstallMemory(ctx);\n\n // Bridge candidates: the current-scope CLAUDE.md plus any CLAUDE.md the\n // ledger recorded a bridge in (scope drift between install and uninstall).\n const pairs = new Map<string, { agentsMd: string; createdFile: boolean }>();\n if (ctx.scope === \"project\" || ctx.scope === \"user\") {\n pairs.set(this.claudeMdPath(ctx), {\n agentsMd: this.agentsMdPath(ctx),\n createdFile: false,\n });\n }\n for (const row of priorRows) {\n const existing = pairs.get(row.path);\n pairs.set(row.path, {\n agentsMd: existing?.agentsMd ?? join(dirname(row.path), \"AGENTS.md\"),\n createdFile: (existing?.createdFile ?? false) || row.createdFile,\n });\n }\n for (const [claudeMd, { agentsMd, createdFile }] of pairs) {\n changes.push(...this.releaseAgentsImportBridge(ctx, claudeMd, agentsMd, createdFile));\n }\n return changes;\n }\n\n /**\n * Refcounted bridge release: remove the `_shared/claude-agents-import` block\n * from CLAUDE.md ONLY when the sibling AGENTS.md holds zero agent-connector\n * blocks from OTHER connectors (namespace-wide count, excluding this\n * connector's own blocks so the answer is identical on dry-run and real run).\n * A user-authored `@AGENTS.md` import (no markers) is NEVER touched.\n */\n private releaseAgentsImportBridge(\n ctx: InstallContext,\n claudeMd: string,\n agentsMd: string,\n createdFile: boolean,\n ): ChangeRecord[] {\n if (!existsSync(claudeMd)) return [];\n let raw: string;\n try {\n raw = readFileSync(claudeMd, \"utf8\");\n } catch {\n return [];\n }\n if (!listManagedBlocks(raw).some((b) => b.blockId === CLAUDE_AGENTS_IMPORT_BLOCK_ID)) {\n return []; // no managed bridge here (user wiring or block mode) — nothing to release\n }\n let remaining = 0;\n if (existsSync(agentsMd)) {\n try {\n remaining = listManagedBlocks(readFileSync(agentsMd, \"utf8\")).filter(\n (b) => !b.blockId.startsWith(`${ctx.connector.id}/`),\n ).length;\n } catch {\n remaining = 1; // unreadable → conservative: keep the bridge\n }\n }\n if (remaining > 0) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: claudeMd,\n detail:\n `memory: @AGENTS.md import bridge retained — ${remaining} agent-connector ` +\n `block(s) from other connectors remain in ${agentsMd}`,\n },\n ];\n }\n return removeManagedBlocksFile(\n claudeMd,\n { blockId: CLAUDE_AGENTS_IMPORT_BLOCK_ID },\n { dryRun: ctx.dryRun, deleteFileIfCreated: createdFile },\n ).map((r) => ({\n platform: this.id,\n action: r.action,\n path: r.path,\n detail: `memory: ${r.detail}`,\n }));\n }\n\n /** True when a hook command references our home binary AND this connector id\n * (anchored so a shared-prefix id can't collide — see isHomeBinHookCommand). */\n private isOurCommand(command: string | undefined, ctx: InstallContext): boolean {\n return isHomeBinHookCommand(command, ctx.homeBinPath, ctx.connector.id);\n }\n\n // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const settingsPath = this.getHookConfigPath(ctx);\n const connectorId = ctx.connector.id;\n const homeBin = ctx.homeBinPath;\n const hookEvents = ctx.connector.hookEvents;\n // Native passthrough hooks count toward \"declares hooks\" ONLY when declared\n // for this platform (the serialized meta keeps the event-name keys, so this\n // works for doctor's handler-less meta-derived connectors too).\n const declaredHookCount =\n hookEvents.length +\n Object.keys(ctx.connector.platforms[HOST]?.nativeHooks ?? {}).length;\n const checks: HealthCheck[] = [\n {\n name: `${this.name}: settings.json present`,\n check: () => {\n // Same \"only assert what the connector declares\" rule as the\n // content-surface checks below: a hookless connector never writes\n // hooks into settings.json, so its absence is healthy, not a failure.\n if (declaredHookCount === 0) {\n return { status: \"OK\", detail: \"no hooks declared\" };\n }\n return existsSync(settingsPath)\n ? { status: \"OK\", detail: settingsPath }\n : { status: \"FAIL\", detail: `not found: ${settingsPath}` };\n },\n },\n {\n name: `${this.name}: hook command registered`,\n check: () => {\n if (declaredHookCount === 0) {\n return { status: \"OK\", detail: \"no hooks declared\" };\n }\n const settings = this.readJson<{ hooks?: Record<string, ClaudeHookEntry[]> }>(\n settingsPath,\n );\n if (!settings) return { status: \"FAIL\", detail: `cannot read ${settingsPath}` };\n const hooks = settings.hooks ?? {};\n const registered = Object.values(hooks).some((entries) =>\n (entries ?? []).some((e) =>\n (e.hooks ?? []).some((h) =>\n isHomeBinHookCommand(h.command, homeBin, connectorId),\n ),\n ),\n );\n return registered\n ? { status: \"OK\", detail: \"hook command present\" }\n : {\n status: \"FAIL\",\n detail: `no hook for ${connectorId} in ${settingsPath}`,\n };\n },\n },\n ];\n\n // Content-surface checks: only assert presence of the files this connector\n // declares (skip silently for surfaces it never asked for).\n for (const cmd of ctx.connector.commands) {\n const p = this.commandPath(ctx, cmd.name);\n checks.push({\n name: `${this.name}: command ${cmd.name} present`,\n check: () =>\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\n });\n }\n for (const skill of ctx.connector.skills) {\n const p = join(this.skillDir(ctx, skill.name), \"SKILL.md\");\n checks.push({\n name: `${this.name}: skill ${skill.name} present`,\n check: () =>\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\n });\n }\n for (const agent of ctx.connector.subagents) {\n const p = this.subagentPath(ctx, agent.name);\n checks.push({\n name: `${this.name}: subagent ${agent.name} present`,\n check: () =>\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\n });\n }\n\n // Statusline check: only assert it when the connector declares one AND it\n // is not disabled for this host. settings.json.statusLine.command must be OUR\n // home-bin statusline command (ok); present but not ours → drifted/skip-warn\n // (never our concern to fix); absent → missing.\n // Fire the check when the connector DECLARES a statusline (the live-config\n // doctor path) OR when the ownership ledger holds a statusLine row this\n // connector owns (the REGISTERED-connector path: connectorFromMeta can't\n // re-expose the render fn, so statusline comes back undefined — but the\n // ledger row proves the surface was wired). Mirrors uninstallStatusline,\n // which is also ledger-keyed; without this the wired statusLine has ZERO\n // doctor coverage in the registered path (configPatchDiagnostics excludes it).\n const statuslineLedgerOwned = ledgerEntriesOwnedBy(\n loadConfigPatchLedger(ctx.dataRoot),\n HOST,\n connectorId,\n ).some((e) => e.key === STATUSLINE_KEY);\n if (\n (ctx.connector.statusline != null || statuslineLedgerOwned) &&\n ctx.connector.platforms[HOST]?.statusline !== false\n ) {\n checks.push({\n name: `${this.name}: statusline wired`,\n check: () => {\n const settings = this.readJson<{ statusLine?: { command?: unknown } }>(settingsPath);\n const command = settings?.statusLine?.command;\n if (command === undefined) {\n return { status: \"FAIL\", detail: `statusLine not set in ${settingsPath}` };\n }\n if (\n typeof command === \"string\" &&\n isHomeBinStatuslineCommand(command, homeBin, connectorId)\n ) {\n return { status: \"OK\", detail: \"statusLine command present\" };\n }\n // Present but not ours — a non-AC statusLine we must never clobber.\n return {\n status: \"FAIL\",\n detail: `statusLine in ${settingsPath} is not agent-connector's (left untouched)`,\n };\n },\n });\n }\n return checks;\n }\n\n // ── Runtime: parse Claude stdin JSON → normalized event ──────────────────\n\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\n const input = (raw ?? {}) as ClaudeWireInput;\n const connectorId = typeof input.connector === \"string\" ? input.connector : \"\";\n const sessionId = extractSessionId(input);\n const projectDir = typeof input.cwd === \"string\" ? input.cwd : undefined;\n\n const base = {\n hostPlatform: HOST,\n connectorId,\n sessionId,\n raw,\n ...(projectDir !== undefined ? { projectDir } : {}),\n } as const;\n\n switch (event) {\n case \"PreToolUse\": {\n const ev: PreToolUseEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n };\n return ev;\n }\n case \"PostToolUse\": {\n const ev: PostToolUseEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n ...(toolResponseToString(input.tool_response) !== undefined\n ? { toolOutput: toolResponseToString(input.tool_response) }\n : {}),\n };\n return ev;\n }\n case \"SessionStart\": {\n const ev: SessionStartEvent = {\n ...base,\n source: normalizeSessionSource(input.source),\n };\n return ev;\n }\n case \"SessionEnd\": {\n const ev: SessionEndEvent = {\n ...base,\n ...(typeof input.reason === \"string\" ? { reason: input.reason } : {}),\n };\n return ev;\n }\n case \"UserPromptSubmit\": {\n const ev: UserPromptSubmitEvent = {\n ...base,\n prompt: typeof input.prompt === \"string\" ? input.prompt : \"\",\n };\n return ev;\n }\n case \"PreCompact\": {\n const ev: PreCompactEvent = {\n ...base,\n ...(input.trigger === \"auto\" || input.trigger === \"manual\"\n ? { trigger: input.trigger }\n : {}),\n };\n return ev;\n }\n case \"Stop\": {\n const ev: StopEvent = {\n ...base,\n ...(typeof input.stop_hook_active === \"boolean\"\n ? { stopHookActive: input.stop_hook_active }\n : {}),\n };\n return ev;\n }\n case \"Notification\": {\n const ev: NotificationEvent = {\n ...base,\n message: typeof input.message === \"string\" ? input.message : \"\",\n };\n return ev;\n }\n case \"PermissionRequest\": {\n const ev: PermissionRequestEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n ...(Array.isArray(input.permission_suggestions)\n ? { permissionSuggestions: input.permission_suggestions }\n : {}),\n };\n return ev;\n }\n case \"PostToolUseFailure\": {\n const ev: PostToolUseFailureEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n error: typeof input.error === \"string\" ? input.error : \"\",\n ...(typeof input.tool_use_id === \"string\"\n ? { toolUseId: input.tool_use_id }\n : {}),\n ...(typeof input.is_interrupt === \"boolean\"\n ? { isInterrupt: input.is_interrupt }\n : {}),\n ...(typeof input.duration_ms === \"number\"\n ? { durationMs: input.duration_ms }\n : {}),\n };\n return ev;\n }\n case \"SubagentStart\": {\n const ev: SubagentStartEvent = {\n ...base,\n ...(typeof input.agent_id === \"string\" ? { agentId: input.agent_id } : {}),\n ...(typeof input.agent_type === \"string\"\n ? { agentType: input.agent_type }\n : {}),\n };\n return ev;\n }\n case \"SubagentStop\": {\n // agent_id/agent_type stay optional — the SDK does not reliably\n // populate agent_type on SubagentStop (real-world quirk).\n const ev: SubagentStopEvent = {\n ...base,\n ...(typeof input.agent_id === \"string\" ? { agentId: input.agent_id } : {}),\n ...(typeof input.agent_type === \"string\"\n ? { agentType: input.agent_type }\n : {}),\n ...(typeof input.agent_transcript_path === \"string\"\n ? { agentTranscriptPath: input.agent_transcript_path }\n : {}),\n ...(typeof input.last_assistant_message === \"string\"\n ? { lastAssistantMessage: input.last_assistant_message }\n : {}),\n ...(typeof input.stop_hook_active === \"boolean\"\n ? { stopHookActive: input.stop_hook_active }\n : {}),\n };\n return ev;\n }\n default: {\n // Exhaustive guard — every HookEventName is handled above.\n const _never: never = event;\n throw new Error(`unsupported claude-code hook event: ${String(_never)}`);\n }\n }\n }\n\n // ── Runtime: normalized response → Claude native hook reply ──────────────\n\n formatReply(event: HookEventName, response: HookResponse): HookReply {\n const hookEventName = event as ClaudeHookEvent;\n const decision = response.decision ?? \"allow\";\n\n // PermissionRequest replies use Claude's nested decision{behavior} envelope\n // and are the ONE event where an EXPLICIT \"allow\" is an ACTIVE grant (it\n // suppresses the permission dialog) rather than passthrough:\n // allow → decision{behavior:\"allow\"} (+updatedInput when set);\n // Claude still enforces its own deny rules — an allow\n // never overrides a matching deny rule (host-enforced).\n // modify → an allow grant carrying updatedInput.\n // deny → decision{behavior:\"deny\", message} (shown to Claude).\n // ask/context/void → NO decision output: fall through to the native\n // dialog (the dialog IS the ask).\n if (event === \"PermissionRequest\") {\n if (response.decision === \"deny\") {\n return this.stdout({\n hookSpecificOutput: {\n hookEventName,\n decision: {\n behavior: \"deny\",\n message: response.reason ?? \"Blocked by hook\",\n },\n },\n });\n }\n if (\n response.decision === \"allow\" ||\n (response.decision === \"modify\" && response.updatedInput)\n ) {\n return this.stdout({\n hookSpecificOutput: {\n hookEventName,\n decision: {\n behavior: \"allow\",\n ...(response.updatedInput\n ? { updatedInput: response.updatedInput }\n : {}),\n },\n },\n });\n }\n return { exitCode: 0 };\n }\n\n // PostToolUseFailure (feedback beside the error) and SubagentStart (context\n // injected at the start of the SUBAGENT's conversation) are observe/context-\n // only on Claude: \"context\" emits additionalContext, and a \"deny\" DEGRADES\n // to the same shape carrying the reason (the tool already failed / the\n // spawn is not blockable). Everything else passes through.\n if (event === \"PostToolUseFailure\" || event === \"SubagentStart\") {\n const context =\n decision === \"context\"\n ? response.additionalContext\n : decision === \"deny\"\n ? response.reason ?? response.additionalContext\n : undefined;\n if (context) {\n return this.stdout({\n hookSpecificOutput: { hookEventName, additionalContext: context },\n });\n }\n return { exitCode: 0 };\n }\n\n // deny → block the action with a reason (exit 0; JSON carries the decision).\n // Claude's deny shape is EVENT-SPECIFIC: PreToolUse uses\n // hookSpecificOutput.permissionDecision, but Stop / SubagentStop /\n // UserPromptSubmit / PostToolUse honor only the TOP-LEVEL\n // {\"decision\":\"block\",\"reason\"} — rendering those as permissionDecision is\n // silently ignored by Claude (found porting oh-my-claudecode: its ralph\n // persistence loop denies the Stop event, which never blocked through the\n // old shape). A SubagentStop block keeps the subagent running with `reason`\n // as its next instruction (Stop semantics).\n if (decision === \"deny\") {\n if (\n event === \"Stop\" ||\n event === \"SubagentStop\" ||\n event === \"UserPromptSubmit\" ||\n event === \"PostToolUse\"\n ) {\n return this.stdout({\n decision: \"block\",\n reason: response.reason ?? \"Blocked by hook\",\n });\n }\n return this.stdout({\n hookSpecificOutput: {\n hookEventName,\n permissionDecision: \"deny\",\n permissionDecisionReason: response.reason ?? \"Blocked by hook\",\n },\n });\n }\n\n // ask → prompt the user to confirm.\n if (decision === \"ask\") {\n return this.stdout({\n hookSpecificOutput: {\n hookEventName,\n permissionDecision: \"ask\",\n permissionDecisionReason:\n response.reason ?? \"Confirmation required by hook\",\n },\n });\n }\n\n // modify → rewrite PreToolUse input (only where Claude supports it).\n if (decision === \"modify\") {\n if (event === \"PreToolUse\" && response.updatedInput) {\n return this.stdout({\n hookSpecificOutput: { hookEventName, updatedInput: response.updatedInput },\n });\n }\n // Output rewrite is unsupported on Claude; fall through to allow.\n }\n\n // context → inject soft guidance (also the SessionStart context path).\n if (decision === \"context\" && response.additionalContext) {\n return this.stdout({\n hookSpecificOutput: { hookEventName, additionalContext: response.additionalContext },\n });\n }\n\n // allow / void / unsupported-degradation → pass through with exit 0.\n return { exitCode: 0 };\n }\n\n private stdout(payload: unknown): HookReply {\n return { exitCode: 0, stdout: JSON.stringify(payload) };\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// configPatch: sensitive-key denylist + JSON leaf-path helpers\n// ─────────────────────────────────────────────────────────────────────────\n\n/**\n * SENSITIVE-KEY DENYLIST (claude-code, v1) — THE documented list. configPatch\n * targeting any key below is HARD-REFUSED (warn ChangeRecord, never applied;\n * no override flag in v1). Rationale: configPatch writes bare host keys with\n * no inherent attribution, and these keys are security-relevant — permission\n * grants, tool allowlists, credential/auth helpers, login pinning, and any\n * env var that can reroute credentials or traffic. The OMC case\n * `env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS` passes; credential rerouting and\n * self-granted permissions do not. Reviewed whenever the host matrix updates.\n *\n * permissions, permissions.* — self-granted permission rules\n * allowedTools / disallowedTools (.*) — tool allowlist tampering\n * apiKey* (e.g. apiKeyHelper) — credential helpers\n * awsAuthRefresh / awsCredentialExport — AWS credential plumbing\n * forceLoginMethod / forceLoginOrgUUID — login/org pinning\n * otelHeadersHelper — telemetry-header (token) helper\n * hooks*, mcpServers* (+ enable/enabled/disabledMcpjsonServers)\n * — refused upstream by the\n * agent-connector NAMESPACE guard\n * env.ANTHROPIC_* — API key / base-URL rerouting\n * env.AWS_* — AWS credentials\n * env.*_PROXY — traffic interception\n * env.*TOKEN* / env.*KEY* / env.*SECRET* — generic credential patterns\n */\nconst SENSITIVE_KEY_RULES: ReadonlyArray<{ re: RegExp; label: string }> = [\n { re: /^permissions(\\.|$)/, label: \"permissions\" },\n { re: /^allowedTools(\\.|$)/, label: \"allowedTools\" },\n { re: /^disallowedTools(\\.|$)/, label: \"disallowedTools\" },\n { re: /^apiKey/i, label: \"apiKey*\" },\n { re: /^awsAuthRefresh$/, label: \"awsAuthRefresh\" },\n { re: /^awsCredentialExport$/, label: \"awsCredentialExport\" },\n { re: /^forceLoginMethod$/, label: \"forceLoginMethod\" },\n { re: /^forceLoginOrgUUID$/, label: \"forceLoginOrgUUID\" },\n { re: /^otelHeadersHelper$/, label: \"otelHeadersHelper\" },\n { re: /^env\\.ANTHROPIC_/, label: \"env.ANTHROPIC_*\" },\n { re: /^env\\.AWS_/, label: \"env.AWS_*\" },\n { re: /^env\\.[^.]*_PROXY(\\.|$)/i, label: \"env.*_PROXY\" },\n { re: /^env\\.[^.]*TOKEN/i, label: \"env.*TOKEN*\" },\n { re: /^env\\.[^.]*KEY/i, label: \"env.*KEY*\" },\n { re: /^env\\.[^.]*SECRET/i, label: \"env.*SECRET*\" },\n];\n\n/**\n * The matched denylist pattern label when `key` is sensitive on claude-code,\n * else null. Exported so tests and docs stay pinned to the real list.\n */\nexport function claudeSensitiveKeyViolation(key: string): string | null {\n for (const rule of SENSITIVE_KEY_RULES) {\n if (rule.re.test(key)) return rule.label;\n }\n return null;\n}\n\n/** Result of looking up a dotted leaf path in a parsed JSON object. */\ntype JsonLeafLookup =\n | { kind: \"absent\" }\n | { kind: \"present\"; value: JsonValue }\n | { kind: \"blocked\"; atPath: string };\n\n/**\n * Walk `segments` (a validated dotted leaf path) through `root`. \"blocked\"\n * reports the first intermediate that exists but is not a plain object —\n * the skip-warn case (we never replace a non-object intermediate).\n */\nfunction readJsonLeaf(root: Record<string, unknown>, segments: string[]): JsonLeafLookup {\n let node: Record<string, unknown> = root;\n for (let i = 0; i < segments.length - 1; i++) {\n const next = node[segments[i]!];\n if (next === undefined) return { kind: \"absent\" };\n if (next === null || typeof next !== \"object\" || Array.isArray(next)) {\n return { kind: \"blocked\", atPath: segments.slice(0, i + 1).join(\".\") };\n }\n node = next as Record<string, unknown>;\n }\n const leaf = node[segments[segments.length - 1]!];\n if (leaf === undefined) return { kind: \"absent\" };\n return { kind: \"present\", value: leaf as JsonValue };\n}\n\n/**\n * Write `value` at the leaf, creating ONLY absent intermediate objects along\n * the way (callers must have verified the path is not blocked).\n */\nfunction writeJsonLeaf(\n root: Record<string, unknown>,\n segments: string[],\n value: JsonValue,\n): void {\n let node: Record<string, unknown> = root;\n for (let i = 0; i < segments.length - 1; i++) {\n const seg = segments[i]!;\n const next = node[seg];\n if (next === undefined) {\n const created: Record<string, unknown> = {};\n node[seg] = created;\n node = created;\n } else {\n node = next as Record<string, unknown>;\n }\n }\n node[segments[segments.length - 1]!] = value;\n}\n\n/**\n * Delete the leaf key only. Intermediate objects — even ones we created — are\n * deliberately left in place (harmless; pruning risks collateral).\n */\nfunction deleteJsonLeaf(root: Record<string, unknown>, segments: string[]): void {\n let node: Record<string, unknown> = root;\n for (let i = 0; i < segments.length - 1; i++) {\n const next = node[segments[i]!];\n if (next === null || typeof next !== \"object\" || Array.isArray(next)) return;\n node = next as Record<string, unknown>;\n }\n delete node[segments[segments.length - 1]!];\n}\n\n/** Claude Code native interpolation token: `${env:VAR}` → `${VAR}`. */\nfunction claudeEnvToken(name: string): string {\n return `\\${${name}}`;\n}\n\nfunction normalizeSessionSource(source: string | undefined): SessionStartEvent[\"source\"] {\n switch (source) {\n case \"compact\":\n return \"compact\";\n case \"resume\":\n return \"resume\";\n case \"clear\":\n return \"clear\";\n default:\n return \"startup\";\n }\n}\n\nexport const adapter = new ClaudeCodeAdapter();\nexport default adapter;\n","/**\n * adapters/claude-code/wire — Claude Code hook wire protocol.\n *\n * Claude Code pipes a JSON object to a hook command on stdin and reads a JSON\n * object (or empty) from stdout, interpreting the exit code as well. This module\n * captures the exact stdin shape and the canonical reply shape so the adapter's\n * parse/format methods are a single source of truth.\n *\n * Stdin (documented Claude Code hook input):\n * {\n * session_id, transcript_path, cwd, hook_event_name,\n * tool_name, tool_input, tool_response, // tool events\n * permission_suggestions, // PermissionRequest\n * tool_use_id, error, is_interrupt, duration_ms, // PostToolUseFailure\n * agent_id, agent_type, // SubagentStart/Stop\n * agent_transcript_path, last_assistant_message, // SubagentStop\n * source, // SessionStart\n * reason, // SessionEnd\n * prompt, // UserPromptSubmit\n * trigger, // PreCompact\n * stop_hook_active, // Stop / SubagentStop\n * message // Notification\n * }\n *\n * Stdout (canonical reply): a `hookSpecificOutput` object keyed by\n * `hookEventName`, carrying `permissionDecision` (allow|deny|ask) +\n * `permissionDecisionReason`, `additionalContext`, and (PreToolUse)\n * `updatedInput`; PermissionRequest instead takes a nested\n * `decision: { behavior: \"allow\"|\"deny\", ... }`; Stop-class blocks\n * (Stop / SubagentStop / UserPromptSubmit / PostToolUse) take the TOP-LEVEL\n * `{\"decision\":\"block\",\"reason\"}`. Exit 0 = proceed; the JSON refines the\n * decision.\n */\n\n/** Canonical Claude Code hook event names (the values of `hook_event_name`). */\nexport const CLAUDE_HOOK_EVENTS = [\n \"PreToolUse\",\n \"PostToolUse\",\n \"PreCompact\",\n \"SessionStart\",\n \"SessionEnd\",\n \"UserPromptSubmit\",\n \"Stop\",\n \"Notification\",\n \"PermissionRequest\",\n \"PostToolUseFailure\",\n \"SubagentStart\",\n \"SubagentStop\",\n] as const;\n\nexport type ClaudeHookEvent = (typeof CLAUDE_HOOK_EVENTS)[number];\n\n/**\n * Raw Claude Code hook stdin payload. Every field is optional — a given event\n * only populates the subset relevant to it. `connector` is NOT a Claude field;\n * it is threaded in by the universal entrypoint so parseEvent can recover the\n * connector id (the home binary passes `--connector <id>` and may inject it).\n */\nexport interface ClaudeWireInput {\n session_id?: string;\n transcript_path?: string;\n cwd?: string;\n hook_event_name?: string;\n\n // tool events\n tool_name?: string;\n tool_input?: Record<string, unknown>;\n /** PostToolUse result payload (string or structured). */\n tool_response?: unknown;\n\n // PermissionRequest — permission-update entries the dialog would offer.\n // NOTE: the docs explicitly state PermissionRequest has NO tool_use_id.\n permission_suggestions?: unknown[];\n\n // PostToolUseFailure\n tool_use_id?: string;\n error?: string;\n is_interrupt?: boolean;\n duration_ms?: number;\n\n // SubagentStart / SubagentStop — agent_type is unreliable on SubagentStop\n // (the SDK may not populate it); treat both as optional everywhere.\n agent_id?: string;\n agent_type?: string;\n // SubagentStop — the subagent's OWN transcript (transcript_path stays the\n // parent session's) + the text of its final response.\n agent_transcript_path?: string;\n last_assistant_message?: string;\n\n // SessionStart\n source?: string;\n // SessionEnd\n reason?: string;\n // UserPromptSubmit\n prompt?: string;\n // PreCompact\n trigger?: string;\n // Stop / SubagentStop\n stop_hook_active?: boolean;\n // Notification\n message?: string;\n\n /** Injected by the entrypoint so the runtime knows which connector to dispatch. */\n connector?: string;\n}\n\n/**\n * Extract a stable session id from a Claude wire payload.\n * Priority mirrors the proven adapter: transcript UUID > session_id > \"\".\n * (The framework's normalized event uses \"\" when no id is available, per\n * core/types BaseEvent.sessionId docstring — no ppid fabrication here.)\n */\nexport function extractSessionId(input: ClaudeWireInput): string {\n if (typeof input.transcript_path === \"string\") {\n const m = input.transcript_path.match(/([a-f0-9-]{36})\\.jsonl$/);\n if (m && m[1]) return m[1];\n }\n if (typeof input.session_id === \"string\" && input.session_id !== \"\") {\n return input.session_id;\n }\n return \"\";\n}\n\n/** Coerce a Claude PostToolUse `tool_response` into a string for the normalized event. */\nexport function toolResponseToString(value: unknown): string | undefined {\n if (value == null) return undefined;\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n"],"mappings":"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","names":["entry"]}
package/dist/cli/sdk.js CHANGED
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  main
4
- } from "../chunk-3RBLIHPZ.js";
4
+ } from "../chunk-KGXDYGNJ.js";
5
5
  import {
6
6
  loadConnectorFromPath
7
- } from "../chunk-3JCRUROU.js";
8
- import "../chunk-GSGDG2BV.js";
7
+ } from "../chunk-KGJWE6A2.js";
8
+ import "../chunk-ADTHT2FN.js";
9
+ import "../chunk-3PFFTFCU.js";
9
10
  import "../chunk-N6HH7K6P.js";
10
11
  import "../chunk-TRQKHP7D.js";
11
12
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/sdk.ts"],"sourcesContent":["/**\n * cli/sdk — the EMBEDDED SDK entry point for a developer-branded CLI.\n *\n * A developer adds agent-connector as a dependency, writes their connector\n * config, and ships their OWN bin. `createConnectorCli` returns a runner that\n * exposes EVERY agent-connector subcommand under the developer's brand, fully\n * delegated and AUTO-SCOPED to the developer's connector:\n *\n * #!/usr/bin/env node\n * import { fileURLToPath } from \"node:url\";\n * import { createConnectorCli } from \"@ken-jo/agent-connector/cli\";\n * createConnectorCli({\n * name: \"acme-db\",\n * connector: fileURLToPath(new URL(\"./agent-connector.config.mjs\", import.meta.url)),\n * }).run();\n * // fileURLToPath, NOT URL.pathname — .pathname yields \"/C:/…\" on Windows.\n *\n * Then a consumer runs `acme-db install`, `acme-db leaderboard`, `acme-db\n * telemetry`, `acme-db doctor`, etc. — and each one targets the developer's\n * connector WITHOUT the consumer having to pass --connector.\n *\n * This module is PURE ARGUMENT TRANSFORMATION: it injects the right --connector\n * (path) or --connector <id> filter when the user did not supply one, then hands\n * off to {@link main} with the developer's program name. It never duplicates any\n * command logic — every behavior still lives in the command modules.\n */\n\nimport { loadConnectorFromPath } from \"../core/load-connector.js\";\nimport { main } from \"./app.js\";\n\n/** Options for {@link createConnectorCli}. */\nexport interface CreateConnectorCliOptions {\n /** The developer's bin/brand name (shown in usage/help, e.g. \"acme-db\"). */\n name: string;\n /**\n * Absolute path to the developer's connector config (.mjs / .js / .json) that\n * ships inside their package. Injected as `--connector <path>` for the\n * connector-targeted subcommands when the user did not pass one.\n */\n connector: string;\n /**\n * The connector id used for the telemetry/leaderboard FILTER injection. When\n * omitted it is derived lazily by loading the connector config the first time a\n * telemetry/leaderboard subcommand runs.\n */\n connectorId?: string;\n}\n\n/** The runner returned by {@link createConnectorCli}. */\nexport interface ConnectorCli {\n /**\n * Run a branded invocation. `argv` defaults to `process.argv.slice(2)`.\n * Resolves to the process exit code (0 success, non-zero failure).\n */\n run(argv?: string[]): Promise<number>;\n}\n\n/**\n * Connector-targeted subcommands whose `--connector` is a CONFIG PATH: they load\n * the connector definition from disk. For these we inject the developer's config\n * PATH so their connector is the implicit target.\n *\n * (`uninstall` also accepts `--connector-id`; injecting the path is sufficient —\n * uninstall derives the id from the config when no explicit id is given.)\n */\nconst CONFIG_PATH_COMMANDS: ReadonlySet<string> = new Set([\n \"install\",\n \"uninstall\",\n \"upgrade\",\n // `sync` + `update` are back-compat aliases of `upgrade`; scope them too so a\n // branded `acme-db sync` / `acme-db update` still targets the dev connector.\n \"sync\",\n \"update\",\n \"doctor\",\n \"status\",\n \"package\",\n]);\n\n/**\n * Connector-targeted subcommands whose `--connector` is the registered connector\n * ID, spliced right AFTER the subcommand token: `serve` and `hook` pass it\n * straight to the runtime. (They cannot take a trailing flag — serve has a `--`\n * separator and hook has positionals — so the flag must lead.)\n */\nconst ID_HEAD_COMMANDS: ReadonlySet<string> = new Set([\"serve\", \"hook\"]);\n\n/**\n * View subcommands where `--connector <id>` is a FILTER appended at the END:\n * `leaderboard` (top-level) and `telemetry` (whose own sub — report|export|\n * leaderboard — is the leading positional, so the filter must come after it).\n * Appending keeps that leading positional intact while parseArgs still reads the\n * flag, so the branded tool shows ITS connector's data.\n *\n * Note: `usage` reads host CLI logs which carry no connector attribution, so it\n * is intentionally absent — there is nothing to scope it to.\n */\nconst ID_TAIL_COMMANDS: ReadonlySet<string> = new Set([\"telemetry\", \"leaderboard\"]);\n\n/**\n * Should the tail (telemetry/leaderboard) filter injection be SKIPPED because the\n * invocation is just asking for help / has no actionable sub? Skipping leaves the\n * branded usage text intact instead of turning `acme-db telemetry` into\n * `telemetry --connector <id>` (which the telemetry dispatcher would reject as an\n * unknown sub). True when a help flag appears, or when `telemetry` has no sub.\n */\nfunction wantsHelp(argv: string[]): boolean {\n if (argv.includes(\"--help\") || argv.includes(\"-h\")) return true;\n // `telemetry` with no sub-subcommand → show its help, don't inject a filter.\n if (argv[0] === \"telemetry\" && argv[1] === undefined) return true;\n return false;\n}\n\n/** Did the user already pass a --connector / --connector-id flag (any form)? */\nfunction hasConnectorFlag(argv: string[]): boolean {\n for (const a of argv) {\n if (a === \"--connector\" || a === \"--connector-id\") return true;\n if (a.startsWith(\"--connector=\") || a.startsWith(\"--connector-id=\")) return true;\n }\n return false;\n}\n\n/**\n * Splice `--connector <value>` immediately after the subcommand token (argv[0])\n * so it sits BEFORE any positionals or a `serve` `--` separator. Used for the\n * config-path commands and for serve/hook (whose `--` / positional grammar makes\n * trailing append unsafe). The original argv is never mutated.\n */\nfunction injectAfterCommand(argv: string[], flag: string, value: string): string[] {\n return [argv[0] as string, flag, value, ...argv.slice(1)];\n}\n\n/**\n * Append `--connector <value>` to the END of argv. Used for the view commands\n * (`leaderboard`/`telemetry`) whose leading positional sub must be preserved.\n * The original argv is never mutated.\n */\nfunction appendFlag(argv: string[], flag: string, value: string): string[] {\n return [...argv, flag, value];\n}\n\nexport function createConnectorCli(opts: CreateConnectorCliOptions): ConnectorCli {\n if (typeof opts.name !== \"string\" || opts.name.trim() === \"\") {\n throw new TypeError(\"createConnectorCli: `name` must be a non-empty string\");\n }\n if (typeof opts.connector !== \"string\" || opts.connector.trim() === \"\") {\n throw new TypeError(\"createConnectorCli: `connector` must be a non-empty path\");\n }\n\n // Cache the derived id so the connector module is loaded at most once across\n // repeated `.run()` calls in the same process.\n let cachedId: string | undefined = opts.connectorId;\n\n async function resolveConnectorId(): Promise<string> {\n if (cachedId !== undefined && cachedId !== \"\") return cachedId;\n const { connector } = await loadConnectorFromPath(opts.connector);\n cachedId = connector.id;\n return cachedId;\n }\n\n async function run(argv: string[] = process.argv.slice(2)): Promise<number> {\n const command = argv[0];\n\n // No subcommand, a help/version flag, or an unknown command: nothing to scope\n // — hand off verbatim so usage/version is branded and errors stay accurate.\n if (command === undefined || command.startsWith(\"-\")) {\n return main(argv, { programName: opts.name });\n }\n\n let scoped = argv;\n\n if (!hasConnectorFlag(argv)) {\n if (CONFIG_PATH_COMMANDS.has(command)) {\n // Inject the connector CONFIG PATH as the implicit target.\n scoped = injectAfterCommand(argv, \"--connector\", opts.connector);\n } else if (ID_HEAD_COMMANDS.has(command)) {\n // serve/hook take the connector ID and pass it to the runtime. Splice it\n // right after the subcommand token so a serve `--` separator and hook's\n // positionals are preserved.\n const id = await resolveConnectorId();\n scoped = injectAfterCommand(argv, \"--connector\", id);\n } else if (ID_TAIL_COMMANDS.has(command) && !wantsHelp(argv)) {\n // leaderboard/telemetry use the connector ID as a FILTER. Append it so\n // telemetry's leading positional sub (report|export|leaderboard) stays\n // the first token while parseArgs still reads the flag. We skip injection\n // for a bare/help invocation so the (un-filtered) usage text still shows.\n const id = await resolveConnectorId();\n scoped = appendFlag(argv, \"--connector\", id);\n }\n }\n\n return main(scoped, { programName: opts.name });\n }\n\n return { run };\n}\n"],"mappings":";;;;;;;;;;;;AAiEA,IAAM,uBAA4C,oBAAI,IAAI;AAAA,EACxD;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAQD,IAAM,mBAAwC,oBAAI,IAAI,CAAC,SAAS,MAAM,CAAC;AAYvE,IAAM,mBAAwC,oBAAI,IAAI,CAAC,aAAa,aAAa,CAAC;AASlF,SAAS,UAAU,MAAyB;AAC1C,MAAI,KAAK,SAAS,QAAQ,KAAK,KAAK,SAAS,IAAI,EAAG,QAAO;AAE3D,MAAI,KAAK,CAAC,MAAM,eAAe,KAAK,CAAC,MAAM,OAAW,QAAO;AAC7D,SAAO;AACT;AAGA,SAAS,iBAAiB,MAAyB;AACjD,aAAW,KAAK,MAAM;AACpB,QAAI,MAAM,iBAAiB,MAAM,iBAAkB,QAAO;AAC1D,QAAI,EAAE,WAAW,cAAc,KAAK,EAAE,WAAW,iBAAiB,EAAG,QAAO;AAAA,EAC9E;AACA,SAAO;AACT;AAQA,SAAS,mBAAmB,MAAgB,MAAc,OAAyB;AACjF,SAAO,CAAC,KAAK,CAAC,GAAa,MAAM,OAAO,GAAG,KAAK,MAAM,CAAC,CAAC;AAC1D;AAOA,SAAS,WAAW,MAAgB,MAAc,OAAyB;AACzE,SAAO,CAAC,GAAG,MAAM,MAAM,KAAK;AAC9B;AAEO,SAAS,mBAAmB,MAA+C;AAChF,MAAI,OAAO,KAAK,SAAS,YAAY,KAAK,KAAK,KAAK,MAAM,IAAI;AAC5D,UAAM,IAAI,UAAU,uDAAuD;AAAA,EAC7E;AACA,MAAI,OAAO,KAAK,cAAc,YAAY,KAAK,UAAU,KAAK,MAAM,IAAI;AACtE,UAAM,IAAI,UAAU,0DAA0D;AAAA,EAChF;AAIA,MAAI,WAA+B,KAAK;AAExC,iBAAe,qBAAsC;AACnD,QAAI,aAAa,UAAa,aAAa,GAAI,QAAO;AACtD,UAAM,EAAE,UAAU,IAAI,MAAM,sBAAsB,KAAK,SAAS;AAChE,eAAW,UAAU;AACrB,WAAO;AAAA,EACT;AAEA,iBAAe,IAAI,OAAiB,QAAQ,KAAK,MAAM,CAAC,GAAoB;AAC1E,UAAM,UAAU,KAAK,CAAC;AAItB,QAAI,YAAY,UAAa,QAAQ,WAAW,GAAG,GAAG;AACpD,aAAO,KAAK,MAAM,EAAE,aAAa,KAAK,KAAK,CAAC;AAAA,IAC9C;AAEA,QAAI,SAAS;AAEb,QAAI,CAAC,iBAAiB,IAAI,GAAG;AAC3B,UAAI,qBAAqB,IAAI,OAAO,GAAG;AAErC,iBAAS,mBAAmB,MAAM,eAAe,KAAK,SAAS;AAAA,MACjE,WAAW,iBAAiB,IAAI,OAAO,GAAG;AAIxC,cAAM,KAAK,MAAM,mBAAmB;AACpC,iBAAS,mBAAmB,MAAM,eAAe,EAAE;AAAA,MACrD,WAAW,iBAAiB,IAAI,OAAO,KAAK,CAAC,UAAU,IAAI,GAAG;AAK5D,cAAM,KAAK,MAAM,mBAAmB;AACpC,iBAAS,WAAW,MAAM,eAAe,EAAE;AAAA,MAC7C;AAAA,IACF;AAEA,WAAO,KAAK,QAAQ,EAAE,aAAa,KAAK,KAAK,CAAC;AAAA,EAChD;AAEA,SAAO,EAAE,IAAI;AACf;","names":[]}
1
+ {"version":3,"sources":["../../src/cli/sdk.ts"],"sourcesContent":["/**\n * cli/sdk — the EMBEDDED SDK entry point for a developer-branded CLI.\n *\n * A developer adds agent-connector as a dependency, writes their connector\n * config, and ships their OWN bin. `createConnectorCli` returns a runner that\n * exposes EVERY agent-connector subcommand under the developer's brand, fully\n * delegated and AUTO-SCOPED to the developer's connector:\n *\n * #!/usr/bin/env node\n * import { fileURLToPath } from \"node:url\";\n * import { createConnectorCli } from \"@ken-jo/agent-connector/cli\";\n * createConnectorCli({\n * name: \"acme-db\",\n * connector: fileURLToPath(new URL(\"./agent-connector.config.mjs\", import.meta.url)),\n * }).run();\n * // fileURLToPath, NOT URL.pathname — .pathname yields \"/C:/…\" on Windows.\n *\n * Then a consumer runs `acme-db install`, `acme-db leaderboard`, `acme-db\n * telemetry`, `acme-db doctor`, etc. — and each one targets the developer's\n * connector WITHOUT the consumer having to pass --connector.\n *\n * This module is PURE ARGUMENT TRANSFORMATION: it injects the right --connector\n * (path) or --connector <id> filter when the user did not supply one, then hands\n * off to {@link main} with the developer's program name. It never duplicates any\n * command logic — every behavior still lives in the command modules.\n */\n\nimport { loadConnectorFromPath } from \"../core/load-connector.js\";\nimport { main } from \"./app.js\";\n\n/** Options for {@link createConnectorCli}. */\nexport interface CreateConnectorCliOptions {\n /** The developer's bin/brand name (shown in usage/help, e.g. \"acme-db\"). */\n name: string;\n /**\n * Absolute path to the developer's connector config (.mjs / .js / .json) that\n * ships inside their package. Injected as `--connector <path>` for the\n * connector-targeted subcommands when the user did not pass one.\n */\n connector: string;\n /**\n * The connector id used for the telemetry/leaderboard FILTER injection. When\n * omitted it is derived lazily by loading the connector config the first time a\n * telemetry/leaderboard subcommand runs.\n */\n connectorId?: string;\n}\n\n/** The runner returned by {@link createConnectorCli}. */\nexport interface ConnectorCli {\n /**\n * Run a branded invocation. `argv` defaults to `process.argv.slice(2)`.\n * Resolves to the process exit code (0 success, non-zero failure).\n */\n run(argv?: string[]): Promise<number>;\n}\n\n/**\n * Connector-targeted subcommands whose `--connector` is a CONFIG PATH: they load\n * the connector definition from disk. For these we inject the developer's config\n * PATH so their connector is the implicit target.\n *\n * (`uninstall` also accepts `--connector-id`; injecting the path is sufficient —\n * uninstall derives the id from the config when no explicit id is given.)\n */\nconst CONFIG_PATH_COMMANDS: ReadonlySet<string> = new Set([\n \"install\",\n \"uninstall\",\n \"upgrade\",\n // `sync` + `update` are back-compat aliases of `upgrade`; scope them too so a\n // branded `acme-db sync` / `acme-db update` still targets the dev connector.\n \"sync\",\n \"update\",\n \"doctor\",\n \"status\",\n \"package\",\n]);\n\n/**\n * Connector-targeted subcommands whose `--connector` is the registered connector\n * ID, spliced right AFTER the subcommand token: `serve` and `hook` pass it\n * straight to the runtime. (They cannot take a trailing flag — serve has a `--`\n * separator and hook has positionals — so the flag must lead.)\n */\nconst ID_HEAD_COMMANDS: ReadonlySet<string> = new Set([\"serve\", \"hook\"]);\n\n/**\n * View subcommands where `--connector <id>` is a FILTER appended at the END:\n * `leaderboard` (top-level) and `telemetry` (whose own sub — report|export|\n * leaderboard — is the leading positional, so the filter must come after it).\n * Appending keeps that leading positional intact while parseArgs still reads the\n * flag, so the branded tool shows ITS connector's data.\n *\n * Note: `usage` reads host CLI logs which carry no connector attribution, so it\n * is intentionally absent — there is nothing to scope it to.\n */\nconst ID_TAIL_COMMANDS: ReadonlySet<string> = new Set([\"telemetry\", \"leaderboard\"]);\n\n/**\n * Should the tail (telemetry/leaderboard) filter injection be SKIPPED because the\n * invocation is just asking for help / has no actionable sub? Skipping leaves the\n * branded usage text intact instead of turning `acme-db telemetry` into\n * `telemetry --connector <id>` (which the telemetry dispatcher would reject as an\n * unknown sub). True when a help flag appears, or when `telemetry` has no sub.\n */\nfunction wantsHelp(argv: string[]): boolean {\n if (argv.includes(\"--help\") || argv.includes(\"-h\")) return true;\n // `telemetry` with no sub-subcommand → show its help, don't inject a filter.\n if (argv[0] === \"telemetry\" && argv[1] === undefined) return true;\n return false;\n}\n\n/** Did the user already pass a --connector / --connector-id flag (any form)? */\nfunction hasConnectorFlag(argv: string[]): boolean {\n for (const a of argv) {\n if (a === \"--connector\" || a === \"--connector-id\") return true;\n if (a.startsWith(\"--connector=\") || a.startsWith(\"--connector-id=\")) return true;\n }\n return false;\n}\n\n/**\n * Splice `--connector <value>` immediately after the subcommand token (argv[0])\n * so it sits BEFORE any positionals or a `serve` `--` separator. Used for the\n * config-path commands and for serve/hook (whose `--` / positional grammar makes\n * trailing append unsafe). The original argv is never mutated.\n */\nfunction injectAfterCommand(argv: string[], flag: string, value: string): string[] {\n return [argv[0] as string, flag, value, ...argv.slice(1)];\n}\n\n/**\n * Append `--connector <value>` to the END of argv. Used for the view commands\n * (`leaderboard`/`telemetry`) whose leading positional sub must be preserved.\n * The original argv is never mutated.\n */\nfunction appendFlag(argv: string[], flag: string, value: string): string[] {\n return [...argv, flag, value];\n}\n\nexport function createConnectorCli(opts: CreateConnectorCliOptions): ConnectorCli {\n if (typeof opts.name !== \"string\" || opts.name.trim() === \"\") {\n throw new TypeError(\"createConnectorCli: `name` must be a non-empty string\");\n }\n if (typeof opts.connector !== \"string\" || opts.connector.trim() === \"\") {\n throw new TypeError(\"createConnectorCli: `connector` must be a non-empty path\");\n }\n\n // Cache the derived id so the connector module is loaded at most once across\n // repeated `.run()` calls in the same process.\n let cachedId: string | undefined = opts.connectorId;\n\n async function resolveConnectorId(): Promise<string> {\n if (cachedId !== undefined && cachedId !== \"\") return cachedId;\n const { connector } = await loadConnectorFromPath(opts.connector);\n cachedId = connector.id;\n return cachedId;\n }\n\n async function run(argv: string[] = process.argv.slice(2)): Promise<number> {\n const command = argv[0];\n\n // No subcommand, a help/version flag, or an unknown command: nothing to scope\n // — hand off verbatim so usage/version is branded and errors stay accurate.\n if (command === undefined || command.startsWith(\"-\")) {\n return main(argv, { programName: opts.name });\n }\n\n let scoped = argv;\n\n if (!hasConnectorFlag(argv)) {\n if (CONFIG_PATH_COMMANDS.has(command)) {\n // Inject the connector CONFIG PATH as the implicit target.\n scoped = injectAfterCommand(argv, \"--connector\", opts.connector);\n } else if (ID_HEAD_COMMANDS.has(command)) {\n // serve/hook take the connector ID and pass it to the runtime. Splice it\n // right after the subcommand token so a serve `--` separator and hook's\n // positionals are preserved.\n const id = await resolveConnectorId();\n scoped = injectAfterCommand(argv, \"--connector\", id);\n } else if (ID_TAIL_COMMANDS.has(command) && !wantsHelp(argv)) {\n // leaderboard/telemetry use the connector ID as a FILTER. Append it so\n // telemetry's leading positional sub (report|export|leaderboard) stays\n // the first token while parseArgs still reads the flag. We skip injection\n // for a bare/help invocation so the (un-filtered) usage text still shows.\n const id = await resolveConnectorId();\n scoped = appendFlag(argv, \"--connector\", id);\n }\n }\n\n return main(scoped, { programName: opts.name });\n }\n\n return { run };\n}\n"],"mappings":";;;;;;;;;;;;;AAiEA,IAAM,uBAA4C,oBAAI,IAAI;AAAA,EACxD;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAQD,IAAM,mBAAwC,oBAAI,IAAI,CAAC,SAAS,MAAM,CAAC;AAYvE,IAAM,mBAAwC,oBAAI,IAAI,CAAC,aAAa,aAAa,CAAC;AASlF,SAAS,UAAU,MAAyB;AAC1C,MAAI,KAAK,SAAS,QAAQ,KAAK,KAAK,SAAS,IAAI,EAAG,QAAO;AAE3D,MAAI,KAAK,CAAC,MAAM,eAAe,KAAK,CAAC,MAAM,OAAW,QAAO;AAC7D,SAAO;AACT;AAGA,SAAS,iBAAiB,MAAyB;AACjD,aAAW,KAAK,MAAM;AACpB,QAAI,MAAM,iBAAiB,MAAM,iBAAkB,QAAO;AAC1D,QAAI,EAAE,WAAW,cAAc,KAAK,EAAE,WAAW,iBAAiB,EAAG,QAAO;AAAA,EAC9E;AACA,SAAO;AACT;AAQA,SAAS,mBAAmB,MAAgB,MAAc,OAAyB;AACjF,SAAO,CAAC,KAAK,CAAC,GAAa,MAAM,OAAO,GAAG,KAAK,MAAM,CAAC,CAAC;AAC1D;AAOA,SAAS,WAAW,MAAgB,MAAc,OAAyB;AACzE,SAAO,CAAC,GAAG,MAAM,MAAM,KAAK;AAC9B;AAEO,SAAS,mBAAmB,MAA+C;AAChF,MAAI,OAAO,KAAK,SAAS,YAAY,KAAK,KAAK,KAAK,MAAM,IAAI;AAC5D,UAAM,IAAI,UAAU,uDAAuD;AAAA,EAC7E;AACA,MAAI,OAAO,KAAK,cAAc,YAAY,KAAK,UAAU,KAAK,MAAM,IAAI;AACtE,UAAM,IAAI,UAAU,0DAA0D;AAAA,EAChF;AAIA,MAAI,WAA+B,KAAK;AAExC,iBAAe,qBAAsC;AACnD,QAAI,aAAa,UAAa,aAAa,GAAI,QAAO;AACtD,UAAM,EAAE,UAAU,IAAI,MAAM,sBAAsB,KAAK,SAAS;AAChE,eAAW,UAAU;AACrB,WAAO;AAAA,EACT;AAEA,iBAAe,IAAI,OAAiB,QAAQ,KAAK,MAAM,CAAC,GAAoB;AAC1E,UAAM,UAAU,KAAK,CAAC;AAItB,QAAI,YAAY,UAAa,QAAQ,WAAW,GAAG,GAAG;AACpD,aAAO,KAAK,MAAM,EAAE,aAAa,KAAK,KAAK,CAAC;AAAA,IAC9C;AAEA,QAAI,SAAS;AAEb,QAAI,CAAC,iBAAiB,IAAI,GAAG;AAC3B,UAAI,qBAAqB,IAAI,OAAO,GAAG;AAErC,iBAAS,mBAAmB,MAAM,eAAe,KAAK,SAAS;AAAA,MACjE,WAAW,iBAAiB,IAAI,OAAO,GAAG;AAIxC,cAAM,KAAK,MAAM,mBAAmB;AACpC,iBAAS,mBAAmB,MAAM,eAAe,EAAE;AAAA,MACrD,WAAW,iBAAiB,IAAI,OAAO,KAAK,CAAC,UAAU,IAAI,GAAG;AAK5D,cAAM,KAAK,MAAM,mBAAmB;AACpC,iBAAS,WAAW,MAAM,eAAe,EAAE;AAAA,MAC7C;AAAA,IACF;AAEA,WAAO,KAAK,QAAQ,EAAE,aAAa,KAAK,KAAK,CAAC;AAAA,EAChD;AAEA,SAAO,EAAE,IAAI;AACf;","names":[]}
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  main
4
- } from "./chunk-3RBLIHPZ.js";
4
+ } from "./chunk-KGXDYGNJ.js";
5
5
 
6
6
  // src/cli/index.ts
7
7
  main(process.argv.slice(2)).then((code) => {
@@ -4,12 +4,12 @@ import {
4
4
  } from "./chunk-DBQMX75U.js";
5
5
  import {
6
6
  BaseAdapter
7
- } from "./chunk-PD4VFEBY.js";
7
+ } from "./chunk-IW77FFNX.js";
8
8
  import "./chunk-7L6ITC4T.js";
9
9
  import {
10
10
  buildServeWrapperCommand,
11
11
  shouldWrapForTelemetry
12
- } from "./chunk-MEH7GC7R.js";
12
+ } from "./chunk-BXGFUENQ.js";
13
13
  import "./chunk-N6HH7K6P.js";
14
14
  import "./chunk-TRQKHP7D.js";
15
15
 
@@ -61,7 +61,13 @@ var CodebuffAdapter = class extends BaseAdapter {
61
61
  canModifyOutput: false,
62
62
  canInjectSessionContext: false,
63
63
  // Codebuff registers stdio and Streamable HTTP MCP servers.
64
- transports: ["stdio", "http"]
64
+ transports: ["stdio", "http"],
65
+ // Content surfaces: Codebuff reads AgentSkills from
66
+ // <configDir>/skills/<name>/SKILL.md (configDir is .agents, so the path is
67
+ // .agents/skills/<name>/SKILL.md). Verified against codebuff source
68
+ // sdk/src/skills/load-skills.ts — the frontmatter `name` MUST equal the dir
69
+ // name. Commands / subagents have no native Codebuff surface.
70
+ supportsSkills: true
65
71
  };
66
72
  // ── Detection ────────────────────────────────────────────────────────────
67
73
  detectInstalled(projectDir) {
@@ -169,6 +175,89 @@ var CodebuffAdapter = class extends BaseAdapter {
169
175
  if (!env || Object.keys(env).length === 0) return void 0;
170
176
  return rewriteEnvRefsDeep({ ...env });
171
177
  }
178
+ // ── Content surfaces: skills ──────────────────────────────────────────────
179
+ // CONTENT-ONLY: pure native-file writers. No runtime dispatch, no home-bin
180
+ // pointer, no telemetry wrap. Each method is idempotent (byte-identical →
181
+ // skip) via writeContentFile and reversible via removeContentFile. Honors
182
+ // platforms["codebuff"].skills === false to skip. Both user and project scope
183
+ // are supported (configDir resolves per scope).
184
+ //
185
+ // Native location:
186
+ // skill → <configDir>/skills/<name>/SKILL.md (+ resources)
187
+ // configDir is .agents, so .agents/skills/<name>/SKILL.md. Verified
188
+ // against codebuff source sdk/src/skills/load-skills.ts — the
189
+ // frontmatter `name` MUST equal the dir name.
190
+ skillDir(ctx, name) {
191
+ return join(this.getConfigDir(ctx), "skills", name);
192
+ }
193
+ installSkills(ctx) {
194
+ const { connector } = ctx;
195
+ if (connector.platforms[HOST]?.skills === false) {
196
+ return [{ platform: this.id, action: "skip", detail: "skills disabled for codebuff" }];
197
+ }
198
+ if (connector.skills.length === 0) {
199
+ return [{ platform: this.id, action: "skip", detail: "connector declares no skills" }];
200
+ }
201
+ const changes = [];
202
+ for (const skill of connector.skills) {
203
+ const dir = this.skillDir(ctx, skill.name);
204
+ changes.push(
205
+ this.writeContentFile(join(dir, "SKILL.md"), this.renderSkill(skill), ctx.dryRun)
206
+ );
207
+ for (const [rel, contents] of Object.entries(skill.resources ?? {})) {
208
+ const target = this.resolveWithin(dir, rel);
209
+ if (target === null) {
210
+ changes.push({
211
+ platform: this.id,
212
+ action: "warn",
213
+ detail: `skill resource "${rel}" escapes the skill dir; skipped`
214
+ });
215
+ continue;
216
+ }
217
+ changes.push(this.writeContentFile(target, contents, ctx.dryRun));
218
+ }
219
+ }
220
+ return changes;
221
+ }
222
+ uninstallSkills(ctx) {
223
+ const { connector } = ctx;
224
+ if (connector.skills.length === 0) {
225
+ return [{ platform: this.id, action: "skip", detail: "connector declares no skills" }];
226
+ }
227
+ const changes = [];
228
+ for (const skill of connector.skills) {
229
+ const dir = this.skillDir(ctx, skill.name);
230
+ changes.push(this.removeContentFile(join(dir, "SKILL.md"), ctx.dryRun));
231
+ for (const rel of Object.keys(skill.resources ?? {})) {
232
+ const target = this.resolveWithin(dir, rel);
233
+ if (target === null) continue;
234
+ changes.push(this.removeContentFile(target, ctx.dryRun));
235
+ }
236
+ changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));
237
+ }
238
+ return changes;
239
+ }
240
+ /**
241
+ * Render a skill's SKILL.md: frontmatter (name, description + optional model,
242
+ * allowed-tools, disable-model-invocation) + body. UNIFORM with every other
243
+ * skill-supporting platform — only the parent dir differs. Codebuff requires
244
+ * the frontmatter `name` to equal the dir name (load-skills.ts), which holds
245
+ * because skillDir uses skill.name for both.
246
+ */
247
+ renderSkill(skill) {
248
+ const frontmatter = {
249
+ name: skill.name,
250
+ description: skill.description
251
+ };
252
+ if (skill.model !== void 0) frontmatter.model = skill.model;
253
+ const allow = skill.tools?.allow;
254
+ if (allow && allow.length > 0) frontmatter["allowed-tools"] = allow.join(", ");
255
+ if (skill.disableModelInvocation !== void 0) {
256
+ frontmatter["disable-model-invocation"] = skill.disableModelInvocation;
257
+ }
258
+ if (skill.extra) Object.assign(frontmatter, skill.extra);
259
+ return this.renderFrontmatterMd(frontmatter, skill.body);
260
+ }
172
261
  // ── Hooks (unavailable — Codebuff is mcp-only) ────────────────────────────
173
262
  installHooks(_ctx) {
174
263
  return [
@@ -192,7 +281,7 @@ var CodebuffAdapter = class extends BaseAdapter {
192
281
  getHealthChecks(ctx) {
193
282
  const mcpPath = this.getServerConfigPath(ctx);
194
283
  const connectorId = ctx.connector.id;
195
- return [
284
+ const checks = [
196
285
  {
197
286
  name: `${this.name}: mcp.json present`,
198
287
  check: () => existsSync(mcpPath) ? { status: "OK", detail: mcpPath } : { status: "FAIL", detail: `not found: ${mcpPath}` }
@@ -215,6 +304,14 @@ var CodebuffAdapter = class extends BaseAdapter {
215
304
  }
216
305
  }
217
306
  ];
307
+ for (const skill of ctx.connector.skills) {
308
+ const p = join(this.skillDir(ctx, skill.name), "SKILL.md");
309
+ checks.push({
310
+ name: `${this.name}: skill ${skill.name} present`,
311
+ check: () => existsSync(p) ? { status: "OK", detail: p } : { status: "FAIL", detail: `not found: ${p}` }
312
+ });
313
+ }
314
+ return checks;
218
315
  }
219
316
  };
220
317
  var adapter = new CodebuffAdapter();
@@ -224,4 +321,4 @@ export {
224
321
  adapter,
225
322
  codebuff_default as default
226
323
  };
227
- //# sourceMappingURL=codebuff-LE3KBZGM.js.map
324
+ //# sourceMappingURL=codebuff-SH2S3QAN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/codebuff/index.ts"],"sourcesContent":["/**\n * adapters/codebuff — Codebuff platform adapter for agent-connector.\n *\n * Codebuff is an **mcp-only** host: it exposes no lifecycle hook system, and MCP\n * is its extensibility mechanism. This adapter therefore installs only the MCP\n * server and reports hooks as unavailable (mirrors the Warp reference path that\n * validates the `mcp-only` paradigm end-to-end).\n *\n * MCP config (SPEC):\n * - project scope (preferred) → <projectDir>/.agents/mcp.json\n * - user scope → ~/.agents/mcp.json\n * Both are JSON, root key \"mcpServers\". There is no separate hook file — the\n * hook \"config path\" is the same mcp.json so the generic doctor/backup behave\n * sensibly.\n *\n * A stdio server entry is the standard `{ type:\"stdio\", command, args, env }`\n * shape. Codebuff supports native `$VAR` interpolation, so `${env:VAR}` refs are\n * rewritten to Codebuff's native `$VAR` token (rewriteEnvRefs) rather than being\n * resolved to literals — secrets are never baked into the config file.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport type { Adapter, InstallContext } from \"../spi.js\";\nimport type {\n ChangeRecord,\n DetectedPlatform,\n HealthCheck,\n HookParadigm,\n PlatformCapabilities,\n PlatformId,\n ServerDef,\n SkillDef,\n Transport,\n} from \"../../core/types.js\";\nimport { rewriteEnvRefs } from \"../../core/interpolate.js\";\nimport {\n buildServeWrapperCommand,\n shouldWrapForTelemetry,\n} from \"../../core/spawn.js\";\n\nconst HOST: PlatformId = \"codebuff\";\nconst MCP_ROOT_KEY = \"mcpServers\";\n\n/**\n * Render `${env:VAR}`/`${env:VAR:-default}` into Codebuff's native `$VAR` token.\n *\n * When the portable ref carried a default (`${env:VAR:-fallback}`), Codebuff's\n * native `$VAR` token cannot express it — so a bare native token would silently\n * DROP the default. Instead, resolve the default at install time: emit the live\n * value when VAR is set and non-empty, else the literal fallback. The native\n * token is only emitted when there is no default to preserve.\n */\nconst toNativeRef = (name: string, def?: string): string => {\n if (def !== undefined) {\n const v = process.env[name];\n return v != null && v !== \"\" ? v : def;\n }\n return `$${name}`;\n};\n\n/** Recursively rewrite every `${env:VAR}` ref in a JSON-ish value to `$VAR`. */\nfunction rewriteEnvRefsDeep<T>(value: T): T {\n if (typeof value === \"string\") {\n return rewriteEnvRefs(value, toNativeRef) as unknown as T;\n }\n if (Array.isArray(value)) {\n return value.map((v) => rewriteEnvRefsDeep(v)) as unknown as T;\n }\n if (value && typeof value === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value)) out[k] = rewriteEnvRefsDeep(v);\n return out as T;\n }\n return value;\n}\n\n/**\n * Native MCP server entry shapes Codebuff accepts under `mcpServers`.\n * A stdio entry is tagged with `type:\"stdio\"`; remote transports carry a `url`.\n */\ninterface CodebuffStdioServer {\n type: \"stdio\";\n command: string;\n args?: string[];\n env?: Record<string, string>;\n}\ninterface CodebuffHttpServer {\n type: \"http\";\n url: string;\n headers?: Record<string, string>;\n}\n\nexport class CodebuffAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"Codebuff\";\n readonly paradigm: HookParadigm = \"mcp-only\";\n\n readonly capabilities: PlatformCapabilities = {\n // Memory surface: AGENTS.md-first managed block via the BaseAdapter default\n // (memoryTargets: project <projectDir>/AGENTS.md; user scope where documented).\n supportsMemory: true,\n // Codebuff has no lifecycle hook system — every hook capability is false.\n preToolUse: false,\n postToolUse: false,\n preCompact: false,\n sessionStart: false,\n sessionEnd: false,\n userPromptSubmit: false,\n stop: false,\n notification: false,\n canModifyArgs: false,\n canModifyOutput: false,\n canInjectSessionContext: false,\n // Codebuff registers stdio and Streamable HTTP MCP servers.\n transports: [\"stdio\", \"http\"],\n // Content surfaces: Codebuff reads AgentSkills from\n // <configDir>/skills/<name>/SKILL.md (configDir is .agents, so the path is\n // .agents/skills/<name>/SKILL.md). Verified against codebuff source\n // sdk/src/skills/load-skills.ts — the frontmatter `name` MUST equal the dir\n // name. Commands / subagents have no native Codebuff surface.\n supportsSkills: true,\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userDir = join(homedir(), \".agents\");\n const userMcp = join(userDir, \"mcp.json\");\n const projDir = join(projectDir, \".agents\");\n const projMcp = join(projDir, \"mcp.json\");\n\n const userInstalled = existsSync(userDir) || existsSync(userMcp);\n const projInstalled = existsSync(projDir) || existsSync(projMcp);\n const installed = userInstalled || projInstalled;\n // Project is the preferred scope; fall back to user when only that matched.\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\n const configPath = scope === \"project\" ? projMcp : userMcp;\n\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath,\n scope,\n reason: installed\n ? `found Codebuff config (${scope})`\n : `no .agents config dir at ${userDir} or ${projDir}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n getConfigDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".agents\")\n : join(homedir(), \".agents\");\n }\n\n getServerConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"mcp.json\");\n }\n\n /**\n * Codebuff has no hook file — hooks are not a thing here. The hook \"config\n * path\" is the same mcp.json so the generic doctor/backup behave sensibly.\n */\n getHookConfigPath(ctx: InstallContext): string {\n return this.getServerConfigPath(ctx);\n }\n\n // ── MCP server install / uninstall ───────────────────────────────────────\n\n installServer(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const override = connector.platforms[HOST]?.server;\n if (!connector.server || override === false) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: connector.server\n ? \"server registration disabled for codebuff\"\n : \"connector declares no MCP server\",\n },\n ];\n }\n\n // Shallow-merge any per-platform server override into the base ServerDef.\n const server: ServerDef =\n override && typeof override === \"object\"\n ? { ...connector.server, ...override }\n : connector.server;\n\n const serverPath = this.getServerConfigPath(ctx);\n const entry = this.renderServerEntry(ctx, server);\n\n return [\n this.upsertServerInJson(serverPath, MCP_ROOT_KEY, connector.id, entry, ctx.dryRun),\n ];\n }\n\n uninstallServer(ctx: InstallContext): ChangeRecord[] {\n const serverPath = this.getServerConfigPath(ctx);\n return [\n this.removeServerFromJson(serverPath, MCP_ROOT_KEY, ctx.connector.id, ctx.dryRun),\n ];\n }\n\n /** Render a normalized ServerDef into Codebuff's native mcpServers entry. */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): CodebuffStdioServer | CodebuffHttpServer {\n const transport: Transport = server.transport;\n\n if (transport === \"stdio\") {\n let command = server.command ?? \"\";\n let args = [...(server.args ?? [])];\n\n // Transparent telemetry wrapping: route the real command through\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\n if (shouldWrapForTelemetry(server, ctx.connector.telemetry)) {\n const wrapped = buildServeWrapperCommand(\n ctx.homeBinPath,\n ctx.connector.id,\n command,\n args,\n ctx.scope,\n this.id,\n );\n command = wrapped.command;\n args = wrapped.args;\n }\n\n // Codebuff supports native `$VAR` interpolation, so rewrite every\n // ${env:VAR} ref to `$VAR` rather than baking literals into the config.\n const entry: CodebuffStdioServer = {\n type: \"stdio\",\n command: rewriteEnvRefsDeep(command),\n };\n if (args.length > 0) entry.args = rewriteEnvRefsDeep(args);\n const env = this.renderEnv(server.env);\n if (env) entry.env = env;\n return entry;\n }\n\n // http (and any other remote transport) — Codebuff registers a URL.\n const entry: CodebuffHttpServer = {\n type: \"http\",\n url: rewriteEnvRefsDeep(server.url ?? \"\"),\n };\n const headers = this.renderEnv(server.headers);\n if (headers) entry.headers = headers;\n return entry;\n }\n\n /**\n * Render env/header values. Codebuff supports native `$VAR` interpolation, so\n * rewrite `${env:VAR}` references to `$VAR` rather than resolving to literals.\n */\n private renderEnv(\n env: Record<string, string> | undefined,\n ): Record<string, string> | undefined {\n if (!env || Object.keys(env).length === 0) return undefined;\n return rewriteEnvRefsDeep({ ...env });\n }\n\n // ── Content surfaces: skills ──────────────────────────────────────────────\n // CONTENT-ONLY: pure native-file writers. No runtime dispatch, no home-bin\n // pointer, no telemetry wrap. Each method is idempotent (byte-identical →\n // skip) via writeContentFile and reversible via removeContentFile. Honors\n // platforms[\"codebuff\"].skills === false to skip. Both user and project scope\n // are supported (configDir resolves per scope).\n //\n // Native location:\n // skill → <configDir>/skills/<name>/SKILL.md (+ resources)\n // configDir is .agents, so .agents/skills/<name>/SKILL.md. Verified\n // against codebuff source sdk/src/skills/load-skills.ts — the\n // frontmatter `name` MUST equal the dir name.\n\n private skillDir(ctx: InstallContext, name: string): string {\n return join(this.getConfigDir(ctx), \"skills\", name);\n }\n\n override installSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.skills === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"skills disabled for codebuff\" }];\n }\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n changes.push(\n this.writeContentFile(join(dir, \"SKILL.md\"), this.renderSkill(skill), ctx.dryRun),\n );\n // Bundle any resource files beside SKILL.md (relative path → contents).\n // Defense-in-depth: skip+warn on any key that escapes the skill dir\n // (config-time validation already rejects these, but never trust input).\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n detail: `skill resource \"${rel}\" escapes the skill dir; skipped`,\n });\n continue;\n }\n changes.push(this.writeContentFile(target, contents, ctx.dryRun));\n }\n }\n return changes;\n }\n\n override uninstallSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n // Remove only the files we wrote (SKILL.md + declared resources), then the\n // skill dir itself when we own its full contents.\n changes.push(this.removeContentFile(join(dir, \"SKILL.md\"), ctx.dryRun));\n for (const rel of Object.keys(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) continue; // never delete outside the skill dir\n changes.push(this.removeContentFile(target, ctx.dryRun));\n }\n // Only remove the skill dir when WE own its full contents — never rm -rf a\n // dir that still holds user-added / sibling-tool / shared files.\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\n }\n return changes;\n }\n\n /**\n * Render a skill's SKILL.md: frontmatter (name, description + optional model,\n * allowed-tools, disable-model-invocation) + body. UNIFORM with every other\n * skill-supporting platform — only the parent dir differs. Codebuff requires\n * the frontmatter `name` to equal the dir name (load-skills.ts), which holds\n * because skillDir uses skill.name for both.\n */\n private renderSkill(skill: SkillDef): string {\n const frontmatter: Record<string, unknown> = {\n name: skill.name,\n description: skill.description,\n };\n if (skill.model !== undefined) frontmatter.model = skill.model;\n const allow = skill.tools?.allow;\n if (allow && allow.length > 0) frontmatter[\"allowed-tools\"] = allow.join(\", \");\n if (skill.disableModelInvocation !== undefined) {\n frontmatter[\"disable-model-invocation\"] = skill.disableModelInvocation;\n }\n if (skill.extra) Object.assign(frontmatter, skill.extra);\n return this.renderFrontmatterMd(frontmatter, skill.body);\n }\n\n // ── Hooks (unavailable — Codebuff is mcp-only) ────────────────────────────\n\n installHooks(_ctx: InstallContext): ChangeRecord[] {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: \"hooks unavailable (Codebuff is mcp-only)\",\n },\n ];\n }\n\n uninstallHooks(_ctx: InstallContext): ChangeRecord[] {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: \"hooks unavailable (Codebuff is mcp-only)\",\n },\n ];\n }\n\n // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const mcpPath = this.getServerConfigPath(ctx);\n const connectorId = ctx.connector.id;\n const checks: HealthCheck[] = [\n {\n name: `${this.name}: mcp.json present`,\n check: () =>\n existsSync(mcpPath)\n ? { status: \"OK\", detail: mcpPath }\n : { status: \"FAIL\", detail: `not found: ${mcpPath}` },\n },\n {\n name: `${this.name}: server entry registered`,\n check: () => {\n // Only assert what the connector declares: a server-less connector\n // never writes a server entry, so its absence is healthy.\n if (!ctx.connector.server) {\n return { status: \"OK\", detail: \"no MCP server declared\" };\n }\n const cfg = this.readJson<{ [k: string]: Record<string, unknown> }>(mcpPath);\n const bucket = cfg?.[MCP_ROOT_KEY];\n if (!cfg || !bucket) {\n return { status: \"FAIL\", detail: `no ${MCP_ROOT_KEY} in ${mcpPath}` };\n }\n return connectorId in bucket\n ? { status: \"OK\", detail: `${MCP_ROOT_KEY}.${connectorId} present` }\n : {\n status: \"FAIL\",\n detail: `no ${MCP_ROOT_KEY}.${connectorId} in ${mcpPath}`,\n };\n },\n },\n ];\n\n // Content-surface checks: assert presence only for the skills this connector\n // declares (a skill-less connector writes none, so absence is healthy).\n for (const skill of ctx.connector.skills) {\n const p = join(this.skillDir(ctx, skill.name), \"SKILL.md\");\n checks.push({\n name: `${this.name}: skill ${skill.name} present`,\n check: () =>\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\n });\n }\n return checks;\n }\n}\n\nexport const adapter = new CodebuffAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}