@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
@@ -1,21 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  fail
4
- } from "./chunk-QC5A3TFQ.js";
4
+ } from "./chunk-A2T4Q7RM.js";
5
5
  import {
6
6
  runAction
7
- } from "./chunk-H67V7DEL.js";
7
+ } from "./chunk-YYISBXOM.js";
8
8
  import "./chunk-OP4KBXUO.js";
9
- import "./chunk-F5RX62T7.js";
10
- import "./chunk-EROJDXMW.js";
11
- import "./chunk-QOGMDOUX.js";
9
+ import "./chunk-7QRUZAUG.js";
10
+ import "./chunk-NYR55UT7.js";
11
+ import "./chunk-WI6YSXOC.js";
12
12
  import "./chunk-BCHWFTV4.js";
13
13
  import "./chunk-KHO5WNTP.js";
14
- import "./chunk-MZF2YCXX.js";
15
- import "./chunk-DCK5FADX.js";
16
- import "./chunk-BMD7ANKF.js";
14
+ import "./chunk-MOW2RKHX.js";
15
+ import "./chunk-HOE2MN36.js";
16
+ import "./chunk-XQUUNAGC.js";
17
17
  import "./chunk-FAHIMJRU.js";
18
- import "./chunk-I5MLE6S7.js";
18
+ import "./chunk-TO57WYBB.js";
19
19
  import "./chunk-N6HH7K6P.js";
20
20
  import "./chunk-TRQKHP7D.js";
21
21
 
@@ -52,4 +52,4 @@ async function run(argv) {
52
52
  export {
53
53
  run
54
54
  };
55
- //# sourceMappingURL=action-EV63GAPY.js.map
55
+ //# sourceMappingURL=action-RWPRIZIC.js.map
@@ -4,12 +4,11 @@ import {
4
4
  } from "./chunk-DBQMX75U.js";
5
5
  import {
6
6
  BaseAdapter
7
- } from "./chunk-CPLK7GTE.js";
8
- import "./chunk-7L6ITC4T.js";
7
+ } from "./chunk-KG6T3YNJ.js";
8
+ import "./chunk-IEGR4TP3.js";
9
9
  import {
10
- buildServeWrapperCommand,
11
- shouldWrapForTelemetry
12
- } from "./chunk-I5MLE6S7.js";
10
+ buildWrappedStdio
11
+ } from "./chunk-TO57WYBB.js";
13
12
  import "./chunk-N6HH7K6P.js";
14
13
  import "./chunk-TRQKHP7D.js";
15
14
 
@@ -184,18 +183,7 @@ var AmazonQAdapter = class extends BaseAdapter {
184
183
  if (transport === "stdio") {
185
184
  let command = server.command ?? "";
186
185
  let args = [...server.args ?? []];
187
- if (shouldWrapForTelemetry(server, ctx.connector.telemetry)) {
188
- const wrapped = buildServeWrapperCommand(
189
- ctx.homeBinPath,
190
- ctx.connector.id,
191
- command,
192
- args,
193
- ctx.scope,
194
- this.id
195
- );
196
- command = wrapped.command;
197
- args = wrapped.args;
198
- }
186
+ ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));
199
187
  const entry = {
200
188
  command: resolveEnvRefsDeep(command)
201
189
  };
@@ -273,4 +261,4 @@ export {
273
261
  adapter,
274
262
  amazon_q_default as default
275
263
  };
