@ken-jo/agent-connector 0.4.6 → 0.4.8

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 (187) hide show
  1. package/dist/{action-EV63GAPY.js → action-RWPRIZIC.js} +10 -10
  2. package/dist/{amazon-q-COAL3764.js → amazon-q-5LJOB5L3.js} +6 -18
  3. package/dist/amazon-q-5LJOB5L3.js.map +1 -0
  4. package/dist/{amp-XJQ4TDAU.js → amp-PU4LFSY6.js} +16 -48
  5. package/dist/amp-PU4LFSY6.js.map +1 -0
  6. package/dist/{antigravity-AMKKKHS4.js → antigravity-DWW35HZO.js} +6 -5
  7. package/dist/{antigravity-cli-XERXEH5W.js → antigravity-cli-VTQ6DNWL.js} +6 -5
  8. package/dist/{antigravity-cli-XERXEH5W.js.map → antigravity-cli-VTQ6DNWL.js.map} +1 -1
  9. package/dist/{chunk-F5RX62T7.js → chunk-7QRUZAUG.js} +2 -2
  10. package/dist/{chunk-G5CQHVQG.js → chunk-7TVBFRVI.js} +12 -15
  11. package/dist/chunk-7TVBFRVI.js.map +1 -0
  12. package/dist/{chunk-QC5A3TFQ.js → chunk-A2T4Q7RM.js} +18 -18
  13. package/dist/{chunk-2X4EH2D7.js → chunk-CDVOBKSG.js} +4 -4
  14. package/dist/{chunk-RQPKL62M.js → chunk-CENEXP7K.js} +9 -38
  15. package/dist/chunk-CENEXP7K.js.map +1 -0
  16. package/dist/chunk-FBJQGRET.js +38 -0
  17. package/dist/chunk-FBJQGRET.js.map +1 -0
  18. package/dist/{chunk-WZA4CSGJ.js → chunk-H53QZQJI.js} +15 -2
  19. package/dist/chunk-H53QZQJI.js.map +1 -0
  20. package/dist/{chunk-DCK5FADX.js → chunk-HOE2MN36.js} +2 -2
  21. package/dist/{chunk-7L6ITC4T.js → chunk-IEGR4TP3.js} +22 -6
  22. package/dist/chunk-IEGR4TP3.js.map +1 -0
  23. package/dist/{chunk-CPLK7GTE.js → chunk-KG6T3YNJ.js} +353 -36
  24. package/dist/chunk-KG6T3YNJ.js.map +1 -0
  25. package/dist/{chunk-MZF2YCXX.js → chunk-MOW2RKHX.js} +2 -2
  26. package/dist/{chunk-EXLS7BSI.js → chunk-NLFPH4S2.js} +10 -2
  27. package/dist/chunk-NLFPH4S2.js.map +1 -0
  28. package/dist/{chunk-EROJDXMW.js → chunk-NYR55UT7.js} +2 -2
  29. package/dist/{chunk-SRVAA2VN.js → chunk-OZ5EXXQV.js} +2 -2
  30. package/dist/{chunk-I5MLE6S7.js → chunk-TO57WYBB.js} +15 -1
  31. package/dist/chunk-TO57WYBB.js.map +1 -0
  32. package/dist/chunk-UM5S7DKK.js +33 -0
  33. package/dist/chunk-UM5S7DKK.js.map +1 -0
  34. package/dist/{chunk-5G4EPJ4Y.js → chunk-VRKTVCYJ.js} +7 -7
  35. package/dist/{chunk-QOGMDOUX.js → chunk-WI6YSXOC.js} +3 -3
  36. package/dist/{chunk-BMD7ANKF.js → chunk-XQUUNAGC.js} +36 -36
  37. package/dist/{chunk-LQRAPXS4.js → chunk-YS2NYJ6R.js} +15 -49
  38. package/dist/chunk-YS2NYJ6R.js.map +1 -0
  39. package/dist/{chunk-H67V7DEL.js → chunk-YYISBXOM.js} +7 -7
  40. package/dist/{claude-code-T2LPFNC3.js → claude-code-64X6RR2S.js} +46 -133
  41. package/dist/claude-code-64X6RR2S.js.map +1 -0
  42. package/dist/cli/sdk.js +4 -4
  43. package/dist/cli.js +1 -1
  44. package/dist/{cline-WRYMNS7Z.js → cline-T7ZDJYZQ.js} +15 -47
  45. package/dist/cline-T7ZDJYZQ.js.map +1 -0
  46. package/dist/{codebuff-PODYPOOP.js → codebuff-PPPY3SJV.js} +9 -40
  47. package/dist/codebuff-PPPY3SJV.js.map +1 -0
  48. package/dist/{codex-O4G7D7KK.js → codex-EEVN43C2.js} +115 -172
  49. package/dist/codex-EEVN43C2.js.map +1 -0
  50. package/dist/{continue-K43SUHLQ.js → continue-VLLZO4PM.js} +12 -33
  51. package/dist/continue-VLLZO4PM.js.map +1 -0
  52. package/dist/{copilot-cli-Q3SSPT4V.js → copilot-cli-A7G5WB4N.js} +17 -64
  53. package/dist/copilot-cli-A7G5WB4N.js.map +1 -0
  54. package/dist/{crush-MBEH2R3I.js → crush-AH24GDDB.js} +17 -42
  55. package/dist/crush-AH24GDDB.js.map +1 -0
  56. package/dist/{cursor-TMBXDYR4.js → cursor-GJBSMXI6.js} +61 -183
  57. package/dist/cursor-GJBSMXI6.js.map +1 -0
  58. package/dist/{detect-AHJIUMBO.js → detect-YDCZNV4W.js} +4 -4
  59. package/dist/{doctor-G5MLCPAB.js → doctor-DGC7P3P7.js} +13 -12
  60. package/dist/{doctor-G5MLCPAB.js.map → doctor-DGC7P3P7.js.map} +1 -1
  61. package/dist/{droid-JC2NT6S4.js → droid-RBWCFKL3.js} +63 -144
  62. package/dist/droid-RBWCFKL3.js.map +1 -0
  63. package/dist/{gemini-cli-ILR7M5X3.js → gemini-cli-CFPFEJEA.js} +20 -63
  64. package/dist/gemini-cli-CFPFEJEA.js.map +1 -0
  65. package/dist/{goose-SFO5BBGW.js → goose-UBJVQFUE.js} +107 -183
  66. package/dist/goose-UBJVQFUE.js.map +1 -0
  67. package/dist/{hermes-3N7WN4WS.js → hermes-6FXGXLNL.js} +41 -83
  68. package/dist/hermes-6FXGXLNL.js.map +1 -0
  69. package/dist/{hook-76JBKTUX.js → hook-CDGSCASQ.js} +10 -10
  70. package/dist/index.js +2 -2
  71. package/dist/{install-R7252QFH.js → install-2D3UKEME.js} +13 -12
  72. package/dist/{install-R7252QFH.js.map → install-2D3UKEME.js.map} +1 -1
  73. package/dist/{jetbrains-copilot-NRZHI5PC.js → jetbrains-copilot-K26KMA3U.js} +12 -37
  74. package/dist/jetbrains-copilot-K26KMA3U.js.map +1 -0
  75. package/dist/{kilo-IX4T3OHJ.js → kilo-BKZJ26RM.js} +26 -90
  76. package/dist/kilo-BKZJ26RM.js.map +1 -0
  77. package/dist/{kilo-cli-2AYCXBQD.js → kilo-cli-6UVWCXQD.js} +17 -48
  78. package/dist/kilo-cli-6UVWCXQD.js.map +1 -0
  79. package/dist/{kimi-2YFK2GBA.js → kimi-QALYPSRR.js} +20 -31
  80. package/dist/kimi-QALYPSRR.js.map +1 -0
  81. package/dist/{kiro-YL6AWUYG.js → kiro-J5J42I5Z.js} +12 -31
  82. package/dist/kiro-J5J42I5Z.js.map +1 -0
  83. package/dist/{leaderboard-V6VWA5ZV.js → leaderboard-VZQXNWTX.js} +2 -2
  84. package/dist/{mimo-code-FTMGSKMQ.js → mimo-code-BEE622P2.js} +22 -87
  85. package/dist/mimo-code-BEE622P2.js.map +1 -0
  86. package/dist/{mux-5XZFB44C.js → mux-5HTNKK4K.js} +10 -54
  87. package/dist/mux-5HTNKK4K.js.map +1 -0
  88. package/dist/{nemoclaw-CQYXZVQN.js → nemoclaw-DNFIZFDF.js} +5 -5
  89. package/dist/{omp-2QMEY6HD.js → omp-I3UTRBNP.js} +16 -48
  90. package/dist/omp-I3UTRBNP.js.map +1 -0
  91. package/dist/{openclaw-UZC437RW.js → openclaw-QE2LMWIF.js} +5 -5
  92. package/dist/{opencode-L4BGFP25.js → opencode-ZFSUYJXI.js} +22 -88
  93. package/dist/opencode-ZFSUYJXI.js.map +1 -0
  94. package/dist/{package-DNLQTPNN.js → package-BSCCMW4E.js} +8 -8
  95. package/dist/{pi-PVVPVWKG.js → pi-H2KBBDDJ.js} +4 -4
  96. package/dist/{qwen-code-G4CXKUHR.js → qwen-code-5LE34FNE.js} +63 -152
  97. package/dist/qwen-code-5LE34FNE.js.map +1 -0
  98. package/dist/{roo-code-67TYJIQR.js → roo-code-XH4GCYIS.js} +15 -52
  99. package/dist/roo-code-XH4GCYIS.js.map +1 -0
  100. package/dist/runtime/index.js +8 -8
  101. package/dist/sdk/index.js +3 -3
  102. package/dist/sdk/test.js +5 -5
  103. package/dist/{serve-EOVWYBGZ.js → serve-MQNGPY2H.js} +10 -10
  104. package/dist/{status-VTD6XXLW.js → status-MRHVRDFY.js} +8 -7
  105. package/dist/{status-VTD6XXLW.js.map → status-MRHVRDFY.js.map} +1 -1
  106. package/dist/{statusline-3ET5YPQ5.js → statusline-IYWA75TR.js} +9 -9
  107. package/dist/{telemetry-QCTMKDBQ.js → telemetry-IONIOMLC.js} +5 -5
  108. package/dist/{trae-7CZZGOGI.js → trae-RVNRSV7X.js} +10 -39
  109. package/dist/trae-RVNRSV7X.js.map +1 -0
  110. package/dist/{uninstall-FL3SH2DT.js → uninstall-ESLSVCLE.js} +13 -12
  111. package/dist/{uninstall-FL3SH2DT.js.map → uninstall-ESLSVCLE.js.map} +1 -1
  112. package/dist/{upgrade-SLFG2FCT.js → upgrade-VICY5T64.js} +13 -12
  113. package/dist/{upgrade-SLFG2FCT.js.map → upgrade-VICY5T64.js.map} +1 -1
  114. package/dist/{usage-IRBLVUZM.js → usage-TCUWV2YZ.js} +2 -2
  115. package/dist/{usage-event-VFF77WYY.js → usage-event-CBZZP37Q.js} +9 -9
  116. package/dist/{vscode-copilot-MF2CDNMT.js → vscode-copilot-B2QBBHJW.js} +17 -65
  117. package/dist/vscode-copilot-B2QBBHJW.js.map +1 -0
  118. package/dist/{warp-VKG55TAT.js → warp-5R54ST3N.js} +7 -19
  119. package/dist/warp-5R54ST3N.js.map +1 -0
  120. package/dist/{windsurf-FU5G4SHF.js → windsurf-L32UEOLY.js} +6 -18
  121. package/dist/windsurf-L32UEOLY.js.map +1 -0
  122. package/dist/{zed-SFUHL3GS.js → zed-FDJHJZKD.js} +11 -21
  123. package/dist/zed-FDJHJZKD.js.map +1 -0
  124. package/package.json +1 -1
  125. package/dist/amazon-q-COAL3764.js.map +0 -1
  126. package/dist/amp-XJQ4TDAU.js.map +0 -1
  127. package/dist/chunk-7L6ITC4T.js.map +0 -1
  128. package/dist/chunk-CPLK7GTE.js.map +0 -1
  129. package/dist/chunk-EXLS7BSI.js.map +0 -1
  130. package/dist/chunk-G5CQHVQG.js.map +0 -1
  131. package/dist/chunk-I5MLE6S7.js.map +0 -1
  132. package/dist/chunk-LQRAPXS4.js.map +0 -1
  133. package/dist/chunk-RQPKL62M.js.map +0 -1
  134. package/dist/chunk-WZA4CSGJ.js.map +0 -1
  135. package/dist/claude-code-T2LPFNC3.js.map +0 -1
  136. package/dist/cline-WRYMNS7Z.js.map +0 -1
  137. package/dist/codebuff-PODYPOOP.js.map +0 -1
  138. package/dist/codex-O4G7D7KK.js.map +0 -1
  139. package/dist/continue-K43SUHLQ.js.map +0 -1
  140. package/dist/copilot-cli-Q3SSPT4V.js.map +0 -1
  141. package/dist/crush-MBEH2R3I.js.map +0 -1
  142. package/dist/cursor-TMBXDYR4.js.map +0 -1
  143. package/dist/droid-JC2NT6S4.js.map +0 -1
  144. package/dist/gemini-cli-ILR7M5X3.js.map +0 -1
  145. package/dist/goose-SFO5BBGW.js.map +0 -1
  146. package/dist/hermes-3N7WN4WS.js.map +0 -1
  147. package/dist/jetbrains-copilot-NRZHI5PC.js.map +0 -1
  148. package/dist/kilo-IX4T3OHJ.js.map +0 -1
  149. package/dist/kilo-cli-2AYCXBQD.js.map +0 -1
  150. package/dist/kimi-2YFK2GBA.js.map +0 -1
  151. package/dist/kiro-YL6AWUYG.js.map +0 -1
  152. package/dist/mimo-code-FTMGSKMQ.js.map +0 -1
  153. package/dist/mux-5XZFB44C.js.map +0 -1
  154. package/dist/omp-2QMEY6HD.js.map +0 -1
  155. package/dist/opencode-L4BGFP25.js.map +0 -1
  156. package/dist/qwen-code-G4CXKUHR.js.map +0 -1
  157. package/dist/roo-code-67TYJIQR.js.map +0 -1
  158. package/dist/trae-7CZZGOGI.js.map +0 -1
  159. package/dist/vscode-copilot-MF2CDNMT.js.map +0 -1
  160. package/dist/warp-VKG55TAT.js.map +0 -1
  161. package/dist/windsurf-FU5G4SHF.js.map +0 -1
  162. package/dist/zed-SFUHL3GS.js.map +0 -1
  163. /package/dist/{action-EV63GAPY.js.map → action-RWPRIZIC.js.map} +0 -0
  164. /package/dist/{antigravity-AMKKKHS4.js.map → antigravity-DWW35HZO.js.map} +0 -0
  165. /package/dist/{chunk-F5RX62T7.js.map → chunk-7QRUZAUG.js.map} +0 -0
  166. /package/dist/{chunk-QC5A3TFQ.js.map → chunk-A2T4Q7RM.js.map} +0 -0
  167. /package/dist/{chunk-2X4EH2D7.js.map → chunk-CDVOBKSG.js.map} +0 -0
  168. /package/dist/{chunk-DCK5FADX.js.map → chunk-HOE2MN36.js.map} +0 -0
  169. /package/dist/{chunk-MZF2YCXX.js.map → chunk-MOW2RKHX.js.map} +0 -0
  170. /package/dist/{chunk-EROJDXMW.js.map → chunk-NYR55UT7.js.map} +0 -0
  171. /package/dist/{chunk-SRVAA2VN.js.map → chunk-OZ5EXXQV.js.map} +0 -0
  172. /package/dist/{chunk-5G4EPJ4Y.js.map → chunk-VRKTVCYJ.js.map} +0 -0
  173. /package/dist/{chunk-QOGMDOUX.js.map → chunk-WI6YSXOC.js.map} +0 -0
  174. /package/dist/{chunk-BMD7ANKF.js.map → chunk-XQUUNAGC.js.map} +0 -0
  175. /package/dist/{chunk-H67V7DEL.js.map → chunk-YYISBXOM.js.map} +0 -0
  176. /package/dist/{detect-AHJIUMBO.js.map → detect-YDCZNV4W.js.map} +0 -0
  177. /package/dist/{hook-76JBKTUX.js.map → hook-CDGSCASQ.js.map} +0 -0
  178. /package/dist/{leaderboard-V6VWA5ZV.js.map → leaderboard-VZQXNWTX.js.map} +0 -0
  179. /package/dist/{nemoclaw-CQYXZVQN.js.map → nemoclaw-DNFIZFDF.js.map} +0 -0
  180. /package/dist/{openclaw-UZC437RW.js.map → openclaw-QE2LMWIF.js.map} +0 -0
  181. /package/dist/{package-DNLQTPNN.js.map → package-BSCCMW4E.js.map} +0 -0
  182. /package/dist/{pi-PVVPVWKG.js.map → pi-H2KBBDDJ.js.map} +0 -0
  183. /package/dist/{serve-EOVWYBGZ.js.map → serve-MQNGPY2H.js.map} +0 -0
  184. /package/dist/{statusline-3ET5YPQ5.js.map → statusline-IYWA75TR.js.map} +0 -0
  185. /package/dist/{telemetry-QCTMKDBQ.js.map → telemetry-IONIOMLC.js.map} +0 -0
  186. /package/dist/{usage-IRBLVUZM.js.map → usage-TCUWV2YZ.js.map} +0 -0
  187. /package/dist/{usage-event-VFF77WYY.js.map → usage-event-CBZZP37Q.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/windsurf/index.ts"],"sourcesContent":["/**\n * adapters/windsurf — Windsurf (Codeium / Cognition's Cascade agent) adapter.\n *\n * Windsurf is an mcp-only host from agent-connector's perspective: there is no\n * user-installable hook/plugin layer (it is a GUI editor). AC registers the MCP\n * server PLUS three content surfaces (memory, workflows, skills — see below). The\n * MCP config is a Claude-Desktop-style OBJECT map keyed by server name (exactly\n * like the cursor adapter's `mcpServers`), NOT an array.\n *\n * MCP config (primary-verified — docs.devin.ai/desktop/cascade/mcp, formerly\n * docs.windsurf.com):\n * - user/global scope ONLY → ~/.codeium/windsurf/mcp_config.json\n * (Windows %USERPROFILE%\\.codeium\\windsurf\\mcp_config.json — homedir()\n * covers it). The docs specify NO project/workspace config path, so a\n * project-scope install returns a skip ChangeRecord.\n * - root key \"mcpServers\" — a JSON object/map keyed by server name.\n *\n * Server entry shapes (primary-verified):\n * - stdio: { command, args?, env? }\n * - remote: { serverUrl, headers? } — the docs use `serverUrl` (an `url`\n * alias is mentioned but `serverUrl` is the documented primary). There is\n * NO `type` discriminator and NO `disabled` field — stdio vs remote is\n * distinguished by `command` vs `serverUrl`. `headers` is emitted only when\n * the connector's remote server provides them.\n *\n * Native interpolation: Windsurf supports `${env:VAR}` / `${file:/path}`\n * tokens, but AC does not need to emit those — values are resolved to literals\n * at install time (the safe path, same as droid/crush/amazon-q).\n *\n * Memory / rules (primary-verified — docs.windsurf.com/windsurf/cascade/rules,\n * llms-full.txt): a `.windsurf/rules/` workspace directory holds `.md` rule\n * files, each declaring an activation mode \"in its frontmatter via the `trigger`\n * field\". `trigger: always_on` means \"full rule content is included in the\n * system prompt on every message\" (the docs' literal Activation-Modes table).\n * AC owns a DEDICATED file there (`.windsurf/rules/agent-connector.md`) that MUST\n * LEAD with that always-on frontmatter, so — like the continue adapter and unlike\n * the cline/amazon-q managed-block targets — we write the WHOLE file\n * (frontmatter + body) via the content-file writers and own it end-to-end\n * (install creates, uninstall deletes). The connector's memory `content` is\n * host-agnostic (MemoryDef forbids its own frontmatter), so the always-on\n * directive is an adapter-level wrapper. WORKSPACE/PROJECT SCOPE: `global_rules.md`\n * is a single SHARED global file (not an AC-owned dir), so user scope skip-warns.\n *\n * Content surfaces — workflows (slash commands) + skills, BOTH project AND user\n * scope:\n * - workflows → project `<projectDir>/.windsurf/workflows/<name>.md`,\n * user `~/.codeium/windsurf/global_workflows/<name>.md` (the user dir is\n * `global_workflows`, NOT `workflows`). Each becomes a `/<name>` slash\n * command. Windsurf caps each workflow file at 12,000 chars — over-budget\n * files are still written but warned.\n * - skills → project `<projectDir>/.windsurf/skills/<name>/SKILL.md`,\n * user `~/.codeium/windsurf/skills/<name>/SKILL.md` (the dir is `skills` in\n * BOTH scopes). Same SKILL.md convention cline/claude-code/qwen-code use.\n * Both reuse the shared claude-code renderers (renderCommandMd/renderSkillMd).\n *\n * Hook \"config path\" is aliased to the MCP file (no separate hook file) so the\n * base doctor/backup helpers behave sensibly (the amazon-q / roo-code idiom).\n */\n\nimport { existsSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, join } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport { renderCommandMd, renderSkillMd } from \"../claude-code/render.js\";\nimport type { Adapter, InstallContext } from \"../spi.js\";\nimport type {\n ChangeRecord,\n DetectedPlatform,\n HealthCheck,\n HookParadigm,\n PlatformCapabilities,\n PlatformId,\n ServerDef,\n Transport,\n} from \"../../core/types.js\";\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\nimport {\n buildWrappedStdio,\n} from \"../../core/spawn.js\";\n\nconst HOST: PlatformId = \"windsurf\";\nconst MCP_ROOT_KEY = \"mcpServers\";\n\n/**\n * Windsurf caps each workflow (slash-command) file at 12,000 characters\n * (docs.windsurf.com). We still write an over-budget file but emit a warn so the\n * author can trim it, mirroring base.ts's memory soft-budget warn. Skills have no\n * documented size cap, so they are not guarded.\n */\nconst WORKFLOW_MAX_CHARS = 12000;\n\n/**\n * Native MCP server entry shapes Windsurf accepts under `mcpServers` (an OBJECT\n * map keyed by server name, Claude-Desktop-style):\n * - stdio: { command, args?, env? } — transport inferred from `command`.\n * - remote: { serverUrl, headers? } — `serverUrl` (NOT `url`); NO `type`\n * discriminator and NO `disabled` flag. `headers` only when provided.\n */\ninterface WindsurfStdioServer {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n}\ninterface WindsurfRemoteServer {\n serverUrl: string;\n headers?: Record<string, string>;\n}\n\nexport class WindsurfAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"Windsurf\";\n readonly paradigm: HookParadigm = \"mcp-only\";\n\n readonly capabilities: PlatformCapabilities = {\n // Memory surface: WIRED. Windsurf reads `.windsurf/rules/*.md` (NOT\n // AGENTS.md), so the AGENTS.md-first BaseAdapter default does not apply — the\n // installMemory/uninstallMemory overrides below write a DEDICATED\n // agent-connector-owned file (<projectDir>/.windsurf/rules/agent-connector.md)\n // that LEADS with `trigger: always_on` frontmatter (full content in the\n // system prompt on every message). Workspace/project scope only; user scope\n // skip-warns (global_rules.md is a shared global file, not an AC-owned dir).\n supportsMemory: true,\n //\n // mcp-only: Windsurf is a GUI editor with no user-installable hook/plugin\n // layer. Every hook flag is false.\n preToolUse: false,\n postToolUse: false,\n preCompact: false,\n sessionStart: false,\n sessionEnd: false,\n userPromptSubmit: false,\n stop: false,\n notification: false,\n // No hook layer → no arg/output rewrite, no context injection.\n canModifyArgs: false,\n canModifyOutput: false,\n canInjectSessionContext: false,\n // Windsurf registers stdio + remote (http/sse) MCP servers; the remote\n // entry is distinguished by `serverUrl` (vs stdio's `command`).\n transports: [\"stdio\", \"http\", \"sse\"],\n // Content surfaces: WIRED in BOTH scopes. Windsurf reads user-authored\n // WORKFLOWS (each becomes a `/<name>` slash command) and Agent SKILLS (the\n // same SKILL.md frontmatter convention cline/claude-code/qwen-code use):\n // workflows → project .windsurf/workflows/<name>.md,\n // user ~/.codeium/windsurf/global_workflows/<name>.md\n // skills → project .windsurf/skills/<name>/SKILL.md,\n // user ~/.codeium/windsurf/skills/<name>/SKILL.md\n // The install overrides below branch the path on ctx.scope and write at both.\n // Subagents stay UNSET (no documented user-authored dir): base skip-warns.\n supportsCommands: true,\n supportsSkills: true,\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(_projectDir: string): DetectedPlatform {\n const userDir = join(homedir(), \".codeium\", \"windsurf\");\n const userMcp = join(userDir, \"mcp_config.json\");\n const installed = existsSync(userDir) || existsSync(userMcp);\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath: userMcp,\n scope: \"user\",\n reason: installed\n ? `found Windsurf config under ${userDir}`\n : `no Windsurf config at ${userDir}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n /**\n * Windsurf's MCP config is USER/GLOBAL scope only — the docs specify no\n * project/workspace path. getConfigDir always resolves the user dir\n * (homedir() covers USERPROFILE on Windows); a project-scope install is\n * handled by installServer returning a skip, never a write under projectDir.\n */\n getConfigDir(_ctx: InstallContext): string {\n return join(homedir(), \".codeium\", \"windsurf\");\n }\n\n getServerConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"mcp_config.json\");\n }\n\n /**\n * Windsurf has no separate hook file — hook config path aliases the MCP file\n * so the generic doctor/backup helpers behave sensibly (amazon-q idiom).\n */\n getHookConfigPath(ctx: InstallContext): string {\n return this.getServerConfigPath(ctx);\n }\n\n // ── Memory surface: the `.windsurf/rules` content tree ────────────────────\n // A DEDICATED agent-connector-owned file that MUST LEAD with `trigger:\n // always_on` frontmatter (full content in the system prompt on every message).\n // Because of that leading frontmatter we do NOT use the base managed-block\n // engine — we own the whole file via the content-file writers: install\n // writes/updates it idempotently, uninstall deletes it. WORKSPACE/PROJECT scope\n // only (global_rules.md is a shared global file, not an AC-owned dir).\n\n /** <projectDir>/.windsurf/rules/agent-connector.md — the dedicated owned file. */\n private memoryFilePath(ctx: InstallContext): string {\n return join(ctx.projectDir, \".windsurf\", \"rules\", \"agent-connector.md\");\n }\n\n /** True when `<projectDir>/.windsurf/rules` exists and is a regular FILE. */\n private rulesDirIsFile(ctx: InstallContext): boolean {\n const p = join(ctx.projectDir, \".windsurf\", \"rules\");\n if (!existsSync(p)) return false;\n try {\n return statSync(p).isFile();\n } catch {\n return false;\n }\n }\n\n /**\n * Compose the dedicated rule file: `trigger: always_on` frontmatter (the\n * always-on activation directive) + every declared memory entry's content,\n * joined with a blank line. The connector's content is host-agnostic markdown\n * (MemoryDef forbids its own frontmatter), so the directive is ours to add.\n */\n private renderMemoryFile(ctx: InstallContext): string {\n const body = (ctx.connector.memory ?? [])\n .map((m) => m.content.trim())\n .filter((c) => c.length > 0)\n .join(\"\\n\\n\");\n return this.renderFrontmatterMd({ trigger: \"always_on\" }, body);\n }\n\n override installMemory(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const entries = connector.memory ?? [];\n if (connector.platforms[this.id]?.memory === false) {\n return [{ platform: this.id, action: \"skip\", detail: `memory disabled for ${this.id}` }];\n }\n if (entries.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no memory\" }];\n }\n // Windsurf's verified per-rule `.windsurf/rules` dir is WORKSPACE scope only.\n if (ctx.scope !== \"project\") {\n return [\n {\n platform: this.id,\n action: \"warn\",\n detail:\n `no ${ctx.scope}-scope rules dir verified for windsurf ` +\n `(.windsurf/rules is workspace-scope; global_rules.md is a shared file); ` +\n `${entries.length} skipped`,\n },\n ];\n }\n // Rules-path collision: never write under a `.windsurf/rules` that is a FILE.\n if (this.rulesDirIsFile(ctx)) {\n return [\n {\n platform: this.id,\n action: \"warn\",\n path: join(ctx.projectDir, \".windsurf\", \"rules\"),\n detail:\n \"existing .windsurf/rules is a file, not a directory; left untouched — \" +\n \"convert it to a .windsurf/rules/ directory to receive agent-connector memory\",\n },\n ];\n }\n return [this.writeContentFile(this.memoryFilePath(ctx), this.renderMemoryFile(ctx), ctx.dryRun)];\n }\n\n override uninstallMemory(ctx: InstallContext): ChangeRecord[] {\n // Only the project-scope dedicated file was ever written; a `.windsurf/rules`\n // that is a FILE was never ours (installMemory warned), so leave it.\n if (ctx.scope !== \"project\" || this.rulesDirIsFile(ctx)) {\n const path = this.memoryFilePath(ctx);\n return [\n { platform: this.id, action: \"skip\", path, detail: `${basename(path)} absent` },\n ];\n }\n return [this.removeContentFile(this.memoryFilePath(ctx), ctx.dryRun)];\n }\n\n // ── Content surfaces: commands (workflows) + skills ───────────────────────\n // CONTENT-ONLY native-file writers, structured like installMemory: dedicated-\n // file ownership, dryRun honored via writeContentFile/removeContentFile. Both\n // reuse the shared claude-code renderers (renderCommandMd / renderSkillMd) — no\n // new markdown serializer. BOTH scopes write (the project dir AND the\n // ~/.codeium/windsurf user/global dirs are documented surfaces):\n //\n // commands (workflows)\n // - project → <projectDir>/.windsurf/workflows/<name>.md\n // - user → ~/.codeium/windsurf/global_workflows/<name>.md\n // (NOTE: the user dir is `global_workflows`, NOT `workflows`.)\n // skills\n // - project → <projectDir>/.windsurf/skills/<name>/SKILL.md\n // - user → ~/.codeium/windsurf/skills/<name>/SKILL.md\n // (the dir is `skills` in BOTH scopes; same SKILL.md convention\n // cline/claude-code/qwen-code use.)\n //\n // renderCommandMd emits Claude-flavored frontmatter keys (argument-hint, model,\n // allowed-tools); Windsurf ignores unknown frontmatter keys, so they are inert/\n // tolerated — no Windsurf-specific renderer is needed.\n\n /** Workflow file: project `.windsurf/workflows`, user `~/.codeium/windsurf/global_workflows`. */\n private commandPath(ctx: InstallContext, name: string): string {\n const dir =\n ctx.scope === \"project\"\n ? join(ctx.projectDir, \".windsurf\", \"workflows\")\n : join(homedir(), \".codeium\", \"windsurf\", \"global_workflows\");\n return join(dir, `${name}.md`);\n }\n\n /** Skill dir: project `.windsurf/skills/<name>`, user `~/.codeium/windsurf/skills/<name>`. */\n private skillDir(ctx: InstallContext, name: string): string {\n const base =\n ctx.scope === \"project\"\n ? join(ctx.projectDir, \".windsurf\", \"skills\")\n : join(homedir(), \".codeium\", \"windsurf\", \"skills\");\n return join(base, name);\n }\n\n // ── Commands (workflows) ──────────────────────────────────────────────────\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 windsurf\" }];\n }\n if (connector.commands.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const cmd of connector.commands) {\n const rendered = renderCommandMd(cmd);\n changes.push(this.writeContentFile(this.commandPath(ctx, cmd.name), rendered, ctx.dryRun));\n // Windsurf caps each workflow file at 12,000 characters (docs.windsurf.com).\n // Still write the file — warn so the author can trim it (Windsurf may reject\n // or truncate the overflow), mirroring base.ts's memory soft-budget warn.\n if (rendered.length > WORKFLOW_MAX_CHARS) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: this.commandPath(ctx, cmd.name),\n detail:\n `workflow \"${cmd.name}\" is ${rendered.length} chars ` +\n `(Windsurf caps each workflow at ${WORKFLOW_MAX_CHARS}); ` +\n `the host may reject or truncate it — trim the command`,\n });\n }\n }\n return changes;\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 // ── 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 windsurf\" }];\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 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 // ── 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 windsurf\"\n : \"connector declares no MCP server\",\n },\n ];\n }\n\n // Windsurf has no project-level MCP config (user scope only — the docs\n // document only ~/.codeium/windsurf/mcp_config.json). A project-scope\n // install is reported as a skip rather than written into the project tree.\n if (ctx.scope === \"project\") {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail:\n \"Windsurf has no project-level MCP config (user scope only); \" +\n \"re-run with --scope user\",\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\n // NEVER clobber a malformed `mcpServers`. The base upsert tolerates a\n // missing file / missing key (it creates the object), but a PRESENT-but-\n // non-object `mcpServers` (e.g. an array or string from a hand-edit) would\n // get a named property bolted on and silently corrupted — so skip-and-warn.\n const malformed = this.malformedRootKey(serverPath);\n if (malformed) return [malformed];\n\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 const malformed = this.malformedRootKey(serverPath);\n if (malformed) return [malformed];\n return [\n this.removeServerFromJson(serverPath, MCP_ROOT_KEY, ctx.connector.id, ctx.dryRun),\n ];\n }\n\n /**\n * Guard for a PRESENT-but-non-object `mcpServers` root key: returns a\n * skip-warn ChangeRecord when the existing config parses but its `mcpServers`\n * value is not a plain object (an array / string / number / null). Returns\n * undefined when the file is absent, unparseable (the base upsert's own\n * overwrite guard handles that), or `mcpServers` is absent / a plain object.\n */\n private malformedRootKey(configPath: string): ChangeRecord | undefined {\n const cfg = this.readJson<Record<string, unknown>>(configPath);\n if (!cfg || !(MCP_ROOT_KEY in cfg)) return undefined;\n const root = cfg[MCP_ROOT_KEY];\n if (root !== null && typeof root === \"object\" && !Array.isArray(root)) {\n return undefined;\n }\n return {\n platform: this.id,\n action: \"warn\",\n path: configPath,\n detail: `existing ${MCP_ROOT_KEY} in ${configPath} is not an object map; left untouched (back it up / fix it, then re-run)`,\n };\n }\n\n /** Render a normalized ServerDef into Windsurf's native mcpServers entry. */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): WindsurfStdioServer | WindsurfRemoteServer {\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 // Windsurf supports ${env:VAR} natively, but AC resolves references to\n // literals at install time (the safe path, same as amazon-q/droid/crush).\n const entry: WindsurfStdioServer = {\n command: resolveEnvRefsDeep(command),\n };\n if (args.length > 0) entry.args = resolveEnvRefsDeep(args);\n const env = this.renderEnv(server.env);\n if (env) entry.env = env;\n return entry;\n }\n\n // http / sse (and any other remote transport) — Windsurf registers a remote\n // URL under `serverUrl` (NOT `url`). NO `type` discriminator, NO `disabled`.\n // `headers` only when the connector's remote server provides them.\n const entry: WindsurfRemoteServer = {\n serverUrl: resolveEnvRefsDeep(server.url ?? \"\"),\n };\n const headers = this.renderEnv(server.headers);\n if (headers) entry.headers = headers;\n return entry;\n }\n\n /**\n * Render env/header values. Windsurf has a native ${env:VAR} token, but AC\n * resolves references to literals at install time (the safe path).\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 // ── Hooks (unavailable — Windsurf is mcp-only) ────────────────────────────\n\n installHooks(_ctx: InstallContext): ChangeRecord[] {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: \"hooks unavailable (Windsurf is mcp-only)\",\n },\n ];\n }\n\n uninstallHooks(_ctx: InstallContext): ChangeRecord[] {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: \"hooks unavailable (Windsurf is mcp-only)\",\n },\n ];\n }\n\n // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const mcpPath = this.getServerConfigPath(ctx);\n const connectorId = ctx.connector.id;\n return [\n {\n name: `${this.name}: mcp_config.json present`,\n check: () =>\n existsSync(mcpPath)\n ? { status: \"OK\", detail: mcpPath }\n : { status: \"FAIL\", detail: `not found: ${mcpPath}` },\n },\n {\n name: `${this.name}: server entry registered`,\n check: () => {\n if (!ctx.connector.server) {\n return { status: \"OK\", detail: \"no MCP server declared\" };\n }\n const cfg = this.readJson<{ [k: string]: Record<string, unknown> }>(mcpPath);\n const bucket = cfg?.[MCP_ROOT_KEY];\n if (!cfg || !bucket) {\n return { status: \"FAIL\", detail: `no ${MCP_ROOT_KEY} in ${mcpPath}` };\n }\n return connectorId in bucket\n ? { status: \"OK\", detail: `${MCP_ROOT_KEY}.${connectorId} present` }\n : {\n status: \"FAIL\",\n detail: `no ${MCP_ROOT_KEY}.${connectorId} in ${mcpPath}`,\n };\n },\n },\n ];\n }\n}\n\nexport const adapter = new WindsurfAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}
@@ -1,24 +1,26 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ roamingAppData
4
+ } from "./chunk-UM5S7DKK.js";
2
5
  import {
3
6
  resolveEnvRefsDeep
4
7
  } from "./chunk-DBQMX75U.js";
