@ken-jo/agent-connector 0.4.67 → 0.4.75

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 (160) hide show
  1. package/README.md +43 -6
  2. package/dist/{action-RUM6GP23.js → action-TCKBTTZX.js} +8 -8
  3. package/dist/{amazon-q-KXVJFT7Q.js → amazon-q-CB4XFX7T.js} +3 -3
  4. package/dist/{amp-WAPHJYTK.js → amp-6Q5OYHNW.js} +7 -3
  5. package/dist/amp-6Q5OYHNW.js.map +1 -0
  6. package/dist/{antigravity-GF3RU42A.js → antigravity-WIK3XBN5.js} +4 -4
  7. package/dist/{antigravity-cli-OH27IFH5.js → antigravity-cli-L3RZMF6V.js} +4 -4
  8. package/dist/{chunk-E45SUUD7.js → chunk-24K6JOKV.js} +3 -3
  9. package/dist/{chunk-IZ4XQ23W.js → chunk-2L6LTQ6L.js} +41 -6
  10. package/dist/chunk-2L6LTQ6L.js.map +1 -0
  11. package/dist/{chunk-RQCBBLTA.js → chunk-5LAFKXFM.js} +2 -2
  12. package/dist/{chunk-UVBAH263.js → chunk-7ITLLYWB.js} +2 -2
  13. package/dist/{chunk-DBQMX75U.js → chunk-BEFVJ2OE.js} +28 -2
  14. package/dist/chunk-BEFVJ2OE.js.map +1 -0
  15. package/dist/{chunk-ZSMGHEB5.js → chunk-DI6OWKH2.js} +7 -3
  16. package/dist/chunk-DI6OWKH2.js.map +1 -0
  17. package/dist/chunk-ECSRTK4M.js +386 -0
  18. package/dist/chunk-ECSRTK4M.js.map +1 -0
  19. package/dist/{chunk-F5COBB5F.js → chunk-FUXUEXDP.js} +3 -3
  20. package/dist/{chunk-NXR4HM5N.js → chunk-HKM3HUOK.js} +19 -19
  21. package/dist/{chunk-NXR4HM5N.js.map → chunk-HKM3HUOK.js.map} +1 -1
  22. package/dist/{chunk-P5KA5NVR.js → chunk-MDZG5QHB.js} +49 -3
  23. package/dist/chunk-MDZG5QHB.js.map +1 -0
  24. package/dist/{chunk-CSRBMJLU.js → chunk-MHDQWZ4A.js} +5 -5
  25. package/dist/{chunk-RHML2NOB.js → chunk-NUGMVVV2.js} +2 -2
  26. package/dist/chunk-NUGMVVV2.js.map +1 -0
  27. package/dist/{chunk-ZEFUDBTY.js → chunk-OEQJGBBW.js} +4 -4
  28. package/dist/{chunk-3Y23ZYYF.js → chunk-Q42SEI7W.js} +3 -3
  29. package/dist/{chunk-LS65GL2P.js → chunk-Q5LECKZL.js} +36 -36
  30. package/dist/{chunk-GCRRX4MO.js → chunk-TW4DVR4V.js} +2 -2
  31. package/dist/{claude-code-WLN43K7I.js → claude-code-HFBAAVWS.js} +10 -6
  32. package/dist/claude-code-HFBAAVWS.js.map +1 -0
  33. package/dist/cli/sdk.js +4 -4
  34. package/dist/cli.js +1 -1
  35. package/dist/{cline-PEGTGVQD.js → cline-26W4FEZ6.js} +3 -3
  36. package/dist/{codebuff-UG6LVSOM.js → codebuff-J5KEEBIL.js} +7 -3
  37. package/dist/codebuff-J5KEEBIL.js.map +1 -0
  38. package/dist/{codex-4LVDQXCD.js → codex-JKQ6TLRI.js} +16 -23
  39. package/dist/codex-JKQ6TLRI.js.map +1 -0
  40. package/dist/{continue-DYV5V55Y.js → continue-KQSJUSWX.js} +3 -3
  41. package/dist/{copilot-cli-NVFXFLUF.js → copilot-cli-YBNKLYUB.js} +65 -22
  42. package/dist/copilot-cli-YBNKLYUB.js.map +1 -0
  43. package/dist/{crush-PP4HYZLT.js → crush-JTWTZIPB.js} +20 -10
  44. package/dist/crush-JTWTZIPB.js.map +1 -0
  45. package/dist/{cursor-XMXOZKAP.js → cursor-2NIZSDZ4.js} +4 -4
  46. package/dist/{detect-IZOWP5AA.js → detect-CWEIQCRC.js} +4 -4
  47. package/dist/{doctor-5IVUQ2YH.js → doctor-AC437ZAW.js} +95 -13
  48. package/dist/doctor-AC437ZAW.js.map +1 -0
  49. package/dist/{droid-ETNOUIPJ.js → droid-HF2AIFB2.js} +3 -3
  50. package/dist/{gemini-cli-P7XJXWVH.js → gemini-cli-2EOK26S2.js} +3 -3
  51. package/dist/{goose-UZVA6MQC.js → goose-55JOTXS5.js} +3 -3
  52. package/dist/{hermes-IC6R4CII.js → hermes-QVZOZU4B.js} +3 -3
  53. package/dist/{hook-7IUPIHCZ.js → hook-VYD3OCLM.js} +8 -8
  54. package/dist/index.d.ts +2 -2
  55. package/dist/index.js +2 -2
  56. package/dist/{install-EP6GPQ65.js → install-S6BYIJ62.js} +11 -11
  57. package/dist/{introspect-BFcXpfUp.d.ts → introspect-5o5ick0_.d.ts} +9 -4
  58. package/dist/{jetbrains-copilot-MZO2RQGJ.js → jetbrains-copilot-DZ2ATXFN.js} +2 -2
  59. package/dist/{kilo-CCB34CQQ.js → kilo-GJNSBWVV.js} +3 -3
  60. package/dist/{kilo-cli-EOMN3WC7.js → kilo-cli-2CCB3DBI.js} +3 -3
  61. package/dist/{kimi-GUSJME55.js → kimi-YRPCSB6N.js} +3 -3
  62. package/dist/{kiro-6OHZ5RGV.js → kiro-BUOQFASX.js} +3 -3
  63. package/dist/{leaderboard-6I2E5XZK.js → leaderboard-SUSUDKHR.js} +2 -2
  64. package/dist/{mimo-code-ZPJJ6IIW.js → mimo-code-V4FP5PUJ.js} +3 -3
  65. package/dist/{mux-AFTVMGGM.js → mux-CMJSM42O.js} +3 -3
  66. package/dist/{nemoclaw-D5EN4G2Q.js → nemoclaw-VP56PGKC.js} +4 -4
  67. package/dist/{omp-GKI2PZ7G.js → omp-OOFGD3GG.js} +3 -3
  68. package/dist/{openclaw-A76PCNBV.js → openclaw-V73XHPXP.js} +4 -4
  69. package/dist/{opencode-M34E6PI7.js → opencode-MKLHSQRD.js} +3 -3
  70. package/dist/{package-BWLV24OO.js → package-KOAAVKHH.js} +9 -9
  71. package/dist/{pi-HVG6ZWFE.js → pi-NMVL7OFL.js} +2 -2
  72. package/dist/{qwen-code-OWLM3I5P.js → qwen-code-2XE2T6F4.js} +3 -3
  73. package/dist/{roo-code-RFKKTNNI.js → roo-code-YJOIKCCS.js} +3 -3
  74. package/dist/runtime/index.d.ts +1 -1
  75. package/dist/runtime/index.js +6 -6
  76. package/dist/sdk/index.d.ts +3 -3
  77. package/dist/sdk/index.js +3 -3
  78. package/dist/sdk/test.d.ts +33 -3
  79. package/dist/sdk/test.js +10 -280
  80. package/dist/sdk/test.js.map +1 -1
  81. package/dist/{serve-CM4HZPMP.js → serve-BU23QUSJ.js} +8 -8
  82. package/dist/{status-BPB4VLQX.js → status-N5LCQQ3R.js} +6 -6
  83. package/dist/{statusline-HIKR2I4Q.js → statusline-442XOF7R.js} +7 -7
  84. package/dist/{telemetry-SBVUJYNE.js → telemetry-V4YQL2NU.js} +5 -5
  85. package/dist/{trae-FVHQALK3.js → trae-QSV2JZFT.js} +3 -3
  86. package/dist/{types-ChUrvw0j.d.ts → types-D6RWGXm1.d.ts} +13 -0
  87. package/dist/{uninstall-MO3RGGVE.js → uninstall-WGEKTCDZ.js} +11 -11
  88. package/dist/{upgrade-6XIGSPGY.js → upgrade-IH7CKPTO.js} +11 -11
  89. package/dist/{usage-IBN36ZVW.js → usage-DI7XRCKM.js} +2 -2
  90. package/dist/{usage-event-4RJP37K6.js → usage-event-2FCU55AN.js} +7 -7
  91. package/dist/{vscode-copilot-6FLDRTKV.js → vscode-copilot-R23RTVST.js} +7 -3
  92. package/dist/vscode-copilot-R23RTVST.js.map +1 -0
  93. package/dist/{warp-7CC52UJV.js → warp-B72XSQ5G.js} +3 -3
  94. package/dist/{windsurf-6ZLQMBQW.js → windsurf-642VBMQ2.js} +3 -3
  95. package/dist/{zed-FULJMNBV.js → zed-6UJS7JKB.js} +3 -3
  96. package/package.json +1 -1
  97. package/dist/amp-WAPHJYTK.js.map +0 -1
  98. package/dist/chunk-DBQMX75U.js.map +0 -1
  99. package/dist/chunk-IZ4XQ23W.js.map +0 -1
  100. package/dist/chunk-P5KA5NVR.js.map +0 -1
  101. package/dist/chunk-RHML2NOB.js.map +0 -1
  102. package/dist/chunk-ZSMGHEB5.js.map +0 -1
  103. package/dist/claude-code-WLN43K7I.js.map +0 -1
  104. package/dist/codebuff-UG6LVSOM.js.map +0 -1
  105. package/dist/codex-4LVDQXCD.js.map +0 -1
  106. package/dist/copilot-cli-NVFXFLUF.js.map +0 -1
  107. package/dist/crush-PP4HYZLT.js.map +0 -1
  108. package/dist/doctor-5IVUQ2YH.js.map +0 -1
  109. package/dist/vscode-copilot-6FLDRTKV.js.map +0 -1
  110. /package/dist/{action-RUM6GP23.js.map → action-TCKBTTZX.js.map} +0 -0
  111. /package/dist/{amazon-q-KXVJFT7Q.js.map → amazon-q-CB4XFX7T.js.map} +0 -0
  112. /package/dist/{antigravity-GF3RU42A.js.map → antigravity-WIK3XBN5.js.map} +0 -0
  113. /package/dist/{antigravity-cli-OH27IFH5.js.map → antigravity-cli-L3RZMF6V.js.map} +0 -0
  114. /package/dist/{chunk-E45SUUD7.js.map → chunk-24K6JOKV.js.map} +0 -0
  115. /package/dist/{chunk-RQCBBLTA.js.map → chunk-5LAFKXFM.js.map} +0 -0
  116. /package/dist/{chunk-UVBAH263.js.map → chunk-7ITLLYWB.js.map} +0 -0
  117. /package/dist/{chunk-F5COBB5F.js.map → chunk-FUXUEXDP.js.map} +0 -0
  118. /package/dist/{chunk-CSRBMJLU.js.map → chunk-MHDQWZ4A.js.map} +0 -0
  119. /package/dist/{chunk-ZEFUDBTY.js.map → chunk-OEQJGBBW.js.map} +0 -0
  120. /package/dist/{chunk-3Y23ZYYF.js.map → chunk-Q42SEI7W.js.map} +0 -0
  121. /package/dist/{chunk-LS65GL2P.js.map → chunk-Q5LECKZL.js.map} +0 -0
  122. /package/dist/{chunk-GCRRX4MO.js.map → chunk-TW4DVR4V.js.map} +0 -0
  123. /package/dist/{cline-PEGTGVQD.js.map → cline-26W4FEZ6.js.map} +0 -0
  124. /package/dist/{continue-DYV5V55Y.js.map → continue-KQSJUSWX.js.map} +0 -0
  125. /package/dist/{cursor-XMXOZKAP.js.map → cursor-2NIZSDZ4.js.map} +0 -0
  126. /package/dist/{detect-IZOWP5AA.js.map → detect-CWEIQCRC.js.map} +0 -0
  127. /package/dist/{droid-ETNOUIPJ.js.map → droid-HF2AIFB2.js.map} +0 -0
  128. /package/dist/{gemini-cli-P7XJXWVH.js.map → gemini-cli-2EOK26S2.js.map} +0 -0
  129. /package/dist/{goose-UZVA6MQC.js.map → goose-55JOTXS5.js.map} +0 -0
  130. /package/dist/{hermes-IC6R4CII.js.map → hermes-QVZOZU4B.js.map} +0 -0
  131. /package/dist/{hook-7IUPIHCZ.js.map → hook-VYD3OCLM.js.map} +0 -0
  132. /package/dist/{install-EP6GPQ65.js.map → install-S6BYIJ62.js.map} +0 -0
  133. /package/dist/{jetbrains-copilot-MZO2RQGJ.js.map → jetbrains-copilot-DZ2ATXFN.js.map} +0 -0
  134. /package/dist/{kilo-CCB34CQQ.js.map → kilo-GJNSBWVV.js.map} +0 -0
  135. /package/dist/{kilo-cli-EOMN3WC7.js.map → kilo-cli-2CCB3DBI.js.map} +0 -0
  136. /package/dist/{kimi-GUSJME55.js.map → kimi-YRPCSB6N.js.map} +0 -0
  137. /package/dist/{kiro-6OHZ5RGV.js.map → kiro-BUOQFASX.js.map} +0 -0
  138. /package/dist/{leaderboard-6I2E5XZK.js.map → leaderboard-SUSUDKHR.js.map} +0 -0
  139. /package/dist/{mimo-code-ZPJJ6IIW.js.map → mimo-code-V4FP5PUJ.js.map} +0 -0
  140. /package/dist/{mux-AFTVMGGM.js.map → mux-CMJSM42O.js.map} +0 -0
  141. /package/dist/{nemoclaw-D5EN4G2Q.js.map → nemoclaw-VP56PGKC.js.map} +0 -0
  142. /package/dist/{omp-GKI2PZ7G.js.map → omp-OOFGD3GG.js.map} +0 -0
  143. /package/dist/{openclaw-A76PCNBV.js.map → openclaw-V73XHPXP.js.map} +0 -0
  144. /package/dist/{opencode-M34E6PI7.js.map → opencode-MKLHSQRD.js.map} +0 -0
  145. /package/dist/{package-BWLV24OO.js.map → package-KOAAVKHH.js.map} +0 -0
  146. /package/dist/{pi-HVG6ZWFE.js.map → pi-NMVL7OFL.js.map} +0 -0
  147. /package/dist/{qwen-code-OWLM3I5P.js.map → qwen-code-2XE2T6F4.js.map} +0 -0
  148. /package/dist/{roo-code-RFKKTNNI.js.map → roo-code-YJOIKCCS.js.map} +0 -0
  149. /package/dist/{serve-CM4HZPMP.js.map → serve-BU23QUSJ.js.map} +0 -0
  150. /package/dist/{status-BPB4VLQX.js.map → status-N5LCQQ3R.js.map} +0 -0
  151. /package/dist/{statusline-HIKR2I4Q.js.map → statusline-442XOF7R.js.map} +0 -0
  152. /package/dist/{telemetry-SBVUJYNE.js.map → telemetry-V4YQL2NU.js.map} +0 -0
  153. /package/dist/{trae-FVHQALK3.js.map → trae-QSV2JZFT.js.map} +0 -0
  154. /package/dist/{uninstall-MO3RGGVE.js.map → uninstall-WGEKTCDZ.js.map} +0 -0
  155. /package/dist/{upgrade-6XIGSPGY.js.map → upgrade-IH7CKPTO.js.map} +0 -0
  156. /package/dist/{usage-IBN36ZVW.js.map → usage-DI7XRCKM.js.map} +0 -0
  157. /package/dist/{usage-event-4RJP37K6.js.map → usage-event-2FCU55AN.js.map} +0 -0
  158. /package/dist/{warp-7CC52UJV.js.map → warp-B72XSQ5G.js.map} +0 -0
  159. /package/dist/{windsurf-6ZLQMBQW.js.map → windsurf-642VBMQ2.js.map} +0 -0
  160. /package/dist/{zed-FULJMNBV.js.map → zed-6UJS7JKB.js.map} +0 -0
