@ken-jo/agent-connector 0.4.75 → 0.4.91

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 (192) hide show
  1. package/README.md +3 -3
  2. package/dist/{action-TCKBTTZX.js → action-L44DXFHT.js} +14 -14
  3. package/dist/{amazon-q-CB4XFX7T.js → amazon-q-B52EY2SV.js} +5 -5
  4. package/dist/{amp-6Q5OYHNW.js → amp-UXABVUKC.js} +5 -5
  5. package/dist/{antigravity-WIK3XBN5.js → antigravity-RZHN53VB.js} +6 -6
  6. package/dist/antigravity-cli-JO6GUTV7.js +436 -0
  7. package/dist/antigravity-cli-JO6GUTV7.js.map +1 -0
  8. package/dist/{chunk-Q5LECKZL.js → chunk-25CPWJA7.js} +116 -36
  9. package/dist/chunk-25CPWJA7.js.map +1 -0
  10. package/dist/{chunk-D6ZJS4ND.js → chunk-4FWETID5.js} +2 -2
  11. package/dist/{chunk-Q42SEI7W.js → chunk-4HVQ7IUM.js} +3 -3
  12. package/dist/{chunk-IU42THN7.js → chunk-4NSU3KWX.js} +2 -2
  13. package/dist/{chunk-7CZKXXBD.js → chunk-56R2ER7K.js} +2 -2
  14. package/dist/{chunk-HKM3HUOK.js → chunk-7HUUINPB.js} +18 -18
  15. package/dist/{chunk-TZ5KGCE2.js → chunk-AY3RGRTT.js} +2 -2
  16. package/dist/{chunk-MHDQWZ4A.js → chunk-BLTVZACS.js} +23 -13
  17. package/dist/chunk-BLTVZACS.js.map +1 -0
  18. package/dist/{chunk-7ITLLYWB.js → chunk-G4CEELKO.js} +5 -5
  19. package/dist/{chunk-TO57WYBB.js → chunk-HORHRHNG.js} +9 -3
  20. package/dist/chunk-HORHRHNG.js.map +1 -0
  21. package/dist/{chunk-2HCJV6UO.js → chunk-IXOQDZWC.js} +9 -2
  22. package/dist/chunk-IXOQDZWC.js.map +1 -0
  23. package/dist/{chunk-2L6LTQ6L.js → chunk-KIRCPLM4.js} +21 -10
  24. package/dist/chunk-KIRCPLM4.js.map +1 -0
  25. package/dist/{chunk-24K6JOKV.js → chunk-LAIITCMW.js} +8 -8
  26. package/dist/{chunk-OEQJGBBW.js → chunk-LF76VPGQ.js} +9 -9
  27. package/dist/{chunk-7QRUZAUG.js → chunk-LN76OGNR.js} +2 -2
  28. package/dist/{chunk-DI6OWKH2.js → chunk-NBUEL74R.js} +3 -3
  29. package/dist/{chunk-IRUYJD23.js → chunk-NLE2J5P4.js} +1 -1
  30. package/dist/{chunk-5LAFKXFM.js → chunk-NWLRJNXM.js} +3 -3
  31. package/dist/{chunk-ECSRTK4M.js → chunk-QARPXSIV.js} +4 -4
  32. package/dist/{chunk-AXAHW2KU.js → chunk-QKLJU4JX.js} +2 -2
  33. package/dist/{chunk-MDZG5QHB.js → chunk-R6LML2YS.js} +2 -2
  34. package/dist/{chunk-FUXUEXDP.js → chunk-UBB7T54N.js} +3 -3
  35. package/dist/{chunk-NUGMVVV2.js → chunk-VVFDU4IX.js} +4 -4
  36. package/dist/{chunk-ALVXORZM.js → chunk-YYNXIUR2.js} +2 -2
  37. package/dist/{chunk-TW4DVR4V.js → chunk-ZMLVR4J7.js} +7 -2
  38. package/dist/chunk-ZMLVR4J7.js.map +1 -0
  39. package/dist/{claude-code-HFBAAVWS.js → claude-code-WS4NAGZT.js} +9 -9
  40. package/dist/cli/sdk.js +7 -7
  41. package/dist/cli.js +1 -1
  42. package/dist/{cline-26W4FEZ6.js → cline-NNMVCECA.js} +5 -5
  43. package/dist/codebuddy-RBEZGXBG.js +643 -0
  44. package/dist/codebuddy-RBEZGXBG.js.map +1 -0
  45. package/dist/{codebuff-J5KEEBIL.js → codebuff-RJIDSEU3.js} +5 -5
  46. package/dist/{codex-JKQ6TLRI.js → codex-ZZ434GYR.js} +8 -8
  47. package/dist/{continue-KQSJUSWX.js → continue-MNM7YVJY.js} +6 -6
  48. package/dist/{copilot-cli-YBNKLYUB.js → copilot-cli-SMTX5F65.js} +5 -5
  49. package/dist/{crush-JTWTZIPB.js → crush-NYDBHIJE.js} +5 -5
  50. package/dist/{cursor-2NIZSDZ4.js → cursor-AOELDNZU.js} +6 -6
  51. package/dist/{detect-CWEIQCRC.js → detect-3S46RUMK.js} +4 -4
  52. package/dist/devin-PRJY2TTD.js +510 -0
  53. package/dist/devin-PRJY2TTD.js.map +1 -0
  54. package/dist/{doctor-AC437ZAW.js → doctor-3CUBPQKU.js} +22 -22
  55. package/dist/{droid-HF2AIFB2.js → droid-PTCH2K7Y.js} +5 -5
  56. package/dist/{gemini-cli-2EOK26S2.js → gemini-cli-QGLN2UMS.js} +5 -5
  57. package/dist/{goose-55JOTXS5.js → goose-DQ6GSZ5O.js} +6 -6
  58. package/dist/grok-cli-5QD235UB.js +482 -0
  59. package/dist/grok-cli-5QD235UB.js.map +1 -0
  60. package/dist/{hermes-QVZOZU4B.js → hermes-E47IG63A.js} +6 -6
  61. package/dist/{hook-VYD3OCLM.js → hook-P6EKDINW.js} +14 -14
  62. package/dist/index.d.ts +2 -2
  63. package/dist/index.js +5 -5
  64. package/dist/{install-S6BYIJ62.js → install-7DMK53SB.js} +18 -18
  65. package/dist/{introspect-5o5ick0_.d.ts → introspect-DYOIX8Ov.d.ts} +1 -1
  66. package/dist/{jetbrains-copilot-DZ2ATXFN.js → jetbrains-copilot-T2EPKROP.js} +13 -7
  67. package/dist/jetbrains-copilot-T2EPKROP.js.map +1 -0
  68. package/dist/junie-SQ4SDLGK.js +227 -0
  69. package/dist/junie-SQ4SDLGK.js.map +1 -0
  70. package/dist/{kilo-GJNSBWVV.js → kilo-OU2ZLZKB.js} +8 -8
  71. package/dist/{kilo-cli-2CCB3DBI.js → kilo-cli-NMWGYF4F.js} +8 -8
  72. package/dist/{kimi-YRPCSB6N.js → kimi-Z7L2LEEI.js} +5 -5
  73. package/dist/{kiro-BUOQFASX.js → kiro-4IN5IH46.js} +81 -6
  74. package/dist/kiro-4IN5IH46.js.map +1 -0
  75. package/dist/{leaderboard-SUSUDKHR.js → leaderboard-LF5SP6X2.js} +7 -7
  76. package/dist/{mimo-code-V4FP5PUJ.js → mimo-code-G2CBZ4M6.js} +5 -5
  77. package/dist/mistral-vibe-TRQDHAWV.js +300 -0
  78. package/dist/mistral-vibe-TRQDHAWV.js.map +1 -0
  79. package/dist/{mux-CMJSM42O.js → mux-JNM3F2NW.js} +5 -5
  80. package/dist/{nemoclaw-VP56PGKC.js → nemoclaw-SHA4IUML.js} +6 -6
  81. package/dist/{omp-OOFGD3GG.js → omp-OOVUNXME.js} +5 -5
  82. package/dist/open-interpreter-4PKL56AA.js +264 -0
  83. package/dist/open-interpreter-4PKL56AA.js.map +1 -0
  84. package/dist/openclaw-BD56E5MV.js +17 -0
  85. package/dist/{opencode-MKLHSQRD.js → opencode-W2RK4M7G.js} +5 -5
  86. package/dist/openhands-5LNH3BKB.js +384 -0
  87. package/dist/openhands-5LNH3BKB.js.map +1 -0
  88. package/dist/{package-KOAAVKHH.js → package-2EAIYSJ4.js} +13 -13
  89. package/dist/{pi-NMVL7OFL.js → pi-BUADR5MJ.js} +143 -6
  90. package/dist/pi-BUADR5MJ.js.map +1 -0
  91. package/dist/{qwen-code-2XE2T6F4.js → qwen-code-TUJNHKNI.js} +9 -9
  92. package/dist/{roo-code-YJOIKCCS.js → roo-code-L5F7S6QH.js} +5 -5
  93. package/dist/runtime/index.d.ts +12 -1
  94. package/dist/runtime/index.js +12 -12
  95. package/dist/sdk/index.d.ts +3 -3
  96. package/dist/sdk/index.js +6 -6
  97. package/dist/sdk/test.d.ts +2 -2
  98. package/dist/sdk/test.js +10 -10
  99. package/dist/{serve-BU23QUSJ.js → serve-K62FW3V7.js} +24 -17
  100. package/dist/serve-K62FW3V7.js.map +1 -0
  101. package/dist/{status-N5LCQQ3R.js → status-E5MCFZM6.js} +11 -11
  102. package/dist/{statusline-442XOF7R.js → statusline-LIPF2KVP.js} +13 -13
  103. package/dist/{telemetry-V4YQL2NU.js → telemetry-4OC56NTM.js} +10 -10
  104. package/dist/{trae-QSV2JZFT.js → trae-Z7CQ2A2Q.js} +5 -5
  105. package/dist/{types-D6RWGXm1.d.ts → types-C4qMgbJn.d.ts} +10 -9
  106. package/dist/{uninstall-WGEKTCDZ.js → uninstall-2YYKN5DX.js} +18 -18
  107. package/dist/{upgrade-IH7CKPTO.js → upgrade-55AFPJEF.js} +18 -18
  108. package/dist/{usage-DI7XRCKM.js → usage-3PB3WZSL.js} +3 -3
  109. package/dist/{usage-event-2FCU55AN.js → usage-event-KD5FW6W4.js} +13 -13
  110. package/dist/{vscode-copilot-R23RTVST.js → vscode-copilot-LU5NC4ZS.js} +5 -5
  111. package/dist/{warp-B72XSQ5G.js → warp-4PPG5LOM.js} +5 -5
  112. package/dist/{windsurf-642VBMQ2.js → windsurf-3T3RVXKM.js} +5 -5
  113. package/dist/{zed-6UJS7JKB.js → zed-ZF2OQ75O.js} +123 -7
  114. package/dist/zed-ZF2OQ75O.js.map +1 -0
  115. package/package.json +1 -1
  116. package/dist/antigravity-cli-L3RZMF6V.js +0 -87
  117. package/dist/antigravity-cli-L3RZMF6V.js.map +0 -1
  118. package/dist/chunk-2HCJV6UO.js.map +0 -1
  119. package/dist/chunk-2L6LTQ6L.js.map +0 -1
  120. package/dist/chunk-MHDQWZ4A.js.map +0 -1
  121. package/dist/chunk-Q5LECKZL.js.map +0 -1
  122. package/dist/chunk-TO57WYBB.js.map +0 -1
  123. package/dist/chunk-TW4DVR4V.js.map +0 -1
  124. package/dist/jetbrains-copilot-DZ2ATXFN.js.map +0 -1
  125. package/dist/kiro-BUOQFASX.js.map +0 -1
  126. package/dist/openclaw-V73XHPXP.js +0 -17
  127. package/dist/pi-NMVL7OFL.js.map +0 -1
  128. package/dist/serve-BU23QUSJ.js.map +0 -1
  129. package/dist/zed-6UJS7JKB.js.map +0 -1
  130. /package/dist/{action-TCKBTTZX.js.map → action-L44DXFHT.js.map} +0 -0
  131. /package/dist/{amazon-q-CB4XFX7T.js.map → amazon-q-B52EY2SV.js.map} +0 -0
  132. /package/dist/{amp-6Q5OYHNW.js.map → amp-UXABVUKC.js.map} +0 -0
  133. /package/dist/{antigravity-WIK3XBN5.js.map → antigravity-RZHN53VB.js.map} +0 -0
  134. /package/dist/{chunk-D6ZJS4ND.js.map → chunk-4FWETID5.js.map} +0 -0
  135. /package/dist/{chunk-Q42SEI7W.js.map → chunk-4HVQ7IUM.js.map} +0 -0
  136. /package/dist/{chunk-IU42THN7.js.map → chunk-4NSU3KWX.js.map} +0 -0
  137. /package/dist/{chunk-7CZKXXBD.js.map → chunk-56R2ER7K.js.map} +0 -0
  138. /package/dist/{chunk-HKM3HUOK.js.map → chunk-7HUUINPB.js.map} +0 -0
  139. /package/dist/{chunk-TZ5KGCE2.js.map → chunk-AY3RGRTT.js.map} +0 -0
  140. /package/dist/{chunk-7ITLLYWB.js.map → chunk-G4CEELKO.js.map} +0 -0
  141. /package/dist/{chunk-24K6JOKV.js.map → chunk-LAIITCMW.js.map} +0 -0
  142. /package/dist/{chunk-OEQJGBBW.js.map → chunk-LF76VPGQ.js.map} +0 -0
  143. /package/dist/{chunk-7QRUZAUG.js.map → chunk-LN76OGNR.js.map} +0 -0
  144. /package/dist/{chunk-DI6OWKH2.js.map → chunk-NBUEL74R.js.map} +0 -0
  145. /package/dist/{chunk-IRUYJD23.js.map → chunk-NLE2J5P4.js.map} +0 -0
  146. /package/dist/{chunk-5LAFKXFM.js.map → chunk-NWLRJNXM.js.map} +0 -0
  147. /package/dist/{chunk-ECSRTK4M.js.map → chunk-QARPXSIV.js.map} +0 -0
  148. /package/dist/{chunk-AXAHW2KU.js.map → chunk-QKLJU4JX.js.map} +0 -0
  149. /package/dist/{chunk-MDZG5QHB.js.map → chunk-R6LML2YS.js.map} +0 -0
  150. /package/dist/{chunk-FUXUEXDP.js.map → chunk-UBB7T54N.js.map} +0 -0
  151. /package/dist/{chunk-NUGMVVV2.js.map → chunk-VVFDU4IX.js.map} +0 -0
  152. /package/dist/{chunk-ALVXORZM.js.map → chunk-YYNXIUR2.js.map} +0 -0
  153. /package/dist/{claude-code-HFBAAVWS.js.map → claude-code-WS4NAGZT.js.map} +0 -0
  154. /package/dist/{cline-26W4FEZ6.js.map → cline-NNMVCECA.js.map} +0 -0
  155. /package/dist/{codebuff-J5KEEBIL.js.map → codebuff-RJIDSEU3.js.map} +0 -0
  156. /package/dist/{codex-JKQ6TLRI.js.map → codex-ZZ434GYR.js.map} +0 -0
  157. /package/dist/{continue-KQSJUSWX.js.map → continue-MNM7YVJY.js.map} +0 -0
  158. /package/dist/{copilot-cli-YBNKLYUB.js.map → copilot-cli-SMTX5F65.js.map} +0 -0
  159. /package/dist/{crush-JTWTZIPB.js.map → crush-NYDBHIJE.js.map} +0 -0
  160. /package/dist/{cursor-2NIZSDZ4.js.map → cursor-AOELDNZU.js.map} +0 -0
  161. /package/dist/{detect-CWEIQCRC.js.map → detect-3S46RUMK.js.map} +0 -0
  162. /package/dist/{doctor-AC437ZAW.js.map → doctor-3CUBPQKU.js.map} +0 -0
  163. /package/dist/{droid-HF2AIFB2.js.map → droid-PTCH2K7Y.js.map} +0 -0
  164. /package/dist/{gemini-cli-2EOK26S2.js.map → gemini-cli-QGLN2UMS.js.map} +0 -0
  165. /package/dist/{goose-55JOTXS5.js.map → goose-DQ6GSZ5O.js.map} +0 -0
  166. /package/dist/{hermes-QVZOZU4B.js.map → hermes-E47IG63A.js.map} +0 -0
  167. /package/dist/{hook-VYD3OCLM.js.map → hook-P6EKDINW.js.map} +0 -0
  168. /package/dist/{install-S6BYIJ62.js.map → install-7DMK53SB.js.map} +0 -0
  169. /package/dist/{kilo-GJNSBWVV.js.map → kilo-OU2ZLZKB.js.map} +0 -0
  170. /package/dist/{kilo-cli-2CCB3DBI.js.map → kilo-cli-NMWGYF4F.js.map} +0 -0
  171. /package/dist/{kimi-YRPCSB6N.js.map → kimi-Z7L2LEEI.js.map} +0 -0
  172. /package/dist/{leaderboard-SUSUDKHR.js.map → leaderboard-LF5SP6X2.js.map} +0 -0
  173. /package/dist/{mimo-code-V4FP5PUJ.js.map → mimo-code-G2CBZ4M6.js.map} +0 -0
  174. /package/dist/{mux-CMJSM42O.js.map → mux-JNM3F2NW.js.map} +0 -0
  175. /package/dist/{nemoclaw-VP56PGKC.js.map → nemoclaw-SHA4IUML.js.map} +0 -0
  176. /package/dist/{omp-OOFGD3GG.js.map → omp-OOVUNXME.js.map} +0 -0
  177. /package/dist/{openclaw-V73XHPXP.js.map → openclaw-BD56E5MV.js.map} +0 -0
  178. /package/dist/{opencode-MKLHSQRD.js.map → opencode-W2RK4M7G.js.map} +0 -0
  179. /package/dist/{package-KOAAVKHH.js.map → package-2EAIYSJ4.js.map} +0 -0
  180. /package/dist/{qwen-code-2XE2T6F4.js.map → qwen-code-TUJNHKNI.js.map} +0 -0
  181. /package/dist/{roo-code-YJOIKCCS.js.map → roo-code-L5F7S6QH.js.map} +0 -0
  182. /package/dist/{status-N5LCQQ3R.js.map → status-E5MCFZM6.js.map} +0 -0
  183. /package/dist/{statusline-442XOF7R.js.map → statusline-LIPF2KVP.js.map} +0 -0
  184. /package/dist/{telemetry-V4YQL2NU.js.map → telemetry-4OC56NTM.js.map} +0 -0
  185. /package/dist/{trae-QSV2JZFT.js.map → trae-Z7CQ2A2Q.js.map} +0 -0
  186. /package/dist/{uninstall-WGEKTCDZ.js.map → uninstall-2YYKN5DX.js.map} +0 -0
  187. /package/dist/{upgrade-IH7CKPTO.js.map → upgrade-55AFPJEF.js.map} +0 -0
  188. /package/dist/{usage-DI7XRCKM.js.map → usage-3PB3WZSL.js.map} +0 -0
  189. /package/dist/{usage-event-2FCU55AN.js.map → usage-event-KD5FW6W4.js.map} +0 -0
  190. /package/dist/{vscode-copilot-R23RTVST.js.map → vscode-copilot-LU5NC4ZS.js.map} +0 -0
  191. /package/dist/{warp-B72XSQ5G.js.map → warp-4PPG5LOM.js.map} +0 -0
  192. /package/dist/{windsurf-642VBMQ2.js.map → windsurf-3T3RVXKM.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/runtime/serve.ts","../src/telemetry/calibration.ts","../src/telemetry/proxy.ts","../src/runtime/usage-event.ts","../src/runtime/statusline-entrypoint.ts","../src/runtime/action-entrypoint.ts"],"sourcesContent":["/**\n * runtime/serve — the `agent-connector serve` telemetry-wrapping entrypoint.\n *\n * When a stdio MCP server opts into transparent telemetry, its host config is\n * rewritten (by the adapter, via core/spawn.buildServeWrapperCommand) to launch\n * <homeBin> serve --connector <id> -- <realCommand> <realArgs...>\n * instead of the server directly. The CLI parses those flags and calls\n * {@link runServe}, which stands up the per-session telemetry context (store,\n * tokenizer, project identity, host detection) and hands off to the proxy.\n *\n * The proxy (telemetry/proxy.runServeProxy) forwards bytes VERBATIM in both\n * directions and measures aggregate per-tool token counts out of band, so this\n * wrapper is transparent to both the host and the real server. It resolves with\n * the child server's exit code, which the CLI uses as its own.\n */\n\nimport { randomUUID } from \"node:crypto\";\n\nimport { detectRuntimeHost } from \"../adapters/detect.js\";\nimport { REGISTERED_PLATFORM_IDS } from \"../adapters/registry.js\";\nimport { loadRegisteredConnector } from \"../core/load-connector.js\";\nimport { projectIdentity } from \"../core/paths.js\";\nimport { detectLaunchMethod } from \"../core/spawn.js\";\nimport type { PlatformId } from \"../core/types.js\";\nimport { runServeProxy } from \"../telemetry/proxy.js\";\nimport { openStore } from \"../telemetry/store.js\";\nimport { getTokenizer } from \"../telemetry/tokenizer.js\";\nimport type { TelemetryInstallScope } from \"../telemetry/types.js\";\n\n/** Flags the CLI hands to {@link runServe}. */\nexport interface RunServeOptions {\n /** Connector id from `--connector <id>`; selects telemetry config + stamps records. */\n connectorId: string;\n /** The real MCP server executable to spawn (everything after `--`). */\n serverCommand: string;\n /** Arguments passed to that executable. */\n serverArgs: string[];\n /**\n * Install scope from `--scope <user|project>`. OPTIONAL: absent for configs\n * written before scope plumbing existed — left unstamped so older rows read\n * as \"unknown\". Stamped verbatim onto every telemetry record when present.\n */\n installScope?: TelemetryInstallScope;\n /**\n * Install TARGET platform id from `--host <platformId>` (baked into the\n * wrapper at install time). OPTIONAL: when a recognized platform id, it\n * OVERRIDES runtime env detection so headless spawns stamp hostPlatform\n * correctly (detectRuntimeHost only knows env markers for a few hosts and\n * otherwise mis-attributes). Absent/unrecognized → fall back to detection.\n */\n hostPlatformOverride?: PlatformId;\n}\n\n/**\n * Launch the developer's real MCP server under the telemetry-wrapping proxy.\n *\n * Resolves with the child server's exit code (propagated as this process's exit\n * code by the CLI). The session id comes from AGENT_CONNECTOR_SESSION when the\n * host sets it (empty otherwise); the host platform is detected from runtime env\n * markers; the project identity partitions telemetry by the stable project key.\n */\n/**\n * Resolve a session id for telemetry attribution. Prefers a host-provided\n * session/thread marker (so records from the same host session group together);\n * falls back to a per-process UUID — each `serve` invocation is one server\n * session, a sensible default granularity — so `--by session` rollups are never\n * collapsed into a single empty-keyed group.\n */\nfunction resolveSessionId(env: NodeJS.ProcessEnv = process.env): string {\n return (\n env.AGENT_CONNECTOR_SESSION ||\n env.CLAUDE_SESSION_ID ||\n env.CODEX_THREAD_ID ||\n env.CURSOR_TRACE_ID ||\n env.MCP_SESSION_ID ||\n `proc-${randomUUID()}`\n );\n}\n\nexport async function runServe(opts: RunServeOptions): Promise<number> {\n const { connectorId, serverCommand, serverArgs, installScope, hostPlatformOverride } =\n opts;\n\n const connector = await loadRegisteredConnector(connectorId);\n\n const id = projectIdentity(process.cwd());\n // Prefer the install TARGET platform baked into the wrapper (--host), but only\n // when it is a KNOWN registered platform id — a bad/unknown value falls back to\n // runtime env detection so a config typo can never poison hostPlatform.\n const hostPlatform: PlatformId =\n hostPlatformOverride !== undefined &&\n REGISTERED_PLATFORM_IDS.has(hostPlatformOverride)\n ? hostPlatformOverride\n : detectRuntimeHost().platform;\n const sessionId = resolveSessionId();\n\n // `serve` only ever wraps a locally-spawned stdio server (a remote/http server\n // is never launched through the proxy), so isRemote is always false here.\n const launchMethod = detectLaunchMethod(serverCommand, serverArgs);\n\n const store = openStore({});\n const tok = getTokenizer();\n\n return runServeProxy({\n connectorId,\n command: serverCommand,\n args: serverArgs,\n store,\n tokenizer: tok,\n modelFamilyHint: connector.telemetry.modelFamilyHint,\n hostPlatform,\n sessionId,\n projectKey: id.key,\n projectDir: id.dir,\n measureToolDefs: connector.telemetry.measureToolDefs,\n installScope,\n launchMethod,\n });\n}\n","/**\n * telemetry/calibration — OPT-IN Anthropic count_tokens calibration.\n *\n * The default tokenizer counts every family with the OpenAI o200k_base BPE, so\n * an Anthropic session's counts are an honest-but-approximate stand-in\n * (\"tokenizer-approx\"). This module lets a developer OPT IN to calibrating that\n * approximation against Anthropic's real `count_tokens` endpoint: we sample a\n * tiny fraction of tool calls off-box, learn a per-family correction factor\n * (rolling mean of exact/approx), and apply it to the locally-tokenized counts\n * so they land much closer to the host's real numbers — labeled honestly as\n * \"tokenizer-calibrated\".\n *\n * PRIVACY + SAFETY — load-bearing invariants:\n * • OPT-IN only. Nothing here runs unless BOTH AGENT_CONNECTOR_CALIBRATE\n * contains \"anthropic\" AND ANTHROPIC_API_KEY is set (see isCalibrationEnabled).\n * • Sampling only — shouldSample() rate-limits hard so we never hammer the API.\n * • Content leaves the box ONLY on a sampled call, ONLY when opted in. We store\n * a single scalar factor + sample count — NEVER the sampled text itself.\n * • Fail-open everywhere: a network/parse/IO error returns null / passes the\n * approximation through unchanged and NEVER throws into a tool call or hook.\n *\n * No new dependencies: uses Node's global fetch (Node >= 18) and node:fs.\n */\n\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { dataRoot, ensureDir } from \"../core/paths.js\";\nimport type { ConfidenceSource, ModelFamily } from \"./types.js\";\n\n// ── Env switches ──────────────────────────────────────────────────────────\n\n/**\n * Is opt-in Anthropic calibration enabled for this process?\n *\n * Requires BOTH:\n * • AGENT_CONNECTOR_CALIBRATE — a comma-separated allowlist that INCLUDES\n * `anthropic` (so a future `AGENT_CONNECTOR_CALIBRATE=openai,anthropic` can\n * opt other families in without touching this gate), and\n * • ANTHROPIC_API_KEY — a non-empty key to authenticate the off-box call.\n *\n * Either missing → disabled (the privacy-safe default).\n */\nexport function isCalibrationEnabled(): boolean {\n const families = (process.env.AGENT_CONNECTOR_CALIBRATE || \"\")\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => s !== \"\");\n const key = (process.env.ANTHROPIC_API_KEY || \"\").trim();\n return families.includes(\"anthropic\") && key !== \"\";\n}\n\n// ── Factor store (dataRoot/calibration.json) ────────────────────────────────\n\n/** One learned correction factor for a model family: factor + sample count. */\nexport interface CalibrationFactor {\n /** Multiply an approx count by this to estimate the real count. */\n factor: number;\n /** How many samples have folded into the rolling mean. */\n samples: number;\n}\n\n/** The on-disk factor map, keyed by model family. */\nexport type CalibrationFactors = Partial<Record<ModelFamily, CalibrationFactor>>;\n\n/** Path to the learned-factor store: dataRoot()/calibration.json. */\nexport function calibrationPath(): string {\n return join(dataRoot(), \"calibration.json\");\n}\n\n/**\n * Clamp a measured exact/approx ratio into a sane range. A pathological sample\n * (e.g. an empty-string approx of 0 → Infinity, or a parse glitch) must never\n * poison the rolling mean, so ratios are pinned to [0.2, 5].\n */\nconst RATIO_MIN = 0.2;\nconst RATIO_MAX = 5;\n\nfunction clampRatio(ratio: number): number | null {\n if (!Number.isFinite(ratio) || ratio <= 0) return null;\n if (ratio < RATIO_MIN) return RATIO_MIN;\n if (ratio > RATIO_MAX) return RATIO_MAX;\n return ratio;\n}\n\n/**\n * Load the learned factors from disk. Fail-open: a missing/unreadable/malformed\n * file returns an empty map rather than throwing.\n */\nexport function loadFactors(): CalibrationFactors {\n const path = calibrationPath();\n if (!existsSync(path)) return {};\n try {\n const parsed = JSON.parse(readFileSync(path, \"utf8\")) as unknown;\n if (parsed === null || typeof parsed !== \"object\") return {};\n const out: CalibrationFactors = {};\n for (const [family, value] of Object.entries(parsed as Record<string, unknown>)) {\n if (value === null || typeof value !== \"object\") continue;\n const rec = value as Record<string, unknown>;\n const factor = rec[\"factor\"];\n const samples = rec[\"samples\"];\n if (\n typeof factor === \"number\" &&\n Number.isFinite(factor) &&\n factor > 0 &&\n typeof samples === \"number\" &&\n Number.isFinite(samples) &&\n samples >= 0\n ) {\n (out as Record<string, CalibrationFactor>)[family] = {\n factor,\n samples,\n };\n }\n }\n return out;\n } catch {\n return {};\n }\n}\n\n/**\n * Fold one observed exact/approx `ratio` into the rolling mean for `family` and\n * persist it. A running average converges to the true mean while staying cheap\n * and stateless across processes (each writer reads the prior count, blends in\n * the new sample, writes back). Fail-open: any read/write/clamp problem leaves\n * the store untouched and never throws.\n */\nexport function recordSample(family: ModelFamily, ratio: number): void {\n const clamped = clampRatio(ratio);\n if (clamped === null) return;\n try {\n const factors = loadFactors();\n const prior = factors[family];\n let next: CalibrationFactor;\n if (prior === undefined || prior.samples <= 0) {\n next = { factor: clamped, samples: 1 };\n } else {\n const samples = prior.samples + 1;\n // Running average: new mean = old mean + (sample - old mean) / n.\n const factor = prior.factor + (clamped - prior.factor) / samples;\n next = { factor, samples };\n }\n const updated: CalibrationFactors = { ...factors, [family]: next };\n const path = calibrationPath();\n ensureDir(dataRoot());\n writeFileSync(path, `${JSON.stringify(updated, null, 2)}\\n`, \"utf8\");\n } catch {\n /* fail-open: a calibration write must never break a tool call */\n }\n}\n\n// ── Anthropic count_tokens (off-box, sampled, fail-open) ─────────────────────\n\n/** Default model used for count_tokens when no family→model map applies. */\nconst DEFAULT_ANTHROPIC_MODEL = \"claude-3-5-sonnet-latest\";\n\n/** Anthropic count_tokens endpoint. */\nconst COUNT_TOKENS_URL = \"https://api.anthropic.com/v1/messages/count_tokens\";\n\n/** The single field we read out of a successful response. */\ninterface CountTokensResponse {\n input_tokens?: unknown;\n}\n\n/**\n * Ask Anthropic's `count_tokens` endpoint for the exact token count of `text`\n * under `model`. Returns the integer count, or `null` on ANY failure (no key,\n * non-200, network error, unparseable body) — fail-open by contract.\n *\n * Only ever called on a SAMPLED tool call when calibration is opted in, so the\n * sampled text leaves the box only under explicit operator consent.\n */\nexport async function countTokensAnthropic(\n text: string,\n model: string = DEFAULT_ANTHROPIC_MODEL,\n): Promise<number | null> {\n const apiKey = (process.env.ANTHROPIC_API_KEY || \"\").trim();\n if (apiKey === \"\") return null;\n try {\n const res = await fetch(COUNT_TOKENS_URL, {\n method: \"POST\",\n headers: {\n \"x-api-key\": apiKey,\n \"anthropic-version\": \"2023-06-01\",\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({\n model,\n messages: [{ role: \"user\", content: text }],\n }),\n });\n if (!res.ok) return null;\n const body = (await res.json()) as CountTokensResponse;\n const n = body.input_tokens;\n if (typeof n === \"number\" && Number.isFinite(n) && n >= 0) {\n return n;\n }\n return null;\n } catch {\n return null;\n }\n}\n\n// ── Sampling (rate-limit so we never hammer the API) ─────────────────────────\n\n/**\n * Sample roughly 1 in {@link SAMPLE_EVERY} calls, with a hard per-minute cap so\n * a burst of tool calls can never fan out into a burst of API calls. Both\n * counters are in-memory (per process) — calibration is a best-effort,\n * low-volume background signal, not a per-call requirement.\n */\nconst SAMPLE_EVERY = 20;\nconst MAX_SAMPLES_PER_MINUTE = 10;\n\nlet callCounter = 0;\nlet windowStartMs = 0;\nlet samplesThisWindow = 0;\n\n/**\n * Should THIS call fire an off-box count_tokens sample? Combines a 1-in-N\n * counter with a rolling per-minute cap. Pure in-memory bookkeeping; never\n * throws, never blocks.\n */\nexport function shouldSample(now: number = Date.now()): boolean {\n // Roll the per-minute window.\n if (now - windowStartMs >= 60_000) {\n windowStartMs = now;\n samplesThisWindow = 0;\n }\n callCounter += 1;\n if (callCounter % SAMPLE_EVERY !== 0) return false;\n if (samplesThisWindow >= MAX_SAMPLES_PER_MINUTE) return false;\n samplesThisWindow += 1;\n return true;\n}\n\n/** Reset the in-memory sampling counters. Test-only seam; cheap + side-effect-free. */\nexport function _resetSamplingForTest(): void {\n callCounter = 0;\n windowStartMs = 0;\n samplesThisWindow = 0;\n}\n\n// ── Apply a learned factor to a local approximation ──────────────────────────\n\n/** Result of {@link applyCalibration}: the adjusted count + its honest source. */\nexport interface CalibratedCount {\n tokens: number;\n source: Extract<ConfidenceSource, \"tokenizer-approx\" | \"tokenizer-calibrated\">;\n}\n\n/**\n * Adjust a locally-tokenized `approxTokens` count by the learned factor for\n * `family`. When a stored factor exists for the anthropic family, return the\n * scaled count labeled \"tokenizer-calibrated\"; otherwise pass the approximation\n * through unchanged as \"tokenizer-approx\". Pure: reads the factor store but\n * mutates nothing.\n */\nexport function applyCalibration(\n approxTokens: number,\n family: ModelFamily,\n factors: CalibrationFactors = loadFactors(),\n): CalibratedCount {\n if (family === \"anthropic\") {\n const f = factors[family];\n if (f !== undefined && f.samples > 0 && Number.isFinite(f.factor) && f.factor > 0) {\n return {\n tokens: Math.max(0, Math.round(approxTokens * f.factor)),\n source: \"tokenizer-calibrated\",\n };\n }\n }\n return { tokens: approxTokens, source: \"tokenizer-approx\" };\n}\n\n/** The model used for a family's count_tokens sample (anthropic → default model). */\nexport function modelForFamily(_family: ModelFamily): string {\n return DEFAULT_ANTHROPIC_MODEL;\n}\n","/**\n * telemetry/proxy — the telemetry-wrapping MCP stdio proxy.\n *\n * `agent-connector serve <command> <args…>` spawns the developer's REAL MCP\n * server as a child and sits transparently between the host and that server,\n * speaking the MCP stdio wire format: NEWLINE-DELIMITED JSON-RPC (one single-line\n * JSON object per message, terminated by `\\n`; stdio has NO Content-Length\n * framing). Bytes are forwarded VERBATIM in both directions so the proxy can\n * never corrupt the stream; a side line-buffer tees a COPY of each direction,\n * parses complete messages, and measures per-tool token usage out of band.\n *\n * Honesty / safety rules baked in here:\n * • Forwarding always happens FIRST. Measurement runs after the bytes are out\n * the door and is wrapped so a measurement bug can never break a tool call.\n * • Telemetry stores AGGREGATE COUNTS ONLY — the parsed `tools/call` arguments\n * and results are tokenized and discarded; raw content is never persisted.\n * • AGENT_CONNECTOR_TELEMETRY=0 → still proxy transparently, skip all measure.\n *\n * The proxy resolves with the child's exit code and propagates SIGINT/SIGTERM.\n */\n\nimport type { PlatformId } from \"../core/types.js\";\nimport { spawnChild } from \"../core/spawn-child.js\";\nimport { type JsonRpcMessage, LineBuffer, idKey, isObject } from \"./jsonrpc.js\";\nimport {\n applyCalibration,\n countTokensAnthropic,\n isCalibrationEnabled,\n modelForFamily,\n recordSample,\n shouldSample,\n} from \"./calibration.js\";\nimport { measureToolCall, measureToolDefs } from \"./measure.js\";\nimport { newRecordId } from \"./store.js\";\nimport { inferModelFamily } from \"./tokenizer.js\";\nimport type {\n ConfidenceSource,\n LaunchMethod,\n ModelFamily,\n TelemetryInstallScope,\n TelemetryStore,\n Tokenizer,\n ToolEventRecord,\n} from \"./types.js\";\n\n/** Options for {@link runServeProxy}. */\nexport interface RunServeProxyOptions {\n /** Connector id this server belongs to (stamped on every record). */\n connectorId: string;\n /** The real MCP server executable to spawn. */\n command: string;\n /** Arguments passed to that executable. */\n args: string[];\n /** Where measured records are appended. */\n store: TelemetryStore;\n /** Tokenizer used for measurement (defaults baked into measure helpers). */\n tokenizer: Tokenizer;\n /**\n * Telemetry model-family hint. \"auto\" infers the family from the MCP client's\n * `initialize` clientInfo.name; any explicit family wins outright.\n */\n modelFamilyHint: \"auto\" | ModelFamily;\n /** Host platform executing this proxy (stamped on every record). */\n hostPlatform: PlatformId;\n /** Host session id (stamped on every record). */\n sessionId: string;\n /** Hashed stable project identity (stamped on every record). */\n projectKey: string;\n /** Human-readable project directory (stamped on every record). */\n projectDir: string;\n /** When true, tokenize the `tools/list` schema once → tool-defs overhead. */\n measureToolDefs: boolean;\n /**\n * Install scope (global user vs project-local) stamped on every record.\n * OPTIONAL: omitted for configs written before scope plumbing existed, leaving\n * the field off the row so it reads as \"unknown\".\n */\n installScope?: TelemetryInstallScope;\n /**\n * How the wrapped server was launched (npx/bunx/uvx/node/binary/http), stamped\n * on every record. OPTIONAL for the same backward-compat reason as above.\n */\n launchMethod?: LaunchMethod;\n}\n\n// ── JSON-RPC shapes we read (kept local + narrow; everything else opaque) ─────\n\n/** A client→server `tools/call` we remember until its result comes back. */\ninterface PendingCall {\n toolName: string;\n args: unknown;\n}\n\n/**\n * Canonical string form of a tool call's arguments for an off-box count_tokens\n * sample — mirrors the tokenizer's own serialization so the sampled text equals\n * the bytes we approximated locally. A string passes through; anything else is\n * JSON-stringified; a value that stringifies to undefined becomes \"\".\n */\nfunction canonicalArgs(value: unknown): string {\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value) ?? \"\";\n } catch {\n return \"\";\n }\n}\n\n/**\n * Run the telemetry-wrapping MCP stdio proxy.\n *\n * Spawns `command args` with piped stdin/stdout (stderr inherited), forwards\n * both directions byte-for-byte, and measures `tools/call` round-trips and the\n * one-time `tools/list` tool-defs overhead into `store`. Resolves with the\n * child's exit code (or a signal-derived code) once the child closes.\n */\nexport async function runServeProxy(\n opts: RunServeProxyOptions,\n): Promise<number> {\n const {\n connectorId,\n command,\n args,\n store,\n tokenizer,\n modelFamilyHint,\n hostPlatform,\n sessionId,\n projectKey,\n projectDir,\n measureToolDefs: shouldMeasureToolDefs,\n installScope,\n launchMethod,\n } = opts;\n\n // Global kill switch: still proxy transparently, but skip ALL measurement.\n const measuringEnabled = process.env.AGENT_CONNECTOR_TELEMETRY !== \"0\";\n // OPT-IN Anthropic count_tokens calibration. Resolved once per session — the\n // gate (AGENT_CONNECTOR_CALIBRATE + ANTHROPIC_API_KEY) is process-level and\n // does not change mid-session. Off by default; privacy-safe.\n const calibrationEnabled = isCalibrationEnabled();\n\n // spawnChild fixes native-Windows package-runner launches: a bare npx/uvx\n // resolves to a .cmd shim that raw CreateProcess can't find/launch, so it is\n // run via a quoted single command line with a shell. No-op on macOS/Linux.\n const child = spawnChild(command, args, {\n stdio: [\"pipe\", \"pipe\", \"inherit\"],\n env: process.env,\n });\n\n // ── Per-session measurement state ───────────────────────────────────────\n // Family resolved from the client's `initialize` (or the hint) and cached.\n let family: ModelFamily = inferModelFamily(\"\", modelFamilyHint);\n // Outstanding tools/call requests, keyed by JSON-RPC id.\n const pending = new Map<string, PendingCall>();\n // Monotonic sequence so two records in the same ms still get distinct ids.\n let seq = 0;\n // tools/list overhead is measured exactly once per session.\n let toolDefsMeasured = false;\n\n /**\n * Build a base record stamped with the per-session identity fields plus the\n * scope dimensions. `installScope` / `launchMethod` are spread in ONLY when\n * defined, so a session without them leaves those fields off the row entirely\n * (read as \"unknown\") rather than writing an explicit `undefined`.\n */\n function baseRecord(): Omit<\n ToolEventRecord,\n \"toolName\" | \"scope\" | \"inputTokens\" | \"outputTokens\" | \"confidenceSource\" | \"isError\"\n > {\n return {\n id: newRecordId(seq++),\n ts: Date.now(),\n connectorId,\n hostPlatform,\n sessionId,\n projectKey,\n projectDir,\n ...(installScope !== undefined ? { installScope } : {}),\n ...(launchMethod !== undefined ? { launchMethod } : {}),\n };\n }\n\n /**\n * Inspect one parsed CLIENT→SERVER message. Caches the model family on\n * `initialize` and remembers `tools/call` requests so their results can be\n * measured when they come back. Never throws into the data path.\n */\n function onClientMessage(msg: JsonRpcMessage): void {\n const method = msg.method;\n if (method === \"initialize\") {\n const params = isObject(msg.params) ? msg.params : undefined;\n const clientInfo =\n params && isObject(params[\"clientInfo\"])\n ? (params[\"clientInfo\"] as Record<string, unknown>)\n : undefined;\n const clientName =\n clientInfo && typeof clientInfo[\"name\"] === \"string\"\n ? (clientInfo[\"name\"] as string)\n : \"\";\n family = inferModelFamily(clientName, modelFamilyHint);\n return;\n }\n\n if (method === \"tools/call\") {\n const key = idKey(msg.id);\n if (key === null) return; // a call with no id has no result to match\n const params = isObject(msg.params) ? msg.params : undefined;\n const toolName =\n params && typeof params[\"name\"] === \"string\"\n ? (params[\"name\"] as string)\n : \"unknown\";\n const callArgs = params ? params[\"arguments\"] : undefined;\n pending.set(key, { toolName, args: callArgs });\n }\n }\n\n /**\n * Inspect one parsed SERVER→CLIENT message. Matches `tools/call` results to\n * remembered requests and measures them; measures `tools/list` results once.\n * Never throws into the data path.\n */\n function onServerMessage(msg: JsonRpcMessage): void {\n const key = idKey(msg.id);\n if (key === null) return; // notifications carry no id we can correlate\n\n const pendingCall = pending.get(key);\n if (pendingCall !== undefined) {\n pending.delete(key);\n recordToolCall(pendingCall, msg);\n return;\n }\n\n // Not a tracked tools/call — it may be the tools/list result we measure\n // once for the fixed tool-definition overhead.\n if (shouldMeasureToolDefs && !toolDefsMeasured) {\n const result = isObject(msg.result) ? msg.result : undefined;\n const tools = result ? result[\"tools\"] : undefined;\n if (Array.isArray(tools)) {\n recordToolDefs(tools);\n }\n }\n }\n\n /** Measure a matched tools/call round-trip and append the record. */\n function recordToolCall(call: PendingCall, response: JsonRpcMessage): void {\n const hasError = response.error !== undefined;\n const result = response.result;\n // A JSON-RPC error has no `result`; measure against an empty object so the\n // input (args) tokens are still recorded honestly.\n const resultForMeasure = hasError ? {} : result;\n const measurement = measureToolCall(\n call.args,\n resultForMeasure,\n family,\n tokenizer,\n );\n\n // OPT-IN calibration: for an anthropic session, nudge the locally-tokenized\n // approx counts toward Anthropic's real numbers via the learned factor, and\n // fire a sampled off-box count_tokens to keep that factor fresh. Both steps\n // are best-effort and wrapped so they can never break the record path.\n let inputTokens = measurement.inputTokens;\n let outputTokens = measurement.outputTokens;\n let confidenceSource: ConfidenceSource = measurement.source;\n if (calibrationEnabled && family === \"anthropic\") {\n try {\n ({ inputTokens, outputTokens, confidenceSource } = calibrateCounts(\n measurement.inputTokens,\n measurement.outputTokens,\n measurement.source,\n ));\n maybeSampleCalibration(call.args, measurement.inputTokens);\n } catch {\n // Calibration is a non-essential enrichment — fall back to the raw\n // measurement values already captured above.\n }\n }\n\n // MCP signals a tool-level failure via result.isError===true; a JSON-RPC\n // protocol error (response.error) is also a failure.\n const resultIsError =\n isObject(result) && result[\"isError\"] === true;\n store.append({\n ...baseRecord(),\n toolName: call.toolName,\n scope: \"call\",\n inputTokens,\n outputTokens,\n confidenceSource,\n isError: hasError || resultIsError,\n });\n }\n\n /**\n * Apply the learned anthropic factor to the approx input/output counts. Only\n * a `tokenizer-approx` measurement is calibratable (a heuristic fallback or\n * host-native count is left exactly as-is); the combined source becomes\n * `tokenizer-calibrated` only when at least one side was actually scaled.\n */\n function calibrateCounts(\n rawIn: number,\n rawOut: number,\n rawSource: ConfidenceSource,\n ): { inputTokens: number; outputTokens: number; confidenceSource: ConfidenceSource } {\n if (rawSource !== \"tokenizer-approx\") {\n return { inputTokens: rawIn, outputTokens: rawOut, confidenceSource: rawSource };\n }\n const cin = applyCalibration(rawIn, family);\n const cout = applyCalibration(rawOut, family);\n const calibrated =\n cin.source === \"tokenizer-calibrated\" || cout.source === \"tokenizer-calibrated\";\n return {\n inputTokens: cin.tokens,\n outputTokens: cout.tokens,\n confidenceSource: calibrated ? \"tokenizer-calibrated\" : \"tokenizer-approx\",\n };\n }\n\n /**\n * On a SAMPLED call, fire-and-forget an off-box count_tokens for the call's\n * input args and fold the resulting exact/approx ratio into the learned\n * factor. Returns immediately — the network round-trip never blocks\n * forwarding or measurement. Fail-open: any error is swallowed.\n */\n function maybeSampleCalibration(args: unknown, approxInputTokens: number): void {\n if (approxInputTokens <= 0) return; // nothing to ratio against\n if (!shouldSample()) return;\n const text = canonicalArgs(args);\n if (text === \"\") return;\n // Detached promise — intentionally NOT awaited so the proxy never blocks on\n // the network. Errors are handled inside countTokensAnthropic (returns null)\n // and the .catch is a belt-and-braces guard against an unhandled rejection.\n void countTokensAnthropic(text, modelForFamily(family))\n .then((exact) => {\n if (exact !== null && exact > 0) {\n recordSample(family, exact / approxInputTokens);\n }\n })\n .catch(() => {\n /* fail-open: a calibration sample must never surface an error */\n });\n }\n\n /** Measure the one-time tools/list overhead and append the record. */\n function recordToolDefs(tools: readonly unknown[]): void {\n toolDefsMeasured = true;\n const count = measureToolDefs(tools, family, tokenizer);\n store.append({\n ...baseRecord(),\n toolName: \"*\",\n scope: \"tool_defs\",\n inputTokens: count.tokens,\n outputTokens: 0,\n confidenceSource: count.source,\n isError: false,\n });\n }\n\n /** Parse one NDJSON line and route it, swallowing any measurement error. */\n function handleLine(line: string, direction: \"client\" | \"server\"): void {\n if (!measuringEnabled) return;\n let msg: JsonRpcMessage;\n try {\n const parsed = JSON.parse(line) as unknown;\n if (!isObject(parsed)) return;\n msg = parsed as JsonRpcMessage;\n } catch {\n return; // not a complete/valid JSON message — ignore for telemetry\n }\n try {\n if (direction === \"client\") onClientMessage(msg);\n else onServerMessage(msg);\n } catch {\n // Measurement must NEVER break the proxy. Drop the record silently.\n }\n }\n\n const clientLines = new LineBuffer((line) => handleLine(line, \"client\"));\n const serverLines = new LineBuffer((line) => handleLine(line, \"server\"));\n\n // ── Transparent byte forwarding (host stdin → child stdin) ───────────────\n // Forward VERBATIM first, then tee a copy into the line buffer to measure.\n // Honor backpressure: if the child's stdin buffer is full, pause the host\n // stdin and resume on drain so a slow server can't make us buffer unboundedly.\n process.stdin.on(\"data\", (chunk: Buffer) => {\n if (child.stdin && child.stdin.writable) {\n const ok = child.stdin.write(chunk);\n if (!ok) {\n process.stdin.pause();\n child.stdin.once(\"drain\", () => process.stdin.resume());\n }\n }\n if (measuringEnabled) {\n try {\n clientLines.push(chunk);\n } catch {\n /* tee side-channel must never affect forwarding */\n }\n }\n });\n process.stdin.on(\"end\", () => {\n if (child.stdin && !child.stdin.destroyed) child.stdin.end();\n });\n\n // ── Transparent byte forwarding (child stdout → host stdout) ─────────────\n if (child.stdout) {\n const childStdout = child.stdout;\n childStdout.on(\"data\", (chunk: Buffer) => {\n const ok = process.stdout.write(chunk);\n if (!ok) {\n childStdout.pause();\n process.stdout.once(\"drain\", () => childStdout.resume());\n }\n if (measuringEnabled) {\n try {\n serverLines.push(chunk);\n } catch {\n /* tee side-channel must never affect forwarding */\n }\n }\n });\n }\n\n // ── Signal propagation: forward SIGINT/SIGTERM to the child ──────────────\n const forwardSignal = (signal: NodeJS.Signals): void => {\n try {\n if (!child.killed) child.kill(signal);\n } catch {\n /* child may already be gone */\n }\n };\n const onSigint = (): void => forwardSignal(\"SIGINT\");\n const onSigterm = (): void => forwardSignal(\"SIGTERM\");\n process.on(\"SIGINT\", onSigint);\n process.on(\"SIGTERM\", onSigterm);\n\n // ── Resolve with the child's exit code (or signal-derived code) ──────────\n return await new Promise<number>((resolve) => {\n const finish = (code: number): void => {\n process.removeListener(\"SIGINT\", onSigint);\n process.removeListener(\"SIGTERM\", onSigterm);\n try {\n store.close();\n } catch {\n /* best-effort flush */\n }\n resolve(code);\n };\n\n child.on(\"error\", () => {\n // The server could not be spawned/launched. Surface a conventional\n // \"command not executable\" style failure code.\n finish(126);\n });\n\n child.on(\"close\", (code, signal) => {\n if (typeof code === \"number\") {\n finish(code);\n return;\n }\n // Killed by a signal → conventional 128 + signal number where known.\n if (signal) {\n const num = signalToNumber(signal);\n finish(num === undefined ? 1 : 128 + num);\n return;\n }\n finish(1);\n });\n });\n}\n\n/** Map the common termination signals to their numbers for exit-code math. */\nfunction signalToNumber(signal: NodeJS.Signals): number | undefined {\n const table: Partial<Record<NodeJS.Signals, number>> = {\n SIGINT: 2,\n SIGQUIT: 3,\n SIGKILL: 9,\n SIGTERM: 15,\n };\n return table[signal];\n}\n\nexport default runServeProxy;\n","/**\n * runtime/usage-event — the OPT-IN host-native turn-usage enricher (enricher 4a).\n *\n * Gemini CLI / Antigravity fire an `AfterModel` (Antigravity CLI: `PostInvocation`)\n * hook AFTER each model turn, whose stdin payload carries a `usageMetadata` block\n * with the host's OWN exact token accounting for that whole conversation turn:\n * { promptTokenCount, candidatesTokenCount, cachedContentTokenCount,\n * thoughtsTokenCount, totalTokenCount }\n * This is the single point in the whole matrix where a host reports REAL per-turn\n * usage to a command we control — so we record it as `confidenceSource:\"host-native\"`\n * (the top of CONFIDENCE_RANK), upgrading those rows from the serve-proxy estimate.\n *\n * DISTINCT, NEVER-SUMMED ORIGIN. Host-native turn usage is WHOLE-CONVERSATION, not\n * per-MCP. To avoid double-counting against (a) the per-MCP serve-proxy `call`\n * rows and (b) the usage-reader host-scan numbers, every record written here uses\n * the DISTINCT scope `\"model_turn\"`. The MCP leaderboard excludes that scope (just\n * as it special-cases `tool_defs`); the unified leaderboard surfaces it as its own\n * clearly-labeled section that is explicitly never added to the other two origins.\n *\n * PRIVACY + FAIL-OPEN. This enricher is OPT-IN at install time (see the adapters);\n * it stores AGGREGATE COUNTS ONLY (no raw content — the payload's prompt/response\n * text is never read). ANY parse / store / IO error degrades to exit 0 and records\n * NOTHING: a host-native usage hook must never break a model turn. This function\n * never throws.\n */\n\nimport { projectIdentity } from \"../core/paths.js\";\nimport { newRecordId, openStore } from \"../telemetry/store.js\";\nimport type { PlatformId } from \"../core/types.js\";\nimport type { ToolEventRecord } from \"../telemetry/types.js\";\n\n/** Flags + stdin the CLI hands to {@link runUsageEvent}. */\nexport interface RunUsageEventOptions {\n /** Host platform id from the command (`usage-event <platformId> …`). */\n platformId: string;\n /** Connector id from `--connector <id>` (stamped on the record). */\n connectorId: string;\n /** Raw stdin payload (host-native JSON). Empty string is tolerated → no record. */\n stdin: string;\n}\n\n/** Process-level result the CLI translates into an exit code. */\nexport interface RunUsageEventResult {\n /** Always 0 — a host-native usage hook must never block a model turn. */\n exitCode: number;\n /** True when a `model_turn` record was appended (false on any fail-open path). */\n recorded: boolean;\n}\n\n/** The never-records, never-throws result. */\nconst NOOP: RunUsageEventResult = { exitCode: 0, recorded: false };\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\n/** Coerce a value to a non-negative safe integer (NaN/negatives/floats → 0). */\nfunction toNonNegInt(v: unknown): number {\n const n = typeof v === \"number\" ? v : typeof v === \"string\" ? Number(v) : NaN;\n if (!Number.isFinite(n) || n < 0) return 0;\n return Math.floor(n);\n}\n\n/** First non-empty string among the given keys of an object. */\nfunction firstStr(obj: Record<string, unknown>, keys: readonly string[]): string | undefined {\n for (const k of keys) {\n const v = obj[k];\n if (typeof v === \"string\" && v.trim() !== \"\") return v;\n }\n return undefined;\n}\n\n/** Read a token field tolerant of both camelCase and snake_case spellings. */\nfunction tokenField(\n meta: Record<string, unknown>,\n keys: readonly string[],\n): number {\n for (const k of keys) {\n if (k in meta) return toNonNegInt(meta[k]);\n }\n return 0;\n}\n\n/** Locate the `usageMetadata` block under either spelling, top-level or nested. */\nfunction findUsageMetadata(root: Record<string, unknown>): Record<string, unknown> | undefined {\n for (const k of [\"usageMetadata\", \"usage_metadata\"]) {\n if (isObject(root[k])) return root[k] as Record<string, unknown>;\n }\n // Some hosts nest the model response (with its usage) under a `response` /\n // `modelResponse` envelope — probe one level down, best-effort.\n for (const k of [\"response\", \"modelResponse\", \"model_response\"]) {\n const nested = root[k];\n if (isObject(nested)) {\n for (const mk of [\"usageMetadata\", \"usage_metadata\"]) {\n if (isObject(nested[mk])) return nested[mk] as Record<string, unknown>;\n }\n }\n }\n return undefined;\n}\n\n/** A registered PlatformId, or \"unknown\" when the id is not one we know. */\nconst KNOWN_PLATFORMS: ReadonlySet<string> = new Set<PlatformId>([\n \"claude-code\", \"codex\", \"cursor\", \"vscode-copilot\", \"jetbrains-copilot\",\n \"copilot-cli\", \"gemini-cli\", \"opencode\", \"kilo\", \"kilo-cli\", \"warp\", \"hermes\",\n \"openclaw\", \"zed\", \"antigravity\", \"antigravity-cli\", \"kiro\", \"qwen-code\",\n \"kimi\", \"pi\", \"omp\", \"droid\", \"roo-code\", \"trae\", \"amp\", \"codebuff\", \"mux\",\n \"crush\", \"goose\", \"synthetic\", \"unknown\",\n]);\n\nfunction asPlatformId(id: string): PlatformId {\n return (KNOWN_PLATFORMS.has(id) ? id : \"unknown\") as PlatformId;\n}\n\n/**\n * Record one host-native model turn. Parses the host's `usageMetadata`, maps it to\n * a DISTINCT `model_turn` `ToolEventRecord` (confidence `host-native`, toolName\n * `\"*\"`), and appends it to the shared telemetry store. NEVER throws and never\n * blocks the turn: every failure path resolves to {@link NOOP} (exit 0, nothing\n * recorded).\n */\nexport async function runUsageEvent(\n opts: RunUsageEventOptions,\n): Promise<RunUsageEventResult> {\n try {\n // Global telemetry kill switch is honored by the store's append (no-op when\n // AGENT_CONNECTOR_TELEMETRY=0); we still parse cheaply and let append drop it.\n const trimmed = opts.stdin.trim();\n if (trimmed === \"\") return NOOP;\n\n let raw: unknown;\n try {\n raw = JSON.parse(trimmed);\n } catch {\n return NOOP; // malformed payload → fail-open, record nothing\n }\n if (!isObject(raw)) return NOOP;\n\n const meta = findUsageMetadata(raw);\n if (meta === undefined) return NOOP;\n\n const promptTokens = tokenField(meta, [\"promptTokenCount\", \"prompt_token_count\"]);\n const candidates = tokenField(meta, [\"candidatesTokenCount\", \"candidates_token_count\"]);\n const cached = tokenField(meta, [\"cachedContentTokenCount\", \"cached_content_token_count\"]);\n const thoughts = tokenField(meta, [\"thoughtsTokenCount\", \"thoughts_token_count\"]);\n\n // promptTokenCount is cache-INCLUSIVE (Gemini-family semantics, mirrored by\n // the antigravity-shared usage reader): net fresh input = prompt - cached.\n const inputTokens = Math.max(0, promptTokens - Math.min(cached, promptTokens));\n // Output = generated candidates + reasoning (\"thoughts\") tokens.\n const outputTokens = candidates + thoughts;\n\n // A turn with no measurable tokens is not worth a row.\n if (inputTokens === 0 && outputTokens === 0) return NOOP;\n\n // Identity: prefer payload session/cwd; fall back to process.cwd() for the\n // project key so a turn always lands in a stable project partition.\n const sessionId =\n firstStr(raw, [\"session_id\", \"sessionId\", \"conversationId\", \"conversation_id\"]) ?? \"\";\n const cwd = firstStr(raw, [\"cwd\", \"workspace\", \"projectDir\", \"project_dir\"]) ?? process.cwd();\n const id = projectIdentity(cwd);\n\n const record: ToolEventRecord = {\n id: newRecordId(0),\n ts: Date.now(),\n connectorId: opts.connectorId,\n toolName: \"*\",\n scope: \"model_turn\",\n hostPlatform: asPlatformId(opts.platformId),\n sessionId,\n projectKey: id.key,\n projectDir: id.dir,\n inputTokens,\n outputTokens,\n confidenceSource: \"host-native\",\n isError: false,\n };\n\n const store = openStore({});\n try {\n store.append(record);\n } finally {\n try {\n store.close();\n } catch {\n /* best-effort flush */\n }\n }\n return { exitCode: 0, recorded: true };\n } catch {\n // Fail-open: a host-native usage enricher must never surface an error.\n return NOOP;\n }\n}\n\nexport default runUsageEvent;\n","/**\n * runtime/statusline-entrypoint — the universal statusline (HUD) renderer.\n *\n * A statusline-supporting host points its status line config at the single stable\n * home binary (`<homeBin> statusline <platformId> --connector <id>`, built by\n * core/spawn.buildHomeBinStatuslineCommand). The CLI reads stdin and calls\n * {@link runStatusline} with the parsed flags + the raw stdin string. This module:\n *\n * 1. Loads the registered connector (live render handler) and the host adapter.\n * 2. Parses the host's raw status payload into a normalized StatuslineContext.\n * 3. Calls the connector's render(ctx) and coerces the result to a string.\n * 4. Formats the line into the host's native status reply (exit code + stdout).\n *\n * FAIL-SAFE is the contract (NOT fail-open with carve-outs like hooks): a status\n * line is decorative — it must NEVER wedge the host or spew an error/stack trace\n * into the status bar. So ANY error path — bad payload, missing connector,\n * throwing render, adapter without statusline support — returns exit 0 with NO\n * stdout (an empty status line), never a non-zero exit and never partial output.\n *\n * NOTE (follow-up): no telemetry is recorded for statusline renders in v1 (out of\n * scope). When added, it MUST stay inside the same fail-safe envelope.\n */\n\nimport type { PlatformId } from \"../core/types.js\";\nimport { log } from \"../core/logger.js\";\nimport {\n loadRegisteredConnector,\n readRegisteredMeta,\n} from \"../core/load-connector.js\";\nimport { loadAdapter } from \"../adapters/registry.js\";\nimport {\n attachLazyTelemetryUsage,\n buildTelemetryAccessor,\n} from \"./telemetry-accessor.js\";\n\n/** Flags + stdin the CLI hands to {@link runStatusline}. */\nexport interface RunStatuslineOptions {\n /** Host platform id from the command (`statusline <platformId> …`). */\n platformId: string;\n /** Connector id from `--connector <id>`. */\n connectorId: string;\n /** Raw stdin payload (host-native status JSON). Empty string is tolerated → `{}`. */\n stdin: string;\n}\n\n/** Process-level result the CLI translates into exit code + stdout/stderr. */\nexport interface RunStatuslineResult {\n exitCode: number;\n stdout?: string;\n stderr?: string;\n}\n\n/** The fail-safe result: exit 0, no output (an empty status line). */\nconst EMPTY: RunStatuslineResult = { exitCode: 0 };\n\n/**\n * Tolerantly parse the host's stdin payload. Empty / whitespace-only input is a\n * legitimate \"no payload\" signal and resolves to `{}`. Malformed JSON also\n * degrades to `{}` rather than throwing — fail-safe is the contract.\n */\nfunction parseStdin(stdin: string): unknown {\n const trimmed = stdin.trim();\n if (trimmed === \"\") return {};\n try {\n return JSON.parse(trimmed);\n } catch {\n return {};\n }\n}\n\n/**\n * Render one host status-line invocation. Always resolves (never rejects): every\n * failure path returns the empty {@link EMPTY} result so the CLI exits cleanly\n * with an empty status line. See the module header for the fail-safe contract.\n */\nexport async function runStatusline(\n opts: RunStatuslineOptions,\n): Promise<RunStatuslineResult> {\n const { platformId, connectorId, stdin } = opts;\n\n try {\n const connector = await loadRegisteredConnector(connectorId);\n const adapter = await loadAdapter(platformId);\n\n // Nothing to render: no statusline declared, or the host adapter has no\n // statusline runtime support (parse/format pair). Empty line, exit 0.\n if (\n !connector.statusline ||\n typeof connector.statusline.render !== \"function\" ||\n !adapter ||\n !adapter.parseStatusInput ||\n !adapter.formatStatusOutput\n ) {\n return EMPTY;\n }\n\n const raw = parseStdin(stdin);\n const ctx = adapter.parseStatusInput(raw);\n // The command carries the authoritative connector id; stamp it so render()\n // sees the connector it was dispatched for.\n ctx.connectorId = connectorId;\n // capabilities is REQUIRED on StatuslineContext. claude-code's parseStatusInput\n // sets it, but a future/third-party adapter could omit it — backfill so the\n // runtime guarantee matches the type (mirrors the simulate harness). Never\n // let render() see undefined capabilities while the type claims it is present.\n if (ctx.capabilities == null) ctx.capabilities = adapter.capabilities;\n // Recover the install scope from the registered metadata (sync) and stamp it\n // onto the ctx — scope is an install-time property the entrypoint has no\n // other access to. Undefined when the meta carries none. Also expose the\n // per-connector telemetry usage accessor (lazy, fail-safe to zeros).\n ctx.scope = readRegisteredMeta(connectorId)?.scope;\n ctx.telemetry = buildTelemetryAccessor(connectorId);\n // Keep `ctx.usage` synchronous for render functions, but compute it only if\n // the render actually reads the property. Status lines refresh frequently,\n // and the NDJSON backend has to scan the store for an all-time summary.\n attachLazyTelemetryUsage(ctx, connectorId);\n\n // Per-host render override: when rendering for host X, `hosts[X].render`\n // wins over the top-level render; a host not listed (or a per-host entry\n // that is somehow not a function) falls back to the top-level render.\n // Selection NEVER throws — fail-safe is preserved.\n const perHost = connector.statusline.hosts?.[platformId as PlatformId]?.render;\n const render =\n typeof perHost === \"function\" ? perHost : connector.statusline.render;\n\n const rendered = await render(ctx);\n // Coerce: a non-string return (number, accidental object) is stringified so\n // a misbehaving render never crashes the format step. null/undefined → \"\".\n const line = rendered == null ? \"\" : String(rendered);\n\n const reply = adapter.formatStatusOutput(line);\n return {\n exitCode: reply.exitCode,\n ...(reply.stdout !== undefined ? { stdout: reply.stdout } : {}),\n ...(reply.stderr !== undefined ? { stderr: reply.stderr } : {}),\n };\n } catch (err) {\n // FAIL-SAFE: a status line must never wedge the host or surface an error.\n // Log for diagnostics (stderr of the home binary — not the status bar) and\n // return the empty line.\n const message = err instanceof Error ? err.message : String(err);\n log.error(`statusline ${platformId} (${connectorId}) failed:`, message);\n return EMPTY;\n }\n}\n\nexport default runStatusline;\n","/**\n * runtime/action-entrypoint — the universal user-invokable action dispatcher.\n *\n * A future host affordance (slash command / keybinding) points at the single\n * stable home binary (`<homeBin> action <platformId> <actionId> --connector\n * <id>`, built by core/spawn.buildHomeBinActionCommand). The CLI parses the\n * flags and calls {@link runAction}. This module:\n *\n * 1. Loads the registered connector (live run handler) and the host adapter.\n * 2. Builds the shared {@link HostCtx} (host + the adapter's capabilities; NO\n * stdin — an action takes no host payload, unlike a hook or status line).\n * 3. Finds the action by id, resolves the per-host run override, runs it, and\n * prints the optional result.message.\n *\n * USER-TRIGGERED ERROR SEMANTICS (the key difference from hooks/statusline):\n * actions are invoked DELIBERATELY by a user, so errors are SURFACED, never\n * failed silently. An unknown action id or a throwing run → exit 1 + a stderr\n * message. (Hooks fail-open to exit 0; the statusline fail-safes to an empty\n * line — both are passive surfaces a host fires automatically. An action is not:\n * swallowing its failure would leave the user staring at nothing, unable to\n * tell the action ran.)\n *\n * NOTE (follow-up): no telemetry is recorded for action runs in v1 (out of\n * scope), and no adapter EMITS the affordance yet — v1 ships the dispatch\n * backbone only.\n */\n\nimport type {\n HostCtx,\n PlatformCapabilities,\n PlatformId,\n} from \"../core/types.js\";\nimport {\n loadRegisteredConnector,\n readRegisteredMeta,\n} from \"../core/load-connector.js\";\nimport { loadAdapter, REGISTERED_PLATFORM_IDS } from \"../adapters/registry.js\";\nimport { buildTelemetryAccessor } from \"./telemetry-accessor.js\";\n\n/** Flags the CLI hands to {@link runAction} (no stdin — actions take no payload). */\nexport interface RunActionOptions {\n /** Host platform id from the command (`action <platformId> <actionId> …`). */\n platformId: string;\n /** Connector id from `--connector <id>`. */\n connectorId: string;\n /** The action id positional (`action <platformId> <actionId> …`). */\n actionId: string;\n}\n\n/** Process-level result the CLI translates into exit code + stdout/stderr. */\nexport interface RunActionResult {\n exitCode: number;\n stdout?: string;\n stderr?: string;\n}\n\n/**\n * Minimal all-false capabilities for the fallback ctx when the host adapter is\n * unknown/unregistered. The action still runs (it takes no host payload), but\n * branching on `ctx.capabilities` reads every flag as off — no affordance is\n * advertised for a host we cannot describe.\n */\nconst EMPTY_CAPABILITIES: PlatformCapabilities = {\n preToolUse: false,\n postToolUse: false,\n preCompact: false,\n sessionStart: false,\n sessionEnd: false,\n userPromptSubmit: false,\n stop: false,\n notification: false,\n canModifyArgs: false,\n canModifyOutput: false,\n canInjectSessionContext: false,\n transports: [],\n};\n\n/**\n * Dispatch one user-invokable action. Always resolves (never rejects): every\n * path returns a concrete {@link RunActionResult} so the CLI can exit cleanly,\n * but UNLIKE the hook/statusline runtimes an error resolves to exit 1 + a stderr\n * message (actions are user-triggered — surface the failure). See the module\n * header for the user-triggered error contract.\n */\nexport async function runAction(\n opts: RunActionOptions,\n): Promise<RunActionResult> {\n const { platformId, connectorId, actionId } = opts;\n\n let connector;\n try {\n connector = await loadRegisteredConnector(connectorId);\n } catch (err) {\n // A user asked to run an action on a connector we cannot load — surface it\n // (do NOT fail-open: the user would otherwise see nothing and assume it ran).\n const message = err instanceof Error ? err.message : String(err);\n return { exitCode: 1, stderr: message };\n }\n\n const action = connector.actions.find((a) => a.id === actionId);\n if (!action) {\n return {\n exitCode: 1,\n stderr: `no action \"${actionId}\" on connector ${connectorId}`,\n };\n }\n\n // Build the shared HostCtx. capabilities come from the adapter; an unknown\n // adapter still runs with the minimal ctx (an action takes no host payload).\n const adapter = await loadAdapter(platformId).catch(() => undefined);\n const host: PlatformId = REGISTERED_PLATFORM_IDS.has(platformId as PlatformId)\n ? (platformId as PlatformId)\n : \"unknown\";\n const ctx: HostCtx = {\n host,\n capabilities: adapter?.capabilities ?? EMPTY_CAPABILITIES,\n // Recover the install scope from the registered metadata (sync) — scope is\n // an install-time property the entrypoint otherwise has no access to —\n // and expose the per-connector telemetry usage accessor (lazy, fail-safe).\n scope: readRegisteredMeta(connectorId)?.scope,\n telemetry: buildTelemetryAccessor(connectorId),\n };\n\n // Per-host run override: when running for host X, `hosts[X].run` wins over the\n // top-level run; a host not listed (or a per-host entry that is somehow not a\n // function) falls back to the top-level run.\n const perHost = action.hosts?.[platformId as PlatformId]?.run;\n const run = typeof perHost === \"function\" ? perHost : action.run;\n\n try {\n const result = await run(ctx);\n const message = result?.message;\n if (typeof message === \"string\" && message !== \"\") {\n return { exitCode: 0, stdout: message };\n }\n // void / no message → success with no output.\n return { exitCode: 0 };\n } catch (err) {\n // USER-TRIGGERED: a throwing action surfaces its failure (exit 1 + stderr),\n // never a silent fail-open. This is the documented difference from\n // hooks/statusline.\n const message = err instanceof Error ? err.message : String(err);\n return {\n exitCode: 1,\n stderr: `action \"${actionId}\" failed: ${message}`,\n };\n }\n}\n\nexport default runAction;\n"],"mappings":"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","names":["args","isObject"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/adapters/registry.ts"],"sourcesContent":["/**\n * adapters/registry — single source of truth for the platforms agent-connector\n * targets. Generalized from context-mode's `ADAPTER_REGISTRY` pattern, adapted\n * to our `Adapter` / `AdapterFactory` contract (adapters/spi.ts).\n *\n * In context-mode the same platform set was redeclared in four places (env-var\n * detection, session-dir lookup, the lazy adapter loader, and per-adapter base\n * constructors); adding a platform meant editing all of them and missing one\n * was silent. Here the list lives ONCE below: each platform is one entry with a\n * lazy `load()` thunk that resolves the adapter singleton. Adding a platform is\n * a single new entry — `getFactory` / `loadAdapter` / `allAdapters` and the\n * detection cascade in detect.ts all derive from this list.\n *\n * `load()` returns the module's default export, which every adapter file is\n * required to provide as its singleton (`export default adapter;`). It is a\n * function (not an eager import) so module loading stays lazy: an adapter is\n * only imported when it is actually needed, keeping startup cheap.\n *\n * Order is load-bearing for runtime host detection (detect.ts iterates env\n * markers in registry order): forks MUST precede their parent so a session\n * running inside a derived shell is not misclassified as the parent. For the\n * three Phase-1 adapters this is moot, but the ordering convention is fixed now\n * so later additions (cursor is a VS Code fork, etc.) slot in correctly.\n */\n\nimport type { PlatformId } from \"../core/types.js\";\nimport type { Adapter, AdapterFactory } from \"./spi.js\";\n\n/**\n * Authoritative list of installable platforms. One entry per platform; the\n * `load` thunk lazily imports the adapter module and returns its default-export\n * singleton. To add a platform: drop its `src/adapters/<id>/index.ts` in place\n * (default-exporting an `Adapter`) and add one entry here.\n */\nexport const ADAPTER_REGISTRY: readonly AdapterFactory[] = [\n {\n id: \"claude-code\",\n load: () => import(\"./claude-code/index.js\").then((m) => m.default),\n },\n {\n id: \"codex\",\n load: () => import(\"./codex/index.js\").then((m) => m.default),\n },\n {\n id: \"cursor\",\n load: () => import(\"./cursor/index.js\").then((m) => m.default),\n },\n // vscode-copilot after cursor: cursor is a VS Code fork, so the fork's runtime\n // markers must be checked first during host detection.\n {\n id: \"vscode-copilot\",\n load: () => import(\"./vscode-copilot/index.js\").then((m) => m.default),\n },\n {\n id: \"copilot-cli\",\n load: () => import(\"./copilot-cli/index.js\").then((m) => m.default),\n },\n {\n id: \"gemini-cli\",\n load: () => import(\"./gemini-cli/index.js\").then((m) => m.default),\n },\n {\n id: \"warp\",\n load: () => import(\"./warp/index.js\").then((m) => m.default),\n },\n // ts-plugin paradigm: OpenCode loads a generated plugin module that bridges\n // its in-process events to the universal hook entrypoint.\n {\n id: \"opencode\",\n load: () => import(\"./opencode/index.js\").then((m) => m.default),\n },\n // mimo-code is Xiaomi's MiMoCode (@mimo-ai/cli, bin `mimo`) — an OpenCode FORK\n // (ts-plugin, MCP root key \"mcp\", ~/.config/mimocode/mimocode.json). Grouped\n // beside the OpenCode family whose config dialect + plugin contract it shares;\n // detected via the DISTINCT ~/.config/mimocode dir, so there is no fork-ordering\n // constraint vs opencode (no shared config file to disambiguate).\n {\n id: \"mimo-code\",\n load: () => import(\"./mimo-code/index.js\").then((m) => m.default),\n },\n // kilo-cli is the SQLite-backed OpenCode FORK command-line product (ts-plugin,\n // loads @kilocode/plugin modules registered in kilo.jsonc's \"plugin\" array;\n // MCP root key \"mcp\", ~/.config/kilo/kilo.jsonc). Grouped beside the OpenCode\n // family whose plugin contract + config dialect it shares; distinct host from\n // the \"kilo\" extension so there is no fork-ordering constraint between them.\n {\n id: \"kilo-cli\",\n load: () => import(\"./kilo-cli/index.js\").then((m) => m.default),\n },\n // Wave 1 — mcp-only adapters (no lifecycle hooks; MCP registration only).\n {\n id: \"droid\",\n load: () => import(\"./droid/index.js\").then((m) => m.default),\n },\n {\n id: \"roo-code\",\n load: () => import(\"./roo-code/index.js\").then((m) => m.default),\n },\n // kilo is the Kilo Code VS Code extension (kilocode.kilo-code) — a Roo/Cline\n // fork, so it sits beside roo-code (mcp-only, root key \"mcpServers\", VS Code\n // globalStorage / .kilocode project scope). Distinct host from \"kilo-cli\".\n {\n id: \"kilo\",\n load: () => import(\"./kilo/index.js\").then((m) => m.default),\n },\n // cline is the Cline VS Code extension (saoudrizwan.claude-dev) — the most-\n // installed AI coding extension and the PARENT that roo-code and kilo forked.\n // mcp-only (no hook layer); MCP at the globalStorage cline_mcp_settings.json\n // (\"mcpServers\"); content lives in the .clinerules tree + ~/Documents/Cline.\n // NO runtime-marker collision with roo-code (rooveterinaryinc.roo-cline / .roo)\n // or kilo (kilocode.kilo-code / .kilo) — distinct ext ids + dotdirs — so there\n // is NO fork-before-parent ordering constraint here; it simply sits beside them.\n {\n id: \"cline\",\n load: () => import(\"./cline/index.js\").then((m) => m.default),\n },\n {\n id: \"trae\",\n load: () => import(\"./trae/index.js\").then((m) => m.default),\n },\n // antigravity-cli BEFORE antigravity: the `agy` CLI is a fork of the IDE\n // adapter with its own runtime markers (the universal hook command tags the\n // host as \"antigravity-cli\"), so the more-specific CLI marker must be checked\n // before the IDE/parent during host detection.\n {\n id: \"antigravity-cli\",\n load: () => import(\"./antigravity-cli/index.js\").then((m) => m.default),\n },\n {\n id: \"antigravity\",\n load: () => import(\"./antigravity/index.js\").then((m) => m.default),\n },\n {\n id: \"zed\",\n load: () => import(\"./zed/index.js\").then((m) => m.default),\n },\n {\n id: \"amp\",\n load: () => import(\"./amp/index.js\").then((m) => m.default),\n },\n {\n id: \"codebuff\",\n load: () => import(\"./codebuff/index.js\").then((m) => m.default),\n },\n {\n id: \"mux\",\n load: () => import(\"./mux/index.js\").then((m) => m.default),\n },\n // Pi — mcp-only host with no writable MCP config; drives the Agent Skills\n // surface only (writes <piDir>/skills/<name>/SKILL.md).\n {\n id: \"pi\",\n load: () => import(\"./pi/index.js\").then((m) => m.default),\n },\n // Wave 2 — json-stdio adapters (full hook dispatch via the universal entrypoint).\n // jetbrains-copilot before vscode-copilot is unnecessary (distinct hosts); grouped here.\n {\n id: \"jetbrains-copilot\",\n load: () => import(\"./jetbrains-copilot/index.js\").then((m) => m.default),\n },\n {\n id: \"qwen-code\",\n load: () => import(\"./qwen-code/index.js\").then((m) => m.default),\n },\n {\n id: \"kiro\",\n load: () => import(\"./kiro/index.js\").then((m) => m.default),\n },\n {\n id: \"kimi\",\n load: () => import(\"./kimi/index.js\").then((m) => m.default),\n },\n {\n id: \"crush\",\n load: () => import(\"./crush/index.js\").then((m) => m.default),\n },\n // Wave 3 — json-stdio adapters with YAML config (MCP in YAML; hooks per host).\n {\n id: \"goose\",\n load: () => import(\"./goose/index.js\").then((m) => m.default),\n },\n {\n id: \"hermes\",\n load: () => import(\"./hermes/index.js\").then((m) => m.default),\n },\n // Wave 4 — ts-plugin adapters (generate a bridge module to the universal entrypoint).\n {\n id: \"omp\",\n load: () => import(\"./omp/index.js\").then((m) => m.default),\n },\n // nemoclaw BEFORE openclaw (fork-before-parent convention). NVIDIA NemoClaw\n // wraps OpenClaw and DRIVES the SAME ~/.openclaw/openclaw.json, so a NemoClaw\n // box carries BOTH the ~/.nemoclaw/ and ~/.openclaw/ markers. Exclusivity is\n // enforced at the SOURCE: OpenClawAdapter.detectInstalled BOWS OUT when\n // ~/.nemoclaw/ is present, so the shared config is never double-targeted as two\n // platforms. This ordering is the deterministic tie-break (matching the\n // antigravity-cli/antigravity precedent). nemoclaw extends OpenClawAdapter\n // (id/name/detection overridden), so inherited server/hook registration still\n // lands in the wrapped openclaw.json.\n {\n id: \"nemoclaw\",\n load: () => import(\"./nemoclaw/index.js\").then((m) => m.default),\n },\n {\n id: \"openclaw\",\n load: () => import(\"./openclaw/index.js\").then((m) => m.default),\n },\n // Wave 5 — mcp-only: Amazon Q Developer CLI. JSON MCP config under ~/.aws/amazonq/\n // (user) and .amazonq/ (project); root key \"mcpServers\"; bare stdio entry\n // { command, args, env, timeout? } or remote entry { type: \"http\", url } (no\n // headers) for http. The agent-format hooks layer (cli-agents/*.json) +\n // agents/prompts content surfaces are separate, not-yet-wired surfaces; this\n // adapter installs MCP entries + the .amazonq/rules memory surface.\n {\n id: \"amazon-q\",\n load: () => import(\"./amazon-q/index.js\").then((m) => m.default),\n },\n // Continue (the `cn` terminal agent / Continue.dev, npm @continuedev/cli) —\n // json-stdio (Claude-compatible hooks). MCP config is YAML at ~/.continue/config.yaml (user) and\n // <projectDir>/.continue/config.yaml (project); root key \"mcpServers\" is a\n // YAML ARRAY of { name, command, type?, args?, env?, cwd?, url } entries (NOT a\n // keyed map). Hooks: a Claude-compatible json-stdio layer in settings.json\n // (~/.continue/settings.json — separate from the MCP config.yaml; PR #11029) +\n // nativeHooks for the host-specific events. Distinct ~/.continue marker — no\n // fork-ordering constraint vs any sibling.\n {\n id: \"continue\",\n load: () => import(\"./continue/index.js\").then((m) => m.default),\n },\n // Windsurf (Codeium / Cognition's Cascade agent) — mcp-only. USER/GLOBAL scope\n // ONLY: MCP config is JSON at ~/.codeium/windsurf/mcp_config.json (the docs\n // document no project/workspace path), root key \"mcpServers\" is a Claude-\n // Desktop-style OBJECT map keyed by server name (like cursor). stdio entry\n // { command, args?, env? }; remote entry { serverUrl, headers? } (NOT `url`;\n // no type/disabled). No user-installable hook/plugin layer (GUI editor), so it\n // stays mcp-only paradigm — but content surfaces ARE wired: workflows\n // (.windsurf/workflows + ~/.codeium/windsurf/global_workflows), skills\n // (.windsurf/skills + ~/.codeium/windsurf/skills), and the .windsurf/rules\n // memory surface. Distinct ~/.codeium marker — no fork-ordering constraint.\n {\n id: \"windsurf\",\n load: () => import(\"./windsurf/index.js\").then((m) => m.default),\n },\n];\n\n/** O(1) lookup index, built once at module-load time. */\nconst REGISTRY_BY_ID: ReadonlyMap<PlatformId, AdapterFactory> = new Map(\n ADAPTER_REGISTRY.map((factory) => [factory.id, factory] as const),\n);\n\n/** Every platform id present in the registry (useful for matrix tests). */\nexport const REGISTERED_PLATFORM_IDS: ReadonlySet<PlatformId> = new Set(\n ADAPTER_REGISTRY.map((factory) => factory.id),\n);\n\n/**\n * Look up the lazy factory for a platform id. Returns `undefined` for ids that\n * are not registered (including `\"unknown\"` and typos) so callers can fall back\n * deliberately rather than crash.\n */\nexport function getFactory(id: PlatformId | string): AdapterFactory | undefined {\n return REGISTRY_BY_ID.get(id as PlatformId);\n}\n\n/**\n * Resolve a platform id to its adapter singleton. Returns `undefined` when the\n * id is not registered — callers decide whether to skip or fall back.\n */\nexport async function loadAdapter(id: PlatformId | string): Promise<Adapter | undefined> {\n const factory = getFactory(id);\n return factory ? factory.load() : undefined;\n}\n\n/**\n * Load every registered adapter. Imports run in parallel; the result preserves\n * registry order so downstream detection/install logic sees forks before\n * parents.\n */\nexport async function allAdapters(): Promise<Adapter[]> {\n return Promise.all(ADAPTER_REGISTRY.map((factory) => factory.load()));\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/spawn.ts"],"sourcesContent":["/**\n * core/spawn — cross-platform command construction.\n *\n * Borrowed from context-mode (issues #369/#372/#548/#738): bare `node` is\n * unreliable on Windows Git Bash (MSYS) and MSYS rewrites absolute paths on\n * non-C: drives. Always use the resolved runtime path, forward slashes, and\n * double-quoting. No-ops on macOS/Linux.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport type { InstallScope, PlatformId, ServerDef } from \"./types.js\";\nimport type { InstallContext } from \"../adapters/spi.js\";\nimport type {\n LaunchMethod,\n TelemetryInstallScope,\n} from \"../telemetry/types.js\";\n\n/**\n * Narrow the framework's 5-value {@link InstallScope} down to the two telemetry\n * slicing buckets: only a `project`-local install is `project`; everything else\n * (system/user/profile/managed) is global and reads as `user`.\n */\nexport function narrowInstallScope(scope: InstallScope): TelemetryInstallScope {\n return scope === \"project\" ? \"project\" : \"user\";\n}\n\n/** Build `\"<nodePath>\" \"<scriptPath>\"`. */\nexport function buildNodeCommand(\n scriptPath: string,\n opts?: { nodePath?: string },\n): string {\n const nodePath = (opts?.nodePath ?? process.execPath).replace(/\\\\/g, \"/\");\n const safe = scriptPath.replace(/\\\\/g, \"/\");\n return `\"${nodePath}\" \"${safe}\"`;\n}\n\n/**\n * Strict inverse of buildNodeCommand. Returns the two quoted tokens, or null if\n * `cmd` was not produced by buildNodeCommand (no fragile last-whitespace tail\n * grabbing — that was the #548 doubled-path bug when paths contained spaces).\n */\nexport function parseNodeCommand(\n cmd: string,\n): { nodePath: string; scriptPath: string } | null {\n if (typeof cmd !== \"string\" || cmd.length === 0) return null;\n const m = cmd.match(/^\"([^\"]+)\"\\s+\"([^\"]+)\"\\s*$/);\n if (!m || !m[1] || !m[2]) return null;\n return { nodePath: m[1], scriptPath: m[2] };\n}\n\n/** Quote a single argument for inclusion in a host hook command string. */\nexport function quoteArg(arg: string): string {\n return `\"${arg.replace(/\\\\/g, \"/\")}\"`;\n}\n\n/**\n * True when `hay` (slash-normalized) has the quoted home-bin path IMMEDIATELY\n * followed by `verb` — i.e. the verb sits in its command SLOT (right after the\n * home binary), not merely somewhere in the argument list. This distinguishes\n * `\"<bin>\" statusline …` from `\"<bin>\" action … statusline …`: the action verb\n * takes a free-form `actionId` positional that can legitimately equal another\n * verb's name (`statusline` / `usage-event` / `hook`), and only the SLOT\n * position identifies the real verb. `homeBinNorm` is the slash-normalized\n * home-bin path the caller already derived.\n */\nfunction hasVerbSlot(hay: string, homeBinNorm: string, verb: string): boolean {\n return hay.includes(`\"${homeBinNorm}\" ${verb} `);\n}\n\n/**\n * Build the universal hook command a host config points at:\n * \"<homeBin>\" hook <platformId> <event> --connector <id>\n * Pointing every host at the one stable home binary is how a single update\n * propagates everywhere (docs/ARCHITECTURE.md §3 R1).\n */\nexport function buildHomeBinHookCommand(\n homeBinPath: string,\n platformId: string,\n event: string,\n connectorId: string,\n): string {\n return `${quoteArg(homeBinPath)} hook ${platformId} ${event} --connector ${connectorId}`;\n}\n\n/**\n * True when `command` is a home-bin hook command for exactly `connectorId`.\n *\n * Critical: the connector id is the LAST token of the hook command\n * (`... --connector <id>`), so a naive `command.includes(\"--connector \" + id)`\n * collides on shared-prefix ids — `--connector acme-db` contains\n * `--connector acme`, which would let uninstalling `acme` strip `acme-db`'s\n * hooks. We anchor the id token: the character after it must be end-of-string,\n * whitespace, or a closing double-quote (the JSON-embedded case). Connector ids\n * are kebab-case (ID_RE) so they never contain whitespace or quotes themselves.\n */\nexport function isHomeBinHookCommand(\n command: string | undefined,\n homeBinPath: string,\n connectorId: string,\n): boolean {\n if (!command) return false;\n // The stored command was forward-slashed by quoteArg(); homeBinPath() yields\n // NATIVE (back)slashes on Windows (node:path join). Normalize BOTH sides so the\n // ownership substring test holds on win32 (without this, detection always\n // returns false there → duplicate hooks on re-install + orphans on uninstall).\n // No-op on POSIX.\n const hay = command.replace(/\\\\/g, \"/\");\n if (!hay.includes(homeBinPath.replace(/\\\\/g, \"/\"))) return false;\n const token = `--connector ${connectorId}`;\n let from = 0;\n for (;;) {\n const idx = hay.indexOf(token, from);\n if (idx < 0) return false;\n const after = hay.charAt(idx + token.length);\n if (after === \"\" || after === '\"' || /\\s/.test(after)) return true;\n from = idx + token.length;\n }\n}\n\n/**\n * Build the OPT-IN host-native usage-event command an AfterModel / PostInvocation\n * hook points at:\n * \"<homeBin>\" usage-event <platformId> --connector <id>\n * Mirrors {@link buildHomeBinHookCommand} (same anchoring rules apply) but routes\n * to the hidden `usage-event` entrypoint, which records a DISTINCT `model_turn`\n * row instead of dispatching a connector handler.\n */\nexport function buildUsageEventCommand(\n homeBinPath: string,\n platformId: string,\n connectorId: string,\n): string {\n return `${quoteArg(homeBinPath)} usage-event ${platformId} --connector ${connectorId}`;\n}\n\n/**\n * True when `command` is OUR host-native usage-event command for exactly\n * `connectorId`. Same end-of-token anchoring as {@link isHomeBinHookCommand} so a\n * shared-prefix id can't collide; additionally requires the ` usage-event ` verb\n * so it is never confused with a plain `hook` command during uninstall.\n */\nexport function isUsageEventCommand(\n command: string | undefined,\n homeBinPath: string,\n connectorId: string,\n): boolean {\n if (!command) return false;\n // Normalize separators like isHomeBinHookCommand (win32 ownership detection).\n const hay = command.replace(/\\\\/g, \"/\");\n const homeBinNorm = homeBinPath.replace(/\\\\/g, \"/\");\n if (!hay.includes(homeBinNorm)) return false;\n if (!hasVerbSlot(hay, homeBinNorm, \"usage-event\")) return false;\n return isHomeBinHookCommand(command, homeBinPath, connectorId);\n}\n\n/**\n * Build the home-bin statusline command a host's status line config points at:\n * \"<homeBin>\" statusline <platformId> --connector <id>\n * Mirrors {@link buildHomeBinHookCommand} / {@link buildUsageEventCommand} (the\n * same single-home-binary indirection) but routes to the `statusline`\n * entrypoint, which renders the connector's HUD line for the host.\n */\nexport function buildHomeBinStatuslineCommand(\n homeBinPath: string,\n platformId: string,\n connectorId: string,\n): string {\n return `${quoteArg(homeBinPath)} statusline ${platformId} --connector ${connectorId}`;\n}\n\n/**\n * True when `command` is OUR home-bin statusline command for exactly\n * `connectorId`. Same end-of-token anchoring as {@link isHomeBinHookCommand} so a\n * shared-prefix id can't collide; additionally requires the ` statusline ` verb\n * so it is never confused with a plain `hook` / `usage-event` command.\n */\nexport function isHomeBinStatuslineCommand(\n command: string | undefined,\n homeBinPath: string,\n connectorId: string,\n): boolean {\n if (!command) return false;\n // Normalize separators like isHomeBinHookCommand (win32 ownership detection).\n const hay = command.replace(/\\\\/g, \"/\");\n const homeBinNorm = homeBinPath.replace(/\\\\/g, \"/\");\n if (!hay.includes(homeBinNorm)) return false;\n if (!hasVerbSlot(hay, homeBinNorm, \"statusline\")) return false;\n return isHomeBinHookCommand(command, homeBinPath, connectorId);\n}\n\n/**\n * Build the home-bin action command a future host affordance (slash command /\n * keybinding) points at:\n * \"<homeBin>\" action <platformId> <actionId> --connector <id>\n * Mirrors {@link buildHomeBinStatuslineCommand} (the same single-home-binary\n * indirection) but routes to the `action` entrypoint, which re-imports the\n * connector and runs the named action's run(ctx). v1 ships only this command\n * builder + the runtime verb; no adapter EMITS the affordance yet.\n */\nexport function buildHomeBinActionCommand(\n homeBinPath: string,\n platformId: string,\n actionId: string,\n connectorId: string,\n): string {\n return `${quoteArg(homeBinPath)} action ${platformId} ${actionId} --connector ${connectorId}`;\n}\n\n/**\n * True when `command` is OUR home-bin action command for exactly `connectorId`.\n * Same end-of-token anchoring as {@link isHomeBinHookCommand} so a shared-prefix\n * id can't collide; additionally requires the ` action ` verb so it is never\n * confused with a plain `hook` / `usage-event` / `statusline` command.\n */\nexport function isHomeBinActionCommand(\n command: string | undefined,\n homeBinPath: string,\n connectorId: string,\n): boolean {\n if (!command) return false;\n // Normalize separators like isHomeBinHookCommand (win32 ownership detection).\n const hay = command.replace(/\\\\/g, \"/\");\n const homeBinNorm = homeBinPath.replace(/\\\\/g, \"/\");\n if (!hay.includes(homeBinNorm)) return false;\n if (!hasVerbSlot(hay, homeBinNorm, \"action\")) return false;\n return isHomeBinHookCommand(command, homeBinPath, connectorId);\n}\n\n/**\n * Single source of truth for \"is OPT-IN host-native turn-usage capture enabled\n * for this connector?\" — read by the Gemini / Antigravity adapters at install\n * time to decide whether to ALSO write the AfterModel / PostInvocation usage hook.\n * Enabled when the connector opts in via telemetry.hostNativeUsage OR when the\n * install-time env switch AGENT_CONNECTOR_HOST_NATIVE=1 forces it on. Off by\n * default (privacy: host-native capture is never installed silently).\n */\nexport function isHostNativeUsageEnabled(\n telemetry: { enabled: boolean; hostNativeUsage?: boolean },\n env: NodeJS.ProcessEnv = process.env,\n): boolean {\n if (telemetry.enabled !== true) return false;\n if (env.AGENT_CONNECTOR_HOST_NATIVE === \"1\") return true;\n return telemetry.hostNativeUsage === true;\n}\n\n/**\n * Single source of truth for \"should this server be wrapped by `serve` for\n * telemetry?\" — so every adapter behaves identically even for a server that\n * skipped normalizeServer (e.g. a per-platform override). On by default for an\n * stdio server with a command, unless explicitly disabled or telemetry is off.\n */\nexport function shouldWrapForTelemetry(\n server: ServerDef,\n telemetry: { enabled: boolean },\n): boolean {\n return (\n server.wrapForTelemetry !== false &&\n telemetry.enabled === true &&\n server.transport === \"stdio\" &&\n typeof server.command === \"string\" &&\n server.command !== \"\"\n );\n}\n\n/**\n * Build the telemetry-wrapping server command:\n * \"<homeBin>\" serve --connector <id> --scope <scope> --host <platformId> -- <realCommand> <realArgs...>\n * Used when a stdio server opts into transparent telemetry capture.\n *\n * `scope` records the install dimension (global user vs project-local) on every\n * telemetry row so usage can be sliced by it later. It is OPTIONAL for backward\n * compatibility: when omitted, the `--scope` flag is not emitted and the runtime\n * treats the scope as \"unknown\".\n *\n * `platformId` bakes the install TARGET platform into the wrapper so the proxy\n * stamps `hostPlatform` correctly even under a headless spawn where runtime env\n * markers are absent (detectRuntimeHost only knows claude-code/cursor/codex and\n * otherwise mis-attributes). Emitted as `--host <platformId>` in the FLAG\n * section (before `--`). It is OPTIONAL + backward-compatible: when omitted the\n * `--host` flag is not emitted and the runtime falls back to env detection.\n */\nexport function buildServeWrapperCommand(\n homeBinPath: string,\n connectorId: string,\n realCommand: string,\n realArgs: string[],\n scope?: InstallScope,\n platformId?: PlatformId,\n): { command: string; args: string[] } {\n const flags = [\"serve\", \"--connector\", connectorId];\n if (scope !== undefined) flags.push(\"--scope\", narrowInstallScope(scope));\n if (platformId !== undefined) flags.push(\"--host\", platformId);\n return {\n command: homeBinPath,\n args: [...flags, \"--\", realCommand, ...realArgs],\n };\n}\n\n/**\n * Telemetry serve-wrap for a stdio command: when the connector opts in, route\n * `command`/`args` through `<homeBin> serve --connector <id> -- …`; otherwise\n * return them unchanged. Consolidates the per-host wrap snippet — the caller\n * keeps its own command/args seeding + downstream env-resolution + entry shaping.\n */\nexport function buildWrappedStdio(\n ctx: Pick<InstallContext, \"homeBinPath\" | \"connector\" | \"scope\">,\n server: ServerDef,\n platformId: PlatformId,\n command: string,\n args: string[],\n): { command: string; args: string[] } {\n if (!shouldWrapForTelemetry(server, ctx.connector.telemetry)) {\n return { command, args };\n }\n return buildServeWrapperCommand(\n ctx.homeBinPath,\n ctx.connector.id,\n command,\n args,\n ctx.scope,\n platformId,\n );\n}\n\n/** Injectable deps for {@link resolveSpawnCommand} (so the win32 branch is unit-testable on POSIX). */\nexport interface SpawnResolveDeps {\n platform?: NodeJS.Platform;\n /** PATH value (`;`-separated on Windows). */\n pathEnv?: string;\n /** PATHEXT value (`;`-separated). */\n pathExt?: string;\n /** File-existence probe (defaults to fs.existsSync). */\n exists?: (p: string) => boolean;\n}\n\n/** How a child command should be handed to spawn() on this platform. */\nexport interface SpawnResolution {\n /** The command to pass to spawn() (an absolute path on win32 when resolved). */\n file: string;\n /**\n * Whether spawn() MUST use `shell: true`. On native Windows a `.cmd`/`.bat`\n * shim (npx.cmd, pnpm.cmd, the agent-connector.cmd launcher) cannot be run by\n * raw CreateProcess — Node throws EINVAL since the 2024 security fix unless a\n * shell is used. `.exe` resolves directly with no shell.\n */\n needsShell: boolean;\n}\n\n/**\n * Resolve a child command for spawn() across platforms. NO-OP on macOS/Linux\n * (returns the command unchanged, no shell). On native Windows it fixes the two\n * spawn failure modes for bare package runners:\n * 1. raw CreateProcess ignores PATHEXT, so spawn(\"npx\") → ENOENT even though\n * `npx.cmd` is on PATH. We search PATH × PATHEXT and return the resolved\n * absolute path.\n * 2. a resolved `.cmd`/`.bat` still cannot be launched without a shell, so we\n * flag `needsShell` for those (and `.exe`/`.com` run directly).\n * A bare name that PATH search misses falls back to `{ file: command,\n * needsShell: true }` so cmd.exe's own PATHEXT lookup still finds it.\n */\nexport function resolveSpawnCommand(\n command: string,\n deps: SpawnResolveDeps = {},\n): SpawnResolution {\n const platform = deps.platform ?? process.platform;\n if (platform !== \"win32\") return { file: command, needsShell: false };\n\n const isBatch = (s: string): boolean => /\\.(cmd|bat)$/i.test(s);\n\n // Already a path or already has an extension → don't search; only decide shell.\n if (/[\\\\/]/.test(command) || /\\.[a-z0-9]+$/i.test(command)) {\n return { file: command, needsShell: isBatch(command) };\n }\n\n const exists = deps.exists ?? existsSync;\n const pathEnv = deps.pathEnv ?? process.env.PATH ?? process.env.Path ?? \"\";\n const pathExt = deps.pathExt ?? process.env.PATHEXT ?? \".COM;.EXE;.BAT;.CMD\";\n const dirs = pathEnv.split(\";\").filter((d) => d !== \"\");\n const exts = pathExt.split(\";\").filter((e) => e !== \"\");\n for (const dir of dirs) {\n for (const ext of exts) {\n const candidate = join(dir, command + ext);\n if (exists(candidate)) return { file: candidate, needsShell: isBatch(ext) };\n }\n }\n // Not found on PATH — let cmd.exe resolve it (handles shim dirs we may miss).\n return { file: command, needsShell: true };\n}\n\n/** Basenames (case-insensitive, sans common extensions) of the ephemeral package runners. */\nconst PACKAGE_RUNNERS: Record<string, Extract<LaunchMethod, \"npx\" | \"bunx\" | \"uvx\">> = {\n npx: \"npx\",\n bunx: \"bunx\",\n uvx: \"uvx\",\n};\n\n/** Basenames of language interpreters that launch a local script. */\nconst INTERPRETERS: ReadonlySet<string> = new Set([\"node\", \"bun\", \"deno\"]);\n\n/**\n * Strip a directory prefix and a trailing executable extension to get the bare\n * program name. Tolerates both POSIX and Windows separators (the wrapped command\n * may be an absolute Windows path) and lowercases for case-insensitive matching.\n */\nfunction commandBasename(realCommand: string): string {\n const noDir = realCommand.replace(/\\\\/g, \"/\").split(\"/\").pop() ?? realCommand;\n return noDir.replace(/\\.(exe|cmd|bat|com)$/i, \"\").toLowerCase();\n}\n\n/**\n * Classify how the real MCP server is launched, for the \"launch-method\" slicing\n * dimension. Package runners (npx/bunx/uvx) and interpreters (node/bun/deno) are\n * detected by the command basename. A remote (http) server is not launched\n * locally, so the caller — which alone knows the transport — passes\n * `isRemote: true` to force \"http\". Anything else resolves to \"binary\".\n */\nexport function detectLaunchMethod(\n realCommand: string,\n realArgs: string[],\n opts?: { isRemote?: boolean },\n): LaunchMethod {\n void realArgs; // reserved: args may later refine node-vs-script heuristics\n if (opts?.isRemote === true) return \"http\";\n if (typeof realCommand !== \"string\" || realCommand.trim() === \"\") {\n return \"unknown\";\n }\n const base = commandBasename(realCommand);\n if (base === \"\") return \"unknown\";\n const runner = PACKAGE_RUNNERS[base];\n if (runner !== undefined) return runner;\n if (INTERPRETERS.has(base)) return \"node\";\n return \"binary\";\n}\n"],"mappings":";;;AASA,SAAS,kBAAkB;AAC3B,SAAS,YAAY;AAcd,SAAS,mBAAmB,OAA4C;AAC7E,SAAO,UAAU,YAAY,YAAY;AAC3C;AA2BO,SAAS,SAAS,KAAqB;AAC5C,SAAO,IAAI,IAAI,QAAQ,OAAO,GAAG,CAAC;AACpC;AAYA,SAAS,YAAY,KAAa,aAAqB,MAAuB;AAC5E,SAAO,IAAI,SAAS,IAAI,WAAW,KAAK,IAAI,GAAG;AACjD;AAQO,SAAS,wBACd,aACA,YACA,OACA,aACQ;AACR,SAAO,GAAG,SAAS,WAAW,CAAC,SAAS,UAAU,IAAI,KAAK,gBAAgB,WAAW;AACxF;AAaO,SAAS,qBACd,SACA,aACA,aACS;AACT,MAAI,CAAC,QAAS,QAAO;AAMrB,QAAM,MAAM,QAAQ,QAAQ,OAAO,GAAG;AACtC,MAAI,CAAC,IAAI,SAAS,YAAY,QAAQ,OAAO,GAAG,CAAC,EAAG,QAAO;AAC3D,QAAM,QAAQ,eAAe,WAAW;AACxC,MAAI,OAAO;AACX,aAAS;AACP,UAAM,MAAM,IAAI,QAAQ,OAAO,IAAI;AACnC,QAAI,MAAM,EAAG,QAAO;AACpB,UAAM,QAAQ,IAAI,OAAO,MAAM,MAAM,MAAM;AAC3C,QAAI,UAAU,MAAM,UAAU,OAAO,KAAK,KAAK,KAAK,EAAG,QAAO;AAC9D,WAAO,MAAM,MAAM;AAAA,EACrB;AACF;AAUO,SAAS,uBACd,aACA,YACA,aACQ;AACR,SAAO,GAAG,SAAS,WAAW,CAAC,gBAAgB,UAAU,gBAAgB,WAAW;AACtF;AAQO,SAAS,oBACd,SACA,aACA,aACS;AACT,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,MAAM,QAAQ,QAAQ,OAAO,GAAG;AACtC,QAAM,cAAc,YAAY,QAAQ,OAAO,GAAG;AAClD,MAAI,CAAC,IAAI,SAAS,WAAW,EAAG,QAAO;AACvC,MAAI,CAAC,YAAY,KAAK,aAAa,aAAa,EAAG,QAAO;AAC1D,SAAO,qBAAqB,SAAS,aAAa,WAAW;AAC/D;AASO,SAAS,8BACd,aACA,YACA,aACQ;AACR,SAAO,GAAG,SAAS,WAAW,CAAC,eAAe,UAAU,gBAAgB,WAAW;AACrF;AAQO,SAAS,2BACd,SACA,aACA,aACS;AACT,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,MAAM,QAAQ,QAAQ,OAAO,GAAG;AACtC,QAAM,cAAc,YAAY,QAAQ,OAAO,GAAG;AAClD,MAAI,CAAC,IAAI,SAAS,WAAW,EAAG,QAAO;AACvC,MAAI,CAAC,YAAY,KAAK,aAAa,YAAY,EAAG,QAAO;AACzD,SAAO,qBAAqB,SAAS,aAAa,WAAW;AAC/D;AAWO,SAAS,0BACd,aACA,YACA,UACA,aACQ;AACR,SAAO,GAAG,SAAS,WAAW,CAAC,WAAW,UAAU,IAAI,QAAQ,gBAAgB,WAAW;AAC7F;AAQO,SAAS,uBACd,SACA,aACA,aACS;AACT,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,MAAM,QAAQ,QAAQ,OAAO,GAAG;AACtC,QAAM,cAAc,YAAY,QAAQ,OAAO,GAAG;AAClD,MAAI,CAAC,IAAI,SAAS,WAAW,EAAG,QAAO;AACvC,MAAI,CAAC,YAAY,KAAK,aAAa,QAAQ,EAAG,QAAO;AACrD,SAAO,qBAAqB,SAAS,aAAa,WAAW;AAC/D;AAUO,SAAS,yBACd,WACA,MAAyB,QAAQ,KACxB;AACT,MAAI,UAAU,YAAY,KAAM,QAAO;AACvC,MAAI,IAAI,gCAAgC,IAAK,QAAO;AACpD,SAAO,UAAU,oBAAoB;AACvC;AAQO,SAAS,uBACd,QACA,WACS;AACT,SACE,OAAO,qBAAqB,SAC5B,UAAU,YAAY,QACtB,OAAO,cAAc,WACrB,OAAO,OAAO,YAAY,YAC1B,OAAO,YAAY;AAEvB;AAmBO,SAAS,yBACd,aACA,aACA,aACA,UACA,OACA,YACqC;AACrC,QAAM,QAAQ,CAAC,SAAS,eAAe,WAAW;AAClD,MAAI,UAAU,OAAW,OAAM,KAAK,WAAW,mBAAmB,KAAK,CAAC;AACxE,MAAI,eAAe,OAAW,OAAM,KAAK,UAAU,UAAU;AAC7D,SAAO;AAAA,IACL,SAAS;AAAA,IACT,MAAM,CAAC,GAAG,OAAO,MAAM,aAAa,GAAG,QAAQ;AAAA,EACjD;AACF;AAQO,SAAS,kBACd,KACA,QACA,YACA,SACA,MACqC;AACrC,MAAI,CAAC,uBAAuB,QAAQ,IAAI,UAAU,SAAS,GAAG;AAC5D,WAAO,EAAE,SAAS,KAAK;AAAA,EACzB;AACA,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,IAAI,UAAU;AAAA,IACd;AAAA,IACA;AAAA,IACA,IAAI;AAAA,IACJ;AAAA,EACF;AACF;AAsCO,SAAS,oBACd,SACA,OAAyB,CAAC,GACT;AACjB,QAAM,WAAW,KAAK,YAAY,QAAQ;AAC1C,MAAI,aAAa,QAAS,QAAO,EAAE,MAAM,SAAS,YAAY,MAAM;AAEpE,QAAM,UAAU,CAAC,MAAuB,gBAAgB,KAAK,CAAC;AAG9D,MAAI,QAAQ,KAAK,OAAO,KAAK,gBAAgB,KAAK,OAAO,GAAG;AAC1D,WAAO,EAAE,MAAM,SAAS,YAAY,QAAQ,OAAO,EAAE;AAAA,EACvD;AAEA,QAAM,SAAS,KAAK,UAAU;AAC9B,QAAM,UAAU,KAAK,WAAW,QAAQ,IAAI,QAAQ,QAAQ,IAAI,QAAQ;AACxE,QAAM,UAAU,KAAK,WAAW,QAAQ,IAAI,WAAW;AACvD,QAAM,OAAO,QAAQ,MAAM,GAAG,EAAE,OAAO,CAAC,MAAM,MAAM,EAAE;AACtD,QAAM,OAAO,QAAQ,MAAM,GAAG,EAAE,OAAO,CAAC,MAAM,MAAM,EAAE;AACtD,aAAW,OAAO,MAAM;AACtB,eAAW,OAAO,MAAM;AACtB,YAAM,YAAY,KAAK,KAAK,UAAU,GAAG;AACzC,UAAI,OAAO,SAAS,EAAG,QAAO,EAAE,MAAM,WAAW,YAAY,QAAQ,GAAG,EAAE;AAAA,IAC5E;AAAA,EACF;AAEA,SAAO,EAAE,MAAM,SAAS,YAAY,KAAK;AAC3C;AAGA,IAAM,kBAAiF;AAAA,EACrF,KAAK;AAAA,EACL,MAAM;AAAA,EACN,KAAK;AACP;AAGA,IAAM,eAAoC,oBAAI,IAAI,CAAC,QAAQ,OAAO,MAAM,CAAC;AAOzE,SAAS,gBAAgB,aAA6B;AACpD,QAAM,QAAQ,YAAY,QAAQ,OAAO,GAAG,EAAE,MAAM,GAAG,EAAE,IAAI,KAAK;AAClE,SAAO,MAAM,QAAQ,yBAAyB,EAAE,EAAE,YAAY;AAChE;AASO,SAAS,mBACd,aACA,UACA,MACc;AACd,OAAK;AACL,MAAI,MAAM,aAAa,KAAM,QAAO;AACpC,MAAI,OAAO,gBAAgB,YAAY,YAAY,KAAK,MAAM,IAAI;AAChE,WAAO;AAAA,EACT;AACA,QAAM,OAAO,gBAAgB,WAAW;AACxC,MAAI,SAAS,GAAI,QAAO;AACxB,QAAM,SAAS,gBAAgB,IAAI;AACnC,MAAI,WAAW,OAAW,QAAO;AACjC,MAAI,aAAa,IAAI,IAAI,EAAG,QAAO;AACnC,SAAO;AACT;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/adapters/detect.ts"],"sourcesContent":["/**\n * adapters/detect — two complementary detection answers.\n *\n * 1. detectInstalledPlatforms(projectDir): which hosts are INSTALLED on this\n * machine (probe each adapter's config dirs / marker files). Drives the\n * install planner (\"auto\" target expansion, `doctor`).\n *\n * 2. detectRuntimeHost(env): which host is EXECUTING right now (read env\n * markers the host runtime injects into its child processes). Drives the\n * universal hook entrypoint — it must know which adapter's wire format the\n * stdin payload is in before it can parse it.\n *\n * Both derive their platform set from `ADAPTER_REGISTRY` (the single source of\n * truth in registry.ts), generalizing context-mode's detection cascade\n * (env-var tier → config-dir tier → low-confidence fallback) to our\n * Adapter/AdapterFactory contract. The config-dir tier is delegated to each\n * adapter's `detectInstalled()` rather than duplicated here, so adding a\n * platform never requires editing this file.\n */\n\nimport type { DetectedPlatform, DetectionSignal, PlatformId } from \"../core/types.js\";\nimport { ADAPTER_REGISTRY, loadAdapter } from \"./registry.js\";\n\n/**\n * Detect every platform installed on this machine.\n *\n * Loads each registered adapter and calls its `detectInstalled(projectDir)`\n * (which probes the platform's native config dirs + marker files), returning\n * only those reported `installed === true`, in registry order. Adapters never\n * throw from detection, but we guard each call so one misbehaving adapter\n * cannot abort the whole probe.\n *\n * @param projectDir Resolved project root — lets project-scoped adapters look\n * for `<projectDir>/.mcp.json`, `<projectDir>/.cursor`, etc.\n */\nexport async function detectInstalledPlatforms(\n projectDir: string,\n): Promise<DetectedPlatform[]> {\n const adapters = await Promise.all(\n ADAPTER_REGISTRY.map(async (factory) => {\n try {\n return await factory.load();\n } catch {\n return undefined;\n }\n }),\n );\n\n const detected: DetectedPlatform[] = [];\n for (const adapter of adapters) {\n if (!adapter) continue;\n try {\n const result = adapter.detectInstalled(projectDir);\n if (result.installed) detected.push(result);\n } catch {\n // A single adapter's detection failure must not sink the whole probe.\n }\n }\n return detected;\n}\n\n/**\n * One env-marker rule for runtime-host detection. `vars` is checked in order;\n * the FIRST rule with any non-empty matching env var wins, so the table order\n * is the detection precedence (forks before parents). Each var is documented at\n * the rule so the source of the marker is auditable.\n */\ninterface RuntimeSignalRule {\n readonly platform: PlatformId;\n /** Env var names that prove \"this host is executing me\". */\n readonly vars: readonly string[];\n /** Human-readable note (printed in the DetectionSignal.reason). */\n readonly note: string;\n}\n\n/**\n * Ordered env-marker table. Forks BEFORE parents (cursor — a VS Code fork —\n * precedes any future vscode-copilot entry so a Cursor session inside a\n * VS Code-derived shell is not misclassified). Markers are verified against\n * each host's source:\n *\n * - claude-code: CLAUDE_CODE_ENTRYPOINT is set on every Claude Code session;\n * CLAUDE_PLUGIN_ROOT is set when a plugin is loaded. Both are CC-exclusive\n * and serve as the disambiguators when CC runs inside another IDE's shell.\n * - codex: CODEX_THREAD_ID is set per exec (codex-rs/core exec_env);\n * CODEX_CI is set in CI mode (unified_exec process_manager).\n * - cursor: CURSOR_TRACE_ID is the widely-observed Cursor marker (Cursor\n * CLI / agent); CURSOR_CLI marks the Cursor terminal; CURSOR_CWD is the\n * documented workspace var.\n */\nconst RUNTIME_SIGNALS: readonly RuntimeSignalRule[] = [\n {\n platform: \"claude-code\",\n vars: [\"CLAUDE_CODE_ENTRYPOINT\", \"CLAUDE_PLUGIN_ROOT\", \"CLAUDE_PROJECT_DIR\", \"CLAUDE_SESSION_ID\"],\n note: \"Claude Code env marker set\",\n },\n {\n platform: \"cursor\",\n vars: [\"CURSOR_TRACE_ID\", \"CURSOR_CLI\", \"CURSOR_CWD\"],\n note: \"Cursor env marker set\",\n },\n {\n platform: \"codex\",\n vars: [\"CODEX_THREAD_ID\", \"CODEX_CI\"],\n note: \"Codex env marker set\",\n },\n];\n\n/**\n * Identify which host runtime is executing the current process from environment\n * markers. High confidence on an env-marker hit; otherwise an explicit\n * `AGENT_CONNECTOR_PLATFORM` override (high confidence, validated against the\n * registry) is honored; failing both, returns `unknown` at low confidence so\n * the caller can decide on a safe default.\n *\n * Pure with respect to its `env` argument (defaults to `process.env`) so it is\n * trivially testable — pass a synthetic env to assert each rule.\n */\nexport function detectRuntimeHost(env: NodeJS.ProcessEnv = process.env): DetectionSignal {\n // ── Explicit override (highest priority, validated against the registry) ──\n const override = env.AGENT_CONNECTOR_PLATFORM;\n if (override && override.trim() !== \"\") {\n if (REGISTERED_RUNTIME_IDS.has(override as PlatformId)) {\n return {\n platform: override as PlatformId,\n confidence: \"high\",\n reason: `AGENT_CONNECTOR_PLATFORM=${override} override`,\n };\n }\n }\n\n // ── Env-marker tier (forks before parents; first hit wins) ──────────────\n for (const rule of RUNTIME_SIGNALS) {\n const hit = rule.vars.find((name) => {\n const value = env[name];\n return typeof value === \"string\" && value !== \"\";\n });\n if (hit) {\n return {\n platform: rule.platform,\n confidence: \"high\",\n reason: `${rule.note} (${hit})`,\n };\n }\n }\n\n // ── Fallback: no host marker present ────────────────────────────────────\n return {\n platform: \"unknown\",\n confidence: \"low\",\n reason: \"no host runtime env marker detected\",\n };\n}\n\n/** Platform ids the runtime-signal table knows how to detect. */\nconst REGISTERED_RUNTIME_IDS: ReadonlySet<PlatformId> = new Set(\n RUNTIME_SIGNALS.map((rule) => rule.platform),\n);\n\n// Re-export for callers that resolve an adapter straight from a detection\n// result without reaching into registry.ts.\nexport { loadAdapter };\n"],"mappings":";;;;;;AAmCA,eAAsB,yBACpB,YAC6B;AAC7B,QAAM,WAAW,MAAM,QAAQ;AAAA,IAC7B,iBAAiB,IAAI,OAAO,YAAY;AACtC,UAAI;AACF,eAAO,MAAM,QAAQ,KAAK;AAAA,MAC5B,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,WAA+B,CAAC;AACtC,aAAW,WAAW,UAAU;AAC9B,QAAI,CAAC,QAAS;AACd,QAAI;AACF,YAAM,SAAS,QAAQ,gBAAgB,UAAU;AACjD,UAAI,OAAO,UAAW,UAAS,KAAK,MAAM;AAAA,IAC5C,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;AA+BA,IAAM,kBAAgD;AAAA,EACpD;AAAA,IACE,UAAU;AAAA,IACV,MAAM,CAAC,0BAA0B,sBAAsB,sBAAsB,mBAAmB;AAAA,IAChG,MAAM;AAAA,EACR;AAAA,EACA;AAAA,IACE,UAAU;AAAA,IACV,MAAM,CAAC,mBAAmB,cAAc,YAAY;AAAA,IACpD,MAAM;AAAA,EACR;AAAA,EACA;AAAA,IACE,UAAU;AAAA,IACV,MAAM,CAAC,mBAAmB,UAAU;AAAA,IACpC,MAAM;AAAA,EACR;AACF;AAYO,SAAS,kBAAkB,MAAyB,QAAQ,KAAsB;AAEvF,QAAM,WAAW,IAAI;AACrB,MAAI,YAAY,SAAS,KAAK,MAAM,IAAI;AACtC,QAAI,uBAAuB,IAAI,QAAsB,GAAG;AACtD,aAAO;AAAA,QACL,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,QAAQ,4BAA4B,QAAQ;AAAA,MAC9C;AAAA,IACF;AAAA,EACF;AAGA,aAAW,QAAQ,iBAAiB;AAClC,UAAM,MAAM,KAAK,KAAK,KAAK,CAAC,SAAS;AACnC,YAAM,QAAQ,IAAI,IAAI;AACtB,aAAO,OAAO,UAAU,YAAY,UAAU;AAAA,IAChD,CAAC;AACD,QAAI,KAAK;AACP,aAAO;AAAA,QACL,UAAU,KAAK;AAAA,QACf,YAAY;AAAA,QACZ,QAAQ,GAAG,KAAK,IAAI,KAAK,GAAG;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AAGA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,QAAQ;AAAA,EACV;AACF;AAGA,IAAM,yBAAkD,IAAI;AAAA,EAC1D,gBAAgB,IAAI,CAAC,SAAS,KAAK,QAAQ;AAC7C;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/adapters/jetbrains-copilot/index.ts"],"sourcesContent":["/**\n * adapters/jetbrains-copilot — JetBrains Copilot platform adapter for agent-connector.\n *\n * JetBrains Copilot shares the Copilot hook paradigm with VS Code Copilot\n * (Claude-compatible json-stdio), but diverges on MCP registration:\n *\n * - MCP servers: JetBrains stores MCP server registration via the IDE Settings\n * UI (Settings > Tools > GitHub Copilot > MCP > Configure), NOT in any file\n * we can reliably write — the runtime owns the `servers` key behind the UI.\n * So `installServer` writes NOTHING and returns a \"warn\" ChangeRecord telling\n * the user to add the server via the JetBrains MCP settings UI. Writing a\n * bogus file would be ignored at best and corrupt real UI state at worst.\n * `getHealthChecks` surfaces this as a WARN (not FAIL).\n *\n * - Hooks (Copilot Preview hooks): file-based and identical in shape to VS Code\n * Copilot. We write one per-connector file at\n * <projectDir>/.github/hooks/<connector-id>.json shaped as:\n * { \"version\": 1, \"hooks\": { <Event>: [ { \"type\": \"command\", \"command\" } ] } }\n * The top-level `version: 1` is REQUIRED — the Copilot hooks runtime rejects a\n * version-less file and no hooks fire. Each entry is a FLAT { type, command }\n * object (no Claude-style { matcher, hooks:[...] } wrapper). JetBrains parses\n * matchers but IGNORES them — ALL hooks fire on ALL tools — so we omit the\n * matcher entirely rather than persist an advisory one that never applies.\n *\n * - Reply: Claude-compatible JSON on stdout (exit 0), a `hookSpecificOutput`\n * object keyed by the PascalCase `hookEventName` carrying permissionDecision\n * (deny|ask) + permissionDecisionReason and additionalContext. This mirrors\n * vscode-copilot/claude-code exactly EXCEPT JetBrains cannot rewrite tool\n * input (canModifyArgs:false), so a \"modify\" decision degrades to allow.\n *\n * Env interpolation: GitHub Copilot does not document a portable native env\n * token for the hooks file, and the hooks file only ever carries our home-bin\n * hook command (no secrets), so there is nothing to interpolate here. MCP env\n * interpolation is moot because we never write the MCP file.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { dirname, 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 NotificationEvent,\n PlatformCapabilities,\n PlatformId,\n PostToolUseEvent,\n PostCompactEvent,\n PreCompactEvent,\n PreToolUseEvent,\n SessionEndEvent,\n SessionStartEvent,\n StopEvent,\n UserPromptSubmitEvent,\n} from \"../../core/types.js\";\nimport {\n buildHomeBinHookCommand,\n isHomeBinHookCommand,\n} from \"../../core/spawn.js\";\nimport { renderSkillMd } from \"../claude-code/render.js\";\nimport { normalizeSessionSource } from \"../claude-code/wire.js\";\n\nconst HOST: PlatformId = \"jetbrains-copilot\";\n\n/** Top-level version the Copilot hooks runtime requires; a version-less file is rejected. */\nconst JETBRAINS_HOOKS_VERSION = 1;\n\n/**\n * JetBrains Copilot reads PascalCase hook event names from its hooks file —\n * identical to VS Code Copilot / Claude Code. Only the events JetBrains actually\n * delivers are registered; everything else has no Copilot equivalent and is\n * reported as a warn/skip at install time.\n */\nconst EVENT_MAP: Partial<Record<HookEventName, string>> = {\n PreToolUse: \"PreToolUse\",\n PostToolUse: \"PostToolUse\",\n PreCompact: \"PreCompact\",\n SessionStart: \"SessionStart\",\n SessionEnd: \"SessionEnd\",\n UserPromptSubmit: \"UserPromptSubmit\",\n};\n\n/** A single JetBrains Copilot native hook entry — a flat command object. */\ninterface JetBrainsHookEntry {\n type: \"command\";\n command: string;\n}\n\n/** The shape of a JetBrains Copilot .github/hooks/<connector>.json file. */\ninterface JetBrainsHooksFile {\n version?: number;\n hooks?: Record<string, JetBrainsHookEntry[]>;\n}\n\n/** Raw JetBrains Copilot hook stdin payload (Claude-compatible snake_case fields). */\ninterface JetBrainsWireInput {\n session_id?: string;\n transcript_path?: string;\n cwd?: string;\n workspace_roots?: string[];\n hook_event_name?: string;\n\n // tool events. PostToolUse fires ONLY after a tool completes SUCCESSFULLY and\n // sends { tool_name, tool_input, tool_use_id, tool_response } — the VS Code\n // `.github/hooks` dialect this host ALIASES (vscode-copilot), NOT copilot-cli's\n // `tool_result`. `tool_response` is the sole result field; there is NO\n // `tool_output` and NO `error_message`, so those reads are dead here.\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\n stop_hook_active?: boolean;\n // Notification\n message?: string;\n\n /** Injected by the entrypoint so the runtime knows which connector to dispatch. */\n connector?: string;\n}\n\nexport class JetBrainsCopilotAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"JetBrains Copilot\";\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 // JetBrains Copilot's Preview hooks runtime delivers Pre/PostToolUse,\n // PreCompact, SessionStart, SessionEnd, and UserPromptSubmit (GitHub's\n // hooks-reference) — same surface as VS Code Copilot, whose reply contract\n // this adapter mirrors exactly (see formatReply: UserPromptSubmit/PostToolUse\n // deny → top-level {decision:block}). Stop stays unwired (refuted for\n // JetBrains: an unimplemented feature request, not in the documented schema).\n preToolUse: true,\n postToolUse: true,\n preCompact: true,\n sessionStart: true,\n sessionEnd: true,\n userPromptSubmit: true,\n stop: false,\n notification: false,\n // Newer events: the JetBrains Copilot Preview hooks runtime documents no\n // permission-dialog, tool-failure, or subagent lifecycle events, so\n // permissionRequest / postToolUseFailure / subagentStart / subagentStop\n // stay unset — install reports the standard skip-warn for them.\n // Per the JetBrains spec this host is deny/ask-only: a PreToolUse hook\n // CANNOT rewrite tool input, and PostToolUse cannot rewrite tool output.\n canModifyArgs: false,\n canModifyOutput: false,\n canInjectSessionContext: true,\n // MCP is managed via the IDE Settings UI (Settings > Tools > GitHub Copilot\n // > MCP). The UI accepts local stdio servers AND remote Streamable HTTP / SSE\n // servers; AC writes no file, so this list only describes what the UI accepts\n // (install reports a UI-managed warn for every transport).\n transports: [\"stdio\", \"http\", \"sse\"],\n // Content surfaces: JetBrains Copilot consumes the GitHub Copilot .github/\n // files (it has no distinct authoring location), so it is an ALIAS of the\n // vscode-copilot writer for prompt files and Agent Skills. It has no native\n // subagent/chat-mode surface, so subagents stay unsupported (BaseAdapter\n // returns the skip/warn default).\n supportsCommands: true,\n supportsSkills: true,\n supportsSubagents: false,\n // Native passthrough: GitHub's JetBrains-Copilot changelog documents an\n // errorOccurred / ErrorOccurred lifecycle event with NO canonical\n // HookEventName analog (PostToolUseFailure is tool-scoped, not a session-wide\n // error event). A connector reaches it via platforms[\"jetbrains-copilot\"].\n // nativeHooks; installHooks files the event-name key VERBATIM and the generic\n // uninstall reverses it. PascalCase ErrorOccurred matches the adapter's\n // Claude-compatible payload dialect (GitHub hooks-reference accepts both).\n supportsNativeHooks: true,\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n // JetBrains Copilot integration is observable through two markers:\n // • the project hooks tree (<projectDir>/.github/hooks) we write to, and\n // • our per-connector hooks file specifically.\n // There is no reliable user-profile MCP file to probe (the UI owns it), so\n // detection is project-scoped and keyed on the hooks footprint.\n const githubDir = join(projectDir, \".github\");\n const hooksDir = join(githubDir, \"hooks\");\n const installed = existsSync(hooksDir) || existsSync(githubDir);\n const configPath = hooksDir;\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath,\n scope: \"project\",\n reason: installed\n ? `found JetBrains Copilot hooks tree at ${hooksDir}`\n : `no JetBrains Copilot hooks tree at ${hooksDir}`,\n confidence: installed ? \"medium\" : \"low\",\n };\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n /** Hooks live under the workspace .github tree for both scopes. */\n getConfigDir(ctx: InstallContext): string {\n return join(ctx.projectDir, \".github\");\n }\n\n /**\n * MCP server registration has NO writable file on JetBrains — the IDE owns it\n * behind the Settings UI. We still return a stable path (the hooks file) so the\n * base-adapter `doctor`/`backupSettings` helpers have a sensible target rather\n * than a nonexistent/bogus MCP path. `installServer` never writes here.\n */\n getServerConfigPath(ctx: InstallContext): string {\n return this.getHookConfigPath(ctx);\n }\n\n /**\n * Hook registration lives in the workspace-discovered .github/hooks tree, which\n * JetBrains Copilot scans for *.json hook files. We write one file per connector\n * so installs/uninstalls never clobber another connector's hooks. Anchored on\n * projectDir for both scopes — .github/hooks is a workspace concept (there is no\n * user-profile equivalent in the Copilot hooks schema).\n */\n getHookConfigPath(ctx: InstallContext): string {\n return join(ctx.projectDir, \".github\", \"hooks\", `${ctx.connector.id}.json`);\n }\n\n // ── MCP server install / uninstall ───────────────────────────────────────\n\n /**\n * JetBrains MCP registration is UI-only. We never write a file: a bogus file is\n * ignored at best and corrupts real UI-managed state at worst. Emit a \"warn\"\n * ChangeRecord that tells the user exactly where to add the server by hand.\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 jetbrains-copilot\"\n : \"connector declares no MCP server\",\n },\n ];\n }\n\n return [\n {\n platform: this.id,\n action: \"warn\",\n detail:\n `JetBrains Copilot manages MCP servers via the IDE Settings UI — ` +\n `add \"${connector.id}\" manually under Settings > Tools > GitHub Copilot ` +\n `> MCP > Configure (no file is written here).`,\n },\n ];\n }\n\n /**\n * Nothing was written for the MCP server, so there is nothing to remove. Mirror\n * the install-time guidance as a \"warn\" so an uninstall report is honest about\n * the UI-managed entry the user may still want to remove by hand.\n */\n uninstallServer(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (!connector.server || connector.platforms[HOST]?.server === false) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: \"no MCP server was registered for jetbrains-copilot\",\n },\n ];\n }\n return [\n {\n platform: this.id,\n action: \"warn\",\n detail:\n `JetBrains Copilot MCP servers are UI-managed — if \"${connector.id}\" was ` +\n `added manually, remove it under Settings > Tools > GitHub Copilot > MCP.`,\n },\n ];\n }\n\n // ── Hook install / uninstall ─────────────────────────────────────────────\n\n installHooks(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const override = connector.platforms[HOST];\n const hooksDisabled = override?.hooks === false;\n // `hooks: false` disables only the NORMALIZED events; nativeHooks is a\n // sibling, jetbrains-copilot-scoped declaration that installs regardless.\n const normalizedEvents = hooksDisabled ? [] : connector.hookEvents;\n const nativeHooks = override?.nativeHooks ?? {};\n const nativeEvents = Object.keys(nativeHooks);\n\n if (normalizedEvents.length === 0 && nativeEvents.length === 0) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: hooksDisabled\n ? \"hooks disabled for jetbrains-copilot\"\n : \"connector declares no hooks\",\n },\n ];\n }\n\n const hooksPath = this.getHookConfigPath(ctx);\n const symlink = this.symlinkPathWarning(hooksPath);\n if (symlink) return [symlink];\n\n const file = this.readJson<JetBrainsHooksFile>(hooksPath) ?? {};\n const __skip = this.malformedHookRootSkip(hooksPath, (file as Record<string, unknown>).hooks);\n if (__skip) return [__skip];\n const hooks = (file.hooks ??= {});\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const event of normalizedEvents) {\n const jetbrainsEvent = EVENT_MAP[event];\n if (!jetbrainsEvent) {\n // No JetBrains Copilot equivalent for this normalized event — report+skip.\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: hooksPath,\n detail: `${event} has no JetBrains Copilot hook equivalent — skipped`,\n });\n continue;\n }\n\n const command = buildHomeBinHookCommand(ctx.homeBinPath, HOST, event, connector.id);\n // Matchers are IGNORED by JetBrains (all hooks fire on all tools), so we omit\n // the matcher entirely — a flat { type, command } entry.\n const entry: JetBrainsHookEntry = { type: \"command\", command };\n\n const bucket = (hooks[jetbrainsEvent] ??= []);\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.${jetbrainsEvent} 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.${jetbrainsEvent}`,\n });\n } else {\n bucket.push(entry);\n changes.push({\n platform: this.id,\n action: \"create\",\n path: hooksPath,\n detail: `hooks.${jetbrainsEvent}`,\n });\n }\n mutated = true;\n }\n\n // NATIVE passthrough events: jetbrains-copilot-native event-name keys (e.g.\n // ErrorOccurred) filed VERBATIM into the hooks map — no EVENT_MAP, since they\n // ARE Copilot events. Flat { type, command } entry (matchers are ignored);\n // matched by EXACT command so a native key coinciding with a normalized one\n // never clobbers it.\n for (const nativeEvent of nativeEvents) {\n const command = buildHomeBinHookCommand(ctx.homeBinPath, HOST, nativeEvent, connector.id);\n const entry: JetBrainsHookEntry = { type: \"command\", command };\n const bucket = (hooks[nativeEvent] ??= []);\n const existingIdx = bucket.findIndex((e) => e.command === command);\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.${nativeEvent} (native) 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.${nativeEvent} (native)`,\n });\n } else {\n bucket.push(entry);\n changes.push({\n platform: this.id,\n action: \"create\",\n path: hooksPath,\n detail: `hooks.${nativeEvent} (native)`,\n });\n }\n mutated = true;\n }\n\n if (mutated) {\n // The top-level version is REQUIRED — a version-less file is rejected and\n // no hooks fire. Always (re)assert it when we write.\n file.version = JETBRAINS_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 symlink = this.symlinkPathWarning(hooksPath);\n if (symlink) return [symlink];\n\n const file = this.readJson<JetBrainsHooksFile>(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 jetbrainsEvent of Object.keys(hooks)) {\n const bucket = hooks[jetbrainsEvent];\n if (!Array.isArray(bucket)) continue;\n\n const before = bucket.length;\n // Only strip OUR connector's home-bin commands — never another connector's\n // (isHomeBinHookCommand is id-anchored against a shared-prefix collision).\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[jetbrainsEvent] = next;\n else delete hooks[jetbrainsEvent];\n changes.push({\n platform: this.id,\n action: \"remove\",\n path: hooksPath,\n detail: `hooks.${jetbrainsEvent} (${removed})`,\n });\n mutated = true;\n }\n }\n\n if (mutated) {\n // The hooks file is connector-OWNED (<connector-id>.json), so when our\n // strip leaves it with NO hooks we must DELETE the whole file rather than\n // rewrite a `{ \"hooks\": {}, \"version\": 1 }` shell — an empty shell is an\n // orphan per-connector file that lingers after uninstall. A non-empty\n // result still belongs to us, so we rewrite it as before. dryRun reports\n // the would-be remove without mutating the filesystem.\n if (Object.keys(hooks).length === 0) {\n changes.push(\n this.removeManagedFile(\n hooksPath,\n ctx.dryRun,\n \"removed empty connector hooks file\",\n \"no hooks file present\",\n ),\n );\n // Clean up the parent .github/hooks dir only when it is now empty (it is\n // a per-connector tree; leave it in place if other connectors' files\n // remain).\n changes.push(this.removeDirIfEmpty(dirname(hooksPath), ctx.dryRun));\n } else {\n this.writeJson(hooksPath, file, ctx.dryRun);\n }\n }\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 ──────────────────────────────────\n // CONTENT-ONLY: pure native-file writers under the workspace .github/ tree\n // ({prompts,skills}). No runtime dispatch, no home-bin pointer, no telemetry\n // wrap. Each method is idempotent (byte-identical → skip) via\n // BaseAdapter.writeContentFile and reversible via removeContentFile. Honors\n // platforms[\"jetbrains-copilot\"] per-surface false to skip.\n //\n // ALIAS of vscode-copilot: JetBrains consumes the GitHub Copilot .github/\n // files and has no distinct authoring location, so the rendered content +\n // paths here are IDENTICAL to the vscode-copilot writer.\n //\n // SHARED .github TREE: vscode-copilot, copilot-cli, and jetbrains-copilot all\n // write under the SAME project <projectDir>/.github tree. The rendered content\n // is identical and idempotent across those connectors, and uninstall here only\n // removes the files THIS connector declared — never another writer's files.\n //\n // SCOPE NOTE: .github is a workspace concept and this adapter is project-\n // scoped (no user-profile .github authoring location exists in the Copilot\n // prompt/skill discovery), so the content root is always the project .github\n // tree — the same dir getConfigDir already anchors on.\n\n /** Root of the content tree — the project .github tree (see getConfigDir). */\n private contentRootDir(ctx: InstallContext): string {\n return this.getConfigDir(ctx);\n }\n\n private promptsDir(ctx: InstallContext): string {\n return join(this.contentRootDir(ctx), \"prompts\");\n }\n private skillsDir(ctx: InstallContext): string {\n return join(this.contentRootDir(ctx), \"skills\");\n }\n\n /** Native command file path: <ghDir>/prompts/<name>.prompt.md. */\n private commandPath(ctx: InstallContext, name: string): string {\n return join(this.promptsDir(ctx), `${name}.prompt.md`);\n }\n /** Native skill dir: <ghDir>/skills/<name>. */\n private skillDir(ctx: InstallContext, name: string): string {\n return join(this.skillsDir(ctx), name);\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 jetbrains-copilot\" }];\n }\n if (connector.commands.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\n }\n return connector.commands.map((cmd) =>\n this.writeContentFile(\n this.commandPath(ctx, cmd.name),\n this.renderCommand(cmd),\n ctx.dryRun,\n ),\n );\n }\n\n override uninstallCommands(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.commands.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\n }\n return connector.commands.map((cmd) =>\n this.removeContentFile(this.commandPath(ctx, cmd.name), ctx.dryRun),\n );\n }\n\n /** Render a Copilot prompt file: md+frontmatter(description, tools, model, argument-hint). */\n private renderCommand(cmd: CommandDef): string {\n const frontmatter: Record<string, unknown> = {};\n if (cmd.description !== undefined) frontmatter.description = cmd.description;\n // Copilot prompt files express tool access as a `tools` array, sourced from\n // the portable tools.allow policy.\n const allow = cmd.tools?.allow;\n if (allow && allow.length > 0) frontmatter.tools = [...allow];\n if (cmd.model !== undefined) frontmatter.model = cmd.model;\n if (cmd.argumentHint !== undefined) frontmatter[\"argument-hint\"] = cmd.argumentHint;\n if (cmd.extra) Object.assign(frontmatter, cmd.extra);\n return this.renderFrontmatterMd(frontmatter, cmd.prompt);\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 jetbrains-copilot\" }];\n }\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n changes.push(\n this.writeContentFile(join(dir, \"SKILL.md\"), renderSkillMd(skill), ctx.dryRun),\n );\n // Bundle any resource files beside SKILL.md (relative path → contents).\n // Defense-in-depth: skip+warn on any key that escapes the skill dir\n // (config-time validation already rejects these, but never trust input).\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n detail: `skill resource \"${rel}\" escapes the skill dir; skipped`,\n });\n continue;\n }\n changes.push(this.writeContentFile(target, contents, ctx.dryRun));\n }\n }\n return changes;\n }\n\n override uninstallSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n // Remove only the files we wrote (SKILL.md + declared resources), then the\n // skill dir itself when we own its full contents.\n changes.push(this.removeContentFile(join(dir, \"SKILL.md\"), ctx.dryRun));\n for (const rel of Object.keys(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) continue; // never delete outside the skill dir\n changes.push(this.removeContentFile(target, ctx.dryRun));\n }\n // Only remove the skill dir when WE own its full contents — never rm -rf a\n // dir that still holds user-added / sibling-tool / shared files.\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\n }\n return changes;\n }\n\n // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\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 hasServer =\n ctx.connector.server != null &&\n ctx.connector.platforms[HOST]?.server !== false;\n const checks: HealthCheck[] = [\n {\n // MCP cannot be verified from disk — JetBrains owns it behind the UI.\n // BaseAdapter.doctor maps != OK to a hard FAIL, but an unverifiable\n // UI-managed surface must NOT hard-fail doctor (that contradicts the\n // install-time WARN). Return OK with a verify-in-UI detail instead.\n name: `${this.name}: MCP server (UI-managed)`,\n check: () =>\n hasServer\n ? {\n status: \"OK\",\n detail:\n \"MCP is UI-managed — verify in Settings > Tools > GitHub Copilot > MCP\",\n }\n : { status: \"OK\", detail: \"connector declares no MCP server\" },\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<JetBrainsHooksFile>(hooksPath);\n if (!file) return { status: \"FAIL\", detail: `not found: ${hooksPath}` };\n if (file.version !== JETBRAINS_HOOKS_VERSION) {\n return {\n status: \"FAIL\",\n detail: `${hooksPath} missing required \"version\": ${JETBRAINS_HOOKS_VERSION} — Copilot rejects it`,\n };\n }\n const registered = Object.values(file.hooks ?? {}).some((entries) =>\n (entries ?? []).some((e) =>\n isHomeBinHookCommand(e.command, homeBin, connectorId),\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 files this connector\n // declares (skip silently for surfaces it never asked for). Subagents are\n // unsupported here, so they are never checked.\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 return checks;\n }\n\n // ── Runtime: parse JetBrains Copilot stdin JSON → normalized event ────────\n\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\n const input = (raw ?? {}) as JetBrainsWireInput;\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 // PRIMARY SOURCE (VS Code Copilot hooks docs, \"PostToolUse input\"):\n // JetBrains aliases the VS Code `.github/hooks` surface, which fires\n // PostToolUse only after a tool completes SUCCESSFULLY and serializes a\n // single result field, `tool_response`. There is NO `tool_output` and NO\n // `error_message` in this dialect, so the old fallback legs read\n // host-nonexistent fields and the `error_message`-driven `isError` could\n // never become true. Read only `tool_response`; a tool-failure event\n // (PostToolUseFailure) is not part of this surface and is not wired.\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 \"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 \"PostCompact\": {\n // JetBrains Copilot does not fire PostCompact natively (postCompact\n // unset → warn-skip at install). Parsed defensively, mirroring\n // PreCompact, so a manual/mis-routed dispatch normalizes instead of\n // hitting the guard.\n const ev: PostCompactEvent = {\n ...base,\n ...(input.trigger === \"auto\" || input.trigger === \"manual\"\n ? { trigger: input.trigger }\n : {}),\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 \"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 \"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 case \"PostToolUseFailure\":\n case \"SubagentStart\":\n case \"SubagentStop\": {\n // No JetBrains Copilot analog — its Preview hooks runtime documents no\n // permission-dialog, tool-failure, or subagent lifecycle events.\n // Install already skip-warns these via EVENT_MAP; a runtime dispatch is\n // a mis-route — fail loudly.\n throw new Error(`unsupported jetbrains-copilot hook event: ${String(event)}`);\n }\n default: {\n // Exhaustive guard — every HookEventName is handled above. (JetBrains only\n // delivers the four it declares; the rest are handled defensively so a\n // mis-dispatch stays inert rather than crashing.)\n const _never: never = event;\n throw new Error(`unsupported jetbrains-copilot hook event: ${String(_never)}`);\n }\n }\n }\n\n /** Resolve the project dir from the wire payload, preferring the explicit cwd. */\n private getProjectDir(input: JetBrainsWireInput): string | undefined {\n return input.cwd ?? input.workspace_roots?.[0] ?? undefined;\n }\n\n // ── Runtime: normalized response → JetBrains Copilot native 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 // JetBrains Copilot's reply is Claude-compatible, identical to vscode-copilot:\n // `hookSpecificOutput.permissionDecision` is read ONLY for the pre-execution\n // PreToolUse permission event. The post-execution / turn-control events —\n // PostToolUse, UserPromptSubmit, Stop, SubagentStop — block via the TOP-LEVEL\n // {\"decision\":\"block\",\"reason\"} instead (PostToolUse runs AFTER the tool, so a\n // permissionDecision there is silently ignored). Mirrors vscode-copilot #56/#58.\n if (decision === \"deny\") {\n if (\n event === \"PostToolUse\" ||\n event === \"UserPromptSubmit\" ||\n event === \"Stop\" ||\n event === \"SubagentStop\"\n ) {\n return this.stdout({\n decision: \"block\",\n reason: response.reason ?? \"Blocked by hook\",\n });\n }\n return this.stdout({\n hookSpecificOutput: {\n hookEventName,\n permissionDecision: \"deny\",\n permissionDecisionReason: response.reason ?? \"Blocked by hook\",\n },\n });\n }\n\n // ask → prompt the user to confirm.\n if (decision === \"ask\") {\n return this.stdout({\n hookSpecificOutput: {\n hookEventName,\n permissionDecision: \"ask\",\n permissionDecisionReason:\n response.reason ?? \"Confirmation required by hook\",\n },\n });\n }\n\n // modify → unsupported on JetBrains (canModifyArgs:false): a PreToolUse hook\n // cannot rewrite tool input here, so degrade to allow rather than emit an\n // updatedInput the host will ignore.\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 / modify-degradation / unsupported → 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 JetBrains Copilot wire payload. Priority\n * mirrors the Claude-compatible wire: transcript UUID > session_id > \"\" (the\n * framework uses \"\" when no id is available — no ppid fabrication here).\n */\nfunction extractSessionId(input: JetBrainsWireInput): string {\n if (typeof input.transcript_path === \"string\") {\n const m = input.transcript_path.match(/([a-f0-9-]{36})\\.jsonl$/);\n if (m && m[1]) return m[1];\n }\n if (typeof input.session_id === \"string\" && input.session_id !== \"\") {\n return input.session_id;\n }\n return \"\";\n}\n\n/** Coerce a Claude-compatible PostToolUse `tool_response` into a string. */\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 JetBrainsCopilotAdapter();\nexport default adapter;\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/adapters/kiro/index.ts"],"sourcesContent":["/**\n * adapters/kiro — Kiro (AWS) platform adapter for agent-connector.\n *\n * Kiro 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` under `~/.kiro/settings/` (user) or\n * `<projectDir>/.kiro/settings/` (project). The file is JSONC; we WRITE\n * plain JSON (valid JSONC), mirroring the other JSON-config adapters. Root\n * key `mcpServers`; a stdio server is `{ command, args, env }`.\n * Ref: https://kiro.dev/docs/mcp/configuration/\n *\n * 2. Hooks — NOT a settings file but an AGENT file:\n * `~/.kiro/agents/kiro_default.json`. Kiro auto-loads the built-in default\n * agent `kiro_default` for a new chat session, so hooks must register on\n * THAT agent (a file literally named `default.json` would define an inactive\n * custom agent the user must `/agent`-swap to). We merge a `hooks` key into\n * the existing agent JSON, creating a minimal agent object if absent.\n * Ref: kiro.dev/docs/cli/custom-agents/configuration-reference#hooks-field\n *\n * Hook protocol is EXIT-CODE based (unlike Claude's JSON-decision wrapper):\n * - exit 0 → allow the action.\n * - exit 2 → block the action; the reason is written to stderr (PreToolUse).\n * - context injection → exit 0 with the guidance text written as PLAIN STDOUT\n * (NOT a JSON envelope). Kiro adds a hook's STDOUT to the agent's context\n * ONLY for agentSpawn and userPromptSubmit; for preToolUse / postToolUse /\n * stop the docs say STDOUT is \"captured but not shown\" — there is no\n * context channel, so a `context` decision on those degrades to exit 0.\n * Ref: https://kiro.dev/docs/cli/hooks (Hook output / Hook types).\n * Kiro CANNOT rewrite tool arguments or output (exit codes only), so\n * canModifyArgs / canModifyOutput are false; `modify` degrades to allow.\n *\n * Native hook event vocabulary differs from the canonical names and is mapped:\n * PreToolUse → preToolUse\n * PostToolUse → postToolUse\n * SessionStart → agentSpawn (Kiro's session-start equivalent)\n * UserPromptSubmit → userPromptSubmit\n * Stop → stop (documented Kiro hook)\n * Kiro has no equivalent for PreCompact / SessionEnd / Notification; those are\n * reported as a warn/skip at install time.\n *\n * Env handling: Kiro documents no `${env:VAR}` token of the framework's syntax,\n * so env/header/url refs are resolved to literals at install time via\n * resolveEnvRefsDeep — the safe default matching the Gemini/Codex adapters.\n *\n * Grounded in context-mode's proven Kiro adapter (src/adapters/kiro/*).\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 PlatformCapabilities,\n PlatformId,\n PostToolUseEvent,\n PreToolUseEvent,\n ServerDef,\n SessionStartEvent,\n SkillDef,\n StopEvent,\n Transport,\n UserPromptSubmitEvent,\n} from \"../../core/types.js\";\nimport { renderSkillMd } from \"../claude-code/render.js\";\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\nimport {\n buildHomeBinHookCommand,\n buildWrappedStdio,\n isHomeBinHookCommand,\n} from \"../../core/spawn.js\";\nimport { normalizeSessionSource } from \"../claude-code/wire.js\";\n\nconst HOST: PlatformId = \"kiro\";\nconst MCP_ROOT_KEY = \"mcpServers\";\n\n/** The built-in agent Kiro auto-loads for a new chat session. */\nconst DEFAULT_AGENT_FILE = \"kiro_default.json\";\n\n/**\n * Kiro-native hook event names (the keys under an agent file's `hooks` object).\n * Only the events Kiro actually fires for the json-stdio command paradigm.\n */\nconst KIRO_EVENT = {\n preToolUse: \"preToolUse\",\n postToolUse: \"postToolUse\",\n agentSpawn: \"agentSpawn\",\n userPromptSubmit: \"userPromptSubmit\",\n stop: \"stop\",\n} as const;\n\n/**\n * Map canonical event names → Kiro's native hook event names. Only the events\n * Kiro supports are present; PreCompact / SessionEnd / Notification have no Kiro\n * equivalent and are reported as a warn/skip at install time.\n */\nconst EVENT_MAP: Partial<Record<HookEventName, string>> = {\n PreToolUse: KIRO_EVENT.preToolUse,\n PostToolUse: KIRO_EVENT.postToolUse,\n SessionStart: KIRO_EVENT.agentSpawn,\n UserPromptSubmit: KIRO_EVENT.userPromptSubmit,\n Stop: KIRO_EVENT.stop,\n};\n\n/**\n * Kiro events whose hook STDOUT is added to the agent's context: agentSpawn\n * (≈ SessionStart) and userPromptSubmit. For preToolUse / postToolUse / stop the\n * docs say STDOUT is \"captured but not shown to user\" — no context channel — so a\n * `context` decision on those degrades to a plain exit-0 pass-through.\n * Ref: https://kiro.dev/docs/cli/hooks\n */\nconst CONTEXT_EVENTS: ReadonlySet<string> = new Set([\n KIRO_EVENT.agentSpawn,\n KIRO_EVENT.userPromptSubmit,\n]);\n\n/** A single Kiro native hook registration entry (Claude-shaped, nested). */\ninterface KiroHookEntry {\n matcher: string;\n hooks: Array<{ type: \"command\"; command: string }>;\n}\n\n/** The shape of a Kiro agent file (only the parts we touch). */\ninterface KiroAgentFile {\n hooks?: Record<string, KiroHookEntry[]>;\n [key: string]: unknown;\n}\n\n/** The shape of Kiro's mcp.json (only the parts we touch). */\ninterface KiroMcpFile {\n mcpServers?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\n/** Native MCP server entry shapes Kiro accepts under `mcpServers`. */\ninterface KiroStdioServer {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n cwd?: string;\n}\ninterface KiroHttpServer {\n url: string;\n headers?: Record<string, string>;\n}\n\n/**\n * Raw Kiro CLI hook stdin payload (snake_case wire fields).\n *\n * Fields are the ones Kiro ACTUALLY serializes onto a hook's stdin per\n * kiro.dev/docs/cli/hooks. NOTE the stop hook: its stdin is exactly\n * `{ hook_event_name, cwd, session_id, assistant_response }` — there is NO\n * `stop_hook_active` field (Kiro does not model a re-entrant stop-hook flag),\n * so we read `assistant_response` (the agent's last response text) rather than a\n * never-emitted boolean. Ref: kiro.dev/docs/cli/hooks (Stop Hook → Hook Event).\n */\ninterface KiroWireInput {\n connector?: unknown;\n hook_event_name?: string;\n cwd?: string;\n session_id?: string;\n tool_name?: string;\n tool_input?: Record<string, unknown>;\n tool_response?: unknown;\n source?: string;\n prompt?: string;\n /** Stop hook only: the text of the assistant's last response. */\n assistant_response?: string;\n}\n\nexport class KiroAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"Kiro\";\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 — always included, no inclusion modes; user scope →\n // ~/.kiro/steering/agent-connector.md below).\n supportsMemory: true,\n preToolUse: true,\n postToolUse: true,\n preCompact: false,\n sessionStart: true,\n sessionEnd: false,\n // Kiro fires userPromptSubmit and stop, but it has no PreCompact /\n // SessionEnd / Notification equivalent.\n userPromptSubmit: true,\n stop: true,\n notification: false,\n // Newer events: Kiro's native set (agentSpawn / userPromptSubmit /\n // preToolUse / postToolUse / stop) has no permission-dialog, tool-failure,\n // or subagent lifecycle events, so permissionRequest / postToolUseFailure /\n // subagentStart / subagentStop stay unset — install reports the standard\n // skip-warn for them.\n // Kiro's hook protocol is exit-code only — a hook can allow (0), block (2),\n // or inject agentSpawn context, but it CANNOT rewrite tool args or output.\n canModifyArgs: false,\n canModifyOutput: false,\n // agentSpawn (and userPromptSubmit) add the hook's plain STDOUT to context.\n canInjectSessionContext: true,\n transports: [\"stdio\", \"http\"],\n // Skills: Kiro reads SKILL.md from .kiro/skills/<name>/SKILL.md (project)\n // and ~/.kiro/skills/<name>/SKILL.md (user).\n supportsSkills: true,\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userDir = join(homedir(), \".kiro\");\n const userMcp = this.userMcpPath();\n const projectDirKiro = join(projectDir, \".kiro\");\n const projectMcp = this.projectMcpPath(projectDir);\n\n const userInstalled = existsSync(userDir) || existsSync(userMcp);\n const projInstalled = existsSync(projectDirKiro) || existsSync(projectMcp);\n const installed = userInstalled || projInstalled;\n // Report the scope/path that actually matched, so a project-only install\n // isn't misreported as a (non-existent) user install.\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\n const configPath = scope === \"project\" ? projectMcp : userMcp;\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 Kiro config at ${projectMcp}`\n : `found Kiro config under ${userDir}`\n : `no Kiro config at ${userDir}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Memory surface: global steering dir at user scope ───────────────────\n // Project scope stays on the AGENTS.md base default (workspace-root\n // AGENTS.md is always included, with no inclusion modes). User scope targets\n // a dedicated agent-connector.md in Kiro's documented ~/.kiro/steering/ dir\n // (default-always inclusion; AC-created → cleanly deletable on uninstall).\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(), \".kiro\", \"steering\", \"agent-connector.md\"),\n reason: \"kiro global steering dir (~/.kiro/steering; agent-connector-owned file)\",\n },\n ];\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n getConfigDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".kiro\")\n : join(homedir(), \".kiro\");\n }\n\n /** MCP servers live in mcp.json under the scope's `.kiro/settings/`. */\n getServerConfigPath(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? this.projectMcpPath(ctx.projectDir)\n : this.userMcpPath();\n }\n\n /**\n * Hooks live in an AGENT file, NOT a settings file. Kiro auto-loads the\n * built-in default agent (`kiro_default`) for a new chat session, so we always\n * register hooks on the user-scope default agent — that is the agent Kiro\n * actually loads regardless of install scope.\n */\n getHookConfigPath(_ctx: InstallContext): string {\n return join(homedir(), \".kiro\", \"agents\", DEFAULT_AGENT_FILE);\n }\n\n private userMcpPath(): string {\n return join(homedir(), \".kiro\", \"settings\", \"mcp.json\");\n }\n\n private projectMcpPath(projectDir: string): string {\n return join(projectDir, \".kiro\", \"settings\", \"mcp.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 kiro\"\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 Kiro's native mcpServers entry. */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): KiroStdioServer | KiroHttpServer {\n const transport: Transport = server.transport;\n\n if (transport === \"stdio\") {\n let command = server.command ?? \"\";\n let args = [...(server.args ?? [])];\n\n // Transparent telemetry wrapping: route the real command through\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\n ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\n\n // Kiro documents no native interpolation token, so resolve every\n // ${env:VAR} to a literal at install time.\n const entry: KiroStdioServer = { command: resolveEnvRefsDeep(command) };\n if (args.length > 0) entry.args = resolveEnvRefsDeep(args);\n const env = this.renderEnv(server.env);\n if (env) entry.env = env;\n if (server.cwd) entry.cwd = resolveEnvRefsDeep(server.cwd);\n return entry;\n }\n\n // http (and any other remote transport) — Kiro registers a URL.\n const entry: KiroHttpServer = { url: resolveEnvRefsDeep(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. Kiro documents no native interpolation token, so\n * resolve `${env:VAR}` references to literals at install time.\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 // ── Skills surface ───────────────────────────────────────────────────────\n // Kiro reads SKILL.md from:\n // project scope → <projectDir>/.kiro/skills/<name>/SKILL.md\n // user scope → ~/.kiro/skills/<name>/SKILL.md\n\n private skillsDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".kiro\", \"skills\")\n : join(homedir(), \".kiro\", \"skills\");\n }\n\n private skillDir(ctx: InstallContext, name: string): string {\n return join(this.skillsDir(ctx), name);\n }\n\n override installSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.skills === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"skills disabled for kiro\" }];\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 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 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;\n changes.push(this.removeContentFile(target, ctx.dryRun));\n }\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\n }\n return changes;\n }\n\n private renderSkill(skill: SkillDef): string {\n return renderSkillMd(skill);\n }\n\n // ── Hook install / uninstall (merge into the agent file) ─────────────────\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 kiro\" }];\n }\n if (connector.hookEvents.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no hooks\" }];\n }\n\n const agentPath = this.getHookConfigPath(ctx);\n // Merge into the existing agent JSON; create a minimal agent object if absent.\n const agent = this.readJson<KiroAgentFile>(agentPath) ?? {};\n const __skip = this.malformedHookRootSkip(agentPath, (agent as Record<string, unknown>).hooks);\n if (__skip) return [__skip];\n const hooks = (agent.hooks ??= {});\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const event of connector.hookEvents) {\n const kiroEvent = EVENT_MAP[event];\n if (!kiroEvent) {\n // No Kiro equivalent for this canonical event — report and continue.\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: agentPath,\n detail: `${event} has no Kiro 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: KiroHookEntry = {\n matcher,\n hooks: [{ type: \"command\", command }],\n };\n\n const bucket = (hooks[kiroEvent] ??= []);\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: agentPath,\n detail: `hooks.${kiroEvent} already registered`,\n });\n continue;\n }\n bucket[existingIdx] = entry;\n changes.push({\n platform: this.id,\n action: \"update\",\n path: agentPath,\n detail: `hooks.${kiroEvent}`,\n });\n } else {\n bucket.push(entry);\n changes.push({\n platform: this.id,\n action: \"create\",\n path: agentPath,\n detail: `hooks.${kiroEvent}`,\n });\n }\n mutated = true;\n }\n\n if (mutated) this.writeJson(agentPath, agent, ctx.dryRun);\n return changes;\n }\n\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n const agentPath = this.getHookConfigPath(ctx);\n const agent = this.readJson<KiroAgentFile>(agentPath);\n const hooks = agent?.hooks;\n if (!agent || !hooks) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: agentPath,\n detail: \"no hooks section present\",\n },\n ];\n }\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const kiroEvent of Object.keys(hooks)) {\n const bucket = hooks[kiroEvent];\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: KiroHookEntry[] = [];\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[kiroEvent] = next;\n else delete hooks[kiroEvent];\n changes.push({\n platform: this.id,\n action: \"remove\",\n path: agentPath,\n detail: `hooks.${kiroEvent} (${removed})`,\n });\n mutated = true;\n }\n }\n\n if (mutated) this.writeJson(agentPath, agent, ctx.dryRun);\n if (changes.length === 0) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: agentPath,\n detail: \"no matching hook entries\",\n });\n }\n return changes;\n }\n\n private entryHasOurCommand(entry: KiroHookEntry, 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 agentPath = 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 // Only assert what the connector declares (same rule as the hook\n // check below): a server-less connector never writes an mcpServers\n // entry, so its absence is healthy.\n if (!ctx.connector.server) {\n return { status: \"OK\", detail: \"no MCP server declared\" };\n }\n const cfg = this.readJson<KiroMcpFile>(mcpPath);\n const bucket = cfg?.mcpServers;\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 : { status: \"FAIL\", detail: `no ${MCP_ROOT_KEY}.${connectorId} in ${mcpPath}` };\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 agent = this.readJson<KiroAgentFile>(agentPath);\n if (!agent) return { status: \"FAIL\", detail: `cannot read ${agentPath}` };\n const hooks = agent.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 ${agentPath}` };\n },\n },\n ];\n }\n\n // ── Runtime: parse Kiro stdin JSON → normalized event ────────────────────\n\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\n const input = (raw ?? {}) as KiroWireInput;\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 \"SessionStart\": {\n const ev: SessionStartEvent = {\n ...base,\n source: normalizeSessionSource(input.source),\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 // Kiro's stop stdin is EXACTLY { hook_event_name, cwd, session_id,\n // assistant_response } — there is no `stop_hook_active` flag (reading it\n // always yielded undefined), so we read the real `assistant_response`\n // (the agent's last response text) instead and surface it as\n // lastAssistantMessage. Ref: kiro.dev/docs/cli/hooks (Stop Hook Event).\n const ev: StopEvent & { lastAssistantMessage?: string } = {\n ...base,\n ...(typeof input.assistant_response === \"string\"\n ? { lastAssistantMessage: input.assistant_response }\n : {}),\n };\n return ev;\n }\n default: {\n // Kiro never delivers PreCompact / SessionEnd / Notification nor the\n // newer PermissionRequest / PostToolUseFailure / SubagentStart /\n // SubagentStop (no native equivalents). If the runtime dispatches one\n // anyway, surface it loudly rather than silently mis-parse.\n throw new Error(`unsupported kiro hook event: ${String(event)}`);\n }\n }\n }\n\n // ── Runtime: normalized response → Kiro native (exit-code) hook reply ─────\n\n formatReply(event: HookEventName, response: HookResponse): HookReply {\n const decision = response.decision ?? \"allow\";\n\n // deny → block the action: exit 2 with the reason on stderr.\n if (decision === \"deny\") {\n return { exitCode: 2, stderr: response.reason ?? \"Blocked by hook\" };\n }\n\n // ask → Kiro has no native \"ask\"; degrade to deny (exit 2) to stay fail-safe.\n if (decision === \"ask\") {\n return {\n exitCode: 2,\n stderr: response.reason ?? \"Action requires user confirmation (security policy)\",\n };\n }\n\n // Stop → exit-code only (deny already handled above as exit 2). There is no\n // context/additionalContext channel on a Stop hook, so anything non-deny\n // passes through with exit 0 (do not fall into the context branch).\n if (event === \"Stop\") {\n return { exitCode: 0 };\n }\n\n // context → inject soft guidance. Kiro adds a hook's PLAIN STDOUT to the\n // agent's context (no JSON envelope), but ONLY for the agentSpawn and\n // userPromptSubmit events; preToolUse / postToolUse have no context channel\n // (their STDOUT is \"captured but not shown\"). So emit the raw text on stdout\n // only when the FIRING event maps to a context-supporting Kiro event;\n // otherwise the context decision degrades to a plain exit-0 pass-through\n // rather than a mislabeled/ineffective payload. exit 0 = allow.\n // Ref: https://kiro.dev/docs/cli/hooks\n const kiroEvent = EVENT_MAP[event];\n if (\n decision === \"context\" &&\n response.additionalContext &&\n kiroEvent !== undefined &&\n CONTEXT_EVENTS.has(kiroEvent)\n ) {\n return { exitCode: 0, stdout: response.additionalContext };\n }\n\n // modify is unsupported on Kiro (exit-code protocol — cannot rewrite\n // args/output); allow / void → pass through with exit 0.\n return { exitCode: 0 };\n }\n}\n\n/** Coerce a Kiro 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 KiroAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}
@@ -1,17 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- OpenClawAdapter,
4
- adapter,
5
- openclaw_default
6
- } from "./chunk-FUXUEXDP.js";
7
- import "./chunk-BEFVJ2OE.js";
8
- import "./chunk-NUGMVVV2.js";
9
- import "./chunk-TO57WYBB.js";
10
- import "./chunk-ALVXORZM.js";
11
- import "./chunk-2HCJV6UO.js";
12
- export {
13
- OpenClawAdapter,
14
- adapter,
15
- openclaw_default as default
16
- };
17
- //# sourceMappingURL=openclaw-V73XHPXP.js.map