276
- //# sourceMappingURL=amazon-q-COAL3764.js.map
264
+ //# sourceMappingURL=amazon-q-5LJOB5L3.js.map
@@ -0,0 +1 @@
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 buildWrappedStdio,\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 ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\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,17 +1,19 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ renderBridgePrelude
4
+ } from "./chunk-FBJQGRET.js";
2
5
  import {
3
6
  rewriteEnvRefs
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
 
@@ -166,18 +168,7 @@ var AmpAdapter = class extends BaseAdapter {
166
168
  if (transport === "stdio") {
167
169
  let command = server.command ?? "";
168
170
  let args = [...server.args ?? []];
169
- if (shouldWrapForTelemetry(server, ctx.connector.telemetry)) {
170
- const wrapped = buildServeWrapperCommand(
171
- ctx.homeBinPath,
172
- ctx.connector.id,
173
- command,
174
- args,
175
- ctx.scope,
176
- this.id
177
- );
178
- command = wrapped.command;
179
- args = wrapped.args;
180
- }
171
+ ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));
181
172
  const entry2 = { command: this.rewrite(command) };
182
173
  if (args.length > 0) entry2.args = args.map((a) => this.rewrite(a));
183
174
  const env = this.renderEnv(server.env);
@@ -385,8 +376,6 @@ var AmpAdapter = class extends BaseAdapter {
385
376
  }
386
377
  /** Compose the generated plugin source with plain string concatenation. */
387
378
  buildPluginSource(ctx) {
388
- const homeBin = JSON.stringify(ctx.homeBinPath);
389
- const connectorId = JSON.stringify(ctx.connector.id);
390
379
  const canonicalOff = ctx.connector.platforms[HOST]?.hooks === false;
391
380
  const events = canonicalOff ? [] : ctx.connector.hookEvents.filter(
392
381
  (e) => EVENT_TO_AMP[e] !== void 0
@@ -406,34 +395,13 @@ var AmpAdapter = class extends BaseAdapter {
406
395
  import type { PluginAPI } from "@ampcode/plugin";
407
396
  import { execFileSync, execSync } from "node:child_process";
408
397
 
409
- const HOME_BIN = ${homeBin};
410
- const CONNECTOR_ID = ${connectorId};
411
-
412
- /**
413
- * Invoke the universal hook entrypoint for one event.
414
- * @param {string} event canonical event name
415
- * @param {object} payload amp-shaped payload posted on stdin
416
- * @returns {object|null} normalized HookResponse, or null on any failure
417
- */
418
- function bridge(event, payload) {
419
- try {
420
- // On Windows HOME_BIN is the agent-connector.cmd launcher: Node cannot
421
- // execFile a batch file, and shell+args is deprecated (DEP0190), so run one
422
- // quoted command line via a shell. POSIX keeps the direct execFile (no shell).
423
- const args = ["hook", "amp", event, "--connector", CONNECTOR_ID];
424
- const opts = { input: JSON.stringify(payload), encoding: "utf8" };
425
- const stdout =
426
- process.platform === "win32"
427
- ? execSync([HOME_BIN, ...args].map((a) => '"' + a + '"').join(" "), opts)
428
- : execFileSync(HOME_BIN, args, opts);
429
- const text = (stdout || "").trim();
430
- if (text === "") return { decision: "allow" };
431
- return JSON.parse(text);
432
- } catch {
433
- // Fail-open \u2014 never wedge an Amp tool call / lifecycle event.
434
- return null;
435
- }
436
- }
398
+ ${renderBridgePrelude({
399
+ homeBin: ctx.homeBinPath,
400
+ connectorId: ctx.connector.id,
401
+ hookSlug: "amp",
402
+ payloadNoun: "amp",
403
+ failOpenComment: "Fail-open \u2014 never wedge an Amp tool call / lifecycle event."
404
+ })}
437
405
 
438
406
  // Amp documents no project-dir env var; the plugin process runs in the workspace
439
407
  // root, so resolve once at load. Session id is rebound on each session.start.
@@ -663,4 +631,4 @@ export {
663
631
  adapter,
664
632
  amp_default as default
665
633
  };
666
- //# sourceMappingURL=amp-XJQ4TDAU.js.map
634
+ //# sourceMappingURL=amp-PU4LFSY6.js.map
@@ -0,0 +1 @@
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 { renderBridgePrelude } from \"../../core/ts-plugin-bridge.js\";\nimport {\n buildWrappedStdio,\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 ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\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 // `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\n${renderBridgePrelude({\n homeBin: ctx.homeBinPath,\n connectorId: ctx.connector.id,\n hookSlug: \"amp\",\n payloadNoun: \"amp\",\n failOpenComment: \"Fail-open — never wedge an Amp tool call / lifecycle event.\",\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"]}
@@ -3,11 +3,12 @@ import {
3
3
  AntigravityAdapter,
4
4
  adapter,
5
5
  antigravity_default
6
- } from "./chunk-LQRAPXS4.js";
6
+ } from "./chunk-YS2NYJ6R.js";
7
+ import "./chunk-H53QZQJI.js";
7
8
  import "./chunk-DBQMX75U.js";
8
- import "./chunk-CPLK7GTE.js";
9
- import "./chunk-7L6ITC4T.js";
10
- import "./chunk-I5MLE6S7.js";
9
+ import "./chunk-KG6T3YNJ.js";
10
+ import "./chunk-IEGR4TP3.js";
11
+ import "./chunk-TO57WYBB.js";
11
12
  import "./chunk-N6HH7K6P.js";
12
13
  import "./chunk-TRQKHP7D.js";
13
14
  export {
@@ -15,4 +16,4 @@ export {
15
16
  adapter,
16
17
  antigravity_default as default
17
18
  };
18
- //# sourceMappingURL=antigravity-AMKKKHS4.js.map
19
+ //# sourceMappingURL=antigravity-DWW35HZO.js.map
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  AntigravityAdapter
4
- } from "./chunk-LQRAPXS4.js";
4
+ } from "./chunk-YS2NYJ6R.js";
5
+ import "./chunk-H53QZQJI.js";
5
6
  import "./chunk-DBQMX75U.js";
