@ken-jo/agent-connector 0.3.1 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/README.md +180 -16
  2. package/dist/action-WT7GVRCC.js +55 -0
  3. package/dist/action-WT7GVRCC.js.map +1 -0
  4. package/dist/amazon-q-COAL3764.js +276 -0
  5. package/dist/amazon-q-COAL3764.js.map +1 -0
  6. package/dist/{amp-YGV66GJT.js → amp-4U33CU7E.js} +81 -5
  7. package/dist/amp-4U33CU7E.js.map +1 -0
  8. package/dist/{antigravity-7IBYFO6P.js → antigravity-AMKKKHS4.js} +4 -4
  9. package/dist/{antigravity-cli-JEOUP2VN.js → antigravity-cli-XERXEH5W.js} +4 -4
  10. package/dist/{chunk-3JCRUROU.js → chunk-24IDL5RW.js} +13 -4
  11. package/dist/chunk-24IDL5RW.js.map +1 -0
  12. package/dist/chunk-2AVLX7GH.js +351 -0
  13. package/dist/chunk-2AVLX7GH.js.map +1 -0
  14. package/dist/{chunk-GSGDG2BV.js → chunk-4ENJK5S2.js} +106 -176
  15. package/dist/chunk-4ENJK5S2.js.map +1 -0
  16. package/dist/{chunk-ZAM4M7LI.js → chunk-5OWS5CMA.js} +136 -296
  17. package/dist/chunk-5OWS5CMA.js.map +1 -0
  18. package/dist/{chunk-PD4VFEBY.js → chunk-CPLK7GTE.js} +79 -5
  19. package/dist/chunk-CPLK7GTE.js.map +1 -0
  20. package/dist/chunk-DCKFYWGM.js +237 -0
  21. package/dist/chunk-DCKFYWGM.js.map +1 -0
  22. package/dist/chunk-EGCBZ2DC.js +83 -0
  23. package/dist/chunk-EGCBZ2DC.js.map +1 -0
  24. package/dist/chunk-F5RX62T7.js +21 -0
  25. package/dist/chunk-F5RX62T7.js.map +1 -0
  26. package/dist/chunk-FAHIMJRU.js +177 -0
  27. package/dist/chunk-FAHIMJRU.js.map +1 -0
  28. package/dist/{chunk-MEH7GC7R.js → chunk-I5MLE6S7.js} +33 -3
  29. package/dist/chunk-I5MLE6S7.js.map +1 -0
  30. package/dist/{chunk-KVAAFYRR.js → chunk-KHO5WNTP.js} +2 -18
  31. package/dist/chunk-KHO5WNTP.js.map +1 -0
  32. package/dist/{chunk-KQSNDFBN.js → chunk-LQRAPXS4.js} +3 -3
  33. package/dist/{chunk-3RBLIHPZ.js → chunk-O5TWCIJN.js} +27 -17
  34. package/dist/chunk-O5TWCIJN.js.map +1 -0
  35. package/dist/{chunk-WNREHWKL.js → chunk-QREL7LZJ.js} +5 -4
  36. package/dist/chunk-QREL7LZJ.js.map +1 -0
  37. package/dist/{chunk-KMAKDD3Z.js → chunk-RIMVWCZY.js} +37 -12
  38. package/dist/chunk-RIMVWCZY.js.map +1 -0
  39. package/dist/{openclaw-UZ5BMCGQ.js → chunk-URHQMFB3.js} +210 -41
  40. package/dist/chunk-URHQMFB3.js.map +1 -0
  41. package/dist/chunk-WZA4CSGJ.js +28 -0
  42. package/dist/chunk-WZA4CSGJ.js.map +1 -0
  43. package/dist/chunk-XJ4S47CT.js +44 -0
  44. package/dist/chunk-XJ4S47CT.js.map +1 -0
  45. package/dist/{claude-code-4275HQU4.js → claude-code-W4PUFZL5.js} +194 -52
  46. package/dist/claude-code-W4PUFZL5.js.map +1 -0
  47. package/dist/cli/sdk.js +5 -3
  48. package/dist/cli/sdk.js.map +1 -1
  49. package/dist/cli.js +1 -1
  50. package/dist/cline-WRYMNS7Z.js +442 -0
  51. package/dist/cline-WRYMNS7Z.js.map +1 -0
  52. package/dist/{codebuff-LE3KBZGM.js → codebuff-DH5Y7GAT.js} +106 -5
  53. package/dist/codebuff-DH5Y7GAT.js.map +1 -0
  54. package/dist/{codex-4BY2ZJIW.js → codex-DDHIV767.js} +43 -11
  55. package/dist/codex-DDHIV767.js.map +1 -0
  56. package/dist/continue-K43SUHLQ.js +790 -0
  57. package/dist/continue-K43SUHLQ.js.map +1 -0
  58. package/dist/{copilot-cli-IPISKO3V.js → copilot-cli-Q3SSPT4V.js} +70 -12
  59. package/dist/copilot-cli-Q3SSPT4V.js.map +1 -0
  60. package/dist/{crush-X3E25EQG.js → crush-MBEH2R3I.js} +130 -6
  61. package/dist/crush-MBEH2R3I.js.map +1 -0
  62. package/dist/{cursor-UH3W622V.js → cursor-TMBXDYR4.js} +119 -16
  63. package/dist/cursor-TMBXDYR4.js.map +1 -0
  64. package/dist/{detect-U3E7NVNW.js → detect-KG5FG3EV.js} +5 -3
  65. package/dist/{detect-U3E7NVNW.js.map → detect-KG5FG3EV.js.map} +1 -1
  66. package/dist/{doctor-DZTWED4O.js → doctor-FLZF34Y3.js} +226 -96
  67. package/dist/doctor-FLZF34Y3.js.map +1 -0
  68. package/dist/{droid-T5VBRXZF.js → droid-JC2NT6S4.js} +298 -10
  69. package/dist/droid-JC2NT6S4.js.map +1 -0
  70. package/dist/{gemini-cli-ZSUK55UA.js → gemini-cli-ILR7M5X3.js} +62 -10
  71. package/dist/gemini-cli-ILR7M5X3.js.map +1 -0
  72. package/dist/{goose-M3RR3CZG.js → goose-SFO5BBGW.js} +112 -10
  73. package/dist/goose-SFO5BBGW.js.map +1 -0
  74. package/dist/{hermes-CUNKIAR5.js → hermes-3N7WN4WS.js} +329 -15
  75. package/dist/hermes-3N7WN4WS.js.map +1 -0
  76. package/dist/{hook-EVY7LOUQ.js → hook-XR3Z45FB.js} +16 -10
  77. package/dist/hook-XR3Z45FB.js.map +1 -0
  78. package/dist/index.d.ts +71 -3
  79. package/dist/index.js +23 -3
  80. package/dist/{install-OWAS5UIE.js → install-BSR62UHJ.js} +12 -9
  81. package/dist/{install-OWAS5UIE.js.map → install-BSR62UHJ.js.map} +1 -1
  82. package/dist/introspect-Nw8hTReX.d.ts +53 -0
  83. package/dist/{jetbrains-copilot-C3HDGGML.js → jetbrains-copilot-NRZHI5PC.js} +85 -18
  84. package/dist/jetbrains-copilot-NRZHI5PC.js.map +1 -0
  85. package/dist/{kilo-PKAJCWPX.js → kilo-5NWOXVSD.js} +16 -16
  86. package/dist/kilo-5NWOXVSD.js.map +1 -0
  87. package/dist/{kilo-cli-QWUVXG2O.js → kilo-cli-UZ7R5UOP.js} +3 -3
  88. package/dist/{kimi-EVD7YKXS.js → kimi-2YFK2GBA.js} +87 -25
  89. package/dist/kimi-2YFK2GBA.js.map +1 -0
  90. package/dist/{kiro-UQRY6EIO.js → kiro-YL6AWUYG.js} +3 -3
  91. package/dist/{leaderboard-CSWHI4UY.js → leaderboard-MJG24O35.js} +2 -2
  92. package/dist/mimo-code-FTMGSKMQ.js +790 -0
  93. package/dist/mimo-code-FTMGSKMQ.js.map +1 -0
  94. package/dist/{mux-5CI5FP2W.js → mux-5XZFB44C.js} +156 -6
  95. package/dist/mux-5XZFB44C.js.map +1 -0
  96. package/dist/nemoclaw-W5KEJ3WX.js +58 -0
  97. package/dist/nemoclaw-W5KEJ3WX.js.map +1 -0
  98. package/dist/{omp-AXA7XY22.js → omp-2QMEY6HD.js} +138 -18
  99. package/dist/omp-2QMEY6HD.js.map +1 -0
  100. package/dist/openclaw-EXJEFNZI.js +18 -0
  101. package/dist/openclaw-EXJEFNZI.js.map +1 -0
  102. package/dist/{opencode-NZBRLJN3.js → opencode-WNXYJR4X.js} +84 -27
  103. package/dist/opencode-WNXYJR4X.js.map +1 -0
  104. package/dist/{package-WFOS4QVU.js → package-ACZXJHWB.js} +8 -6
  105. package/dist/{package-WFOS4QVU.js.map → package-ACZXJHWB.js.map} +1 -1
  106. package/dist/{pi-WMTUX6ES.js → pi-PVVPVWKG.js} +3 -2
  107. package/dist/{pi-WMTUX6ES.js.map → pi-PVVPVWKG.js.map} +1 -1
  108. package/dist/{qwen-code-MRRIUQ3P.js → qwen-code-G4CXKUHR.js} +426 -10
  109. package/dist/qwen-code-G4CXKUHR.js.map +1 -0
  110. package/dist/{roo-code-NI5UU6JB.js → roo-code-67TYJIQR.js} +137 -4
  111. package/dist/roo-code-67TYJIQR.js.map +1 -0
  112. package/dist/runtime/index.d.ts +96 -2
  113. package/dist/runtime/index.js +19 -10
  114. package/dist/sdk/index.d.ts +52 -0
  115. package/dist/sdk/index.js +82 -0
  116. package/dist/sdk/index.js.map +1 -0
  117. package/dist/sdk/test.d.ts +74 -0
  118. package/dist/sdk/test.js +292 -0
  119. package/dist/sdk/test.js.map +1 -0
  120. package/dist/{serve-3C2VFPAY.js → serve-GER7URPR.js} +13 -9
  121. package/dist/{serve-3C2VFPAY.js.map → serve-GER7URPR.js.map} +1 -1
  122. package/dist/{status-MKQYX5MW.js → status-LAJE3BM5.js} +10 -7
  123. package/dist/{status-MKQYX5MW.js.map → status-LAJE3BM5.js.map} +1 -1
  124. package/dist/statusline-L376ZPZU.js +60 -0
  125. package/dist/statusline-L376ZPZU.js.map +1 -0
  126. package/dist/{telemetry-3DN6XGYB.js → telemetry-B3DX3PWU.js} +6 -4
  127. package/dist/{telemetry-3DN6XGYB.js.map → telemetry-B3DX3PWU.js.map} +1 -1
  128. package/dist/{trae-CQC72RHH.js → trae-7CZZGOGI.js} +99 -5
  129. package/dist/trae-7CZZGOGI.js.map +1 -0
  130. package/dist/{types-CNigfEuR.d.ts → types-CRVrFWeU.d.ts} +322 -18
  131. package/dist/{uninstall-WG6PFWF3.js → uninstall-ZYTW7YMZ.js} +12 -9
  132. package/dist/{uninstall-WG6PFWF3.js.map → uninstall-ZYTW7YMZ.js.map} +1 -1
  133. package/dist/{upgrade-32NC2RKI.js → upgrade-4LUEEOZW.js} +12 -9
  134. package/dist/{upgrade-32NC2RKI.js.map → upgrade-4LUEEOZW.js.map} +1 -1
  135. package/dist/{usage-CJOM2WQM.js → usage-ZFBVQF3H.js} +2 -2
  136. package/dist/{usage-event-472X3DOY.js → usage-event-GZ32AGEB.js} +12 -8
  137. package/dist/{usage-event-472X3DOY.js.map → usage-event-GZ32AGEB.js.map} +1 -1
  138. package/dist/{vscode-copilot-4RVRTCKV.js → vscode-copilot-MF2CDNMT.js} +23 -10
  139. package/dist/vscode-copilot-MF2CDNMT.js.map +1 -0
  140. package/dist/{warp-X6MB67NT.js → warp-VKG55TAT.js} +55 -4
  141. package/dist/warp-VKG55TAT.js.map +1 -0
  142. package/dist/windsurf-FU5G4SHF.js +443 -0
  143. package/dist/windsurf-FU5G4SHF.js.map +1 -0
  144. package/dist/{zed-NTCYW4V2.js → zed-SFUHL3GS.js} +3 -3
  145. package/package.json +10 -2
  146. package/dist/amp-YGV66GJT.js.map +0 -1
  147. package/dist/chunk-3JCRUROU.js.map +0 -1
  148. package/dist/chunk-3RBLIHPZ.js.map +0 -1
  149. package/dist/chunk-GSGDG2BV.js.map +0 -1
  150. package/dist/chunk-KMAKDD3Z.js.map +0 -1
  151. package/dist/chunk-KVAAFYRR.js.map +0 -1
  152. package/dist/chunk-MEH7GC7R.js.map +0 -1
  153. package/dist/chunk-NJU275US.js +0 -238
  154. package/dist/chunk-NJU275US.js.map +0 -1
  155. package/dist/chunk-PD4VFEBY.js.map +0 -1
  156. package/dist/chunk-WNREHWKL.js.map +0 -1
  157. package/dist/chunk-ZAM4M7LI.js.map +0 -1
  158. package/dist/claude-code-4275HQU4.js.map +0 -1
  159. package/dist/codebuff-LE3KBZGM.js.map +0 -1
  160. package/dist/codex-4BY2ZJIW.js.map +0 -1
  161. package/dist/copilot-cli-IPISKO3V.js.map +0 -1
  162. package/dist/crush-X3E25EQG.js.map +0 -1
  163. package/dist/cursor-UH3W622V.js.map +0 -1
  164. package/dist/doctor-DZTWED4O.js.map +0 -1
  165. package/dist/droid-T5VBRXZF.js.map +0 -1
  166. package/dist/gemini-cli-ZSUK55UA.js.map +0 -1
  167. package/dist/goose-M3RR3CZG.js.map +0 -1
  168. package/dist/hermes-CUNKIAR5.js.map +0 -1
  169. package/dist/hook-EVY7LOUQ.js.map +0 -1
  170. package/dist/jetbrains-copilot-C3HDGGML.js.map +0 -1
  171. package/dist/kilo-PKAJCWPX.js.map +0 -1
  172. package/dist/kimi-EVD7YKXS.js.map +0 -1
  173. package/dist/mux-5CI5FP2W.js.map +0 -1
  174. package/dist/omp-AXA7XY22.js.map +0 -1
  175. package/dist/openclaw-UZ5BMCGQ.js.map +0 -1
  176. package/dist/opencode-NZBRLJN3.js.map +0 -1
  177. package/dist/qwen-code-MRRIUQ3P.js.map +0 -1
  178. package/dist/roo-code-NI5UU6JB.js.map +0 -1
  179. package/dist/trae-CQC72RHH.js.map +0 -1
  180. package/dist/vscode-copilot-4RVRTCKV.js.map +0 -1
  181. package/dist/warp-X6MB67NT.js.map +0 -1
  182. /package/dist/{antigravity-7IBYFO6P.js.map → antigravity-AMKKKHS4.js.map} +0 -0
  183. /package/dist/{antigravity-cli-JEOUP2VN.js.map → antigravity-cli-XERXEH5W.js.map} +0 -0
  184. /package/dist/{chunk-KQSNDFBN.js.map → chunk-LQRAPXS4.js.map} +0 -0
  185. /package/dist/{kilo-cli-QWUVXG2O.js.map → kilo-cli-UZ7R5UOP.js.map} +0 -0
  186. /package/dist/{kiro-UQRY6EIO.js.map → kiro-YL6AWUYG.js.map} +0 -0
  187. /package/dist/{leaderboard-CSWHI4UY.js.map → leaderboard-MJG24O35.js.map} +0 -0
  188. /package/dist/{usage-CJOM2WQM.js.map → usage-ZFBVQF3H.js.map} +0 -0
  189. /package/dist/{zed-NTCYW4V2.js.map → zed-SFUHL3GS.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/adapters/copilot-cli/index.ts"],"sourcesContent":["/**\n * adapters/copilot-cli — GitHub Copilot CLI platform adapter for agent-connector.\n *\n * GitHub Copilot CLI is a json-stdio host: the host pipes a JSON payload to a\n * hook command on stdin and reads JSON/exit-code back. Its hook event names and\n * reply shape are Claude-compatible (PascalCase events, `hookSpecificOutput`\n * reply wrapper), so the normalized HookEventName values map 1:1 — no event\n * rename table is needed.\n *\n * Native config (user/global only — Copilot CLI has no project-scoped config):\n * - MCP servers: ~/.copilot/mcp-config.json, root key \"mcpServers\". An stdio\n * server is written with type \"local\" (the host also accepts \"stdio\") plus\n * `tools: [\"*\"]`. Remote servers use type \"http\".\n * - Hooks: a Claude-compatible hooks file shaped `{ version: 1, hooks: { … } }`\n * discovered from ~/.copilot/hooks/*.json. We write a single dedicated file,\n * ~/.copilot/hooks/agent-connector.json, so we never disturb a user's own\n * hook files and removal is a clean, scoped operation. Each event maps to an\n * array of flat command entries `{ matcher?, hooks: [{ type:\"command\", command }] }`\n * — the Claude shape, which Copilot CLI reads.\n * - Reply: a `hookSpecificOutput` object keyed by `hookEventName` carrying\n * `permissionDecision` (allow|deny|ask) + `permissionDecisionReason`,\n * `additionalContext`, and (PreToolUse) `updatedInput`. PreToolUse is\n * fail-closed on the host side; exit 0 + JSON refines the decision.\n *\n * Env handling: the host is not documented to support `${env:VAR}` interpolation\n * inside mcp-config.json, so env/header/url refs are resolved to literals at\n * install time via resolveEnvRefsDeep (the safe default for a no-native-interp\n * host, matching the Codex adapter's approach).\n *\n * Content surfaces (surfaces-design §4-5): Copilot CLI exposes skills and\n * subagents but NO prompt-file command surface, so commands inherit the\n * BaseAdapter skip/warn default (supportsCommands stays false).\n * - skills: folder-per-skill `<dir>/skills/<name>/SKILL.md` (+ resource files).\n * user scope → ~/.copilot/skills; project scope → <projectDir>/.github/skills.\n * - subagents: user scope → ~/.copilot/agents/<name>.agent.md; project scope →\n * <projectDir>/.github/agents/<name>.agent.md (md + frontmatter:\n * name, description, tools, model).\n * The .github/ tree is shared with the vscode-copilot and jetbrains-copilot\n * connectors; we write identical, idempotent content and on uninstall remove\n * only the files this connector wrote.\n *\n * Grounded in docs/research/understand-report.md §2 (Platform Integration\n * Matrix, \"GitHub Copilot CLI\" row).\n */\n\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport type { Adapter, HookReply, InstallContext, MemoryTarget, NormalizedEvent } from \"../spi.js\";\nimport type {\n ChangeRecord,\n DetectedPlatform,\n HealthCheck,\n HookEventName,\n HookParadigm,\n HookResponse,\n NotificationEvent,\n PermissionRequestEvent,\n PlatformCapabilities,\n PlatformId,\n PostToolUseEvent,\n PostToolUseFailureEvent,\n PreCompactEvent,\n PreToolUseEvent,\n ServerDef,\n SessionEndEvent,\n SessionStartEvent,\n SkillDef,\n StopEvent,\n SubagentDef,\n SubagentStartEvent,\n SubagentStopEvent,\n Transport,\n UserPromptSubmitEvent,\n} from \"../../core/types.js\";\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\nimport {\n buildHomeBinHookCommand,\n buildServeWrapperCommand,\n isHomeBinHookCommand,\n shouldWrapForTelemetry,\n} from \"../../core/spawn.js\";\n\nconst HOST: PlatformId = \"copilot-cli\";\nconst MCP_ROOT_KEY = \"mcpServers\";\n\n/** Native hooks-file version Copilot CLI expects (`{ version: 1, hooks: {…} }`). */\nconst COPILOT_HOOKS_VERSION = 1;\n\n/**\n * Copilot CLI accepts both camelCase and PascalCase hook event names; PascalCase\n * is the portable, Claude/VS Code-compatible form (and selects the snake_case\n * payload dialect), so we emit it directly. Our normalized HookEventName values\n * are already PascalCase and match 1:1, hence no rename table — every declared\n * event has a native equivalent, including the newer four: subagentStart\n * (additionalContext only, matcher on agent name), subagentStop (can block and\n * force continuation), permissionRequest (decision control), and\n * postToolUseFailure (recovery guidance; the host also has a broader\n * errorOccurred event we do not register).\n */\ntype CopilotHookEvent = HookEventName;\n\n/** A single Copilot CLI hook registration entry (Claude-shaped). */\ninterface CopilotHookEntry {\n matcher: string;\n hooks: Array<{ type: \"command\"; command: string }>;\n}\n\n/** The shape of the Copilot CLI hooks file we own. */\ninterface CopilotHooksFile {\n version?: number;\n hooks?: Record<string, CopilotHookEntry[]>;\n}\n\n/** Native MCP server entry shapes Copilot CLI accepts under `mcpServers`. */\ninterface CopilotLocalServer {\n /** stdio transport is registered as type \"local\" (host also accepts \"stdio\"). */\n type: \"local\";\n command: string;\n args?: string[];\n env?: Record<string, string>;\n cwd?: string;\n tools: string[];\n}\ninterface CopilotHttpServer {\n type: \"http\";\n url: string;\n headers?: Record<string, string>;\n tools: string[];\n}\n\n/** Raw Copilot CLI hook stdin payload (Claude-style: PascalCase event, snake_case fields). */\ninterface CopilotWireInput {\n connector?: unknown;\n session_id?: string;\n transcript_path?: string;\n cwd?: string;\n hook_event_name?: string;\n\n // tool events\n tool_name?: string;\n tool_input?: Record<string, unknown>;\n tool_response?: unknown;\n\n // SessionStart\n source?: string;\n // SessionEnd\n reason?: string;\n // UserPromptSubmit\n prompt?: string;\n // PreCompact\n trigger?: string;\n // Stop / SubagentStop\n stop_hook_active?: boolean;\n // Notification\n message?: string;\n\n // PermissionRequest — permission-update entries the dialog would offer.\n permission_suggestions?: unknown[];\n\n // PostToolUseFailure\n tool_use_id?: string;\n error?: string;\n is_interrupt?: boolean;\n duration_ms?: number;\n\n // SubagentStart / SubagentStop — agent_type is unreliable on SubagentStop\n // (Claude-compatible quirk); treat both as optional everywhere.\n agent_id?: string;\n agent_type?: string;\n // SubagentStop — the subagent's OWN transcript + its final response text.\n agent_transcript_path?: string;\n last_assistant_message?: string;\n}\n\nexport class CopilotCliAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"GitHub Copilot CLI\";\n readonly paradigm: HookParadigm = \"json-stdio\";\n\n readonly capabilities: PlatformCapabilities = {\n // Memory surface: AGENTS.md-first managed block (project <projectDir>/AGENTS.md\n // via the base default; user scope → ~/.copilot/copilot-instructions.md below).\n supportsMemory: true,\n // Copilot CLI delivers the full Claude-compatible lifecycle event set.\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 — Copilot CLI has native analogs for all four:\n // permissionRequest (decision control), postToolUseFailure (recovery\n // guidance), subagentStart (context-only), subagentStop (blockable).\n permissionRequest: true,\n postToolUseFailure: true,\n subagentStart: true,\n subagentStop: true,\n // PreToolUse is fail-closed and can rewrite tool input (updatedInput); a\n // PostToolUse hook cannot rewrite already-emitted tool output.\n canModifyArgs: true,\n canModifyOutput: false,\n canInjectSessionContext: true,\n transports: [\"stdio\", \"http\"],\n // Content surfaces: Copilot CLI exposes skills + subagents, but has no\n // prompt-file command surface, so commands stay false (inherits BaseAdapter\n // skip/warn).\n supportsCommands: false,\n supportsSkills: true,\n supportsSubagents: true,\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(_projectDir: string): DetectedPlatform {\n const userDir = join(homedir(), \".copilot\");\n const mcpConfig = join(userDir, \"mcp-config.json\");\n const hooksDir = join(userDir, \"hooks\");\n const installed =\n existsSync(userDir) || existsSync(mcpConfig) || existsSync(hooksDir);\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath: mcpConfig,\n scope: \"user\",\n reason: installed\n ? `found GitHub Copilot CLI config under ${userDir}`\n : `no GitHub Copilot CLI config at ${userDir}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Memory surface: user-scope global instructions file ─────────────────\n // Project scope stays on the AGENTS.md base default (root AGENTS.md is the\n // primary instructions file). User scope targets Copilot CLI's documented\n // $HOME/.copilot/copilot-instructions.md — a markdown file shared with other\n // writers, so the managed block (not whole-file ownership) applies as usual.\n protected override memoryTargets(ctx: InstallContext): MemoryTarget[] {\n if (this.memoryOverride(ctx)?.path || ctx.scope !== \"user\") {\n return super.memoryTargets(ctx);\n }\n return [\n {\n path: join(homedir(), \".copilot\", \"copilot-instructions.md\"),\n reason: \"copilot-cli global instructions (~/.copilot/copilot-instructions.md)\",\n },\n ];\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n /** Copilot CLI is user/global only — scope is ignored. */\n getConfigDir(_ctx: InstallContext): string {\n return join(homedir(), \".copilot\");\n }\n\n getServerConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"mcp-config.json\");\n }\n\n /**\n * Copilot CLI discovers hooks from any `~/.copilot/hooks/*.json`. We write a\n * single dedicated file so we never disturb the user's own hook files and\n * uninstall is a clean, scoped operation.\n */\n getHookConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"hooks\", \"agent-connector.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 copilot-cli\"\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 Copilot CLI's native mcpServers entry. */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): CopilotLocalServer | CopilotHttpServer {\n const transport: Transport = server.transport;\n const tools = this.renderTools(server);\n\n if (transport === \"stdio\") {\n let command = server.command ?? \"\";\n let args = [...(server.args ?? [])];\n\n // Transparent telemetry wrapping: route the real command through\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\n if (shouldWrapForTelemetry(server, ctx.connector.telemetry)) {\n const wrapped = buildServeWrapperCommand(\n ctx.homeBinPath,\n ctx.connector.id,\n command,\n args,\n ctx.scope,\n this.id,\n );\n command = wrapped.command;\n args = wrapped.args;\n }\n\n const entry: CopilotLocalServer = {\n type: \"local\",\n command: resolveEnvRefsDeep(command),\n tools,\n };\n if (args.length > 0) entry.args = args.map((a) => resolveEnvRefsDeep(a));\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) — Copilot registers a URL.\n const entry: CopilotHttpServer = {\n type: \"http\",\n url: resolveEnvRefsDeep(server.url ?? \"\"),\n tools,\n };\n const headers = this.renderEnv(server.headers);\n if (headers) entry.headers = headers;\n return entry;\n }\n\n /**\n * Render env/header values. Copilot CLI is not documented to support native\n * `${env:VAR}` interpolation in mcp-config.json, so refs resolve to literals\n * at install time (the safe default for a no-native-interp host).\n */\n private renderEnv(\n env: Record<string, string> | undefined,\n ): Record<string, string> | undefined {\n if (!env || Object.keys(env).length === 0) return undefined;\n return resolveEnvRefsDeep({ ...env });\n }\n\n /** Render the tool allow-list. Copilot CLI expects `tools` on every entry; default [\"*\"]. */\n private renderTools(server: ServerDef): string[] {\n const include = server.tools?.include;\n return include && include.length > 0 ? [...include] : [\"*\"];\n }\n\n // ── Hook install / uninstall ─────────────────────────────────────────────\n\n installHooks(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.hooks === false) {\n return [\n { platform: this.id, action: \"skip\", detail: \"hooks disabled for copilot-cli\" },\n ];\n }\n if (connector.hookEvents.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no hooks\" }];\n }\n\n const hooksPath = this.getHookConfigPath(ctx);\n const file = this.readJson<CopilotHooksFile>(hooksPath) ?? {};\n const hooks = (file.hooks ??= {});\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const event of connector.hookEvents) {\n // PascalCase events map 1:1 to Copilot CLI's native event names.\n const copilotEvent: CopilotHookEvent = event;\n const command = buildHomeBinHookCommand(ctx.homeBinPath, HOST, event, connector.id);\n const matcher = connector.hooks[event]?.matcher ?? \"\";\n const entry: CopilotHookEntry = {\n matcher,\n hooks: [{ type: \"command\", command }],\n };\n\n const bucket = (hooks[copilotEvent] ??= []);\n const existingIdx = bucket.findIndex((e) => this.entryHasOurCommand(e, ctx));\n\n if (existingIdx >= 0) {\n if (JSON.stringify(bucket[existingIdx]) === JSON.stringify(entry)) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: `hooks.${copilotEvent} already registered`,\n });\n continue;\n }\n bucket[existingIdx] = entry;\n changes.push({\n platform: this.id,\n action: \"update\",\n path: hooksPath,\n detail: `hooks.${copilotEvent}`,\n });\n } else {\n bucket.push(entry);\n changes.push({\n platform: this.id,\n action: \"create\",\n path: hooksPath,\n detail: `hooks.${copilotEvent}`,\n });\n }\n mutated = true;\n }\n\n if (mutated) {\n file.version = COPILOT_HOOKS_VERSION;\n this.writeJson(hooksPath, file, ctx.dryRun);\n }\n return changes;\n }\n\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n const hooksPath = this.getHookConfigPath(ctx);\n const file = this.readJson<CopilotHooksFile>(hooksPath);\n const hooks = file?.hooks;\n if (!file || !hooks) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: \"no hooks section present\",\n },\n ];\n }\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const copilotEvent of Object.keys(hooks)) {\n const bucket = hooks[copilotEvent];\n if (!Array.isArray(bucket)) continue;\n\n // Strip our hook command from each entry; drop entries left empty so we\n // never remove another connector's (or the user's own) hook commands.\n const next: CopilotHookEntry[] = [];\n let removed = 0;\n for (const e of bucket) {\n const innerBefore = e.hooks?.length ?? 0;\n const inner = (e.hooks ?? []).filter((h) => !this.isOurCommand(h.command, ctx));\n removed += innerBefore - inner.length;\n if (inner.length > 0) next.push({ matcher: e.matcher ?? \"\", hooks: inner });\n }\n\n if (removed > 0) {\n if (next.length > 0) hooks[copilotEvent] = next;\n else delete hooks[copilotEvent];\n changes.push({\n platform: this.id,\n action: \"remove\",\n path: hooksPath,\n detail: `hooks.${copilotEvent} (${removed})`,\n });\n mutated = true;\n }\n }\n\n if (mutated) this.writeJson(hooksPath, file, ctx.dryRun);\n if (changes.length === 0) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: \"no matching hook entries\",\n });\n }\n return changes;\n }\n\n private entryHasOurCommand(entry: CopilotHookEntry, ctx: InstallContext): boolean {\n return (entry.hooks ?? []).some((h) => this.isOurCommand(h.command, ctx));\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: skills / subagents ─────────────────────────────────\n // CONTENT-ONLY: pure native-file writers. No runtime dispatch, no home-bin\n // pointer, no telemetry wrap. Each method is idempotent (byte-identical →\n // skip) via BaseAdapter.writeContentFile and reversible via removeContentFile.\n // Honors platforms[\"copilot-cli\"] per-surface false to skip. Commands are\n // unsupported here — they inherit the BaseAdapter skip/warn default.\n //\n // Path scoping: user scope lives under ~/.copilot (getConfigDir); project\n // scope lives under the shared <projectDir>/.github tree (the same files\n // vscode-copilot / jetbrains-copilot would write). We write identical content\n // and on uninstall remove only the files this connector wrote.\n\n /** Root dir for content surfaces: ~/.copilot (user) or <projectDir>/.github (project). */\n private contentDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".github\")\n : this.getConfigDir(ctx);\n }\n\n private skillsDir(ctx: InstallContext): string {\n return join(this.contentDir(ctx), \"skills\");\n }\n private agentsDir(ctx: InstallContext): string {\n return join(this.contentDir(ctx), \"agents\");\n }\n\n /** Native skill dir: <contentDir>/skills/<name>. */\n private skillDir(ctx: InstallContext, name: string): string {\n return join(this.skillsDir(ctx), name);\n }\n /** Native subagent file path: <contentDir>/agents/<name>.agent.md. */\n private subagentPath(ctx: InstallContext, name: string): string {\n return join(this.agentsDir(ctx), `${name}.agent.md`);\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 copilot-cli\" }];\n }\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n changes.push(\n this.writeContentFile(join(dir, \"SKILL.md\"), this.renderSkill(skill), ctx.dryRun),\n );\n // Bundle any resource files beside SKILL.md (relative path → contents).\n // Defense-in-depth: skip+warn on any key that escapes the skill dir\n // (config-time validation already rejects these, but never trust input).\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n detail: `skill resource \"${rel}\" escapes the skill dir; skipped`,\n });\n continue;\n }\n changes.push(this.writeContentFile(target, contents, ctx.dryRun));\n }\n }\n return changes;\n }\n\n override uninstallSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n // Remove only the files we wrote (SKILL.md + declared resources), then the\n // skill dir itself when we own its full contents.\n changes.push(this.removeContentFile(join(dir, \"SKILL.md\"), ctx.dryRun));\n for (const rel of Object.keys(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) continue; // never delete outside the skill dir\n changes.push(this.removeContentFile(target, ctx.dryRun));\n }\n // Only remove the skill dir when WE own its full contents — never rm -rf a\n // dir that still holds user-added / sibling-tool / shared files.\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\n }\n return changes;\n }\n\n /**\n * Render a skill's SKILL.md: frontmatter (name, description + optional model,\n * allowed-tools, disable-model-invocation) + body. Uniform Agent Skills shape\n * shared across every skill-supporting connector.\n */\n private renderSkill(skill: SkillDef): string {\n const frontmatter: Record<string, unknown> = {\n name: skill.name,\n description: skill.description,\n };\n if (skill.model !== undefined) frontmatter.model = skill.model;\n const allow = skill.tools?.allow;\n if (allow && allow.length > 0) frontmatter[\"allowed-tools\"] = allow.join(\", \");\n if (skill.disableModelInvocation !== undefined) {\n frontmatter[\"disable-model-invocation\"] = skill.disableModelInvocation;\n }\n if (skill.extra) Object.assign(frontmatter, skill.extra);\n return this.renderFrontmatterMd(frontmatter, skill.body);\n }\n\n // ── 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 copilot-cli\" }];\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 (name, description, tools, model) + prompt body. */\n private renderSubagent(agent: SubagentDef): string {\n const frontmatter: Record<string, unknown> = {\n name: agent.name,\n description: agent.description,\n };\n const allow = agent.tools?.allow;\n if (allow && allow.length > 0) frontmatter.tools = allow.join(\", \");\n if (agent.model !== undefined) frontmatter.model = agent.model;\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 connectorId = ctx.connector.id;\n const homeBin = ctx.homeBinPath;\n const hookEvents = ctx.connector.hookEvents;\n const checks: HealthCheck[] = [\n {\n name: `${this.name}: mcp-config.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}: hook command registered`,\n check: () => {\n if (hookEvents.length === 0) {\n return { status: \"OK\", detail: \"no hooks declared\" };\n }\n const file = this.readJson<CopilotHooksFile>(hooksPath);\n if (!file) return { status: \"FAIL\", detail: `cannot read ${hooksPath}` };\n const hooks = file.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 : { status: \"FAIL\", detail: `no hook for ${connectorId} in ${hooksPath}` };\n },\n },\n ];\n\n // Content-surface checks: only assert presence of the surfaces this\n // connector declares (skip silently for surfaces it never asked for).\n // Commands are unsupported on Copilot CLI, so no command check.\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 Copilot CLI stdin JSON → normalized event ─────────────\n\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\n const input = (raw ?? {}) as CopilotWireInput;\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 toolOutput = toolResponseToString(input.tool_response);\n const ev: PostToolUseEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n ...(toolOutput !== undefined ? { toolOutput } : {}),\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 — hosts do not reliably populate\n // agent_type on SubagentStop (Claude-compatible quirk).\n const ev: SubagentStopEvent = {\n ...base,\n ...(typeof input.agent_id === \"string\" ? { agentId: input.agent_id } : {}),\n ...(typeof input.agent_type === \"string\"\n ? { agentType: input.agent_type }\n : {}),\n ...(typeof input.agent_transcript_path === \"string\"\n ? { agentTranscriptPath: input.agent_transcript_path }\n : {}),\n ...(typeof input.last_assistant_message === \"string\"\n ? { lastAssistantMessage: input.last_assistant_message }\n : {}),\n ...(typeof input.stop_hook_active === \"boolean\"\n ? { stopHookActive: input.stop_hook_active }\n : {}),\n };\n return ev;\n }\n default: {\n // Exhaustive guard — every HookEventName is handled above.\n const _never: never = event;\n throw new Error(`unsupported copilot-cli hook event: ${String(_never)}`);\n }\n }\n }\n\n // ── Runtime: normalized response → Copilot CLI native hook reply ─────────\n\n formatReply(event: HookEventName, response: HookResponse): HookReply {\n const hookEventName = event;\n const decision = response.decision ?? \"allow\";\n\n // PermissionRequest replies use the Claude-compatible nested\n // decision{behavior} envelope and are the ONE event where an EXPLICIT\n // \"allow\" is an ACTIVE grant (it suppresses the permission dialog) rather\n // than passthrough:\n // allow → decision{behavior:\"allow\"} (+updatedInput when set);\n // the host still enforces its own deny rules.\n // modify → an allow grant carrying updatedInput.\n // deny → decision{behavior:\"deny\", message}.\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 (recovery guidance beside the error) and SubagentStart\n // (context prepended to the SUBAGENT's conversation — creation is not\n // blockable on Copilot CLI) are observe/context-only: \"context\" emits\n // additionalContext, and a \"deny\" DEGRADES to the same shape carrying the\n // reason. 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 // SubagentStop is the Stop-semantics exception: like Claude, the block is\n // the TOP-LEVEL {\"decision\":\"block\",\"reason\"} — it keeps the subagent\n // running with `reason` as its next instruction (the host \"can block and\n // force continuation\").\n if (decision === \"deny\") {\n if (event === \"SubagentStop\") {\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: response.reason ?? \"Confirmation required by hook\",\n },\n });\n }\n\n // modify → rewrite PreToolUse input (only where Copilot CLI 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 Copilot CLI; 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 * Extract a stable session id from a Copilot CLI wire payload.\n * Priority mirrors the Claude wire protocol: transcript UUID > session_id > \"\".\n */\nfunction extractSessionId(input: CopilotWireInput): string {\n if (typeof input.transcript_path === \"string\") {\n const m = input.transcript_path.match(/([a-f0-9-]{36})\\.jsonl$/);\n if (m && m[1]) return m[1];\n }\n if (typeof input.session_id === \"string\" && input.session_id !== \"\") {\n return input.session_id;\n }\n return \"\";\n}\n\n/** Coerce a Copilot PostToolUse `tool_response` into a string for the normalized event. */\nfunction toolResponseToString(value: unknown): string | undefined {\n if (value == null) return undefined;\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nfunction normalizeSessionSource(source: string | undefined): SessionStartEvent[\"source\"] {\n switch (source) {\n case \"compact\":\n return \"compact\";\n case \"resume\":\n return \"resume\";\n case \"clear\":\n return \"clear\";\n default:\n return \"startup\";\n }\n}\n\nexport const adapter = new CopilotCliAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/adapters/crush/index.ts"],"sourcesContent":["/**\n * adapters/crush — Crush (Charm) platform adapter for agent-connector.\n *\n * Crush is a json-stdio host. A single JSON config file holds BOTH the MCP\n * server registrations and the hook registrations, and agent-connector MERGES\n * into it (never replaces it — unrelated keys are preserved verbatim):\n * - User scope: ~/.config/crush/crush.json\n * (Windows: %LOCALAPPDATA%\\crush\\crush.json)\n * - Project scope: ./.crush.json (preferred) or ./crush.json\n *\n * MCP servers live under the ROOT KEY \"mcp\" (NOT \"mcpServers\"). A stdio entry is\n * { type:\"stdio\", command, args, env, timeout:120, disabled:false }.\n * Hooks live under the top-level \"hooks\" key. Crush supports PreToolUse ONLY;\n * the hook reads the host's JSON on stdin and writes a JSON object on stdout\n * carrying a `decision` field. A deny is `{ decision:\"deny\", reason }` on\n * stdout (exit 0); an allow is an empty stdout (exit 0). Crush cannot rewrite\n * tool args/output nor inject session context — every non-deny decision (and\n * every non-PreToolUse event) degrades to a silent allow.\n *\n * SECURITY NOTE: Crush expands `$(...)` command substitution in its config file\n * at load time. We therefore NEVER emit shell-substitution syntax into the\n * command/args/env we write — every value is a literal path/string built by the\n * spawn helpers (which quote, not interpolate). Connector ids are kebab-case and\n * the home-bin path is an absolute literal, so nothing we write can be coerced\n * into a `$(...)` substitution.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport type { Adapter, HookReply, InstallContext, NormalizedEvent } from \"../spi.js\";\nimport type {\n ChangeRecord,\n DetectedPlatform,\n HealthCheck,\n HookEventName,\n HookParadigm,\n HookResponse,\n PlatformCapabilities,\n PlatformId,\n PreToolUseEvent,\n ServerDef,\n Transport,\n} from \"../../core/types.js\";\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\nimport {\n buildHomeBinHookCommand,\n buildServeWrapperCommand,\n isHomeBinHookCommand,\n shouldWrapForTelemetry,\n} from \"../../core/spawn.js\";\n\nconst HOST: PlatformId = \"crush\";\n/** Crush registers MCP servers under \"mcp\" — NOT the \"mcpServers\" of Claude/Gemini. */\nconst MCP_ROOT_KEY = \"mcp\";\n/** Default per-server timeout (seconds) Crush expects on a stdio entry. */\nconst STDIO_TIMEOUT_SECONDS = 120;\n\n/**\n * Crush hook events agent-connector can register. Crush honors PreToolUse ONLY,\n * and only its deny decision is meaningful; every other normalized event has no\n * Crush equivalent and is skipped at install time.\n */\nconst CRUSH_HOOK_EVENTS = [\"PreToolUse\"] as const;\ntype CrushHookEventName = (typeof CRUSH_HOOK_EVENTS)[number];\n\n/**\n * Newer canonical events with NO Crush analog: there is no permission-dialog,\n * tool-failure, or subagent lifecycle hook. Declared hooks for these warn-skip\n * at install so the degradation is reported, never silent. (The legacy silent\n * drop of the other unwired events — SessionStart, Stop, … — predates this\n * convention and is deliberately left untouched.)\n */\nconst WARN_SKIP_EVENTS: ReadonlySet<HookEventName> = new Set([\n \"PermissionRequest\",\n \"PostToolUseFailure\",\n \"SubagentStart\",\n \"SubagentStop\",\n]);\n\n// ─────────────────────────────────────────────────────────────────────────\n// Native config shapes (only the parts we touch; rest preserved verbatim)\n// ─────────────────────────────────────────────────────────────────────────\n\n/** One hook registration entry as Crush stores it under top-level \"hooks\". */\ninterface CrushHookEntry {\n matcher?: string;\n command: string;\n [key: string]: unknown;\n}\n\n/** Crush's crush.json shape — only the keys we read/merge. */\ninterface CrushConfigFile {\n mcp?: Record<string, unknown>;\n hooks?: Record<string, CrushHookEntry[]>;\n [key: string]: unknown;\n}\n\n/** Native stdio MCP server entry under \"mcp\". */\ninterface CrushStdioServer {\n type: \"stdio\";\n command: string;\n args: string[];\n env?: Record<string, string>;\n timeout: number;\n disabled: boolean;\n}\n\n/** Native HTTP MCP server entry under \"mcp\". */\ninterface CrushHttpServer {\n type: \"http\";\n url: string;\n headers?: Record<string, string>;\n timeout: number;\n disabled: boolean;\n}\n\n/** Raw Crush hook stdin payload (Claude-style: PascalCase event, snake_case fields). */\ninterface CrushHookInput {\n tool_name?: string;\n tool_input?: Record<string, unknown>;\n session_id?: string;\n cwd?: string;\n hook_event_name?: string;\n connector?: unknown;\n}\n\nexport class CrushAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"Crush\";\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 // PreToolUse deny is the only hook decision Crush honors.\n preToolUse: true,\n postToolUse: false,\n preCompact: false,\n sessionStart: false,\n sessionEnd: false,\n userPromptSubmit: false,\n stop: false,\n notification: false,\n // Newer events: Crush honors PreToolUse ONLY — no permission-dialog,\n // tool-failure, or subagent lifecycle events exist, so permissionRequest /\n // postToolUseFailure / subagentStart / subagentStop stay unset — install\n // reports the standard skip-warn for them.\n // Crush is deny-only: it cannot rewrite tool args/output nor inject context.\n canModifyArgs: false,\n canModifyOutput: false,\n canInjectSessionContext: false,\n transports: [\"stdio\", \"http\"],\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userDir = this.userConfigDir();\n const userConfig = join(userDir, \"crush.json\");\n const projectDot = join(projectDir, \".crush.json\");\n const projectBare = join(projectDir, \"crush.json\");\n const userInstalled = existsSync(userDir) || existsSync(userConfig);\n const projInstalled = existsSync(projectDot) || existsSync(projectBare);\n const installed = userInstalled || projInstalled;\n // Report the scope/path that actually matched so a project-only install is\n // not misreported as a (non-existent) user install.\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\n const projectPath = existsSync(projectBare) && !existsSync(projectDot) ? projectBare : projectDot;\n const configPath = scope === \"project\" ? projectPath : userConfig;\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 Crush config at ${configPath}`\n : `found Crush config under ${userDir}`\n : `no Crush config at ${userConfig}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n getConfigDir(ctx: InstallContext): string {\n return ctx.scope === \"project\" ? ctx.projectDir : this.userConfigDir();\n }\n\n /** MCP servers and hooks share ONE crush.json file. */\n getServerConfigPath(ctx: InstallContext): string {\n if (ctx.scope === \"project\") {\n // Prefer ./.crush.json, but MERGE into an existing ./crush.json if that is\n // the file already present (so we don't fork the user's config in two).\n const dot = join(ctx.projectDir, \".crush.json\");\n const bare = join(ctx.projectDir, \"crush.json\");\n if (existsSync(bare) && !existsSync(dot)) return bare;\n return dot;\n }\n return join(this.userConfigDir(), \"crush.json\");\n }\n\n /** Hooks live in the SAME crush.json under the top-level \"hooks\" key. */\n getHookConfigPath(ctx: InstallContext): string {\n return this.getServerConfigPath(ctx);\n }\n\n /**\n * Crush's user config dir:\n * - Windows: %LOCALAPPDATA%\\crush (Local; falls back to AppData/Local)\n * - macOS / Linux: ~/.config/crush\n */\n private userConfigDir(): string {\n if (process.platform === \"win32\") {\n const localAppData =\n process.env.LOCALAPPDATA && process.env.LOCALAPPDATA.trim() !== \"\"\n ? process.env.LOCALAPPDATA\n : resolve(homedir(), \"AppData\", \"Local\");\n return join(localAppData, \"crush\");\n }\n return join(homedir(), \".config\", \"crush\");\n }\n\n // ── MCP server install / uninstall (crush.json → mcp.<id>) ───────────────\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 crush\"\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 /**\n * Render a normalized ServerDef into Crush's native \"mcp\" entry. Crush has no\n * documented native `${env:VAR}` interpolation — and it expands `$(...)` at\n * load time — so refs are resolved to LITERALS at install time (the safe\n * posture for a host without native interpolation, matching Codex/Kimi).\n */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): CrushStdioServer | CrushHttpServer {\n const transport: Transport = server.transport;\n const disabled = server.enabled === false;\n\n if (transport === \"stdio\") {\n let command = server.command ?? \"\";\n let args = [...(server.args ?? [])];\n\n // Transparent telemetry wrapping: route the real command through\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\n if (shouldWrapForTelemetry(server, ctx.connector.telemetry)) {\n const wrapped = buildServeWrapperCommand(\n ctx.homeBinPath,\n ctx.connector.id,\n command,\n args,\n ctx.scope,\n this.id,\n );\n command = wrapped.command;\n args = wrapped.args;\n }\n\n // Resolve to literals — never emit `$(...)` Crush would expand at load.\n command = resolveEnvRefsDeep(command);\n args = resolveEnvRefsDeep(args);\n\n const entry: CrushStdioServer = {\n type: \"stdio\",\n command,\n args,\n timeout: STDIO_TIMEOUT_SECONDS,\n disabled,\n };\n const env = this.renderEnv(server.env);\n if (env) entry.env = env;\n return entry;\n }\n\n // http (and any other remote transport we surface) — Crush registers a URL.\n const entry: CrushHttpServer = {\n type: \"http\",\n url: resolveEnvRefsDeep(server.url ?? \"\"),\n timeout: STDIO_TIMEOUT_SECONDS,\n disabled,\n };\n const headers = this.renderEnv(server.headers);\n if (headers) entry.headers = headers;\n return entry;\n }\n\n /** Resolve env/header values to literals (no native interpolation on Crush). */\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(resolveEnvRefsDeep({ ...env }))) {\n out[k] = String(v);\n }\n return out;\n }\n\n // ── Hook install / uninstall (crush.json → hooks.PreToolUse[]) ───────────\n\n installHooks(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.hooks === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"hooks disabled for crush\" }];\n }\n\n const events = this.effectiveHookEvents(ctx);\n const dropped = this.warnSkipHookEvents(ctx);\n const path = this.getHookConfigPath(ctx);\n\n if (events.length === 0 && dropped.length === 0) {\n return [{ platform: this.id, action: \"skip\", path, detail: \"no hooks declared\" }];\n }\n\n const cfg = this.readJson<CrushConfigFile>(path) ?? {};\n const hooks = (cfg.hooks ??= {});\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n // Declared events Crush cannot fire are reported, never silently dropped.\n for (const event of dropped) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n path,\n detail: `${event} has no Crush hook equivalent — skipped`,\n });\n }\n\n for (const event of events) {\n const command = buildHomeBinHookCommand(ctx.homeBinPath, HOST, event, connector.id);\n const matcher = connector.hooks[event]?.matcher ?? \"\";\n const entry: CrushHookEntry = { matcher, command };\n\n const bucket = (hooks[event] ??= []);\n const existingIdx = bucket.findIndex((e) => this.isOurHook(e, ctx));\n\n if (existingIdx >= 0) {\n if (JSON.stringify(bucket[existingIdx]) === JSON.stringify(entry)) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path,\n detail: `hooks.${event} already registered`,\n });\n continue;\n }\n bucket[existingIdx] = entry;\n changes.push({ platform: this.id, action: \"update\", path, detail: `hooks.${event}` });\n } else {\n bucket.push(entry);\n changes.push({ platform: this.id, action: \"create\", path, detail: `hooks.${event}` });\n }\n mutated = true;\n }\n\n if (mutated) this.writeJson(path, cfg, ctx.dryRun);\n return changes;\n }\n\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n const path = this.getHookConfigPath(ctx);\n const cfg = this.readJson<CrushConfigFile>(path);\n const hooks = cfg?.hooks;\n if (!cfg || !hooks) {\n return [\n { platform: this.id, action: \"skip\", path, detail: \"no hooks section present\" },\n ];\n }\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const event of Object.keys(hooks)) {\n const bucket = hooks[event];\n if (!Array.isArray(bucket)) continue;\n\n // Keep every entry that is NOT ours (anchored match) so a shared-prefix\n // connector id — or the user's own hook — is never stripped.\n const kept = bucket.filter((e) => !this.isOurHook(e, ctx));\n const removed = bucket.length - kept.length;\n if (removed > 0) {\n if (kept.length > 0) hooks[event] = kept;\n else delete hooks[event];\n changes.push({\n platform: this.id,\n action: \"remove\",\n path,\n detail: `hooks.${event} (${removed})`,\n });\n mutated = true;\n }\n }\n\n if (mutated) this.writeJson(path, cfg, ctx.dryRun);\n if (changes.length === 0) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path,\n detail: \"no matching hook entries\",\n });\n }\n return changes;\n }\n\n // ── Internal helpers ─────────────────────────────────────────────────────\n\n /** Which canonical hook events to register for Crush, honoring overrides. */\n private effectiveHookEvents(ctx: InstallContext): CrushHookEventName[] {\n if (ctx.connector.platforms[HOST]?.hooks === false) return [];\n return CRUSH_HOOK_EVENTS.filter((e) => ctx.connector.hookEvents.includes(e));\n }\n\n /** Declared events Crush has no analog for — install reports a warn-skip. */\n private warnSkipHookEvents(ctx: InstallContext): HookEventName[] {\n if (ctx.connector.platforms[HOST]?.hooks === false) return [];\n return ctx.connector.hookEvents.filter((e) => WARN_SKIP_EVENTS.has(e));\n }\n\n /**\n * Does this hook entry belong to this connector? Anchored on the home-bin +\n * connector-id token (isHomeBinHookCommand) so uninstalling a shared-prefix\n * connector id never strips a sibling's hook.\n */\n private isOurHook(entry: CrushHookEntry | undefined, ctx: InstallContext): boolean {\n if (!entry || typeof entry !== \"object\") return false;\n return isHomeBinHookCommand(entry.command, ctx.homeBinPath, ctx.connector.id);\n }\n\n // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const configPath = this.getServerConfigPath(ctx);\n const connectorId = ctx.connector.id;\n const homeBin = ctx.homeBinPath;\n const hookEvents = this.effectiveHookEvents(ctx);\n return [\n {\n name: `${this.name}: crush.json present`,\n check: () =>\n existsSync(configPath)\n ? { status: \"OK\", detail: configPath }\n : { status: \"FAIL\", detail: `not found: ${configPath}` },\n },\n {\n name: `${this.name}: mcp.${connectorId} registered`,\n check: () => {\n if (!ctx.connector.server) return { status: \"OK\", detail: \"no MCP server declared\" };\n const cfg = this.readJson<CrushConfigFile>(configPath);\n const bucket = cfg?.[MCP_ROOT_KEY];\n const present =\n typeof bucket === \"object\" && bucket !== null && connectorId in bucket;\n return present\n ? { status: \"OK\", detail: `mcp.${connectorId}` }\n : { status: \"FAIL\", detail: `mcp.${connectorId} not found in ${configPath}` };\n },\n },\n {\n name: `${this.name}: hook command registered`,\n check: () => {\n if (hookEvents.length === 0) {\n return { status: \"OK\", detail: \"no hooks declared\" };\n }\n const cfg = this.readJson<CrushConfigFile>(configPath);\n if (!cfg) return { status: \"FAIL\", detail: `cannot read ${configPath}` };\n const hooks = cfg.hooks ?? {};\n const registered = Object.values(hooks).some((entries) =>\n (entries ?? []).some((e) => isHomeBinHookCommand(e?.command, homeBin, connectorId)),\n );\n return registered\n ? { status: \"OK\", detail: \"hook command present\" }\n : { status: \"FAIL\", detail: `no hook for ${connectorId} in ${configPath}` };\n },\n },\n ];\n }\n\n // ── Runtime: parse Crush stdin JSON → normalized event ───────────────────\n\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\n const input = (raw ?? {}) as CrushHookInput;\n const connectorId = typeof input.connector === \"string\" ? input.connector : \"\";\n const sessionId = typeof input.session_id === \"string\" ? input.session_id : \"\";\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 if (event === \"PreToolUse\") {\n const ev: PreToolUseEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n };\n return ev;\n }\n\n // Crush only ever delivers PreToolUse. Surface anything else loudly rather\n // than silently mis-parsing a payload the host cannot actually produce.\n throw new Error(`unsupported crush hook event: ${String(event)}`);\n }\n\n // ── Runtime: normalized response → Crush native hook reply ───────────────\n\n formatReply(event: HookEventName, response: HookResponse): HookReply {\n const decision = response.decision ?? \"allow\";\n\n // deny → Crush blocks the pending tool call via a stdout JSON object with a\n // `decision:\"deny\"` (+ reason). Only PreToolUse is honored; every other\n // event/decision degrades to a silent allow.\n if (decision === \"deny\" && event === \"PreToolUse\") {\n return this.stdout({\n decision: \"deny\",\n reason: response.reason ?? \"Blocked by hook\",\n });\n }\n\n // allow / modify / context / ask / unsupported → pass through (exit 0, empty\n // stdout). Crush cannot rewrite args/output or inject context, so those are\n // dropped fail-open here (the deny path above is the only fail-safe lever).\n return { exitCode: 0 };\n }\n\n private stdout(payload: unknown): HookReply {\n return { exitCode: 0, stdout: JSON.stringify(payload) };\n }\n}\n\nexport const adapter = new CrushAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}
@@ -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 (`buildHomeBinHookCommand`) so one\n * 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, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { BaseAdapter } 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 PreToolUseEvent,\n ServerDef,\n SessionStartEvent,\n SkillDef,\n StopEvent,\n SubagentDef,\n SubagentStartEvent,\n SubagentStopEvent,\n Transport,\n} from \"../../core/types.js\";\nimport { rewriteEnvRefs } from \"../../core/interpolate.js\";\nimport {\n buildHomeBinHookCommand,\n buildServeWrapperCommand,\n isHomeBinHookCommand,\n shouldWrapForTelemetry,\n} from \"../../core/spawn.js\";\n\nconst HOST: PlatformId = \"cursor\";\nconst MCP_ROOT_KEY = \"mcpServers\";\n\n/** Native hooks.json version Cursor expects. */\nconst 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} 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 */\nconst 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};\n\n/** A single Cursor native hook entry — a flat command object. */\ninterface CursorHookEntry {\n command: string;\n matcher?: string;\n}\n\n/** The shape of Cursor's hooks.json. */\ninterface CursorHooksFile {\n version?: number;\n hooks?: Record<string, CursorHookEntry[]>;\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 // 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, and stop.\n preToolUse: true,\n postToolUse: true,\n preCompact: false,\n sessionStart: true,\n sessionEnd: false,\n userPromptSubmit: false,\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 };\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 if (shouldWrapForTelemetry(server, ctx.connector.telemetry)) {\n const wrapped = buildServeWrapperCommand(\n ctx.homeBinPath,\n ctx.connector.id,\n command,\n args,\n ctx.scope,\n this.id,\n );\n command = wrapped.command;\n args = wrapped.args;\n }\n\n const entry: 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 if (connector.platforms[HOST]?.hooks === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"hooks disabled for cursor\" }];\n }\n if (connector.hookEvents.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no hooks\" }];\n }\n\n const hooksPath = this.getHookConfigPath(ctx);\n const file = this.readJson<CursorHooksFile>(hooksPath) ?? {};\n const hooks = (file.hooks ??= {});\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const event of connector.hookEvents) {\n const cursorEvent = EVENT_MAP[event];\n if (!cursorEvent) {\n // No Cursor equivalent for this normalized event — report and skip.\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: hooksPath,\n detail: `${event} has no Cursor hook equivalent — skipped`,\n });\n continue;\n }\n\n const command = buildHomeBinHookCommand(ctx.homeBinPath, HOST, event, connector.id);\n const matcher = connector.hooks[event]?.matcher;\n const entry: CursorHookEntry = matcher ? { command, matcher } : { command };\n\n const bucket = (hooks[cursorEvent] ??= []);\n const existingIdx = bucket.findIndex((e) => this.isOurCommand(e.command, ctx));\n\n if (existingIdx >= 0) {\n if (JSON.stringify(bucket[existingIdx]) === JSON.stringify(entry)) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: `hooks.${cursorEvent} already registered`,\n });\n continue;\n }\n bucket[existingIdx] = entry;\n changes.push({\n platform: this.id,\n action: \"update\",\n path: hooksPath,\n detail: `hooks.${cursorEvent}`,\n });\n } else {\n bucket.push(entry);\n changes.push({\n platform: this.id,\n action: \"create\",\n path: hooksPath,\n detail: `hooks.${cursorEvent}`,\n });\n }\n mutated = true;\n }\n\n if (mutated) {\n file.version = CURSOR_HOOKS_VERSION;\n this.writeJson(hooksPath, file, ctx.dryRun);\n }\n return changes;\n }\n\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n const hooksPath = this.getHookConfigPath(ctx);\n const file = this.readJson<CursorHooksFile>(hooksPath);\n const hooks = file?.hooks;\n if (!file || !hooks) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: \"no hooks section present\",\n },\n ];\n }\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const cursorEvent of Object.keys(hooks)) {\n const bucket = hooks[cursorEvent];\n if (!Array.isArray(bucket)) continue;\n\n const before = bucket.length;\n const next = bucket.filter((e) => !this.isOurCommand(e.command, ctx));\n const removed = before - next.length;\n if (removed > 0) {\n if (next.length > 0) hooks[cursorEvent] = next;\n else delete hooks[cursorEvent];\n changes.push({\n platform: this.id,\n action: \"remove\",\n path: hooksPath,\n detail: `hooks.${cursorEvent} (${removed})`,\n });\n mutated = true;\n }\n }\n\n if (mutated) this.writeJson(hooksPath, file, ctx.dryRun);\n if (changes.length === 0) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: \"no matching hook entries\",\n });\n }\n return changes;\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, \"&gt;\"));\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\"), this.renderSkill(skill), ctx.dryRun),\n );\n // Bundle any resource files beside SKILL.md (relative path → contents).\n // Defense-in-depth: skip+warn on any key that escapes the skill dir\n // (config-time validation already rejects these, but never trust input).\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n detail: `skill resource \"${rel}\" escapes the skill dir; skipped`,\n });\n continue;\n }\n changes.push(this.writeContentFile(target, contents, ctx.dryRun));\n }\n }\n return changes;\n }\n\n override uninstallSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n // Remove only the files we wrote (SKILL.md + declared resources), then the\n // skill dir itself when we own its full contents.\n changes.push(this.removeContentFile(join(dir, \"SKILL.md\"), ctx.dryRun));\n for (const rel of Object.keys(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) continue; // never delete outside the skill dir\n changes.push(this.removeContentFile(target, ctx.dryRun));\n }\n // Only remove the skill dir when WE own its full contents — never rm -rf a\n // dir that still holds user-added / sibling-tool / shared files.\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\n }\n return changes;\n }\n\n /**\n * Render a skill's SKILL.md: frontmatter (name, description + optional model,\n * allowed-tools, disable-model-invocation) + body. Uniform across platforms;\n * only the parent dir differs.\n */\n private renderSkill(skill: SkillDef): string {\n const frontmatter: Record<string, unknown> = {\n name: skill.name,\n description: skill.description,\n };\n if (skill.model !== undefined) frontmatter.model = skill.model;\n const allow = skill.tools?.allow;\n if (allow && allow.length > 0) frontmatter[\"allowed-tools\"] = allow.join(\", \");\n if (skill.disableModelInvocation !== undefined) {\n frontmatter[\"disable-model-invocation\"] = skill.disableModelInvocation;\n }\n if (skill.extra) Object.assign(frontmatter, skill.extra);\n return this.renderFrontmatterMd(frontmatter, skill.body);\n }\n\n // ── 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 \"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 SessionEnd / UserPromptSubmit / PreCompact /\n // Notification / PermissionRequest (no native equivalent — permission\n // is an OUTPUT field of its before* hooks, not an event). If the\n // 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 // 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\nfunction normalizeSessionSource(source: string | undefined): SessionStartEvent[\"source\"] {\n switch (source) {\n case \"compact\":\n return \"compact\";\n case \"resume\":\n return \"resume\";\n case \"clear\":\n return \"clear\";\n default:\n return \"startup\";\n }\n}\n\nexport const adapter = new CursorAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cli/commands/doctor.ts","../src/runtime/probe.ts"],"sourcesContent":["/**\n * cli/commands/doctor — health-check every detected platform.\n *\n * For each detected host (or the explicit --targets list) we load its adapter,\n * build a uniform InstallContext, and run adapter.doctor(ctx). Results are\n * printed as pass/warn/fail with any suggested fix. Exit code is non-zero when\n * any check fails (warns alone do not fail the command).\n *\n * The connector context comes from the local config when present; otherwise a\n * minimal id-only connector is used so path-only checks still run.\n */\n\nimport { parseArgs } from \"node:util\";\n\nimport type {\n DiagnosticResult,\n InstallScope,\n PlatformId,\n ResolvedConnector,\n} from \"../../core/types.js\";\nimport type { InstallContext } from \"../../adapters/spi.js\";\nimport { detectInstalledPlatforms } from \"../../adapters/detect.js\";\nimport { loadAdapter, REGISTERED_PLATFORM_IDS } from \"../../adapters/registry.js\";\nimport {\n findConnectorConfig,\n listRegisteredConnectors,\n loadConnectorFromPath,\n} from \"../../core/load-connector.js\";\nimport { marketplaceDoctorChecks } from \"../../core/marketplace.js\";\nimport { readMarketplaceInstalls } from \"../../core/marketplace-state.js\";\nimport { dataRoot, homeBinPath } from \"../../core/paths.js\";\nimport { probeStdioServer } from \"../../runtime/probe.js\";\nimport { fail, parseScope, parseTargets, print } from \"../app.js\";\n\nconst STATUS_GLYPH: Record<DiagnosticResult[\"status\"], string> = {\n pass: \"[pass]\",\n warn: \"[warn]\",\n fail: \"[FAIL]\",\n};\n\n/**\n * Resolve which connector(s) doctor should health-check, in precedence order:\n * 1. An explicit --connector path, or a local agent-connector.config.* file.\n * 2. Every connector registered under the data-root (what is actually\n * installed). This is the common case — `doctor` from anywhere reports on\n * the real installs, not a guess from the working directory.\n * 3. A minimal id-only placeholder so path-only checks still run.\n */\nasync function resolveDoctorConnectors(\n connectorPath: string | undefined,\n projectDir: string,\n): Promise<ResolvedConnector[]> {\n const configPath = connectorPath ?? findConnectorConfig(projectDir);\n if (configPath) {\n try {\n const { connector } = await loadConnectorFromPath(configPath);\n return [connector];\n } catch {\n /* fall through */\n }\n }\n\n const registered = listRegisteredConnectors();\n if (registered.length > 0) return registered;\n\n return [\n {\n id: \"agent-connector\",\n displayName: \"agent-connector\",\n version: \"0.0.0\",\n hooks: {},\n hookEvents: [],\n telemetry: {\n enabled: true,\n modelFamilyHint: \"auto\",\n measureToolDefs: true,\n hostNativeUsage: false,\n store: \"ndjson\",\n calibration: { anthropicCountTokens: false },\n },\n commands: [],\n skills: [],\n subagents: [],\n memory: [],\n platforms: {},\n targets: \"auto\",\n },\n ];\n}\n\nfunction buildContext(\n connector: ResolvedConnector,\n id: PlatformId,\n scope: InstallScope,\n projectDir: string,\n): InstallContext {\n return {\n connector,\n scope: connector.platforms[id]?.scope ?? scope,\n projectDir,\n homeBinPath: homeBinPath(),\n dataRoot: dataRoot(),\n dryRun: true,\n };\n}\n\nexport async function run(argv: string[]): Promise<number> {\n const { values } = parseArgs({\n args: argv,\n options: {\n scope: { type: \"string\", default: \"user\" },\n targets: { type: \"string\" },\n connector: { type: \"string\" },\n project: { type: \"string\" },\n json: { type: \"boolean\", default: false },\n probe: { type: \"boolean\", default: false },\n },\n allowPositionals: false,\n });\n\n const projectDir = values.project ?? process.cwd();\n\n const scope = parseScope(values.scope);\n if (scope == null) return fail(`invalid --scope \"${values.scope}\" (use user|project)`);\n\n const connectors = await resolveDoctorConnectors(values.connector, projectDir);\n const multi = connectors.length > 1;\n\n // Target set: explicit --targets (intersected with the registry), else the\n // same chain install uses — connector-declared targets ∩ detected platforms\n // (\"auto\" = everything detected). Without this, doctor red-flags every\n // detected host the connector never targeted (found dogfooding context-mode:\n // targets:[5 ids] installed clean, doctor FAILed the other 9 detected hosts).\n const explicit = parseTargets(values.targets);\n let ids: PlatformId[];\n if (explicit && explicit.length > 0) {\n ids = explicit.filter((id) => REGISTERED_PLATFORM_IDS.has(id));\n } else {\n const detected = await detectInstalledPlatforms(projectDir);\n ids = detected.map((p) => p.id);\n const anyAuto = connectors.some((c) => c.targets === \"auto\");\n if (!anyAuto) {\n const targeted = new Set(connectors.flatMap((c) => c.targets as PlatformId[]));\n ids = ids.filter((id) => targeted.has(id));\n }\n }\n\n if (ids.length === 0 && !values.probe) {\n print(\"doctor: no target platforms (none detected; pass --targets to force).\");\n return 0;\n }\n\n const byPlatform: { platform: PlatformId; results: DiagnosticResult[] }[] = [];\n let anyFail = false;\n\n for (const id of ids) {\n const adapter = await loadAdapter(id);\n if (!adapter) {\n byPlatform.push({\n platform: id,\n results: [\n {\n check: `${id}: adapter`,\n status: \"fail\",\n message: `no adapter registered for ${id}`,\n },\n ],\n });\n anyFail = true;\n continue;\n }\n const results: DiagnosticResult[] = [];\n for (const connector of connectors) {\n // A connector with an explicit target list is only checked on those hosts.\n if (connector.targets !== \"auto\" && !connector.targets.includes(id)) continue;\n\n // MARKETPLACE-installed on this host: its surfaces are delivered via the\n // host's plugin (in the plugin cache), NOT the direct-config locations the\n // adapter's doctor() inspects — so the direct checks would falsely FAIL\n // (mcp_servers/command/skill \"not found\"). Skip them; the marketplace-method\n // checks below cover this install's real health.\n if (readMarketplaceInstalls(connector.id)[id]) {\n const note: DiagnosticResult = {\n check: `${connector.id}: ${id} delivery`,\n status: \"pass\",\n message: \"surfaces delivered via the marketplace plugin — see marketplace checks\",\n };\n results.push(multi ? { ...note, check: `(${connector.id}) ${note.check}` } : note);\n continue;\n }\n\n const ctx = buildContext(connector, id, scope, projectDir);\n let r: DiagnosticResult[];\n try {\n r = adapter.doctor(ctx);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n r = [{ check: `${adapter.name}: doctor`, status: \"fail\", message }];\n }\n // When checking multiple connectors, tag each check with the connector id.\n results.push(\n ...(multi\n ? r.map((d) => ({ ...d, check: `(${connector.id}) ${d.check}` }))\n : r),\n );\n }\n if (results.some((d) => d.status === \"fail\")) anyFail = true;\n byPlatform.push({ platform: id, results });\n }\n\n // ── Marketplace-method checks (framework-level, read-only fs — they run in\n // isolated homes without spawning a host CLI): duplicate-registration,\n // registration intact, state↔host drift, staleness, the embedded home-bin\n // launcher, missing host binary. Silent for connectors with no marketplace\n // state at all. Results merge into the platform's bucket (appended when the\n // platform was not otherwise targeted, e.g. a recorded install whose host\n // binary disappeared).\n for (const connector of connectors) {\n const groups = await marketplaceDoctorChecks(connector, scope, projectDir);\n for (const group of groups) {\n const tagged = multi\n ? group.results.map((d) => ({ ...d, check: `(${connector.id}) ${d.check}` }))\n : group.results;\n if (tagged.some((d) => d.status === \"fail\")) anyFail = true;\n const bucket = byPlatform.find((b) => b.platform === group.platform);\n if (bucket) bucket.results.push(...tagged);\n else byPlatform.push({ platform: group.platform, results: tagged });\n }\n }\n\n // ── Live MCP probe (--probe): connector-scoped, not platform-scoped ──────\n // Spawns each connector's REAL stdio server and runs initialize → ping →\n // tools/list. Probe FAILs fold into the doctor exit code.\n const probes: { connector: string; results: DiagnosticResult[] }[] = [];\n if (values.probe) {\n for (const connector of connectors) {\n const s = connector.server;\n if (!s || s.transport !== \"stdio\" || !s.command) {\n probes.push({\n connector: connector.id,\n results: [\n {\n check: `${connector.id}: MCP probe`,\n status: \"warn\",\n message: s\n ? `transport \"${s.transport}\" is not stdio — live probe skipped`\n : \"no server to probe\",\n },\n ],\n });\n continue;\n }\n const results = await probeStdioServer(s.command, s.args ?? [], {\n label: connector.id,\n ...(s.env ? { env: s.env } : {}),\n });\n if (results.some((d) => d.status === \"fail\")) anyFail = true;\n probes.push({ connector: connector.id, results });\n }\n }\n\n if (values.json) {\n print(JSON.stringify(values.probe ? { platforms: byPlatform, probes } : byPlatform, null, 2));\n return anyFail ? 1 : 0;\n }\n\n for (const { platform, results } of byPlatform) {\n print(`${platform}:`);\n for (const r of results) {\n print(` ${STATUS_GLYPH[r.status]} ${r.check} — ${r.message}`);\n if (r.fix) print(` fix: ${r.fix}`);\n }\n print(\"\");\n }\n for (const { connector, results } of probes) {\n print(`probe ${connector}:`);\n for (const r of results) {\n print(` ${STATUS_GLYPH[r.status]} ${r.check} — ${r.message}`);\n if (r.fix) print(` fix: ${r.fix}`);\n }\n print(\"\");\n }\n print(anyFail ? \"doctor: one or more checks FAILED.\" : \"doctor: all checks passed.\");\n return anyFail ? 1 : 0;\n}\n","/**\n * runtime/probe — a live MCP connection-lifecycle probe for `doctor --probe`.\n *\n * Where `doctor` checks files on disk, this spawns the connector's REAL stdio\n * server and speaks the MCP wire protocol to it: initialize → (read negotiated\n * protocolVersion + capabilities + serverInfo) → notifications/initialized →\n * ping (liveness) → tools/list (gated on the tools capability). It reuses the\n * SAME newline-delimited JSON-RPC framing + id-correlation as the telemetry\n * proxy (telemetry/jsonrpc), so the probe and the serve path read the wire\n * identically. Each step becomes a DiagnosticResult so doctor renders/aggregates\n * it uniformly; a dead/unlaunchable server FAILs (non-zero doctor exit).\n *\n * Negotiation rule: we OFFER {@link MCP_PROTOCOL_VERSION} but ACCEPT whatever\n * version the server returns (we only report it), per the spec — never a\n * hardcoded equality. There is no MCP shutdown message; we close stdin then\n * SIGTERM/SIGKILL.\n */\n\nimport type { DiagnosticResult } from \"../core/types.js\";\nimport { MCP_PROTOCOL_VERSION } from \"../core/mcp-standard.js\";\nimport { spawnChild } from \"../core/spawn-child.js\";\nimport { type JsonRpcMessage, LineBuffer, idKey, isObject } from \"../telemetry/jsonrpc.js\";\n\nconst DEFAULT_TIMEOUT_MS = 5000;\n\nexport interface ProbeOptions {\n /** Per-step timeout in ms (default 5000). */\n timeoutMs?: number;\n /** Prefix for each DiagnosticResult.check (e.g. the connector id). */\n label?: string;\n /** Env merged over process.env for the spawned server (${env:VAR} resolved). */\n env?: Record<string, string>;\n /** Protocol version offered in initialize. Default {@link MCP_PROTOCOL_VERSION}. */\n protocolVersion?: string;\n}\n\nfunction diag(\n status: DiagnosticResult[\"status\"],\n check: string,\n message: string,\n fix?: string,\n): DiagnosticResult {\n return { check, status, message, ...(fix ? { fix } : {}) };\n}\n\nfunction errMsg(e: unknown): string {\n return e instanceof Error ? e.message : String(e);\n}\n\n/** Resolve `${env:VAR}` references in env values against the current process env. */\nfunction resolveEnv(env: Record<string, string> | undefined): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(env ?? {})) {\n out[k] = v.replace(/\\$\\{env:([A-Za-z_][A-Za-z0-9_]*)\\}/g, (_m, name) => process.env[name] ?? \"\");\n }\n return out;\n}\n\n/**\n * Spawn the stdio MCP server `command args` and run a real lifecycle probe.\n * Always resolves (never rejects) with one DiagnosticResult per step.\n */\nexport async function probeStdioServer(\n command: string,\n args: string[],\n opts: ProbeOptions = {},\n): Promise<DiagnosticResult[]> {\n const label = opts.label ? `${opts.label}: ` : \"\";\n const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const protocolVersion = opts.protocolVersion ?? MCP_PROTOCOL_VERSION;\n const results: DiagnosticResult[] = [];\n\n // spawnChild resolves a bare Windows package runner (npx/uvx → .cmd/.exe) so\n // the probe agrees with the live serve path; no-op on macOS/Linux.\n const child = spawnChild(command, args, {\n stdio: [\"pipe\", \"pipe\", \"inherit\"],\n env: { ...process.env, ...resolveEnv(opts.env) },\n });\n\n interface Pending {\n resolve: (m: JsonRpcMessage) => void;\n reject: (e: Error) => void;\n }\n const pending = new Map<string, Pending>();\n let spawnErr: Error | null = null;\n let exitCode: number | null = null;\n\n const rejectAll = (e: Error): void => {\n for (const p of pending.values()) p.reject(e);\n pending.clear();\n };\n child.on(\"error\", (e) => {\n spawnErr = e;\n rejectAll(e);\n });\n child.on(\"exit\", (code) => {\n exitCode = code ?? 0;\n rejectAll(new Error(`server exited (code ${exitCode}) before responding`));\n });\n\n const lines = new LineBuffer((line) => {\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n return; // non-JSON stdout noise — ignore\n }\n if (!isObject(parsed)) return;\n const k = idKey((parsed as JsonRpcMessage).id);\n if (k && pending.has(k)) {\n const p = pending.get(k)!;\n pending.delete(k);\n p.resolve(parsed as JsonRpcMessage);\n }\n });\n child.stdout?.on(\"data\", (c: Buffer) => lines.push(c));\n\n const send = (m: JsonRpcMessage): void => {\n if (child.stdin && child.stdin.writable) child.stdin.write(`${JSON.stringify(m)}\\n`);\n };\n const request = (id: number | string, method: string, params?: unknown): Promise<JsonRpcMessage> => {\n const key = idKey(id)!;\n return new Promise<JsonRpcMessage>((resolve, reject) => {\n const timer = setTimeout(() => {\n pending.delete(key);\n reject(new Error(`no response within ${timeoutMs}ms`));\n }, timeoutMs);\n if (typeof timer.unref === \"function\") timer.unref();\n pending.set(key, {\n resolve: (m) => {\n clearTimeout(timer);\n resolve(m);\n },\n reject: (e) => {\n clearTimeout(timer);\n reject(e);\n },\n });\n send({ jsonrpc: \"2.0\", id, method, ...(params !== undefined ? { params } : {}) });\n });\n };\n\n const cleanup = (): DiagnosticResult[] => {\n try {\n if (child.stdin && child.stdin.writable) child.stdin.end();\n } catch {\n /* ignore */\n }\n try {\n child.kill(\"SIGTERM\");\n } catch {\n /* ignore */\n }\n const killTimer = setTimeout(() => {\n try {\n child.kill(\"SIGKILL\");\n } catch {\n /* ignore */\n }\n }, 500);\n if (typeof killTimer.unref === \"function\") killTimer.unref();\n return results;\n };\n\n // 1. initialize\n let initResult: Record<string, unknown>;\n try {\n const res = await request(1, \"initialize\", {\n protocolVersion,\n capabilities: {},\n clientInfo: { name: \"agent-connector-probe\", version: \"1\" },\n });\n if (isObject(res.error)) {\n results.push(\n diag(\"fail\", `${label}MCP initialize`, `server returned error: ${JSON.stringify(res.error)}`),\n );\n return cleanup();\n }\n initResult = isObject(res.result) ? res.result : {};\n } catch (e) {\n if (spawnErr) {\n results.push(\n diag(\n \"fail\",\n `${label}MCP initialize`,\n `server not launchable: ${errMsg(spawnErr)}`,\n `check that \"${command}\" is installed and on PATH`,\n ),\n );\n } else if (exitCode !== null) {\n // On Windows an unresolvable command surfaces as an early non-zero exit\n // (cmd.exe \"command not found\") rather than a spawn 'error' event, so fold\n // the not-launchable hint in here too — useful whether the command is\n // missing or the server genuinely crashed before initialize.\n results.push(\n diag(\n \"fail\",\n `${label}MCP initialize`,\n `server not launchable, or it exited (code ${exitCode}) before initialize`,\n `check that \"${command}\" is installed and on PATH`,\n ),\n );\n } else {\n results.push(diag(\"fail\", `${label}MCP initialize`, errMsg(e)));\n }\n return cleanup();\n }\n\n const serverInfo = isObject(initResult.serverInfo) ? initResult.serverInfo : {};\n const sName = typeof serverInfo.name === \"string\" ? serverInfo.name : \"unknown\";\n const sVer = typeof serverInfo.version === \"string\" ? serverInfo.version : \"?\";\n const negotiated =\n typeof initResult.protocolVersion === \"string\" ? initResult.protocolVersion : \"(none)\";\n results.push(diag(\"pass\", `${label}MCP initialize`, `serverInfo ${sName}@${sVer}, protocol ${negotiated}`));\n\n // capabilities (presence = feature offered)\n const caps = isObject(initResult.capabilities) ? initResult.capabilities : {};\n const capNames = [\"tools\", \"resources\", \"prompts\", \"logging\", \"completions\"].filter((c) => c in caps);\n results.push(\n diag(\"pass\", `${label}capabilities`, capNames.length > 0 ? capNames.join(\", \") : \"(none advertised)\"),\n );\n\n // 2. initialized notification (required before normal requests)\n send({ jsonrpc: \"2.0\", method: \"notifications/initialized\" });\n\n // 3. ping — liveness confirm (warn, not fail, on timeout)\n try {\n await request(\"probe-ping\", \"ping\");\n results.push(diag(\"pass\", `${label}ping`, \"alive\"));\n } catch (e) {\n results.push(diag(\"warn\", `${label}ping`, `no ping response (${errMsg(e)})`));\n }\n\n // 4. tools/list — only if the server advertised a tools capability\n if (\"tools\" in caps) {\n try {\n const res = await request(2, \"tools/list\", {});\n const r = isObject(res.result) ? res.result : {};\n const tools = Array.isArray(r.tools) ? r.tools : [];\n results.push(diag(\"pass\", `${label}tools/list`, `${tools.length} tool(s)`));\n } catch (e) {\n results.push(diag(\"fail\", `${label}tools/list`, `no tools/list response (${errMsg(e)})`));\n }\n } else {\n results.push(\n diag(\"warn\", `${label}tools/list`, \"skipped — server advertised no tools capability\"),\n );\n }\n\n return cleanup();\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/adapters/droid/index.ts"],"sourcesContent":["/**\n * adapters/droid — Droid (Factory AI) platform adapter for agent-connector.\n *\n * Droid is a **json-stdio** host with TWO native config surfaces that live in\n * DIFFERENT files (so getServerConfigPath ≠ getHookConfigPath):\n *\n * 1. MCP servers — `mcp.json` (root key `mcpServers`):\n * - user scope → ~/.factory/mcp.json\n * - project scope → <projectDir>/.factory/mcp.json\n * Native stdio entry shape: { type:\"stdio\", command, args, env, disabled };\n * a remote server registers a URL ({ type:\"http\", url, headers, disabled }).\n *\n * 2. Hooks — a SEPARATE `hooks.json` (root key `hooks`) under the same\n * `.factory` dir. Droid ships a FULL Claude-compatible lifecycle hook\n * system (live-confirmed): PascalCase event names, Claude snake_case stdin\n * wire fields, and a Claude-shaped `hookSpecificOutput` reply. Hook\n * registrations use the Claude NESTED-rule shape:\n * { hooks: { <Event>: [ { matcher?, hooks:[{ type:\"command\", command }] } ] } }\n *\n * Supported events (Claude-compatible): PreToolUse, PostToolUse,\n * UserPromptSubmit, Stop, SubagentStop (stop-only — no SubagentStart). Droid\n * exposes no PreCompact / SessionStart / SessionEnd / Notification /\n * PermissionRequest / PostToolUseFailure / SubagentStart, so those degrade to\n * a warn/skip at install time.\n *\n * Reply protocol is Claude-shaped JSON on stdout (exit 0 + `hookSpecificOutput`\n * with permissionDecision allow|deny|ask, plus additionalContext). Droid cannot\n * rewrite already-emitted tool output, so canModifyOutput is false; it CAN\n * inject session context (additionalContext) so canInjectSessionContext is true.\n *\n * Env handling: env/header/url refs are resolved to literals at install time via\n * resolveEnvRefsDeep — the safe default matching the Kiro/Qwen adapters. Droid\n * also accepts native ${VAR}, but resolve-to-literal avoids surprises.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport type { Adapter, HookReply, InstallContext, NormalizedEvent } from \"../spi.js\";\nimport type {\n ChangeRecord,\n DetectedPlatform,\n HealthCheck,\n HookEventName,\n HookParadigm,\n HookResponse,\n PlatformCapabilities,\n PlatformId,\n PostToolUseEvent,\n PreToolUseEvent,\n ServerDef,\n StopEvent,\n SubagentStopEvent,\n Transport,\n UserPromptSubmitEvent,\n} from \"../../core/types.js\";\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\nimport {\n buildHomeBinHookCommand,\n buildServeWrapperCommand,\n isHomeBinHookCommand,\n shouldWrapForTelemetry,\n} from \"../../core/spawn.js\";\n\nconst HOST: PlatformId = \"droid\";\nconst MCP_ROOT_KEY = \"mcpServers\";\n\n/**\n * Canonical events Droid actually fires. Droid's hook event names are\n * Claude-identical (PascalCase), so the canonical name is registered directly.\n * PreCompact / SessionStart / SessionEnd / Notification have no Droid equivalent\n * and are reported as a warn/skip at install time.\n *\n * Droid is a STOP-ONLY subagent host: its live hooks-reference lists\n * SubagentStop but NO SubagentStart, and it has no permission-dialog\n * (PermissionRequest) or tool-failure (PostToolUseFailure) events — those\n * three warn/skip as well.\n */\nconst SUPPORTED_EVENTS: ReadonlySet<HookEventName> = new Set<HookEventName>([\n \"PreToolUse\",\n \"PostToolUse\",\n \"UserPromptSubmit\",\n \"Stop\",\n \"SubagentStop\",\n]);\n\n/**\n * Native MCP server entry shapes Droid accepts under `mcpServers`.\n * A stdio entry carries an explicit `type: \"stdio\"` discriminator and a\n * `disabled` flag; remote transports register a URL.\n */\ninterface DroidStdioServer {\n type: \"stdio\";\n command: string;\n args?: string[];\n env?: Record<string, string>;\n disabled: boolean;\n}\ninterface DroidHttpServer {\n type: \"http\";\n url: string;\n headers?: Record<string, string>;\n disabled: boolean;\n}\n\n/** A single Droid native hook registration entry (Claude-shaped, nested). */\ninterface DroidHookEntry {\n matcher: string;\n hooks: Array<{ type: \"command\"; command: string }>;\n}\n\n/** The shape of Droid's hooks.json (only the parts we touch). */\ninterface DroidHooksFile {\n hooks?: Record<string, DroidHookEntry[]>;\n [key: string]: unknown;\n}\n\n/** Raw Droid CLI hook stdin payload (Claude-compatible snake_case wire fields). */\ninterface DroidWireInput {\n session_id?: string;\n transcript_path?: string;\n cwd?: string;\n hook_event_name?: string;\n tool_name?: string;\n tool_input?: Record<string, unknown>;\n tool_response?: unknown;\n prompt?: string;\n /** Stop / SubagentStop loop guard. */\n stop_hook_active?: boolean;\n // SubagentStop — Claude-compatible snake_case fields. agent_type is\n // unreliable on SubagentStop across hosts; treat both as optional.\n agent_id?: string;\n agent_type?: string;\n agent_transcript_path?: string;\n last_assistant_message?: string;\n /** Injected by the entrypoint so the runtime knows which connector to dispatch. */\n connector?: unknown;\n}\n\nexport class DroidAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"Droid (Factory)\";\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 preToolUse: true,\n postToolUse: true,\n preCompact: false,\n sessionStart: false,\n sessionEnd: false,\n userPromptSubmit: true,\n stop: true,\n notification: false,\n // Newer events: Droid ships SubagentStop (stop-only — no SubagentStart).\n // permissionRequest / postToolUseFailure / subagentStart stay unset (no\n // Droid analog); install reports the standard skip-warn for them.\n subagentStop: true,\n // Droid's PreToolUse can deny/ask (Claude-shaped), but it cannot rewrite\n // already-emitted tool output. canModifyArgs left false until confirmed.\n canModifyArgs: false,\n canModifyOutput: false,\n // Droid honors additionalContext on the stdout reply.\n canInjectSessionContext: true,\n // Droid registers stdio and Streamable HTTP MCP servers.\n transports: [\"stdio\", \"http\"],\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userDir = join(homedir(), \".factory\");\n const userMcp = join(userDir, \"mcp.json\");\n const projDir = join(projectDir, \".factory\");\n const projMcp = join(projDir, \"mcp.json\");\n\n const userInstalled = existsSync(userDir) || existsSync(userMcp);\n const projInstalled = existsSync(projDir) || existsSync(projMcp);\n const installed = userInstalled || projInstalled;\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\n const configPath = scope === \"project\" ? projMcp : userMcp;\n\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath,\n scope,\n reason: installed\n ? `found Droid config (${scope}) at ${configPath}`\n : `no .factory config at ${userDir} or ${projDir}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n getConfigDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".factory\")\n : join(homedir(), \".factory\");\n }\n\n getServerConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"mcp.json\");\n }\n\n /** Hooks live in a SEPARATE hooks.json under the same `.factory` dir. */\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 droid\"\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 Droid's native mcpServers entry. */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): DroidStdioServer | DroidHttpServer {\n const transport: Transport = server.transport;\n const disabled = server.enabled === false;\n\n if (transport === \"stdio\") {\n let command = server.command ?? \"\";\n let args = [...(server.args ?? [])];\n\n // Transparent telemetry wrapping: route the real command through\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\n if (shouldWrapForTelemetry(server, ctx.connector.telemetry)) {\n const wrapped = buildServeWrapperCommand(\n ctx.homeBinPath,\n ctx.connector.id,\n command,\n args,\n ctx.scope,\n this.id,\n );\n command = wrapped.command;\n args = wrapped.args;\n }\n\n // Resolve every ${env:VAR} to a literal at install time (safe path).\n const entry: DroidStdioServer = {\n type: \"stdio\",\n command: resolveEnvRefsDeep(command),\n disabled,\n };\n if (args.length > 0) entry.args = resolveEnvRefsDeep(args);\n const env = this.renderEnv(server.env);\n if (env) entry.env = env;\n return entry;\n }\n\n // http (and any other remote transport) — Droid registers a URL.\n const entry: DroidHttpServer = {\n type: \"http\",\n url: resolveEnvRefsDeep(server.url ?? \"\"),\n disabled,\n };\n const headers = this.renderEnv(server.headers);\n if (headers) entry.headers = headers;\n return entry;\n }\n\n /**\n * Render env/header values. Resolve `${env:VAR}` references to literals at\n * install time (the safe path; Droid would also accept native ${VAR}).\n */\n private renderEnv(\n env: Record<string, string> | undefined,\n ): Record<string, string> | undefined {\n if (!env || Object.keys(env).length === 0) return undefined;\n return resolveEnvRefsDeep({ ...env });\n }\n\n // ── Hook install / uninstall (separate hooks.json, nested-rule shape) ─────\n\n installHooks(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.hooks === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"hooks disabled for droid\" }];\n }\n if (connector.hookEvents.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no hooks\" }];\n }\n\n const hookPath = this.getHookConfigPath(ctx);\n // Merge into any existing hooks.json so the user's own hooks survive.\n const file = this.readJson<DroidHooksFile>(hookPath) ?? {};\n const hooks = (file.hooks ??= {});\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const event of connector.hookEvents) {\n if (!SUPPORTED_EVENTS.has(event)) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: hookPath,\n detail: `${event} has no Droid hook equivalent — skipped`,\n });\n continue;\n }\n\n // Droid's event names are Claude-identical (PascalCase) — register the\n // canonical event name directly.\n const command = buildHomeBinHookCommand(ctx.homeBinPath, HOST, event, connector.id);\n const matcher = connector.hooks[event]?.matcher ?? \"\";\n const entry: DroidHookEntry = {\n matcher,\n hooks: [{ type: \"command\", command }],\n };\n\n const bucket = (hooks[event] ??= []);\n const existingIdx = bucket.findIndex((e) => this.entryHasOurCommand(e, ctx));\n\n if (existingIdx >= 0) {\n if (JSON.stringify(bucket[existingIdx]) === JSON.stringify(entry)) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: hookPath,\n detail: `hooks.${event} already registered`,\n });\n continue;\n }\n bucket[existingIdx] = entry;\n changes.push({\n platform: this.id,\n action: \"update\",\n path: hookPath,\n detail: `hooks.${event}`,\n });\n } else {\n bucket.push(entry);\n changes.push({\n platform: this.id,\n action: \"create\",\n path: hookPath,\n detail: `hooks.${event}`,\n });\n }\n mutated = true;\n }\n\n if (mutated) this.writeJson(hookPath, file, ctx.dryRun);\n return changes;\n }\n\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n const hookPath = this.getHookConfigPath(ctx);\n const file = this.readJson<DroidHooksFile>(hookPath);\n const hooks = file?.hooks;\n if (!file || !hooks) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: hookPath,\n detail: \"no hooks section present\",\n },\n ];\n }\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const event of Object.keys(hooks)) {\n const bucket = hooks[event];\n if (!Array.isArray(bucket)) continue;\n\n // Strip our hook command from each entry; drop entries left empty so we\n // never remove another connector's (or the user's own) hook commands. The\n // id token is anchored (isHomeBinHookCommand) so a shared-prefix connector\n // id is never affected.\n const next: DroidHookEntry[] = [];\n let removed = 0;\n for (const e of bucket) {\n const innerBefore = e.hooks?.length ?? 0;\n const inner = (e.hooks ?? []).filter((h) => !this.isOurCommand(h.command, ctx));\n removed += innerBefore - inner.length;\n if (inner.length > 0) next.push({ matcher: e.matcher ?? \"\", hooks: inner });\n }\n\n if (removed > 0) {\n if (next.length > 0) hooks[event] = next;\n else delete hooks[event];\n changes.push({\n platform: this.id,\n action: \"remove\",\n path: hookPath,\n detail: `hooks.${event} (${removed})`,\n });\n mutated = true;\n }\n }\n\n if (mutated) this.writeJson(hookPath, file, ctx.dryRun);\n if (changes.length === 0) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: hookPath,\n detail: \"no matching hook entries\",\n });\n }\n return changes;\n }\n\n private entryHasOurCommand(entry: DroidHookEntry, ctx: InstallContext): boolean {\n return (entry.hooks ?? []).some((h) => this.isOurCommand(h.command, ctx));\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 mcpPath = this.getServerConfigPath(ctx);\n const hookPath = this.getHookConfigPath(ctx);\n const connectorId = ctx.connector.id;\n const homeBin = ctx.homeBinPath;\n const hookEvents = ctx.connector.hookEvents;\n return [\n {\n name: `${this.name}: mcp.json present`,\n check: () =>\n existsSync(mcpPath)\n ? { status: \"OK\", detail: mcpPath }\n : { status: \"FAIL\", detail: `not found: ${mcpPath}` },\n },\n {\n name: `${this.name}: server entry registered`,\n check: () => {\n if (!ctx.connector.server) {\n return { status: \"OK\", detail: \"no MCP server declared\" };\n }\n const cfg = this.readJson<{ [k: string]: Record<string, unknown> }>(mcpPath);\n const bucket = cfg?.[MCP_ROOT_KEY];\n if (!cfg || !bucket) {\n return { status: \"FAIL\", detail: `no ${MCP_ROOT_KEY} in ${mcpPath}` };\n }\n return connectorId in bucket\n ? { status: \"OK\", detail: `${MCP_ROOT_KEY}.${connectorId} present` }\n : {\n status: \"FAIL\",\n detail: `no ${MCP_ROOT_KEY}.${connectorId} in ${mcpPath}`,\n };\n },\n },\n {\n name: `${this.name}: hook command registered`,\n check: () => {\n if (hookEvents.length === 0) {\n return { status: \"OK\", detail: \"no hooks declared\" };\n }\n const file = this.readJson<DroidHooksFile>(hookPath);\n if (!file) return { status: \"FAIL\", detail: `cannot read ${hookPath}` };\n const hooks = file.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 : { status: \"FAIL\", detail: `no hook for ${connectorId} in ${hookPath}` };\n },\n },\n ];\n }\n\n // ── Runtime: parse Droid stdin JSON → normalized event ────────────────────\n\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\n const input = (raw ?? {}) as DroidWireInput;\n const connectorId = typeof input.connector === \"string\" ? input.connector : \"\";\n const sessionId = typeof input.session_id === \"string\" ? input.session_id : \"\";\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 \"UserPromptSubmit\": {\n const ev: UserPromptSubmitEvent = {\n ...base,\n prompt: typeof input.prompt === \"string\" ? input.prompt : \"\",\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 \"SubagentStop\": {\n // agent_id/agent_type stay optional — hosts do not reliably populate\n // agent_type on SubagentStop (Claude-compatible quirk).\n const ev: SubagentStopEvent = {\n ...base,\n ...(typeof input.agent_id === \"string\" ? { agentId: input.agent_id } : {}),\n ...(typeof input.agent_type === \"string\"\n ? { agentType: input.agent_type }\n : {}),\n ...(typeof input.agent_transcript_path === \"string\"\n ? { agentTranscriptPath: input.agent_transcript_path }\n : {}),\n ...(typeof input.last_assistant_message === \"string\"\n ? { lastAssistantMessage: input.last_assistant_message }\n : {}),\n ...(typeof input.stop_hook_active === \"boolean\"\n ? { stopHookActive: input.stop_hook_active }\n : {}),\n };\n return ev;\n }\n default: {\n // Droid never delivers PreCompact / SessionStart / SessionEnd /\n // Notification / PermissionRequest / PostToolUseFailure / SubagentStart\n // (no native equivalent). If the runtime dispatches one anyway, surface\n // it loudly rather than silently mis-parse.\n throw new Error(`unsupported droid hook event: ${String(event)}`);\n }\n }\n }\n\n // ── Runtime: normalized response → Droid native (Claude-shaped) hook reply ─\n\n formatReply(event: HookEventName, response: HookResponse): HookReply {\n const hookEventName = event;\n const decision = response.decision ?? \"allow\";\n\n // deny → block the action with a reason (exit 0; JSON carries the decision).\n if (decision === \"deny\") {\n // SubagentStop deny carries Stop semantics — it keeps the subagent\n // running with `reason` as its next instruction — and (Claude-compatible)\n // is honored only as the TOP-LEVEL {\"decision\":\"block\",\"reason\"}, not as\n // a permissionDecision envelope.\n if (event === \"SubagentStop\") {\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: response.reason ?? \"Confirmation required by hook\",\n },\n });\n }\n\n // context → inject soft guidance (Droid honors additionalContext).\n if (decision === \"context\" && response.additionalContext) {\n return this.stdout({\n hookSpecificOutput: { hookEventName, additionalContext: response.additionalContext },\n });\n }\n\n // allow / modify (unsupported — exit-code/decision protocol only) / void →\n // 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/** Coerce a Droid PostToolUse `tool_response` into a string for the normalized event. */\nfunction toolResponseToString(value: unknown): string | undefined {\n if (value == null) return undefined;\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nexport const adapter = new DroidAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}