@@ -1,16 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runUsageEvent
4
- } from "./chunk-CSRBMJLU.js";
4
+ } from "./chunk-MHDQWZ4A.js";
5
5
  import "./chunk-OP4KBXUO.js";
6
6
  import "./chunk-7QRUZAUG.js";
7
- import "./chunk-GCRRX4MO.js";
8
- import "./chunk-E45SUUD7.js";
7
+ import "./chunk-TW4DVR4V.js";
8
+ import "./chunk-24K6JOKV.js";
9
9
  import "./chunk-D6ZJS4ND.js";
10
10
  import "./chunk-KHO5WNTP.js";
11
- import "./chunk-RQCBBLTA.js";
12
- import "./chunk-UVBAH263.js";
13
- import "./chunk-LS65GL2P.js";
11
+ import "./chunk-5LAFKXFM.js";
12
+ import "./chunk-7ITLLYWB.js";
13
+ import "./chunk-Q5LECKZL.js";
14
14
  import "./chunk-7CZKXXBD.js";
15
15
  import "./chunk-TO57WYBB.js";
16
16
  import "./chunk-ALVXORZM.js";
@@ -50,4 +50,4 @@ async function run(argv) {
50
50
  export {
51
51
  run
52
52
  };
53
- //# sourceMappingURL=usage-event-4RJP37K6.js.map
53
+ //# sourceMappingURL=usage-event-2FCU55AN.js.map
@@ -4,12 +4,12 @@ import {
4
4
  } from "./chunk-H53QZQJI.js";
5
5
  import {
6
6
  rewriteEnvRefs
7
- } from "./chunk-DBQMX75U.js";
7
+ } from "./chunk-BEFVJ2OE.js";
8
8
  import {
9
9
  BaseAdapter,
10
10
  renderSkillMd,
11
11
  renderSubagentMd
12
- } from "./chunk-RHML2NOB.js";
12
+ } from "./chunk-NUGMVVV2.js";
13
13
  import {
14
14
  buildHomeBinHookCommand,
15
15
  buildWrappedStdio,
@@ -68,6 +68,10 @@ var VSCodeCopilotAdapter = class extends BaseAdapter {
68
68
  canModifyOutput: false,
69
69
  canInjectSessionContext: true,
70
70
  transports: ["stdio", "http", "sse"],
71
+ // Server env/url use VS Code's NATIVE ${env:VAR} interpolation
72
+ // (rewriteEnvRefs) — the token survives into mcp.json, never a baked
73
+ // literal — so the installer's unset-env-ref bake warn does not apply here.
74
+ nativeServerEnvInterpolation: true,
71
75
  // Content surfaces: VS Code Copilot authors prompt files, Agent Skills, and
72
76
  // chat-mode agent files under the workspace .github/ tree (see content-file
73
77
  // path helpers below). All three are supported.
@@ -744,4 +748,4 @@ export {
744
748
  adapter,
745
749
  vscode_copilot_default as default
746
750
  };
747
- //# sourceMappingURL=vscode-copilot-6FLDRTKV.js.map
751
+ //# sourceMappingURL=vscode-copilot-R23RTVST.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/vscode-copilot/index.ts"],"sourcesContent":["/**\n * adapters/vscode-copilot — VS Code Copilot platform adapter for agent-connector.\n *\n * Generalized from context-mode's proven VS Code Copilot adapter: the served\n * identity is now `ctx.connector` (not a hardcoded \"context-mode\"), and every\n * hook command points at the single stable home binary\n * (`buildHomeBinHookCommand`) so one framework update propagates everywhere.\n *\n * VS Code Copilot is a json-stdio host (report §2 \"Platform Integration Matrix\"):\n * - MCP servers: workspace (project) scope → <projectDir>/.vscode/mcp.json;\n * user-profile scope → ~/.vscode/mcp.json. The ROOT KEY is \"servers\" (NOT\n * \"mcpServers\" — a Cursor footgun VS Code deliberately diverges on), with an\n * optional sibling \"inputs\" array. The file is officially JSONC, but a plain\n * JSON write is valid JSONC, so we write strict JSON.\n * - Hooks (Preview, ~v1.110): discovered from .github/hooks/*.json (and from\n * Claude-compatible .claude/settings.json). We write a per-connector file at\n * <projectDir>/.github/hooks/<connector-id>.json shaped like the Copilot\n * hooks schema: `{ version: 1, hooks: { <PascalCaseEvent>: [ { type:\n * \"command\", command } ] } }`. The top-level `version: 1` is REQUIRED — the\n * Copilot runtime rejects a version-less file and no hooks fire. Unlike\n * Claude, each entry is a FLAT `{ type, command }` object (no `{ matcher,\n * hooks:[...] }` wrapper). Matchers are parsed but IGNORED (all hooks fire\n * on all tools) — we still persist a connector-declared matcher for parity.\n * - Reply: Claude-compatible JSON on stdout (exit 0). A `hookSpecificOutput`\n * object keyed by PascalCase `hookEventName` carries permissionDecision\n * (deny|ask) + permissionDecisionReason, additionalContext, and (PreToolUse)\n * updatedInput. This mirrors the claude-code adapter exactly.\n *\n * Env interpolation: VS Code supports its own `${env:VAR}` (and `${input:VAR}`)\n * native interpolation, so env/header/url values are rewritten to the native\n * `${env:VAR}` token rather than baked into the file. The token is documented at\n * vscodeEnvToken below.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport type { Adapter, HookReply, InstallContext, NormalizedEvent } from \"../spi.js\";\nimport type {\n ChangeRecord,\n CommandDef,\n DetectedPlatform,\n HealthCheck,\n HookEventName,\n HookParadigm,\n HookResponse,\n NotificationEvent,\n PlatformCapabilities,\n PlatformId,\n PostToolUseEvent,\n PostCompactEvent,\n PreCompactEvent,\n PreToolUseEvent,\n ServerDef,\n SessionEndEvent,\n SessionStartEvent,\n StopEvent,\n SubagentStartEvent,\n SubagentStopEvent,\n Transport,\n UserPromptSubmitEvent,\n} from \"../../core/types.js\";\nimport { rewriteEnvRefs } from \"../../core/interpolate.js\";\nimport {\n buildHomeBinHookCommand,\n buildWrappedStdio,\n isHomeBinHookCommand,\n} from \"../../core/spawn.js\";\nimport { renderSkillMd, renderSubagentMd } from \"../claude-code/render.js\";\nimport { normalizeSessionSource } from \"../claude-code/wire.js\";\n\nconst HOST: PlatformId = \"vscode-copilot\";\n\n/**\n * VS Code's MCP root key is \"servers\" — NOT \"mcpServers\". This is the single\n * most common VS Code Copilot integration bug (report §1): a config written\n * under \"mcpServers\" is silently ignored.\n */\nconst MCP_ROOT_KEY = \"servers\";\n\n/** Top-level version the Copilot hooks runtime requires; a version-less file is rejected. */\nconst VSCODE_HOOKS_VERSION = 1;\n\n/**\n * VS Code Copilot reads PascalCase hook event names from its hooks file —\n * identical to Claude Code. Only the events VS Code actually delivers are\n * registered; everything else has no Copilot equivalent and is reported as a\n * warn/skip at install time.\n *\n * VS Code's official Hook Events table (microsoft/vscode-copilot-chat:\n * assets/prompts/skills/agent-customization/references/hooks.md) is, verbatim\n * (PascalCase): SessionStart, UserPromptSubmit, PreToolUse, PostToolUse,\n * PreCompact, SubagentStart, SubagentStop, Stop — all eight now wired 1:1.\n * SessionEnd, Notification, PermissionRequest and PostToolUseFailure are NOT in\n * the list — they have no VS Code analog and skip-warn.\n */\nconst EVENT_MAP: Partial<Record<HookEventName, string>> = {\n PreToolUse: \"PreToolUse\",\n PostToolUse: \"PostToolUse\",\n PreCompact: \"PreCompact\",\n SessionStart: \"SessionStart\",\n UserPromptSubmit: \"UserPromptSubmit\",\n Stop: \"Stop\",\n SubagentStart: \"SubagentStart\",\n SubagentStop: \"SubagentStop\",\n};\n\n/** A single VS Code Copilot native hook entry — a flat command object. */\ninterface VSCodeHookEntry {\n type: \"command\";\n command: string;\n}\n\n/** The shape of a VS Code Copilot .github/hooks/<connector>.json file. */\ninterface VSCodeHooksFile {\n version?: number;\n hooks?: Record<string, VSCodeHookEntry[]>;\n}\n\n/** Native MCP server entry shapes VS Code accepts under `servers`. */\ninterface VSCodeStdioServer {\n type: \"stdio\";\n command: string;\n args?: string[];\n env?: Record<string, string>;\n cwd?: string;\n}\ninterface VSCodeHttpServer {\n type: \"http\" | \"sse\";\n url: string;\n headers?: Record<string, string>;\n}\n\n/**\n * Raw VS Code Copilot hook stdin payload. Field names are PRIMARY-SOURCE\n * VERIFIED against the official docs (https://code.visualstudio.com/docs/copilot/\n * customization/hooks — \"Hook input and output\"). Only fields the host actually\n * serializes are declared here; the snake_case shape happens to align with the\n * Claude dialect but the field SET is VS Code's own.\n *\n * Common input fields (every event): timestamp, cwd, session_id,\n * hook_event_name, transcript_path. There is NO `workspace_roots` field — the\n * old `workspace_roots[0]` projectDir fallback read a host-nonexistent field\n * (removed; getProjectDir now relies on `cwd` only).\n */\ninterface VSCodeWireInput {\n session_id?: string;\n transcript_path?: string;\n cwd?: string;\n hook_event_name?: string;\n\n // tool events. PostToolUse fires ONLY after a tool completes SUCCESSFULLY and\n // sends { tool_name, tool_input, tool_use_id, tool_response } — there is NO\n // `tool_output` and NO `error_message` field, so the old isError/tool_output/\n // error_message reads were dead (removed). Primary source: docs \"PostToolUse\n // input\" — `tool_response` is the only result field.\n tool_name?: string;\n tool_input?: Record<string, unknown>;\n tool_response?: unknown;\n tool_use_id?: string;\n\n // SessionStart\n source?: string;\n // SessionEnd\n reason?: string;\n // UserPromptSubmit\n prompt?: string;\n // PreCompact\n trigger?: string;\n // Stop / SubagentStop\n stop_hook_active?: boolean;\n // Notification\n message?: string;\n\n // SubagentStart / SubagentStop. Per docs \"SubagentStart input\" /\n // \"SubagentStop input\" the payload is EXACTLY { agent_id, agent_type } (+\n // stop_hook_active on Stop). There is NO `agent_transcript_path` and NO\n // `last_assistant_message` on this host — those reads were dead (removed).\n agent_id?: string;\n agent_type?: string;\n\n /** Injected by the entrypoint so the runtime knows which connector to dispatch. */\n connector?: string;\n}\n\nexport class VSCodeCopilotAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"VS Code Copilot\";\n readonly paradigm: HookParadigm = \"json-stdio\";\n\n readonly capabilities: PlatformCapabilities = {\n // Memory surface: AGENTS.md-first managed block via the BaseAdapter default\n // (memoryTargets: project <projectDir>/AGENTS.md; user scope where documented).\n supportsMemory: true,\n // VS Code Copilot's Preview hooks runtime delivers all eight events in its\n // official Hook Events table: Pre/PostToolUse, PreCompact, SessionStart,\n // UserPromptSubmit, Stop, and Subagent Start/Stop. PostToolUse, UserPromptSubmit,\n // Stop and SubagentStop are BLOCKABLE via the top-level {decision:\"block\"} shape;\n // PreToolUse permission flows through hookSpecificOutput.permissionDecision (per\n // the Output Contract — see formatReply).\n preToolUse: true,\n postToolUse: true,\n preCompact: true,\n sessionStart: true,\n sessionEnd: false,\n userPromptSubmit: true,\n stop: true,\n notification: false,\n // Newer events: VS Code's Preview hooks runtime delivers SubagentStart /\n // SubagentStop (Claude-compatible). permissionRequest / postToolUseFailure\n // stay unset — no VS Code analog exists; install reports the skip-warn.\n subagentStart: true,\n subagentStop: true,\n // PreToolUse can rewrite tool input (updatedInput) but a PostToolUse hook\n // cannot rewrite already-emitted tool output — same as Claude/Cursor.\n canModifyArgs: true,\n canModifyOutput: false,\n canInjectSessionContext: true,\n transports: [\"stdio\", \"http\", \"sse\"],\n // Server env/url use VS Code's NATIVE ${env:VAR} interpolation\n // (rewriteEnvRefs) — the token survives into mcp.json, never a baked\n // literal — so the installer's unset-env-ref bake warn does not apply here.\n nativeServerEnvInterpolation: true,\n // Content surfaces: VS Code Copilot authors prompt files, Agent Skills, and\n // chat-mode agent files under the workspace .github/ tree (see content-file\n // path helpers below). All three are supported.\n supportsCommands: true,\n supportsSkills: true,\n supportsSubagents: true,\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userDir = join(homedir(), \".vscode\");\n const userMcp = join(userDir, \"mcp.json\");\n const userInsidersDir = join(homedir(), \".vscode-insiders\");\n const projectVscode = join(projectDir, \".vscode\");\n const projectMcp = join(projectVscode, \"mcp.json\");\n\n const projInstalled = existsSync(projectMcp) || existsSync(projectVscode);\n const userInstalled =\n existsSync(userMcp) || existsSync(userDir) || existsSync(userInsidersDir);\n const installed = projInstalled || userInstalled;\n\n // Report the scope/path/reason for the marker that actually matched, so a\n // project-only install isn't misreported as a (non-existent) user install.\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\n const configPath = scope === \"project\" ? projectMcp : userMcp;\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath,\n scope,\n reason: installed\n ? scope === \"project\"\n ? `found project VS Code config at ${projectVscode}`\n : `found VS Code config under ${userDir}`\n : `no VS Code config at ${userDir}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n /**\n * Config dir choice (documented per task brief): project (workspace) scope →\n * <projectDir>/.vscode; user-profile scope → ~/.vscode. The real VS Code user\n * profile dir is OS-specific and not reliably discoverable without launching\n * VS Code, so ~/.vscode is the reasonable, cross-OS, no-launch choice — it is\n * also where \"MCP: Open User Configuration\" writes on a default profile.\n */\n getConfigDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".vscode\")\n : join(homedir(), \".vscode\");\n }\n\n /** MCP server registration lives in <configDir>/mcp.json under root \"servers\". */\n getServerConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"mcp.json\");\n }\n\n /**\n * Hook registration lives in the workspace-discovered .github/hooks tree,\n * which VS Code Copilot scans for *.json hook files. We write one file per\n * connector so installs/uninstalls never clobber another connector's hooks.\n * Anchored on projectDir for both scopes — .github/hooks is a workspace\n * concept (there is no user-profile equivalent in the Copilot hooks schema).\n */\n getHookConfigPath(ctx: InstallContext): string {\n return join(ctx.projectDir, \".github\", \"hooks\", `${ctx.connector.id}.json`);\n }\n\n // ── MCP server install / uninstall ───────────────────────────────────────\n\n 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 vscode-copilot\"\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 VS Code's native `servers` entry. */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): VSCodeStdioServer | VSCodeHttpServer {\n const transport: Transport = server.transport;\n\n if (transport === \"stdio\") {\n let command = server.command ?? \"\";\n let args = [...(server.args ?? [])];\n\n // Transparent telemetry wrapping: route the real command through\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\n ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\n\n const entry: VSCodeStdioServer = { type: \"stdio\", command: this.rewrite(command) };\n if (args.length > 0) entry.args = args.map((a) => this.rewrite(a));\n const env = this.renderEnv(server.env);\n if (env) entry.env = env;\n if (server.cwd) entry.cwd = this.rewrite(server.cwd);\n return entry;\n }\n\n // Remote transports — VS Code registers a URL. An explicit `sse` forces an\n // SSE-only connection; `http` (Streamable HTTP) auto-falls-back to SSE when a\n // server doesn't support it (code.visualstudio.com/docs/agents/reference/mcp-configuration).\n const entry: VSCodeHttpServer = {\n type: transport === \"sse\" ? \"sse\" : \"http\",\n url: this.rewrite(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. VS Code supports its own `${env:VAR}` native\n * interpolation, so translate `${env:VAR}` refs to that native token rather\n * than baking secrets into the file. Literals pass through unchanged.\n */\n private renderEnv(\n env: Record<string, string> | undefined,\n ): Record<string, string> | undefined {\n if (!env || Object.keys(env).length === 0) return undefined;\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(env)) out[k] = this.rewrite(v);\n return out;\n }\n\n /** Translate `${env:VAR(:-default)}` to VS Code's native `${env:VAR}` token. */\n private rewrite(value: string): string {\n return rewriteEnvRefs(value, vscodeEnvToken);\n }\n\n // ── Hook install / uninstall ─────────────────────────────────────────────\n\n installHooks(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.hooks === false) {\n return [\n { platform: this.id, action: \"skip\", detail: \"hooks disabled for vscode-copilot\" },\n ];\n }\n if (connector.hookEvents.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no hooks\" }];\n }\n\n const hooksPath = this.getHookConfigPath(ctx);\n const symlink = this.symlinkPathWarning(hooksPath);\n if (symlink) return [symlink];\n\n const file = this.readJson<VSCodeHooksFile>(hooksPath) ?? {};\n const __skip = this.malformedHookRootSkip(hooksPath, (file as Record<string, unknown>).hooks);\n if (__skip) return [__skip];\n const hooks = (file.hooks ??= {});\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const event of connector.hookEvents) {\n const vscodeEvent = EVENT_MAP[event];\n if (!vscodeEvent) {\n // No VS Code Copilot equivalent for this normalized event — report+skip.\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: hooksPath,\n detail: `${event} has no VS Code Copilot hook equivalent — skipped`,\n });\n continue;\n }\n\n const command = buildHomeBinHookCommand(ctx.homeBinPath, HOST, event, connector.id);\n const entry: VSCodeHookEntry = { type: \"command\", command };\n\n const bucket = (hooks[vscodeEvent] ??= []);\n const existingIdx = bucket.findIndex((e) => this.isOurCommand(e.command, ctx));\n\n if (existingIdx >= 0) {\n if (JSON.stringify(bucket[existingIdx]) === JSON.stringify(entry)) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: `hooks.${vscodeEvent} already registered`,\n });\n continue;\n }\n bucket[existingIdx] = entry;\n changes.push({\n platform: this.id,\n action: \"update\",\n path: hooksPath,\n detail: `hooks.${vscodeEvent}`,\n });\n } else {\n bucket.push(entry);\n changes.push({\n platform: this.id,\n action: \"create\",\n path: hooksPath,\n detail: `hooks.${vscodeEvent}`,\n });\n }\n mutated = true;\n }\n\n if (mutated) {\n // The top-level version is REQUIRED — a version-less file is rejected and\n // no hooks fire. Always (re)assert it when we write.\n file.version = VSCODE_HOOKS_VERSION;\n this.writeJson(hooksPath, file, ctx.dryRun);\n }\n return changes;\n }\n\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n const hooksPath = this.getHookConfigPath(ctx);\n const symlink = this.symlinkPathWarning(hooksPath);\n if (symlink) return [symlink];\n\n const file = this.readJson<VSCodeHooksFile>(hooksPath);\n const hooks = file?.hooks;\n if (!file || !hooks) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: \"no hooks section present\",\n },\n ];\n }\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const vscodeEvent of Object.keys(hooks)) {\n const bucket = hooks[vscodeEvent];\n if (!Array.isArray(bucket)) continue;\n\n const before = bucket.length;\n // Only strip OUR connector's home-bin commands — never another\n // connector's (isHomeBinHookCommand is id-anchored).\n const next = bucket.filter((e) => !this.isOurCommand(e.command, ctx));\n const removed = before - next.length;\n if (removed > 0) {\n if (next.length > 0) hooks[vscodeEvent] = next;\n else delete hooks[vscodeEvent];\n changes.push({\n platform: this.id,\n action: \"remove\",\n path: hooksPath,\n detail: `hooks.${vscodeEvent} (${removed})`,\n });\n mutated = true;\n }\n }\n\n if (mutated) {\n // The hooks file is connector-OWNED (<connector-id>.json), so when our\n // strip leaves it with NO hooks we must DELETE the whole file rather than\n // rewrite a `{ \"version\": 1, \"hooks\": {} }` shell — an empty shell is an\n // orphan per-connector file that lingers after uninstall. A non-empty\n // result still belongs to us, so we rewrite it as before. dryRun reports\n // the would-be remove without mutating the filesystem.\n if (Object.keys(hooks).length === 0) {\n changes.push(\n this.removeManagedFile(\n hooksPath,\n ctx.dryRun,\n \"removed empty connector hooks file\",\n \"no hooks file present\",\n ),\n );\n // Clean up the parent .github/hooks dir only when it is now empty (it is\n // a per-connector tree; leave it in place if other connectors' files\n // remain).\n changes.push(this.removeDirIfEmpty(dirname(hooksPath), ctx.dryRun));\n } else {\n this.writeJson(hooksPath, file, ctx.dryRun);\n }\n }\n if (changes.length === 0) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: \"no matching hook entries\",\n });\n }\n return changes;\n }\n\n /** True when a hook command references our home binary AND this connector id\n * (anchored so a shared-prefix id can't collide — see isHomeBinHookCommand). */\n private isOurCommand(command: string | undefined, ctx: InstallContext): boolean {\n return isHomeBinHookCommand(command, ctx.homeBinPath, ctx.connector.id);\n }\n\n // ── Content surfaces: commands / skills / subagents ──────────────────────\n // CONTENT-ONLY: pure native-file writers under the workspace .github/ tree\n // ({prompts,skills,agents}). No runtime dispatch, no home-bin pointer, no\n // telemetry wrap. Each method is idempotent (byte-identical → skip) via\n // BaseAdapter.writeContentFile and reversible via removeContentFile. Honors\n // platforms[\"vscode-copilot\"] per-surface false to skip.\n //\n // SHARED .github TREE: vscode-copilot, copilot-cli, and jetbrains-copilot all\n // write under the SAME project <projectDir>/.github tree. The rendered content\n // is identical and idempotent across those connectors, and uninstall here only\n // removes the files THIS connector declared — never another writer's files.\n //\n // SCOPE NOTE: .github is a workspace concept; the Copilot prompt/skill/agent\n // discovery is workspace-rooted and there is no documented per-user .github\n // authoring location. VS Code's reliable per-user authoring root is the user\n // profile prompts dir under the OS app-data path, which is not discoverable\n // without launching VS Code. So for user scope we anchor on\n // <homedir>/.config/github-copilot (the documented cross-OS Copilot user dir;\n // see contentRootDir) rather than fabricating a profile path. Project scope is\n // the primary, fully-supported path.\n\n /**\n * Root of the content tree. Project (workspace) scope → <projectDir>/.github,\n * which VS Code Copilot scans for prompt/skill/agent files (and which\n * copilot-cli + jetbrains-copilot share). User scope has no documented\n * workspace-independent .github equivalent, so we anchor on the documented\n * cross-OS Copilot user dir ~/.config/github-copilot to keep user-scope writes\n * deterministic and removable.\n */\n private contentRootDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".github\")\n : join(homedir(), \".config\", \"github-copilot\");\n }\n\n private promptsDir(ctx: InstallContext): string {\n return join(this.contentRootDir(ctx), \"prompts\");\n }\n private skillsDir(ctx: InstallContext): string {\n // Project scope: .github/skills (a VS Code-documented project location).\n // User scope: ~/.agents/skills — the vendor-neutral Agent Skills location\n // VS Code reads for personal skills. Deliberately NOT ~/.copilot/skills\n // (also read): copilot-cli's adapter owns that dir, and two adapters\n // writing the same SKILL.md would fight over ownership at uninstall.\n // (~/.config/github-copilot/skills, the 0.1.0 target, is read by nothing.)\n return ctx.scope === \"project\"\n ? join(this.contentRootDir(ctx), \"skills\")\n : join(homedir(), \".agents\", \"skills\");\n }\n private agentsDir(ctx: InstallContext): string {\n return join(this.contentRootDir(ctx), \"agents\");\n }\n\n /** Native command file path: <ghDir>/prompts/<name>.prompt.md. */\n private commandPath(ctx: InstallContext, name: string): string {\n return join(this.promptsDir(ctx), `${name}.prompt.md`);\n }\n /** Native skill dir: <ghDir>/skills/<name>. */\n private skillDir(ctx: InstallContext, name: string): string {\n return join(this.skillsDir(ctx), name);\n }\n /** Native subagent file path: <ghDir>/agents/<name>.agent.md. */\n private subagentPath(ctx: InstallContext, name: string): string {\n return join(this.agentsDir(ctx), `${name}.agent.md`);\n }\n\n // ── Commands ──────────────────────────────────────────────────────────────\n\n override installCommands(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.commands === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"commands disabled for vscode-copilot\" }];\n }\n if (connector.commands.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\n }\n return connector.commands.map((cmd) =>\n this.writeContentFile(\n this.commandPath(ctx, cmd.name),\n this.renderCommand(cmd),\n ctx.dryRun,\n ),\n );\n }\n\n override uninstallCommands(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.commands.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\n }\n return connector.commands.map((cmd) =>\n this.removeContentFile(this.commandPath(ctx, cmd.name), ctx.dryRun),\n );\n }\n\n /** Render a VS Code Copilot prompt file: md+frontmatter(description, tools, model, argument-hint). */\n private renderCommand(cmd: CommandDef): string {\n const frontmatter: Record<string, unknown> = {};\n if (cmd.description !== undefined) frontmatter.description = cmd.description;\n // VS Code prompt files express tool access as a `tools` array, sourced from\n // the portable tools.allow policy.\n const allow = cmd.tools?.allow;\n if (allow && allow.length > 0) frontmatter.tools = [...allow];\n if (cmd.model !== undefined) frontmatter.model = cmd.model;\n if (cmd.argumentHint !== undefined) frontmatter[\"argument-hint\"] = cmd.argumentHint;\n if (cmd.extra) Object.assign(frontmatter, cmd.extra);\n return this.renderFrontmatterMd(frontmatter, cmd.prompt);\n }\n\n // ── Skills ────────────────────────────────────────────────────────────────\n\n override installSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.skills === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"skills disabled for vscode-copilot\" }];\n }\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n changes.push(\n this.writeContentFile(join(dir, \"SKILL.md\"), renderSkillMd(skill), ctx.dryRun),\n );\n // Bundle any resource files beside SKILL.md (relative path → contents).\n // Defense-in-depth: skip+warn on any key that escapes the skill dir\n // (config-time validation already rejects these, but never trust input).\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n detail: `skill resource \"${rel}\" escapes the skill dir; skipped`,\n });\n continue;\n }\n changes.push(this.writeContentFile(target, contents, ctx.dryRun));\n }\n }\n return changes;\n }\n\n override uninstallSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n // Remove only the files we wrote (SKILL.md + declared resources), then the\n // skill dir itself when we own its full contents.\n changes.push(this.removeContentFile(join(dir, \"SKILL.md\"), ctx.dryRun));\n for (const rel of Object.keys(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) continue; // never delete outside the skill dir\n changes.push(this.removeContentFile(target, ctx.dryRun));\n }\n // Only remove the skill dir when WE own its full contents — never rm -rf a\n // dir that still holds user-added / sibling-tool / shared files.\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\n }\n return changes;\n }\n\n // ── Subagents ───────────────────────────────────────────────────────────────\n\n override installSubagents(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.subagents === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"subagents disabled for vscode-copilot\" }];\n }\n if (connector.subagents.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\n }\n return connector.subagents.map((agent) =>\n this.writeContentFile(\n this.subagentPath(ctx, agent.name),\n renderSubagentMd(agent),\n ctx.dryRun,\n ),\n );\n }\n\n override uninstallSubagents(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.subagents.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\n }\n return connector.subagents.map((agent) =>\n this.removeContentFile(this.subagentPath(ctx, agent.name), ctx.dryRun),\n );\n }\n\n // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const mcpPath = this.getServerConfigPath(ctx);\n const hooksPath = this.getHookConfigPath(ctx);\n const connectorId = ctx.connector.id;\n const homeBin = ctx.homeBinPath;\n const hookEvents = ctx.connector.hookEvents;\n const checks: HealthCheck[] = [\n {\n name: `${this.name}: mcp.json present`,\n check: () =>\n existsSync(mcpPath)\n ? { status: \"OK\", detail: mcpPath }\n : { status: \"FAIL\", detail: `not found: ${mcpPath}` },\n },\n {\n name: `${this.name}: hook command registered`,\n check: () => {\n if (hookEvents.length === 0) {\n return { status: \"OK\", detail: \"no hooks declared\" };\n }\n const file = this.readJson<VSCodeHooksFile>(hooksPath);\n if (!file) return { status: \"FAIL\", detail: `not found: ${hooksPath}` };\n if (file.version !== VSCODE_HOOKS_VERSION) {\n return {\n status: \"FAIL\",\n detail: `${hooksPath} missing required \"version\": ${VSCODE_HOOKS_VERSION} — Copilot rejects it`,\n };\n }\n const registered = Object.values(file.hooks ?? {}).some((entries) =>\n (entries ?? []).some((e) =>\n isHomeBinHookCommand(e.command, homeBin, connectorId),\n ),\n );\n return registered\n ? { status: \"OK\", detail: \"hook command present\" }\n : { status: \"FAIL\", detail: `no hook for ${connectorId} in ${hooksPath}` };\n },\n },\n ];\n\n // Content-surface checks: only assert presence of the files this connector\n // declares (skip silently for surfaces it never asked for).\n for (const cmd of ctx.connector.commands) {\n const p = this.commandPath(ctx, cmd.name);\n checks.push({\n name: `${this.name}: command ${cmd.name} present`,\n check: () =>\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\n });\n }\n for (const skill of ctx.connector.skills) {\n const p = join(this.skillDir(ctx, skill.name), \"SKILL.md\");\n checks.push({\n name: `${this.name}: skill ${skill.name} present`,\n check: () =>\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\n });\n }\n for (const agent of ctx.connector.subagents) {\n const p = this.subagentPath(ctx, agent.name);\n checks.push({\n name: `${this.name}: subagent ${agent.name} present`,\n check: () =>\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\n });\n }\n return checks;\n }\n\n // ── Runtime: parse VS Code Copilot stdin JSON → normalized event ──────────\n\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\n const input = (raw ?? {}) as VSCodeWireInput;\n const connectorId = typeof input.connector === \"string\" ? input.connector : \"\";\n const sessionId = extractSessionId(input);\n const projectDir = this.getProjectDir(input);\n\n const base = {\n hostPlatform: HOST,\n connectorId,\n sessionId,\n raw,\n ...(projectDir !== undefined ? { projectDir } : {}),\n } as const;\n\n switch (event) {\n case \"PreToolUse\": {\n const ev: PreToolUseEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n };\n return ev;\n }\n case \"PostToolUse\": {\n // PRIMARY SOURCE (docs \"PostToolUse input\"): VS Code PostToolUse fires\n // ONLY after a tool completes SUCCESSFULLY and serializes a single\n // result field, `tool_response`. There is NO `tool_output` and NO\n // `error_message` field in this dialect, so the old `?? input.tool_output\n // ?? input.error_message` fallback legs read host-nonexistent fields and\n // the `error_message`-driven `isError` could never become true. Read only\n // `tool_response`; a tool-failure event (PostToolUseFailure, field\n // `error`) is not part of VS Code's eight-event table and is not wired.\n const toolOutput = toolResponseToString(input.tool_response);\n const ev: PostToolUseEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n ...(toolOutput !== undefined ? { toolOutput } : {}),\n };\n return ev;\n }\n case \"PreCompact\": {\n const ev: PreCompactEvent = {\n ...base,\n ...(input.trigger === \"auto\" || input.trigger === \"manual\"\n ? { trigger: input.trigger }\n : {}),\n };\n return ev;\n }\n case \"PostCompact\": {\n // VS Code Copilot does not fire PostCompact natively (postCompact unset\n // → warn-skip at install). Parsed defensively, mirroring PreCompact, so\n // a manual/mis-routed dispatch normalizes instead of hitting the guard.\n const ev: PostCompactEvent = {\n ...base,\n ...(input.trigger === \"auto\" || input.trigger === \"manual\"\n ? { trigger: input.trigger }\n : {}),\n };\n return ev;\n }\n case \"SessionStart\": {\n const ev: SessionStartEvent = {\n ...base,\n source: normalizeSessionSource(input.source ?? input.trigger),\n };\n return ev;\n }\n case \"SessionEnd\": {\n const ev: SessionEndEvent = {\n ...base,\n ...(typeof input.reason === \"string\" ? { reason: input.reason } : {}),\n };\n return ev;\n }\n case \"UserPromptSubmit\": {\n const ev: UserPromptSubmitEvent = {\n ...base,\n prompt: typeof input.prompt === \"string\" ? input.prompt : \"\",\n };\n return ev;\n }\n case \"Stop\": {\n const ev: StopEvent = {\n ...base,\n ...(typeof input.stop_hook_active === \"boolean\"\n ? { stopHookActive: input.stop_hook_active }\n : {}),\n };\n return ev;\n }\n case \"Notification\": {\n const ev: NotificationEvent = {\n ...base,\n message: typeof input.message === \"string\" ? input.message : \"\",\n };\n return ev;\n }\n case \"SubagentStart\": {\n const ev: SubagentStartEvent = {\n ...base,\n ...(typeof input.agent_id === \"string\" ? { agentId: input.agent_id } : {}),\n ...(typeof input.agent_type === \"string\"\n ? { agentType: input.agent_type }\n : {}),\n };\n return ev;\n }\n case \"SubagentStop\": {\n // PRIMARY SOURCE (docs \"SubagentStop input\"): the payload is EXACTLY\n // { agent_id, agent_type, stop_hook_active }. There is NO\n // `agent_transcript_path` and NO `last_assistant_message` field on this\n // host, so agentTranscriptPath / lastAssistantMessage were always\n // undefined — those reads are removed. (agent_id/agent_type stay optional\n // defensively; a path consumer should fall back to the common\n // `transcript_path`, which is the only transcript VS Code provides.)\n const ev: SubagentStopEvent = {\n ...base,\n ...(typeof input.agent_id === \"string\" ? { agentId: input.agent_id } : {}),\n ...(typeof input.agent_type === \"string\"\n ? { agentType: input.agent_type }\n : {}),\n ...(typeof input.stop_hook_active === \"boolean\"\n ? { stopHookActive: input.stop_hook_active }\n : {}),\n };\n return ev;\n }\n case \"PermissionRequest\":\n case \"PostToolUseFailure\": {\n // No VS Code Copilot analog (its Preview event list has neither a\n // permission-dialog event nor a tool-failure event). Install already\n // skip-warns these; a runtime dispatch is a mis-route — fail loudly.\n throw new Error(`unsupported vscode-copilot hook event: ${String(event)}`);\n }\n default: {\n // Exhaustive guard — every HookEventName is handled above. (VS Code only\n // delivers the events in EVENT_MAP; the rest are handled defensively so\n // a mis-dispatch stays inert rather than crashing.)\n const _never: never = event;\n throw new Error(`unsupported vscode-copilot hook event: ${String(_never)}`);\n }\n }\n }\n\n /**\n * Resolve the project dir from the wire payload. PRIMARY SOURCE (docs \"Common\n * input fields\"): the only working-directory field VS Code sends is `cwd`.\n * There is no `workspace_roots` field, so the old `?? workspace_roots[0]`\n * fallback read a host-nonexistent field and is removed.\n */\n private getProjectDir(input: VSCodeWireInput): string | undefined {\n return typeof input.cwd === \"string\" ? input.cwd : undefined;\n }\n\n // ── Runtime: normalized response → VS Code Copilot native hook reply ──────\n\n formatReply(event: HookEventName, response: HookResponse): HookReply {\n const hookEventName = event;\n const decision = response.decision ?? \"allow\";\n\n // SubagentStart is observe/context-only (the spawn is not blockable):\n // \"context\" injects additionalContext at the start of the SUBAGENT's\n // conversation, and a \"deny\" DEGRADES to the same shape carrying the\n // reason. Everything else passes through.\n if (event === \"SubagentStart\") {\n const context =\n decision === \"context\"\n ? response.additionalContext\n : decision === \"deny\"\n ? response.reason ?? response.additionalContext\n : undefined;\n if (context) {\n return this.stdout({\n hookSpecificOutput: { hookEventName, additionalContext: context },\n });\n }\n return { exitCode: 0 };\n }\n\n // deny → block the action with a reason (exit 0; JSON carries the decision).\n // Per VS Code's Output Contract, `hookSpecificOutput.permissionDecision` is\n // read ONLY for the pre-execution TOOL-permission event (PreToolUse). The\n // post-execution / turn-control events — PostToolUse, Stop, UserPromptSubmit\n // and SubagentStop — block via the TOP-LEVEL {\"decision\":\"block\",\"reason\"}\n // instead: PostToolUse blocks further processing (hooks.md: \"PostToolUse\n // output can block further processing with decision: block\") with `reason` as\n // feedback; Stop/SubagentStop keep the (sub)agent running with `reason` as the\n // next instruction; UserPromptSubmit blocks the prompt with `reason`. The tool\n // already ran by PostToolUse, so there is no permission left to grant — a\n // permissionDecision there is silently ignored (the old behaviour dropped the\n // deny).\n if (decision === \"deny\") {\n if (\n event === \"PostToolUse\" ||\n event === \"SubagentStop\" ||\n event === \"Stop\" ||\n event === \"UserPromptSubmit\"\n ) {\n return this.stdout({\n decision: \"block\",\n reason: response.reason ?? \"Blocked by hook\",\n });\n }\n return this.stdout({\n hookSpecificOutput: {\n hookEventName,\n permissionDecision: \"deny\",\n permissionDecisionReason: response.reason ?? \"Blocked by hook\",\n },\n });\n }\n\n // ask → prompt the user to confirm.\n if (decision === \"ask\") {\n return this.stdout({\n hookSpecificOutput: {\n hookEventName,\n permissionDecision: \"ask\",\n permissionDecisionReason:\n response.reason ?? \"Confirmation required by hook\",\n },\n });\n }\n\n // modify → rewrite PreToolUse input (only where VS Code supports it).\n if (decision === \"modify\") {\n if (event === \"PreToolUse\" && response.updatedInput) {\n return this.stdout({\n hookSpecificOutput: { hookEventName, updatedInput: response.updatedInput },\n });\n }\n // Output rewrite is unsupported on VS Code; fall through to allow.\n }\n\n // context → inject soft guidance (also the SessionStart context path).\n if (decision === \"context\" && response.additionalContext) {\n return this.stdout({\n hookSpecificOutput: { hookEventName, additionalContext: response.additionalContext },\n });\n }\n\n // allow / void / unsupported-degradation → pass through with exit 0.\n return { exitCode: 0 };\n }\n\n private stdout(payload: unknown): HookReply {\n return { exitCode: 0, stdout: JSON.stringify(payload) };\n }\n}\n\n/**\n * VS Code native interpolation token: `${env:VAR}` → `${env:VAR}` (passthrough).\n * VS Code also supports `${input:VAR}` (prompted/secret inputs declared in the\n * sibling `inputs` array); we keep portable `${env:VAR}` refs as the native env\n * token so secrets are never baked into the committed config.\n */\nfunction vscodeEnvToken(name: string): string {\n return `\\${env:${name}}`;\n}\n\n/**\n * Extract a stable session id from a VS Code Copilot wire payload. Priority\n * mirrors the Claude-compatible wire: transcript UUID > session_id > \"\" (the\n * framework uses \"\" when no id is available — no ppid fabrication here).\n */\nfunction extractSessionId(input: VSCodeWireInput): string {\n if (typeof input.transcript_path === \"string\") {\n const m = input.transcript_path.match(/([a-f0-9-]{36})\\.jsonl$/);\n if (m && m[1]) return m[1];\n }\n if (typeof input.session_id === \"string\" && input.session_id !== \"\") {\n return input.session_id;\n }\n return \"\";\n}\n\n/** Coerce a Claude-compatible PostToolUse `tool_response` into a string. */\nfunction toolResponseToString(value: unknown): string | undefined {\n if (value == null) return undefined;\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nexport const adapter = new VSCodeCopilotAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  resolveEnvRefsDeep
4
- } from "./chunk-DBQMX75U.js";
4
+ } from "./chunk-BEFVJ2OE.js";
5
5
  import {
6
6
  BaseAdapter,
7
7
  renderSkillMd
8
- } from "./chunk-RHML2NOB.js";
8
+ } from "./chunk-NUGMVVV2.js";
9
9
  import {
10
10
  buildWrappedStdio,
11
11
  isHomeBinHookCommand
@@ -339,4 +339,4 @@ export {
339
339
  adapter,
340
340
  warp_default as default
341
341
  };
342
- //# sourceMappingURL=warp-7CC52UJV.js.map
342
+ //# sourceMappingURL=warp-B72XSQ5G.js.map
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  resolveEnvRefsDeep
4
- } from "./chunk-DBQMX75U.js";
4
+ } from "./chunk-BEFVJ2OE.js";
5
5
  import {
6
6
  BaseAdapter,
7
7
  renderCommandMd,
8
8
  renderSkillMd
9
- } from "./chunk-RHML2NOB.js";
9
+ } from "./chunk-NUGMVVV2.js";
10
10
  import {
11
11
  buildWrappedStdio
12
12
  } from "./chunk-TO57WYBB.js";