6
- import "./chunk-CPLK7GTE.js";
7
- import "./chunk-7L6ITC4T.js";
8
- import "./chunk-I5MLE6S7.js";
7
+ import "./chunk-KG6T3YNJ.js";
8
+ import "./chunk-IEGR4TP3.js";
9
+ import "./chunk-TO57WYBB.js";
9
10
  import "./chunk-N6HH7K6P.js";
10
11
  import "./chunk-TRQKHP7D.js";
11
12
 
@@ -84,4 +85,4 @@ export {
84
85
  adapter,
85
86
  antigravity_cli_default as default
86
87
  };
87
- //# sourceMappingURL=antigravity-cli-XERXEH5W.js.map
88
+ //# sourceMappingURL=antigravity-cli-VTQ6DNWL.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/adapters/antigravity-cli/index.ts"],"sourcesContent":["/**\n * adapters/antigravity-cli — Google Antigravity CLI (`agy`) platform adapter.\n *\n * Antigravity ships in two distinct runtimes that share the Gemini-family\n * `~/.gemini` tree and ALL of the same native formats (the JSON `mcp_config.json`\n * shape, the `hooks.json` lifecycle-hook shape, markdown Workflows, and Agent\n * Skills `SKILL.md`): the IDE/desktop app (the parent `AntigravityAdapter`,\n * id \"antigravity\") and this standalone CLI binary `agy` (id \"antigravity-cli\").\n *\n * This adapter is a thin fork of the IDE adapter. It REUSES every render / hook /\n * parse / surface path from {@link AntigravityAdapter} unchanged — the only\n * differences are identity and detection:\n *\n * - id = \"antigravity-cli\", name = \"Antigravity CLI\". Identity flows into the\n * universal hook command (`<homeBin> hook antigravity-cli <event> …`) and the\n * `hostPlatform` stamp, so a CLI-installed hook dispatches back to THIS\n * adapter at runtime — the reason the parent's install/parse logic was made\n * to read `this.id` rather than a fixed host constant.\n * - Detection probes the `agy` binary at ~/.local/bin/agy and/or the SHARED\n * ~/.gemini/antigravity/ presence (distinct runtime markers from the IDE).\n *\n * CONFIRMED-BY-INSTALL (2026-06-03, docs/research/antigravity-paths-confirmed.md):\n * the `agy` CLI v1.0.0 has NO separate config dir — `~/.gemini/antigravity-cli/`,\n * `~/.config/antigravity*`, and `~/.agy` are ALL ABSENT. `agy` SHARES the IDE's\n * `~/.gemini/antigravity/` tree (mcp_config.json, hooks.json, workflows, skills).\n * So the user-scope config resolution here is IDENTICAL to the IDE adapter (the\n * inherited USER_CONFIG_CANDIDATES) — installing both the IDE and CLI connectors\n * therefore writes the SAME files and is idempotent (observed as skip), which is\n * expected and correct. `agy`'s own extension surface is the `agy plugin` system\n * (install/uninstall/list/enable/disable) — future work would deploy as an agy\n * plugin; for now the MCP/workflows/skills surfaces ride the shared IDE files.\n *\n * LIVE-TEST RESOLUTION (2026-06-04, real `agy` v1.0.5 login + spawn): the prior\n * \"shares the IDE's ~/.gemini/antigravity/ file\" claim was WRONG for the CLI. The\n * standalone `agy` reads user MCP from **~/.gemini/config/mcp_config.json**\n * (root key `mcpServers`; project scope <proj>/.agents/mcp_config.json) — PROVEN:\n * a live `agy -p` session spawned an MCP server placed in `config/` and completed\n * a real initialize+tools/list+tools/call handshake; a negative control in\n * `antigravity/` was ignored. The binary carries \"failed to read mcp_config.json\"\n * + a literal \"/.gemini/config\" path; there is NO `--mcp-config` flag and `agy\n * mcp` is TUI-only. So this adapter now OVERRIDES userConfigCandidates to prefer\n * `~/.gemini/config/mcp_config.json` (canonical) over the inherited IDE\n * `antigravity/` default (kept as a prefer-existing fallback). Telemetry-wrap is\n * compatible: agy spawns command+args verbatim, so the home-bin serve wrapper is\n * spawned as written — i.e. a real agy session now emits a per-MCP telemetry row.\n * (agy also keeps its own home ~/.gemini/antigravity-cli/ for auth/state, but MCP\n * config lives in the shared ~/.gemini/config/.)\n *\n * Project scope is IDENTICAL to the IDE adapter (`<proj>/.agents/…`), as is every\n * hook/command/skill render and the runtime parse/format — all inherited.\n *\n * The user-scope config paths shared with the IDE (hooks.json + the global skills\n * dir) remain MEDIUM-CONFIDENCE / PATH-PROBED in the parent (not present on the\n * observed install) and surfaced by the doctor; user-scope mcp_config + workflows\n * are CONFIRMED at ~/.gemini/antigravity/.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { AntigravityAdapter } from \"../antigravity/index.js\";\nimport type { Adapter } from \"../spi.js\";\nimport type { DetectedPlatform, PlatformId } from \"../../core/types.js\";\n\nconst HOST: PlatformId = \"antigravity-cli\";\n\nexport class AntigravityCliAdapter extends AntigravityAdapter implements Adapter {\n override readonly id: PlatformId = HOST;\n override readonly name = \"Antigravity CLI\";\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n /**\n * Probe the CLI's runtime markers, DISTINCT from the IDE app even though the\n * two share `~/.gemini/antigravity/`: the `agy` binary at ~/.local/bin/agy\n * (the definitive CLI marker, CONFIRMED present) and the shared\n * ~/.gemini/antigravity/ tree (or a user-scope mcp_config candidate / the\n * project config). Reported before the IDE adapter in the registry so the\n * more-specific CLI marker (the `agy` binary) wins host detection. Note: a\n * machine with ONLY the IDE (no `agy` binary) will not match here, while one\n * with the CLI matches on the binary regardless of the shared config dir.\n */\n override detectInstalled(projectDir: string): DetectedPlatform {\n const home = homedir();\n const userConfig = this.resolveUserConfigPath();\n const agyBin = join(home, \".local\", \"bin\", \"agy\");\n const sharedDir = join(home, \".gemini\", \"antigravity\");\n const projectConfig = join(projectDir, \".agents\", \"mcp_config.json\");\n\n // The `agy` binary is the definitive CLI marker. The shared antigravity dir\n // and the user-scope mcp_config candidates are secondary signals (they also\n // match a pure-IDE install, so the binary is what truly distinguishes the CLI).\n const cliMarker = existsSync(agyBin);\n const userInstalled =\n cliMarker ||\n existsSync(sharedDir) ||\n this.userConfigCandidates().some((parts) => existsSync(join(home, ...parts)));\n const projInstalled = existsSync(projectConfig);\n const installed = userInstalled || projInstalled;\n\n // Report the scope/path that actually matched, so a project-only install\n // isn't misreported as a (non-existent) user install.\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\n const configPath = scope === \"project\" ? projectConfig : userConfig;\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 ? scope === \"project\"\n ? `found project Antigravity CLI config at ${projectConfig}`\n : `found Antigravity CLI (agy) at ${agyBin} / shared ${sharedDir}`\n : `no Antigravity CLI install at ${agyBin}, ${sharedDir}, or ${projectConfig}`,\n // The `agy` binary is a high-confidence CLI marker; matching only the shared\n // config dir is weaker (it could be a pure-IDE install).\n confidence: cliMarker ? \"high\" : installed ? \"medium\" : \"low\",\n };\n }\n\n /**\n * MCP user-config path — LIVE-PROVEN for `agy` v1.0.5 (2026-06-04). The\n * standalone CLI reads user MCP servers from `~/.gemini/config/mcp_config.json`\n * (root key `mcpServers`), NOT the IDE's `~/.gemini/antigravity/mcp_config.json`:\n * a real `agy -p` session spawned an MCP server ONLY when it was placed in\n * `config/` (negative control: a server in `antigravity/` was ignored), and the\n * binary carries the error string \"failed to read mcp_config.json\" + a literal\n * \"/.gemini/config\" path. `agy mcp` is TUI-only (no headless add) and there is\n * no `--mcp-config` flag. So the CLI must PREFER `config/` over the inherited\n * `antigravity/` default; the IDE path stays as a prefer-existing fallback.\n * (Skills/workflows/hooks dirs remain inherited; project scope\n * `<proj>/.agents/mcp_config.json` is already correct and live-proven.)\n */\n private static readonly CLI_USER_CONFIG_CANDIDATES = [\n [\".gemini\", \"config\", \"mcp_config.json\"], // CONFIRMED canonical for agy v1.0.5\n [\".gemini\", \"antigravity\", \"mcp_config.json\"], // legacy IDE layout (prefer-existing)\n ] as const;\n\n protected override userConfigCandidates(): ReadonlyArray<readonly string[]> {\n return AntigravityCliAdapter.CLI_USER_CONFIG_CANDIDATES;\n }\n}\n\nexport const adapter = new AntigravityCliAdapter();\nexport default adapter;\n"],"mappings":";;;;;;;;;;;;AAyDA,SAAS,kBAAkB;AAC3B,SAAS,eAAe;AACxB,SAAS,YAAY;AAMrB,IAAM,OAAmB;AAElB,IAAM,wBAAN,MAAM,+BAA8B,mBAAsC;AAAA,EAC7D,KAAiB;AAAA,EACjB,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAchB,gBAAgB,YAAsC;AAC7D,UAAM,OAAO,QAAQ;AACrB,UAAM,aAAa,KAAK,sBAAsB;AAC9C,UAAM,SAAS,KAAK,MAAM,UAAU,OAAO,KAAK;AAChD,UAAM,YAAY,KAAK,MAAM,WAAW,aAAa;AACrD,UAAM,gBAAgB,KAAK,YAAY,WAAW,iBAAiB;AAKnE,UAAM,YAAY,WAAW,MAAM;AACnC,UAAM,gBACJ,aACA,WAAW,SAAS,KACpB,KAAK,qBAAqB,EAAE,KAAK,CAAC,UAAU,WAAW,KAAK,MAAM,GAAG,KAAK,CAAC,CAAC;AAC9E,UAAM,gBAAgB,WAAW,aAAa;AAC9C,UAAM,YAAY,iBAAiB;AAInC,UAAM,QAAQ,iBAAiB,CAAC,gBAAgB,YAAY;AAC5D,UAAM,aAAa,UAAU,YAAY,gBAAgB;AAEzD,WAAO;AAAA,MACL,IAAI,KAAK;AAAA,MACT,MAAM,KAAK;AAAA,MACX;AAAA,MACA,UAAU,KAAK;AAAA,MACf,cAAc,KAAK;AAAA,MACnB;AAAA,MACA;AAAA,MACA,QAAQ,YACJ,UAAU,YACR,2CAA2C,aAAa,KACxD,kCAAkC,MAAM,aAAa,SAAS,KAChE,iCAAiC,MAAM,KAAK,SAAS,QAAQ,aAAa;AAAA;AAAA;AAAA,MAG9E,YAAY,YAAY,SAAS,YAAY,WAAW;AAAA,IAC1D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,OAAwB,6BAA6B;AAAA,IACnD,CAAC,WAAW,UAAU,iBAAiB;AAAA;AAAA,IACvC,CAAC,WAAW,eAAe,iBAAiB;AAAA;AAAA,EAC9C;AAAA,EAEmB,uBAAyD;AAC1E,WAAO,uBAAsB;AAAA,EAC/B;AACF;AAEO,IAAM,UAAU,IAAI,sBAAsB;AACjD,IAAO,0BAAQ;","names":[]}
1
+ {"version":3,"sources":["../src/adapters/antigravity-cli/index.ts"],"sourcesContent":["/**\n * adapters/antigravity-cli — Google Antigravity CLI (`agy`) platform adapter.\n *\n * Antigravity ships in two distinct runtimes that share the Gemini-family\n * `~/.gemini` tree and ALL of the same native formats (the JSON `mcp_config.json`\n * shape, the `hooks.json` lifecycle-hook shape, markdown Workflows, and Agent\n * Skills `SKILL.md`): the IDE/desktop app (the parent `AntigravityAdapter`,\n * id \"antigravity\") and this standalone CLI binary `agy` (id \"antigravity-cli\").\n *\n * This adapter is a thin fork of the IDE adapter. It REUSES every render / hook /\n * parse / surface path from {@link AntigravityAdapter} unchanged — the only\n * differences are identity and detection:\n *\n * - id = \"antigravity-cli\", name = \"Antigravity CLI\". Identity flows into the\n * universal hook command (`<homeBin> hook antigravity-cli <event> …`) and the\n * `hostPlatform` stamp, so a CLI-installed hook dispatches back to THIS\n * adapter at runtime — the reason the parent's install/parse logic was made\n * to read `this.id` rather than a fixed host constant.\n * - Detection probes the `agy` binary at ~/.local/bin/agy and/or the SHARED\n * ~/.gemini/antigravity/ presence (distinct runtime markers from the IDE).\n *\n * CONFIRMED-BY-INSTALL (2026-06-03, docs/research/antigravity-paths-confirmed.md):\n * the `agy` CLI v1.0.0 has NO separate config dir — `~/.gemini/antigravity-cli/`,\n * `~/.config/antigravity*`, and `~/.agy` are ALL ABSENT. `agy` SHARES the IDE's\n * `~/.gemini/antigravity/` tree (mcp_config.json, hooks.json, workflows, skills).\n * So the user-scope config resolution here is IDENTICAL to the IDE adapter (the\n * inherited USER_CONFIG_CANDIDATES) — installing both the IDE and CLI connectors\n * therefore writes the SAME files and is idempotent (observed as skip), which is\n * expected and correct. `agy`'s own extension surface is the `agy plugin` system\n * (install/uninstall/list/enable/disable) — future work would deploy as an agy\n * plugin; for now the MCP/workflows/skills surfaces ride the shared IDE files.\n *\n * LIVE-TEST RESOLUTION (2026-06-04, real `agy` v1.0.5 login + spawn): the prior\n * \"shares the IDE's ~/.gemini/antigravity/ file\" claim was WRONG for the CLI. The\n * standalone `agy` reads user MCP from **~/.gemini/config/mcp_config.json**\n * (root key `mcpServers`; project scope <proj>/.agents/mcp_config.json) — PROVEN:\n * a live `agy -p` session spawned an MCP server placed in `config/` and completed\n * a real initialize+tools/list+tools/call handshake; a negative control in\n * `antigravity/` was ignored. The binary carries \"failed to read mcp_config.json\"\n * + a literal \"/.gemini/config\" path; there is NO `--mcp-config` flag and `agy\n * mcp` is TUI-only. So this adapter now OVERRIDES userConfigCandidates to prefer\n * `~/.gemini/config/mcp_config.json` (canonical) over the inherited IDE\n * `antigravity/` default (kept as a prefer-existing fallback). Telemetry-wrap is\n * compatible: agy spawns command+args verbatim, so the home-bin serve wrapper is\n * spawned as written — i.e. a real agy session now emits a per-MCP telemetry row.\n * (agy also keeps its own home ~/.gemini/antigravity-cli/ for auth/state, but MCP\n * config lives in the shared ~/.gemini/config/.)\n *\n * Project scope is IDENTICAL to the IDE adapter (`<proj>/.agents/…`), as is every\n * hook/command/skill render and the runtime parse/format — all inherited.\n *\n * The user-scope config paths shared with the IDE (hooks.json + the global skills\n * dir) remain MEDIUM-CONFIDENCE / PATH-PROBED in the parent (not present on the\n * observed install) and surfaced by the doctor; user-scope mcp_config + workflows\n * are CONFIRMED at ~/.gemini/antigravity/.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { AntigravityAdapter } from \"../antigravity/index.js\";\nimport type { Adapter } from \"../spi.js\";\nimport type { DetectedPlatform, PlatformId } from \"../../core/types.js\";\n\nconst HOST: PlatformId = \"antigravity-cli\";\n\nexport class AntigravityCliAdapter extends AntigravityAdapter implements Adapter {\n override readonly id: PlatformId = HOST;\n override readonly name = \"Antigravity CLI\";\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n /**\n * Probe the CLI's runtime markers, DISTINCT from the IDE app even though the\n * two share `~/.gemini/antigravity/`: the `agy` binary at ~/.local/bin/agy\n * (the definitive CLI marker, CONFIRMED present) and the shared\n * ~/.gemini/antigravity/ tree (or a user-scope mcp_config candidate / the\n * project config). Reported before the IDE adapter in the registry so the\n * more-specific CLI marker (the `agy` binary) wins host detection. Note: a\n * machine with ONLY the IDE (no `agy` binary) will not match here, while one\n * with the CLI matches on the binary regardless of the shared config dir.\n */\n override detectInstalled(projectDir: string): DetectedPlatform {\n const home = homedir();\n const userConfig = this.resolveUserConfigPath();\n const agyBin = join(home, \".local\", \"bin\", \"agy\");\n const sharedDir = join(home, \".gemini\", \"antigravity\");\n const projectConfig = join(projectDir, \".agents\", \"mcp_config.json\");\n\n // The `agy` binary is the definitive CLI marker. The shared antigravity dir\n // and the user-scope mcp_config candidates are secondary signals (they also\n // match a pure-IDE install, so the binary is what truly distinguishes the CLI).\n const cliMarker = existsSync(agyBin);\n const userInstalled =\n cliMarker ||\n existsSync(sharedDir) ||\n this.userConfigCandidates().some((parts) => existsSync(join(home, ...parts)));\n const projInstalled = existsSync(projectConfig);\n const installed = userInstalled || projInstalled;\n\n // Report the scope/path that actually matched, so a project-only install\n // isn't misreported as a (non-existent) user install.\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\n const configPath = scope === \"project\" ? projectConfig : userConfig;\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 ? scope === \"project\"\n ? `found project Antigravity CLI config at ${projectConfig}`\n : `found Antigravity CLI (agy) at ${agyBin} / shared ${sharedDir}`\n : `no Antigravity CLI install at ${agyBin}, ${sharedDir}, or ${projectConfig}`,\n // The `agy` binary is a high-confidence CLI marker; matching only the shared\n // config dir is weaker (it could be a pure-IDE install).\n confidence: cliMarker ? \"high\" : installed ? \"medium\" : \"low\",\n };\n }\n\n /**\n * MCP user-config path — LIVE-PROVEN for `agy` v1.0.5 (2026-06-04). The\n * standalone CLI reads user MCP servers from `~/.gemini/config/mcp_config.json`\n * (root key `mcpServers`), NOT the IDE's `~/.gemini/antigravity/mcp_config.json`:\n * a real `agy -p` session spawned an MCP server ONLY when it was placed in\n * `config/` (negative control: a server in `antigravity/` was ignored), and the\n * binary carries the error string \"failed to read mcp_config.json\" + a literal\n * \"/.gemini/config\" path. `agy mcp` is TUI-only (no headless add) and there is\n * no `--mcp-config` flag. So the CLI must PREFER `config/` over the inherited\n * `antigravity/` default; the IDE path stays as a prefer-existing fallback.\n * (Skills/workflows/hooks dirs remain inherited; project scope\n * `<proj>/.agents/mcp_config.json` is already correct and live-proven.)\n */\n private static readonly CLI_USER_CONFIG_CANDIDATES = [\n [\".gemini\", \"config\", \"mcp_config.json\"], // CONFIRMED canonical for agy v1.0.5\n [\".gemini\", \"antigravity\", \"mcp_config.json\"], // legacy IDE layout (prefer-existing)\n ] as const;\n\n protected override userConfigCandidates(): ReadonlyArray<readonly string[]> {\n return AntigravityCliAdapter.CLI_USER_CONFIG_CANDIDATES;\n }\n}\n\nexport const adapter = new AntigravityCliAdapter();\nexport default adapter;\n"],"mappings":";;;;;;;;;;;;;AAyDA,SAAS,kBAAkB;AAC3B,SAAS,eAAe;AACxB,SAAS,YAAY;AAMrB,IAAM,OAAmB;AAElB,IAAM,wBAAN,MAAM,+BAA8B,mBAAsC;AAAA,EAC7D,KAAiB;AAAA,EACjB,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAchB,gBAAgB,YAAsC;AAC7D,UAAM,OAAO,QAAQ;AACrB,UAAM,aAAa,KAAK,sBAAsB;AAC9C,UAAM,SAAS,KAAK,MAAM,UAAU,OAAO,KAAK;AAChD,UAAM,YAAY,KAAK,MAAM,WAAW,aAAa;AACrD,UAAM,gBAAgB,KAAK,YAAY,WAAW,iBAAiB;AAKnE,UAAM,YAAY,WAAW,MAAM;AACnC,UAAM,gBACJ,aACA,WAAW,SAAS,KACpB,KAAK,qBAAqB,EAAE,KAAK,CAAC,UAAU,WAAW,KAAK,MAAM,GAAG,KAAK,CAAC,CAAC;AAC9E,UAAM,gBAAgB,WAAW,aAAa;AAC9C,UAAM,YAAY,iBAAiB;AAInC,UAAM,QAAQ,iBAAiB,CAAC,gBAAgB,YAAY;AAC5D,UAAM,aAAa,UAAU,YAAY,gBAAgB;AAEzD,WAAO;AAAA,MACL,IAAI,KAAK;AAAA,MACT,MAAM,KAAK;AAAA,MACX;AAAA,MACA,UAAU,KAAK;AAAA,MACf,cAAc,KAAK;AAAA,MACnB;AAAA,MACA;AAAA,MACA,QAAQ,YACJ,UAAU,YACR,2CAA2C,aAAa,KACxD,kCAAkC,MAAM,aAAa,SAAS,KAChE,iCAAiC,MAAM,KAAK,SAAS,QAAQ,aAAa;AAAA;AAAA;AAAA,MAG9E,YAAY,YAAY,SAAS,YAAY,WAAW;AAAA,IAC1D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,OAAwB,6BAA6B;AAAA,IACnD,CAAC,WAAW,UAAU,iBAAiB;AAAA;AAAA,IACvC,CAAC,WAAW,eAAe,iBAAiB;AAAA;AAAA,EAC9C;AAAA,EAEmB,uBAAyD;AAC1E,WAAO,uBAAsB;AAAA,EAC/B;AACF;AAEO,IAAM,UAAU,IAAI,sBAAsB;AACjD,IAAO,0BAAQ;","names":[]}
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  resolveSpawnCommand
4
- } from "./chunk-I5MLE6S7.js";
4
+ } from "./chunk-TO57WYBB.js";
5
5
 