5
8
  import {
6
9
  BaseAdapter
7
- } from "./chunk-CPLK7GTE.js";
10
+ } from "./chunk-KG6T3YNJ.js";
8
11
  import {
9
12
  renderSkillMd
10
- } from "./chunk-7L6ITC4T.js";
13
+ } from "./chunk-IEGR4TP3.js";
11
14
  import {
12
- buildServeWrapperCommand,
13
- shouldWrapForTelemetry
14
- } from "./chunk-I5MLE6S7.js";
15
+ buildWrappedStdio
16
+ } from "./chunk-TO57WYBB.js";
15
17
  import "./chunk-N6HH7K6P.js";
16
18
  import "./chunk-TRQKHP7D.js";
17
19
 
18
20
  // src/adapters/zed/index.ts
19
21
  import { existsSync } from "fs";
20
22
  import { homedir } from "os";
21
- import { join, resolve } from "path";
23
+ import { join } from "path";
22
24
  var HOST = "zed";
23
25
  var MCP_ROOT_KEY = "context_servers";
24
26
  var ZedAdapter = class _ZedAdapter extends BaseAdapter {
@@ -94,8 +96,7 @@ var ZedAdapter = class _ZedAdapter extends BaseAdapter {
94
96
  */
95
97
  userConfigDir() {
96
98
  if (process.platform === "win32") {
97
- const appData = process.env.APPDATA && process.env.APPDATA.trim() !== "" ? process.env.APPDATA : resolve(homedir(), "AppData", "Roaming");
98
- return join(appData, "Zed");
99
+ return join(roamingAppData(), "Zed");
99
100
  }
100
101
  return join(homedir(), ".config", "zed");
101
102
  }
@@ -175,18 +176,7 @@ var ZedAdapter = class _ZedAdapter extends BaseAdapter {
175
176
  if (transport === "stdio") {
176
177
  let command = server.command ?? "";
177
178
  let args = [...server.args ?? []];
178
- if (shouldWrapForTelemetry(server, ctx.connector.telemetry)) {
179
- const wrapped = buildServeWrapperCommand(
180
- ctx.homeBinPath,
181
- ctx.connector.id,
182
- command,
183
- args,
184
- ctx.scope,
185
- this.id
186
- );
187
- command = wrapped.command;
188
- args = wrapped.args;
189
- }
179
+ ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));
190
180
  const entry2 = { command: resolveEnvRefsDeep(command) };
191
181
  if (args.length > 0) entry2.args = resolveEnvRefsDeep(args);
192
182
  const env = this.renderEnv(server.env);
@@ -321,4 +311,4 @@ export {
321
311
  adapter,
322
312
  zed_default as default
323
313
  };
324
- //# sourceMappingURL=zed-SFUHL3GS.js.map
314
+ //# sourceMappingURL=zed-FDJHJZKD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/zed/index.ts"],"sourcesContent":["/**\n * adapters/zed — Zed editor platform adapter for agent-connector.\n *\n * Zed is an **mcp-only** host: it is an IDE, not a CLI with a hook pipeline, so\n * there is NO lifecycle hook system. MCP (\"context servers\") is the only\n * integration path, so this adapter installs only the MCP server and reports\n * hooks as unavailable — like Warp, it exercises the `mcp-only` paradigm.\n *\n * MCP config (one JSON-with-comments settings file, NOT a dedicated MCP file):\n * - user scope → settings.json under Zed's OS-native config dir (Rust\n * `dirs::config_dir()`):\n * • Windows: %APPDATA%\\Zed\\settings.json (Roaming, NOT %LOCALAPPDATA%)\n * • macOS / Linux: ~/.config/zed/settings.json\n * - project scope → <projectDir>/.zed/settings.json\n * Root key is \"context_servers\" (NOT \"mcpServers\"). The same file holds the\n * (non-existent) hook config — there is no separate hook file here.\n *\n * MERGE CONTRACT: Zed's settings.json is a large user-owned IDE config. We read\n * the whole file, set ONLY context_servers[<id>], and write it back — every\n * other top-level key and sibling context server is preserved. (Zed accepts\n * JSONC; we WRITE plain JSON, mirroring the other JSON-config adapters.)\n *\n * ENTRY SHAPE QUIRK (verified against context-mode's proven Zed adapter +\n * zed-industries/zed crates/settings_content/src/project.rs): Zed's\n * context_servers Stdio variant flattens ContextServerCommand and renames its\n * `path` field to the JSON key `command`. The accepted shape is therefore a\n * FLAT entry: { \"command\": \"<exe>\", \"args\": [...], \"env\": {...} }. The nested\n * { command: { path, args } } form fails to deserialize under Zed's\n * #[serde(untagged)] enum and is silently dropped (the server never loads).\n *\n * Zed documents no native ${env:VAR} interpolation token for context_servers,\n * so env refs are resolved to literals at install time (the no-native-token\n * path, same as Warp).\n *\n * Skills surface: Zed reads SKILL.md files from:\n * project scope → <projectDir>/.agents/skills/<name>/SKILL.md\n * user scope → ~/.agents/skills/<name>/SKILL.md\n */\n\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport type { Adapter, InstallContext, MemoryTarget } from \"../spi.js\";\nimport type {\n ChangeRecord,\n DetectedPlatform,\n HealthCheck,\n HookParadigm,\n PlatformCapabilities,\n PlatformId,\n ServerDef,\n SkillDef,\n Transport,\n} from \"../../core/types.js\";\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\nimport { roamingAppData } from \"../../core/host-paths.js\";\nimport {\n buildWrappedStdio,\n} from \"../../core/spawn.js\";\nimport { renderSkillMd } from \"../claude-code/render.js\";\n\nconst HOST: PlatformId = \"zed\";\nconst MCP_ROOT_KEY = \"context_servers\";\n\n/**\n * Zed's context_servers Stdio entry. FLAT shape — `command` is a string, NOT a\n * nested { path, args } object (see file header). Remote transports are\n * represented as a URL-bearing entry.\n */\ninterface ZedStdioServer {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n}\ninterface ZedHttpServer {\n url: string;\n headers?: Record<string, string>;\n}\n\nexport class ZedAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"Zed\";\n readonly paradigm: HookParadigm = \"mcp-only\";\n\n readonly capabilities: PlatformCapabilities = {\n // Memory surface: AGENTS.md-first managed block. Zed's project rules file\n // is FIRST-MATCH across nine candidates — memoryTargets below probes that\n // order and writes into the file Zed will actually read; user scope is the\n // personal ~/.config/zed/AGENTS.md (%APPDATA%\\Zed on Windows, base map).\n supportsMemory: true,\n // Zed has no lifecycle hook system — every hook capability is false.\n preToolUse: false,\n postToolUse: false,\n preCompact: false,\n sessionStart: false,\n sessionEnd: false,\n userPromptSubmit: false,\n stop: false,\n notification: false,\n canModifyArgs: false,\n canModifyOutput: false,\n canInjectSessionContext: false,\n // Zed registers stdio context servers; remote URLs are also accepted.\n transports: [\"stdio\", \"sse\", \"http\"],\n // Skills: Zed reads SKILL.md from .agents/skills/<name>/SKILL.md (project)\n // and ~/.agents/skills/<name>/SKILL.md (user).\n supportsSkills: true,\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userDir = this.userConfigDir();\n const userSettings = this.userSettingsPath();\n const projDir = join(projectDir, \".zed\");\n const projSettings = join(projDir, \"settings.json\");\n\n const userInstalled = existsSync(userDir) || existsSync(userSettings);\n const projInstalled = existsSync(projDir) || existsSync(projSettings);\n const installed = userInstalled || projInstalled;\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\n const configPath = scope === \"project\" ? projSettings : userSettings;\n\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath,\n scope,\n reason: installed\n ? `found Zed config (${scope}) at ${configPath}`\n : `no Zed config at ${userSettings} or ${projSettings}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n getConfigDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".zed\")\n : this.userConfigDir();\n }\n\n getServerConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"settings.json\");\n }\n\n /**\n * Zed has no hook file — hooks are not a thing here. The hook \"config path\"\n * is the same settings.json so the generic doctor/backup behave sensibly.\n */\n getHookConfigPath(ctx: InstallContext): string {\n return this.getServerConfigPath(ctx);\n }\n\n /**\n * Zed's user config dir is OS-native (Rust `dirs::config_dir()`), NOT a\n * uniform ~/.config:\n * - Windows: %APPDATA%\\Zed (Roaming, NOT Local/%LOCALAPPDATA%)\n * - macOS / Linux: ~/.config/zed\n */\n private userConfigDir(): string {\n if (process.platform === \"win32\") {\n return join(roamingAppData(), \"Zed\");\n }\n return join(homedir(), \".config\", \"zed\");\n }\n\n private userSettingsPath(): string {\n return join(this.userConfigDir(), \"settings.json\");\n }\n\n // ── Memory surface: first-match project rules probe ─────────────────────\n /**\n * Zed reads exactly ONE project rules file — the FIRST existing of these\n * worktree-root candidates (zed docs/src/ai/instructions.md order). A block\n * in AGENTS.md is silently ignored when e.g. `.cursorrules` exists, so the\n * probe targets the file Zed will actually pick; AGENTS.md is created only\n * when nothing shadows it.\n */\n private static readonly PROJECT_RULES_PROBE_ORDER = [\n \".rules\",\n \".cursorrules\",\n \".windsurfrules\",\n \".clinerules\",\n join(\".github\", \"copilot-instructions.md\"),\n \"AGENT.md\",\n \"AGENTS.md\",\n \"CLAUDE.md\",\n \"GEMINI.md\",\n ];\n\n protected override memoryTargets(ctx: InstallContext): MemoryTarget[] {\n if (this.memoryOverride(ctx)?.path || ctx.scope !== \"project\") {\n return super.memoryTargets(ctx); // user scope: personal AGENTS.md (base map)\n }\n for (const rel of ZedAdapter.PROJECT_RULES_PROBE_ORDER) {\n const candidate = join(ctx.projectDir, rel);\n if (existsSync(candidate)) {\n return [\n {\n path: candidate,\n reason: `zed first-match project rules file (${rel} shadows later candidates)`,\n },\n ];\n }\n }\n return [\n {\n path: join(ctx.projectDir, \"AGENTS.md\"),\n reason: \"AGENTS.md (created; no zed first-match rules file present)\",\n },\n ];\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 zed\"\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 // upsertServerInJson reads the WHOLE settings file, sets only\n // context_servers[<id>], and writes it back — preserving every other\n // top-level key and sibling context server (the merge contract).\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 Zed's native context_servers entry. */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): ZedStdioServer | ZedHttpServer {\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 // Zed has no documented native interpolation token, so resolve every\n // ${env:VAR} to a literal at install time.\n // FLAT shape: `command` is a string, never a nested { path, args }.\n const entry: ZedStdioServer = { 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 return entry;\n }\n\n // sse / http (and any other remote transport) — Zed registers a URL.\n const entry: ZedHttpServer = { 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. Zed 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 // Zed reads SKILL.md files from:\n // project scope → <projectDir>/.agents/skills/<name>/SKILL.md\n // user scope → ~/.agents/skills/<name>/SKILL.md\n\n private skillsDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".agents\", \"skills\")\n : join(homedir(), \".agents\", \"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 zed\" }];\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 // ── Hooks (unavailable — Zed is mcp-only) ────────────────────────────────\n\n installHooks(_ctx: InstallContext): ChangeRecord[] {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: \"hooks unavailable (Zed is mcp-only)\",\n },\n ];\n }\n\n uninstallHooks(_ctx: InstallContext): ChangeRecord[] {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: \"hooks unavailable (Zed is mcp-only)\",\n },\n ];\n }\n\n // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const settingsPath = this.getServerConfigPath(ctx);\n const connectorId = ctx.connector.id;\n return [\n {\n name: `${this.name}: settings.json present`,\n check: () =>\n existsSync(settingsPath)\n ? { status: \"OK\", detail: settingsPath }\n : { status: \"FAIL\", detail: `not found: ${settingsPath}` },\n },\n {\n name: `${this.name}: context server entry registered`,\n check: () => {\n // Only assert what the connector declares: a server-less connector —\n // e.g. a catalog-only bundle of agents/skills/commands — never writes\n // a context_servers entry, so its absence is healthy.\n if (!ctx.connector.server) {\n return { status: \"OK\", detail: \"no MCP server declared\" };\n }\n const cfg = this.readJson<{ [k: string]: Record<string, unknown> }>(settingsPath);\n const bucket = cfg?.[MCP_ROOT_KEY];\n if (!cfg || !bucket) {\n return { status: \"FAIL\", detail: `no ${MCP_ROOT_KEY} in ${settingsPath}` };\n }\n return connectorId in bucket\n ? { status: \"OK\", detail: `${MCP_ROOT_KEY}.${connectorId} present` }\n : {\n status: \"FAIL\",\n detail: `no ${MCP_ROOT_KEY}.${connectorId} in ${settingsPath}`,\n };\n },\n },\n ];\n }\n}\n\nexport const adapter = new ZedAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ken-jo/agent-connector",
3
- "version": "0.4.6",
3
+ "version": "0.4.8",
4
4
  "type": "module",
5
5
  "description": "Write your MCP server + hooks once; agent-connector installs and adapts them across every AI-agent platform (Claude Code, Codex, Cursor, OpenCode, Copilot, Gemini, Warp, …) and gives you default, platform-independent per-tool token telemetry.",
6
6
  "keywords": [
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/adapters/amazon-q/index.ts"],"sourcesContent":["/**\n * adapters/amazon-q — Amazon Q Developer CLI platform adapter.\n *\n * Amazon Q Developer CLI (`q` / `qchat`) is an **mcp-only** host from\n * agent-connector's perspective. Although the agent JSON format exposes a\n * real hooks layer (agentSpawn / userPromptSubmit / preToolUse / postToolUse,\n * JSON-over-STDIN, exit-code 0/2 contract — primary-verified via\n * aws.github.io/amazon-q-developer-cli agent-format + hooks.md), the VERIFIED\n * CONTRACT classifies this adapter as mcp-only because the hook layer lives\n * inside per-agent JSON files (cli-agents/*.json), not in the global/workspace\n * mcp.json that AC targets for MCP registration. We install MCP entries only;\n * hook registration into agent files is a separate, unimplemented surface.\n *\n * MCP config (legacy files, primary-verified via AWS docs):\n * - user scope → ~/.aws/amazonq/mcp.json (global; applies to all workspaces)\n * - project scope → <projectDir>/.amazonq/mcp.json (local workspace)\n * Both are JSON, root key \"mcpServers\". Amazon Q reads BOTH when both exist\n * and merges them (union); workspace wins on same-name conflict with a warning.\n *\n * Server entry shape (primary-verified):\n * - stdio: { command: string; args?: string[]; env?: { [k: string]: string };\n * timeout?: number } (timeout in MILLISECONDS, e.g. 60000;\n * transport inferred from presence of `command` — no `type` key)\n * - http: { type: \"http\"; url: string }\n * (the remote/HTTP shape is written with an explicit `type: \"http\"`\n * discriminator + `url`, per command-line-mcp-config-CLI.html. No\n * `headers` field — Amazon Q remote auth is OAuth, not static\n * headers — and no `disabled` flag.)\n *\n * Path resolution — NOTE the nested user scope:\n * - user: join(homedir(), \".aws\", \"amazonq\") (two path segments)\n * - project: join(projectDir, \".amazonq\") (single dotDir, no .aws)\n * homedir() handles USERPROFILE on Windows automatically; no manual branch.\n *\n * Env interpolation: Amazon Q has no documented native ${env:VAR} token;\n * resolve all references to literals at install time (the safe path, same as\n * droid/crush).\n *\n * Memory / rules (primary-verified — docs.aws.amazon.com context-project-rules):\n * Project rules are plain Markdown files in <projectDir>/.amazonq/rules; Amazon\n * Q \"will automatically use them as context whenever a developer chats with\n * Amazon Q within your project\". NO frontmatter required. We write a DEDICATED\n * agent-connector-owned file there (`.amazonq/rules/agent-connector.md`),\n * mirroring the cline `.clinerules/agent-connector.md` approach: memoryTargets()\n * points at the dedicated file and the base managed-block engine performs the\n * surgical, hash-stamped, uninstall-reversible write. PROJECT SCOPE ONLY — the\n * AWS docs do not cleanly document a user/global rules directory for the CLI\n * (a `~/.aws/amazonq/.../rules` path is unverified), so user scope returns [] →\n * the base installMemory skip-warns rather than writing into an unread path.\n *\n * Hook \"config path\" is aliased to the MCP file (no separate hook file) so the\n * base doctor/backup helpers behave sensibly.\n */\n\nimport { existsSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport type { Adapter, InstallContext, MemoryTarget } from \"../spi.js\";\nimport type {\n ChangeRecord,\n DetectedPlatform,\n HealthCheck,\n HookParadigm,\n PlatformCapabilities,\n PlatformId,\n ServerDef,\n Transport,\n} from \"../../core/types.js\";\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\nimport {\n buildServeWrapperCommand,\n shouldWrapForTelemetry,\n} from \"../../core/spawn.js\";\n\nconst HOST: PlatformId = \"amazon-q\";\nconst MCP_ROOT_KEY = \"mcpServers\";\n\n/**\n * Native MCP server entry shapes Amazon Q accepts under `mcpServers`.\n * - stdio: BARE shape — NO `type` discriminator and NO `disabled` flag; the\n * transport is inferred from the presence of `command`. timeout is in\n * MILLISECONDS (pass timeoutMs through unchanged, do NOT divide).\n * - http: REMOTE shape — explicit `type: \"http\"` + `url`\n * (command-line-mcp-config-CLI.html). NO `headers` (remote auth is OAuth,\n * not static headers) and NO `disabled` flag.\n */\ninterface AmazonQStdioServer {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n timeout?: number;\n}\ninterface AmazonQHttpServer {\n type: \"http\";\n url: string;\n}\n\nexport class AmazonQAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"Amazon Q Developer CLI\";\n readonly paradigm: HookParadigm = \"mcp-only\";\n\n readonly capabilities: PlatformCapabilities = {\n // Memory surface: WIRED. Amazon Q reads `.amazonq/rules` (NOT AGENTS.md), so\n // the AGENTS.md-first BaseAdapter default does not apply — memoryTargets()\n // below overrides it to write a DEDICATED agent-connector-owned file\n // (<projectDir>/.amazonq/rules/agent-connector.md, plain Markdown, no\n // frontmatter — auto-applied as context per the AWS docs). Project scope\n // only; user scope skip-warns (no verified user/global rules dir).\n supportsMemory: true,\n //\n // Amazon Q CLI: the hooks layer lives inside per-agent JSON files, not in\n // the global/workspace mcp.json that AC targets. Every hook flag is false\n // for this mcp-only adapter (hooks not wired into AC install yet).\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 // No hook layer wired → no arg/output rewrite, no context injection.\n canModifyArgs: false,\n canModifyOutput: false,\n canInjectSessionContext: false,\n // Amazon Q registers stdio + Streamable HTTP MCP servers (primary-verified).\n transports: [\"stdio\", \"http\"],\n // Content surfaces: Amazon Q DOES have user-authored surfaces — agents\n // (per-agent JSON in ~/.aws/amazonq/cli-agents/*.json or project\n // .amazonq/cli-agents/*.json: name/description/prompt/tools/hooks/resources;\n // agent-format.md) and a prompt library (~/.aws/amazonq/prompts/*.md). AC does\n // not render either yet, so the supports* flags stay UNSET (base skip-warns) —\n // a deferred wiring opportunity, NOT an absent surface.\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userDir = join(homedir(), \".aws\", \"amazonq\");\n const userMcp = join(userDir, \"mcp.json\");\n const projDir = join(projectDir, \".amazonq\");\n const projMcp = join(projDir, \"mcp.json\");\n\n const userInstalled = existsSync(userDir) || existsSync(userMcp);\n const projInstalled = existsSync(projDir) || existsSync(projMcp);\n const installed = userInstalled || projInstalled;\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\n const configPath = scope === \"project\" ? projMcp : userMcp;\n\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath,\n scope,\n reason: installed\n ? `found Amazon Q config (${scope}) at ${configPath}`\n : `no Amazon Q mcp.json at ${userDir} or ${projDir}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n /**\n * Config directory per scope. Amazon Q uses DIFFERENT basenames:\n * user: ~/.aws/amazonq (two segments — NOT a single dotDir)\n * project: <projectDir>/.amazonq\n * This is the ONE deviation from droid/cursor's single-basename getConfigDir.\n */\n getConfigDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".amazonq\")\n : join(homedir(), \".aws\", \"amazonq\");\n }\n\n getServerConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"mcp.json\");\n }\n\n /**\n * Amazon Q has no separate hook file — hook config path aliases the MCP file\n * so the generic doctor/backup helpers behave sensibly (roo-code idiom).\n */\n getHookConfigPath(ctx: InstallContext): string {\n return this.getServerConfigPath(ctx);\n }\n\n // ── Memory surface: the `.amazonq/rules` content tree ─────────────────────\n // Amazon Q uses `.amazonq/rules` (NOT AGENTS.md) for its OWN project rules, so\n // this override replaces the AGENTS.md base default entirely:\n // project → <projectDir>/.amazonq/rules/agent-connector.md (DEDICATED file\n // AC owns; plain Markdown, auto-applied — no frontmatter needed)\n // user → [] (no verified user/global rules dir → base installMemory\n // skip-warns rather than guessing a path the CLI may not read)\n // When `.amazonq/rules` exists as a single FILE (not a directory) we must NOT\n // create `.amazonq/rules/agent-connector.md` underneath it (that would throw\n // ENOTDIR), so memoryTargets() returns [] and installMemory() emits a precise\n // skip-warn rather than crashing (the cline `.clinerules`-is-a-file precedent).\n protected override memoryTargets(ctx: InstallContext): MemoryTarget[] {\n // An explicit platforms[amazon-q].memory.path override wins (escape hatch).\n if (this.memoryOverride(ctx)?.path) return super.memoryTargets(ctx);\n if (ctx.scope === \"project\") {\n if (this.rulesDirIsFile(ctx.projectDir)) return [];\n return [\n {\n path: join(ctx.projectDir, \".amazonq\", \"rules\", \"agent-connector.md\"),\n reason: \"amazon-q project rules dir (.amazonq/rules; agent-connector-owned file)\",\n },\n ];\n }\n // user scope: no primary-verified user/global rules dir → [] → skip-warn.\n return [];\n }\n\n /**\n * Override installMemory ONLY to surface a precise warn when `.amazonq/rules`\n * exists as a single FILE at project scope (so memoryTargets() returned []):\n * we never write under it. All other behavior delegates to the base\n * implementation (the cline `.clinerules`-is-a-file precedent).\n */\n override installMemory(ctx: InstallContext): ChangeRecord[] {\n if (\n ctx.scope === \"project\" &&\n !this.memoryOverride(ctx)?.path &&\n (ctx.connector.memory ?? []).length > 0 &&\n ctx.connector.platforms[this.id]?.memory !== false &&\n this.rulesDirIsFile(ctx.projectDir)\n ) {\n return [\n {\n platform: this.id,\n action: \"warn\",\n path: join(ctx.projectDir, \".amazonq\", \"rules\"),\n detail:\n \"existing .amazonq/rules is a file, not a directory; left untouched — \" +\n \"convert it to a .amazonq/rules/ directory to receive agent-connector memory\",\n },\n ];\n }\n return super.installMemory(ctx);\n }\n\n /** True when `<dir>/.amazonq/rules` exists and is a regular FILE (not a dir). */\n private rulesDirIsFile(dir: string): boolean {\n const p = join(dir, \".amazonq\", \"rules\");\n if (!existsSync(p)) return false;\n try {\n return statSync(p).isFile();\n } catch {\n return false;\n }\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 amazon-q\"\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 Amazon Q's native mcpServers entry. */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): AmazonQStdioServer | AmazonQHttpServer {\n const transport: Transport = server.transport;\n\n if (transport === \"stdio\") {\n let command = server.command ?? \"\";\n let args = [...(server.args ?? [])];\n\n // Transparent telemetry wrapping: route the real command through\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\n if (shouldWrapForTelemetry(server, ctx.connector.telemetry)) {\n const wrapped = buildServeWrapperCommand(\n ctx.homeBinPath,\n ctx.connector.id,\n command,\n args,\n ctx.scope,\n this.id,\n );\n command = wrapped.command;\n args = wrapped.args;\n }\n\n // Amazon Q has no documented native interpolation token — resolve every\n // ${env:VAR} to a literal at install time (safe path, matches droid/crush).\n const entry: AmazonQStdioServer = {\n command: resolveEnvRefsDeep(command),\n };\n if (args.length > 0) entry.args = resolveEnvRefsDeep(args);\n const env = this.renderEnv(server.env);\n if (env) entry.env = env;\n // timeout: Amazon Q uses MILLISECONDS — pass timeoutMs through unchanged.\n // Only emit when the connector explicitly sets one (do NOT invent a default).\n if (server.timeoutMs !== undefined) entry.timeout = server.timeoutMs;\n return entry;\n }\n\n // http (and any other remote transport) — Amazon Q registers a remote URL.\n // REMOTE shape: { type: \"http\", url } — explicit `type` discriminator, NO\n // `headers` (OAuth auth, not static headers), NO `disabled`.\n return {\n type: \"http\",\n url: resolveEnvRefsDeep(server.url ?? \"\"),\n };\n }\n\n /**\n * Render stdio env values. Amazon Q has no documented native interpolation\n * token, so 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 // ── Hooks (unavailable — Amazon Q CLI is mcp-only in this adapter) ────────\n\n installHooks(_ctx: InstallContext): ChangeRecord[] {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: \"hooks unavailable (Amazon Q CLI is mcp-only)\",\n },\n ];\n }\n\n uninstallHooks(_ctx: InstallContext): ChangeRecord[] {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: \"hooks unavailable (Amazon Q CLI is mcp-only)\",\n },\n ];\n }\n\n // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const mcpPath = this.getServerConfigPath(ctx);\n const connectorId = ctx.connector.id;\n return [\n {\n name: `${this.name}: mcp.json present`,\n check: () =>\n existsSync(mcpPath)\n ? { status: \"OK\", detail: mcpPath }\n : { status: \"FAIL\", detail: `not found: ${mcpPath}` },\n },\n {\n name: `${this.name}: server entry registered`,\n check: () => {\n if (!ctx.connector.server) {\n return { status: \"OK\", detail: \"no MCP server declared\" };\n }\n const cfg = this.readJson<{ [k: string]: Record<string, unknown> }>(mcpPath);\n const bucket = cfg?.[MCP_ROOT_KEY];\n if (!cfg || !bucket) {\n return { status: \"FAIL\", detail: `no ${MCP_ROOT_KEY} in ${mcpPath}` };\n }\n return connectorId in bucket\n ? { status: \"OK\", detail: `${MCP_ROOT_KEY}.${connectorId} present` }\n : {\n status: \"FAIL\",\n detail: `no ${MCP_ROOT_KEY}.${connectorId} in ${mcpPath}`,\n };\n },\n },\n ];\n }\n}\n\nexport const adapter = new AmazonQAdapter();\nexport default adapter;\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/adapters/amp/index.ts"],"sourcesContent":["/**\n * adapters/amp — Amp (Sourcegraph / AmpCode) platform adapter for agent-connector.\n *\n * Amp is a **ts-plugin** host: alongside MCP it loads TypeScript plugin modules\n * from `.amp/plugins/<name>.ts`, each default-exporting a function `(amp) => void`\n * that registers lifecycle handlers via `amp.on(\"<event>\", async (event, ctx) =>\n * …)` (ampcode.com/manual → Plugins). This adapter wires the five amp.on events\n * that have a canonical analog and bridges them to the universal home-bin\n * entrypoint, exactly like the OMP / OpenCode ts-plugin adapters.\n *\n * Event mapping (only events the connector declares are subscribed):\n * SessionStart → amp.on(\"session.start\", …) (thread begins; id = event.thread.id)\n * UserPromptSubmit → amp.on(\"agent.start\", …) (user submits a prompt; observe-only)\n * PreToolUse → amp.on(\"tool.call\", …) (before a tool runs; deny → return\n * { action: \"reject-and-continue\" }, else { action: \"allow\" })\n * PostToolUse → amp.on(\"tool.result\", …) (after a tool finishes; observe-only)\n * Stop → amp.on(\"agent.end\", …) (turn ends; observe-only)\n * Amp documents NO session.end event, so SessionEnd is an honest gap (warn-skip\n * via the unsupported-here detail). tool.call's decision surface is the\n * { action } union (canModifyArgs:false — the \"modify\" input shape is not\n * documented); tool.result CAN return a replacement but the manual never\n * documents its object shape, so PostToolUse is observe-only (canModifyOutput:\n * false) rather than ship a guessed mutation; session.start has no documented\n * context-injection surface (canInjectSessionContext:false).\n *\n * Why we SYNTHESIZE a self-contained module instead of importing handlers:\n * the connector's hook handlers are arbitrary developer code we must not import\n * into Amp's (Bun) runtime — wrong cwd, wrong deps, version skew. So, like the\n * OMP / OpenCode adapters, we generate a tiny ESM/TS plugin that imports NOTHING\n * from agent-connector: each `amp.on(...)` handler shells out to the ONE stable\n * home binary's universal entrypoint (`<homeBin> hook amp <event> --connector\n * <id>`) over child_process, feeds it the amp-shaped payload as JSON on stdin,\n * and JSON.parses the normalized HookResponse back from stdout. Fail-open: any\n * bridge error → no-op. One entrypoint, every paradigm.\n *\n * Plugin scope: the `.amp/plugins/` dir is documented at PROJECT scope only; Amp\n * documents no user-scope plugins dir, so installHooks writes the plugin for\n * project scope and warn-skips user scope (the MCP + skills surfaces keep their\n * own user-scope paths). MCP config (report §2 / §5.3):\n * - user scope → ~/.config/amp/settings.json\n * - project scope → <projectDir>/.amp/settings.json\n * Both are JSONC (we write plain JSON, which is valid JSONC). The settings file\n * is SHARED with the rest of Amp's configuration, so we MERGE our entry into\n * the existing object and never clobber unrelated keys.\n *\n * QUIRK 1 — dotted top-level key: Amp does NOT use a nested `mcpServers` object.\n * The MCP registry is a single FLAT settings key literally named\n * `\"amp.mcpServers\"`, whose value is an object of `{ id: { command, args, env } }`.\n * We therefore set `settings[\"amp.mcpServers\"][connectorId] = entry`. Because the\n * base JSON helpers index `config[rootKey][serverId]`, passing the dotted string\n * as the root key writes exactly that flat key while preserving every sibling\n * setting (true merge).\n *\n * QUIRK 2 — native interpolation: Amp expands `${VAR_NAME}` in stdio entries at\n * runtime, so we KEEP env/header/url refs native by rewriting the portable\n * `${env:VAR}` syntax to Amp's `${VAR}` token rather than resolving to literals\n * (secrets stay out of the settings file).\n *\n * Skills surface: Amp reads SKILL.md files (dir-per-skill, same shape as\n * claude-code) from a skill root that is NOT under the config dir\n * (`~/.config/amp`):\n * - user scope → ~/.config/agents/skills/<name>/SKILL.md (the sibling\n * cross-agent `agents` dir — `~/.config/amp/skills/` is also documented-native,\n * but the `agents` root is the cross-agent standard we standardize on)\n * - project scope → <projectDir>/.agents/skills/<name>/SKILL.md\n * Because that root differs from getConfigDir, skills use a dedicated skillDir()\n * helper rather than reusing getConfigDir.\n */\n\nimport {\n chmodSync,\n existsSync,\n mkdirSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport type {\n Adapter,\n GeneratedPluginFile,\n HookReply,\n InstallContext,\n NormalizedEvent,\n} 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 { rewriteEnvRefs } from \"../../core/interpolate.js\";\nimport {\n buildServeWrapperCommand,\n shouldWrapForTelemetry,\n} from \"../../core/spawn.js\";\nimport { renderSkillMd } from \"../claude-code/render.js\";\n\nconst HOST: PlatformId = \"amp\";\n/**\n * QUIRK: a single FLAT, dotted settings key — NOT a nested object. The base\n * JSON helpers treat this as `config[\"amp.mcpServers\"][serverId]`.\n */\nconst MCP_ROOT_KEY = \"amp.mcpServers\";\n\n/**\n * Canonical → Amp plugin event name map. A connector hook event is only\n * subscribed by the generated plugin when it appears here AND is declared by the\n * connector. Names verified against ampcode.com/manual (Plugins → amp.on events).\n * Amp documents NO `session.end`, so SessionEnd has no entry (honest gap).\n */\nconst EVENT_TO_AMP: Partial<Record<HookEventName, string>> = {\n SessionStart: \"session.start\",\n UserPromptSubmit: \"agent.start\",\n PreToolUse: \"tool.call\",\n PostToolUse: \"tool.result\",\n Stop: \"agent.end\",\n};\n\n/** Raw payload the generated plugin posts to the universal hook entrypoint. */\ninterface AmpBridgePayload {\n toolName?: string;\n toolInput?: Record<string, unknown>;\n toolOutput?: string;\n isError?: boolean;\n prompt?: string;\n sessionId?: string;\n projectDir?: string;\n}\n\n/** Native MCP server entry shapes Amp accepts under `amp.mcpServers`. */\ninterface AmpStdioServer {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n}\ninterface AmpHttpServer {\n url: string;\n headers?: Record<string, string>;\n}\n\nexport class AmpAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"Amp\";\n readonly paradigm: HookParadigm = \"ts-plugin\";\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 // amp.on lifecycle events with a canonical analog (EVENT_TO_AMP):\n // tool.call / tool.result / session.start / agent.start / agent.end.\n preToolUse: true,\n postToolUse: true,\n // Amp has no documented compaction hook.\n preCompact: false,\n sessionStart: true,\n // Amp documents NO session.end event — SessionEnd is an honest gap.\n sessionEnd: false,\n userPromptSubmit: true,\n stop: true,\n notification: false,\n // Newer events: Amp documents no permission/approval, post-tool-failure, or\n // subagent lifecycle hook with a canonical analog, so permissionRequest /\n // postToolUseFailure / subagentStart / subagentStop stay unset — the\n // generated bridge never references them and install reports them as\n // \"unsupported here\".\n // tool.call's documented decision surface is { action: \"allow\" |\n // \"reject-and-continue\" | \"modify\" | \"synthesize\" } (ampcode.com/manual →\n // Plugins → tool.call). We wire allow + reject-and-continue (block); the\n // \"modify\" input-rewrite shape is not byte-documented, so canModifyArgs:false.\n canModifyArgs: false,\n // tool.result says \"return a replacement status/output\" but the manual never\n // documents the replacement OBJECT SHAPE (which keys). Rather than guess it,\n // PostToolUse is observe-only and canModifyOutput stays false until the shape\n // is primary-source-verified (honesty bar: under-claim, never emit a guessed\n // mutation contract).\n canModifyOutput: false,\n // session.start has no documented context-injection surface.\n canInjectSessionContext: false,\n // Amp registers stdio and Streamable HTTP MCP servers.\n transports: [\"stdio\", \"http\"],\n // Skills: Amp reads SKILL.md from ~/.config/agents/skills/<name>/SKILL.md\n // (user) and <projectDir>/.agents/skills/<name>/SKILL.md (project) — a root\n // OUTSIDE the config dir, so the skillDir() helper resolves it explicitly.\n supportsSkills: true,\n // Native passthrough hooks: amp.on events with no canonical HookEventName\n // analog are reachable via platforms[\"amp\"].nativeHooks; the generated plugin\n // registers + bridges each declared native event verbatim and the home-bin\n // runtime dispatches it host-generically via runNativeHook.\n supportsNativeHooks: true,\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userDir = join(homedir(), \".config\", \"amp\");\n const userSettings = join(userDir, \"settings.json\");\n const projectDirAmp = join(projectDir, \".amp\");\n const projectSettings = join(projectDirAmp, \"settings.json\");\n\n const userInstalled = existsSync(userDir) || existsSync(userSettings);\n const projectInstalled = existsSync(projectDirAmp) || existsSync(projectSettings);\n const installed = userInstalled || projectInstalled;\n const scope = projectInstalled && !userInstalled ? \"project\" : \"user\";\n const configPath = scope === \"project\" ? projectSettings : userSettings;\n\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath,\n scope,\n reason: installed\n ? `found Amp config (${scope}) at ${configPath}`\n : `no Amp config at ${userSettings} or ${projectSettings}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n getConfigDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".amp\")\n : join(homedir(), \".config\", \"amp\");\n }\n\n getServerConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"settings.json\");\n }\n\n /**\n * For this ts-plugin host the \"hook config path\" is the generated plugin\n * MODULE. Amp loads every `.ts` file in `.amp/plugins/`, so writing this file\n * IS the registration. The `.amp/plugins/` dir is documented at PROJECT scope\n * (Amp documents no user-scope plugins dir — see pluginsDir); the user-scope\n * path is returned for doctor/uninstall symmetry but installHooks warn-skips it.\n */\n getHookConfigPath(ctx: InstallContext): string {\n return join(this.pluginsDir(ctx), `${ctx.connector.id}.ts`);\n }\n\n /**\n * Plugin directory Amp auto-loads `.ts` modules from. PROJECT scope is the\n * documented `<projectDir>/.amp/plugins`; user scope mirrors the MCP config dir\n * (`~/.config/amp/plugins`) for path symmetry only — installHooks never writes\n * there because Amp documents no user-scope plugins dir.\n */\n private pluginsDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".amp\", \"plugins\")\n : join(this.getConfigDir(ctx), \"plugins\");\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 amp\"\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 // Upsert into the flat \"amp.mcpServers\" key, merging into existing settings.\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 Amp's native `amp.mcpServers` entry. */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): AmpStdioServer | AmpHttpServer {\n const transport: Transport = server.transport;\n\n if (transport === \"stdio\") {\n let command = server.command ?? \"\";\n let args = [...(server.args ?? [])];\n\n // Transparent telemetry wrapping: route the real command through\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\n if (shouldWrapForTelemetry(server, ctx.connector.telemetry)) {\n const wrapped = buildServeWrapperCommand(\n ctx.homeBinPath,\n ctx.connector.id,\n command,\n args,\n ctx.scope,\n this.id,\n );\n command = wrapped.command;\n args = wrapped.args;\n }\n\n // Amp expands ${VAR_NAME} natively, so keep refs native (no literals).\n const entry: AmpStdioServer = { command: this.rewrite(command) };\n if (args.length > 0) entry.args = args.map((a) => this.rewrite(a));\n const env = this.renderEnv(server.env);\n if (env) entry.env = env;\n return entry;\n }\n\n // http (and any other remote transport we surface) — Amp registers a URL.\n const entry: AmpHttpServer = { url: this.rewrite(server.url ?? \"\") };\n const headers = this.renderEnv(server.headers);\n if (headers) entry.headers = headers;\n return entry;\n }\n\n /**\n * Render env/header values. Amp supports native `${VAR_NAME}` interpolation,\n * so translate `${env:VAR}` refs to that native token rather than baking\n * secrets into the file. Literals pass through unchanged.\n */\n private renderEnv(\n env: Record<string, string> | undefined,\n ): Record<string, string> | undefined {\n if (!env || Object.keys(env).length === 0) return undefined;\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(env)) out[k] = this.rewrite(v);\n return out;\n }\n\n /** Translate `${env:VAR(:-default)}` to Amp's native `${VAR}` token. */\n private rewrite(value: string): string {\n return rewriteEnvRefs(value, ampEnvToken);\n }\n\n // ── Skills surface ───────────────────────────────────────────────────────\n // CONTENT-ONLY: pure native-file writers under the skill root. No runtime\n // dispatch, no home-bin pointer, no telemetry wrap. Idempotent (byte-identical\n // → skip) via writeContentFile and reversible via removeContentFile. Honors\n // platforms[\"amp\"].skills === false to skip.\n //\n // QUIRK: the skill root is NOT under getConfigDir (~/.config/amp). Amp reads\n // SKILL.md from the sibling cross-agent `agents` tree:\n // user scope → ~/.config/agents/skills/<name>/SKILL.md\n // project scope → <projectDir>/.agents/skills/<name>/SKILL.md\n // so skillDir() resolves it explicitly rather than reusing getConfigDir.\n\n /** Skill root: user `~/.config/agents/skills`, project `<projectDir>/.agents/skills`. */\n private skillsDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".agents\", \"skills\")\n : join(homedir(), \".config\", \"agents\", \"skills\");\n }\n\n /** Native skill dir: <skillRoot>/<name>. */\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 amp\" }];\n }\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n changes.push(\n this.writeContentFile(join(dir, \"SKILL.md\"), this.renderSkill(skill), ctx.dryRun),\n );\n // Bundle any resource files beside SKILL.md (relative path → contents).\n // Defense-in-depth: skip+warn on any key that escapes the skill dir\n // (config-time validation already rejects these, but never trust input).\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n detail: `skill resource \"${rel}\" escapes the skill dir; skipped`,\n });\n continue;\n }\n changes.push(this.writeContentFile(target, contents, ctx.dryRun));\n }\n }\n return changes;\n }\n\n override uninstallSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n // Remove only the files we wrote (SKILL.md + declared resources), then the\n // skill dir itself when we own its full contents.\n changes.push(this.removeContentFile(join(dir, \"SKILL.md\"), ctx.dryRun));\n for (const rel of Object.keys(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) continue; // never delete outside the skill dir\n changes.push(this.removeContentFile(target, ctx.dryRun));\n }\n // Only remove the skill dir when WE own its full contents — never rm -rf a\n // dir that still holds user-added / sibling-tool / shared files.\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\n }\n return changes;\n }\n\n /** Render a skill's SKILL.md (delegates to the shared renderer). */\n private renderSkill(skill: SkillDef): string {\n return renderSkillMd(skill);\n }\n\n // ── Hook install / uninstall (ts-plugin module) ──────────────────────────\n\n installHooks(ctx: InstallContext): ChangeRecord[] {\n const pluginPath = this.getHookConfigPath(ctx);\n\n // Amp documents no user-scope plugins dir — only `.amp/plugins/` at project\n // scope. Degradation is never silent: warn-skip rather than write to an\n // unverified user path.\n if (ctx.scope !== \"project\") {\n return [\n {\n platform: this.id,\n action: \"warn\",\n path: pluginPath,\n detail:\n \"amp plugins are project-scoped (.amp/plugins/) — no user-scope plugins dir is documented; skipped\",\n },\n ];\n }\n\n // Native passthrough events are a sibling, amp-scoped declaration: `hooks:\n // false` disables only the CANONICAL events, and the generated native loop\n // reads platforms.amp.nativeHooks directly (independent of hookEvents). So\n // whenever native events exist the plugin must still be synthesized.\n const canonicalDisabled = ctx.connector.platforms[HOST]?.hooks === false;\n const hasCanonical = !canonicalDisabled && ctx.connector.hookEvents.length > 0;\n const hasNative = this.nativeHookEvents(ctx).length > 0;\n\n if (!hasCanonical && !hasNative) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: pluginPath,\n detail: canonicalDisabled\n ? \"hooks disabled for amp\"\n : \"connector declares no hooks\",\n },\n ];\n }\n\n const files = this.synthesizePlugin(ctx);\n const changes: ChangeRecord[] = [];\n\n for (const file of files) {\n // Idempotent: compare existing contents before writing.\n const before = existsSync(file.path) ? this.safeRead(file.path) : undefined;\n let action: ChangeRecord[\"action\"];\n if (before === undefined) action = \"create\";\n else if (before === file.contents) action = \"skip\";\n else action = \"update\";\n\n if (action !== \"skip\" && !ctx.dryRun) {\n ensureDir(dirname(file.path));\n writeFileSync(file.path, file.contents, \"utf8\");\n chmodSync(file.path, file.executable ? 0o755 : 0o644);\n }\n\n changes.push({\n platform: this.id,\n action,\n path: file.path,\n detail: `amp plugin module (${this.hookDetail(ctx)})`,\n });\n }\n\n return changes;\n }\n\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n const pluginPath = this.getHookConfigPath(ctx);\n if (!existsSync(pluginPath)) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: pluginPath,\n detail: \"no amp plugin module present\",\n },\n ];\n }\n if (!ctx.dryRun) rmSync(pluginPath, { force: true });\n return [\n {\n platform: this.id,\n action: \"remove\",\n path: pluginPath,\n detail: \"amp plugin module\",\n },\n ];\n }\n\n /**\n * Human-facing summary of which declared events the synthesized module ACTUALLY\n * wires. Only events present in EVENT_TO_AMP are mapped/wired; any declared\n * event with no Amp mapping (e.g. SessionEnd) is reported separately as\n * \"unsupported here\" so the detail never overstates coverage.\n */\n private hookDetail(ctx: InstallContext): string {\n // `hooks: false` suppresses the canonical handlers, so the detail must not\n // claim them; native events are still reported below.\n const canonicalOff = ctx.connector.platforms[HOST]?.hooks === false;\n const declared = canonicalOff ? [] : ctx.connector.hookEvents;\n const mapped = declared.filter((e) => EVENT_TO_AMP[e] !== undefined);\n const unsupported = declared.filter((e) => EVENT_TO_AMP[e] === undefined);\n const native = this.nativeHookEvents(ctx);\n const parts: string[] = [];\n if (mapped.length > 0) parts.push(mapped.join(\",\"));\n if (native.length > 0) parts.push(`native: ${native.join(\",\")}`);\n const base = parts.join(\"; \") || \"no canonical hooks\";\n return unsupported.length > 0\n ? `${base}; unsupported here: ${unsupported.join(\",\")}`\n : base;\n }\n\n /**\n * Amp-native passthrough events declared on platforms[\"amp\"].nativeHooks\n * (amp.on event names with no canonical HookEventName analog). Emitted as\n * generic bridge registrations and dispatched host-generically by the home-bin's\n * runNativeHook.\n */\n private nativeHookEvents(ctx: InstallContext): string[] {\n return Object.keys(ctx.connector.platforms[HOST]?.nativeHooks ?? {});\n }\n\n // ── ts-plugin synthesis ──────────────────────────────────────────────────\n\n /**\n * Build ONE self-contained Amp plugin module (`.amp/plugins/<id>.ts`). It\n * imports nothing from agent-connector; each `amp.on(...)` handler shells out to\n * the universal hook entrypoint via child_process and applies the normalized\n * HookResponse. Its default export is the Amp plugin function `(amp) => void`.\n */\n synthesizePlugin(ctx: InstallContext): GeneratedPluginFile[] {\n const path = this.getHookConfigPath(ctx);\n const contents = this.buildPluginSource(ctx);\n return [{ path, contents, executable: false }];\n }\n\n /** Compose the generated plugin source with plain string concatenation. */\n private buildPluginSource(ctx: InstallContext): string {\n const homeBin = JSON.stringify(ctx.homeBinPath);\n const connectorId = JSON.stringify(ctx.connector.id);\n\n // `platforms.amp.hooks === false` disables only the CANONICAL events (the\n // native loop below reads platforms.amp.nativeHooks directly and is a sibling,\n // unaffected). When canonical hooks are off the module may still be\n // synthesized for native events, so the canonical handler set collapses to\n // empty here rather than short-circuiting the whole plugin.\n const canonicalOff = ctx.connector.platforms[HOST]?.hooks === false;\n const events = canonicalOff\n ? []\n : ctx.connector.hookEvents.filter(\n (e): e is HookEventName => EVENT_TO_AMP[e] !== undefined,\n );\n const has = (e: HookEventName) => events.includes(e);\n\n const header = `/**\n * AUTO-GENERATED by agent-connector — DO NOT EDIT.\n *\n * Self-contained Amp plugin for connector ${ctx.connector.id}.\n * It imports nothing from agent-connector: every hook invocation shells out to\n * the stable home binary's universal entrypoint and JSON-parses the normalized\n * response. Fail-open: any bridge error degrades to a no-op (never wedges Amp).\n *\n * Amp loads this module from .amp/plugins/${ctx.connector.id}.ts; the default\n * export is the plugin function (amp) => void called once with the PluginAPI.\n */\nimport type { PluginAPI } from \"@ampcode/plugin\";\nimport { execFileSync, execSync } from \"node:child_process\";\n\nconst HOME_BIN = ${homeBin};\nconst CONNECTOR_ID = ${connectorId};\n\n/**\n * Invoke the universal hook entrypoint for one event.\n * @param {string} event canonical event name\n * @param {object} payload amp-shaped payload posted on stdin\n * @returns {object|null} normalized HookResponse, or null on any failure\n */\nfunction bridge(event, payload) {\n try {\n // On Windows HOME_BIN is the agent-connector.cmd launcher: Node cannot\n // execFile a batch file, and shell+args is deprecated (DEP0190), so run one\n // quoted command line via a shell. POSIX keeps the direct execFile (no shell).\n const args = [\"hook\", \"amp\", event, \"--connector\", CONNECTOR_ID];\n const opts = { input: JSON.stringify(payload), encoding: \"utf8\" };\n const stdout =\n process.platform === \"win32\"\n ? execSync([HOME_BIN, ...args].map((a) => '\"' + a + '\"').join(\" \"), opts)\n : execFileSync(HOME_BIN, args, opts);\n const text = (stdout || \"\").trim();\n if (text === \"\") return { decision: \"allow\" };\n return JSON.parse(text);\n } catch {\n // Fail-open — never wedge an Amp tool call / lifecycle event.\n return null;\n }\n}\n\n// Amp documents no project-dir env var; the plugin process runs in the workspace\n// root, so resolve once at load. Session id is rebound on each session.start.\nconst PROJECT_DIR = process.cwd();\nlet SESSION_ID = \"\";\n`;\n\n const handlers: string[] = [];\n\n if (has(\"SessionStart\")) {\n handlers.push(` // SessionStart → rebind the session id and notify the connector.\n // Amp's session.start event carries event.thread.id (ampcode.com/manual →\n // Plugins → session.start: \"Example session.start for \\${event.thread.id}\").\n amp.on(\"session.start\", async (event) => {\n SESSION_ID =\n (event && event.thread && event.thread.id) || \"amp-session\";\n bridge(\"SessionStart\", { sessionId: SESSION_ID, projectDir: PROJECT_DIR });\n });`);\n }\n\n if (has(\"UserPromptSubmit\")) {\n handlers.push(` // UserPromptSubmit → agent.start \"fires when the user submits a prompt\"\n // (ampcode.com/manual). The manual's example takes (_event) and documents no\n // prompt field or return surface, so this is observe-only — the raw event is\n // forwarded for the connector to inspect; any deny/context decision is a no-op.\n amp.on(\"agent.start\", async (event) => {\n bridge(\"UserPromptSubmit\", {\n sessionId: SESSION_ID,\n projectDir: PROJECT_DIR,\n raw: event,\n });\n });`);\n }\n\n if (has(\"PreToolUse\")) {\n handlers.push(` // PreToolUse → Amp's tool.call returns a decision union (ampcode.com/manual →\n // Plugins → tool.call): { action: \"allow\" } to run, or { action:\n // \"reject-and-continue\", message } to block and let the agent continue. The\n // tool name is event.tool (verified); the input field is not byte-documented,\n // so event.input is a best-effort hint for the connector's matcher (the matcher\n // keys on the verified tool name). A deny/ask decision maps to reject-and-\n // continue; everything else allows.\n amp.on(\"tool.call\", async (event) => {\n const payload = {\n toolName: (event && event.tool) || \"\",\n toolInput: (event && event.input) || {},\n sessionId: SESSION_ID,\n projectDir: PROJECT_DIR,\n };\n const res = bridge(\"PreToolUse\", payload);\n if (res && (res.decision === \"deny\" || res.decision === \"ask\")) {\n return {\n action: \"reject-and-continue\",\n message: res.reason || \"Blocked by ${ctx.connector.id}\",\n };\n }\n return { action: \"allow\" };\n });`);\n }\n\n if (has(\"PostToolUse\")) {\n handlers.push(` // PostToolUse → tool.result \"fires after a tool finishes and before the result\n // is sent back to the model\" (ampcode.com/manual). The tool name is event.tool\n // and the error signal is event.status === \"error\" (both verified). The manual\n // says a replacement status/output CAN be returned but never documents the\n // replacement object shape, so this is observe-only (canModifyOutput:false) —\n // the raw event is forwarded; we never return a guessed replacement.\n amp.on(\"tool.result\", async (event) => {\n bridge(\"PostToolUse\", {\n toolName: (event && event.tool) || \"\",\n isError: !!(event && event.status === \"error\"),\n sessionId: SESSION_ID,\n projectDir: PROJECT_DIR,\n raw: event,\n });\n });`);\n }\n\n if (has(\"Stop\")) {\n handlers.push(` // Stop → observe turn end. Amp's agent.end exposes no decision surface, so\n // this is observe-only (a deny decision degrades to a no-op).\n amp.on(\"agent.end\", async (event) => {\n bridge(\"Stop\", { sessionId: SESSION_ID, projectDir: PROJECT_DIR, raw: event });\n });`);\n }\n\n // NATIVE passthrough events: amp.on event names with no canonical analog,\n // declared on platforms.amp.nativeHooks (independent of hookEvents, so they\n // install even with hooks:false). Each bridges the NATIVE event name verbatim\n // to the home-bin → runNativeHook dispatches it host-generically.\n for (const ev of this.nativeHookEvents(ctx)) {\n const key = JSON.stringify(ev);\n handlers.push(` // nativeHooks passthrough → ${ev}\n amp.on(${key}, async (event) => {\n bridge(${key}, { sessionId: SESSION_ID, projectDir: PROJECT_DIR, raw: event });\n });`);\n }\n\n const factory = `\nexport default function plugin(amp: PluginAPI) {\n${handlers.join(\"\\n\\n\")}\n}\n`;\n\n return header + factory;\n }\n\n // ── Runtime: parse OUR bridge payload → normalized event ─────────────────\n\n /**\n * `raw` is the payload OUR generated plugin posts (NOT a host-native shape):\n * { toolName?, toolInput?, toolOutput?, isError?, prompt?, sessionId?, projectDir? }\n * so this maps straight through.\n */\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\n const input = (raw ?? {}) as AmpBridgePayload;\n const base = {\n hostPlatform: HOST,\n connectorId: \"\",\n sessionId: typeof input.sessionId === \"string\" ? input.sessionId : \"\",\n raw,\n ...(typeof input.projectDir === \"string\"\n ? { projectDir: input.projectDir }\n : {}),\n } as const;\n\n switch (event) {\n case \"PreToolUse\": {\n const ev: PreToolUseEvent = {\n ...base,\n toolName: input.toolName ?? \"\",\n toolInput: input.toolInput ?? {},\n };\n return ev;\n }\n case \"PostToolUse\": {\n const ev: PostToolUseEvent = {\n ...base,\n toolName: input.toolName ?? \"\",\n toolInput: input.toolInput ?? {},\n ...(typeof input.toolOutput === \"string\"\n ? { toolOutput: input.toolOutput }\n : {}),\n ...(typeof input.isError === \"boolean\"\n ? { isError: input.isError }\n : {}),\n };\n return ev;\n }\n case \"UserPromptSubmit\": {\n const ev: UserPromptSubmitEvent = {\n ...base,\n prompt: typeof input.prompt === \"string\" ? input.prompt : \"\",\n };\n return ev;\n }\n case \"Stop\": {\n const ev: StopEvent = { ...base };\n return ev;\n }\n case \"SessionStart\": {\n const ev: SessionStartEvent = { ...base, source: \"startup\" };\n return ev;\n }\n default:\n // Other canonical events are not surfaced by Amp; treat as a\n // session-start-shaped no-op so the dispatcher fails open gracefully.\n return { ...base, source: \"startup\" } satisfies SessionStartEvent;\n }\n }\n\n // ── Runtime: normalized response → reply the generated bridge parses ─────\n\n /**\n * Unlike json-stdio hosts (whose reply is the host's NATIVE control payload),\n * OUR generated bridge consumes this stdout directly. So the reply body is the\n * NORMALIZED HookResponse itself — the bridge JSON.parses it and, for tool.call,\n * maps a deny/ask decision → { action: \"reject-and-continue\" } (else allow).\n * Other events are observe-only, so their reply is ignored by the handler.\n */\n formatReply(_event: HookEventName, response: HookResponse): HookReply {\n return {\n exitCode: 0,\n stdout: JSON.stringify(response ?? { decision: \"allow\" }),\n };\n }\n\n // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const settingsPath = this.getServerConfigPath(ctx);\n const connectorId = ctx.connector.id;\n return [\n {\n name: `${this.name}: settings.json present`,\n check: () =>\n existsSync(settingsPath)\n ? { status: \"OK\", detail: settingsPath }\n : { status: \"FAIL\", detail: `not found: ${settingsPath}` },\n },\n {\n name: `${this.name}: server entry registered`,\n check: () => {\n // Only assert what the connector declares: a server-less connector\n // never writes a server entry, so its absence is healthy.\n if (!ctx.connector.server) {\n return { status: \"OK\", detail: \"no MCP server declared\" };\n }\n const cfg = this.readJson<{ [k: string]: Record<string, unknown> }>(settingsPath);\n const bucket = cfg?.[MCP_ROOT_KEY];\n if (!cfg || !bucket) {\n return { status: \"FAIL\", detail: `no \"${MCP_ROOT_KEY}\" in ${settingsPath}` };\n }\n return connectorId in bucket\n ? { status: \"OK\", detail: `\"${MCP_ROOT_KEY}\".${connectorId} present` }\n : {\n status: \"FAIL\",\n detail: `no \"${MCP_ROOT_KEY}\".${connectorId} in ${settingsPath}`,\n };\n },\n },\n {\n name: `${this.name}: plugin module present`,\n check: () => {\n const hasHooks =\n ctx.connector.hookEvents.length > 0 ||\n this.nativeHookEvents(ctx).length > 0;\n if (!hasHooks) return { status: \"OK\", detail: \"no hooks declared\" };\n // Amp plugins are project-scoped; a user-scope install warn-skips the\n // plugin, so its absence there is healthy.\n if (ctx.scope !== \"project\") {\n return {\n status: \"OK\",\n detail: \"amp plugins are project-scoped (user scope skipped)\",\n };\n }\n const pluginPath = this.getHookConfigPath(ctx);\n return existsSync(pluginPath)\n ? { status: \"OK\", detail: pluginPath }\n : { status: \"FAIL\", detail: `not found: ${pluginPath}` };\n },\n },\n ];\n }\n\n /** Read a file, returning undefined on any error (idempotency compare). */\n private safeRead(path: string): string | undefined {\n try {\n return readFileSync(path, \"utf8\");\n } catch {\n return undefined;\n }\n }\n}\n\n/** Create a directory (recursive) if it does not already exist. */\nfunction ensureDir(dir: string): void {\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n}\n\n/**\n * Amp native interpolation token: `${env:VAR}` → `${VAR}`.\n *\n * When the portable ref carried a default (`${env:VAR:-fallback}`), Amp's native\n * `${VAR}` token has no way to express it — so a bare native token would silently\n * DROP the default. Instead, resolve the default at install time: emit the live\n * value when VAR is set and non-empty, else the literal fallback. The native\n * token is only emitted when there is no default to preserve.\n */\nfunction ampEnvToken(name: string, def?: string): string {\n if (def !== undefined) {\n const v = process.env[name];\n return v != null && v !== \"\" ? v : def;\n }\n return `\\${${name}}`;\n}\n\nexport const adapter = new AmpAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/adapters/claude-code/render.ts"],"sourcesContent":["/**\n * adapters/claude-code/render — shared content-surface renderers.\n *\n * The single source of truth for how a connector's commands / skills / subagents\n * are serialized into Claude Code's native `md + YAML-frontmatter` documents.\n * BOTH the live claude-code adapter (which writes into ~/.claude or .claude when\n * installing) AND `core/package` (which emits a marketplace-installable plugin\n * bundle) import these so the two paths produce BYTE-IDENTICAL output — there is\n * no second, subtly-different copy to drift.\n *\n * The frontmatter serializer reuses the `yaml` package (the same serializer\n * core/yaml and BaseAdapter.renderFrontmatterMd use): a `---` fence, the YAML\n * block, a closing `---`, a blank line, then the markdown body and a trailing\n * newline.\n */\n\nimport { stringify as stringifyYaml } from \"yaml\";\n\nimport type { CommandDef, SkillDef, SubagentDef } from \"../../core/types.js\";\n\n/**\n * Render a YAML-frontmatter + markdown body document:\n * \"---\\n\" + <yaml> + \"---\\n\\n\" + <body> + \"\\n\".\n * Identical to BaseAdapter.renderFrontmatterMd (which now delegates here).\n */\nexport function renderFrontmatterMd(\n frontmatter: Record<string, unknown>,\n body: string,\n): string {\n return `---\\n${stringifyYaml(frontmatter)}---\\n\\n${body}\\n`;\n}\n\n/**\n * Render a command to md+frontmatter\n * (description, argument-hint, allowed-tools, model + verbatim extra).\n */\nexport function renderCommandMd(cmd: CommandDef): string {\n const frontmatter: Record<string, unknown> = {};\n if (cmd.description !== undefined) frontmatter.description = cmd.description;\n if (cmd.argumentHint !== undefined) frontmatter[\"argument-hint\"] = cmd.argumentHint;\n const allow = cmd.tools?.allow;\n if (allow && allow.length > 0) frontmatter[\"allowed-tools\"] = allow.join(\", \");\n if (cmd.model !== undefined) frontmatter.model = cmd.model;\n if (cmd.extra) Object.assign(frontmatter, cmd.extra);\n return renderFrontmatterMd(frontmatter, cmd.prompt);\n}\n\n/**\n * Render a skill's SKILL.md: frontmatter (name, description + optional model,\n * allowed-tools, disable-model-invocation, verbatim extra) + body.\n */\nexport function renderSkillMd(skill: SkillDef): string {\n const frontmatter: Record<string, unknown> = {\n name: skill.name,\n description: skill.description,\n };\n if (skill.model !== undefined) frontmatter.model = skill.model;\n const allow = skill.tools?.allow;\n if (allow && allow.length > 0) frontmatter[\"allowed-tools\"] = allow.join(\", \");\n if (skill.disableModelInvocation !== undefined) {\n frontmatter[\"disable-model-invocation\"] = skill.disableModelInvocation;\n }\n if (skill.extra) Object.assign(frontmatter, skill.extra);\n return renderFrontmatterMd(frontmatter, skill.body);\n}\n\n/** Render a subagent to md+frontmatter (name, description, tools, model) + prompt body. */\nexport function renderSubagentMd(agent: SubagentDef): string {\n const frontmatter: Record<string, unknown> = {\n name: agent.name,\n description: agent.description,\n };\n const allow = agent.tools?.allow;\n if (allow && allow.length > 0) frontmatter.tools = allow.join(\", \");\n if (agent.model !== undefined) frontmatter.model = agent.model;\n if (agent.extra) Object.assign(frontmatter, agent.extra);\n return renderFrontmatterMd(frontmatter, agent.prompt);\n}\n"],"mappings":";;;AAgBA,SAAS,aAAa,qBAAqB;AASpC,SAAS,oBACd,aACA,MACQ;AACR,SAAO;AAAA,EAAQ,cAAc,WAAW,CAAC;AAAA;AAAA,EAAU,IAAI;AAAA;AACzD;AAMO,SAAS,gBAAgB,KAAyB;AACvD,QAAM,cAAuC,CAAC;AAC9C,MAAI,IAAI,gBAAgB,OAAW,aAAY,cAAc,IAAI;AACjE,MAAI,IAAI,iBAAiB,OAAW,aAAY,eAAe,IAAI,IAAI;AACvE,QAAM,QAAQ,IAAI,OAAO;AACzB,MAAI,SAAS,MAAM,SAAS,EAAG,aAAY,eAAe,IAAI,MAAM,KAAK,IAAI;AAC7E,MAAI,IAAI,UAAU,OAAW,aAAY,QAAQ,IAAI;AACrD,MAAI,IAAI,MAAO,QAAO,OAAO,aAAa,IAAI,KAAK;AACnD,SAAO,oBAAoB,aAAa,IAAI,MAAM;AACpD;AAMO,SAAS,cAAc,OAAyB;AACrD,QAAM,cAAuC;AAAA,IAC3C,MAAM,MAAM;AAAA,IACZ,aAAa,MAAM;AAAA,EACrB;AACA,MAAI,MAAM,UAAU,OAAW,aAAY,QAAQ,MAAM;AACzD,QAAM,QAAQ,MAAM,OAAO;AAC3B,MAAI,SAAS,MAAM,SAAS,EAAG,aAAY,eAAe,IAAI,MAAM,KAAK,IAAI;AAC7E,MAAI,MAAM,2BAA2B,QAAW;AAC9C,gBAAY,0BAA0B,IAAI,MAAM;AAAA,EAClD;AACA,MAAI,MAAM,MAAO,QAAO,OAAO,aAAa,MAAM,KAAK;AACvD,SAAO,oBAAoB,aAAa,MAAM,IAAI;AACpD;AAGO,SAAS,iBAAiB,OAA4B;AAC3D,QAAM,cAAuC;AAAA,IAC3C,MAAM,MAAM;AAAA,IACZ,aAAa,MAAM;AAAA,EACrB;AACA,QAAM,QAAQ,MAAM,OAAO;AAC3B,MAAI,SAAS,MAAM,SAAS,EAAG,aAAY,QAAQ,MAAM,KAAK,IAAI;AAClE,MAAI,MAAM,UAAU,OAAW,aAAY,QAAQ,MAAM;AACzD,MAAI,MAAM,MAAO,QAAO,OAAO,aAAa,MAAM,KAAK;AACvD,SAAO,oBAAoB,aAAa,MAAM,MAAM;AACtD;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/jsonc.ts","../src/adapters/base.ts"],"sourcesContent":["/**\n * core/jsonc — tolerant JSONC / JSON5-lite parsing.\n *\n * Many hosts document their config file as JSONC (or JSON5): // line comments,\n * /* *\\/ block comments, and trailing commas are all legal. A strict JSON.parse\n * false-fails such a perfectly valid file → null → and a careless `?? {}` then\n * OVERWRITES the user's entire config with just our entry (data loss). To avoid\n * that, every JSON/JSONC adapter parses through `parseJsonc`, which strips\n * comments + trailing commas in ONE string-aware pass before JSON.parse.\n *\n * The single pass is deliberately string-literal aware: a // or /* inside a\n * quoted value (e.g. \"http://x//y\") is NOT a comment, and a comma inside a\n * string (e.g. \"a,]\") is NOT a trailing comma — both must survive verbatim.\n */\n\n/**\n * Strip // line comments, /* *\\/ block comments, and trailing commas from JSONC\n * text in a SINGLE string-aware pass.\n *\n * Rules:\n * - While inside a string literal, every character (including //, /*, and ,)\n * is copied verbatim; backslash escapes the next character.\n * - Outside a string, // … runs to end-of-line and /* … *\\/ to its close.\n * - A comma is dropped ONLY when the next non-whitespace, non-comment token is\n * a closing `}` or `]` (a trailing comma). A comma followed by another value\n * or by end-of-input is preserved (the latter lets JSON.parse report the\n * real syntax error instead of us masking it).\n */\nexport function stripJsonc(text: string): string {\n const n = text.length;\n let out = \"\";\n let i = 0;\n let inString = false;\n let quote = \"\";\n\n while (i < n) {\n const ch = text[i] as string;\n\n if (inString) {\n out += ch;\n if (ch === \"\\\\\") {\n // Copy the escaped character verbatim (covers \\\" \\\\ \\/ etc.).\n if (i + 1 < n) {\n out += text[i + 1] as string;\n i += 2;\n continue;\n }\n } else if (ch === quote) {\n inString = false;\n }\n i += 1;\n continue;\n }\n\n const next = i + 1 < n ? (text[i + 1] as string) : \"\";\n\n // Enter a string literal.\n if (ch === '\"' || ch === \"'\") {\n inString = true;\n quote = ch;\n out += ch;\n i += 1;\n continue;\n }\n\n // Line comment — skip to end of line (keep the newline for line tracking).\n if (ch === \"/\" && next === \"/\") {\n i += 2;\n while (i < n && text[i] !== \"\\n\") i += 1;\n continue;\n }\n\n // Block comment — skip to the closing */.\n if (ch === \"/\" && next === \"*\") {\n i += 2;\n while (i < n && !(text[i] === \"*\" && text[i + 1] === \"/\")) i += 1;\n i += 2; // consume the closing */\n continue;\n }\n\n // Trailing comma — drop it only when the next significant token (skipping\n // whitespace AND comments) is a closing } or ]. This stays string-aware\n // because we only reach here outside a string.\n if (ch === \",\") {\n const closer = nextSignificant(text, i + 1);\n if (closer === \"}\" || closer === \"]\") {\n i += 1; // drop the trailing comma\n continue;\n }\n }\n\n out += ch;\n i += 1;\n }\n\n return out;\n}\n\n/**\n * Peek the next significant (non-whitespace, non-comment) character at/after\n * `from`, returning \"\" at end-of-input. Used only outside string literals.\n */\nfunction nextSignificant(text: string, from: number): string {\n const n = text.length;\n let i = from;\n while (i < n) {\n const ch = text[i] as string;\n if (ch === \" \" || ch === \"\\t\" || ch === \"\\r\" || ch === \"\\n\") {\n i += 1;\n continue;\n }\n const next = i + 1 < n ? (text[i + 1] as string) : \"\";\n if (ch === \"/\" && next === \"/\") {\n i += 2;\n while (i < n && text[i] !== \"\\n\") i += 1;\n continue;\n }\n if (ch === \"/\" && next === \"*\") {\n i += 2;\n while (i < n && !(text[i] === \"*\" && text[i + 1] === \"/\")) i += 1;\n i += 2;\n continue;\n }\n return ch;\n }\n return \"\";\n}\n\n/**\n * Parse JSONC text tolerantly: strip comments + trailing commas, then JSON.parse.\n * Throws (like JSON.parse) on genuinely malformed input — callers that want a\n * fail-soft null should wrap in try/catch (BaseAdapter.readJson does).\n */\nexport function parseJsonc<T = unknown>(text: string): T {\n return JSON.parse(stripJsonc(text)) as T;\n}\n","/**\n * adapters/base — shared adapter foundation.\n *\n * Provides JSON config IO, settings backup, and a default doctor. Per-platform\n * specifics (paths, capabilities, native render format, runtime parse/format)\n * are abstract and implemented by each adapter. TOML/YAML adapters override the\n * JSON helpers entirely.\n */\n\nimport {\n copyFileSync,\n existsSync,\n readdirSync,\n readFileSync,\n rmSync,\n statSync,\n writeFileSync,\n} from \"node:fs\";\nimport type { Dirent } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\n\nimport type {\n ChangeRecord,\n DetectedPlatform,\n DiagnosticResult,\n HealthCheck,\n HookParadigm,\n PlatformCapabilities,\n PlatformId,\n PlatformMemoryOverride,\n} from \"../core/types.js\";\nimport { backupsDir, ensureDir } from \"../core/paths.js\";\nimport { parseJsonc } from \"../core/jsonc.js\";\nimport { buildHomeBinActionCommand } from \"../core/spawn.js\";\nimport {\n MEMORY_CONTENT_SOFT_BUDGET_BYTES,\n listManagedBlocks,\n loadMemoryLedger,\n recordMemoryTarget,\n removeManagedBlocksFile,\n saveMemoryLedger,\n upsertManagedBlockFile,\n} from \"../core/managed-block.js\";\nimport { renderFrontmatterMd } from \"./claude-code/render.js\";\nimport type { Adapter, InstallContext, MemoryTarget } from \"./spi.js\";\n\n/** Content-surface kinds with BaseAdapter default install/uninstall handling. */\ntype ContentSurface =\n | \"commands\"\n | \"skills\"\n | \"subagents\"\n | \"memory\"\n | \"statusline\"\n | \"actions\";\n\n/**\n * One resolved action trigger for an EMITTER adapter: the host-native trigger\n * the adapter writes runs `command`, which re-enters the home binary at the\n * `action` verb. `label`/`description` fall back to the action id when the\n * connector declared none. Produced by {@link BaseAdapter.actionTriggers}.\n */\nexport interface ActionTrigger {\n /** The action id — also the per-action file/key name on most hosts. */\n id: string;\n /** Display label (action.description ?? action.id). */\n label: string;\n /** One-line description (action.description ?? action.id). */\n description: string;\n /** `<homeBin> action <host> <id> --connector <connectorId>` (the verb the host runs). */\n command: string;\n}\n\n/**\n * Documented USER-scope AGENTS.md locations, per host (the AGENTS.md-first\n * research matrix). Only hosts with a REAL user/global AGENTS.md file are\n * listed. Hosts whose documented user-scope memory lives in a DIFFERENT file\n * (qwen-code ~/.qwen/QWEN.md, goose .goosehints, kilo/roo/kiro rules dirs,\n * copilot-cli copilot-instructions.md) override memoryTargets in-adapter;\n * hosts whose user rules are app/UI/cloud-managed (warp Drive, trae,\n * jetbrains/cursor settings UI) deliberately have no row — user-scope memory\n * there reports the standard skip-warn (the JetBrains-MCP precedent), never a\n * write into a file the host ignores.\n */\nconst AGENTS_MD_USER_PATHS: Partial<Record<PlatformId, () => MemoryTarget>> = {\n // codex resolves its own user path in-adapter ($CODEX_HOME with ~ expansion\n // + the AGENTS.override.md shadow probe) — deliberately no row here.\n zed: () => ({\n path:\n process.platform === \"win32\" && process.env.APPDATA\n ? join(process.env.APPDATA, \"Zed\", \"AGENTS.md\")\n : join(homedir(), \".config\", \"zed\", \"AGENTS.md\"),\n reason: \"zed personal instructions file\",\n }),\n amp: () => ({\n path: join(homedir(), \".config\", \"amp\", \"AGENTS.md\"),\n reason: \"amp user-scope AGENTS.md\",\n }),\n mux: () => ({\n path: join(homedir(), \".mux\", \"AGENTS.md\"),\n reason: \"mux global AGENTS.md\",\n }),\n pi: () => ({\n path: join(homedir(), \".pi\", \"agent\", \"AGENTS.md\"),\n reason: \"pi global AGENTS.md\",\n }),\n droid: () => ({\n path: join(homedir(), \".factory\", \"AGENTS.md\"),\n reason: \"droid (Factory) personal AGENTS.md\",\n }),\n opencode: () => ({\n path: join(homedir(), \".config\", \"opencode\", \"AGENTS.md\"),\n reason: \"opencode global AGENTS.md\",\n }),\n antigravity: () => ({\n path: join(homedir(), \".gemini\", \"AGENTS.md\"),\n reason: \"antigravity global rules (~/.gemini/AGENTS.md, shared tree)\",\n }),\n \"antigravity-cli\": () => ({\n path: join(homedir(), \".gemini\", \"AGENTS.md\"),\n reason: \"agy shares the IDE's ~/.gemini tree (idempotent upsert dedupes)\",\n }),\n omp: () => ({\n path: join(homedir(), \".omp\", \"agent\", \"AGENTS.md\"),\n reason: \"omp global AGENTS.md (pi-parity; verify for your version)\",\n }),\n};\n\nexport abstract class BaseAdapter implements Adapter {\n abstract readonly id: PlatformId;\n abstract readonly name: string;\n abstract readonly paradigm: HookParadigm;\n abstract readonly capabilities: PlatformCapabilities;\n\n abstract detectInstalled(projectDir: string): DetectedPlatform;\n abstract getConfigDir(ctx: InstallContext): string;\n abstract getServerConfigPath(ctx: InstallContext): string;\n abstract getHookConfigPath(ctx: InstallContext): string;\n abstract installServer(ctx: InstallContext): ChangeRecord[];\n abstract uninstallServer(ctx: InstallContext): ChangeRecord[];\n abstract installHooks(ctx: InstallContext): ChangeRecord[];\n abstract uninstallHooks(ctx: InstallContext): ChangeRecord[];\n\n // ── Content surfaces (commands / skills / subagents) ─────────────────────\n // CONCRETE (overridable) defaults so every adapter inherits all six methods\n // and the installer can call them without optional-chaining. Each returns a\n // single skip when the connector declares no entries of that surface, else a\n // single \"warn\" — mirroring the mcp-only hook handling. Supporting adapters\n // override only the surfaces they honor.\n\n installCommands(ctx: InstallContext): ChangeRecord[] {\n return this.unsupportedSurface(ctx, \"commands\", ctx.connector.commands.length);\n }\n uninstallCommands(ctx: InstallContext): ChangeRecord[] {\n return this.unsupportedSurface(ctx, \"commands\", ctx.connector.commands.length);\n }\n installSkills(ctx: InstallContext): ChangeRecord[] {\n return this.unsupportedSurface(ctx, \"skills\", ctx.connector.skills.length);\n }\n uninstallSkills(ctx: InstallContext): ChangeRecord[] {\n return this.unsupportedSurface(ctx, \"skills\", ctx.connector.skills.length);\n }\n installSubagents(ctx: InstallContext): ChangeRecord[] {\n return this.unsupportedSurface(ctx, \"subagents\", ctx.connector.subagents.length);\n }\n uninstallSubagents(ctx: InstallContext): ChangeRecord[] {\n return this.unsupportedSurface(ctx, \"subagents\", ctx.connector.subagents.length);\n }\n\n // ── Memory surface (managed marker blocks; AGENTS.md-first) ───────────────\n // ONE generic implementation for every supporting host: the per-adapter\n // `memoryTargets()` hook resolves WHERE to write (AGENTS.md defaults below;\n // claude-code → CLAUDE.md and gemini-cli → GEMINI.md override it), and the\n // core/managed-block engine performs the surgical, hash-stamped block edit.\n // Unlike commands/skills/subagents these files are SHARED and user-authored —\n // bytes outside this connector's own marker pair are never touched.\n\n /**\n * Resolve the memory/rules file(s) this host actually reads at ctx.scope.\n * Base default (AGENTS.md-first, owner mandate):\n * - an explicit `platforms[<id>].memory.path` override wins;\n * - project scope → `<projectDir>/AGENTS.md` (the agents.md standard);\n * - user scope → the host's documented user-scope AGENTS.md, when one\n * exists ({@link AGENTS_MD_USER_PATHS}); otherwise [] → skip-warn.\n * Exception hosts (claude-code, gemini-cli) override this hook.\n */\n protected memoryTargets(ctx: InstallContext): MemoryTarget[] {\n const override = this.memoryOverride(ctx);\n if (override?.path) {\n const base = ctx.scope === \"project\" ? ctx.projectDir : homedir();\n return [\n {\n path: isAbsolute(override.path) ? override.path : join(base, override.path),\n reason: `platforms.${this.id}.memory.path override`,\n },\n ];\n }\n if (ctx.scope === \"project\") {\n return [\n { path: join(ctx.projectDir, \"AGENTS.md\"), reason: \"AGENTS.md standard (project root)\" },\n ];\n }\n if (ctx.scope === \"user\") {\n const user = AGENTS_MD_USER_PATHS[this.id]?.();\n return user ? [user] : [];\n }\n return [];\n }\n\n /** The per-platform memory override object, when one is declared. */\n protected memoryOverride(ctx: InstallContext): PlatformMemoryOverride | undefined {\n const o = ctx.connector.platforms[this.id]?.memory;\n return o && typeof o === \"object\" ? o : undefined;\n }\n\n installMemory(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n // `?? []` tolerates pre-resolved connectors from versions before the\n // memory surface existed (the installer applies the same guard).\n const entries = connector.memory ?? [];\n if (connector.platforms[this.id]?.memory === false) {\n return [{ platform: this.id, action: \"skip\", detail: `memory disabled for ${this.id}` }];\n }\n if (entries.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no memory\" }];\n }\n if (!(this.capabilities.supportsMemory ?? false)) {\n return this.unsupportedSurface(ctx, \"memory\", entries.length);\n }\n\n const changes: ChangeRecord[] = [];\n const override = this.memoryOverride(ctx);\n if (override?.mode && this.id !== \"claude-code\") {\n changes.push({\n platform: this.id,\n action: \"warn\",\n detail: `memory.mode is claude-code-only; ignored on ${this.id}`,\n });\n }\n if (ctx.scope !== \"project\" && ctx.scope !== \"user\") {\n // system/profile/managed memory files are admin-owned — out of scope (v1).\n changes.push({\n platform: this.id,\n action: \"warn\",\n detail:\n `memory not supported at ${ctx.scope} scope on ${this.id} ` +\n `(managed/admin memory files are out of scope); ${entries.length} skipped`,\n });\n return changes;\n }\n const targets = this.memoryTargets(ctx);\n if (targets.length === 0) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n detail:\n `no ${ctx.scope}-scope memory file on ${this.id} ` +\n `(user rules are app/UI-managed or undocumented); ${entries.length} skipped`,\n });\n return changes;\n }\n changes.push(...this.writeMemoryBlocks(ctx, targets));\n return changes;\n }\n\n /**\n * Upsert every declared memory entry's block into every resolved target and\n * record the ownership ledger rows (`connectorDir(id)/memory-state.json`).\n * Shared by the base implementation and the exception-host overrides.\n */\n protected writeMemoryBlocks(ctx: InstallContext, targets: MemoryTarget[]): ChangeRecord[] {\n const changes: ChangeRecord[] = [];\n const ledger = loadMemoryLedger(ctx.connector.id);\n let ledgerMutated = false;\n\n for (const target of targets) {\n for (const entry of ctx.connector.memory ?? []) {\n const blockId = `${ctx.connector.id}/${entry.name ?? \"memory\"}`;\n const res = upsertManagedBlockFile(target.path, {\n blockId,\n connectorId: ctx.connector.id,\n content: entry.content,\n ...(target.commentStyle ? { commentStyle: target.commentStyle } : {}),\n force: ctx.force ?? false,\n dryRun: ctx.dryRun,\n });\n changes.push({\n platform: this.id,\n action: res.action,\n path: target.path,\n detail: `memory: ${res.detail} — ${target.reason}`,\n });\n if (res.backupPath) {\n changes.push({\n platform: this.id,\n action: \"create\",\n path: res.backupPath,\n detail: \"backed up memory file before destructive change\",\n });\n }\n const bytes = Buffer.byteLength(entry.content, \"utf8\");\n if (bytes > MEMORY_CONTENT_SOFT_BUDGET_BYTES) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: target.path,\n detail:\n `memory entry \"${entry.name ?? \"memory\"}\" is ${bytes} bytes ` +\n `(soft budget ${MEMORY_CONTENT_SOFT_BUDGET_BYTES}); this file is injected into ` +\n `every prompt — keep guidance terse`,\n });\n }\n if (res.action !== \"warn\") {\n recordMemoryTarget(ledger, {\n platform: this.id,\n scope: ctx.scope,\n path: target.path,\n blockId,\n createdFile: res.createdFile,\n hash: res.hash,\n });\n ledgerMutated = true;\n }\n }\n // Per-FILE budget (e.g. codex caps combined project docs at 32 KiB —\n // budgetBytes ≈ 28 KiB leaves headroom): warn when the whole target file\n // (user content + every block) outgrows what the host will actually load.\n if (target.budgetBytes !== undefined && !ctx.dryRun && existsSync(target.path)) {\n const fileBytes = statSync(target.path).size;\n if (fileBytes > target.budgetBytes) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: target.path,\n detail:\n `memory file is ${fileBytes} bytes — over this host's ~${target.budgetBytes}-byte ` +\n `budget; the host may truncate or drop it`,\n });\n }\n }\n }\n\n if (ledgerMutated && !ctx.dryRun) saveMemoryLedger(ctx.connector.id, ledger);\n return changes;\n }\n\n uninstallMemory(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (!(this.capabilities.supportsMemory ?? false)) {\n // Nothing could ever have been written by a non-supporting adapter.\n return this.unsupportedSurface(ctx, \"memory\", (connector.memory ?? []).length);\n }\n\n // Candidate files = union of (a) memoryTargets recomputed NOW (probe re-run\n // — catches teammate machines with no ledger; the markers in the committed\n // file are the source of truth) and (b) ledger rows for this platform from\n // EVERY scope (catches a scope flag that differs from install time).\n const ledger = loadMemoryLedger(connector.id);\n const mine = ledger.targets.filter((t) => t.platform === this.id);\n const candidates = new Map<string, { createdFile: boolean }>();\n if (ctx.scope === \"project\" || ctx.scope === \"user\") {\n for (const t of this.memoryTargets(ctx)) {\n candidates.set(t.path, { createdFile: false });\n }\n }\n for (const row of mine) {\n const existing = candidates.get(row.path);\n candidates.set(row.path, { createdFile: (existing?.createdFile ?? false) || row.createdFile });\n }\n if (candidates.size === 0) {\n return [\n { platform: this.id, action: \"skip\", detail: `no memory targets to clean on ${this.id}` },\n ];\n }\n\n // Prefix scan (`<connectorId>/`), NOT the declared entry list: renamed or\n // removed entries and stale blocks from older versions are reclaimed too.\n const changes: ChangeRecord[] = [];\n for (const [path, { createdFile }] of candidates) {\n const results = removeManagedBlocksFile(\n path,\n { blockIdPrefix: `${connector.id}/` },\n { dryRun: ctx.dryRun, deleteFileIfCreated: createdFile },\n );\n for (const r of results) {\n changes.push({\n platform: this.id,\n action: r.action,\n path: r.path,\n detail: `memory: ${r.detail}`,\n });\n if (r.backupPath) {\n changes.push({\n platform: this.id,\n action: \"create\",\n path: r.backupPath,\n detail: \"backed up memory file before block removal\",\n });\n }\n }\n }\n\n // Prune this connector's ledger rows for this platform (the file itself is\n // deleted when no rows remain). Markers stay the uninstall source of truth.\n if (!ctx.dryRun && mine.length > 0) {\n ledger.targets = ledger.targets.filter((t) => t.platform !== this.id);\n saveMemoryLedger(connector.id, ledger);\n }\n return changes;\n }\n\n /**\n * Doctor: per-ledger-row memory state for this platform — file present,\n * block present, and recorded-vs-actual inner hash (drift → warn, the\n * user edited inside our block; sync reports the same drift and never\n * clobbers it without --force).\n */\n protected memoryDiagnostics(ctx: InstallContext): DiagnosticResult[] {\n const results: DiagnosticResult[] = [];\n const rows = loadMemoryLedger(ctx.connector.id).targets.filter(\n (t) => t.platform === this.id,\n );\n for (const row of rows) {\n const check = `${this.name}: memory block ${row.blockId}`;\n if (!existsSync(row.path)) {\n results.push({\n check,\n status: \"warn\",\n message: `memory file missing: ${row.path}`,\n fix: \"agent-connector install (sync) will re-create the block\",\n fixable: true,\n });\n continue;\n }\n let raw: string;\n try {\n raw = readFileSync(row.path, \"utf8\");\n } catch {\n results.push({ check, status: \"warn\", message: `cannot read ${row.path}` });\n continue;\n }\n const block = listManagedBlocks(raw).find((b) => b.blockId === row.blockId);\n if (!block) {\n results.push({\n check,\n status: \"warn\",\n message: `managed block not found in ${row.path}`,\n fix: \"agent-connector install (sync) will re-append it\",\n fixable: true,\n });\n } else if (block.drifted) {\n results.push({\n check,\n status: \"warn\",\n message:\n `user-edited: inner content hash ${block.actualHash} differs from recorded ` +\n `${block.recordedHash} in ${row.path}; sync leaves it intact (use --force to overwrite)`,\n });\n } else {\n results.push({ check, status: \"pass\", message: `intact in ${row.path}` });\n }\n // Shadow-flip probe: re-run memoryTargets NOW for the row's scope — if\n // the host's resolution moved (a WARP.md / AGENTS.override.md / .rules /\n // .hermes.md appeared, gemini context.fileName changed), the written\n // block sits in a file the host no longer reads. The #1 wrong-file\n // risk; doctor is the detection layer.\n // (`_shared/` bridge rows deliberately live OUTSIDE memoryTargets —\n // e.g. claude-code's @AGENTS.md import in CLAUDE.md — skip those.)\n if (\n !row.blockId.startsWith(\"_shared/\") &&\n row.scope === ctx.scope &&\n (ctx.scope === \"project\" || ctx.scope === \"user\")\n ) {\n const current = this.memoryTargets(ctx);\n if (current.length > 0 && !current.some((t) => t.path === row.path)) {\n results.push({\n check,\n status: \"warn\",\n message:\n `${this.id} now resolves its ${row.scope}-scope memory file to ` +\n `${current[0]!.path} (${current[0]!.reason}) — the block in ${row.path} ` +\n `may no longer be read`,\n fix: \"agent-connector install (sync) re-probes and writes the file the host reads now\",\n fixable: true,\n });\n }\n }\n }\n return results;\n }\n\n // ── Declarative host-config key patches (configPatch) ─────────────────────\n // CONCRETE (overridable) defaults, mirroring the content surfaces above: the\n // installer additionally guards these behind capabilities.supportsConfigPatch\n // (the nativeHooks precedent), so these defaults only fire if a capability-\n // flagged adapter forgot to override them — still skip-warn, never silent.\n\n installConfigPatches(ctx: InstallContext): ChangeRecord[] {\n const count = (ctx.connector.platforms[this.id]?.configPatch ?? []).length;\n if (count === 0) {\n return [\n { platform: this.id, action: \"skip\", detail: \"connector declares no configPatch entries\" },\n ];\n }\n return [\n {\n platform: this.id,\n action: \"warn\",\n detail: `configPatch not supported on ${this.id}; ${count} skipped`,\n },\n ];\n }\n\n uninstallConfigPatches(_ctx: InstallContext): ChangeRecord[] {\n // Nothing was ever applied by a non-supporting adapter → nothing to release.\n return [];\n }\n\n // ── Statusline surface (a HUD/status line) ────────────────────────────────\n // CONCRETE (overridable) defaults, mirroring the content surfaces: the\n // installer calls these unconditionally (BaseAdapter defines them), and they\n // self-skip when the connector declares no statusline, else skip-warn on a\n // non-supporting host. Only claude-code overrides them today.\n\n installStatusline(ctx: InstallContext): ChangeRecord[] {\n if (ctx.connector.statusline == null) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no statusline\" }];\n }\n if (ctx.connector.platforms[this.id]?.statusline === false) {\n return [{ platform: this.id, action: \"skip\", detail: `statusline disabled for ${this.id}` }];\n }\n if (!(this.capabilities.supportsStatusline ?? false)) {\n return this.unsupportedSurface(ctx, \"statusline\", 1);\n }\n // A supporting adapter must override this; the default is the same skip-warn\n // safety net the configPatch defaults provide (never silent).\n return this.unsupportedSurface(ctx, \"statusline\", 1);\n }\n\n uninstallStatusline(ctx: InstallContext): ChangeRecord[] {\n if (ctx.connector.statusline == null) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no statusline\" }];\n }\n if (!(this.capabilities.supportsStatusline ?? false)) {\n // Nothing could ever have been written by a non-supporting adapter.\n return this.unsupportedSurface(ctx, \"statusline\", 1);\n }\n return this.unsupportedSurface(ctx, \"statusline\", 1);\n }\n\n // ── Action surface (a user-invokable action) ──────────────────────────────\n // CONCRETE (overridable) defaults, mirroring the statusline pair. v1 ships\n // ONLY the dispatch backbone: there is no verifiable host affordance to emit,\n // so EVERY host honestly skip-warns and NO adapter overrides these. (`?? []`\n // tolerates pre-resolved connectors from versions before the action surface\n // existed, exactly like installMemory.)\n\n installActions(ctx: InstallContext): ChangeRecord[] {\n return this.unsupportedSurface(ctx, \"actions\", (ctx.connector.actions ?? []).length);\n }\n uninstallActions(ctx: InstallContext): ChangeRecord[] {\n return this.unsupportedSurface(ctx, \"actions\", (ctx.connector.actions ?? []).length);\n }\n\n /**\n * Shared, surface-agnostic helper for the action EMITTERS: yield one\n * {@link ActionTrigger} per declared action, each carrying the home-bin verb\n * command the host trigger must run\n * (`<homeBin> action <host> <actionId> --connector <id>`, via\n * {@link buildHomeBinActionCommand}) plus a `label`/`description` that fall\n * back to the action id. Each supporting adapter iterates this and writes its\n * host-native trigger (hermes quick_commands / warp workflow / droid exec\n * file) — the per-host file shape is NOT this helper's concern, only the\n * common (id, label, description, command) tuple. Callers own the standard\n * guards (platforms[id].actions === false / empty actions).\n */\n protected actionTriggers(ctx: InstallContext): ActionTrigger[] {\n return (ctx.connector.actions ?? []).map((action) => ({\n id: action.id,\n label: action.description ?? action.id,\n description: action.description ?? action.id,\n command: buildHomeBinActionCommand(\n ctx.homeBinPath,\n this.id,\n action.id,\n ctx.connector.id,\n ),\n }));\n }\n\n /**\n * Default response for a content surface this platform cannot honor: a single\n * skip when the connector declares none of that surface, else a single \"warn\"\n * ChangeRecord noting how many were skipped. Mirrors mcp-only hook handling.\n */\n protected unsupportedSurface(\n _ctx: InstallContext,\n surface: ContentSurface,\n count: number,\n ): ChangeRecord[] {\n if (count === 0) {\n return [{ platform: this.id, action: \"skip\", detail: `connector declares no ${surface}` }];\n }\n return [\n {\n platform: this.id,\n action: \"warn\",\n detail: `${surface} not supported on ${this.id}; ${count} skipped`,\n },\n ];\n }\n\n // ── Content-file helpers (used by surface-supporting adapters) ────────────\n\n /**\n * Write a content file idempotently: \"skip\" when the existing bytes are\n * already identical, else \"create\"/\"update\". Creates parent dirs (mkdir -p).\n * Honors dryRun (computes the action but writes nothing).\n */\n protected writeContentFile(path: string, contents: string, dryRun: boolean): ChangeRecord {\n let action: ChangeRecord[\"action\"];\n if (!existsSync(path)) {\n action = \"create\";\n } else {\n let current: string | null = null;\n try {\n current = readFileSync(path, \"utf8\");\n } catch {\n current = null;\n }\n action = current === contents ? \"skip\" : \"update\";\n }\n if (action !== \"skip\" && !dryRun) {\n ensureDir(dirname(path));\n writeFileSync(path, contents, \"utf8\");\n }\n return { platform: this.id, action, path, detail: basename(path) };\n }\n\n /**\n * Remove a content file we wrote; \"skip\" when already absent. Honors dryRun.\n * Uses rmSync with `force` to also tolerate a path that is a directory tree\n * (e.g. a skill folder removed by the supporting adapter).\n */\n protected removeContentFile(path: string, dryRun: boolean): ChangeRecord {\n if (!existsSync(path)) {\n return { platform: this.id, action: \"skip\", path, detail: `${basename(path)} absent` };\n }\n if (!dryRun) {\n rmSync(path, { recursive: true, force: true });\n }\n return { platform: this.id, action: \"remove\", path, detail: basename(path) };\n }\n\n /**\n * Defense-in-depth path containment: resolve `rel` against `baseDir` and\n * return the absolute path ONLY when it stays inside `baseDir`. Returns null\n * when `rel` escapes (absolute path, `..` traversal, etc.) so a caller can\n * skip-and-warn rather than write/delete outside the surface dir. This is the\n * runtime backstop behind the config-time validation in normalizeSkills.\n */\n protected resolveWithin(baseDir: string, rel: string): string | null {\n const base = resolve(baseDir);\n const target = resolve(base, rel);\n if (target === base) return null; // rel resolved to the dir itself (e.g. \"\" / \".\")\n const rind = relative(base, target);\n // Outside when the relative path climbs out (`..`) or is itself absolute.\n if (rind === \"\" || rind.startsWith(\"..\") || resolve(base, rind) !== target) {\n return null;\n }\n if (rind === \"..\" || rind.startsWith(`..${sep}`)) return null;\n return target;\n }\n\n /**\n * Recursively report whether a directory tree contains any regular FILE (vs\n * only empty/nested-empty subdirectories). Symlinks count as files (we never\n * recurse through them). Used by removeDirIfEmpty to decide if a tree is safe\n * to drop. An unreadable entry is treated as \"a file is present\" (conservative).\n */\n private dirTreeHasFile(dir: string): boolean {\n let entries: Dirent[];\n try {\n entries = readdirSync(dir, { withFileTypes: true });\n } catch {\n return true; // unreadable → assume it holds data; do not remove\n }\n for (const e of entries) {\n if (e.isDirectory()) {\n if (this.dirTreeHasFile(join(dir, e.name))) return true;\n } else {\n return true; // a file / symlink / special → the tree is not \"empty\"\n }\n }\n return false;\n }\n\n /**\n * Remove a directory ONLY when its tree holds NO regular files — i.e. it is\n * empty or contains only (nested) empty directories, such as the intermediate\n * dirs our own nested skill resources created. Replaces the unconditional\n * `rm -rf <dir>` that uninstallSkills used to call, which destroyed user-added\n * files / sibling-tool files / shared skill dirs the connector never wrote.\n * When ANY file remains (at any depth) the whole tree is left in place and the\n * skip is noted. Honors dryRun (computes the action but removes nothing). A\n * missing dir is a no-op \"skip\".\n */\n protected removeDirIfEmpty(dir: string, dryRun: boolean): ChangeRecord {\n if (!existsSync(dir)) {\n return { platform: this.id, action: \"skip\", path: dir, detail: `${basename(dir)} absent` };\n }\n let stat: ReturnType<typeof statSync>;\n try {\n stat = statSync(dir);\n } catch {\n return {\n platform: this.id,\n action: \"skip\",\n path: dir,\n detail: `${basename(dir)} unreadable; left in place`,\n };\n }\n if (!stat.isDirectory()) {\n return {\n platform: this.id,\n action: \"skip\",\n path: dir,\n detail: `${basename(dir)} not a directory; left in place`,\n };\n }\n if (this.dirTreeHasFile(dir)) {\n return {\n platform: this.id,\n action: \"skip\",\n path: dir,\n detail: `${basename(dir)} still holds files we did not write; left in place`,\n };\n }\n if (!dryRun) {\n try {\n // The tree is files-free: only (possibly nested) empty dirs remain, which\n // are ours / inert. A recursive remove drops them without touching data.\n rmSync(dir, { recursive: true, force: true });\n } catch {\n // Lost a race or perms — non-fatal; report as a skip.\n return {\n platform: this.id,\n action: \"skip\",\n path: dir,\n detail: `${basename(dir)} could not be removed; left in place`,\n };\n }\n }\n return { platform: this.id, action: \"remove\", path: dir, detail: basename(dir) };\n }\n\n /**\n * Render a YAML-frontmatter + markdown body document:\n * \"---\\n\" + <yaml> + \"---\\n\\n\" + <body> + \"\\n\".\n * Delegates to the shared renderer (adapters/claude-code/render) so every\n * content-file path — adapters AND the plugin packager — emits identical bytes.\n */\n protected renderFrontmatterMd(\n frontmatter: Record<string, unknown>,\n body: string,\n ): string {\n return renderFrontmatterMd(frontmatter, body);\n }\n\n // ── JSON config helpers (used by JSON-format adapters) ───────────────────\n\n /**\n * Read + parse a JSON/JSONC config file, returning null when it is absent OR\n * unparseable. Parses TOLERANTLY via parseJsonc (strips // and /* *\\/ comments\n * and trailing commas) so a perfectly valid JSONC file never false-fails to\n * null — that null is what `?? {}` would otherwise turn into a clobbering\n * overwrite of the user's whole config.\n */\n protected readJson<T = Record<string, unknown>>(path: string): T | null {\n if (!existsSync(path)) return null;\n try {\n return parseJsonc<T>(readFileSync(path, \"utf8\"));\n } catch {\n return null;\n }\n }\n\n /**\n * True when `path` exists and holds non-whitespace content but readJson cannot\n * parse it (even after JSONC stripping). The overwrite guard: writing a\n * `{}`-based config over a present-but-broken settings file would silently\n * destroy the user's data, so callers warn-and-skip instead.\n */\n protected isPresentButUnparseable(path: string): boolean {\n if (!existsSync(path)) return false;\n let raw: string;\n try {\n if (statSync(path).size === 0) return false;\n raw = readFileSync(path, \"utf8\");\n } catch {\n return false;\n }\n if (raw.trim() === \"\") return false;\n return this.readJson(path) === null;\n }\n\n protected writeJson(path: string, data: unknown, dryRun = false): void {\n if (dryRun) return;\n ensureDir(dirname(path));\n writeFileSync(path, `${JSON.stringify(data, null, 2)}\\n`, \"utf8\");\n }\n\n /**\n * Upsert `entry` at `config[rootKey][serverId]` in a JSON file, creating the\n * file/object as needed. Returns a ChangeRecord describing create/update/skip.\n * Idempotent: an identical entry yields \"skip\".\n */\n protected upsertServerInJson(\n configPath: string,\n rootKey: string,\n serverId: string,\n entry: unknown,\n dryRun = false,\n ): ChangeRecord {\n // OVERWRITE GUARD: never replace a present, non-empty, unparseable settings\n // file with a `{}`-based config — that would silently destroy the user's\n // data. Warn and skip so they can back it up / fix it and re-run.\n if (this.isPresentButUnparseable(configPath)) {\n return {\n platform: this.id,\n action: \"warn\",\n path: configPath,\n detail: `existing ${configPath} is not parseable; left untouched (back it up / fix it, then re-run)`,\n };\n }\n const cfg = this.readJson<Record<string, Record<string, unknown>>>(configPath) ?? {};\n const bucket = (cfg[rootKey] ??= {});\n const before = JSON.stringify(bucket[serverId]);\n const after = JSON.stringify(entry);\n let action: ChangeRecord[\"action\"];\n if (before === undefined) action = \"create\";\n else if (before === after) action = \"skip\";\n else action = \"update\";\n if (action !== \"skip\") {\n bucket[serverId] = entry;\n this.writeJson(configPath, cfg, dryRun);\n }\n return { platform: this.id, action, path: configPath, detail: `${rootKey}.${serverId}` };\n }\n\n /** Remove `config[rootKey][serverId]` from a JSON file. */\n protected removeServerFromJson(\n configPath: string,\n rootKey: string,\n serverId: string,\n dryRun = false,\n ): ChangeRecord {\n // OVERWRITE GUARD (see upsertServerInJson): a present-but-unparseable file\n // would round-trip to `{}` and erase the user's config, so warn and skip.\n if (this.isPresentButUnparseable(configPath)) {\n return {\n platform: this.id,\n action: \"warn\",\n path: configPath,\n detail: `existing ${configPath} is not parseable; left untouched (back it up / fix it, then re-run)`,\n };\n }\n const cfg = this.readJson<Record<string, Record<string, unknown>>>(configPath);\n const bucket = cfg?.[rootKey];\n if (!cfg || !bucket || !(serverId in bucket)) {\n return { platform: this.id, action: \"skip\", path: configPath, detail: `${rootKey}.${serverId} absent` };\n }\n delete bucket[serverId];\n this.writeJson(configPath, cfg, dryRun);\n return { platform: this.id, action: \"remove\", path: configPath, detail: `${rootKey}.${serverId}` };\n }\n\n // ── Backup ───────────────────────────────────────────────────────────────\n\n backupSettings(ctx: InstallContext): string | null {\n const files = [...new Set([this.getServerConfigPath(ctx), this.getHookConfigPath(ctx)])].filter(\n (f) => existsSync(f),\n );\n if (files.length === 0) return null;\n if (ctx.dryRun) return null;\n ensureDir(backupsDir());\n const stamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n let last: string | null = null;\n for (const f of files) {\n const dest = join(backupsDir(), `${this.id}-${stamp}-${basename(f)}`);\n copyFileSync(f, dest);\n last = dest;\n }\n return last;\n }\n\n // ── Diagnostics ─────────────────────────────────────────────────────────\n\n getHealthChecks?(ctx: InstallContext): readonly HealthCheck[];\n\n doctor(ctx: InstallContext): DiagnosticResult[] {\n const results: DiagnosticResult[] = [];\n const cfg = this.getServerConfigPath(ctx);\n results.push(\n existsSync(cfg)\n ? { check: `${this.name}: config present`, status: \"pass\", message: cfg }\n : {\n check: `${this.name}: config present`,\n status: \"warn\",\n message: `not found: ${cfg}`,\n fix: `agent-connector install --targets ${this.id}`,\n // Only sync-recoverable when the connector actually declares a\n // server — a re-sync writes the config file only then. For a\n // serverless (memory/configPatch-only) connector the file is never\n // created, so marking it fixable would loop it into \"still failing\".\n fixable: !!ctx.connector.server,\n },\n );\n for (const hc of this.getHealthChecks?.(ctx) ?? []) {\n const r = hc.check();\n results.push({\n check: hc.name,\n status: r.status === \"OK\" ? \"pass\" : \"fail\",\n message: r.detail ?? r.status,\n });\n }\n // Memory-surface checks are ledger-driven: no installed memory → no rows →\n // no noise. Shared by every adapter (the overrides call super.doctor()).\n results.push(...this.memoryDiagnostics(ctx));\n return results;\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/yaml.ts"],"sourcesContent":["/**\n * core/yaml — minimal YAML config IO.\n *\n * The YAML analog of BaseAdapter's JSON helpers (readJson/writeJson). Adapters\n * whose native config is YAML (Goose's config.yaml, Hermes's config.yaml) cannot\n * use the JSON helpers, so they reach for these two functions instead — same\n * existsSync-guard / parse-failure-tolerant / dryRun-respecting contract, just\n * over the `yaml` package's parse()/stringify() rather than JSON.parse/stringify.\n *\n * Deliberately tiny: read-or-null and ensureDir+write. All merge/upsert/idempotency\n * logic lives in each adapter (the shapes differ per platform), exactly as the\n * JSON adapters layer their own upsert on top of writeJson.\n */\n\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\n\nimport { parse, stringify } from \"yaml\";\n\nimport { ensureDir } from \"./paths.js\";\n\n/**\n * Read and parse a YAML file. Returns `null` when the file is missing OR when it\n * fails to parse (mirrors BaseAdapter.readJson's fail-soft behavior so a corrupt\n * file degrades to \"treat as absent\" rather than throwing mid-install).\n */\nexport function readYaml<T = Record<string, unknown>>(path: string): T | null {\n if (!existsSync(path)) return null;\n try {\n const parsed = parse(readFileSync(path, \"utf8\")) as T | null | undefined;\n // An empty YAML document parses to null/undefined — normalize to null.\n return parsed == null ? null : parsed;\n } catch {\n return null;\n }\n}\n\n/**\n * Serialize `data` to YAML and write it to `path`, creating parent dirs as\n * needed. Honors `dryRun` (no write). Mirrors BaseAdapter.writeJson's signature.\n */\nexport function writeYaml(path: string, data: unknown, dryRun = false): void {\n if (dryRun) return;\n ensureDir(dirname(path));\n writeFileSync(path, stringify(data), \"utf8\");\n}\n"],"mappings":";;;;;;AAcA,SAAS,YAAY,cAAc,qBAAqB;AACxD,SAAS,eAAe;AAExB,SAAS,OAAO,iBAAiB;AAS1B,SAAS,SAAsC,MAAwB;AAC5E,MAAI,CAAC,WAAW,IAAI,EAAG,QAAO;AAC9B,MAAI;AACF,UAAM,SAAS,MAAM,aAAa,MAAM,MAAM,CAAC;AAE/C,WAAO,UAAU,OAAO,OAAO;AAAA,EACjC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMO,SAAS,UAAU,MAAc,MAAe,SAAS,OAAa;AAC3E,MAAI,OAAQ;AACZ,YAAU,QAAQ,IAAI,CAAC;AACvB,gBAAc,MAAM,UAAU,IAAI,GAAG,MAAM;AAC7C;","names":[]}