@ken-jo/agent-connector 0.4.43 → 0.4.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -4
- package/dist/{action-ZUHMOGLV.js → action-AIB2W4DU.js} +12 -12
- package/dist/{amazon-q-UFLBUSHG.js → amazon-q-PH7OFPJD.js} +7 -11
- package/dist/amazon-q-PH7OFPJD.js.map +1 -0
- package/dist/{amp-5DJK7VAL.js → amp-ZYRC2VCH.js} +38 -63
- package/dist/amp-ZYRC2VCH.js.map +1 -0
- package/dist/{antigravity-NWP2TUG6.js → antigravity-PM5NMS2J.js} +5 -5
- package/dist/{antigravity-cli-KPNLE7X4.js → antigravity-cli-LN25XGWX.js} +5 -5
- package/dist/{chunk-LETB5HCK.js → chunk-3QCDVSMX.js} +2 -2
- package/dist/{chunk-ERV4TKRV.js → chunk-4K5HEGVE.js} +2 -2
- package/dist/{chunk-H3BATOBP.js → chunk-AAOYOAQT.js} +2 -2
- package/dist/{chunk-2RPHDVHW.js → chunk-AEQRMVRB.js} +2 -2
- package/dist/{chunk-L7ESV37V.js → chunk-BZOOVTFG.js} +4 -2
- package/dist/chunk-BZOOVTFG.js.map +1 -0
- package/dist/{chunk-3Q6YEDCG.js → chunk-C3TFA4CJ.js} +17 -45
- package/dist/chunk-C3TFA4CJ.js.map +1 -0
- package/dist/{chunk-QY42WGBX.js → chunk-D65GIBCG.js} +34 -3
- package/dist/chunk-D65GIBCG.js.map +1 -0
- package/dist/{chunk-RAJBLK2V.js → chunk-FVARNRCE.js} +26 -10
- package/dist/chunk-FVARNRCE.js.map +1 -0
- package/dist/{chunk-A767JFHW.js → chunk-GI4FDVWI.js} +65 -35
- package/dist/chunk-GI4FDVWI.js.map +1 -0
- package/dist/{chunk-5HSLICR3.js → chunk-IDKI42JW.js} +36 -36
- package/dist/{chunk-54B5HAVT.js → chunk-JZIM33C2.js} +10 -7
- package/dist/chunk-JZIM33C2.js.map +1 -0
- package/dist/{chunk-3ZZK4KXG.js → chunk-KAEYJGK7.js} +18 -18
- package/dist/{chunk-ZY25RG4Y.js → chunk-LBOGRZGY.js} +4 -2
- package/dist/chunk-LBOGRZGY.js.map +1 -0
- package/dist/{chunk-VDSXVNEH.js → chunk-NFMHYIN2.js} +5 -5
- package/dist/{chunk-XW46WVR2.js → chunk-O3HIYTBK.js} +10 -5
- package/dist/chunk-O3HIYTBK.js.map +1 -0
- package/dist/{chunk-AQ53TOH4.js → chunk-O4BKQSPP.js} +7 -4
- package/dist/chunk-O4BKQSPP.js.map +1 -0
- package/dist/{chunk-YG3KFOOQ.js → chunk-QP35SRUZ.js} +2 -2
- package/dist/{chunk-4CBHYWUG.js → chunk-RFYQXT7C.js} +7 -7
- package/dist/{chunk-5TMIJ7AY.js → chunk-RGQTN7K3.js} +5 -5
- package/dist/{chunk-M3H7PQWT.js → chunk-WOUGWPZQ.js} +4 -2
- package/dist/chunk-WOUGWPZQ.js.map +1 -0
- package/dist/{chunk-F4DSMVZ7.js → chunk-ZQCT63JU.js} +2 -2
- package/dist/{claude-code-YNNKQCCR.js → claude-code-GCXXEWUN.js} +15 -8
- package/dist/claude-code-GCXXEWUN.js.map +1 -0
- package/dist/cli/sdk.js +7 -7
- package/dist/cli.js +1 -1
- package/dist/{cline-AGFJF4AC.js → cline-KHZLG7CU.js} +4 -4
- package/dist/{codebuff-YUQ4PN7G.js → codebuff-EQGWZEP4.js} +4 -4
- package/dist/{codex-FLU37DV3.js → codex-7X7RC6JJ.js} +32 -6
- package/dist/codex-7X7RC6JJ.js.map +1 -0
- package/dist/{continue-ZMI4YN75.js → continue-V4MB3WQ3.js} +9 -5
- package/dist/continue-V4MB3WQ3.js.map +1 -0
- package/dist/{copilot-cli-XPRJ5MQB.js → copilot-cli-7EPIJHFM.js} +12 -32
- package/dist/copilot-cli-7EPIJHFM.js.map +1 -0
- package/dist/{crush-3OB5ZTCC.js → crush-3AAA75C5.js} +4 -4
- package/dist/{cursor-F4HYO2FP.js → cursor-DTYZROKS.js} +5 -5
- package/dist/{detect-FXGBSNQU.js → detect-LWZEM7SN.js} +4 -4
- package/dist/{doctor-2O65SAPG.js → doctor-54P4JFA6.js} +14 -14
- package/dist/{droid-NZCKYKOV.js → droid-QMNO5WZ2.js} +6 -12
- package/dist/droid-QMNO5WZ2.js.map +1 -0
- package/dist/{gemini-cli-3ZGCXUDD.js → gemini-cli-7JU7ZWQL.js} +19 -6
- package/dist/gemini-cli-7JU7ZWQL.js.map +1 -0
- package/dist/{goose-MGGNVXJP.js → goose-36TJNDKD.js} +16 -22
- package/dist/goose-36TJNDKD.js.map +1 -0
- package/dist/{hermes-L3CBJ37L.js → hermes-S4JZ6H42.js} +44 -22
- package/dist/hermes-S4JZ6H42.js.map +1 -0
- package/dist/{hook-D3PY6TDK.js → hook-UT3Q43AB.js} +12 -12
- package/dist/index.d.ts +2 -2
- package/dist/index.js +5 -5
- package/dist/{install-SVBIK4VJ.js → install-F4OIDYAK.js} +14 -14
- package/dist/{introspect-B164-hj3.d.ts → introspect-BFcXpfUp.d.ts} +1 -1
- package/dist/{jetbrains-copilot-M2LHJBAW.js → jetbrains-copilot-6QLKUCAY.js} +17 -12
- package/dist/jetbrains-copilot-6QLKUCAY.js.map +1 -0
- package/dist/{kilo-RMRP2EL7.js → kilo-WLZOYKZK.js} +18 -55
- package/dist/kilo-WLZOYKZK.js.map +1 -0
- package/dist/{kilo-cli-6ITBNHTH.js → kilo-cli-FBX4OFIZ.js} +18 -55
- package/dist/kilo-cli-FBX4OFIZ.js.map +1 -0
- package/dist/{kimi-I35VOOY4.js → kimi-7YXRAQ6Z.js} +28 -14
- package/dist/kimi-7YXRAQ6Z.js.map +1 -0
- package/dist/{kiro-2K5UJVGC.js → kiro-CSBQA6EX.js} +5 -5
- package/dist/kiro-CSBQA6EX.js.map +1 -0
- package/dist/{leaderboard-ZMZST52G.js → leaderboard-ZIAXBUWD.js} +5 -5
- package/dist/{mimo-code-K7AMX2QW.js → mimo-code-GYJNEULG.js} +21 -56
- package/dist/mimo-code-GYJNEULG.js.map +1 -0
- package/dist/{mux-GT7FWVLH.js → mux-DAIC3VY7.js} +4 -4
- package/dist/{nemoclaw-GQMS6CUM.js → nemoclaw-GS3XA7V2.js} +5 -5
- package/dist/{omp-2RPYIZUF.js → omp-O6KNB4MM.js} +17 -46
- package/dist/omp-O6KNB4MM.js.map +1 -0
- package/dist/{openclaw-P5GMEEGC.js → openclaw-344VBMLY.js} +5 -5
- package/dist/{opencode-5D2SK3EX.js → opencode-JPHRZPDQ.js} +21 -56
- package/dist/opencode-JPHRZPDQ.js.map +1 -0
- package/dist/{package-EDYQF6C6.js → package-5FRMSWRT.js} +11 -11
- package/dist/{pi-ZMM4KJTO.js → pi-EFBTBI2B.js} +4 -4
- package/dist/{qwen-code-4ZLVGN2C.js → qwen-code-CLSMTMHX.js} +12 -5
- package/dist/qwen-code-CLSMTMHX.js.map +1 -0
- package/dist/{roo-code-67QGLQRM.js → roo-code-YIX3RPR2.js} +4 -4
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +10 -10
- package/dist/sdk/index.d.ts +3 -3
- package/dist/sdk/index.js +6 -6
- package/dist/sdk/test.d.ts +2 -2
- package/dist/sdk/test.js +9 -9
- package/dist/{serve-427CCEYA.js → serve-NQBXN4FG.js} +12 -12
- package/dist/{status-6IHRW6PI.js → status-5ZM6LXHV.js} +10 -10
- package/dist/{statusline-2CKH5RHO.js → statusline-O76BCBUK.js} +11 -11
- package/dist/{telemetry-WNVKL7HW.js → telemetry-NO7UUUSJ.js} +10 -10
- package/dist/{trae-TMJPHWZ5.js → trae-JESXQKAF.js} +4 -4
- package/dist/{types-COSBYpKs.d.ts → types-ChUrvw0j.d.ts} +8 -8
- package/dist/{uninstall-QFCDXGKR.js → uninstall-QCROBR6A.js} +14 -14
- package/dist/{upgrade-PP46DURC.js → upgrade-KJ4QRZDZ.js} +14 -14
- package/dist/{usage-VDORZJPT.js → usage-UY6DCND6.js} +2 -2
- package/dist/{usage-event-4533OURF.js → usage-event-T4HWQDZF.js} +11 -11
- package/dist/{vscode-copilot-H7JKUKLZ.js → vscode-copilot-56USZ5X4.js} +26 -19
- package/dist/vscode-copilot-56USZ5X4.js.map +1 -0
- package/dist/{warp-SVDVKQQI.js → warp-Y6JNLLGR.js} +4 -4
- package/dist/{windsurf-H36YKOMR.js → windsurf-X7QCJ3XR.js} +4 -4
- package/dist/{zed-LHWJALLZ.js → zed-L3ML5MHF.js} +4 -4
- package/package.json +2 -1
- package/dist/amazon-q-UFLBUSHG.js.map +0 -1
- package/dist/amp-5DJK7VAL.js.map +0 -1
- package/dist/chunk-3Q6YEDCG.js.map +0 -1
- package/dist/chunk-54B5HAVT.js.map +0 -1
- package/dist/chunk-A767JFHW.js.map +0 -1
- package/dist/chunk-AQ53TOH4.js.map +0 -1
- package/dist/chunk-L7ESV37V.js.map +0 -1
- package/dist/chunk-M3H7PQWT.js.map +0 -1
- package/dist/chunk-QY42WGBX.js.map +0 -1
- package/dist/chunk-RAJBLK2V.js.map +0 -1
- package/dist/chunk-XW46WVR2.js.map +0 -1
- package/dist/chunk-ZY25RG4Y.js.map +0 -1
- package/dist/claude-code-YNNKQCCR.js.map +0 -1
- package/dist/codex-FLU37DV3.js.map +0 -1
- package/dist/continue-ZMI4YN75.js.map +0 -1
- package/dist/copilot-cli-XPRJ5MQB.js.map +0 -1
- package/dist/droid-NZCKYKOV.js.map +0 -1
- package/dist/gemini-cli-3ZGCXUDD.js.map +0 -1
- package/dist/goose-MGGNVXJP.js.map +0 -1
- package/dist/hermes-L3CBJ37L.js.map +0 -1
- package/dist/jetbrains-copilot-M2LHJBAW.js.map +0 -1
- package/dist/kilo-RMRP2EL7.js.map +0 -1
- package/dist/kilo-cli-6ITBNHTH.js.map +0 -1
- package/dist/kimi-I35VOOY4.js.map +0 -1
- package/dist/kiro-2K5UJVGC.js.map +0 -1
- package/dist/mimo-code-K7AMX2QW.js.map +0 -1
- package/dist/omp-2RPYIZUF.js.map +0 -1
- package/dist/opencode-5D2SK3EX.js.map +0 -1
- package/dist/qwen-code-4ZLVGN2C.js.map +0 -1
- package/dist/vscode-copilot-H7JKUKLZ.js.map +0 -1
- /package/dist/{action-ZUHMOGLV.js.map → action-AIB2W4DU.js.map} +0 -0
- /package/dist/{antigravity-NWP2TUG6.js.map → antigravity-PM5NMS2J.js.map} +0 -0
- /package/dist/{antigravity-cli-KPNLE7X4.js.map → antigravity-cli-LN25XGWX.js.map} +0 -0
- /package/dist/{chunk-LETB5HCK.js.map → chunk-3QCDVSMX.js.map} +0 -0
- /package/dist/{chunk-ERV4TKRV.js.map → chunk-4K5HEGVE.js.map} +0 -0
- /package/dist/{chunk-H3BATOBP.js.map → chunk-AAOYOAQT.js.map} +0 -0
- /package/dist/{chunk-2RPHDVHW.js.map → chunk-AEQRMVRB.js.map} +0 -0
- /package/dist/{chunk-5HSLICR3.js.map → chunk-IDKI42JW.js.map} +0 -0
- /package/dist/{chunk-3ZZK4KXG.js.map → chunk-KAEYJGK7.js.map} +0 -0
- /package/dist/{chunk-VDSXVNEH.js.map → chunk-NFMHYIN2.js.map} +0 -0
- /package/dist/{chunk-YG3KFOOQ.js.map → chunk-QP35SRUZ.js.map} +0 -0
- /package/dist/{chunk-4CBHYWUG.js.map → chunk-RFYQXT7C.js.map} +0 -0
- /package/dist/{chunk-5TMIJ7AY.js.map → chunk-RGQTN7K3.js.map} +0 -0
- /package/dist/{chunk-F4DSMVZ7.js.map → chunk-ZQCT63JU.js.map} +0 -0
- /package/dist/{cline-AGFJF4AC.js.map → cline-KHZLG7CU.js.map} +0 -0
- /package/dist/{codebuff-YUQ4PN7G.js.map → codebuff-EQGWZEP4.js.map} +0 -0
- /package/dist/{crush-3OB5ZTCC.js.map → crush-3AAA75C5.js.map} +0 -0
- /package/dist/{cursor-F4HYO2FP.js.map → cursor-DTYZROKS.js.map} +0 -0
- /package/dist/{detect-FXGBSNQU.js.map → detect-LWZEM7SN.js.map} +0 -0
- /package/dist/{doctor-2O65SAPG.js.map → doctor-54P4JFA6.js.map} +0 -0
- /package/dist/{hook-D3PY6TDK.js.map → hook-UT3Q43AB.js.map} +0 -0
- /package/dist/{install-SVBIK4VJ.js.map → install-F4OIDYAK.js.map} +0 -0
- /package/dist/{leaderboard-ZMZST52G.js.map → leaderboard-ZIAXBUWD.js.map} +0 -0
- /package/dist/{mux-GT7FWVLH.js.map → mux-DAIC3VY7.js.map} +0 -0
- /package/dist/{nemoclaw-GQMS6CUM.js.map → nemoclaw-GS3XA7V2.js.map} +0 -0
- /package/dist/{openclaw-P5GMEEGC.js.map → openclaw-344VBMLY.js.map} +0 -0
- /package/dist/{package-EDYQF6C6.js.map → package-5FRMSWRT.js.map} +0 -0
- /package/dist/{pi-ZMM4KJTO.js.map → pi-EFBTBI2B.js.map} +0 -0
- /package/dist/{roo-code-67QGLQRM.js.map → roo-code-YIX3RPR2.js.map} +0 -0
- /package/dist/{serve-427CCEYA.js.map → serve-NQBXN4FG.js.map} +0 -0
- /package/dist/{status-6IHRW6PI.js.map → status-5ZM6LXHV.js.map} +0 -0
- /package/dist/{statusline-2CKH5RHO.js.map → statusline-O76BCBUK.js.map} +0 -0
- /package/dist/{telemetry-WNVKL7HW.js.map → telemetry-NO7UUUSJ.js.map} +0 -0
- /package/dist/{trae-TMJPHWZ5.js.map → trae-JESXQKAF.js.map} +0 -0
- /package/dist/{uninstall-QFCDXGKR.js.map → uninstall-QCROBR6A.js.map} +0 -0
- /package/dist/{upgrade-PP46DURC.js.map → upgrade-KJ4QRZDZ.js.map} +0 -0
- /package/dist/{usage-VDORZJPT.js.map → usage-UY6DCND6.js.map} +0 -0
- /package/dist/{usage-event-4533OURF.js.map → usage-event-T4HWQDZF.js.map} +0 -0
- /package/dist/{warp-SVDVKQQI.js.map → warp-Y6JNLLGR.js.map} +0 -0
- /package/dist/{windsurf-H36YKOMR.js.map → windsurf-X7QCJ3XR.js.map} +0 -0
- /package/dist/{zed-LHWJALLZ.js.map → zed-L3ML5MHF.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapters/cursor/index.ts"],"sourcesContent":["/**\n * adapters/cursor — Cursor platform adapter for agent-connector.\n *\n * Generalized from context-mode's proven Cursor adapter: the served identity is\n * now `ctx.connector` (not a hardcoded \"context-mode\"), and every hook command\n * points at the single stable home binary (the shared hook-merge engine builds\n * the command) so one framework update propagates everywhere.\n *\n * Cursor is a json-stdio host:\n * - MCP servers: user scope → ~/.cursor/mcp.json (\"mcpServers\"); project scope\n * → <projectDir>/.cursor/mcp.json (\"mcpServers\").\n * - Hooks: <configDir>/hooks.json with shape `{ version, hooks: { <cursorEvent>:\n * [ { command, matcher? } ] } }`. Unlike Claude, each entry is a FLAT command\n * object (no `{ matcher, hooks:[...] }` wrapper).\n * - Reply: a JSON object on stdout (exit 0). deny/ask carry `permission` +\n * `user_message`; modify carries `updated_input`; context injects via\n * `agent_message` (PreToolUse) or `additional_context` (Post/SessionStart).\n *\n * Cursor supports its own `${env:VAR}` native interpolation, so env/header/url\n * values are rewritten to that native token rather than baked into the file.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { BaseAdapter, type HookMergeDescriptor } from \"../base.js\";\nimport type { Adapter, HookReply, InstallContext, NormalizedEvent } from \"../spi.js\";\nimport type {\n ChangeRecord,\n CommandDef,\n DetectedPlatform,\n HealthCheck,\n HookEventName,\n HookParadigm,\n HookResponse,\n PlatformCapabilities,\n PlatformId,\n PostToolUseEvent,\n PostToolUseFailureEvent,\n PreCompactEvent,\n PreToolUseEvent,\n ServerDef,\n SessionEndEvent,\n SessionStartEvent,\n StopEvent,\n SubagentDef,\n SubagentStartEvent,\n SubagentStopEvent,\n Transport,\n UserPromptSubmitEvent,\n} from \"../../core/types.js\";\nimport { rewriteEnvRefs } from \"../../core/interpolate.js\";\nimport {\n buildWrappedStdio,\n isHomeBinHookCommand,\n} from \"../../core/spawn.js\";\nimport { renderSkillMd } from \"../claude-code/render.js\";\nimport { normalizeSessionSource } from \"../claude-code/wire.js\";\n\nconst HOST: PlatformId = \"cursor\";\nconst MCP_ROOT_KEY = \"mcpServers\";\n\n/**\n * Native hooks.json version Cursor expects. Exported as the SINGLE source of\n * truth for Cursor's hooks-file version, shared with the `cursor-plugin`\n * package emitter so the live install + the packaged bundle can never stamp\n * different versions (see core/package-formats/cursor.ts).\n */\nexport const CURSOR_HOOKS_VERSION = 1;\n\n/**\n * Cursor-native hook event names, in the lower-camel form Cursor reads from\n * hooks.json. The first four are the events the proven context-mode adapter\n * registers; postToolUseFailure / subagentStart / subagentStop are Cursor's\n * documented \"Subagent (Task tool) lifecycle\" + tool-failure hooks.\n */\nconst CURSOR_EVENT = {\n PreToolUse: \"preToolUse\",\n PostToolUse: \"postToolUse\",\n SessionStart: \"sessionStart\",\n Stop: \"stop\",\n PostToolUseFailure: \"postToolUseFailure\",\n SubagentStart: \"subagentStart\",\n SubagentStop: \"subagentStop\",\n // Lifecycle/prompt events Cursor 1.7+ documents (cursor.com/docs/hooks):\n // sessionEnd is fire-and-forget; preCompact is observational (cannot block);\n // beforeSubmitPrompt fires before a prompt is sent and CAN prevent submission\n // (Cursor itself matches beforeSubmitPrompt against the value \"UserPromptSubmit\").\n SessionEnd: \"sessionEnd\",\n PreCompact: \"preCompact\",\n UserPromptSubmit: \"beforeSubmitPrompt\",\n} as const;\n\n/**\n * Map our normalized event names to Cursor's native hook event names. Only the\n * events Cursor actually supports are present; everything else has no Cursor\n * equivalent and is reported as a skip/warn at install time.\n *\n * PermissionRequest is deliberately ABSENT: Cursor has no permission-dialog\n * event — its permission gate is the OUTPUT field `permission: \"allow\"|\"deny\"|\n * \"ask\"` of the before* hooks (beforeShellExecution / beforeMCPExecution /\n * beforeReadFile / preToolUse), not an observable event. Install reports the\n * standard skip-warn for it.\n *\n * Exported as the SINGLE source of truth for canonical→Cursor-native event\n * mapping, shared with the `cursor-plugin` package emitter (see\n * core/package-formats/cursor.ts) so the packaged bundle's hooks.json keys can\n * never silently diverge from the live install adapter's.\n */\nexport const CURSOR_EVENT_MAP: Partial<Record<HookEventName, string>> = {\n PreToolUse: CURSOR_EVENT.PreToolUse,\n PostToolUse: CURSOR_EVENT.PostToolUse,\n SessionStart: CURSOR_EVENT.SessionStart,\n Stop: CURSOR_EVENT.Stop,\n PostToolUseFailure: CURSOR_EVENT.PostToolUseFailure,\n SubagentStart: CURSOR_EVENT.SubagentStart,\n SubagentStop: CURSOR_EVENT.SubagentStop,\n SessionEnd: CURSOR_EVENT.SessionEnd,\n PreCompact: CURSOR_EVENT.PreCompact,\n UserPromptSubmit: CURSOR_EVENT.UserPromptSubmit,\n};\n\n/** A single Cursor native hook entry — a flat command object. */\ninterface CursorHookEntry {\n command: string;\n matcher?: string;\n}\n\n/** Native MCP server entry shapes Cursor accepts under `mcpServers`. */\ninterface CursorStdioServer {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n cwd?: string;\n}\ninterface CursorHttpServer {\n url: string;\n headers?: Record<string, string>;\n}\n\n/** Raw Cursor hook stdin payload (snake_case wire fields). */\ninterface CursorWireInput {\n connector?: unknown;\n tool_name?: string;\n tool_input?: Record<string, unknown>;\n tool_output?: string;\n error_message?: string;\n cwd?: string;\n workspace_roots?: string[];\n conversation_id?: string;\n session_id?: string;\n generation_id?: string;\n source?: string;\n trigger?: string;\n status?: string;\n loop_count?: number;\n stop_hook_active?: boolean;\n\n // beforeSubmitPrompt (UserPromptSubmit) — the submitted prompt text.\n // sessionEnd — the documented end reason. Both field names are taken\n // verbatim from cursor.com/docs/hooks (snake_case wire).\n prompt?: string;\n reason?: string;\n\n // postToolUseFailure — Cursor's existing error vocabulary is error_message;\n // the Claude-compatible names are accepted defensively (unverified wire).\n error?: string;\n tool_use_id?: string;\n is_interrupt?: boolean;\n duration_ms?: number;\n\n // subagentStart / subagentStop (Task-tool lifecycle). Both name families are\n // parsed defensively: agent_* (Claude-compatible) and subagent_* (Cursor-ish).\n agent_id?: string;\n agent_type?: string;\n subagent_id?: string;\n subagent_type?: string;\n last_assistant_message?: string;\n}\n\nexport class CursorAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"Cursor\";\n readonly paradigm: HookParadigm = \"json-stdio\";\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 // Cursor natively supports pre/post tool-use, session start/end, prompt\n // submission, context compaction, and stop (cursor.com/docs/hooks, v1.7+).\n preToolUse: true,\n postToolUse: true,\n preCompact: true,\n sessionStart: true,\n sessionEnd: true,\n userPromptSubmit: true,\n stop: true,\n notification: false,\n // Newer events: Cursor has dedicated postToolUseFailure + subagentStart/\n // subagentStop hooks. permissionRequest stays unset — Cursor's permission\n // gate is an OUTPUT field of its before* hooks, not an observable event\n // (see the EVENT_MAP note).\n postToolUseFailure: true,\n subagentStart: true,\n subagentStop: true,\n // Cursor's preToolUse can rewrite tool input (updated_input) but cannot\n // rewrite already-emitted tool output.\n canModifyArgs: true,\n canModifyOutput: false,\n canInjectSessionContext: true,\n transports: [\"stdio\", \"http\"],\n // Content surfaces: Cursor supports all three (commands, skills, subagents).\n supportsCommands: true,\n supportsSkills: true,\n supportsSubagents: true,\n // Native passthrough hooks: Cursor documents many granular hooks with NO\n // canonical analog — beforeShellExecution / afterShellExecution /\n // beforeMCPExecution / afterMCPExecution / beforeReadFile / afterFileEdit /\n // beforeTabFileRead / afterTabFileEdit / workspaceOpen / afterAgentResponse /\n // afterAgentThought (cursor.com/docs/hooks). They are\n // host-specific (below the >=3-host core bar; see\n // docs/research/host-specific-hook-events-design.md). A connector reaches them\n // by declaring platforms[\"cursor\"].nativeHooks; installHooks writes those\n // event-name keys verbatim into hooks.json, and the generic uninstall reverses\n // them.\n supportsNativeHooks: true,\n // Cursor has a command-driven status line (`/statusline` → `statusLine` in\n // ~/.cursor/cli-config.json, GLOBAL scope only) per the Cursor changelog, but\n // the config-key shape + the Claude-parity stdin payload are sourced from a\n // community tool (agent-status-pills), not first-party Cursor docs — payload\n // field names unverified. Deferred pending a live cursor-agent capture; not a\n // permanent gap; user-scope only when wired.\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userDir = join(homedir(), \".cursor\");\n const userMcp = join(userDir, \"mcp.json\");\n const userHooks = join(userDir, \"hooks.json\");\n const projectDirCursor = join(projectDir, \".cursor\");\n const installed =\n existsSync(userDir) ||\n existsSync(userMcp) ||\n existsSync(userHooks) ||\n existsSync(projectDirCursor);\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath: userMcp,\n scope: \"user\",\n reason: installed\n ? `found Cursor config under ${userDir}`\n : `no Cursor 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, \".cursor\")\n : join(homedir(), \".cursor\");\n }\n\n getServerConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"mcp.json\");\n }\n\n getHookConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"hooks.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 cursor\"\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 Cursor's native mcpServers entry. */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): CursorStdioServer | CursorHttpServer {\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 ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\n\n const entry: CursorStdioServer = { command: this.rewrite(command) };\n if (args.length > 0) entry.args = args.map((a) => this.rewrite(a));\n const env = this.renderEnv(server.env);\n if (env) entry.env = env;\n if (server.cwd) entry.cwd = this.rewrite(server.cwd);\n return entry;\n }\n\n // http (and any other remote transport we surface) — Cursor registers a URL.\n const entry: CursorHttpServer = { url: this.rewrite(server.url ?? \"\") };\n const headers = this.renderEnv(server.headers);\n if (headers) entry.headers = headers;\n return entry;\n }\n\n /**\n * Render env/header values. Cursor supports its own `${env: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)) out[k] = this.rewrite(v);\n return out;\n }\n\n /** Translate `${env:VAR(:-default)}` to Cursor's native `${env:VAR}` token. */\n private rewrite(value: string): string {\n return rewriteEnvRefs(value, cursorEnvToken);\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 events. nativeHooks is a\n // sibling, cursor-scoped declaration on the same override and installs\n // regardless.\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: override?.hooks === false ? \"hooks disabled for cursor\" : \"connector declares no hooks\",\n },\n ];\n }\n\n // Normalized events go through the engine's mapEvent/warn path; native\n // event-name keys ride the separate `native` pass (verbatim keys, EXACT\n // command, the `(native)` detail) — see the descriptor + base.upsertHookEntries.\n const pending = normalizedEvents.map((event) => ({\n event,\n matcher: connector.hooks[event]?.matcher ?? \"\",\n }));\n const native = nativeEvents.map((event) => ({\n event,\n matcher: nativeHooks[event]?.matcher ?? \"\",\n }));\n return this.upsertHookEntries(\n ctx,\n this.getHookConfigPath(ctx),\n pending,\n this.hookDescriptor(ctx),\n native,\n );\n }\n\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n return this.removeHookEntries(ctx, this.getHookConfigPath(ctx), this.hookDescriptor(ctx));\n }\n\n /**\n * Cursor's hook-merge descriptor (FLAT shape `{ command, matcher? }`):\n * - mapEvent renames canonical → Cursor's lower-camel native key\n * (CURSOR_EVENT_MAP); an unmapped event warn-skips (no Cursor equivalent).\n * - renderEntry omits the `matcher` key when the matcher is falsy — this\n * `{command}` vs `{command,matcher}` distinction is load-bearing on-disk\n * bytes (Cursor's flat entry shape), reproduced exactly here.\n * - install find is connector-generic (ANY of our commands at the flat\n * `entry.command`); uninstall drops whole owned entries (flat — NO\n * stripInner). The version stamp is install-only via onMutate.\n * - the native pass uses EXACT-command ownership so a native key coinciding\n * with a normalized event's mapped key adds a SECOND distinct command\n * rather than clobbering the normalized entry.\n */\n private hookDescriptor(ctx: InstallContext): HookMergeDescriptor<CursorHookEntry> {\n return {\n mapEvent: (e) => CURSOR_EVENT_MAP[e as HookEventName],\n unmappedWarnDetail: (e) => `${e} has no Cursor hook equivalent — skipped`,\n renderEntry: (_event, matcher, command) =>\n matcher ? { command, matcher } : { command },\n entryOwnsCommand: (entry, _command) => this.isOurCommand(entry.command, ctx),\n ownsEntryForRemove: (c) => (entry) => this.isOurCommand(entry.command, c),\n skipDetail: (e) => `hooks.${e} already registered`,\n removeDetail: (e, n) => `hooks.${e} (${n})`,\n absentDetail: \"no hooks section present\",\n noMatchDetail: \"no matching hook entries\",\n onMutate: (file) => {\n (file as { version?: number }).version = CURSOR_HOOKS_VERSION;\n },\n nativeOwnsCommand: (entry, command) => entry.command === command,\n nativeSkipDetail: (e) => `hooks.${e} (native) already registered`,\n nativeMutateDetail: (e) => `hooks.${e} (native)`,\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 // ── 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[\"cursor\"] per-surface\n // false to skip. Cursor commands are BODY-ONLY markdown (no frontmatter);\n // skills are the uniform <name>/SKILL.md + resources; subagents are md+fm.\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 cursor\" }];\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 /**\n * Render a Cursor command: BODY-ONLY markdown (no frontmatter). Cursor reads\n * the file as the command prompt verbatim. We prepend the one-line description\n * as an HTML comment header when present so authoring intent survives the\n * round-trip without leaking into the rendered prompt. A description containing\n * \"-->\" would prematurely CLOSE the HTML comment and leak the remainder into\n * the prompt, so we neutralize that sequence before embedding it.\n */\n private renderCommand(cmd: CommandDef): string {\n if (!cmd.description) return `${cmd.prompt}\\n`;\n // Break any literal comment-close so it cannot terminate our header early.\n const safe = cmd.description.replace(/--+>/g, (m) => m.replace(/>/g, \">\"));\n return `<!-- ${safe} -->\\n\\n${cmd.prompt}\\n`;\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 cursor\" }];\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\"), renderSkillMd(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 // ── 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 cursor\" }];\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 Cursor subagent to md+frontmatter (name, description, model, readonly) + prompt body. */\n private renderSubagent(agent: SubagentDef): string {\n const frontmatter: Record<string, unknown> = {\n name: agent.name,\n description: agent.description,\n };\n if (agent.model !== undefined) frontmatter.model = agent.model;\n if (agent.readonly !== undefined) frontmatter.readonly = agent.readonly;\n if (agent.extra) Object.assign(frontmatter, agent.extra);\n return this.renderFrontmatterMd(frontmatter, agent.prompt);\n }\n\n // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const mcpPath = this.getServerConfigPath(ctx);\n const hooksPath = this.getHookConfigPath(ctx);\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}: hooks.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.json, so its absence is healthy, not a failure.\n if (ctx.connector.hookEvents.length === 0) {\n return { status: \"OK\", detail: \"no hooks declared\" };\n }\n return existsSync(hooksPath)\n ? { status: \"OK\", detail: hooksPath }\n : { status: \"FAIL\", detail: `not found: ${hooksPath}` };\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 return checks;\n }\n\n // ── Runtime: parse Cursor stdin JSON → normalized event ──────────────────\n\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\n const input = (raw ?? {}) as CursorWireInput;\n const connectorId = typeof input.connector === \"string\" ? input.connector : \"\";\n const sessionId = extractSessionId(input);\n const projectDir = this.getProjectDir(input);\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 toolOutput = input.tool_output ?? input.error_message;\n const ev: PostToolUseEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n ...(toolOutput !== undefined ? { toolOutput } : {}),\n ...(input.error_message ? { isError: true } : {}),\n };\n return ev;\n }\n case \"SessionStart\": {\n const ev: SessionStartEvent = {\n ...base,\n source: normalizeSessionSource(input.source ?? input.trigger),\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 \"SessionEnd\": {\n // Cursor sessionEnd: { session_id, reason, duration_ms, ... }. session_id\n // is already folded into base.sessionId via extractSessionId; only the\n // documented `reason` enum maps onto the normalized SessionEnd shape.\n const ev: SessionEndEvent = {\n ...base,\n ...(typeof input.reason === \"string\" ? { reason: input.reason } : {}),\n };\n return ev;\n }\n case \"UserPromptSubmit\": {\n // Cursor beforeSubmitPrompt: { prompt, attachments }. attachments has no\n // normalized field and is preserved via base.raw; only `prompt` maps.\n const ev: UserPromptSubmitEvent = {\n ...base,\n prompt: typeof input.prompt === \"string\" ? input.prompt : \"\",\n };\n return ev;\n }\n case \"PreCompact\": {\n // Cursor preCompact: { trigger: \"auto\"|\"manual\", context_*… }. Only the\n // documented `trigger` enum maps onto the normalized PreCompact shape.\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 \"PostToolUseFailure\": {\n // Cursor's established error field is error_message; fall back to the\n // Claude-compatible `error` defensively.\n const error = input.error_message ?? input.error ?? \"\";\n const ev: PostToolUseFailureEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n 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 agentId = input.agent_id ?? input.subagent_id;\n const agentType = input.agent_type ?? input.subagent_type;\n const ev: SubagentStartEvent = {\n ...base,\n ...(typeof agentId === \"string\" ? { agentId } : {}),\n ...(typeof agentType === \"string\" ? { agentType } : {}),\n };\n return ev;\n }\n case \"SubagentStop\": {\n const agentId = input.agent_id ?? input.subagent_id;\n const agentType = input.agent_type ?? input.subagent_type;\n const ev: SubagentStopEvent = {\n ...base,\n ...(typeof agentId === \"string\" ? { agentId } : {}),\n ...(typeof agentType === \"string\" ? { agentType } : {}),\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 // Cursor never delivers Notification / PermissionRequest (no native\n // equivalent — permission is an OUTPUT field of its before* hooks, not\n // an event). If the runtime dispatches one anyway, fail loudly.\n throw new Error(`unsupported cursor hook event: ${String(event)}`);\n }\n }\n }\n\n private getProjectDir(input: CursorWireInput): string | undefined {\n return input.cwd ?? input.workspace_roots?.[0] ?? undefined;\n }\n\n // ── Runtime: normalized response → Cursor native hook reply ──────────────\n\n formatReply(event: HookEventName, response: HookResponse): HookReply {\n const decision = response.decision ?? \"allow\";\n\n // postToolUseFailure (feedback beside the error) and subagentStart (context\n // injected into the SUBAGENT's conversation) are observe/context-only on\n // Cursor: \"context\" emits additional_context, and a \"deny\" DEGRADES to the\n // same shape carrying the reason (the tool already failed / the spawn is\n // not blockable). Everything else is a minimal no-op payload (Cursor\n // rejects empty stdout as \"no valid response\").\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 return this.stdout({ additional_context: context ?? \"\" });\n }\n\n // beforeSubmitPrompt (UserPromptSubmit) is a BLOCK gate, not a permission/\n // context surface: its only documented output is { continue, user_message }\n // (cursor.com/docs/hooks). A \"deny\" prevents submission (continue:false +\n // reason); it cannot inject context (no additional_context/agent_message\n // field), so every non-deny decision is a no-op continue:true.\n if (event === \"UserPromptSubmit\") {\n if (decision === \"deny\") {\n return this.stdout({\n continue: false,\n user_message: response.reason ?? \"Blocked by hook\",\n });\n }\n return this.stdout({ continue: true });\n }\n\n // sessionEnd is fire-and-forget (the response is logged but not used) and\n // preCompact is observational (cannot block or modify compaction) per\n // cursor.com/docs/hooks — neither carries a decision Cursor honors, so both\n // are an unconditional no-op passthrough (mirrors Stop).\n if (event === \"SessionEnd\" || event === \"PreCompact\") {\n return { exitCode: 0 };\n }\n\n // deny → block the action with a user-facing message. (On SubagentStop\n // this follows the adapter's Stop idiom — the deny carries Stop semantics.)\n if (decision === \"deny\") {\n return this.stdout({\n permission: \"deny\",\n user_message: response.reason ?? \"Blocked by hook\",\n });\n }\n\n // ask → prompt the user to confirm.\n if (decision === \"ask\") {\n return this.stdout({\n permission: \"ask\",\n user_message: response.reason ?? \"Confirmation required by hook\",\n });\n }\n\n // modify → rewrite PreToolUse input (only where Cursor supports it).\n if (decision === \"modify\") {\n if (event === \"PreToolUse\" && response.updatedInput) {\n return this.stdout({ updated_input: response.updatedInput });\n }\n // Output rewrite is unsupported on Cursor; fall through to allow.\n }\n\n // context → inject soft guidance. PreToolUse uses `agent_message`; Post and\n // SessionStart use `additional_context`.\n if (decision === \"context\" && response.additionalContext) {\n return event === \"PreToolUse\"\n ? this.stdout({ agent_message: response.additionalContext })\n : this.stdout({ additional_context: response.additionalContext });\n }\n\n // SessionStart always emits valid JSON even on a no-op (Cursor rejects empty\n // stdout as \"no valid response\").\n if (event === \"SessionStart\") {\n return this.stdout({ additional_context: response.additionalContext ?? \"\" });\n }\n\n // allow / void → minimal no-op payload (Cursor rejects empty stdout).\n if (event === \"PreToolUse\") return this.stdout({ agent_message: \"\" });\n if (event === \"PostToolUse\") return this.stdout({ additional_context: \"\" });\n return { exitCode: 0 };\n }\n\n private stdout(payload: unknown): HookReply {\n return { exitCode: 0, stdout: JSON.stringify(payload) };\n }\n}\n\n/** Cursor native interpolation token: `${env:VAR}` → `${env:VAR}` (passthrough). */\nfunction cursorEnvToken(name: string): string {\n return `\\${env:${name}}`;\n}\n\nfunction extractSessionId(input: CursorWireInput): string {\n if (typeof input.conversation_id === \"string\") return input.conversation_id;\n if (typeof input.session_id === \"string\") return input.session_id;\n return \"\";\n}\n\nexport const adapter = new CursorAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/managed-block.ts"],"sourcesContent":["/**\n * core/managed-block — the marker-fenced MANAGED BLOCK engine behind the\n * `memory` content surface.\n *\n * Memory/rules files (AGENTS.md, CLAUDE.md, GEMINI.md, …) are SHARED,\n * user-authored files — unlike commands/skills/subagents, agent-connector does\n * not own them. Every write therefore goes through this one module, which\n * implements idempotent, hash-stamped, uninstall-reversible blocks:\n *\n * <!-- agent-connector:begin <connectorId>/<name> hash=<sha256-12> -->\n * <!-- Managed by agent-connector for \"<connectorId>\". Do not edit … -->\n * …guidance…\n * <!-- agent-connector:end <connectorId>/<name> -->\n *\n * Design rules (each grounded in surveyed prior art — ansible blockinfile,\n * conda init, OMC mergeClaudeMd, Ruler, doctoc):\n * • UNIQUE marker per block: the blockId (`<connectorId>/<entryName>`) lives\n * ON the marker line, so multiple connectors coexist in one file and each\n * update path only ever touches its own pair (ansible's documented\n * multi-block rule). The shared `agent-connector` namespace token lets\n * doctor/uninstall enumerate every block with one scan.\n * • `hash=` is the first 12 hex chars of sha256 over the NORMALIZED inner\n * region (CRLF→LF + trim — stable under prettier/EOL converters): O(1)\n * idempotence (unchanged → skip, no mtime/git churn) and tamper detection\n * (actual inner hash ≠ recorded ⇒ the user edited inside the block ⇒ warn,\n * never clobber without an explicit force).\n * • IN-PLACE replacement (conda semantics): zero bytes outside the marker\n * pair ever change — no move-to-top, no user blank-line reflow.\n * • Line-anchored matching that explicitly tolerates `\\r` line ends and a\n * FENCE-AWARE scanner (markers quoted inside ``` / ~~~ code fences never\n * match) — fixes the CRLF duplicate-block and quoted-marker classes.\n * • First-begin / FIRST-end-after pairing (never last-end): a missing end\n * marker must not swallow a sibling connector's block.\n * • HTML-comment markers are CORRECT for CLAUDE.md: Claude Code strips HTML\n * comments from CLAUDE.md before context injection (verified against docs\n * and the 2.1.172 binary), so the markers and the do-not-edit notice are\n * INVISIBLE to the model there while remaining fully parseable by us for\n * sync/doctor/uninstall. On AGENTS.md hosts (which inline the whole file\n * into the prompt) the short notice doubles as an in-prompt \"do not edit\"\n * instruction to the host's own agent. A `commentStyle: \"hash\"` variant\n * exists for future non-markdown targets (`#`-prefixed marker lines).\n *\n * The module also owns the per-connector MEMORY OWNERSHIP LEDGER\n * (`connectorDir(id)/memory-state.json`): the markers in the file remain the\n * source of truth for uninstall (a teammate's machine with no ledger still\n * uninstalls via the prefix scan); the ledger only adds the created-vs-modified\n * distinction (file deletion rights) and doctor diagnostics.\n */\n\nimport { createHash } from \"node:crypto\";\nimport {\n chmodSync,\n copyFileSync,\n existsSync,\n readFileSync,\n renameSync,\n rmSync,\n statSync,\n writeFileSync,\n} from \"node:fs\";\nimport { basename, dirname, join } from \"node:path\";\n\nimport { backupsDir, connectorDir, ensureDir } from \"./paths.js\";\n\n// ─────────────────────────────────────────────────────────────────────────\n// Grammar constants (shared with defineConnector's content validation)\n// ─────────────────────────────────────────────────────────────────────────\n\n/** Literal begin token. Connector memory content MUST NOT contain it. */\nexport const MANAGED_BLOCK_BEGIN_TOKEN = \"agent-connector:begin\";\n/** Literal end token. Connector memory content MUST NOT contain it. */\nexport const MANAGED_BLOCK_END_TOKEN = \"agent-connector:end\";\n\n/** Hard cap on one memory entry's content (ConnectorConfigError above this). */\nexport const MEMORY_CONTENT_HARD_CAP_BYTES = 16 * 1024;\n/**\n * Soft per-entry budget — exceeded → install-time `warn` ChangeRecord (memory\n * files are injected into EVERY prompt of EVERY session on the host; codex\n * additionally caps combined project docs at 32 KiB).\n */\nexport const MEMORY_CONTENT_SOFT_BUDGET_BYTES = 4 * 1024;\n\n/** Marker comment style: HTML comments (default, all v1 markdown targets) or `#` lines. */\nexport type BlockCommentStyle = \"html\" | \"hash\";\n\n// ─────────────────────────────────────────────────────────────────────────\n// Hashing / rendering\n// ─────────────────────────────────────────────────────────────────────────\n\n/** CRLF/CR → LF + trim: the normalization both hashing sides use. */\nfunction normalizeInner(s: string): string {\n return s.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\").trim();\n}\n\n/** First 12 hex chars of sha256 over the NORMALIZED inner region. */\nexport function hashBlockContent(inner: string): string {\n return createHash(\"sha256\").update(normalizeInner(inner), \"utf8\").digest(\"hex\").slice(0, 12);\n}\n\n/** The conda-style in-block warning, adapted for the LLM era (see header). */\nfunction defaultNotice(connectorId: string): string {\n return (\n `Managed by agent-connector for \"${connectorId}\". Do not edit between these markers: ` +\n `\\`agent-connector sync\\` rewrites this block; ` +\n `\\`agent-connector uninstall ${connectorId}\\` removes it.`\n );\n}\n\nfunction beginLine(blockId: string, hash: string, style: BlockCommentStyle): string {\n return style === \"hash\"\n ? `# ${MANAGED_BLOCK_BEGIN_TOKEN} ${blockId} hash=${hash}`\n : `<!-- ${MANAGED_BLOCK_BEGIN_TOKEN} ${blockId} hash=${hash} -->`;\n}\n\n/** END line is a fixed exact string (no hash) so a content change never strands it. */\nfunction endLine(blockId: string, style: BlockCommentStyle): string {\n return style === \"hash\"\n ? `# ${MANAGED_BLOCK_END_TOKEN} ${blockId}`\n : `<!-- ${MANAGED_BLOCK_END_TOKEN} ${blockId} -->`;\n}\n\nfunction noticeLine(notice: string, style: BlockCommentStyle): string {\n return style === \"hash\" ? `# ${notice}` : `<!-- ${notice} -->`;\n}\n\nexport interface RenderBlockOptions {\n /** `<connectorId>/<entryName>` (or the reserved `_shared/<name>` bridge prefix). */\n blockId: string;\n /** Connector id named in the default do-not-edit notice line. */\n connectorId: string;\n /** The guidance payload (plain markdown; normalized + trimmed on emit). */\n content: string;\n /** Marker comment style; default \"html\". */\n commentStyle?: BlockCommentStyle;\n /** Override the default notice line TEXT (without comment delimiters). */\n notice?: string;\n}\n\n/**\n * Render the block as LOGICAL lines (no EOL chars). The recorded `hash=`\n * covers the full inner region (notice line + content) so install and scan\n * compare like for like.\n */\nexport function renderBlockLines(opts: RenderBlockOptions): string[] {\n const style = opts.commentStyle ?? \"html\";\n const inner = [\n noticeLine(opts.notice ?? defaultNotice(opts.connectorId), style),\n ...normalizeInner(opts.content).split(\"\\n\"),\n ];\n const hash = hashBlockContent(inner.join(\"\\n\"));\n return [beginLine(opts.blockId, hash, style), ...inner, endLine(opts.blockId, style)];\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Scanning (fence-aware, line-anchored, CRLF-tolerant)\n// ─────────────────────────────────────────────────────────────────────────\n\n// Both comment styles are RECOGNIZED in one pass (a file may legitimately mix\n// styles only across rewrites; emission always uses the requested style).\nconst BEGIN_RE =\n /^(?:<!--\\s+agent-connector:begin\\s+(\\S+)\\s+hash=([0-9a-f]{12})\\s+-->|#\\s+agent-connector:begin\\s+(\\S+)\\s+hash=([0-9a-f]{12}))\\s*$/;\nconst END_RE = /^(?:<!--\\s+agent-connector:end\\s+(\\S+)\\s+-->|#\\s+agent-connector:end\\s+(\\S+))\\s*$/;\n\ninterface MarkerEvent {\n kind: \"begin\" | \"end\";\n blockId: string;\n /** Recorded hash (begin markers only). */\n hash?: string;\n /** Line index into the logical-lines array. */\n index: number;\n}\n\n/** Strip ONE trailing `\\r` — `raw.split(\"\\n\")` leaves it on CRLF files. */\nfunction stripCr(line: string): string {\n return line.endsWith(\"\\r\") ? line.slice(0, -1) : line;\n}\n\n/**\n * Scan logical lines for marker events, tracking ``` / ~~~ fence state so a\n * marker QUOTED inside a fenced code block never matches (the OMC class of\n * false positives, eliminated rather than just reduced).\n */\nfunction scanMarkers(logical: string[]): MarkerEvent[] {\n const events: MarkerEvent[] = [];\n let fence: { char: string; len: number } | null = null;\n for (let i = 0; i < logical.length; i++) {\n const line = logical[i]!;\n if (fence) {\n const close = line.match(/^ {0,3}(`{3,}|~{3,})\\s*$/);\n if (close && close[1]![0] === fence.char && close[1]!.length >= fence.len) fence = null;\n continue;\n }\n const open = line.match(/^ {0,3}(`{3,}|~{3,})/);\n if (open) {\n fence = { char: open[1]![0]!, len: open[1]!.length };\n continue;\n }\n const b = line.match(BEGIN_RE);\n if (b) {\n events.push({ kind: \"begin\", blockId: (b[1] ?? b[3])!, hash: (b[2] ?? b[4])!, index: i });\n continue;\n }\n const e = line.match(END_RE);\n if (e) events.push({ kind: \"end\", blockId: (e[1] ?? e[2])!, index: i });\n }\n return events;\n}\n\n/**\n * Logical lines of `raw` that sit OUTSIDE ``` / ~~~ code fences — for host\n * probes that must ignore quoted examples (e.g. the claude-code `@AGENTS.md`\n * import detection). Fence lines themselves are excluded.\n */\nexport function linesOutsideFences(raw: string): string[] {\n const body = raw.startsWith(\"\\uFEFF\") ? raw.slice(1) : raw;\n const logical = body.split(\"\\n\").map(stripCr);\n const out: string[] = [];\n let fence: { char: string; len: number } | null = null;\n for (const line of logical) {\n if (fence) {\n const close = line.match(/^ {0,3}(`{3,}|~{3,})\\s*$/);\n if (close && close[1]![0] === fence.char && close[1]!.length >= fence.len) fence = null;\n continue;\n }\n const open = line.match(/^ {0,3}(`{3,}|~{3,})/);\n if (open) {\n fence = { char: open[1]![0]!, len: open[1]!.length };\n continue;\n }\n out.push(line);\n }\n return out;\n}\n\ninterface BlockPair {\n blockId: string;\n begin: MarkerEvent;\n end: MarkerEvent;\n}\n\n/**\n * Pair markers per blockId: first begin, then the FIRST end at-or-after it.\n * A nested begin for the SAME id (inside an open pair) is treated as inner\n * content; unpaired markers are returned as strays. Per-id state means a\n * missing end for connector A can never swallow connector B's block.\n */\nfunction pairMarkers(events: MarkerEvent[]): { pairs: BlockPair[]; strays: MarkerEvent[] } {\n const open = new Map<string, MarkerEvent>();\n const pairs: BlockPair[] = [];\n const strays: MarkerEvent[] = [];\n for (const ev of events) {\n if (ev.kind === \"begin\") {\n if (!open.has(ev.blockId)) open.set(ev.blockId, ev);\n // else: a begin inside an open pair — inner content / abuse; the hash\n // check will flag the pair as drifted rather than guessing boundaries.\n } else {\n const b = open.get(ev.blockId);\n if (b) {\n pairs.push({ blockId: ev.blockId, begin: b, end: ev });\n open.delete(ev.blockId);\n } else {\n strays.push(ev);\n }\n }\n }\n for (const b of open.values()) strays.push(b);\n return { pairs, strays };\n}\n\n/** One discovered block (for doctor / refcount / uninstall enumeration). */\nexport interface ManagedBlockInfo {\n blockId: string;\n /** The hash recorded on the begin marker line. */\n recordedHash: string;\n /** Hash of the actual normalized inner region as found on disk. */\n actualHash: string;\n /** True when recordedHash ≠ actualHash — the user edited inside the block. */\n drifted: boolean;\n beginLine: number;\n endLine: number;\n}\n\n/** Enumerate every complete agent-connector block in `raw` (namespace scan). */\nexport function listManagedBlocks(raw: string): ManagedBlockInfo[] {\n const body = raw.startsWith(\"\\uFEFF\") ? raw.slice(1) : raw;\n const logical = body.split(\"\\n\").map(stripCr);\n const { pairs } = pairMarkers(scanMarkers(logical));\n return pairs.map((p) => {\n const inner = logical.slice(p.begin.index + 1, p.end.index).join(\"\\n\");\n const actualHash = hashBlockContent(inner);\n const recordedHash = p.begin.hash ?? \"\";\n return {\n blockId: p.blockId,\n recordedHash,\n actualHash,\n drifted: recordedHash !== actualHash,\n beginLine: p.begin.index,\n endLine: p.end.index,\n };\n });\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Pure text upsert / removal\n// ─────────────────────────────────────────────────────────────────────────\n\nexport interface UpsertBlockOptions extends RenderBlockOptions {\n /** Overwrite a USER-EDITED (drifted) block. Default false → warn + leave intact. */\n force?: boolean;\n}\n\nexport interface BlockTextResult {\n /** Resulting full text (=== input when nothing changed). */\n text: string;\n action: \"create\" | \"update\" | \"skip\" | \"warn\";\n detail: string;\n changed: boolean;\n /**\n * True when the rewrite was DESTRUCTIVE-ADJACENT (force-overwrote a drifted\n * block, collapsed duplicate pairs, or stripped stray markers) — the file\n * wrapper writes a timestamped backup before persisting such a change.\n */\n recovered: boolean;\n /** Hash of the (new) rendered inner region — recorded in the ledger. */\n hash: string;\n}\n\n/** Detect the file's dominant EOL; new/replaced lines are emitted with it. */\nfunction detectEol(body: string): \"\\n\" | \"\\r\\n\" {\n const crlf = (body.match(/\\r\\n/g) ?? []).length;\n const total = (body.match(/\\n/g) ?? []).length;\n return crlf > 0 && crlf >= total - crlf ? \"\\r\\n\" : \"\\n\";\n}\n\n/** Add `\\r` to logical lines when the file is CRLF (joined with \"\\n\" later). */\nfunction withEol(lines: string[], eol: \"\\n\" | \"\\r\\n\"): string[] {\n return eol === \"\\r\\n\" ? lines.map((l) => `${l}\\r`) : lines;\n}\n\n/**\n * Strip trailing newline(s) + whitespace-only line tails WITHOUT touching\n * trailing spaces on the last content line (bytes outside our block).\n */\nfunction trimTrailingBlank(body: string): string {\n let out = body;\n for (;;) {\n const m = out.match(/\\r?\\n[ \\t]*$/);\n if (!m) return out;\n out = out.slice(0, out.length - m[0].length);\n }\n}\n\n/** Append the rendered block at EOF with exactly ONE blank separator line. */\nfunction appendBlock(body: string, blockLines: string[], eol: \"\\n\" | \"\\r\\n\"): string {\n const blockText = blockLines.join(eol) + eol;\n if (body.trim() === \"\") return blockText;\n return trimTrailingBlank(body) + eol + eol + blockText;\n}\n\n/**\n * Idempotent upsert of one managed block into `raw` (pure; no I/O).\n * See the module header for the full algorithm contract.\n */\nexport function upsertBlockInText(raw: string, opts: UpsertBlockOptions): BlockTextResult {\n const bom = raw.startsWith(\"\\uFEFF\");\n const body = bom ? raw.slice(1) : raw;\n const eol = detectEol(body);\n const lines = body.split(\"\\n\"); // elements keep a trailing \"\\r\" on CRLF files\n const logical = lines.map(stripCr);\n\n const events = scanMarkers(logical).filter((e) => e.blockId === opts.blockId);\n const { pairs, strays } = pairMarkers(events);\n\n const newLines = renderBlockLines(opts);\n const newHash = hashBlockContent(newLines.slice(1, -1).join(\"\\n\"));\n const finish = (text: string, r: Omit<BlockTextResult, \"text\" | \"hash\">): BlockTextResult => ({\n text: bom ? `\\uFEFF${text}` : text,\n hash: newHash,\n ...r,\n });\n\n if (pairs.length > 0) {\n const { begin, end } = pairs[0]!;\n const recorded = begin.hash ?? \"\";\n const actualHash = hashBlockContent(logical.slice(begin.index + 1, end.index).join(\"\\n\"));\n const drifted = actualHash !== recorded;\n\n if (drifted && !opts.force) {\n return finish(body, {\n action: \"warn\",\n detail:\n `block ${opts.blockId} was edited inside the markers ` +\n `(recorded hash ${recorded}, found ${actualHash}); left untouched — ` +\n `re-run with --force to overwrite the in-block edits`,\n changed: false,\n recovered: false,\n });\n }\n\n const duplicates = pairs.slice(1);\n const needsWrite =\n drifted || recorded !== newHash || duplicates.length > 0 || strays.length > 0;\n if (!needsWrite) {\n return finish(body, {\n action: \"skip\",\n detail: `block ${opts.blockId} already up to date (hash ${newHash})`,\n changed: false,\n recovered: false,\n });\n }\n\n // Build the deletion set: the canonical pair region (replaced in place),\n // duplicate pairs (+ ONE adjacent blank line each), and stray marker LINES.\n const del = new Set<number>();\n for (let i = begin.index; i <= end.index; i++) del.add(i);\n for (const dup of duplicates) {\n for (let i = dup.begin.index; i <= dup.end.index; i++) del.add(i);\n reclaimBlankLine(logical, dup.begin.index, dup.end.index, del, lines.length);\n }\n for (const s of strays) del.add(s.index);\n\n const out: string[] = [];\n for (let i = 0; i < lines.length; i++) {\n if (i === begin.index) out.push(...withEol(newLines, eol));\n if (!del.has(i)) out.push(lines[i]!);\n }\n const notes: string[] = [];\n if (drifted) notes.push(\"in-block edits overwritten (--force; backup taken)\");\n if (duplicates.length > 0) notes.push(`${duplicates.length} duplicate pair(s) collapsed`);\n if (strays.length > 0) notes.push(`${strays.length} stray marker line(s) removed`);\n return finish(out.join(\"\\n\"), {\n action: \"update\",\n detail:\n `block ${opts.blockId} updated (hash ${recorded || \"?\"} → ${newHash})` +\n (notes.length > 0 ? `; ${notes.join(\"; \")}` : \"\"),\n changed: true,\n recovered: drifted || duplicates.length > 0 || strays.length > 0,\n });\n }\n\n if (strays.length > 0) {\n // Corruption recovery: strip ONLY the stray marker line(s) (never the text\n // between guessed boundaries), then proceed as not-found.\n const del = new Set(strays.map((s) => s.index));\n const cleaned = lines.filter((_, i) => !del.has(i)).join(\"\\n\");\n return finish(appendBlock(cleaned, newLines, eol), {\n action: \"create\",\n detail:\n `block ${opts.blockId} appended after recovery: ${strays.length} stray ` +\n `marker line(s) removed (backup taken)`,\n changed: true,\n recovered: true,\n });\n }\n\n // Not found → append at EOF (one blank separator; whole file when empty).\n return finish(appendBlock(body, newLines, eol), {\n action: \"create\",\n detail: `block ${opts.blockId} appended (hash ${newHash})`,\n changed: true,\n recovered: false,\n });\n}\n\n/**\n * Mark ONE blank line adjacent to a removed begin..end region for deletion\n * (prefer the line before; never the post-final-newline \"\" sentinel).\n */\nfunction reclaimBlankLine(\n logical: string[],\n beginIdx: number,\n endIdx: number,\n del: Set<number>,\n lineCount: number,\n): void {\n const before = beginIdx - 1;\n if (before >= 0 && !del.has(before) && logical[before]!.trim() === \"\") {\n del.add(before);\n return;\n }\n const after = endIdx + 1;\n // The final \"\" element of split(\"\\n\") on a newline-terminated file is the\n // trailing-newline sentinel, not a blank line — leave it alone.\n const isSentinel = after === lineCount - 1 && logical[after] === \"\";\n if (after < lineCount && !isSentinel && !del.has(after) && logical[after]!.trim() === \"\") {\n del.add(after);\n }\n}\n\nexport interface RemoveBlocksOptions {\n /** Remove the block with EXACTLY this id… */\n blockId?: string;\n /** …or every block whose id starts with this prefix (e.g. `<connectorId>/`). */\n blockIdPrefix?: string;\n}\n\nexport interface RemoveRecord {\n blockId: string;\n action: \"remove\" | \"warn\";\n detail: string;\n}\n\nexport interface RemoveBlocksResult {\n text: string;\n changed: boolean;\n records: RemoveRecord[];\n /** True when the remaining text is whitespace-only (file-deletion candidate). */\n fileNowEmpty: boolean;\n /** True when a drifted block was removed or stray markers were stripped. */\n recovered: boolean;\n}\n\n/**\n * Remove every matching managed block (begin..end inclusive + at most ONE\n * adjacent blank separator line — no blank-line accumulation across cycles).\n * Drifted blocks are removed WITH a warn (uninstall intent is explicit; the\n * file wrapper backs the file up first). Stray matching markers are stripped\n * line-only with a warn. Pure; no I/O.\n */\nexport function removeBlocksFromText(raw: string, match: RemoveBlocksOptions): RemoveBlocksResult {\n const bom = raw.startsWith(\"\\uFEFF\");\n const body = bom ? raw.slice(1) : raw;\n const lines = body.split(\"\\n\");\n const logical = lines.map(stripCr);\n\n const matches = (id: string): boolean =>\n (match.blockId !== undefined && id === match.blockId) ||\n (match.blockIdPrefix !== undefined && id.startsWith(match.blockIdPrefix));\n\n const { pairs, strays } = pairMarkers(scanMarkers(logical));\n const targetPairs = pairs.filter((p) => matches(p.blockId));\n const targetStrays = strays.filter((s) => matches(s.blockId));\n\n if (targetPairs.length === 0 && targetStrays.length === 0) {\n return { text: raw, changed: false, records: [], fileNowEmpty: false, recovered: false };\n }\n\n const del = new Set<number>();\n const records: RemoveRecord[] = [];\n let recovered = false;\n\n for (const p of targetPairs) {\n const recorded = p.begin.hash ?? \"\";\n const actualHash = hashBlockContent(\n logical.slice(p.begin.index + 1, p.end.index).join(\"\\n\"),\n );\n for (let i = p.begin.index; i <= p.end.index; i++) del.add(i);\n reclaimBlankLine(logical, p.begin.index, p.end.index, del, lines.length);\n if (actualHash !== recorded) {\n recovered = true;\n records.push({\n blockId: p.blockId,\n action: \"warn\",\n detail:\n `block ${p.blockId} had in-block edits (recorded hash ${recorded}, found ` +\n `${actualHash}); removed anyway (backup taken)`,\n });\n }\n records.push({ blockId: p.blockId, action: \"remove\", detail: `block ${p.blockId} removed` });\n }\n for (const s of targetStrays) {\n del.add(s.index);\n recovered = true;\n records.push({\n blockId: s.blockId,\n action: \"warn\",\n detail: `stray ${s.kind} marker for ${s.blockId} removed (marker line only)`,\n });\n }\n\n const text = lines.filter((_, i) => !del.has(i)).join(\"\\n\");\n return {\n text: bom ? `\\uFEFF${text}` : text,\n changed: true,\n records,\n fileNowEmpty: text.trim() === \"\",\n recovered,\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// File-level wrappers (atomic write, backups, dry-run)\n// ─────────────────────────────────────────────────────────────────────────\n\nexport interface BlockFileChange {\n action: \"create\" | \"update\" | \"skip\" | \"warn\" | \"remove\";\n path: string;\n detail: string;\n /** True when the FILE did not exist and this upsert created it (ledger fact). */\n createdFile: boolean;\n /** Set when a pre-mutation backup was written (destructive/recovery paths only). */\n backupPath?: string;\n /** Hash of the rendered inner region (ledger / doctor). */\n hash: string;\n}\n\n/** Timestamped copy into backupsDir(); best-effort (null on failure). */\nfunction backupFile(path: string): string | null {\n try {\n ensureDir(backupsDir());\n const stamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n const dest = join(backupsDir(), `memory-${stamp}-${basename(path)}`);\n copyFileSync(path, dest);\n return dest;\n } catch {\n return null;\n }\n}\n\n/**\n * Atomic write: temp file in the SAME directory + rename, preserving the\n * destination's mode. Shrinks (does not eliminate) the read-modify-write race\n * with hosts that append to memory files mid-session (Claude `#` quick-memory).\n */\nfunction atomicWriteFile(path: string, text: string): void {\n const dir = dirname(path);\n ensureDir(dir);\n const tmp = join(dir, `.${basename(path)}.ac-tmp-${process.pid}-${Date.now()}`);\n try {\n writeFileSync(tmp, text, \"utf8\");\n try {\n chmodSync(tmp, statSync(path).mode);\n } catch {\n /* destination absent — default mode is fine */\n }\n renameSync(tmp, path);\n } catch (err) {\n rmSync(tmp, { force: true });\n throw err;\n }\n}\n\n/**\n * Upsert one managed block into the file at `path` (created when absent).\n * Re-reads immediately before computing+writing; honors dryRun (the action is\n * computed and reported, nothing is written).\n */\nexport function upsertManagedBlockFile(\n path: string,\n opts: UpsertBlockOptions & { dryRun: boolean },\n): BlockFileChange {\n let raw: string | null = null;\n if (existsSync(path)) {\n try {\n raw = readFileSync(path, \"utf8\");\n } catch {\n return {\n action: \"warn\",\n path,\n detail: `cannot read ${path}; memory block ${opts.blockId} not written`,\n createdFile: false,\n hash: \"\",\n };\n }\n }\n\n if (raw === null) {\n const lines = renderBlockLines(opts);\n const hash = hashBlockContent(lines.slice(1, -1).join(\"\\n\"));\n if (!opts.dryRun) atomicWriteFile(path, `${lines.join(\"\\n\")}\\n`);\n return {\n action: \"create\",\n path,\n detail: `created ${basename(path)} with block ${opts.blockId} (hash ${hash})`,\n createdFile: true,\n hash,\n };\n }\n\n const res = upsertBlockInText(raw, opts);\n const change: BlockFileChange = {\n action: res.action,\n path,\n detail: res.detail,\n createdFile: false,\n hash: res.hash,\n };\n if (res.changed && !opts.dryRun) {\n if (res.recovered) {\n const backup = backupFile(path);\n if (backup) change.backupPath = backup;\n }\n atomicWriteFile(path, res.text);\n }\n return change;\n}\n\n/**\n * Remove every matching managed block from the file at `path`. Missing file or\n * no matching markers → a single idempotent \"skip\". When the remaining content\n * is whitespace-only AND `deleteFileIfCreated` is true (the ledger recorded\n * that agent-connector created this file), the file itself is deleted (Ruler\n * revert semantics: delete only what we created).\n */\nexport function removeManagedBlocksFile(\n path: string,\n match: RemoveBlocksOptions,\n opts: { dryRun: boolean; deleteFileIfCreated?: boolean },\n): BlockFileChange[] {\n if (!existsSync(path)) {\n return [\n {\n action: \"skip\",\n path,\n detail: `${basename(path)} absent; nothing to remove`,\n createdFile: false,\n hash: \"\",\n },\n ];\n }\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\");\n } catch {\n return [\n {\n action: \"warn\",\n path,\n detail: `cannot read ${path}; managed blocks left in place`,\n createdFile: false,\n hash: \"\",\n },\n ];\n }\n\n const res = removeBlocksFromText(raw, match);\n if (!res.changed) {\n return [\n {\n action: \"skip\",\n path,\n detail: `no agent-connector blocks matching ${match.blockId ?? match.blockIdPrefix ?? \"?\"} in ${basename(path)}`,\n createdFile: false,\n hash: \"\",\n },\n ];\n }\n\n const changes: BlockFileChange[] = [];\n let backupPath: string | undefined;\n if (!opts.dryRun) {\n if (res.recovered) backupPath = backupFile(path) ?? undefined;\n if (res.fileNowEmpty && opts.deleteFileIfCreated) {\n rmSync(path, { force: true });\n } else {\n atomicWriteFile(path, res.text);\n }\n }\n for (const r of res.records) {\n changes.push({\n action: r.action,\n path,\n detail: r.detail,\n createdFile: false,\n hash: \"\",\n ...(backupPath && r.action === \"warn\" ? { backupPath } : {}),\n });\n }\n if (res.fileNowEmpty && opts.deleteFileIfCreated) {\n changes.push({\n action: \"remove\",\n path,\n detail: `${basename(path)} deleted (agent-connector created it; only whitespace remained)`,\n createdFile: false,\n hash: \"\",\n });\n }\n return changes;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Memory ownership ledger — connectorDir(id)/memory-state.json\n// ─────────────────────────────────────────────────────────────────────────\n\nexport interface MemoryLedgerTarget {\n platform: string;\n scope: string;\n path: string;\n blockId: string;\n /** True when agent-connector CREATED the file (grants deletion rights). */\n createdFile: boolean;\n /** Inner-region hash we last wrote (doctor drift detection). */\n hash: string;\n}\n\nexport interface MemoryLedger {\n version: 1;\n targets: MemoryLedgerTarget[];\n}\n\nexport function memoryLedgerPath(connectorId: string): string {\n return join(connectorDir(connectorId), \"memory-state.json\");\n}\n\nexport function loadMemoryLedger(connectorId: string): MemoryLedger {\n const p = memoryLedgerPath(connectorId);\n if (!existsSync(p)) return { version: 1, targets: [] };\n try {\n const parsed = JSON.parse(readFileSync(p, \"utf8\")) as MemoryLedger;\n if (parsed && Array.isArray(parsed.targets)) return { version: 1, targets: parsed.targets };\n } catch {\n /* corrupt → fresh ledger; the markers remain the source of truth */\n }\n return { version: 1, targets: [] };\n}\n\n/** Persist the ledger; an EMPTY ledger deletes the file (no orphan state). */\nexport function saveMemoryLedger(connectorId: string, ledger: MemoryLedger): void {\n const p = memoryLedgerPath(connectorId);\n if (ledger.targets.length === 0) {\n rmSync(p, { force: true });\n return;\n }\n ensureDir(dirname(p));\n writeFileSync(p, `${JSON.stringify(ledger, null, 2)}\\n`, \"utf8\");\n}\n\n/** True when the connector has any recorded memory targets (uninstall guard). */\nexport function hasMemoryLedger(connectorId: string): boolean {\n return loadMemoryLedger(connectorId).targets.length > 0;\n}\n\n/**\n * Upsert one ledger row (keyed by platform+scope+path+blockId). The\n * `createdFile` fact is STICKY: once we created the file, deletion rights\n * survive later syncs that found it present.\n */\nexport function recordMemoryTarget(ledger: MemoryLedger, t: MemoryLedgerTarget): void {\n const i = ledger.targets.findIndex(\n (x) =>\n x.platform === t.platform &&\n x.scope === t.scope &&\n x.path === t.path &&\n x.blockId === t.blockId,\n );\n if (i >= 0) {\n ledger.targets[i] = { ...t, createdFile: ledger.targets[i]!.createdFile || t.createdFile };\n } else {\n ledger.targets.push(t);\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapters/claude-code/index.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, type HookMergeDescriptor } 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 PostCompactEvent,\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 buildHomeBinStatuslineCommand,\n buildWrappedStdio,\n isHomeBinHookCommand,\n isHomeBinStatuslineCommand,\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 normalizeSessionSource,\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 ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\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\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 return this.upsertHookEntries(ctx, settingsPath, pending, this.hookDescriptor());\n }\n\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n return this.removeHookEntries(ctx, this.getHookConfigPath(ctx), this.hookDescriptor());\n }\n\n /**\n * Claude's hook-merge descriptor (NESTED shape `{ matcher, hooks: [...] }`):\n * - install find = THIS exact command present in the entry's inner `hooks`;\n * - uninstall = inner-strip ONLY (connector-generic `isOurCommand` over the\n * inner commands, drop entries left empty) — claude never removes a whole\n * entry by ownership, so `ownsEntryForRemove` is a never-true predicate;\n * - every detail string is the literal claude-code wording.\n */\n private hookDescriptor(): HookMergeDescriptor<ClaudeHookEntry> {\n return {\n renderEntry: (_event, matcher, command) => ({\n matcher,\n hooks: [{ type: \"command\", command }],\n }),\n entryOwnsCommand: (entry, command) =>\n (entry.hooks ?? []).some((h) => h.command === command),\n ownsEntryForRemove: () => () => false,\n stripInner: (ctx) => (entry) => {\n const innerBefore = entry.hooks?.length ?? 0;\n const inner = (entry.hooks ?? []).filter((h) => !this.isOurCommand(h.command, ctx));\n return {\n next: inner.length > 0 ? { matcher: entry.matcher ?? \"\", hooks: inner } : null,\n removed: innerBefore - inner.length,\n };\n },\n skipDetail: (event) => `hooks.${event} already registered`,\n removeDetail: (event, removed) => `hooks.${event} (${removed})`,\n absentDetail: \"no hooks section present\",\n noMatchDetail: \"no matching hook entries\",\n };\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 fixable: true,\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 case \"PostCompact\": {\n // Claude Code does NOT wire PostCompact as a normalized lifecycle hook\n // (capabilities.postCompact is unset, so installHooks never registers\n // it) — but the exhaustive guard below requires a case for every\n // HookEventName. This arm is a SAFE passthrough: it normalizes the\n // PreCompact-shaped `trigger` defensively, so a manual\n // `hook claude-code PostCompact` invocation normalizes instead of\n // throwing. It mirrors the PreCompact case byte-for-byte.\n const ev: PostCompactEvent = {\n ...base,\n ...(input.trigger === \"auto\" || input.trigger === \"manual\"\n ? { trigger: input.trigger }\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\nexport const adapter = new ClaudeCodeAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}
|