6
6
  // src/core/spawn-child.ts
7
7
  import { spawn } from "child_process";
@@ -18,4 +18,4 @@ function spawnChild(command, args, options) {
18
18
  export {
19
19
  spawnChild
20
20
  };
21
- //# sourceMappingURL=chunk-F5RX62T7.js.map
21
+ //# sourceMappingURL=chunk-7QRUZAUG.js.map
@@ -1,4 +1,8 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ codexConfigHome,
4
+ xdgConfigHome
5
+ } from "./chunk-UM5S7DKK.js";
2
6
  import {
3
7
  connectorDir,
4
8
  connectorsDir,
@@ -136,14 +140,6 @@ function claudeKnownMarketplacePath(name) {
136
140
  const sourcePath = e.source?.path;
137
141
  return typeof sourcePath === "string" ? sourcePath : null;
138
142
  }
139
- function codexConfigHome() {
140
- const env = process.env.CODEX_HOME;
141
- if (env && env.trim() !== "") {
142
- if (env.startsWith("~")) return join(homedir(), env.replace(/^~[/\\]?/, ""));
143
- return resolve(env);
144
- }
145
- return join(homedir(), ".codex");
146
- }
147
143
  function codexPluginKey(connectorId) {
148
144
  return `${connectorId}@${MARKETPLACE_NAME}`;
149
145
  }
@@ -265,10 +261,6 @@ function qwenExtensionInstalled(connectorId) {
265
261
  join(qwenConfigDir(), "extensions", connectorId, "qwen-extension.json")
266
262
  );
267
263
  }