@@ -426,4 +426,4 @@ export {
426
426
  adapter,
427
427
  windsurf_default as default
428
428
  };
429
- //# sourceMappingURL=windsurf-6ZLQMBQW.js.map
429
+ //# sourceMappingURL=windsurf-642VBMQ2.js.map
@@ -4,11 +4,11 @@ import {
4
4
  } from "./chunk-UM5S7DKK.js";
5
5
  import {
6
6
  resolveEnvRefsDeep
7
- } from "./chunk-DBQMX75U.js";
7
+ } from "./chunk-BEFVJ2OE.js";
8
8
  import {
9
9
  BaseAdapter,
10
10
  renderSkillMd
11
- } from "./chunk-RHML2NOB.js";
11
+ } from "./chunk-NUGMVVV2.js";
12
12
  import {
13
13
  buildWrappedStdio
14
14
  } from "./chunk-TO57WYBB.js";
@@ -309,4 +309,4 @@ export {
309
309
  adapter,
310
310
  zed_default as default
311
311
  };
312
- //# sourceMappingURL=zed-FULJMNBV.js.map
312
+ //# sourceMappingURL=zed-6UJS7JKB.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ken-jo/agent-connector",
3
- "version": "0.4.67",
3
+ "version": "0.4.75",
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/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 { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { 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 // ToolResultEvent.output is typed `unknown` by the host (@ampcode/plugin\n // index.d.ts:947 — \"Tool output/result if available\"), so the bridge may\n // forward a string OR a structured value; parseEvent stringifies non-strings.\n toolOutput?: unknown;\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 changes.push(\n this.writeManagedFile(\n file.path,\n file.contents,\n ctx.dryRun,\n `amp plugin module (${this.hookDetail(ctx)})`,\n file.executable,\n ),\n );\n }\n\n return changes;\n }\n\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n const pluginPath = this.getHookConfigPath(ctx);\n return [\n this.removeManagedFile(pluginPath, ctx.dryRun, \"amp plugin module\", \"no amp plugin module present\"),\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 host DOES carry the prompt: AgentStartEvent.message\n // is \"The user's prompt message\" (@ampcode/plugin index.d.ts:1011-1012), so we\n // PROJECT event.message into the bridge payload's prompt key (the prior version\n // dropped it). Observe-only return surface — any deny/context decision is a no-op.\n amp.on(\"agent.start\", async (event) => {\n bridge(\"UserPromptSubmit\", {\n prompt: (event && typeof event.message === \"string\" && event.message) || \"\",\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 host DOES\n // carry the output: ToolResultEvent extends ToolResult.output (typed unknown —\n // \"Tool output/result if available\", @ampcode/plugin index.d.ts:946-947,976), so\n // we PROJECT event.output into the bridge payload's toolOutput (prior version\n // dropped it). Replacement still observe-only (canModifyOutput:false) — the\n // replacement OBJECT shape is undocumented, so we never return a guessed mutation.\n amp.on(\"tool.result\", async (event) => {\n bridge(\"PostToolUse\", {\n toolName: (event && event.tool) || \"\",\n toolOutput: event && event.output,\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 // ToolResultEvent.output is typed `unknown` by the host (@ampcode/plugin\n // index.d.ts:947), so the bridge can forward a string OR a structured value.\n // Accept both: pass strings through, JSON-stringify other non-nullish\n // values (the old `typeof === \"string\"` guard silently dropped the latter).\n const out = coerceToolOutput(input.toolOutput);\n const ev: PostToolUseEvent = {\n ...base,\n toolName: input.toolName ?? \"\",\n toolInput: input.toolInput ?? {},\n ...(out !== undefined ? { toolOutput: out } : {}),\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}\n\n/**\n * Coerce Amp's `ToolResultEvent.output` (typed `unknown` upstream) into the\n * normalized event's `toolOutput: string`. Strings pass through; other\n * non-nullish values (objects / arrays / numbers) are JSON-stringified so a\n * structured tool result is no longer silently dropped. `undefined`/`null`\n * yields `undefined` (the key is omitted by the caller).\n */\nfunction coerceToolOutput(value: unknown): string | undefined {\n if (typeof value === \"string\") return value;\n if (value === undefined || value === null) return undefined;\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\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/core/interpolate.ts"],"sourcesContent":["/**\n * core/interpolate — universal ${env:VAR} interpolation.\n *\n * The developer writes one portable syntax in their connector config:\n * \"${env:ACME_KEY}\" → value of process.env.ACME_KEY\n * \"${env:ACME_URL:-https://x}\" → value, or the default after \":-\" if unset/empty\n *\n * Two consumers:\n * • resolveEnvRefs / resolveEnvRefsDeep — resolve to literals at INSTALL time,\n * for hosts with NO native interpolation (e.g. Codex TOML).\n * • rewriteEnvRefs — translate to a host's NATIVE interpolation token (e.g.\n * Cursor/VS Code \"${env:VAR}\", Claude \"${VAR}\") so secrets are never baked\n * into config files. Adapters choose which to use.\n */\n\n/** Matches ${env:NAME} and ${env:NAME:-default}. NAME is [A-Za-z_][A-Za-z0-9_]*. */\nexport const ENV_REF_RE = /\\$\\{env:([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*))?\\}/g;\n\n/** Resolve every ${env:VAR} in `input` to a literal from `env`. */\nexport function resolveEnvRefs(\n input: string,\n env: NodeJS.ProcessEnv = process.env,\n): string {\n return input.replace(ENV_REF_RE, (_m, name: string, def?: string) => {\n const v = env[name];\n if (v != null && v !== \"\") return v;\n return def ?? \"\";\n });\n}\n\n/** Recursively resolve ${env:VAR} in all strings of a JSON-ish value. */\nexport function resolveEnvRefsDeep<T>(value: T, env: NodeJS.ProcessEnv = process.env): T {\n if (typeof value === \"string\") return resolveEnvRefs(value, env) as unknown as T;\n if (Array.isArray(value)) {\n return value.map((v) => resolveEnvRefsDeep(v, env)) as unknown as T;\n }\n if (value && typeof value === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value)) out[k] = resolveEnvRefsDeep(v, env);\n return out as T;\n }\n return value;\n}\n\n/**\n * Translate every ${env:VAR(:-default)} via `render` into a host-native token.\n * The renderer receives the var name and optional default and returns the\n * replacement string (e.g. `(name) => \"${\" + name + \"}\"` for Claude).\n */\nexport function rewriteEnvRefs(\n input: string,\n render: (name: string, def?: string) => string,\n): string {\n return input.replace(ENV_REF_RE, (_m, name: string, def?: string) =>\n render(name, def),\n );\n}\n\n/** True if the string contains at least one ${env:...} reference. */\nexport function hasEnvRef(input: string): boolean {\n ENV_REF_RE.lastIndex = 0;\n return ENV_REF_RE.test(input);\n}\n"],"mappings":";;;AAgBO,IAAM,aAAa;AAGnB,SAAS,eACd,OACA,MAAyB,QAAQ,KACzB;AACR,SAAO,MAAM,QAAQ,YAAY,CAAC,IAAI,MAAc,QAAiB;AACnE,UAAM,IAAI,IAAI,IAAI;AAClB,QAAI,KAAK,QAAQ,MAAM,GAAI,QAAO;AAClC,WAAO,OAAO;AAAA,EAChB,CAAC;AACH;AAGO,SAAS,mBAAsB,OAAU,MAAyB,QAAQ,KAAQ;AACvF,MAAI,OAAO,UAAU,SAAU,QAAO,eAAe,OAAO,GAAG;AAC/D,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,IAAI,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAAA,EACpD;AACA,MAAI,SAAS,OAAO,UAAU,UAAU;AACtC,UAAM,MAA+B,CAAC;AACtC,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,KAAK,EAAG,KAAI,CAAC,IAAI,mBAAmB,GAAG,GAAG;AAC9E,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAOO,SAAS,eACd,OACA,QACQ;AACR,SAAO,MAAM;AAAA,IAAQ;AAAA,IAAY,CAAC,IAAI,MAAc,QAClD,OAAO,MAAM,GAAG;AAAA,EAClB;AACF;","names":[]}