@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
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/codex/index.ts"],"sourcesContent":["/**\n * adapters/codex — Codex CLI platform adapter for agent-connector.\n *\n * Codex CLI hook paradigm is \"json-stdio\": the host pipes a JSON payload to a\n * command on stdin and reads JSON/exit-code back — the same wire protocol as\n * Claude Code (PascalCase fields, `hookSpecificOutput` reply wrapper).\n *\n * Two native config files live under the Codex config dir\n * (`$CODEX_HOME` || `~/.codex`, mirrored to `<projectDir>/.codex` for project\n * scope):\n * - config.toml → `[mcp_servers.<id>]` MCP registration (TOML, NO native\n * interpolation, so env-refs are resolved to literals at install time).\n * - hooks.json → Claude-compatible hook registration ({ matcher, hooks }).\n *\n * Grounded in context-mode's proven Codex adapter (configs/codex/{config.toml,\n * hooks.json}, src/adapters/codex/*) — exact TOML MCP shape + hook JSON schema.\n *\n * Codex capabilities (upstream, verified against openai/codex source at the\n * stable release tags noted):\n * - PreToolUse `updatedInput` rewrite IS honored (PR #20527, commit d08906a9,\n * stable since codex 0.131.0; applied in the shell/mcp/apply_patch tool\n * handlers, confirmed present through 0.141.0) — hence canModifyArgs is now\n * TRUE. Codex's output_parser.rs requires the rewrite to be paired with\n * `permissionDecision:\"allow\"` (an allow WITHOUT updatedInput, and an\n * updatedInput WITHOUT allow, are both rejected as invalid), so \"modify\"\n * emits the allow+updatedInput envelope together. The still-open tracking\n * issue openai/codex#18491 is now scoped to a NARROWER gap — read_file/grep\n * have no PreToolUse handler yet — not to updatedInput itself, which works\n * for every tool that fires PreToolUse (shell/Bash, apply_patch, MCP).\n * - PostToolUse `updatedMCPToolOutput` is still explicitly rejected as\n * \"unsupported\" by output_parser.rs (no output-rewrite field on\n * PostToolUseOutput at 0.141.0) — hence canModifyOutput stays FALSE.\n *\n * E1 extension events (verified against developers.openai.com/codex/hooks):\n * - PermissionRequest — native, decision-capable via the nested\n * hookSpecificOutput.decision{behavior:\"allow\"|\"deny\", message?} envelope.\n * Codex docs: updatedInput / updatedPermissions / interrupt FAIL CLOSED on\n * this event, so they are never emitted here.\n * - SubagentStart — native; hookSpecificOutput.additionalContext is injected\n * as developer context for the subagent (not blockable).\n * - SubagentStop — native; the documented continuation shape is the TOP-LEVEL\n * {\"decision\":\"block\",\"reason\"} (Stop semantics: keeps the subagent going).\n * - PostToolUseFailure — NO Codex analog (PostToolUse only); declared hooks\n * for it warn-skip at install and the capability flag stays unset.\n * - PostCompact — native (Codex's hook system fires both PreCompact and\n * PostCompact); observe-only, normalizing the `trigger` (manual|auto)\n * exactly like PreCompact, with a passthrough formatReply.\n */\n\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport TOML from \"@iarna/toml\";\n\nimport type {\n ChangeRecord,\n DetectedPlatform,\n HealthCheck,\n HookEventName,\n HookParadigm,\n HookResponse,\n PlatformCapabilities,\n PlatformId,\n ServerDef,\n SkillDef,\n SubagentDef,\n} from \"../../core/types.js\";\nimport { ensureDir } from \"../../core/paths.js\";\nimport { codexConfigHome } from \"../../core/host-paths.js\";\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\nimport {\n removeFromObjectMap,\n upsertInObjectMap,\n type ObjectMapCodec,\n} from \"../../core/object-map.js\";\nimport { writeTomlString } from \"../../core/toml.js\";\nimport {\n buildHomeBinHookCommand,\n buildWrappedStdio,\n} from \"../../core/spawn.js\";\nimport { renderCommandMd, renderSkillMd } from \"../claude-code/render.js\";\nimport { normalizeSessionSource } from \"../claude-code/wire.js\";\nimport { BaseAdapter, type HookMergeDescriptor } from \"../base.js\";\nimport type {\n HookReply,\n InstallContext,\n MemoryTarget,\n NormalizedEvent,\n} from \"../spi.js\";\n\n// ─────────────────────────────────────────────────────────────────────────\n// Native shapes\n// ─────────────────────────────────────────────────────────────────────────\n\n/** Raw Codex hook payload (PascalCase event, snake_case fields — Claude-style). */\ninterface CodexHookInput {\n tool_name?: string;\n tool_input?: Record<string, unknown>;\n // PostToolUse only. The host serializes this as serde_json::Value (any JSON):\n // a BARE STRING for shell/apply_patch (e.g. json!(\"shell output\")) but an\n // OBJECT for MCP/structured tools (the serialized CallToolResult, e.g.\n // json!({content,structuredContent,isError})) — NOT always a string. Typed\n // `unknown` so PostToolUse coerces it for the string-typed toolOutput.\n // Primary source: openai/codex codex-rs/hooks/src/schema.rs PostToolUseCommandInput\n // `tool_response: Value` + core/src/tools/handlers/{mcp.rs object, shell_tests.rs string}.\n tool_response?: unknown;\n session_id?: string;\n cwd?: string;\n hook_event_name?: string;\n source?: string;\n prompt?: string;\n // NO is_error: Codex's PostToolUseCommandInput struct (#[serde(deny_unknown_fields)])\n // never serializes a top-level is_error — the error signal for MCP tools lives\n // INSIDE tool_response as the CallToolResult `isError`. The field was removed;\n // see derivePostToolUseIsError below. (openai/codex codex-rs/hooks/src/schema.rs:317-337)\n stop_hook_active?: boolean;\n trigger?: string;\n message?: string;\n // PostToolUseFailure-style failure field. Codex has NO failure event today;\n // parsed defensively only (the Claude-compatible wire would carry it).\n error?: string;\n // SubagentStart / SubagentStop (agent_type is the matcher subject).\n agent_id?: string;\n agent_type?: string;\n // SubagentStop only — the subagent's own transcript + final message.\n agent_transcript_path?: string;\n last_assistant_message?: string;\n}\n\n/** One hook entry inside hooks.json (Claude-compatible). */\ninterface CodexHookEntry {\n matcher?: string;\n hooks: Array<{ type: \"command\"; command: string }>;\n}\n\n/** Rendered `[mcp_servers.<id>]` table — string env table, no interpolation. */\ninterface CodexMcpEntry {\n // stdio transport\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n // streamable HTTP transport (remote): codex infers the transport from `url`\n // (no explicit transport key). Verified against codex-cli 0.139.0.\n url?: string;\n bearer_token_env_var?: string;\n http_headers?: Record<string, string>;\n}\n\n/**\n * Codex hook events agent-connector registers, in the canonical → native order.\n * Codex uses the same PascalCase event names as Claude Code; the home-binary\n * hook command receives the lowercased event token.\n */\nconst CODEX_HOOK_EVENTS = [\n \"SessionStart\",\n \"PreToolUse\",\n \"PostToolUse\",\n \"PreCompact\",\n \"UserPromptSubmit\",\n \"Stop\",\n \"PermissionRequest\",\n \"SubagentStart\",\n \"SubagentStop\",\n \"PostCompact\",\n] as const;\n\ntype CodexHookEventName = (typeof CODEX_HOOK_EVENTS)[number];\n\n/**\n * Newer E1 canonical events with NO Codex analog: Codex ships PostToolUse only —\n * there is no failure event on the live hooks page. Declared hooks for these\n * warn-skip (action `warn`, exit-1) — the established convention. The legacy\n * SessionEnd / Notification, which Codex also cannot fire, are reported as a\n * VISIBLE `skip` instead (exit-0 preserving) — see the hook descriptor's\n * `unmappedAction`. Nothing Codex cannot fire is ever silently dropped.\n */\nconst WARN_SKIP_EVENTS: ReadonlySet<HookEventName> = new Set([\"PostToolUseFailure\"]);\n\n/**\n * PreToolUse matcher — canonical Codex tool names + bare MCP tool names +\n * external MCP catch-all literal. Charset-clean ([A-Za-z0-9_|] only) so Codex's\n * Rust `regex` exact-matcher short-circuits (no look-around, which Codex\n * rejects at boot). Copied from context-mode's proven matcher.\n */\nconst PRE_TOOL_USE_MATCHER =\n \"local_shell|shell|shell_command|exec_command|Bash|Shell|apply_patch|Edit|Write|grep_files|mcp__\";\n\n/**\n * Coerce Codex's PostToolUse `tool_response` (serde_json::Value — bare string\n * for shell/apply_patch, OBJECT for MCP/structured tools) to a string for the\n * string-typed `toolOutput`. A string passes through verbatim; everything else\n * (object/array/number/bool) is JSON-stringified; undefined/null → undefined\n * (leave `toolOutput` unset).\n *\n * Source: openai/codex codex-rs/hooks/src/schema.rs PostToolUseCommandInput\n * `tool_response: Value`; core/src/tools/handlers/shell_tests.rs emits\n * `json!(\"shell output\")` (string), mcp.rs emits `json!({...})` (object).\n */\nfunction coerceToolResponse(value: unknown): string | undefined {\n if (value === undefined || 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\n/**\n * Derive PostToolUse `isError`. Codex's PostToolUseCommandInput\n * (`#[serde(deny_unknown_fields)]`) has NO top-level is_error field, so the only\n * machine-readable error signal is the MCP CallToolResult `isError` nested in\n * the `tool_response` object (serialized camelCase by rmcp). For shell/\n * apply_patch tool_response is a bare string carrying no boolean, so we report\n * false. Returns false when no such signal exists (never invents one).\n *\n * Source: openai/codex codex-rs/hooks/src/schema.rs:317-337 (no is_error field);\n * codex-rs/core/src/tools/handlers/mcp.rs (tool_response = serialized\n * CallToolResult → `isError` when the MCP call failed).\n */\nfunction derivePostToolUseIsError(toolResponse: unknown): boolean {\n if (toolResponse !== null && typeof toolResponse === \"object\") {\n const flag = (toolResponse as Record<string, unknown>).isError;\n if (typeof flag === \"boolean\") return flag;\n }\n return false;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Adapter\n// ─────────────────────────────────────────────────────────────────────────\n\nexport class CodexAdapter extends BaseAdapter {\n readonly id: PlatformId = \"codex\";\n readonly name = \"Codex CLI\";\n readonly paradigm: HookParadigm = \"json-stdio\";\n\n readonly capabilities: PlatformCapabilities = {\n // Memory surface: AGENTS.md-first managed block. memoryTargets below probes\n // AGENTS.override.md first (it shadows AGENTS.md per directory on codex).\n supportsMemory: true,\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 // E1 events: PermissionRequest (decision-capable) + SubagentStart/Stop are\n // Codex-native. postToolUseFailure stays unset — Codex has no failure event,\n // so a declared hook for it warn-skips at install.\n permissionRequest: true,\n subagentStart: true,\n subagentStop: true,\n // PostCompact: Codex's hook system fires both PreCompact and PostCompact\n // (developers.openai.com/codex/hooks). Observational only — the reply\n // contract mirrors PreCompact (cannot block/modify a completed compaction).\n postCompact: true,\n // PreToolUse updatedInput rewrite is honored upstream (paired with\n // permissionDecision:\"allow\"); PostToolUse output rewrite is not (see header).\n canModifyArgs: true,\n canModifyOutput: false,\n canInjectSessionContext: true,\n transports: [\"stdio\", \"http\"],\n // Content surfaces: Codex implements all three.\n // command → ~/.codex/prompts/<name>.md (md+frontmatter, USER SCOPE ONLY)\n // skill → project: .codex/skills/<name>/SKILL.md · user: ~/.agents/skills/<name>/SKILL.md\n // subagent → <codexDir>/agents/<name>.toml (TOML)\n supportsCommands: true,\n supportsSkills: true,\n supportsSubagents: true,\n };\n\n // ── Detection ──────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userDir = this.userConfigDir();\n const projDir = join(projectDir, \".codex\");\n const userCfg = join(userDir, \"config.toml\");\n const projCfg = join(projDir, \"config.toml\");\n\n const userInstalled = existsSync(userDir) || existsSync(userCfg);\n const projInstalled = existsSync(projDir) || existsSync(projCfg);\n const installed = userInstalled || projInstalled;\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\n const configPath = scope === \"project\" ? projCfg : userCfg;\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 Codex config dir (${scope})`\n : `No .codex config dir at ${userDir} or ${projDir}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Native paths ───────────────────────────────────────────────────────\n\n override getConfigDir(ctx: InstallContext): string {\n if (ctx.scope === \"project\") return join(ctx.projectDir, \".codex\");\n return this.userConfigDir();\n }\n\n override getServerConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"config.toml\");\n }\n\n override getHookConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"hooks.json\");\n }\n\n // ── Memory surface: AGENTS.override.md probe + 32 KiB doc-cap budget ─────\n // Codex reads AGENTS.override.md > AGENTS.md per directory (one file per\n // directory), so when the override file exists OUR block must live there or\n // it is never loaded. Combined project docs are capped at 32 KiB\n // (`project_doc_max_bytes`), hence the ~28 KiB per-file budget warn.\n protected override memoryTargets(ctx: InstallContext): MemoryTarget[] {\n // An explicit path override keeps the base resolution (escape hatch wins).\n if (this.memoryOverride(ctx)?.path) return super.memoryTargets(ctx);\n if (ctx.scope !== \"project\" && ctx.scope !== \"user\") return [];\n const budgetBytes = 28 * 1024;\n const dir = ctx.scope === \"project\" ? ctx.projectDir : this.userConfigDir();\n const overrideMd = join(dir, \"AGENTS.override.md\");\n if (existsSync(overrideMd)) {\n return [\n {\n path: overrideMd,\n reason: \"AGENTS.override.md shadows AGENTS.md on codex (one doc per directory)\",\n budgetBytes,\n },\n ];\n }\n return [\n {\n path: join(dir, \"AGENTS.md\"),\n reason:\n ctx.scope === \"project\"\n ? \"AGENTS.md standard (project root; codex is the format's originator)\"\n : \"codex global guidance ($CODEX_HOME/AGENTS.md)\",\n budgetBytes,\n },\n ];\n }\n\n /** `$CODEX_HOME` (tilde-expanded, then resolved) || `~/.codex` for user\n * scope. Shared with marketplace detection via `codexConfigHome` so the\n * config writer and the install probe never target different dirs. */\n private userConfigDir(): string {\n return codexConfigHome();\n }\n\n // ── TOML config IO (override JSON helpers — config.toml is TOML) ─────────\n\n private readToml(path: string): Record<string, unknown> {\n if (!existsSync(path)) return {};\n try {\n return TOML.parse(readFileSync(path, \"utf8\")) as Record<string, unknown>;\n } catch {\n return {};\n }\n }\n\n private writeToml(path: string, data: Record<string, unknown>, dryRun: boolean): void {\n if (dryRun) return;\n ensureDir(dirname(path));\n // @iarna/toml's stringify type wants its JsonMap; our object is structurally compatible.\n writeFileSync(path, TOML.stringify(data as never), \"utf8\");\n }\n\n /** An ObjectMapCodec over config.toml for the core/object-map engine.\n * `isPresentButUnparseable` is `() => false`: readToml fail-softs to {} and the\n * server path has historically coerced/overwritten rather than warn-skip on an\n * unparseable file — preserved here for byte-identical behavior. */\n private tomlObjectMapCodec(): ObjectMapCodec {\n return {\n parse: (path) => this.readToml(path),\n serialize: (path, data, dryRun) => this.writeToml(path, data, dryRun),\n isPresentButUnparseable: () => false,\n };\n }\n\n // ── Install server (config.toml → [mcp_servers.<id>]) ───────────────────\n\n override installServer(ctx: InstallContext): ChangeRecord[] {\n const { connector, dryRun } = ctx;\n const server = this.effectiveServer(ctx);\n const path = this.getServerConfigPath(ctx);\n\n if (!server) {\n return [{ platform: this.id, action: \"skip\", path, detail: \"no server declared\" }];\n }\n const isStdio = server.transport === \"stdio\" && !!server.command;\n const isHttp = server.transport === \"http\" && !!server.url;\n if (!isStdio && !isHttp) {\n // Codex config.toml [mcp_servers] supports stdio (command) + streamable\n // HTTP (url). Other remote transports (sse/ws) have no codex analog.\n return [\n {\n platform: this.id,\n action: \"skip\",\n path,\n detail: `transport \"${server.transport}\" not registrable in config.toml (stdio + streamable-http only)`,\n },\n ];\n }\n\n const symlink = this.symlinkPathWarning(path);\n if (symlink) return [symlink];\n\n const entry = this.renderMcpEntry(ctx, server);\n\n return [\n upsertInObjectMap({\n codec: this.tomlObjectMapCodec(),\n rootKey: \"mcp_servers\",\n policy: \"coerce\",\n platform: this.id,\n configPath: path,\n entryId: connector.id,\n entry,\n dryRun,\n }),\n ];\n }\n\n override uninstallServer(ctx: InstallContext): ChangeRecord[] {\n const { connector, dryRun } = ctx;\n const path = this.getServerConfigPath(ctx);\n const symlink = this.symlinkPathWarning(path);\n if (symlink) return [symlink];\n\n return [\n removeFromObjectMap({\n codec: this.tomlObjectMapCodec(),\n rootKey: \"mcp_servers\",\n policy: \"coerce\",\n platform: this.id,\n configPath: path,\n entryId: connector.id,\n dryRun,\n }),\n ];\n }\n\n // ── Install hooks (hooks.json) ──────────────────────────────────────────\n\n override installHooks(ctx: InstallContext): ChangeRecord[] {\n const path = this.getHookConfigPath(ctx);\n const hooksOff = ctx.connector.platforms[this.id]?.hooks === false;\n const declared = hooksOff ? [] : ctx.connector.hookEvents;\n\n if (declared.length === 0) {\n return [{ platform: this.id, action: \"skip\", path, detail: \"no hooks declared\" }];\n }\n\n // HOST-ORDERED pending: the unsupported events (mapEvent → undefined →\n // warn/skip via the descriptor) FIRST, then the supported events in\n // CODEX_HOOK_EVENTS order. EVERY declared event is enqueued — an event with\n // no Codex analog is reported VISIBLY (warn for the E1 newer events, a `skip`\n // for the legacy SessionEnd/Notification whose drop predates the convention),\n // never silently dropped. matcher is \"\" for every item; renderEntry derives\n // the real matcher from the event (PreToolUse/PermissionRequest).\n const supported = (e: HookEventName) =>\n (CODEX_HOOK_EVENTS as readonly string[]).includes(e);\n const pending = [\n ...declared.filter((e) => !supported(e)).map((event) => ({ event: event as string, matcher: \"\" })),\n ...declared.filter(supported).map((event) => ({ event: event as string, matcher: \"\" })),\n ];\n return this.upsertHookEntries(ctx, path, pending, this.hookDescriptor(ctx));\n }\n\n override uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n return this.removeHookEntries(ctx, this.getHookConfigPath(ctx), this.hookDescriptor(ctx));\n }\n\n /**\n * Codex hook-merge policy for the shared object-map engine. EVENT-SPECIFIC by\n * construction: every observable (coerce root + bucket, the path-normalized\n * per-event ownership find, the event-derived matcher with `hooks`-then-\n * `matcher` key order, the BARE `hooks.<event>` skip/remove details with NO\n * count, the warn wording, and the absent/no-match skips) is carried here so\n * the engine reproduces the prior in-adapter loop byte-for-byte.\n */\n private hookDescriptor(_ctx: InstallContext): HookMergeDescriptor<CodexHookEntry> {\n return {\n // Codex's server path coerces a malformed root; the hook path matches it.\n malformedPolicy: \"coerce\",\n // Supported event → identity; any other canonical event → undefined → the\n // engine reports it (never silent), at the severity unmappedAction picks.\n mapEvent: (e) =>\n (CODEX_HOOK_EVENTS as readonly string[]).includes(e) ? e : undefined,\n unmappedWarnDetail: (e) => `${e} has no Codex hook equivalent — skipped`,\n // E1 newer events (PostToolUseFailure) keep the established `warn` (exit-1);\n // the legacy SessionEnd / Notification — silently dropped before this fix —\n // become a VISIBLE `skip` so the install exit code is unchanged for them.\n unmappedAction: (e) =>\n WARN_SKIP_EVENTS.has(e as HookEventName) ? \"warn\" : \"skip\",\n renderEntry: (event, _matcher, command) => {\n const entry: CodexHookEntry = { hooks: [{ type: \"command\", command }] };\n // KEY ORDER: hooks THEN matcher. Matcher is EVENT-derived, not from the\n // connector's declared matcher: PermissionRequest matches tool names like\n // PreToolUse (charset-clean), everything else registers \"\" (all).\n entry.matcher =\n event === \"PreToolUse\" || event === \"PermissionRequest\" ? PRE_TOOL_USE_MATCHER : \"\";\n return entry;\n },\n // Idempotency find for the CANONICAL event the engine built `command` from —\n // path-normalized, exact-command, the body of isOurEntry's command check.\n entryOwnsCommand: (entry, command) =>\n Array.isArray(entry.hooks) &&\n entry.hooks.some(\n (h) => (h.command ?? \"\").replace(/\\\\/g, \"/\") === command.replace(/\\\\/g, \"/\"),\n ),\n // FLAT whole-entry removal, EVENT-SPECIFIC: isOurEntry rebuilds our command\n // from the event key being stripped, so a SubagentStop entry is never matched\n // while iterating the PreToolUse bucket.\n ownsEntryForRemove: (c, event) => (entry) =>\n this.isOurEntry(c, event as CodexHookEventName, entry),\n skipDetail: (e) => `hooks.${e}`,\n removeDetail: (e, _n) => `hooks.${e}`,\n absentDetail: \"no hooks.json\",\n noMatchDetail: \"no agent-connector hooks present\",\n // Uninstall scans EXACTLY codex's fixed event set (not Object.keys), so a\n // home-bin command hand-placed under a foreign event key is left untouched —\n // byte-identical to the prior `for (const event of CODEX_HOOK_EVENTS)` loop.\n removeEventKeys: CODEX_HOOK_EVENTS,\n };\n }\n\n // ── Health checks (default doctor renders these) ────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const path = this.getServerConfigPath(ctx);\n const id = ctx.connector.id;\n const checks: HealthCheck[] = [\n {\n name: `${this.name}: config.toml exists`,\n check: () =>\n existsSync(path)\n ? { status: \"OK\", detail: path }\n : { status: \"FAIL\", detail: `not found: ${path}` },\n },\n {\n name: `${this.name}: mcp_servers.${id} registered`,\n check: () => {\n // Only assert what the connector declares (same rule as the\n // content-surface checks below): a server-less connector — e.g. a\n // catalog-only bundle of agents/skills/commands — never writes an\n // [mcp_servers.<id>] table, so its absence is healthy.\n if (!ctx.connector.server) {\n return { status: \"OK\", detail: \"no MCP server declared\" };\n }\n const cfg = this.readToml(path);\n const bucket = cfg[\"mcp_servers\"];\n const present =\n typeof bucket === \"object\" &&\n bucket !== null &&\n id in (bucket as Record<string, unknown>);\n return present\n ? { status: \"OK\", detail: `mcp_servers.${id}` }\n : { status: \"FAIL\", detail: `mcp_servers.${id} not found in ${path}` };\n },\n },\n ];\n\n // Content-surface checks: assert presence only for surfaces this connector\n // declares. Codex commands are user-scope only, so a project-scope install\n // won't have written them — only check command files in user scope.\n if (ctx.scope !== \"project\") {\n for (const cmd of ctx.connector.commands) {\n const p = this.commandPath(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 }\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 // ── Content surfaces: commands / skills / subagents ──────────────────────\n // CONTENT-ONLY: pure native-file writers. No runtime dispatch, no home-bin\n // pointer, no telemetry wrap. Each method is idempotent (byte-identical →\n // skip) via writeContentFile and reversible via removeContentFile. Honors\n // platforms[\"codex\"] per-surface false to skip.\n //\n // Native locations:\n // command → ~/.codex/prompts/<name>.md md+frontmatter(description,argument-hint)\n // USER SCOPE ONLY — project scope yields a single \"warn\".\n // skill → project: <projectDir>/.codex/skills/<name>/SKILL.md (+ resources)\n // user: ~/.agents/skills/<name>/SKILL.md (~/.codex/skills is deprecated)\n // subagent → <codexDir>/agents/<name>.toml TOML via writeTomlString\n\n /** Command files always live under the USER codex dir: ~/.codex/prompts. */\n private commandPath(name: string): string {\n return join(this.userConfigDir(), \"prompts\", `${name}.md`);\n }\n private skillDir(ctx: InstallContext, name: string): string {\n // Project scope: <projectDir>/.codex/skills/<name> — the Project config-layer\n // skills root (codex-rs/core-skills/src/loader.rs, ConfigLayerSource::Project),\n // NOT deprecated. User scope: $HOME/.agents/skills/<name> — codex's CURRENT\n // user skills root. The older $CODEX_HOME/skills (~/.codex/skills) is still\n // read but the loader labels it a \"Deprecated user skills location, kept for\n // backward compatibility\". .agents is anchored to the OS home (home_dir), NOT\n // $CODEX_HOME — so use homedir() here, never userConfigDir() (which honors\n // CODEX_HOME).\n if (ctx.scope === \"project\") return join(this.getConfigDir(ctx), \"skills\", name);\n return join(homedir(), \".agents\", \"skills\", name);\n }\n private subagentPath(ctx: InstallContext, name: string): string {\n return join(this.getConfigDir(ctx), \"agents\", `${name}.toml`);\n }\n\n // ── Commands (USER SCOPE ONLY) ───────────────────────────────────────────\n\n override installCommands(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[this.id]?.commands === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"commands disabled for codex\" }];\n }\n if (ctx.scope === \"project\") {\n return [{ platform: this.id, action: \"warn\", detail: \"codex commands are user-scope only\" }];\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(cmd.name),\n renderCommandMd(cmd, { includeToolsAndModel: false }),\n ctx.dryRun,\n ),\n );\n }\n\n override uninstallCommands(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (ctx.scope === \"project\") {\n return [{ platform: this.id, action: \"warn\", detail: \"codex commands are user-scope only\" }];\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.removeContentFile(this.commandPath(cmd.name), ctx.dryRun),\n );\n }\n\n // ── Skills ───────────────────────────────────────────────────────────────\n\n override installSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[this.id]?.skills === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"skills disabled for codex\" }];\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 const rendered = renderSkillMd(skill);\n changes.push(this.writeContentFile(join(dir, \"SKILL.md\"), rendered, ctx.dryRun));\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 // Migrate away an AC-owned copy at the deprecated user skills root so the\n // skill is not double-registered after the move to ~/.agents/skills.\n changes.push(...this.migrateDeprecatedUserSkill(ctx, skill, rendered));\n }\n return changes;\n }\n\n /**\n * One-time, opt-out-safe migration: prior AC versions wrote user-scope skills\n * to the now-deprecated $CODEX_HOME/skills/<name> root, which codex STILL reads\n * (kept for backward compatibility). Once we write the same skill to the current\n * ~/.agents/skills root, codex would register it TWICE (same frontmatter name,\n * two User-scope roots). If a SKILL.md exists at the deprecated path AND is\n * byte-identical to what we render — i.e. AC-owned, not hand-authored — remove\n * it (and its now-empty dir). The content-equality guard guarantees we never\n * delete a skill a user placed there by hand. No-op for project scope (where\n * .codex/skills is the valid, non-deprecated Project config-layer path) and when\n * a custom CODEX_HOME would make the deprecated path coincide with the new one.\n */\n private migrateDeprecatedUserSkill(\n ctx: InstallContext,\n skill: SkillDef,\n rendered: string,\n ): ChangeRecord[] {\n if (ctx.scope === \"project\") return [];\n const deprecated = join(this.userConfigDir(), \"skills\", skill.name, \"SKILL.md\");\n // Never touch the file we just wrote (pathological CODEX_HOME === ~/.agents).\n if (deprecated === join(this.skillDir(ctx, skill.name), \"SKILL.md\")) return [];\n if (!existsSync(deprecated)) return [];\n if (readFileSync(deprecated, \"utf8\") !== rendered) return []; // hand-authored — leave it\n return [\n this.removeContentFile(deprecated, ctx.dryRun),\n this.removeDirIfEmpty(dirname(deprecated), ctx.dryRun),\n ];\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 (TOML) ─────────────────────────────────────────────────────\n\n override installSubagents(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[this.id]?.subagents === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"subagents disabled for codex\" }];\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(this.subagentPath(ctx, agent.name), this.renderSubagent(agent), ctx.dryRun),\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 /**\n * Render a subagent to a Codex agent TOML file:\n * { name, description, developer_instructions: prompt, model }.\n * model is omitted when undefined so Codex applies its default.\n */\n private renderSubagent(agent: SubagentDef): string {\n const table: Record<string, unknown> = {\n name: agent.name,\n description: agent.description,\n developer_instructions: agent.prompt,\n };\n if (agent.model !== undefined) table.model = agent.model;\n if (agent.extra) Object.assign(table, agent.extra);\n return writeTomlString(table);\n }\n\n // ── Runtime dispatch ────────────────────────────────────────────────────\n\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\n const input = (raw ?? {}) as CodexHookInput;\n const base = {\n hostPlatform: this.id,\n connectorId: \"\",\n sessionId: input.session_id ?? `pid-${process.ppid}`,\n projectDir: input.cwd ?? process.env.CODEX_PROJECT_DIR ?? process.cwd(),\n raw,\n };\n\n switch (event) {\n case \"PreToolUse\":\n return {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n };\n case \"PostToolUse\":\n return {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n // tool_response is a bare string for shell/apply_patch but an OBJECT\n // for MCP tools — coerce non-strings to JSON so the string-typed\n // toolOutput never receives a raw object.\n toolOutput: coerceToolResponse(input.tool_response),\n // Codex never serializes a top-level is_error (deny_unknown_fields);\n // the true error signal is the CallToolResult.isError nested inside\n // tool_response for MCP tools. Derive it from there.\n isError: derivePostToolUseIsError(input.tool_response),\n };\n case \"SessionStart\":\n return { ...base, source: normalizeSessionSource(input.source) };\n case \"SessionEnd\":\n return { ...base, reason: input.message };\n case \"UserPromptSubmit\":\n return { ...base, prompt: input.prompt ?? \"\" };\n case \"PreCompact\":\n return { ...base, trigger: input.trigger === \"manual\" ? \"manual\" : \"auto\" };\n case \"PostCompact\":\n // Post-compaction sibling of PreCompact — same `trigger` normalization\n // (manual|auto), observe-only. Codex's PostCompact payload mirrors\n // PreCompact's; everything else rides on `raw`.\n return { ...base, trigger: input.trigger === \"manual\" ? \"manual\" : \"auto\" };\n case \"Stop\":\n return { ...base, stopHookActive: input.stop_hook_active ?? false };\n case \"Notification\":\n return { ...base, message: input.message ?? \"\" };\n case \"PermissionRequest\":\n // Codex documents tool_name/tool_input (+tool_input.description); it has\n // no permission_suggestions field, so the normalized optional stays unset.\n return {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n };\n case \"PostToolUseFailure\":\n // No Codex analog — never fired natively. Parsed defensively (Claude-\n // compatible wire) so a manual `hook codex PostToolUseFailure` invocation\n // still normalizes instead of throwing.\n return {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n error: input.error ?? \"\",\n };\n case \"SubagentStart\":\n return {\n ...base,\n ...(typeof input.agent_id === \"string\" ? { agentId: input.agent_id } : {}),\n ...(typeof input.agent_type === \"string\" ? { agentType: input.agent_type } : {}),\n };\n case \"SubagentStop\":\n // agent_id/agent_type stay optional — never depend on hosts populating\n // them on stop (the Claude-family SDK quirk).\n return {\n ...base,\n ...(typeof input.agent_id === \"string\" ? { agentId: input.agent_id } : {}),\n ...(typeof input.agent_type === \"string\" ? { agentType: input.agent_type } : {}),\n ...(typeof input.agent_transcript_path === \"string\"\n ? { agentTranscriptPath: input.agent_transcript_path }\n : {}),\n ...(typeof input.last_assistant_message === \"string\"\n ? { lastAssistantMessage: input.last_assistant_message }\n : {}),\n ...(typeof input.stop_hook_active === \"boolean\"\n ? { stopHookActive: input.stop_hook_active }\n : {}),\n };\n }\n }\n\n formatReply(event: HookEventName, response: HookResponse): HookReply {\n // Codex (like Claude Code) reads a `hookSpecificOutput` JSON wrapper from\n // stdout; exit code 0 = allow. Fields the host cannot honor are dropped.\n\n // PermissionRequest uses Codex's nested decision{behavior} envelope and is\n // the ONE event where an EXPLICIT \"allow\" is an ACTIVE grant (suppresses the\n // approval prompt). ask/context/void → NO decision output: fall through to\n // the normal approval flow (the prompt IS the ask). Codex docs: updatedInput\n // / updatedPermissions / interrupt FAIL CLOSED on this event, so \"modify\"\n // also falls through — emitting a bare allow would grant the ORIGINAL input\n // the handler wanted rewritten.\n if (event === \"PermissionRequest\") {\n if (response.decision === \"deny\") {\n return {\n exitCode: 0,\n stdout: JSON.stringify({\n hookSpecificOutput: {\n hookEventName: \"PermissionRequest\",\n decision: {\n behavior: \"deny\",\n message: response.reason ?? \"Blocked by hook\",\n },\n },\n }),\n };\n }\n if (response.decision === \"allow\") {\n return {\n exitCode: 0,\n stdout: JSON.stringify({\n hookSpecificOutput: {\n hookEventName: \"PermissionRequest\",\n decision: { behavior: \"allow\" },\n },\n }),\n };\n }\n return { exitCode: 0 };\n }\n\n // SubagentStart is observe/context-only on Codex (continue:false is parsed\n // but does not stop the subagent): \"context\" injects additionalContext as\n // developer context for the SUBAGENT, and a \"deny\" DEGRADES to the same\n // shape carrying the reason.\n if (event === \"SubagentStart\") {\n const context =\n response.decision === \"context\"\n ? response.additionalContext\n : response.decision === \"deny\"\n ? response.reason ?? response.additionalContext\n : undefined;\n if (context) {\n return {\n exitCode: 0,\n stdout: JSON.stringify({\n hookSpecificOutput: {\n hookEventName: \"SubagentStart\",\n additionalContext: context,\n },\n }),\n };\n }\n return { exitCode: 0 };\n }\n\n if (response.decision === \"deny\") {\n // PreToolUse deny is honored; other events fail-open to allow.\n if (event === \"PreToolUse\") {\n return {\n exitCode: 0,\n stdout: JSON.stringify({\n hookSpecificOutput: {\n hookEventName: \"PreToolUse\",\n permissionDecision: \"deny\",\n permissionDecisionReason: response.reason ?? \"Blocked by hook\",\n },\n }),\n };\n }\n // SubagentStop deny = Stop semantics: the documented continuation shape is\n // the TOP-LEVEL {\"decision\":\"block\",\"reason\"} (keeps the subagent going\n // with `reason` as its next instruction).\n if (event === \"SubagentStop\") {\n return {\n exitCode: 0,\n stdout: JSON.stringify({\n decision: \"block\",\n reason: response.reason ?? \"Blocked by hook\",\n }),\n };\n }\n return { exitCode: 0 };\n }\n\n // modify → rewrite PreToolUse tool input. Codex applies `updatedInput`\n // (PR #20527, stable since 0.131.0) but its output_parser.rs only accepts it\n // when paired with permissionDecision:\"allow\" — emitting updatedInput alone\n // (the Claude Code shape) is rejected as \"updatedInput without\n // permissionDecision:allow\", and an allow alone is rejected too, so the pair\n // is emitted together. Other events fail open (no updatedInput surface).\n if (response.decision === \"modify\") {\n if (event === \"PreToolUse\" && response.updatedInput) {\n return {\n exitCode: 0,\n stdout: JSON.stringify({\n hookSpecificOutput: {\n hookEventName: \"PreToolUse\",\n permissionDecision: \"allow\",\n updatedInput: response.updatedInput,\n },\n }),\n };\n }\n return { exitCode: 0 };\n }\n\n // Context injection: honored on SessionStart, PostToolUse, and PreToolUse\n // (additionalContext — PreToolUse support shipped via PR #20692, stable since\n // codex 0.130.0; injected independent of any permission decision).\n // (SubagentStop accepts only the common output fields — no additionalContext.)\n if (\n response.additionalContext &&\n (event === \"SessionStart\" || event === \"PostToolUse\" || event === \"PreToolUse\")\n ) {\n return {\n exitCode: 0,\n stdout: JSON.stringify({\n hookSpecificOutput: {\n hookEventName: event,\n additionalContext: response.additionalContext,\n },\n }),\n };\n }\n\n // \"allow\" / unsupported-on-Codex (ask) → passthrough.\n return { exitCode: 0 };\n }\n\n // ── Internal helpers ────────────────────────────────────────────────────\n\n /** Resolve the per-platform server override into an effective ServerDef. */\n private effectiveServer(ctx: InstallContext): ServerDef | undefined {\n const override = ctx.connector.platforms[this.id]?.server;\n if (override === false) return undefined;\n const base = ctx.connector.server;\n if (!base) return undefined;\n return override ? { ...base, ...override } : base;\n }\n\n /**\n * Render the `[mcp_servers.<id>]` table. TOML has NO interpolation, so every\n * `${env:VAR}` is resolved to a literal at install time. The env table is a\n * plain string→string map. Honors the telemetry serve-wrapper.\n */\n private renderMcpEntry(ctx: InstallContext, server: ServerDef): CodexMcpEntry {\n // Streamable HTTP server: codex infers the transport from `url` (no explicit\n // transport key). VERIFIED against codex-cli 0.139.0 — `codex mcp add <id>\n // --url <U> --bearer-token-env-var <E>` writes:\n // [mcp_servers.<id>]\n // url = \"…\"\n // bearer_token_env_var = \"…\" (only with bearerEnv auth)\n // Telemetry serve-wrapping is stdio-only (remote cannot be intercepted).\n // installServer's guard only lets stdio+command or http+url reach here, so\n // this branch is exactly the streamable-HTTP case (lock-step with the guard).\n if (server.transport === \"http\") {\n const remote: CodexMcpEntry = { url: resolveEnvRefsDeep(server.url ?? \"\") };\n if (server.auth?.type === \"bearerEnv\" && server.auth.bearerEnvVar) {\n remote.bearer_token_env_var = server.auth.bearerEnvVar;\n }\n if (server.headers && Object.keys(server.headers).length > 0) {\n const headers: Record<string, string> = {};\n for (const [k, v] of Object.entries(resolveEnvRefsDeep(server.headers))) {\n headers[k] = String(v);\n }\n remote.http_headers = headers;\n }\n return remote;\n }\n let command = server.command as string;\n let args = [...(server.args ?? [])];\n\n ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\n\n // Resolve env-refs to literals (TOML cannot interpolate).\n command = resolveEnvRefsDeep(command);\n args = resolveEnvRefsDeep(args);\n\n const entry: CodexMcpEntry = { command };\n if (args.length > 0) entry.args = args;\n\n if (server.env && Object.keys(server.env).length > 0) {\n const env: Record<string, string> = {};\n for (const [k, v] of Object.entries(resolveEnvRefsDeep(server.env))) {\n env[k] = String(v);\n }\n entry.env = env;\n }\n return entry;\n }\n\n /**\n * Does this hooks.json entry belong to this connector for `event`? EVENT-\n * SPECIFIC + path-normalized exact-command match. The engine binds this per\n * event in the uninstall (whole-entry FLAT removal) and the install idempotency\n * find reuses its command body via the descriptor's entryOwnsCommand.\n */\n private isOurEntry(ctx: InstallContext, event: CodexHookEventName, entry: CodexHookEntry): boolean {\n if (!entry || typeof entry !== \"object\" || !Array.isArray(entry.hooks)) return false;\n const ours = buildHomeBinHookCommand(ctx.homeBinPath, \"codex\", event, ctx.connector.id);\n const needle = ours.replace(/\\\\/g, \"/\");\n return entry.hooks.some((h) => (h.command ?? \"\").replace(/\\\\/g, \"/\") === needle);\n }\n}\n\nexport const adapter = new CodexAdapter();\nexport default adapter;\n"],"mappings":"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","names":[]}
@@ -10,10 +10,10 @@ import {
10
10
  } from "./chunk-H53QZQJI.js";