268
- function xdgConfigHome() {
269
- const xdg = process.env.XDG_CONFIG_HOME;
270
- return xdg && xdg.trim() !== "" ? resolve(xdg) : join(homedir(), ".config");
271
- }
272
264
  function opencodeConfigDir() {
273
265
  return join(xdgConfigHome(), "opencode");
274
266
  }
@@ -428,8 +420,13 @@ function marketplaceEvidence(connectorId, platform) {
428
420
  case "kilo-cli":
429
421
  return npmPluginInstalled(platform, connectorId) ? `${connectorId} listed in ${platform}'s config plugin array` : null;
430
422
  case "codex": {
431
- const codexHome = process.env.CODEX_HOME && process.env.CODEX_HOME.trim() !== "" ? resolve(process.env.CODEX_HOME) : join(homedir(), ".codex");
432
- const dir = join(codexHome, "plugins", "cache", MARKETPLACE_NAME, connectorId);
423
+ const dir = join(
424
+ codexConfigHome(),
425
+ "plugins",
426
+ "cache",
427
+ MARKETPLACE_NAME,
428
+ connectorId
429
+ );
433
430
  return existsSync(dir) ? `codex plugin cache ${dir} exists` : null;
434
431
  }
435
432
  default:
@@ -508,4 +505,4 @@ export {
508
505
  marketplaceEvidence,
509
506
  hashDirectory
510
507
  };
511
- //# sourceMappingURL=chunk-G5CQHVQG.js.map
508
+ //# sourceMappingURL=chunk-7TVBFRVI.js.map