11
11
  import {
12
12
  resolveEnvRefsDeep
13
- } from "./chunk-DBQMX75U.js";
13
+ } from "./chunk-BEFVJ2OE.js";
14
14
  import {
15
15
  BaseAdapter
16
- } from "./chunk-RHML2NOB.js";
16
+ } from "./chunk-NUGMVVV2.js";
17
17
  import {
18
18
  buildHomeBinHookCommand,
19
19
  buildWrappedStdio,
@@ -769,4 +769,4 @@ export {
769
769
  adapter,
770
770
  continue_default as default
771
771
  };
772
- //# sourceMappingURL=continue-DYV5V55Y.js.map
772
+ //# sourceMappingURL=continue-KQSJUSWX.js.map
@@ -4,12 +4,12 @@ import {
4
4
  } from "./chunk-H53QZQJI.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
11
  renderSubagentMd
12
- } from "./chunk-RHML2NOB.js";
12
+ } from "./chunk-NUGMVVV2.js";
13
13
  import {
14
14
  buildHomeBinHookCommand,
15
15
  buildWrappedStdio,
@@ -84,11 +84,17 @@ var CopilotCliAdapter = class extends BaseAdapter {
84
84
  permissionRequest: false,
85
85
  postToolUseFailure: false,
86
86
  subagentStart: false,
87
- // PreToolUse is fail-closed and can rewrite tool input (updatedInput); a
88
- // PostToolUse hook cannot rewrite already-emitted tool output.
87
+ // PreToolUse is fail-closed and can rewrite tool input (the host reads a
88
+ // flat top-level `modifiedArgs`); a PostToolUse hook cannot rewrite
89
+ // already-emitted tool output.
89
90
  canModifyArgs: true,
90
91
  canModifyOutput: false,
91
- canInjectSessionContext: true,
92
+ // DEMOTED to false (fail-safe): the installed CLI 1.0.63 bundle has NO
93
+ // additionalContext mechanism — the token appears zero times in app.js, so a
94
+ // context-injection reply (SessionStart/PreCompact/etc.) is a silent no-op.
95
+ // Claiming the capability would advertise an injection path the host never
96
+ // honors; re-promote once a verified bundle ships an additionalContext reader.
97
+ canInjectSessionContext: false,
92
98
  // Copilot CLI's mcp-config.json `type` accepts stdio (written "local"),
93
99
  // http (Streamable HTTP), and sse (legacy) — per GitHub's add-mcp-servers docs.
94
100
  transports: ["stdio", "http", "sse"],
@@ -580,17 +586,17 @@ var CopilotCliAdapter = class extends BaseAdapter {
580
586
  case "PreToolUse": {
581
587
  const ev = {
582
588
  ...base,
583
- toolName: input.tool_name ?? "",
584
- toolInput: input.tool_input ?? {}
589
+ toolName: toolNameOf(input),
590
+ toolInput: toolInputOf(input)
585
591
  };
586
592
  return ev;
587
593
  }
588
594
  case "PostToolUse": {
589
- const toolOutput = input.tool_result?.text_result_for_llm;
595
+ const toolOutput = input.toolResult?.textResultForLlm ?? input.tool_result?.text_result_for_llm;
590
596
  const ev = {
591
597
  ...base,
592
- toolName: input.tool_name ?? "",
593
- toolInput: input.tool_input ?? {},
598
+ toolName: toolNameOf(input),
599
+ toolInput: toolInputOf(input),
594
600
  ...typeof toolOutput === "string" ? { toolOutput } : {}
595
601
  };
596
602
  return ev;
@@ -644,16 +650,16 @@ var CopilotCliAdapter = class extends BaseAdapter {
644
650
  case "PermissionRequest": {
645
651
  const ev = {
646
652
  ...base,
647
- toolName: input.tool_name ?? "",
648
- toolInput: input.tool_input ?? {}
653
+ toolName: toolNameOf(input),
654
+ toolInput: toolInputOf(input)
649
655
  };
650
656
  return ev;
651
657
  }
652
658
  case "PostToolUseFailure": {
653
659
  const ev = {
654
660
  ...base,
655
- toolName: input.tool_name ?? "",
656
- toolInput: input.tool_input ?? {},
661
+ toolName: toolNameOf(input),
662
+ toolInput: toolInputOf(input),
657
663
  error: typeof input.error === "string" ? input.error : ""
658
664
  };
659
665
  return ev;
@@ -717,6 +723,24 @@ var CopilotCliAdapter = class extends BaseAdapter {
717
723
  }
718
724
  return { exitCode: 0 };
719
725
  }
726
+ if (event === "PreToolUse") {
727
+ if (decision === "deny") {
728
+ return this.stdout({
729
+ permissionDecision: "deny",
730
+ permissionDecisionReason: response.reason ?? "Blocked by hook"
731
+ });
732
+ }
733
+ if (decision === "ask") {
734
+ return this.stdout({
735
+ permissionDecision: "ask",
736
+ permissionDecisionReason: response.reason ?? "Confirmation required by hook"
737
+ });
738
+ }
739
+ if (decision === "modify" && response.updatedInput) {
740
+ return this.stdout({ modifiedArgs: response.updatedInput });
741
+ }
742
+ return { exitCode: 0 };
743
+ }
720
744
  if (decision === "deny") {
721
745
  if (event === "SubagentStop") {
722
746
  return this.stdout({
@@ -741,13 +765,6 @@ var CopilotCliAdapter = class extends BaseAdapter {
741
765
  }
742
766
  });
743
767
  }
744
- if (decision === "modify") {
745
- if (event === "PreToolUse" && response.updatedInput) {
746
- return this.stdout({
747
- hookSpecificOutput: { hookEventName, updatedInput: response.updatedInput }
748
- });
749
- }
750
- }
751
768
  if (decision === "context" && response.additionalContext) {
752
769
  return this.stdout({
753
770
  hookSpecificOutput: { hookEventName, additionalContext: response.additionalContext }
@@ -764,11 +781,37 @@ function extractSessionId(input) {
764
781
  const m = input.transcript_path.match(/([a-f0-9-]{36})\.jsonl$/);
765
782
  if (m && m[1]) return m[1];
766
783
  }
784
+ if (typeof input.sessionId === "string" && input.sessionId !== "") {
785
+ return input.sessionId;
786
+ }
767
787
  if (typeof input.session_id === "string" && input.session_id !== "") {
768
788
  return input.session_id;
769
789
  }
770
790
  return "";
771
791
  }
792
+ function toolNameOf(input) {
793
+ if (typeof input.toolName === "string") return input.toolName;
794
+ if (typeof input.tool_name === "string") return input.tool_name;
795
+ return "";
796
+ }
797
+ function toolInputOf(input) {
798
+ const raw = input.toolArgs;
799
+ if (typeof raw === "string") {
800
+ try {
801
+ const parsed = JSON.parse(raw);
802
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
803
+ return parsed;
804
+ }
805
+ } catch {
806
+ }
807
+ } else if (raw && typeof raw === "object" && !Array.isArray(raw)) {
808
+ return raw;
809
+ }
810
+ if (input.tool_input && typeof input.tool_input === "object") {
811
+ return input.tool_input;
812
+ }
813
+ return {};
814
+ }
772
815
  var adapter = new CopilotCliAdapter();
773
816
  var copilot_cli_default = adapter;
774
817
  export {
@@ -776,4 +819,4 @@ export {
776
819
  adapter,
777
820
  copilot_cli_default as default
778
821
  };
779
- //# sourceMappingURL=copilot-cli-NVFXFLUF.js.map
822
+ //# sourceMappingURL=copilot-cli-YBNKLYUB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/copilot-cli/index.ts"],"sourcesContent":["/**\n * adapters/copilot-cli — GitHub Copilot CLI platform adapter for agent-connector.\n *\n * GitHub Copilot CLI is a json-stdio host: the host pipes a JSON payload to a\n * hook command on stdin and reads JSON/exit-code back. Its reply shape is\n * Claude-compatible (`hookSpecificOutput` wrapper), but its hooks-file event\n * KEYS are NOT — the CLI's loader honors ONLY a fixed set of lowerCamelCase\n * keys and SILENTLY DROPS anything else (see EVENT_WIRE_KEY below), so a\n * PascalCase→camelCase rename table IS required when writing the config.\n *\n * Native config (user/global only — Copilot CLI has no project-scoped config):\n * - MCP servers: ~/.copilot/mcp-config.json, root key \"mcpServers\". An stdio\n * server is written with type \"local\" (the host also accepts \"stdio\") plus\n * `tools: [\"*\"]`. Remote servers use type \"http\".\n * - Hooks: a hooks file shaped `{ version: 1, hooks: { … } }` discovered from\n * ~/.copilot/hooks/*.json. We write a single dedicated file,\n * ~/.copilot/hooks/agent-connector.json, so we never disturb a user's own\n * hook files and removal is a clean, scoped operation. Each event maps to an\n * array of flat command entries `{ matcher?, hooks: [{ type:\"command\", command }] }`\n * keyed by the CLI's lowerCamelCase wire name (EVENT_WIRE_KEY).\n * - Reply: the installed CLI 1.0.63 reads the PreToolUse permission decision\n * FLAT at the TOP LEVEL of the hook's stdout JSON — `{ permissionDecision\n * (allow|deny|ask), permissionDecisionReason, modifiedArgs? }` — there is NO\n * `hookSpecificOutput` wrapper in 1.0.63 (verified: the token appears zero\n * times in app.js), and PreToolUse is the ONLY event whose reply the host\n * reads. PreToolUse is fail-closed; exit 0 + the flat JSON refines the\n * decision. The host has no additionalContext mechanism, so context\n * injection is a no-op on this version. (PermissionRequest/SubagentStop keep\n * their Claude-shaped envelopes for forward-compat; they are unread on 1.0.63.)\n *\n * Env handling: the host is not documented to support `${env:VAR}` interpolation\n * inside mcp-config.json, so env/header/url refs are resolved to literals at\n * install time via resolveEnvRefsDeep (the safe default for a no-native-interp\n * host, matching the Codex adapter's approach).\n *\n * Content surfaces (surfaces-design §4-5): Copilot CLI exposes skills and\n * subagents but NO prompt-file command surface, so commands inherit the\n * BaseAdapter skip/warn default (supportsCommands stays false).\n * - skills: folder-per-skill `<dir>/skills/<name>/SKILL.md` (+ resource files).\n * user scope → ~/.copilot/skills; project scope → <projectDir>/.github/skills.\n * - subagents: user scope → ~/.copilot/agents/<name>.agent.md; project scope →\n * <projectDir>/.github/agents/<name>.agent.md (md + frontmatter:\n * name, description, tools, model).\n * The .github/ tree is shared with the vscode-copilot and jetbrains-copilot\n * connectors; we write identical, idempotent content and on uninstall remove\n * only the files this connector wrote.\n *\n * Grounded in docs/research/understand-report.md §2 (Platform Integration\n * Matrix, \"GitHub Copilot CLI\" row).\n */\n\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport type { Adapter, HookReply, InstallContext, MemoryTarget, NormalizedEvent } from \"../spi.js\";\nimport type {\n ChangeRecord,\n DetectedPlatform,\n HealthCheck,\n HookEventName,\n HookParadigm,\n HookResponse,\n NotificationEvent,\n PermissionRequestEvent,\n PlatformCapabilities,\n PlatformId,\n PostToolUseEvent,\n PostToolUseFailureEvent,\n 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 { resolveEnvRefsDeep } 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 = \"copilot-cli\";\nconst MCP_ROOT_KEY = \"mcpServers\";\n\n/** Native hooks-file version Copilot CLI expects (`{ version: 1, hooks: {…} }`). */\nconst COPILOT_HOOKS_VERSION = 1;\n\n/**\n * EVENT→WIRE-KEY map for the hooks file. VERIFIED against the installed GitHub\n * Copilot CLI 1.0.63 bundle (app.js): the hook loader validates every\n * `config.hooks` key against a hardcoded Set of NINE lowerCamelCase event names —\n * { sessionStart, sessionEnd, userPromptSubmitted, preToolUse, postToolUse,\n * errorOccurred, agentStop, subagentStop, preCompact }\n * — and any key NOT in that Set is SILENTLY DROPPED (logged only at debug:\n * \"Ignoring unknown hook event(s)\"). The Zod hooks schema defines the same nine\n * camelCase keys and nothing else. So a PascalCase key like `PreToolUse` never\n * registers → the hook NEVER FIRES. We therefore key the file by the camelCase\n * WIRE name, NOT the PascalCase HookEventName.\n *\n * Two mappings are NOT a naive lowercase-first-letter: Claude's `Stop` is the\n * CLI's `agentStop`, and `UserPromptSubmit` is `userPromptSubmitted`. The rest\n * are first-letter-lowercased. (PascalCase aliases are documented for a newer\n * CLI that selects the snake_case payload dialect, but they are unknown to the\n * loader in 1.0.63 and dropped — camelCase is the only safe wire form here.)\n *\n * Only events Copilot CLI's loader actually accepts appear here. Events the\n * installed loader has no file-hook key for (Notification, PermissionRequest,\n * SubagentStart, PostToolUseFailure) are demoted on `capabilities` and warn-skip\n * at install — they are NOT in this map.\n */\nconst EVENT_WIRE_KEY: Partial<Record<HookEventName, string>> = {\n SessionStart: \"sessionStart\",\n SessionEnd: \"sessionEnd\",\n UserPromptSubmit: \"userPromptSubmitted\",\n PreToolUse: \"preToolUse\",\n PostToolUse: \"postToolUse\",\n PreCompact: \"preCompact\",\n Stop: \"agentStop\",\n SubagentStop: \"subagentStop\",\n};\n\n/**\n * CAPABILITY FILTER for installHooks — maps each canonical HookEventName to the\n * `capabilities` flag that gates it. The adapter's `capabilities` literal is the\n * single source of truth for what Copilot CLI's runtime actually fires; declared\n * events (connector.hookEvents is the connector-level set, NOT pre-filtered by\n * host) are screened through this map so an unsupported event — Copilot CLI has\n * NO post-compaction hook, so `postCompact` stays unset — is reported as a\n * graceful warn/skip instead of being written as a dead `hooks.PostCompact` the\n * host would never fire. Same shape as the goose adapter's EVENT_CAPABILITY.\n */\nconst EVENT_CAPABILITY: Record<HookEventName, keyof PlatformCapabilities> = {\n SessionStart: \"sessionStart\",\n SessionEnd: \"sessionEnd\",\n UserPromptSubmit: \"userPromptSubmit\",\n PreToolUse: \"preToolUse\",\n PostToolUse: \"postToolUse\",\n PreCompact: \"preCompact\",\n Stop: \"stop\",\n Notification: \"notification\",\n PermissionRequest: \"permissionRequest\",\n PostToolUseFailure: \"postToolUseFailure\",\n SubagentStart: \"subagentStart\",\n SubagentStop: \"subagentStop\",\n // Copilot CLI has no post-compaction hook — postCompact stays unset on\n // `capabilities`, so a declared PostCompact warn-skips at install.\n PostCompact: \"postCompact\",\n};\n\n/**\n * A single Copilot CLI hook registration entry (Claude-shaped).\n *\n * `matcher` is OPTIONAL and, when present, MUST be non-empty. Copilot CLI's\n * hooks schema is `matcher: z.string().min(1).optional()` (live-verified on CLI\n * 1.0.63): an OMITTED matcher passes validation, but an EMPTY STRING fails it —\n * the loader logs \"Invalid hook configuration … matcher cannot be empty\" and\n * DISCARDS THE ENTIRE hook file, registering zero hooks. So we OMIT the key\n * entirely when there is no matcher and emit it only when non-empty; we must\n * never write `matcher: \"\"`.\n */\ninterface CopilotHookEntry {\n matcher?: string;\n hooks: Array<{ type: \"command\"; command: string }>;\n}\n\n/** The shape of the Copilot CLI hooks file we own. */\ninterface CopilotHooksFile {\n version?: number;\n hooks?: Record<string, CopilotHookEntry[]>;\n}\n\n/** Native MCP server entry shapes Copilot CLI accepts under `mcpServers`. */\ninterface CopilotLocalServer {\n /** stdio transport is registered as type \"local\" (host also accepts \"stdio\"). */\n type: \"local\";\n command: string;\n args?: string[];\n env?: Record<string, string>;\n cwd?: string;\n tools: string[];\n}\ninterface CopilotHttpServer {\n /** Remote transport: \"http\" (Streamable HTTP) or \"sse\" (legacy). */\n type: \"http\" | \"sse\";\n url: string;\n headers?: Record<string, string>;\n tools: string[];\n}\n\n/** Raw Copilot CLI hook stdin payload.\n *\n * The installed CLI 1.0.63 bundle (app.js) builds tool-event stdin in\n * lowerCamelCase via a single shared getter, NOT the Claude-style snake_case\n * this adapter once assumed:\n * PreToolUse → { sessionId, timestamp, cwd, toolName, toolArgs }\n * PostToolUse → { sessionId, timestamp, cwd, toolName, toolArgs,\n * toolResult: { resultType, textResultForLlm } }\n * where `toolArgs` is a JSON-**string** (the writer does\n * `toolArgs: JSON.stringify(t.toolArgs, null, 2)`). The snake_case fields are\n * retained as a tolerant fallback so a future/alternate dialect still parses,\n * but camelCase is the live wire form on 1.0.63. */\ninterface CopilotWireInput {\n connector?: unknown;\n // session id: camelCase on the live wire; snake_case kept as a fallback.\n sessionId?: string;\n session_id?: string;\n transcript_path?: string;\n cwd?: string;\n hook_event_name?: string;\n\n // tool events — camelCase is the live 1.0.63 wire form; `toolArgs` is a\n // JSON-STRING. snake_case retained as a tolerant fallback.\n toolName?: string;\n toolArgs?: unknown;\n tool_name?: string;\n tool_input?: Record<string, unknown>;\n // PostToolUse: the live bundle ships the result under camelCase\n // `toolResult.{resultType,textResultForLlm}`; the snake_case `tool_result`\n // form is kept as a fallback. PostToolUse fires success-only.\n toolResult?: { resultType?: string; textResultForLlm?: string };\n tool_result?: { result_type?: string; text_result_for_llm?: string };\n\n // SessionStart\n source?: string;\n // SessionEnd\n reason?: string;\n // UserPromptSubmit\n prompt?: string;\n // PreCompact\n trigger?: string;\n // Notification\n message?: string;\n\n // PostToolUseFailure — payload is {tool_name, tool_input, error} + base\n // (hooks-reference.md:421-430). No tool_use_id/is_interrupt/duration_ms.\n error?: string;\n\n // SubagentStart / SubagentStop — VS Code dialect identity is `agent_name`\n // (+ optional `agent_display_name`); there is no agent_id/agent_type\n // (hooks-reference.md:467-476,497-507).\n agent_name?: string;\n agent_display_name?: string;\n}\n\nexport class CopilotCliAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"GitHub Copilot CLI\";\n readonly paradigm: HookParadigm = \"json-stdio\";\n\n readonly capabilities: PlatformCapabilities = {\n // Memory surface: AGENTS.md-first managed block (project <projectDir>/AGENTS.md\n // via the base default; user scope → ~/.copilot/copilot-instructions.md below).\n supportsMemory: true,\n // Copilot CLI's file-hook loader (1.0.63) accepts exactly these of the\n // canonical lifecycle events — every one is a member of its hardcoded\n // camelCase validator Set (see EVENT_WIRE_KEY).\n preToolUse: true,\n postToolUse: true,\n preCompact: true,\n sessionStart: true,\n sessionEnd: true,\n userPromptSubmit: true, // → wire key userPromptSubmitted\n stop: true, // → wire key agentStop\n subagentStop: true,\n // DEMOTED — NOT in the installed CLI 1.0.63 file-hook validator Set, so a\n // hooks-file key for any of these is silently dropped and never fires:\n // notification, permissionRequest, subagentStart, postToolUseFailure.\n // (The github/docs `main` hooks-reference describes them for a NEWER CLI;\n // re-promote per-event once a verified bundle ships them in the Set — until\n // then the fail-safe is false so installHooks warn-skips instead of writing\n // a dead key.)\n notification: false,\n permissionRequest: false,\n postToolUseFailure: false,\n subagentStart: false,\n // PreToolUse is fail-closed and can rewrite tool input (the host reads a\n // flat top-level `modifiedArgs`); a PostToolUse hook cannot rewrite\n // already-emitted tool output.\n canModifyArgs: true,\n canModifyOutput: false,\n // DEMOTED to false (fail-safe): the installed CLI 1.0.63 bundle has NO\n // additionalContext mechanism — the token appears zero times in app.js, so a\n // context-injection reply (SessionStart/PreCompact/etc.) is a silent no-op.\n // Claiming the capability would advertise an injection path the host never\n // honors; re-promote once a verified bundle ships an additionalContext reader.\n canInjectSessionContext: false,\n // Copilot CLI's mcp-config.json `type` accepts stdio (written \"local\"),\n // http (Streamable HTTP), and sse (legacy) — per GitHub's add-mcp-servers docs.\n transports: [\"stdio\", \"http\", \"sse\"],\n // Content surfaces: Copilot CLI exposes skills + subagents, but has no\n // prompt-file command surface, so commands stay false (inherits BaseAdapter\n // skip/warn).\n supportsCommands: false,\n supportsSkills: true,\n supportsSubagents: true,\n // Native passthrough: Copilot CLI has an `errorOccurred` lifecycle event (a\n // member of the camelCase validator Set) with NO canonical HookEventName\n // analog — below the >=3-host core bar (docs/research/host-specific-hook-events-design.md).\n // A connector reaches it via platforms[\"copilot-cli\"].nativeHooks; installHooks\n // files the event-name key VERBATIM (the author must supply the CLI's exact\n // camelCase key, e.g. `errorOccurred` — the loader drops unknown keys) with\n // the same home-bin command shape, and the generic uninstall reverses it.\n supportsNativeHooks: true,\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(_projectDir: string): DetectedPlatform {\n const userDir = join(homedir(), \".copilot\");\n const mcpConfig = join(userDir, \"mcp-config.json\");\n const hooksDir = join(userDir, \"hooks\");\n const installed =\n existsSync(userDir) || existsSync(mcpConfig) || existsSync(hooksDir);\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath: mcpConfig,\n scope: \"user\",\n reason: installed\n ? `found GitHub Copilot CLI config under ${userDir}`\n : `no GitHub Copilot CLI config at ${userDir}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Memory surface: user-scope global instructions file ─────────────────\n // Project scope stays on the AGENTS.md base default (root AGENTS.md is the\n // primary instructions file). User scope targets Copilot CLI's documented\n // $HOME/.copilot/copilot-instructions.md — a markdown file shared with other\n // writers, so the managed block (not whole-file ownership) applies as usual.\n protected override memoryTargets(ctx: InstallContext): MemoryTarget[] {\n if (this.memoryOverride(ctx)?.path || ctx.scope !== \"user\") {\n return super.memoryTargets(ctx);\n }\n return [\n {\n path: join(homedir(), \".copilot\", \"copilot-instructions.md\"),\n reason: \"copilot-cli global instructions (~/.copilot/copilot-instructions.md)\",\n },\n ];\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n /** Copilot CLI is user/global only — scope is ignored. */\n getConfigDir(_ctx: InstallContext): string {\n return join(homedir(), \".copilot\");\n }\n\n getServerConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"mcp-config.json\");\n }\n\n /**\n * Copilot CLI discovers hooks from any `~/.copilot/hooks/*.json`. We write a\n * single dedicated file so we never disturb the user's own hook files and\n * uninstall is a clean, scoped operation.\n */\n getHookConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"hooks\", \"agent-connector.json\");\n }\n\n // ── MCP server install / uninstall ───────────────────────────────────────\n\n installServer(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const override = connector.platforms[HOST]?.server;\n if (!connector.server || override === false) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: connector.server\n ? \"server registration disabled for copilot-cli\"\n : \"connector declares no MCP server\",\n },\n ];\n }\n\n // Shallow-merge any per-platform server override into the base ServerDef.\n const server: ServerDef =\n override && typeof override === \"object\"\n ? { ...connector.server, ...override }\n : connector.server;\n\n const serverPath = this.getServerConfigPath(ctx);\n const entry = this.renderServerEntry(ctx, server);\n\n return [\n this.upsertServerInJson(serverPath, MCP_ROOT_KEY, connector.id, entry, ctx.dryRun),\n ];\n }\n\n uninstallServer(ctx: InstallContext): ChangeRecord[] {\n const serverPath = this.getServerConfigPath(ctx);\n return [\n this.removeServerFromJson(serverPath, MCP_ROOT_KEY, ctx.connector.id, ctx.dryRun),\n ];\n }\n\n /** Render a normalized ServerDef into Copilot CLI's native mcpServers entry. */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): CopilotLocalServer | CopilotHttpServer {\n const transport: Transport = server.transport;\n const tools = this.renderTools(server);\n\n if (transport === \"stdio\") {\n let command = server.command ?? \"\";\n let args = [...(server.args ?? [])];\n\n // Transparent telemetry wrapping: route the real command through\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\n ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\n\n const entry: CopilotLocalServer = {\n type: \"local\",\n command: resolveEnvRefsDeep(command),\n tools,\n };\n if (args.length > 0) entry.args = args.map((a) => resolveEnvRefsDeep(a));\n const env = this.renderEnv(server.env);\n if (env) entry.env = env;\n if (server.cwd) entry.cwd = resolveEnvRefsDeep(server.cwd);\n return entry;\n }\n\n // remote (Streamable http / legacy sse) — Copilot registers a URL keyed by\n // its `type`. AC's canonical \"sse\" → \"sse\"; everything else → \"http\".\n const entry: CopilotHttpServer = {\n type: server.transport === \"sse\" ? \"sse\" : \"http\",\n url: resolveEnvRefsDeep(server.url ?? \"\"),\n tools,\n };\n const headers = this.renderEnv(server.headers);\n if (headers) entry.headers = headers;\n return entry;\n }\n\n /**\n * Render env/header values. Copilot CLI is not documented to support native\n * `${env:VAR}` interpolation in mcp-config.json, so refs resolve to literals\n * at install time (the safe default for a no-native-interp host).\n */\n private renderEnv(\n env: Record<string, string> | undefined,\n ): Record<string, string> | undefined {\n if (!env || Object.keys(env).length === 0) return undefined;\n return resolveEnvRefsDeep({ ...env });\n }\n\n /** Render the tool allow-list. Copilot CLI expects `tools` on every entry; default [\"*\"]. */\n private renderTools(server: ServerDef): string[] {\n const include = server.tools?.include;\n return include && include.length > 0 ? [...include] : [\"*\"];\n }\n\n // ── Hook install / uninstall ─────────────────────────────────────────────\n\n installHooks(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const override = connector.platforms[HOST];\n const hooksDisabled = override?.hooks === false;\n // `hooks: false` disables only the NORMALIZED events; nativeHooks is a\n // sibling, copilot-cli-scoped declaration that installs regardless.\n const normalizedEvents = hooksDisabled ? [] : connector.hookEvents;\n const nativeHooks = override?.nativeHooks ?? {};\n const nativeEvents = Object.keys(nativeHooks);\n\n if (normalizedEvents.length === 0 && nativeEvents.length === 0) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: hooksDisabled\n ? \"hooks disabled for copilot-cli\"\n : \"connector declares no hooks\",\n },\n ];\n }\n\n const hooksPath = this.getHookConfigPath(ctx);\n const file = this.readJson<CopilotHooksFile>(hooksPath) ?? {};\n const __skip = this.malformedHookRootSkip(hooksPath, (file as Record<string, unknown>).hooks);\n if (__skip) return [__skip];\n const hooks = (file.hooks ??= {});\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const event of normalizedEvents) {\n // CAPABILITY FILTER: an event Copilot CLI's runtime does not deliver (e.g.\n // PostCompact — postCompact unset on `capabilities`) must NOT be written as\n // a dead hook the host never fires; report a graceful warn/skip instead.\n if (this.capabilities[EVENT_CAPABILITY[event]] !== true) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: hooksPath,\n detail: `${event} unsupported on copilot-cli — skipped`,\n });\n continue;\n }\n // Key the hooks file by the CLI's camelCase WIRE name — a PascalCase key\n // is silently dropped by the loader (see EVENT_WIRE_KEY). The home-bin\n // command keeps the PascalCase `event` token: that is the AC-internal\n // router event passed to parseEvent/formatReply, NOT a hooks-file key.\n const copilotEvent = EVENT_WIRE_KEY[event];\n if (copilotEvent === undefined) {\n // Defensive: a capability-flagged event with no wire key would write a\n // dead PascalCase key. Treat it like an unsupported event (warn-skip).\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: hooksPath,\n detail: `${event} unsupported on copilot-cli — skipped`,\n });\n continue;\n }\n const command = buildHomeBinHookCommand(ctx.homeBinPath, HOST, event, connector.id);\n const matcher = connector.hooks[event]?.matcher;\n // OMIT the matcher key when there is none — Copilot CLI rejects an empty\n // string (matcher cannot be empty) and discards the whole hooks file.\n const entry: CopilotHookEntry = {\n ...(matcher ? { matcher } : {}),\n hooks: [{ type: \"command\", command }],\n };\n\n const bucket = (hooks[copilotEvent] ??= []);\n const existingIdx = bucket.findIndex((e) => this.entryHasOurCommand(e, ctx));\n\n if (existingIdx >= 0) {\n if (JSON.stringify(bucket[existingIdx]) === JSON.stringify(entry)) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: `hooks.${copilotEvent} already registered`,\n });\n continue;\n }\n bucket[existingIdx] = entry;\n changes.push({\n platform: this.id,\n action: \"update\",\n path: hooksPath,\n detail: `hooks.${copilotEvent}`,\n });\n } else {\n bucket.push(entry);\n changes.push({\n platform: this.id,\n action: \"create\",\n path: hooksPath,\n detail: `hooks.${copilotEvent}`,\n });\n }\n mutated = true;\n }\n\n // NATIVE passthrough events: copilot-cli-native event-name keys (e.g.\n // ErrorOccurred) filed VERBATIM into the hooks map — no EVENT_MAP, since they\n // ARE Copilot events. The command keeps the native token; matched by EXACT\n // command so a native key coinciding with a normalized one never clobbers it.\n for (const nativeEvent of nativeEvents) {\n const command = buildHomeBinHookCommand(ctx.homeBinPath, HOST, nativeEvent, connector.id);\n const matcher = nativeHooks[nativeEvent]?.matcher;\n // OMIT the matcher key when there is none (empty string fails validation).\n const entry: CopilotHookEntry = {\n ...(matcher ? { matcher } : {}),\n hooks: [{ type: \"command\", command }],\n };\n const bucket = (hooks[nativeEvent] ??= []);\n const existingIdx = bucket.findIndex((e) => e.hooks?.[0]?.command === command);\n if (existingIdx >= 0) {\n if (JSON.stringify(bucket[existingIdx]) === JSON.stringify(entry)) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: `hooks.${nativeEvent} (native) already registered`,\n });\n continue;\n }\n bucket[existingIdx] = entry;\n changes.push({\n platform: this.id,\n action: \"update\",\n path: hooksPath,\n detail: `hooks.${nativeEvent} (native)`,\n });\n } else {\n bucket.push(entry);\n changes.push({\n platform: this.id,\n action: \"create\",\n path: hooksPath,\n detail: `hooks.${nativeEvent} (native)`,\n });\n }\n mutated = true;\n }\n\n if (mutated) {\n file.version = COPILOT_HOOKS_VERSION;\n this.writeJson(hooksPath, file, ctx.dryRun);\n }\n return changes;\n }\n\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n const hooksPath = this.getHookConfigPath(ctx);\n const file = this.readJson<CopilotHooksFile>(hooksPath);\n const hooks = file?.hooks;\n if (!file || !hooks) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: hooksPath,\n detail: \"no hooks section present\",\n },\n ];\n }\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const copilotEvent of Object.keys(hooks)) {\n const bucket = hooks[copilotEvent];\n if (!Array.isArray(bucket)) continue;\n\n // Strip our hook command from each entry; drop entries left empty so we\n // never remove another connector's (or the user's own) hook commands.\n const next: CopilotHookEntry[] = [];\n let removed = 0;\n for (const e of bucket) {\n const innerBefore = e.hooks?.length ?? 0;\n const inner = (e.hooks ?? []).filter((h) => !this.isOurCommand(h.command, ctx));\n removed += innerBefore - inner.length;\n // Preserve the entry's original matcher verbatim, but never synthesize an\n // empty string — Copilot CLI rejects `matcher: \"\"` (whole file discarded).\n if (inner.length > 0) next.push({ ...(e.matcher ? { matcher: e.matcher } : {}), hooks: inner });\n }\n\n if (removed > 0) {\n if (next.length > 0) hooks[copilotEvent] = next;\n else delete hooks[copilotEvent];\n changes.push({\n platform: this.id,\n action: \"remove\",\n path: hooksPath,\n detail: `hooks.${copilotEvent} (${removed})`,\n });\n mutated = true;\n }\n }\n\n if (mutated) {\n // When our uninstall empties the hooks map, delete this connector's\n // dedicated file rather than leaving an inert `{version:1,hooks:{}}` stub.\n // The file is owned solely by AC (see getHookConfigPath), so removing it on\n // full teardown is safe and keeps ~/.copilot/hooks clean.\n if (Object.keys(hooks).length === 0) {\n this.removeManagedFile(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 private entryHasOurCommand(entry: CopilotHookEntry, ctx: InstallContext): boolean {\n return (entry.hooks ?? []).some((h) => this.isOurCommand(h.command, ctx));\n }\n\n /** True when a hook command references our home binary AND this connector id\n * (anchored so a shared-prefix id can't collide — see isHomeBinHookCommand). */\n private isOurCommand(command: string | undefined, ctx: InstallContext): boolean {\n return isHomeBinHookCommand(command, ctx.homeBinPath, ctx.connector.id);\n }\n\n // ── Content surfaces: skills / subagents ─────────────────────────────────\n // CONTENT-ONLY: pure native-file writers. No runtime dispatch, no home-bin\n // pointer, no telemetry wrap. Each method is idempotent (byte-identical →\n // skip) via BaseAdapter.writeContentFile and reversible via removeContentFile.\n // Honors platforms[\"copilot-cli\"] per-surface false to skip. Commands are\n // unsupported here — they inherit the BaseAdapter skip/warn default.\n //\n // Path scoping: user scope lives under ~/.copilot (getConfigDir); project\n // scope lives under the shared <projectDir>/.github tree (the same files\n // vscode-copilot / jetbrains-copilot would write). We write identical content\n // and on uninstall remove only the files this connector wrote.\n\n /** Root dir for content surfaces: ~/.copilot (user) or <projectDir>/.github (project). */\n private contentDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".github\")\n : this.getConfigDir(ctx);\n }\n\n private skillsDir(ctx: InstallContext): string {\n return join(this.contentDir(ctx), \"skills\");\n }\n private agentsDir(ctx: InstallContext): string {\n return join(this.contentDir(ctx), \"agents\");\n }\n\n /** Native skill dir: <contentDir>/skills/<name>. */\n private skillDir(ctx: InstallContext, name: string): string {\n return join(this.skillsDir(ctx), name);\n }\n /** Native subagent file path: <contentDir>/agents/<name>.agent.md. */\n private subagentPath(ctx: InstallContext, name: string): string {\n return join(this.agentsDir(ctx), `${name}.agent.md`);\n }\n\n // ── Skills ────────────────────────────────────────────────────────────────\n\n override installSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.skills === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"skills disabled for copilot-cli\" }];\n }\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n changes.push(\n this.writeContentFile(join(dir, \"SKILL.md\"), 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 copilot-cli\" }];\n }\n if (connector.subagents.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\n }\n return connector.subagents.map((agent) =>\n this.writeContentFile(\n this.subagentPath(ctx, agent.name),\n 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-config.json present`,\n check: () =>\n existsSync(mcpPath)\n ? { status: \"OK\", detail: mcpPath }\n : { status: \"FAIL\", detail: `not found: ${mcpPath}` },\n },\n {\n name: `${this.name}: hook command registered`,\n check: () => {\n if (hookEvents.length === 0) {\n return { status: \"OK\", detail: \"no hooks declared\" };\n }\n const file = this.readJson<CopilotHooksFile>(hooksPath);\n if (!file) return { status: \"FAIL\", detail: `cannot read ${hooksPath}` };\n const hooks = file.hooks ?? {};\n const registered = Object.values(hooks).some((entries) =>\n (entries ?? []).some((e) =>\n (e.hooks ?? []).some((h) =>\n isHomeBinHookCommand(h.command, homeBin, connectorId),\n ),\n ),\n );\n return registered\n ? { status: \"OK\", detail: \"hook command present\" }\n : { status: \"FAIL\", detail: `no hook for ${connectorId} in ${hooksPath}` };\n },\n },\n ];\n\n // Content-surface checks: only assert presence of the surfaces this\n // connector declares (skip silently for surfaces it never asked for).\n // Commands are unsupported on Copilot CLI, so no command check.\n for (const skill of ctx.connector.skills) {\n const p = join(this.skillDir(ctx, skill.name), \"SKILL.md\");\n checks.push({\n name: `${this.name}: skill ${skill.name} present`,\n check: () =>\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\n });\n }\n for (const agent of ctx.connector.subagents) {\n const p = this.subagentPath(ctx, agent.name);\n checks.push({\n name: `${this.name}: subagent ${agent.name} present`,\n check: () =>\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\n });\n }\n return checks;\n }\n\n // ── Runtime: parse Copilot CLI stdin JSON → normalized event ─────────────\n\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\n const input = (raw ?? {}) as CopilotWireInput;\n const connectorId = typeof input.connector === \"string\" ? input.connector : \"\";\n const sessionId = extractSessionId(input);\n const projectDir = typeof input.cwd === \"string\" ? input.cwd : undefined;\n\n const base = {\n hostPlatform: HOST,\n connectorId,\n sessionId,\n raw,\n ...(projectDir !== undefined ? { projectDir } : {}),\n } as const;\n\n switch (event) {\n case \"PreToolUse\": {\n // Live 1.0.63 wire: camelCase `toolName` + `toolArgs` (a JSON-STRING).\n // snake_case `tool_name`/`tool_input` are tolerant fallbacks.\n const ev: PreToolUseEvent = {\n ...base,\n toolName: toolNameOf(input),\n toolInput: toolInputOf(input),\n };\n return ev;\n }\n case \"PostToolUse\": {\n // PostToolUse fires success-only. The live 1.0.63 wire carries the\n // result under camelCase `toolResult.textResultForLlm`; the snake_case\n // `tool_result.text_result_for_llm` form is a tolerant fallback. Failures\n // arrive via the separate PostToolUseFailure event, so isError is never\n // set here.\n const toolOutput =\n input.toolResult?.textResultForLlm ?? input.tool_result?.text_result_for_llm;\n const ev: PostToolUseEvent = {\n ...base,\n toolName: toolNameOf(input),\n toolInput: toolInputOf(input),\n ...(typeof toolOutput === \"string\" ? { toolOutput } : {}),\n };\n return ev;\n }\n case \"SessionStart\": {\n const ev: SessionStartEvent = {\n ...base,\n source: normalizeSessionSource(input.source),\n };\n return ev;\n }\n case \"SessionEnd\": {\n const ev: SessionEndEvent = {\n ...base,\n ...(typeof input.reason === \"string\" ? { reason: input.reason } : {}),\n };\n return ev;\n }\n case \"UserPromptSubmit\": {\n const ev: UserPromptSubmitEvent = {\n ...base,\n prompt: typeof input.prompt === \"string\" ? input.prompt : \"\",\n };\n return ev;\n }\n case \"PreCompact\": {\n const ev: PreCompactEvent = {\n ...base,\n ...(input.trigger === \"auto\" || input.trigger === \"manual\"\n ? { trigger: input.trigger }\n : {}),\n };\n return ev;\n }\n case \"PostCompact\": {\n // Copilot CLI does not fire PostCompact natively (postCompact unset →\n // warn-skip at install). Parsed defensively, mirroring PreCompact, so a\n // 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 \"Stop\": {\n // The host signals completion via stop_reason:\"end_turn\", not the\n // stopHookActive loop-guard boolean, so nothing maps onto StopEvent\n // beyond base (hooks-reference.md:449-457).\n const ev: StopEvent = { ...base };\n return ev;\n }\n case \"Notification\": {\n const ev: NotificationEvent = {\n ...base,\n message: typeof input.message === \"string\" ? input.message : \"\",\n };\n return ev;\n }\n case \"PermissionRequest\": {\n // permissionRequest uses the PreToolUse shape (tool_name + tool_input\n // only); the host emits no permission_suggestions payload\n // (hooks-reference.md:218,627-649).\n const ev: PermissionRequestEvent = {\n ...base,\n toolName: toolNameOf(input),\n toolInput: toolInputOf(input),\n };\n return ev;\n }\n case \"PostToolUseFailure\": {\n // Host payload is the tool-event shape + `error`; it carries no\n // tool_use_id / is_interrupt / duration_ms correlation fields. (Demoted\n // on capabilities — below the live-fire bar — but parsed consistently\n // with the live camelCase tool dialect.)\n const ev: PostToolUseFailureEvent = {\n ...base,\n toolName: toolNameOf(input),\n toolInput: toolInputOf(input),\n error: typeof input.error === \"string\" ? input.error : \"\",\n };\n return ev;\n }\n case \"SubagentStart\": {\n // The host's subagent identity field is `agent_name`; there is no\n // agent_id or agent_type (agent_display_name is a human label, not a\n // type), so agentType stays unset (hooks-reference.md:467-476).\n const ev: SubagentStartEvent = {\n ...base,\n ...(typeof input.agent_name === \"string\" ? { agentId: input.agent_name } : {}),\n };\n return ev;\n }\n case \"SubagentStop\": {\n // VS Code dialect: identity is `agent_name`, the subagent transcript is\n // the BASE `transcript_path` (not agent_transcript_path), and there is\n // no agent_type / last_assistant_message / stop_hook_active — the final\n // response is reachable only via transcript_path, and completion is\n // signalled by stop_reason (hooks-reference.md:497-507).\n const ev: SubagentStopEvent = {\n ...base,\n ...(typeof input.agent_name === \"string\" ? { agentId: input.agent_name } : {}),\n ...(typeof input.transcript_path === \"string\"\n ? { agentTranscriptPath: input.transcript_path }\n : {}),\n };\n return ev;\n }\n default: {\n // Exhaustive guard — every HookEventName is handled above.\n const _never: never = event;\n throw new Error(`unsupported copilot-cli hook event: ${String(_never)}`);\n }\n }\n }\n\n // ── Runtime: normalized response → Copilot CLI native hook reply ─────────\n\n formatReply(event: HookEventName, response: HookResponse): HookReply {\n const hookEventName = event;\n const decision = response.decision ?? \"allow\";\n\n // PermissionRequest replies use the Claude-compatible nested\n // decision{behavior} envelope and are the ONE event where an EXPLICIT\n // \"allow\" is an ACTIVE grant (it suppresses the permission dialog) rather\n // than passthrough:\n // allow → decision{behavior:\"allow\"} (+updatedInput when set);\n // the host still enforces its own deny rules.\n // modify → an allow grant carrying updatedInput.\n // deny → decision{behavior:\"deny\", message}.\n // ask/context/void → NO decision output: fall through to the native\n // dialog (the dialog IS the ask).\n if (event === \"PermissionRequest\") {\n if (response.decision === \"deny\") {\n return this.stdout({\n hookSpecificOutput: {\n hookEventName,\n decision: {\n behavior: \"deny\",\n message: response.reason ?? \"Blocked by hook\",\n },\n },\n });\n }\n if (\n response.decision === \"allow\" ||\n (response.decision === \"modify\" && response.updatedInput)\n ) {\n return this.stdout({\n hookSpecificOutput: {\n hookEventName,\n decision: {\n behavior: \"allow\",\n ...(response.updatedInput\n ? { updatedInput: response.updatedInput }\n : {}),\n },\n },\n });\n }\n return { exitCode: 0 };\n }\n\n // PostToolUseFailure (recovery guidance beside the error) and SubagentStart\n // (context prepended to the SUBAGENT's conversation — creation is not\n // blockable on Copilot CLI) are observe/context-only: \"context\" emits\n // additionalContext, and a \"deny\" DEGRADES to the same shape carrying the\n // reason. Everything else passes through.\n if (event === \"PostToolUseFailure\" || event === \"SubagentStart\") {\n const context =\n decision === \"context\"\n ? response.additionalContext\n : decision === \"deny\"\n ? response.reason ?? response.additionalContext\n : undefined;\n if (context) {\n return this.stdout({\n hookSpecificOutput: { hookEventName, additionalContext: context },\n });\n }\n return { exitCode: 0 };\n }\n\n // PreToolUse — the ONLY event whose reply the installed CLI 1.0.63 actually\n // reads, and it reads the permission decision FLAT at the TOP LEVEL of the\n // hook's stdout JSON (VERIFIED in app.js):\n // a => ({ permissionDecision: a?.permissionDecision,\n // permissionDecisionReason: a?.permissionDecisionReason,\n // modifiedArgs: a?.modifiedArgs })\n // There is NO `hookSpecificOutput` wrapper in 1.0.63 (the token appears zero\n // times in the bundle), so a nested reply leaves `a.permissionDecision`\n // undefined and the deny is SILENTLY IGNORED — the tool runs anyway. We\n // therefore emit the flat keys the host honors:\n // deny → { permissionDecision:\"deny\", permissionDecisionReason }\n // → host prints `Denied by preToolUse hook: <reason>`\n // ask → { permissionDecision:\"ask\", permissionDecisionReason }\n // modify → { modifiedArgs } (the host accepts a string or an object and\n // stringifies an object itself; we pass updatedInput as-is)\n // context/additionalContext → NO-OP on 1.0.63 (the bundle has no\n // additionalContext mechanism), so it degrades to exit 0.\n if (event === \"PreToolUse\") {\n if (decision === \"deny\") {\n return this.stdout({\n permissionDecision: \"deny\",\n permissionDecisionReason: response.reason ?? \"Blocked by hook\",\n });\n }\n if (decision === \"ask\") {\n return this.stdout({\n permissionDecision: \"ask\",\n permissionDecisionReason: response.reason ?? \"Confirmation required by hook\",\n });\n }\n if (decision === \"modify\" && response.updatedInput) {\n return this.stdout({ modifiedArgs: response.updatedInput });\n }\n // allow / context / void → pass through (no honored reply on 1.0.63).\n return { exitCode: 0 };\n }\n\n // deny → block the action with a reason (exit 0; JSON carries the decision).\n // SubagentStop is the Stop-semantics exception: like Claude, the block is\n // the TOP-LEVEL {\"decision\":\"block\",\"reason\"} — it keeps the subagent\n // running with `reason` as its next instruction (the host \"can block and\n // force continuation\").\n //\n // NOTE: for every OTHER event, the installed CLI 1.0.63 attaches NO reply\n // reader (the bundle's args getter is `a => {}`), so what we emit below is a\n // no-op on this version; it is retained for forward-compatibility with a\n // CLI that does consume these decisions.\n if (decision === \"deny\") {\n if (event === \"SubagentStop\") {\n return this.stdout({\n decision: \"block\",\n reason: response.reason ?? \"Blocked by hook\",\n });\n }\n return this.stdout({\n hookSpecificOutput: {\n hookEventName,\n permissionDecision: \"deny\",\n permissionDecisionReason: response.reason ?? \"Blocked by hook\",\n },\n });\n }\n\n // ask → prompt the user to confirm.\n if (decision === \"ask\") {\n return this.stdout({\n hookSpecificOutput: {\n hookEventName,\n permissionDecision: \"ask\",\n permissionDecisionReason: response.reason ?? \"Confirmation required by hook\",\n },\n });\n }\n\n // modify is a PreToolUse-only capability and is handled in the flat-reply\n // PreToolUse branch above; for every other event it falls through to allow\n // (output rewrite is unsupported on Copilot CLI).\n\n // context → inject soft guidance (also the SessionStart context path).\n if (decision === \"context\" && response.additionalContext) {\n return this.stdout({\n hookSpecificOutput: { hookEventName, additionalContext: response.additionalContext },\n });\n }\n\n // allow / void / unsupported-degradation → pass through with exit 0.\n return { exitCode: 0 };\n }\n\n private stdout(payload: unknown): HookReply {\n return { exitCode: 0, stdout: JSON.stringify(payload) };\n }\n}\n\n/**\n * Extract a stable session id from a Copilot CLI wire payload.\n * Priority mirrors the Claude wire protocol: transcript UUID > sessionId > \"\".\n * The live 1.0.63 wire sends `sessionId` (camelCase); `session_id` is kept as a\n * tolerant fallback.\n */\nfunction extractSessionId(input: CopilotWireInput): string {\n if (typeof input.transcript_path === \"string\") {\n const m = input.transcript_path.match(/([a-f0-9-]{36})\\.jsonl$/);\n if (m && m[1]) return m[1];\n }\n if (typeof input.sessionId === \"string\" && input.sessionId !== \"\") {\n return input.sessionId;\n }\n if (typeof input.session_id === \"string\" && input.session_id !== \"\") {\n return input.session_id;\n }\n return \"\";\n}\n\n/**\n * Resolve the tool name from a tool-event payload — camelCase `toolName` (the\n * live 1.0.63 wire) with a snake_case `tool_name` fallback.\n */\nfunction toolNameOf(input: CopilotWireInput): string {\n if (typeof input.toolName === \"string\") return input.toolName;\n if (typeof input.tool_name === \"string\") return input.tool_name;\n return \"\";\n}\n\n/**\n * Resolve the tool input object from a tool-event payload. The live 1.0.63 wire\n * sends `toolArgs` as a JSON-STRING (`JSON.stringify(t.toolArgs,null,2)`), so we\n * parse it into an object; an already-object `toolArgs` is accepted as-is, and\n * the snake_case `tool_input` (already an object) is the fallback.\n */\nfunction toolInputOf(input: CopilotWireInput): Record<string, unknown> {\n const raw = input.toolArgs;\n if (typeof raw === \"string\") {\n try {\n const parsed = JSON.parse(raw);\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>;\n }\n } catch {\n // Non-JSON string → fall through to the other shapes / empty object.\n }\n } else if (raw && typeof raw === \"object\" && !Array.isArray(raw)) {\n return raw as Record<string, unknown>;\n }\n if (input.tool_input && typeof input.tool_input === \"object\") {\n return input.tool_input;\n }\n return {};\n}\n\nexport const adapter = new CopilotCliAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}
@@ -5,11 +5,11 @@ import {
5
5
  } from "./chunk-UM5S7DKK.js";
6
6
  import {
7
7
  resolveEnvRefsDeep
8
- } from "./chunk-DBQMX75U.js";
8
+ } from "./chunk-BEFVJ2OE.js";
9
9
  import {
10
10
  BaseAdapter,
11
11
  renderSkillMd
12
- } from "./chunk-RHML2NOB.js";
12
+ } from "./chunk-NUGMVVV2.js";
13
13
  import {
14
14
  buildHomeBinHookCommand,
15
15
  buildWrappedStdio,
@@ -201,9 +201,9 @@ var CrushAdapter = class extends BaseAdapter {
201
201
  return [{ platform: this.id, action: "skip", detail: "hooks disabled for crush" }];
202
202
  }
203
203
  const events = this.effectiveHookEvents(ctx);
204
- const dropped = this.warnSkipHookEvents(ctx);
204
+ const declined = this.declinedHookEvents(ctx);
205
205
  const path = this.getHookConfigPath(ctx);
206
- if (events.length === 0 && dropped.length === 0) {
206
+ if (events.length === 0 && declined.length === 0) {
207
207
  return [{ platform: this.id, action: "skip", path, detail: "no hooks declared" }];
208
208
  }
209
209
  const cfg = this.readJson(path) ?? {};
@@ -212,10 +212,10 @@ var CrushAdapter = class extends BaseAdapter {
212
212
  const hooks = cfg.hooks ??= {};
213
213
  const changes = [];
214
214
  let mutated = false;
215
- for (const event of dropped) {
215
+ for (const { event, action } of declined) {
216
216
  changes.push({
217
217
  platform: this.id,
218
- action: "warn",
218
+ action,
219
219
  path,
220
220
  detail: `${event} has no Crush hook equivalent \u2014 skipped`
221
221
  });
@@ -292,10 +292,20 @@ var CrushAdapter = class extends BaseAdapter {
292
292
  if (ctx.connector.platforms[HOST]?.hooks === false) return [];
293
293
  return CRUSH_HOOK_EVENTS.filter((e) => ctx.connector.hookEvents.includes(e));
294
294
  }
295
- /** Declared events Crush has no analog for — install reports a warn-skip. */
296
- warnSkipHookEvents(ctx) {
295
+ /**
296
+ * Every declared event Crush has NO native equivalent for, tagged with the
297
+ * severity install reports it at — so a host that cannot fire an event is
298
+ * NEVER silent. The 4 newer E1 events ({@link WARN_SKIP_EVENTS}) keep `warn`
299
+ * (exit-1, the established convention); every other unsupported event (the
300
+ * legacy SessionStart / Stop / … that used to vanish) reports a visible
301
+ * `skip` (counted, but exit-0-preserving).
302
+ */
303
+ declinedHookEvents(ctx) {
297
304
  if (ctx.connector.platforms[HOST]?.hooks === false) return [];
298
- return ctx.connector.hookEvents.filter((e) => WARN_SKIP_EVENTS.has(e));
305
+ return ctx.connector.hookEvents.filter((e) => !CRUSH_HOOK_EVENTS.includes(e)).map((event) => ({
306
+ event,
307
+ action: WARN_SKIP_EVENTS.has(event) ? "warn" : "skip"
308
+ }));
299
309
  }
300
310
  /**
301
311
  * Does this hook entry belong to this connector? Anchored on the home-bin +
@@ -485,4 +495,4 @@ export {
485
495
  adapter,
486
496
  crush_default as default
487
497
  };
488
- //# sourceMappingURL=crush-PP4HYZLT.js.map
498
+ //# sourceMappingURL=crush-JTWTZIPB.js.map