@ken-jo/agent-connector 0.4.97 → 0.4.98
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.
- package/README.md +1 -1
- package/dist/{action-IPFDPOZU.js → action-5JM23CFJ.js} +10 -10
- package/dist/action-5JM23CFJ.js.map +1 -0
- package/dist/{amazon-q-IT44LEWV.js → amazon-q-LFZNGN27.js} +3 -3
- package/dist/{amp-P35FRU2Z.js → amp-S22XTPEQ.js} +3 -3
- package/dist/{antigravity-TWIWXTQH.js → antigravity-PZXYAO3X.js} +4 -4
- package/dist/{antigravity-cli-MPE27LPI.js → antigravity-cli-PN474FXM.js} +4 -4
- package/dist/{audit-3E5JAOP2.js → audit-2H7E3Z4N.js} +5 -5
- package/dist/{chunk-L2C5UMKW.js → chunk-6XWORQM6.js} +4 -4
- package/dist/{chunk-FHYR5Q5T.js → chunk-7VSZXOXJ.js} +7 -7
- package/dist/{chunk-FHYR5Q5T.js.map → chunk-7VSZXOXJ.js.map} +1 -1
- package/dist/{chunk-GZZCHJDP.js → chunk-B6PKHS5I.js} +2 -2
- package/dist/{chunk-3EP5V2F4.js → chunk-DOPFBUCX.js} +2 -2
- package/dist/{chunk-GCPEPUD7.js → chunk-DWZ5IWF4.js} +3 -3
- package/dist/{chunk-XVEJAFKW.js → chunk-FJ6F5U3W.js} +3 -3
- package/dist/{chunk-N4ENLZEU.js → chunk-HATCOSQT.js} +19 -19
- package/dist/{chunk-WPTNMYYM.js → chunk-KTBAB556.js} +6 -6
- package/dist/{chunk-WPTNMYYM.js.map → chunk-KTBAB556.js.map} +1 -1
- package/dist/{chunk-7ZFK2WEO.js → chunk-KWC5DQ5Z.js} +2 -2
- package/dist/{chunk-TGZFDXNH.js → chunk-LD5HAN6O.js} +3 -3
- package/dist/{chunk-LQ55E7QI.js → chunk-LZL2YITN.js} +5 -5
- package/dist/{chunk-SLJI5BOM.js → chunk-RNVIK5YJ.js} +2 -2
- package/dist/{chunk-C63AAXK7.js → chunk-RPWD5H6Y.js} +3 -3
- package/dist/{chunk-MLU7NDAZ.js → chunk-S25MVWBP.js} +6 -6
- package/dist/chunk-S25MVWBP.js.map +1 -0
- package/dist/{chunk-NDMNMAKP.js → chunk-TOSNS2BY.js} +43 -43
- package/dist/{chunk-3FINQ2ZF.js → chunk-UNU2KPYJ.js} +9 -7
- package/dist/chunk-UNU2KPYJ.js.map +1 -0
- package/dist/{chunk-Y3K6KJMS.js → chunk-W7AGWAMH.js} +1 -1
- package/dist/chunk-W7AGWAMH.js.map +1 -0
- package/dist/{claude-code-QBWDT5RT.js → claude-code-TA53454O.js} +8 -8
- package/dist/claude-code-TA53454O.js.map +1 -0
- package/dist/cli/sdk.js +4 -4
- package/dist/cli.js +1 -1
- package/dist/{cline-JKEAYWVR.js → cline-GZFN32BM.js} +3 -3
- package/dist/{codebuddy-EB6EYPC3.js → codebuddy-IYS3TQZ3.js} +3 -3
- package/dist/{codebuff-5RSXFU6G.js → codebuff-D3MIKJHC.js} +3 -3
- package/dist/{codex-ART46CDD.js → codex-ZKLP5IXZ.js} +3 -3
- package/dist/{continue-JHZCMSPH.js → continue-I34FNSTJ.js} +3 -3
- package/dist/{copilot-cli-QVAU5CFM.js → copilot-cli-NWPM5GE6.js} +3 -3
- package/dist/{crush-7TORBYUL.js → crush-MDGPZSZU.js} +3 -3
- package/dist/{cursor-W7I4QUFO.js → cursor-JRVK56QA.js} +4 -4
- package/dist/{define-connector-DTWb46UB.d.ts → define-connector-B7tLHVnx.d.ts} +1 -1
- package/dist/{detect-JHSA3G3U.js → detect-FKJC36P4.js} +4 -4
- package/dist/{devin-SSR7S4WX.js → devin-TZMRC57O.js} +3 -3
- package/dist/{doctor-CQJ7TZPA.js → doctor-PGVYUQYG.js} +15 -15
- package/dist/{droid-45PJ7JGF.js → droid-SCFWDJR4.js} +3 -3
- package/dist/{gemini-cli-24PFDK7D.js → gemini-cli-MLDGOR2L.js} +3 -3
- package/dist/{goose-U5D3LCPC.js → goose-5DBHDSJW.js} +3 -3
- package/dist/{grok-cli-L2MHAPBY.js → grok-cli-LX6Q6RUY.js} +3 -3
- package/dist/{hermes-2S5JUTTJ.js → hermes-LJB3SJKB.js} +3 -3
- package/dist/{hook-VHICXHXL.js → hook-PVGBQUQI.js} +10 -10
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/{install-WLENR4KF.js → install-HPDIK7F6.js} +12 -12
- package/dist/{introspect-dNekqPDY.d.ts → introspect-DWCu0Krk.d.ts} +1 -1
- package/dist/{jetbrains-copilot-Z4FC3RM3.js → jetbrains-copilot-2DSVAJMJ.js} +3 -3
- package/dist/{junie-ULGJJIHB.js → junie-GUBDRADP.js} +3 -3
- package/dist/{kilo-WWIJOVWD.js → kilo-HRLWMENX.js} +3 -3
- package/dist/{kilo-cli-QKE2EQLS.js → kilo-cli-IQMFMYZF.js} +3 -3
- package/dist/{kimi-JMUFTVSF.js → kimi-EPD46UJK.js} +3 -3
- package/dist/{kiro-UWUCRKR3.js → kiro-A7DL52FX.js} +3 -3
- package/dist/{leaderboard-NJWKGMXP.js → leaderboard-KCT7XPCI.js} +2 -2
- package/dist/{mimo-code-BPNYYIVM.js → mimo-code-NDGLBXNC.js} +3 -3
- package/dist/{mistral-vibe-LT3DAJ3L.js → mistral-vibe-LLWASF5X.js} +3 -3
- package/dist/{mux-AHNUAY5Z.js → mux-ON4QK3OC.js} +3 -3
- package/dist/{nemoclaw-RE5RZASZ.js → nemoclaw-45R5MFBF.js} +4 -4
- package/dist/{omp-D2EXEPH7.js → omp-ROCTFV3A.js} +3 -3
- package/dist/{open-interpreter-SSGBEUKX.js → open-interpreter-V6CN542J.js} +3 -3
- package/dist/{openclaw-IJ33K45M.js → openclaw-AOKFJGRQ.js} +4 -4
- package/dist/{opencode-YKUKZY3J.js → opencode-YYWQ45LF.js} +3 -3
- package/dist/{openhands-SEZMCUC3.js → openhands-OFFMWCQW.js} +3 -3
- package/dist/{package-JECVQEFT.js → package-TALOSRQ4.js} +9 -9
- package/dist/{pi-YPYV2ULH.js → pi-4W74ETTI.js} +3 -3
- package/dist/{qwen-code-ZHCLCYMC.js → qwen-code-JOBFNEVT.js} +10 -10
- package/dist/qwen-code-JOBFNEVT.js.map +1 -0
- package/dist/{roo-code-7F4HYB34.js → roo-code-RHIGJZNY.js} +3 -3
- package/dist/runtime/index.d.ts +9 -8
- package/dist/runtime/index.js +8 -8
- package/dist/sdk/index.d.ts +4 -4
- package/dist/sdk/index.js +3 -3
- package/dist/sdk/test.d.ts +2 -2
- package/dist/sdk/test.js +6 -6
- package/dist/{serve-LYSBH43G.js → serve-4TEHK726.js} +10 -10
- package/dist/{status-PHKKGEW5.js → status-DVD4EHMX.js} +6 -6
- package/dist/{statusline-ZDD4OZ4F.js → statusline-ZVNH7XBK.js} +9 -9
- package/dist/{telemetry-HDGMI2BK.js → telemetry-NWUJPIK3.js} +5 -5
- package/dist/{trae-Y67HSDOW.js → trae-TLAFSQRQ.js} +3 -3
- package/dist/{types-JyhpJHJa.d.ts → types-C6j18a6R.d.ts} +13 -14
- package/dist/{uninstall-RWO2GM2I.js → uninstall-DZVFV7KE.js} +12 -12
- package/dist/{upgrade-YJCXNUEE.js → upgrade-OUE4ED52.js} +12 -12
- package/dist/{usage-IWO4RQN6.js → usage-NT3ZXALZ.js} +2 -2
- package/dist/{usage-event-AFFKCLHE.js → usage-event-IELZE6WO.js} +9 -9
- package/dist/{vscode-copilot-5CI5B3X6.js → vscode-copilot-VZ5XYSTK.js} +3 -3
- package/dist/{warp-INAKVGBV.js → warp-P2HWXIKT.js} +3 -3
- package/dist/{windsurf-4HM57QAY.js → windsurf-3JC73GZK.js} +3 -3
- package/dist/{zed-YN5X37PQ.js → zed-6CMUKXLI.js} +3 -3
- package/package.json +1 -1
- package/dist/action-IPFDPOZU.js.map +0 -1
- package/dist/chunk-3FINQ2ZF.js.map +0 -1
- package/dist/chunk-MLU7NDAZ.js.map +0 -1
- package/dist/chunk-Y3K6KJMS.js.map +0 -1
- package/dist/claude-code-QBWDT5RT.js.map +0 -1
- package/dist/qwen-code-ZHCLCYMC.js.map +0 -1
- /package/dist/{amazon-q-IT44LEWV.js.map → amazon-q-LFZNGN27.js.map} +0 -0
- /package/dist/{amp-P35FRU2Z.js.map → amp-S22XTPEQ.js.map} +0 -0
- /package/dist/{antigravity-TWIWXTQH.js.map → antigravity-PZXYAO3X.js.map} +0 -0
- /package/dist/{antigravity-cli-MPE27LPI.js.map → antigravity-cli-PN474FXM.js.map} +0 -0
- /package/dist/{audit-3E5JAOP2.js.map → audit-2H7E3Z4N.js.map} +0 -0
- /package/dist/{chunk-L2C5UMKW.js.map → chunk-6XWORQM6.js.map} +0 -0
- /package/dist/{chunk-GZZCHJDP.js.map → chunk-B6PKHS5I.js.map} +0 -0
- /package/dist/{chunk-3EP5V2F4.js.map → chunk-DOPFBUCX.js.map} +0 -0
- /package/dist/{chunk-GCPEPUD7.js.map → chunk-DWZ5IWF4.js.map} +0 -0
- /package/dist/{chunk-XVEJAFKW.js.map → chunk-FJ6F5U3W.js.map} +0 -0
- /package/dist/{chunk-N4ENLZEU.js.map → chunk-HATCOSQT.js.map} +0 -0
- /package/dist/{chunk-7ZFK2WEO.js.map → chunk-KWC5DQ5Z.js.map} +0 -0
- /package/dist/{chunk-TGZFDXNH.js.map → chunk-LD5HAN6O.js.map} +0 -0
- /package/dist/{chunk-LQ55E7QI.js.map → chunk-LZL2YITN.js.map} +0 -0
- /package/dist/{chunk-SLJI5BOM.js.map → chunk-RNVIK5YJ.js.map} +0 -0
- /package/dist/{chunk-C63AAXK7.js.map → chunk-RPWD5H6Y.js.map} +0 -0
- /package/dist/{chunk-NDMNMAKP.js.map → chunk-TOSNS2BY.js.map} +0 -0
- /package/dist/{cline-JKEAYWVR.js.map → cline-GZFN32BM.js.map} +0 -0
- /package/dist/{codebuddy-EB6EYPC3.js.map → codebuddy-IYS3TQZ3.js.map} +0 -0
- /package/dist/{codebuff-5RSXFU6G.js.map → codebuff-D3MIKJHC.js.map} +0 -0
- /package/dist/{codex-ART46CDD.js.map → codex-ZKLP5IXZ.js.map} +0 -0
- /package/dist/{continue-JHZCMSPH.js.map → continue-I34FNSTJ.js.map} +0 -0
- /package/dist/{copilot-cli-QVAU5CFM.js.map → copilot-cli-NWPM5GE6.js.map} +0 -0
- /package/dist/{crush-7TORBYUL.js.map → crush-MDGPZSZU.js.map} +0 -0
- /package/dist/{cursor-W7I4QUFO.js.map → cursor-JRVK56QA.js.map} +0 -0
- /package/dist/{detect-JHSA3G3U.js.map → detect-FKJC36P4.js.map} +0 -0
- /package/dist/{devin-SSR7S4WX.js.map → devin-TZMRC57O.js.map} +0 -0
- /package/dist/{doctor-CQJ7TZPA.js.map → doctor-PGVYUQYG.js.map} +0 -0
- /package/dist/{droid-45PJ7JGF.js.map → droid-SCFWDJR4.js.map} +0 -0
- /package/dist/{gemini-cli-24PFDK7D.js.map → gemini-cli-MLDGOR2L.js.map} +0 -0
- /package/dist/{goose-U5D3LCPC.js.map → goose-5DBHDSJW.js.map} +0 -0
- /package/dist/{grok-cli-L2MHAPBY.js.map → grok-cli-LX6Q6RUY.js.map} +0 -0
- /package/dist/{hermes-2S5JUTTJ.js.map → hermes-LJB3SJKB.js.map} +0 -0
- /package/dist/{hook-VHICXHXL.js.map → hook-PVGBQUQI.js.map} +0 -0
- /package/dist/{install-WLENR4KF.js.map → install-HPDIK7F6.js.map} +0 -0
- /package/dist/{jetbrains-copilot-Z4FC3RM3.js.map → jetbrains-copilot-2DSVAJMJ.js.map} +0 -0
- /package/dist/{junie-ULGJJIHB.js.map → junie-GUBDRADP.js.map} +0 -0
- /package/dist/{kilo-WWIJOVWD.js.map → kilo-HRLWMENX.js.map} +0 -0
- /package/dist/{kilo-cli-QKE2EQLS.js.map → kilo-cli-IQMFMYZF.js.map} +0 -0
- /package/dist/{kimi-JMUFTVSF.js.map → kimi-EPD46UJK.js.map} +0 -0
- /package/dist/{kiro-UWUCRKR3.js.map → kiro-A7DL52FX.js.map} +0 -0
- /package/dist/{leaderboard-NJWKGMXP.js.map → leaderboard-KCT7XPCI.js.map} +0 -0
- /package/dist/{mimo-code-BPNYYIVM.js.map → mimo-code-NDGLBXNC.js.map} +0 -0
- /package/dist/{mistral-vibe-LT3DAJ3L.js.map → mistral-vibe-LLWASF5X.js.map} +0 -0
- /package/dist/{mux-AHNUAY5Z.js.map → mux-ON4QK3OC.js.map} +0 -0
- /package/dist/{nemoclaw-RE5RZASZ.js.map → nemoclaw-45R5MFBF.js.map} +0 -0
- /package/dist/{omp-D2EXEPH7.js.map → omp-ROCTFV3A.js.map} +0 -0
- /package/dist/{open-interpreter-SSGBEUKX.js.map → open-interpreter-V6CN542J.js.map} +0 -0
- /package/dist/{openclaw-IJ33K45M.js.map → openclaw-AOKFJGRQ.js.map} +0 -0
- /package/dist/{opencode-YKUKZY3J.js.map → opencode-YYWQ45LF.js.map} +0 -0
- /package/dist/{openhands-SEZMCUC3.js.map → openhands-OFFMWCQW.js.map} +0 -0
- /package/dist/{package-JECVQEFT.js.map → package-TALOSRQ4.js.map} +0 -0
- /package/dist/{pi-YPYV2ULH.js.map → pi-4W74ETTI.js.map} +0 -0
- /package/dist/{roo-code-7F4HYB34.js.map → roo-code-RHIGJZNY.js.map} +0 -0
- /package/dist/{serve-LYSBH43G.js.map → serve-4TEHK726.js.map} +0 -0
- /package/dist/{status-PHKKGEW5.js.map → status-DVD4EHMX.js.map} +0 -0
- /package/dist/{statusline-ZDD4OZ4F.js.map → statusline-ZVNH7XBK.js.map} +0 -0
- /package/dist/{telemetry-HDGMI2BK.js.map → telemetry-NWUJPIK3.js.map} +0 -0
- /package/dist/{trae-Y67HSDOW.js.map → trae-TLAFSQRQ.js.map} +0 -0
- /package/dist/{uninstall-RWO2GM2I.js.map → uninstall-DZVFV7KE.js.map} +0 -0
- /package/dist/{upgrade-YJCXNUEE.js.map → upgrade-OUE4ED52.js.map} +0 -0
- /package/dist/{usage-IWO4RQN6.js.map → usage-NT3ZXALZ.js.map} +0 -0
- /package/dist/{usage-event-AFFKCLHE.js.map → usage-event-IELZE6WO.js.map} +0 -0
- /package/dist/{vscode-copilot-5CI5B3X6.js.map → vscode-copilot-VZ5XYSTK.js.map} +0 -0
- /package/dist/{warp-INAKVGBV.js.map → warp-P2HWXIKT.js.map} +0 -0
- /package/dist/{windsurf-4HM57QAY.js.map → windsurf-3JC73GZK.js.map} +0 -0
- /package/dist/{zed-YN5X37PQ.js.map → zed-6CMUKXLI.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/spawn.ts"],"sourcesContent":["/**\r\n * core/spawn — cross-platform command construction.\r\n *\r\n * Borrowed from context-mode (issues #369/#372/#548/#738): bare `node` is\r\n * unreliable on Windows Git Bash (MSYS) and MSYS rewrites absolute paths on\r\n * non-C: drives. Always use the resolved runtime path, forward slashes, and\r\n * double-quoting. No-ops on macOS/Linux.\r\n */\r\n\r\nimport { existsSync } from \"node:fs\";\r\nimport { join } from \"node:path\";\r\n\r\nimport { isNonDefaultDataRoot } from \"./paths.js\";\r\nimport type { InstallScope, PlatformId, ServerDef } from \"./types.js\";\r\nimport type { InstallContext } from \"../adapters/spi.js\";\r\nimport type {\r\n LaunchMethod,\r\n TelemetryInstallScope,\r\n} from \"../telemetry/types.js\";\r\n\r\n/**\r\n * Narrow the framework's 5-value {@link InstallScope} down to the two telemetry\r\n * slicing buckets: only a `project`-local install is `project`; everything else\r\n * (system/user/profile/managed) is global and reads as `user`.\r\n */\r\nexport function narrowInstallScope(scope: InstallScope): TelemetryInstallScope {\r\n return scope === \"project\" ? \"project\" : \"user\";\r\n}\r\n\r\n/** Build `\"<nodePath>\" \"<scriptPath>\"`. */\r\nexport function buildNodeCommand(\r\n scriptPath: string,\r\n opts?: { nodePath?: string },\r\n): string {\r\n const nodePath = (opts?.nodePath ?? process.execPath).replace(/\\\\/g, \"/\");\r\n const safe = scriptPath.replace(/\\\\/g, \"/\");\r\n return `\"${nodePath}\" \"${safe}\"`;\r\n}\r\n\r\n/**\r\n * Strict inverse of buildNodeCommand. Returns the two quoted tokens, or null if\r\n * `cmd` was not produced by buildNodeCommand (no fragile last-whitespace tail\r\n * grabbing — that was the #548 doubled-path bug when paths contained spaces).\r\n */\r\nexport function parseNodeCommand(\r\n cmd: string,\r\n): { nodePath: string; scriptPath: string } | null {\r\n if (typeof cmd !== \"string\" || cmd.length === 0) return null;\r\n const m = cmd.match(/^\"([^\"]+)\"\\s+\"([^\"]+)\"\\s*$/);\r\n if (!m || !m[1] || !m[2]) return null;\r\n return { nodePath: m[1], scriptPath: m[2] };\r\n}\r\n\r\n/** Quote a single argument for inclusion in a host hook command string. */\r\nexport function quoteArg(arg: string): string {\r\n return `\"${arg.replace(/\\\\/g, \"/\")}\"`;\r\n}\r\n\r\n/**\r\n * True when `hay` (slash-normalized) has the quoted home-bin path IMMEDIATELY\r\n * followed by `verb` — i.e. the verb sits in its command SLOT (right after the\r\n * home binary), not merely somewhere in the argument list. This distinguishes\r\n * `\"<bin>\" statusline …` from `\"<bin>\" action … statusline …`: the action verb\r\n * takes a free-form `actionId` positional that can legitimately equal another\r\n * verb's name (`statusline` / `usage-event` / `hook`), and only the SLOT\r\n * position identifies the real verb. `homeBinNorm` is the slash-normalized\r\n * home-bin path the caller already derived.\r\n */\r\nfunction hasVerbSlot(hay: string, homeBinNorm: string, verb: string): boolean {\r\n return hay.includes(`\"${homeBinNorm}\" ${verb} `);\r\n}\r\n\r\n/**\r\n * Build the universal hook command a host config points at:\r\n * \"<homeBin>\" hook <platformId> <event> --connector <id>\r\n * Pointing every host at the one stable home binary is how a single update\r\n * propagates everywhere (docs/ARCHITECTURE.md §3 R1).\r\n */\r\nexport function buildHomeBinHookCommand(\r\n homeBinPath: string,\r\n platformId: string,\r\n event: string,\r\n connectorId: string,\r\n): string {\r\n return `${quoteArg(homeBinPath)} hook ${platformId} ${event} --connector ${connectorId}`;\r\n}\r\n\r\n/**\r\n * True when `command` is a home-bin hook command for exactly `connectorId`.\r\n *\r\n * Critical: the connector id is the LAST token of the hook command\r\n * (`... --connector <id>`), so a naive `command.includes(\"--connector \" + id)`\r\n * collides on shared-prefix ids — `--connector acme-db` contains\r\n * `--connector acme`, which would let uninstalling `acme` strip `acme-db`'s\r\n * hooks. We anchor the id token: the character after it must be end-of-string,\r\n * whitespace, or a closing double-quote (the JSON-embedded case). Connector ids\r\n * are kebab-case (ID_RE) so they never contain whitespace or quotes themselves.\r\n */\r\nexport function isHomeBinHookCommand(\r\n command: string | undefined,\r\n homeBinPath: string,\r\n connectorId: string,\r\n): boolean {\r\n if (!command) return false;\r\n // The stored command was forward-slashed by quoteArg(); homeBinPath() yields\r\n // NATIVE (back)slashes on Windows (node:path join). Normalize BOTH sides so the\r\n // ownership substring test holds on win32 (without this, detection always\r\n // returns false there → duplicate hooks on re-install + orphans on uninstall).\r\n // No-op on POSIX.\r\n const hay = command.replace(/\\\\/g, \"/\");\r\n if (!hay.includes(homeBinPath.replace(/\\\\/g, \"/\"))) return false;\r\n const token = `--connector ${connectorId}`;\r\n let from = 0;\r\n for (;;) {\r\n const idx = hay.indexOf(token, from);\r\n if (idx < 0) return false;\r\n const after = hay.charAt(idx + token.length);\r\n if (after === \"\" || after === '\"' || /\\s/.test(after)) return true;\r\n from = idx + token.length;\r\n }\r\n}\r\n\r\n/**\r\n * Build the OPT-IN host-native usage-event command an AfterModel / PostInvocation\r\n * hook points at:\r\n * \"<homeBin>\" usage-event <platformId> --connector <id>\r\n * Mirrors {@link buildHomeBinHookCommand} (same anchoring rules apply) but routes\r\n * to the hidden `usage-event` entrypoint, which records a DISTINCT `model_turn`\r\n * row instead of dispatching a connector handler.\r\n */\r\nexport function buildUsageEventCommand(\r\n homeBinPath: string,\r\n platformId: string,\r\n connectorId: string,\r\n): string {\r\n return `${quoteArg(homeBinPath)} usage-event ${platformId} --connector ${connectorId}`;\r\n}\r\n\r\n/**\r\n * True when `command` is OUR host-native usage-event command for exactly\r\n * `connectorId`. Same end-of-token anchoring as {@link isHomeBinHookCommand} so a\r\n * shared-prefix id can't collide; additionally requires the ` usage-event ` verb\r\n * so it is never confused with a plain `hook` command during uninstall.\r\n */\r\nexport function isUsageEventCommand(\r\n command: string | undefined,\r\n homeBinPath: string,\r\n connectorId: string,\r\n): boolean {\r\n if (!command) return false;\r\n // Normalize separators like isHomeBinHookCommand (win32 ownership detection).\r\n const hay = command.replace(/\\\\/g, \"/\");\r\n const homeBinNorm = homeBinPath.replace(/\\\\/g, \"/\");\r\n if (!hay.includes(homeBinNorm)) return false;\r\n if (!hasVerbSlot(hay, homeBinNorm, \"usage-event\")) return false;\r\n return isHomeBinHookCommand(command, homeBinPath, connectorId);\r\n}\r\n\r\n/**\r\n * Build the home-bin statusline command a host's status line config points at:\r\n * \"<homeBin>\" statusline <platformId> --connector <id>\r\n * Mirrors {@link buildHomeBinHookCommand} / {@link buildUsageEventCommand} (the\r\n * same single-home-binary indirection) but routes to the `statusline`\r\n * entrypoint, which renders the connector's HUD line for the host.\r\n */\r\nexport function buildHomeBinStatuslineCommand(\r\n homeBinPath: string,\r\n platformId: string,\r\n connectorId: string,\r\n): string {\r\n return `${quoteArg(homeBinPath)} statusline ${platformId} --connector ${connectorId}`;\r\n}\r\n\r\n/**\r\n * True when `command` is OUR home-bin statusline command for exactly\r\n * `connectorId`. Same end-of-token anchoring as {@link isHomeBinHookCommand} so a\r\n * shared-prefix id can't collide; additionally requires the ` statusline ` verb\r\n * so it is never confused with a plain `hook` / `usage-event` command.\r\n */\r\nexport function isHomeBinStatuslineCommand(\r\n command: string | undefined,\r\n homeBinPath: string,\r\n connectorId: string,\r\n): boolean {\r\n if (!command) return false;\r\n // Normalize separators like isHomeBinHookCommand (win32 ownership detection).\r\n const hay = command.replace(/\\\\/g, \"/\");\r\n const homeBinNorm = homeBinPath.replace(/\\\\/g, \"/\");\r\n if (!hay.includes(homeBinNorm)) return false;\r\n if (!hasVerbSlot(hay, homeBinNorm, \"statusline\")) return false;\r\n return isHomeBinHookCommand(command, homeBinPath, connectorId);\r\n}\r\n\r\n/**\r\n * Build the home-bin action command a future host affordance (slash command /\r\n * keybinding) points at:\r\n * \"<homeBin>\" action <platformId> <actionId> --connector <id>\r\n * Mirrors {@link buildHomeBinStatuslineCommand} (the same single-home-binary\r\n * indirection) but routes to the `action` entrypoint, which re-imports the\r\n * connector and runs the named action's run(ctx). v1 ships only this command\r\n * builder + the runtime verb; no adapter EMITS the affordance yet.\r\n */\r\nexport function buildHomeBinActionCommand(\r\n homeBinPath: string,\r\n platformId: string,\r\n actionId: string,\r\n connectorId: string,\r\n): string {\r\n return `${quoteArg(homeBinPath)} action ${platformId} ${actionId} --connector ${connectorId}`;\r\n}\r\n\r\n/**\r\n * True when `command` is OUR home-bin action command for exactly `connectorId`.\r\n * Same end-of-token anchoring as {@link isHomeBinHookCommand} so a shared-prefix\r\n * id can't collide; additionally requires the ` action ` verb so it is never\r\n * confused with a plain `hook` / `usage-event` / `statusline` command.\r\n */\r\nexport function isHomeBinActionCommand(\r\n command: string | undefined,\r\n homeBinPath: string,\r\n connectorId: string,\r\n): boolean {\r\n if (!command) return false;\r\n // Normalize separators like isHomeBinHookCommand (win32 ownership detection).\r\n const hay = command.replace(/\\\\/g, \"/\");\r\n const homeBinNorm = homeBinPath.replace(/\\\\/g, \"/\");\r\n if (!hay.includes(homeBinNorm)) return false;\r\n if (!hasVerbSlot(hay, homeBinNorm, \"action\")) return false;\r\n return isHomeBinHookCommand(command, homeBinPath, connectorId);\r\n}\r\n\r\n/**\r\n * Single source of truth for \"is OPT-IN host-native turn-usage capture enabled\r\n * for this connector?\" — read by the Gemini / Antigravity adapters at install\r\n * time to decide whether to ALSO write the AfterModel / PostInvocation usage hook.\r\n * Enabled when the connector opts in via telemetry.hostNativeUsage OR when the\r\n * install-time env switch AGENT_CONNECTOR_HOST_NATIVE=1 forces it on. Off by\r\n * default (privacy: host-native capture is never installed silently).\r\n */\r\nexport function isHostNativeUsageEnabled(\r\n telemetry: { enabled: boolean; hostNativeUsage?: boolean },\r\n env: NodeJS.ProcessEnv = process.env,\r\n): boolean {\r\n if (telemetry.enabled !== true) return false;\r\n if (env.AGENT_CONNECTOR_HOST_NATIVE === \"1\") return true;\r\n return telemetry.hostNativeUsage === true;\r\n}\r\n\r\n/**\r\n * Single source of truth for \"should this server be wrapped by `serve` for\r\n * telemetry?\" — so every adapter behaves identically even for a server that\r\n * skipped normalizeServer (e.g. a per-platform override). On by default for an\r\n * stdio server with a command, unless explicitly disabled or telemetry is off.\r\n */\r\nexport function shouldWrapForTelemetry(\r\n server: ServerDef,\r\n telemetry: { enabled: boolean },\r\n): boolean {\r\n return (\r\n server.wrapForTelemetry !== false &&\r\n telemetry.enabled === true &&\r\n server.transport === \"stdio\" &&\r\n typeof server.command === \"string\" &&\r\n server.command !== \"\"\r\n );\r\n}\r\n\r\n/**\r\n * Build the telemetry-wrapping server command:\r\n * \"<homeBin>\" serve --connector <id> --scope <scope> --host <platformId> -- <realCommand> <realArgs...>\r\n * Used when a stdio server opts into transparent telemetry capture.\r\n *\r\n * `scope` records the install dimension (global user vs project-local) on every\r\n * telemetry row so usage can be sliced by it later. It is OPTIONAL for backward\r\n * compatibility: when omitted, the `--scope` flag is not emitted and the runtime\r\n * treats the scope as \"unknown\".\r\n *\r\n * `platformId` bakes the install TARGET platform into the wrapper so the proxy\r\n * stamps `hostPlatform` correctly even under a headless spawn where runtime env\r\n * markers are absent (detectRuntimeHost only knows claude-code/cursor/codex and\r\n * otherwise mis-attributes). Emitted as `--host <platformId>` in the FLAG\r\n * section (before `--`). It is OPTIONAL + backward-compatible: when omitted the\r\n * `--host` flag is not emitted and the runtime falls back to env detection.\r\n *\r\n * `dataDir` pins the framework data-root the spawned `serve` child must use to\r\n * resolve the connector record (and write telemetry). Emitted as `--data-dir\r\n * <path>` in the FLAG section. It exists because some hosts (codex strips the\r\n * MCP child's environment) do NOT propagate `AGENT_CONNECTOR_DATA_DIR` to the\r\n * spawned server — so a child that relied on inheriting it would resolve the\r\n * DEFAULT `~/.agent-connector` and die with \"Connector not registered\" when the\r\n * install wrote the record under an OVERRIDDEN root. Passing it explicitly makes\r\n * the wrap env-independent for any env-stripping host. OPTIONAL + backward-\r\n * compatible: callers pass it only for a non-default root (a default-root install\r\n * stays flag-free and relies on the correct fallback), and when omitted the\r\n * `--data-dir` flag is not emitted and the runtime resolves the data-root the\r\n * usual way.\r\n */\r\nexport function buildServeWrapperCommand(\r\n homeBinPath: string,\r\n connectorId: string,\r\n realCommand: string,\r\n realArgs: string[],\r\n scope?: InstallScope,\r\n platformId?: PlatformId,\r\n dataDir?: string,\r\n): { command: string; args: string[] } {\r\n const flags = [\"serve\", \"--connector\", connectorId];\r\n if (scope !== undefined) flags.push(\"--scope\", narrowInstallScope(scope));\r\n if (platformId !== undefined) flags.push(\"--host\", platformId);\r\n if (dataDir !== undefined && dataDir !== \"\") flags.push(\"--data-dir\", dataDir);\r\n return {\r\n command: homeBinPath,\r\n args: [...flags, \"--\", realCommand, ...realArgs],\r\n };\r\n}\r\n\r\n/**\r\n * Telemetry serve-wrap for a stdio command: when the connector opts in, route\r\n * `command`/`args` through `<homeBin> serve --connector <id> -- …`; otherwise\r\n * return them unchanged. Consolidates the per-host wrap snippet — the caller\r\n * keeps its own command/args seeding + downstream env-resolution + entry shaping.\r\n *\r\n * When the install's framework data-root is NON-DEFAULT (overridden via\r\n * AGENT_CONNECTOR_DATA_DIR), the wrap also carries an explicit `--data-dir\r\n * <root>` so the spawned `serve` child resolves the connector record from that\r\n * root even on hosts that strip the child's environment (codex). A default-root\r\n * install emits no flag and relies on the correct runtime fallback.\r\n */\r\nexport function buildWrappedStdio(\r\n ctx: Pick<InstallContext, \"homeBinPath\" | \"connector\" | \"scope\" | \"dataRoot\">,\r\n server: ServerDef,\r\n platformId: PlatformId,\r\n command: string,\r\n args: string[],\r\n): { command: string; args: string[] } {\r\n if (!shouldWrapForTelemetry(server, ctx.connector.telemetry)) {\r\n return { command, args };\r\n }\r\n const dataDir = isNonDefaultDataRoot(ctx.dataRoot) ? ctx.dataRoot : undefined;\r\n return buildServeWrapperCommand(\r\n ctx.homeBinPath,\r\n ctx.connector.id,\r\n command,\r\n args,\r\n ctx.scope,\r\n platformId,\r\n dataDir,\r\n );\r\n}\r\n\r\n/** Injectable deps for {@link resolveSpawnCommand} (so the win32 branch is unit-testable on POSIX). */\r\nexport interface SpawnResolveDeps {\r\n platform?: NodeJS.Platform;\r\n /** PATH value (`;`-separated on Windows). */\r\n pathEnv?: string;\r\n /** PATHEXT value (`;`-separated). */\r\n pathExt?: string;\r\n /** File-existence probe (defaults to fs.existsSync). */\r\n exists?: (p: string) => boolean;\r\n}\r\n\r\n/** How a child command should be handed to spawn() on this platform. */\r\nexport interface SpawnResolution {\r\n /** The command to pass to spawn() (an absolute path on win32 when resolved). */\r\n file: string;\r\n /**\r\n * Whether spawn() MUST use `shell: true`. On native Windows a `.cmd`/`.bat`\r\n * shim (npx.cmd, pnpm.cmd, the agent-connector.cmd launcher) cannot be run by\r\n * raw CreateProcess — Node throws EINVAL since the 2024 security fix unless a\r\n * shell is used. `.exe` resolves directly with no shell.\r\n */\r\n needsShell: boolean;\r\n}\r\n\r\n/**\r\n * Resolve a child command for spawn() across platforms. NO-OP on macOS/Linux\r\n * (returns the command unchanged, no shell). On native Windows it fixes the two\r\n * spawn failure modes for bare package runners:\r\n * 1. raw CreateProcess ignores PATHEXT, so spawn(\"npx\") → ENOENT even though\r\n * `npx.cmd` is on PATH. We search PATH × PATHEXT and return the resolved\r\n * absolute path.\r\n * 2. a resolved `.cmd`/`.bat` still cannot be launched without a shell, so we\r\n * flag `needsShell` for those (and `.exe`/`.com` run directly).\r\n * A bare name that PATH search misses falls back to `{ file: command,\r\n * needsShell: true }` so cmd.exe's own PATHEXT lookup still finds it.\r\n */\r\nexport function resolveSpawnCommand(\r\n command: string,\r\n deps: SpawnResolveDeps = {},\r\n): SpawnResolution {\r\n const platform = deps.platform ?? process.platform;\r\n if (platform !== \"win32\") return { file: command, needsShell: false };\r\n\r\n const isBatch = (s: string): boolean => /\\.(cmd|bat)$/i.test(s);\r\n\r\n // Already a path or already has an extension → don't search; only decide shell.\r\n if (/[\\\\/]/.test(command) || /\\.[a-z0-9]+$/i.test(command)) {\r\n return { file: command, needsShell: isBatch(command) };\r\n }\r\n\r\n const exists = deps.exists ?? existsSync;\r\n const pathEnv = deps.pathEnv ?? process.env.PATH ?? process.env.Path ?? \"\";\r\n const pathExt = deps.pathExt ?? process.env.PATHEXT ?? \".COM;.EXE;.BAT;.CMD\";\r\n const dirs = pathEnv.split(\";\").filter((d) => d !== \"\");\r\n const exts = pathExt.split(\";\").filter((e) => e !== \"\");\r\n for (const dir of dirs) {\r\n for (const ext of exts) {\r\n const candidate = join(dir, command + ext);\r\n if (exists(candidate)) return { file: candidate, needsShell: isBatch(ext) };\r\n }\r\n }\r\n // Not found on PATH — let cmd.exe resolve it (handles shim dirs we may miss).\r\n return { file: command, needsShell: true };\r\n}\r\n\r\n/** Basenames (case-insensitive, sans common extensions) of the ephemeral package runners. */\r\nconst PACKAGE_RUNNERS: Record<string, Extract<LaunchMethod, \"npx\" | \"bunx\" | \"uvx\">> = {\r\n npx: \"npx\",\r\n bunx: \"bunx\",\r\n uvx: \"uvx\",\r\n};\r\n\r\n/** Basenames of language interpreters that launch a local script. */\r\nconst INTERPRETERS: ReadonlySet<string> = new Set([\"node\", \"bun\", \"deno\"]);\r\n\r\n/**\r\n * Strip a directory prefix and a trailing executable extension to get the bare\r\n * program name. Tolerates both POSIX and Windows separators (the wrapped command\r\n * may be an absolute Windows path) and lowercases for case-insensitive matching.\r\n */\r\nfunction commandBasename(realCommand: string): string {\r\n const noDir = realCommand.replace(/\\\\/g, \"/\").split(\"/\").pop() ?? realCommand;\r\n return noDir.replace(/\\.(exe|cmd|bat|com)$/i, \"\").toLowerCase();\r\n}\r\n\r\n/**\r\n * Classify how the real MCP server is launched, for the \"launch-method\" slicing\r\n * dimension. Package runners (npx/bunx/uvx) and interpreters (node/bun/deno) are\r\n * detected by the command basename. A remote (http) server is not launched\r\n * locally, so the caller — which alone knows the transport — passes\r\n * `isRemote: true` to force \"http\". Anything else resolves to \"binary\".\r\n */\r\nexport function detectLaunchMethod(\r\n realCommand: string,\r\n realArgs: string[],\r\n opts?: { isRemote?: boolean },\r\n): LaunchMethod {\r\n void realArgs; // reserved: args may later refine node-vs-script heuristics\r\n if (opts?.isRemote === true) return \"http\";\r\n if (typeof realCommand !== \"string\" || realCommand.trim() === \"\") {\r\n return \"unknown\";\r\n }\r\n const base = commandBasename(realCommand);\r\n if (base === \"\") return \"unknown\";\r\n const runner = PACKAGE_RUNNERS[base];\r\n if (runner !== undefined) return runner;\r\n if (INTERPRETERS.has(base)) return \"node\";\r\n return \"binary\";\r\n}\r\n"],"mappings":";;;;;;AASA,SAAS,kBAAkB;AAC3B,SAAS,YAAY;AAed,SAAS,mBAAmB,OAA4C;AAC7E,SAAO,UAAU,YAAY,YAAY;AAC3C;AA2BO,SAAS,SAAS,KAAqB;AAC5C,SAAO,IAAI,IAAI,QAAQ,OAAO,GAAG,CAAC;AACpC;AAYA,SAAS,YAAY,KAAa,aAAqB,MAAuB;AAC5E,SAAO,IAAI,SAAS,IAAI,WAAW,KAAK,IAAI,GAAG;AACjD;AAQO,SAAS,wBACd,aACA,YACA,OACA,aACQ;AACR,SAAO,GAAG,SAAS,WAAW,CAAC,SAAS,UAAU,IAAI,KAAK,gBAAgB,WAAW;AACxF;AAaO,SAAS,qBACd,SACA,aACA,aACS;AACT,MAAI,CAAC,QAAS,QAAO;AAMrB,QAAM,MAAM,QAAQ,QAAQ,OAAO,GAAG;AACtC,MAAI,CAAC,IAAI,SAAS,YAAY,QAAQ,OAAO,GAAG,CAAC,EAAG,QAAO;AAC3D,QAAM,QAAQ,eAAe,WAAW;AACxC,MAAI,OAAO;AACX,aAAS;AACP,UAAM,MAAM,IAAI,QAAQ,OAAO,IAAI;AACnC,QAAI,MAAM,EAAG,QAAO;AACpB,UAAM,QAAQ,IAAI,OAAO,MAAM,MAAM,MAAM;AAC3C,QAAI,UAAU,MAAM,UAAU,OAAO,KAAK,KAAK,KAAK,EAAG,QAAO;AAC9D,WAAO,MAAM,MAAM;AAAA,EACrB;AACF;AAUO,SAAS,uBACd,aACA,YACA,aACQ;AACR,SAAO,GAAG,SAAS,WAAW,CAAC,gBAAgB,UAAU,gBAAgB,WAAW;AACtF;AAQO,SAAS,oBACd,SACA,aACA,aACS;AACT,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,MAAM,QAAQ,QAAQ,OAAO,GAAG;AACtC,QAAM,cAAc,YAAY,QAAQ,OAAO,GAAG;AAClD,MAAI,CAAC,IAAI,SAAS,WAAW,EAAG,QAAO;AACvC,MAAI,CAAC,YAAY,KAAK,aAAa,aAAa,EAAG,QAAO;AAC1D,SAAO,qBAAqB,SAAS,aAAa,WAAW;AAC/D;AASO,SAAS,8BACd,aACA,YACA,aACQ;AACR,SAAO,GAAG,SAAS,WAAW,CAAC,eAAe,UAAU,gBAAgB,WAAW;AACrF;AAQO,SAAS,2BACd,SACA,aACA,aACS;AACT,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,MAAM,QAAQ,QAAQ,OAAO,GAAG;AACtC,QAAM,cAAc,YAAY,QAAQ,OAAO,GAAG;AAClD,MAAI,CAAC,IAAI,SAAS,WAAW,EAAG,QAAO;AACvC,MAAI,CAAC,YAAY,KAAK,aAAa,YAAY,EAAG,QAAO;AACzD,SAAO,qBAAqB,SAAS,aAAa,WAAW;AAC/D;AAWO,SAAS,0BACd,aACA,YACA,UACA,aACQ;AACR,SAAO,GAAG,SAAS,WAAW,CAAC,WAAW,UAAU,IAAI,QAAQ,gBAAgB,WAAW;AAC7F;AAQO,SAAS,uBACd,SACA,aACA,aACS;AACT,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,MAAM,QAAQ,QAAQ,OAAO,GAAG;AACtC,QAAM,cAAc,YAAY,QAAQ,OAAO,GAAG;AAClD,MAAI,CAAC,IAAI,SAAS,WAAW,EAAG,QAAO;AACvC,MAAI,CAAC,YAAY,KAAK,aAAa,QAAQ,EAAG,QAAO;AACrD,SAAO,qBAAqB,SAAS,aAAa,WAAW;AAC/D;AAUO,SAAS,yBACd,WACA,MAAyB,QAAQ,KACxB;AACT,MAAI,UAAU,YAAY,KAAM,QAAO;AACvC,MAAI,IAAI,gCAAgC,IAAK,QAAO;AACpD,SAAO,UAAU,oBAAoB;AACvC;AAQO,SAAS,uBACd,QACA,WACS;AACT,SACE,OAAO,qBAAqB,SAC5B,UAAU,YAAY,QACtB,OAAO,cAAc,WACrB,OAAO,OAAO,YAAY,YAC1B,OAAO,YAAY;AAEvB;AAgCO,SAAS,yBACd,aACA,aACA,aACA,UACA,OACA,YACA,SACqC;AACrC,QAAM,QAAQ,CAAC,SAAS,eAAe,WAAW;AAClD,MAAI,UAAU,OAAW,OAAM,KAAK,WAAW,mBAAmB,KAAK,CAAC;AACxE,MAAI,eAAe,OAAW,OAAM,KAAK,UAAU,UAAU;AAC7D,MAAI,YAAY,UAAa,YAAY,GAAI,OAAM,KAAK,cAAc,OAAO;AAC7E,SAAO;AAAA,IACL,SAAS;AAAA,IACT,MAAM,CAAC,GAAG,OAAO,MAAM,aAAa,GAAG,QAAQ;AAAA,EACjD;AACF;AAcO,SAAS,kBACd,KACA,QACA,YACA,SACA,MACqC;AACrC,MAAI,CAAC,uBAAuB,QAAQ,IAAI,UAAU,SAAS,GAAG;AAC5D,WAAO,EAAE,SAAS,KAAK;AAAA,EACzB;AACA,QAAM,UAAU,qBAAqB,IAAI,QAAQ,IAAI,IAAI,WAAW;AACpE,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,IAAI,UAAU;AAAA,IACd;AAAA,IACA;AAAA,IACA,IAAI;AAAA,IACJ;AAAA,IACA;AAAA,EACF;AACF;AAsCO,SAAS,oBACd,SACA,OAAyB,CAAC,GACT;AACjB,QAAM,WAAW,KAAK,YAAY,QAAQ;AAC1C,MAAI,aAAa,QAAS,QAAO,EAAE,MAAM,SAAS,YAAY,MAAM;AAEpE,QAAM,UAAU,CAAC,MAAuB,gBAAgB,KAAK,CAAC;AAG9D,MAAI,QAAQ,KAAK,OAAO,KAAK,gBAAgB,KAAK,OAAO,GAAG;AAC1D,WAAO,EAAE,MAAM,SAAS,YAAY,QAAQ,OAAO,EAAE;AAAA,EACvD;AAEA,QAAM,SAAS,KAAK,UAAU;AAC9B,QAAM,UAAU,KAAK,WAAW,QAAQ,IAAI,QAAQ,QAAQ,IAAI,QAAQ;AACxE,QAAM,UAAU,KAAK,WAAW,QAAQ,IAAI,WAAW;AACvD,QAAM,OAAO,QAAQ,MAAM,GAAG,EAAE,OAAO,CAAC,MAAM,MAAM,EAAE;AACtD,QAAM,OAAO,QAAQ,MAAM,GAAG,EAAE,OAAO,CAAC,MAAM,MAAM,EAAE;AACtD,aAAW,OAAO,MAAM;AACtB,eAAW,OAAO,MAAM;AACtB,YAAM,YAAY,KAAK,KAAK,UAAU,GAAG;AACzC,UAAI,OAAO,SAAS,EAAG,QAAO,EAAE,MAAM,WAAW,YAAY,QAAQ,GAAG,EAAE;AAAA,IAC5E;AAAA,EACF;AAEA,SAAO,EAAE,MAAM,SAAS,YAAY,KAAK;AAC3C;AAGA,IAAM,kBAAiF;AAAA,EACrF,KAAK;AAAA,EACL,MAAM;AAAA,EACN,KAAK;AACP;AAGA,IAAM,eAAoC,oBAAI,IAAI,CAAC,QAAQ,OAAO,MAAM,CAAC;AAOzE,SAAS,gBAAgB,aAA6B;AACpD,QAAM,QAAQ,YAAY,QAAQ,OAAO,GAAG,EAAE,MAAM,GAAG,EAAE,IAAI,KAAK;AAClE,SAAO,MAAM,QAAQ,yBAAyB,EAAE,EAAE,YAAY;AAChE;AASO,SAAS,mBACd,aACA,UACA,MACc;AACd,OAAK;AACL,MAAI,MAAM,aAAa,KAAM,QAAO;AACpC,MAAI,OAAO,gBAAgB,YAAY,YAAY,KAAK,MAAM,IAAI;AAChE,WAAO;AAAA,EACT;AACA,QAAM,OAAO,gBAAgB,WAAW;AACxC,MAAI,SAAS,GAAI,QAAO;AACxB,QAAM,SAAS,gBAAgB,IAAI;AACnC,MAAI,WAAW,OAAW,QAAO;AACjC,MAAI,aAAa,IAAI,IAAI,EAAG,QAAO;AACnC,SAAO;AACT;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapters/claude-code/index.ts"],"sourcesContent":["/**\r\n * adapters/claude-code — Claude Code platform adapter for agent-connector.\r\n *\r\n * Generalized from context-mode's proven 15-platform Claude adapter: the served\r\n * identity is now `ctx.connector` (not a hardcoded \"context-mode\"), and every\r\n * hook command points at the single stable home binary\r\n * (`buildHomeBinHookCommand`) so one framework update propagates everywhere.\r\n *\r\n * Claude Code is a json-stdio host:\r\n * - MCP servers: user scope → ~/.claude.json (\"mcpServers\"); project scope →\r\n * <projectDir>/.mcp.json (\"mcpServers\").\r\n * - Hooks: <configDir>/settings.json under \"hooks\", keyed by event name, each\r\n * value an array of { matcher, hooks:[{ type:\"command\", command }] }.\r\n * - Reply: a `hookSpecificOutput` object (allow|deny|ask + reason,\r\n * additionalContext, updatedInput) on stdout with exit 0.\r\n */\r\n\r\nimport { copyFileSync, existsSync, lstatSync, readFileSync, realpathSync } from \"node:fs\";\r\nimport { homedir } from \"node:os\";\r\nimport { basename, dirname, join } from \"node:path\";\r\n\r\nimport { BaseAdapter, type HookMergeDescriptor } from \"../base.js\";\r\nimport type { Adapter, HookReply, InstallContext, MemoryTarget, NormalizedEvent } from \"../spi.js\";\r\nimport type {\r\n ChangeRecord,\r\n CommandDef,\r\n ConfigPatchDef,\r\n DetectedPlatform,\r\n DiagnosticResult,\r\n HealthCheck,\r\n HookEventName,\r\n HookParadigm,\r\n HookResponse,\r\n JsonValue,\r\n NotificationEvent,\r\n PermissionRequestEvent,\r\n PlatformCapabilities,\r\n PlatformId,\r\n PostCompactEvent,\r\n PostToolUseEvent,\r\n PostToolUseFailureEvent,\r\n PreCompactEvent,\r\n PreToolUseEvent,\r\n SessionEndEvent,\r\n SessionStartEvent,\r\n ServerDef,\r\n SkillDef,\r\n StatuslineContext,\r\n StopEvent,\r\n SubagentDef,\r\n SubagentStartEvent,\r\n SubagentStopEvent,\r\n Transport,\r\n UserPromptSubmitEvent,\r\n} from \"../../core/types.js\";\r\nimport { resolveEnvRefsDeep, rewriteEnvRefs } from \"../../core/interpolate.js\";\r\nimport {\r\n buildHomeBinStatuslineCommand,\r\n buildWrappedStdio,\r\n isHomeBinHookCommand,\r\n isHomeBinStatuslineCommand,\r\n} from \"../../core/spawn.js\";\r\nimport {\r\n type ConfigPatchLedgerEntry,\r\n addLedgerOwner,\r\n configPatchManualEdit,\r\n configPatchNamespaceViolation,\r\n createLedgerEntry,\r\n describeJsonValue,\r\n dropLedgerEntry,\r\n findLedgerEntry,\r\n hashJsonValue,\r\n isValidConfigPatchKey,\r\n jsonDeepEquals,\r\n ledgerEntriesOwnedBy,\r\n loadConfigPatchLedger,\r\n removeLedgerOwner,\r\n saveConfigPatchLedger,\r\n} from \"../../core/config-patch-ledger.js\";\r\nimport { readRegisteredMeta } from \"../../core/load-connector.js\";\r\nimport {\r\n linesOutsideFences,\r\n listManagedBlocks,\r\n loadMemoryLedger,\r\n recordMemoryTarget,\r\n removeBlocksFromText,\r\n removeManagedBlocksFile,\r\n saveMemoryLedger,\r\n upsertManagedBlockFile,\r\n} from \"../../core/managed-block.js\";\r\nimport { backupsDir, ensureDir } from \"../../core/paths.js\";\r\nimport {\r\n type ClaudeHookEvent,\r\n type ClaudeWireInput,\r\n extractSessionId,\r\n normalizeSessionSource,\r\n toolResponseToString,\r\n} from \"./wire.js\";\r\nimport { renderCommandMd, renderSkillMd, renderSubagentMd } from \"./render.js\";\r\n\r\nconst HOST: PlatformId = \"claude-code\";\r\nconst MCP_ROOT_KEY = \"mcpServers\";\r\n\r\n/**\r\n * settings.json leaf key the statusline surface owns. Wired through the SAME\r\n * set-if-absent ownership ledger as configPatch (it is NOT on the configPatch\r\n * sensitive-key denylist — verified — and is a single top-level leaf), so a\r\n * non-AC statusLine is never clobbered.\r\n */\r\nconst STATUSLINE_KEY = \"statusLine\";\r\n\r\n/**\r\n * Reserved blockId of the SHARED `@AGENTS.md` import bridge in CLAUDE.md\r\n * (agents-import mode). The `_shared/` prefix cannot collide with a connector\r\n * blockId (connector ids match ^[a-z0-9][a-z0-9-]*$), and the bridge is\r\n * refcounted namespace-wide: it is removed only when the LAST agent-connector\r\n * block leaves the sibling AGENTS.md.\r\n */\r\nconst CLAUDE_AGENTS_IMPORT_BLOCK_ID = \"_shared/claude-agents-import\";\r\n\r\n/** A single hook registration entry as Claude Code stores it in settings.json. */\r\ninterface ClaudeHookEntry {\r\n matcher: string;\r\n hooks: Array<{ type: \"command\"; command: string }>;\r\n}\r\n\r\n/** Native MCP server entry shapes Claude Code accepts under `mcpServers`. */\r\ninterface ClaudeStdioServer {\r\n type: \"stdio\";\r\n command: string;\r\n args: string[];\r\n env?: Record<string, string>;\r\n cwd?: string;\r\n}\r\ninterface ClaudeHttpServer {\r\n type: \"http\";\r\n url: string;\r\n headers?: Record<string, string>;\r\n}\r\n\r\n/**\r\n * Claude Code statusLine command stdin payload (the documented status-line hook\r\n * input). Every field optional — a refresh only carries what the host knows.\r\n * `version` and any unmodeled fields stay in StatuslineContext.raw.\r\n */\r\ninterface ClaudeStatuslineInput {\r\n session_id?: string;\r\n transcript_path?: string;\r\n cwd?: string;\r\n version?: string;\r\n model?: { id?: string; display_name?: string };\r\n workspace?: { current_dir?: string; project_dir?: string };\r\n cost?: { total_cost_usd?: number };\r\n}\r\n\r\nexport class ClaudeCodeAdapter extends BaseAdapter implements Adapter {\r\n readonly id: PlatformId = HOST;\r\n readonly name = \"Claude Code\";\r\n readonly paradigm: HookParadigm = \"json-stdio\";\r\n\r\n readonly capabilities: PlatformCapabilities = {\r\n preToolUse: true,\r\n postToolUse: true,\r\n preCompact: true,\r\n sessionStart: true,\r\n sessionEnd: true,\r\n userPromptSubmit: true,\r\n stop: true,\r\n notification: true,\r\n // Newer events — Claude Code is the reference host for all four.\r\n permissionRequest: true,\r\n postToolUseFailure: true,\r\n subagentStart: true,\r\n subagentStop: true,\r\n // Claude Code can rewrite PreToolUse input (updatedInput) but does NOT let a\r\n // PostToolUse hook rewrite already-emitted tool output.\r\n canModifyArgs: true,\r\n canModifyOutput: false,\r\n canInjectSessionContext: true,\r\n // Native passthrough hooks: settings.json hook keys are free-form event\r\n // names, so any host event (TaskCreated, TeammateIdle, WorktreeCreate, …)\r\n // declared under platforms[\"claude-code\"].nativeHooks installs verbatim.\r\n supportsNativeHooks: true,\r\n // Declarative host-config key patches: claude-code is the ONLY v1 host\r\n // (set-if-absent leaf keys in settings.json, refcounted ownership ledger,\r\n // sensitive-key denylist — see SENSITIVE_KEY_RULES below).\r\n supportsConfigPatch: true,\r\n // Statusline surface: claude-code is the ONLY v1 host. installStatusline\r\n // wires settings.json.statusLine = {type:\"command\", command:<home-bin\r\n // statusline cmd>} through the SAME set-if-absent ownership ledger as\r\n // configPatch (never clobbers a statusLine agent-connector does not own).\r\n supportsStatusline: true,\r\n transports: [\"stdio\", \"http\"],\r\n // Server secret-bearing fields use Claude's NATIVE ${VAR} interpolation\r\n // (rewriteEnvRefs) — the token survives into the config, never a baked\r\n // literal — so the installer's unset-env-ref bake warn does not apply here.\r\n nativeServerEnvInterpolation: true,\r\n // Content surfaces: Claude Code is the reference implementation for all three.\r\n supportsCommands: true,\r\n supportsSkills: true,\r\n supportsSubagents: true,\r\n // Memory surface — EXCEPTION host: Claude Code reads CLAUDE.md, NOT\r\n // AGENTS.md (docs are explicit; no AGENTS.md support through v2.1.172), so\r\n // memoryTargets/installMemory below override the base AGENTS.md default.\r\n supportsMemory: true,\r\n };\r\n\r\n // ── Detection ────────────────────────────────────────────────────────────\r\n\r\n detectInstalled(projectDir: string): DetectedPlatform {\r\n const userDir = join(homedir(), \".claude\");\r\n const userSettings = join(userDir, \"settings.json\");\r\n const userServers = join(homedir(), \".claude.json\");\r\n const projectServers = join(projectDir, \".mcp.json\");\r\n const userInstalled =\r\n existsSync(userDir) || existsSync(userSettings) || existsSync(userServers);\r\n const projInstalled = existsSync(projectServers);\r\n const installed = userInstalled || projInstalled;\r\n // Report the scope/path/reason for the marker that actually matched, so a\r\n // project-only install isn't misreported as a (non-existent) user install.\r\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\r\n const configPath = scope === \"project\" ? projectServers : userSettings;\r\n return {\r\n id: this.id,\r\n name: this.name,\r\n installed,\r\n paradigm: this.paradigm,\r\n capabilities: this.capabilities,\r\n configPath,\r\n scope,\r\n reason: installed\r\n ? scope === \"project\"\r\n ? `found project Claude Code config at ${projectServers}`\r\n : `found Claude Code config under ${userDir}`\r\n : `no Claude Code config at ${userDir}`,\r\n confidence: installed ? \"high\" : \"low\",\r\n };\r\n }\r\n\r\n // ── Native paths ─────────────────────────────────────────────────────────\r\n\r\n getConfigDir(ctx: InstallContext): string {\r\n return ctx.scope === \"project\"\r\n ? join(ctx.projectDir, \".claude\")\r\n : join(homedir(), \".claude\");\r\n }\r\n\r\n getServerConfigPath(ctx: InstallContext): string {\r\n return ctx.scope === \"project\"\r\n ? join(ctx.projectDir, \".mcp.json\")\r\n : join(homedir(), \".claude.json\");\r\n }\r\n\r\n getHookConfigPath(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"settings.json\");\r\n }\r\n\r\n // ── MCP server install / uninstall ───────────────────────────────────────\r\n\r\n installServer(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n const override = connector.platforms[HOST]?.server;\r\n if (!connector.server || override === false) {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n detail: connector.server\r\n ? \"server registration disabled for claude-code\"\r\n : \"connector declares no MCP server\",\r\n },\r\n ];\r\n }\r\n\r\n // Shallow-merge any per-platform server override into the base ServerDef.\r\n const server: ServerDef =\r\n override && typeof override === \"object\"\r\n ? { ...connector.server, ...override }\r\n : connector.server;\r\n\r\n const serverPath = this.getServerConfigPath(ctx);\r\n const entry = this.renderServerEntry(ctx, server);\r\n\r\n return [\r\n this.upsertServerInJson(serverPath, MCP_ROOT_KEY, connector.id, entry, ctx.dryRun),\r\n ];\r\n }\r\n\r\n uninstallServer(ctx: InstallContext): ChangeRecord[] {\r\n const serverPath = this.getServerConfigPath(ctx);\r\n return [\r\n this.removeServerFromJson(serverPath, MCP_ROOT_KEY, ctx.connector.id, ctx.dryRun),\r\n ];\r\n }\r\n\r\n /** Render a normalized ServerDef into Claude Code's native mcpServers entry. */\r\n private renderServerEntry(\r\n ctx: InstallContext,\r\n server: ServerDef,\r\n ): ClaudeStdioServer | ClaudeHttpServer {\r\n const transport: Transport = server.transport;\r\n\r\n if (transport === \"stdio\") {\r\n let command = server.command ?? \"\";\r\n let args = [...(server.args ?? [])];\r\n\r\n // Transparent telemetry wrapping: route the real command through\r\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\r\n ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\r\n\r\n const entry: ClaudeStdioServer = { type: \"stdio\", command, args };\r\n const env = this.renderEnv(server.env);\r\n if (env) entry.env = env;\r\n if (server.cwd) entry.cwd = resolveEnvRefsDeep(server.cwd);\r\n return entry;\r\n }\r\n\r\n // http (and any other remote transport we surface) — Claude registers a URL.\r\n const entry: ClaudeHttpServer = {\r\n type: \"http\",\r\n url: rewriteEnvRefs(server.url ?? \"\", claudeEnvToken),\r\n };\r\n if (server.headers) {\r\n entry.headers = this.renderEnv(server.headers) ?? {};\r\n }\r\n return entry;\r\n }\r\n\r\n /**\r\n * Render env/header values. Claude Code supports its own `${VAR}` native\r\n * interpolation, so translate `${env:VAR}` refs to that native token rather\r\n * than baking secrets into the file. Literals pass through unchanged.\r\n */\r\n private renderEnv(\r\n env: Record<string, string> | undefined,\r\n ): Record<string, string> | undefined {\r\n if (!env || Object.keys(env).length === 0) return undefined;\r\n const out: Record<string, string> = {};\r\n for (const [k, v] of Object.entries(env)) {\r\n out[k] = rewriteEnvRefs(v, claudeEnvToken);\r\n }\r\n return out;\r\n }\r\n\r\n // ── Hook install / uninstall ─────────────────────────────────────────────\r\n\r\n installHooks(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n const override = connector.platforms[HOST];\r\n\r\n // `hooks: false` disables only the NORMALIZED hooks. nativeHooks is a\r\n // sibling, explicitly claude-code-scoped declaration on the same override —\r\n // it installs regardless (the dev wrote both keys on the same object).\r\n const normalizedEvents = override?.hooks === false ? [] : connector.hookEvents;\r\n const nativeHooks = override?.nativeHooks ?? {};\r\n const nativeEvents = Object.keys(nativeHooks);\r\n\r\n if (normalizedEvents.length === 0 && nativeEvents.length === 0) {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n detail:\r\n override?.hooks === false\r\n ? \"hooks disabled for claude-code\"\r\n : \"connector declares no hooks\",\r\n },\r\n ];\r\n }\r\n\r\n const settingsPath = this.getHookConfigPath(ctx);\r\n\r\n // One pass over normalized + NATIVE events: native event-name keys are\r\n // written VERBATIM (e.g. \"TaskCreated\"), matcher from the def, and the\r\n // exact same home-bin command shape — so uninstall/doctor/telemetry treat\r\n // both identically.\r\n const pending: Array<{ event: string; matcher: string }> = [\r\n ...normalizedEvents.map((event) => ({\r\n event: event as string,\r\n matcher: connector.hooks[event]?.matcher ?? \"\",\r\n })),\r\n ...nativeEvents.map((event) => ({\r\n event,\r\n matcher: nativeHooks[event]?.matcher ?? \"\",\r\n })),\r\n ];\r\n\r\n return this.upsertHookEntries(ctx, settingsPath, pending, this.hookDescriptor());\r\n }\r\n\r\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\r\n return this.removeHookEntries(ctx, this.getHookConfigPath(ctx), this.hookDescriptor());\r\n }\r\n\r\n /**\r\n * Claude's hook-merge descriptor (NESTED shape `{ matcher, hooks: [...] }`):\r\n * - install find = THIS exact command present in the entry's inner `hooks`;\r\n * - uninstall = inner-strip ONLY (connector-generic `isOurCommand` over the\r\n * inner commands, drop entries left empty) — claude never removes a whole\r\n * entry by ownership, so `ownsEntryForRemove` is a never-true predicate;\r\n * - every detail string is the literal claude-code wording.\r\n */\r\n private hookDescriptor(): HookMergeDescriptor<ClaudeHookEntry> {\r\n return {\r\n renderEntry: (_event, matcher, command) => ({\r\n matcher,\r\n hooks: [{ type: \"command\", command }],\r\n }),\r\n entryOwnsCommand: (entry, command) =>\r\n (entry.hooks ?? []).some((h) => h.command === command),\r\n ownsEntryForRemove: () => () => false,\r\n stripInner: (ctx) => (entry) => {\r\n const innerBefore = entry.hooks?.length ?? 0;\r\n const inner = (entry.hooks ?? []).filter((h) => !this.isOurCommand(h.command, ctx));\r\n return {\r\n next: inner.length > 0 ? { matcher: entry.matcher ?? \"\", hooks: inner } : null,\r\n removed: innerBefore - inner.length,\r\n };\r\n },\r\n skipDetail: (event) => `hooks.${event} already registered`,\r\n removeDetail: (event, removed) => `hooks.${event} (${removed})`,\r\n absentDetail: \"no hooks section present\",\r\n noMatchDetail: \"no matching hook entries\",\r\n };\r\n }\r\n\r\n // ── Declarative host-config key patches (configPatch) ────────────────────\r\n // FIXED semantics (docs/ARCHITECTURE.md §4): set-if-absent on a single\r\n // dotted LEAF key of settings.json, skip-warn on ANY conflict (present key,\r\n // non-object intermediate, drift), refcounted ownership in the persisted\r\n // ledger at <dataRoot>/state/config-patches.json. Reuses the adapter's\r\n // existing whole-file settings.json JSON IO (the same handling the hook\r\n // install performs on this exact file) — Claude Code itself rewrites this\r\n // file, so format preservation is a non-issue here. NOTE for future hosts:\r\n // VS Code JSONC needs jsonc-parser modify/applyEdits and Codex TOML needs an\r\n // anchored edit — core/toml.ts's round-trip is BANNED for configPatch.\r\n\r\n /** The ONLY file configPatch may touch on claude-code: settings.json at scope. */\r\n getPatchableConfigPath(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"settings.json\");\r\n }\r\n\r\n override installConfigPatches(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n const patches = connector.platforms[HOST]?.configPatch ?? [];\r\n if (patches.length === 0) {\r\n return [\r\n { platform: this.id, action: \"skip\", detail: \"connector declares no configPatch entries\" },\r\n ];\r\n }\r\n return this.applyConfigPatches(ctx, patches);\r\n }\r\n\r\n /**\r\n * The shared set-if-absent / ownership-ledger apply loop behind BOTH\r\n * {@link installConfigPatches} and {@link installStatusline}. Routing the\r\n * statusline through the EXACT same path is how a connector's statusLine\r\n * inherits the configPatch contract verbatim: never clobber a statusLine\r\n * agent-connector does not own (skip-warn), record prior state + owner,\r\n * refcounted across connectors, reversible by uninstallConfigPatches.\r\n */\r\n private applyConfigPatches(\r\n ctx: InstallContext,\r\n patches: ConfigPatchDef[],\r\n opts: { surfaceLabel?: \"configPatch\" | \"statusline\" } = {},\r\n ): ChangeRecord[] {\r\n // The user-facing surface name in every ChangeRecord.detail. \"statusline\"\r\n // routes the AC-modeled statusLine key through this loop INTERNALLY — that\r\n // key is namespace-reserved against raw configPatch, so the internal path\r\n // bypasses the namespace guard (the surface, not a smuggled patch, owns it).\r\n const surfaceLabel = opts.surfaceLabel ?? \"configPatch\";\r\n const internal = surfaceLabel !== \"configPatch\";\r\n const { connector } = ctx;\r\n const filePath = this.getPatchableConfigPath(ctx);\r\n const symlink = this.symlinkPathWarning(filePath);\r\n if (symlink) return [symlink];\r\n\r\n // OVERWRITE GUARD (upsertServerInJson precedent): never round-trip a\r\n // present-but-unparseable settings file into `{}`.\r\n if (this.isPresentButUnparseable(filePath)) {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail: `existing ${filePath} is not parseable; configPatch left unapplied (back it up / fix it, then re-run)`,\r\n },\r\n ];\r\n }\r\n const settings = this.readJson<Record<string, unknown>>(filePath) ?? {};\r\n if (typeof settings !== \"object\" || Array.isArray(settings)) {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail: `existing ${filePath} is not a JSON object; configPatch left unapplied`,\r\n },\r\n ];\r\n }\r\n\r\n const ledger = loadConfigPatchLedger(ctx.dataRoot);\r\n const changes: ChangeRecord[] = [];\r\n let fileMutated = false;\r\n let ledgerMutated = false;\r\n\r\n for (const patch of patches) {\r\n // Defense in depth: re-validate grammar + AC-namespace here (a connector\r\n // loaded from raw meta/JSON must not bypass defineConnector's checks).\r\n if (!isValidConfigPatchKey(patch.key)) {\r\n changes.push({\r\n platform: this.id,\r\n action: \"warn\",\r\n detail:\r\n `configPatch ${JSON.stringify(patch.key)} refused: not a dotted leaf path ` +\r\n `(segments must match [A-Za-z0-9_-]+; no array indices)`,\r\n });\r\n continue;\r\n }\r\n // The statusline surface intentionally models the (now namespace-reserved)\r\n // statusLine key, so its internal patches skip this guard.\r\n if (!internal) {\r\n const namespace = configPatchNamespaceViolation(patch.key);\r\n if (namespace) {\r\n changes.push({\r\n platform: this.id,\r\n action: \"warn\",\r\n detail: `configPatch refused: ${namespace}`,\r\n });\r\n continue;\r\n }\r\n }\r\n // SENSITIVE-KEY DENYLIST — hard refuse, no override flag in v1.\r\n const sensitive = claudeSensitiveKeyViolation(patch.key);\r\n if (sensitive) {\r\n changes.push({\r\n platform: this.id,\r\n action: \"warn\",\r\n detail:\r\n `configPatch ${patch.key} refused: matches the claude-code sensitive-key ` +\r\n `denylist (${sensitive}); security-relevant keys are never patched`,\r\n });\r\n continue;\r\n }\r\n\r\n // `${env:VAR}` refs resolve at install time, matching server-entry behavior.\r\n const desired = resolveEnvRefsDeep(patch.value) as JsonValue;\r\n const segments = patch.key.split(\".\");\r\n const leaf = readJsonLeaf(settings, segments);\r\n const entry = findLedgerEntry(ledger, HOST, filePath, patch.key);\r\n\r\n if (leaf.kind === \"blocked\") {\r\n changes.push({\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail:\r\n `${surfaceLabel} ${patch.key} skipped: \"${leaf.atPath}\" exists but is not an ` +\r\n `object — ${configPatchManualEdit(patch)}`,\r\n });\r\n continue;\r\n }\r\n\r\n if (leaf.kind === \"absent\") {\r\n // SET-IF-ABSENT: the one write path. Intermediates created only as needed.\r\n writeJsonLeaf(settings, segments, desired);\r\n fileMutated = true;\r\n if (entry) {\r\n // Stale ledger row (key was deleted out from under us): re-assert the\r\n // value, keep existing owners (they still rely on the key existing),\r\n // and record what was actually (re)written.\r\n entry.writtenValue = desired;\r\n entry.writtenValueHash = hashJsonValue(desired);\r\n addLedgerOwner(entry, connector.id, connector.version);\r\n } else {\r\n createLedgerEntry(ledger, {\r\n platform: HOST,\r\n file: filePath,\r\n key: patch.key,\r\n value: desired,\r\n connectorId: connector.id,\r\n connectorVersion: connector.version,\r\n });\r\n }\r\n ledgerMutated = true;\r\n changes.push({\r\n platform: this.id,\r\n action: \"create\",\r\n path: filePath,\r\n detail: `${surfaceLabel} ${patch.key}: <absent> → ${describeJsonValue(desired)} (${patch.reason})`,\r\n });\r\n continue;\r\n }\r\n\r\n // Key PRESENT — never overwrite; the only question is ownership/refcount.\r\n if (!entry) {\r\n // User- (or other-tool-) owned. No ownership is taken even when values\r\n // happen to match — uninstall must never delete a key we did not create.\r\n changes.push({\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail:\r\n `${surfaceLabel} ${patch.key} skipped: already set to ${describeJsonValue(leaf.value)} ` +\r\n `(not created by agent-connector; desired ${describeJsonValue(desired)}) — ` +\r\n configPatchManualEdit(patch),\r\n });\r\n continue;\r\n }\r\n\r\n if (!jsonDeepEquals(leaf.value, entry.writtenValue)) {\r\n // DRIFT: the user edited the value after we wrote it. Never revert —\r\n // sync re-asserts only ABSENT keys.\r\n changes.push({\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail:\r\n `${surfaceLabel} ${patch.key}: value changed since install ` +\r\n `(current ${describeJsonValue(leaf.value)}, wrote ${describeJsonValue(entry.writtenValue)}); ` +\r\n `leaving in place — ${configPatchManualEdit(patch)}`,\r\n });\r\n continue;\r\n }\r\n\r\n if (jsonDeepEquals(desired, leaf.value)) {\r\n // Same value we own: register as co-owner (refcount++) or plain\r\n // idempotent skip when this connector is already an owner.\r\n const owners = entry.owners.map((o) => o.connectorId);\r\n if (addLedgerOwner(entry, connector.id, connector.version)) {\r\n ledgerMutated = true;\r\n changes.push({\r\n platform: this.id,\r\n action: \"skip\",\r\n path: filePath,\r\n detail: `${surfaceLabel} ${patch.key} already installed; registered as co-owner (co-owned with ${owners.join(\", \")})`,\r\n });\r\n } else {\r\n changes.push({\r\n platform: this.id,\r\n action: \"skip\",\r\n path: filePath,\r\n detail: `${surfaceLabel} ${patch.key} already installed`,\r\n });\r\n }\r\n continue;\r\n }\r\n\r\n // FIRST-WRITER-WINS: another connector owns this key with a different value.\r\n changes.push({\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail:\r\n `${surfaceLabel} ${patch.key} skipped: already owned by ${entry.owners\r\n .map((o) => o.connectorId)\r\n .join(\", \")} with a different value ` +\r\n `(current ${describeJsonValue(leaf.value)}, desired ${describeJsonValue(desired)}) — ` +\r\n configPatchManualEdit(patch),\r\n });\r\n }\r\n\r\n if (fileMutated) this.writeJson(filePath, settings, ctx.dryRun);\r\n if (ledgerMutated && !ctx.dryRun) saveConfigPatchLedger(ctx.dataRoot, ledger);\r\n return changes;\r\n }\r\n\r\n override uninstallConfigPatches(ctx: InstallContext): ChangeRecord[] {\r\n const connectorId = ctx.connector.id;\r\n const ledger = loadConfigPatchLedger(ctx.dataRoot);\r\n // Keyed off the LEDGER (not the declaration): releases ownership for every\r\n // file/scope this connector ever patched, even when the uninstall context\r\n // is a minimal synthetic connector or the scope flag differs from install.\r\n // EXCLUDE the statusLine key — that surface releases via uninstallStatusline\r\n // (the installer runs both), so this never double-processes the same row.\r\n const owned = ledgerEntriesOwnedBy(ledger, HOST, connectorId).filter(\r\n (e) => e.key !== STATUSLINE_KEY,\r\n );\r\n const declared = ctx.connector.platforms[HOST]?.configPatch ?? [];\r\n const changes: ChangeRecord[] = [];\r\n\r\n // Declared patches with NO ownership record anywhere: never delete a key\r\n // we did not create (rule 1) — explicit skip so the outcome is never silent.\r\n const ownedKeys = new Set(owned.map((e) => e.key));\r\n for (const patch of declared) {\r\n if (!ownedKeys.has(patch.key)) {\r\n changes.push({\r\n platform: this.id,\r\n action: \"skip\",\r\n detail: `configPatch ${patch.key}: no ownership recorded; left untouched`,\r\n });\r\n }\r\n }\r\n if (owned.length === 0) return changes;\r\n changes.push(...this.releaseOwnedConfigPatches(ctx, ledger, owned));\r\n return changes;\r\n }\r\n\r\n /**\r\n * The shared last-owner-verified release loop behind BOTH\r\n * {@link uninstallConfigPatches} and {@link uninstallStatusline}: for each\r\n * already-selected owned ledger entry, drop this connector's ownership and\r\n * remove the key ONLY when last-owner ∧ value-unchanged ∧ prior-absent (else\r\n * skip-warn + leave the key). Saves the ledger when it mutated.\r\n */\r\n private releaseOwnedConfigPatches(\r\n ctx: InstallContext,\r\n ledger: ReturnType<typeof loadConfigPatchLedger>,\r\n owned: ConfigPatchLedgerEntry[],\r\n opts: { surfaceLabel?: \"configPatch\" | \"statusline\" } = {},\r\n ): ChangeRecord[] {\r\n const surfaceLabel = opts.surfaceLabel ?? \"configPatch\";\r\n const connectorId = ctx.connector.id;\r\n const changes: ChangeRecord[] = [];\r\n let ledgerMutated = false;\r\n const backedUp = new Set<string>();\r\n\r\n // Group by file (entries may span scopes/files).\r\n const byFile = new Map<string, ConfigPatchLedgerEntry[]>();\r\n for (const entry of owned) {\r\n const bucket = byFile.get(entry.file) ?? [];\r\n bucket.push(entry);\r\n byFile.set(entry.file, bucket);\r\n }\r\n\r\n for (const [filePath, entries] of byFile) {\r\n const symlink = this.symlinkPathWarning(filePath);\r\n if (symlink) {\r\n changes.push(symlink);\r\n continue;\r\n }\r\n\r\n const unparseable = this.isPresentButUnparseable(filePath);\r\n const settings = unparseable\r\n ? null\r\n : this.readJson<Record<string, unknown>>(filePath);\r\n let fileMutated = false;\r\n\r\n for (const entry of entries) {\r\n const { lastOwner } = removeLedgerOwner(entry, connectorId);\r\n ledgerMutated = true;\r\n\r\n if (!lastOwner) {\r\n // The shared-flag case: A uninstalls, B still relies on the key.\r\n changes.push({\r\n platform: this.id,\r\n action: \"skip\",\r\n path: filePath,\r\n detail: `${surfaceLabel} ${entry.key} retained: still owned by ${entry.owners\r\n .map((o) => o.connectorId)\r\n .join(\", \")}`,\r\n });\r\n continue;\r\n }\r\n\r\n // Last owner out → the ledger row is dropped on every branch below;\r\n // the KEY is removed only on the fully-verified branch.\r\n dropLedgerEntry(ledger, entry);\r\n\r\n if (unparseable) {\r\n changes.push({\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail: `${surfaceLabel} ${entry.key}: ${filePath} is not parseable; key left in place (ownership released)`,\r\n });\r\n continue;\r\n }\r\n if (!settings || typeof settings !== \"object\" || Array.isArray(settings)) {\r\n changes.push({\r\n platform: this.id,\r\n action: \"skip\",\r\n path: filePath,\r\n detail: `${surfaceLabel} ${entry.key} already absent (no settings file); ownership record dropped`,\r\n });\r\n continue;\r\n }\r\n const leaf = readJsonLeaf(settings, entry.key.split(\".\"));\r\n if (leaf.kind !== \"present\") {\r\n changes.push({\r\n platform: this.id,\r\n action: \"skip\",\r\n path: filePath,\r\n detail: `${surfaceLabel} ${entry.key} already absent; ownership record dropped`,\r\n });\r\n continue;\r\n }\r\n if (entry.prior?.present !== false || !jsonDeepEquals(leaf.value, entry.writtenValue)) {\r\n // User edited the value after install (or the row predates the\r\n // set-if-absent guarantee): deleting would clobber them. Leave it.\r\n changes.push({\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail:\r\n `${surfaceLabel} ${entry.key}: value changed since install ` +\r\n `(current ${describeJsonValue(leaf.value)}, wrote ${describeJsonValue(entry.writtenValue)}); ` +\r\n `left in place`,\r\n });\r\n continue;\r\n }\r\n\r\n // VERIFIED: last owner + current === writtenValue + prior was absent.\r\n // Back up the exact file before its first mutation, then delete the\r\n // leaf key (intermediate objects we created are left in place).\r\n if (!ctx.dryRun && !backedUp.has(filePath) && existsSync(filePath)) {\r\n const backup = this.backupFileForConfigPatch(filePath);\r\n backedUp.add(filePath);\r\n if (backup) {\r\n changes.push({\r\n platform: this.id,\r\n action: \"create\",\r\n path: backup,\r\n detail: \"backed up settings before configPatch removal\",\r\n });\r\n }\r\n }\r\n deleteJsonLeaf(settings, entry.key.split(\".\"));\r\n fileMutated = true;\r\n changes.push({\r\n platform: this.id,\r\n action: \"remove\",\r\n path: filePath,\r\n detail: `${surfaceLabel} ${entry.key} removed (was ${describeJsonValue(entry.writtenValue)})`,\r\n });\r\n }\r\n\r\n if (fileMutated && settings) this.writeJson(filePath, settings, ctx.dryRun);\r\n }\r\n\r\n if (ledgerMutated && !ctx.dryRun) saveConfigPatchLedger(ctx.dataRoot, ledger);\r\n return changes;\r\n }\r\n\r\n // ── Statusline surface (a HUD/status line) ────────────────────────────────\r\n // Wires settings.json.statusLine = { type:\"command\", command:<home-bin\r\n // statusline cmd> } through the SAME ownership ledger as configPatch: a\r\n // synthetic ConfigPatchDef routed through applyConfigPatches, so the statusLine\r\n // inherits the full set-if-absent contract verbatim — never clobbers a\r\n // statusLine agent-connector does not own (skip-warn), records prior state +\r\n // owner, reversible. The home-bin command makes the host exec\r\n // `<homeBin> statusline claude-code --connector <id>` for every status refresh,\r\n // which re-imports the connector module and renders the line (runtime/\r\n // statusline-entrypoint). No telemetry in v1.\r\n\r\n /** The synthetic statusLine configPatch this connector would write. */\r\n private statuslineConfigPatch(ctx: InstallContext): ConfigPatchDef {\r\n const command = buildHomeBinStatuslineCommand(ctx.homeBinPath, HOST, ctx.connector.id);\r\n return {\r\n key: STATUSLINE_KEY,\r\n value: { type: \"command\", command },\r\n reason: \"agent-connector statusline surface\",\r\n };\r\n }\r\n\r\n override installStatusline(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.statusline == null) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no statusline\" }];\r\n }\r\n if (connector.platforms[HOST]?.statusline === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"statusline disabled for claude-code\" }];\r\n }\r\n // Reuse the configPatch apply path (set-if-absent, ownership ledger, skip-warn\r\n // on any non-AC statusLine). This is the SAME machinery installConfigPatches\r\n // uses on this exact file, so the ownership semantics are identical — only the\r\n // surface LABEL differs (statusLine is namespace-reserved against raw\r\n // configPatch; this internal path bypasses that guard and owns the key).\r\n return this.applyConfigPatches(ctx, [this.statuslineConfigPatch(ctx)], {\r\n surfaceLabel: \"statusline\",\r\n });\r\n }\r\n\r\n override uninstallStatusline(ctx: InstallContext): ChangeRecord[] {\r\n const ledger = loadConfigPatchLedger(ctx.dataRoot);\r\n // Release ONLY the statusLine ledger row this connector owns (keyed off the\r\n // ledger, not the declaration, so an id-only synthetic uninstall still\r\n // reclaims it). Same last-owner-verified delete as uninstallConfigPatches.\r\n const owned = ledgerEntriesOwnedBy(ledger, HOST, ctx.connector.id).filter(\r\n (e) => e.key === STATUSLINE_KEY,\r\n );\r\n if (owned.length === 0) {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n detail: \"statusline: no ownership recorded; left untouched\",\r\n },\r\n ];\r\n }\r\n return this.releaseOwnedConfigPatches(ctx, ledger, owned, {\r\n surfaceLabel: \"statusline\",\r\n });\r\n }\r\n\r\n /**\r\n * Parse Claude Code's statusLine stdin JSON into the normalized\r\n * {@link StatuslineContext}. Claude pipes a JSON object to the statusLine\r\n * command on stdin (model, workspace, cost, etc.); fields the payload omits\r\n * stay undefined. `raw` keeps the verbatim payload (incl. `version`).\r\n */\r\n parseStatusInput(raw: unknown): StatuslineContext {\r\n const input = (raw ?? {}) as ClaudeStatuslineInput;\r\n const model: { id?: string; displayName?: string } = {};\r\n if (typeof input.model?.id === \"string\") model.id = input.model.id;\r\n if (typeof input.model?.display_name === \"string\") {\r\n model.displayName = input.model.display_name;\r\n }\r\n const cwd =\r\n typeof input.cwd === \"string\"\r\n ? input.cwd\r\n : typeof input.workspace?.current_dir === \"string\"\r\n ? input.workspace.current_dir\r\n : undefined;\r\n\r\n const ctx: StatuslineContext = {\r\n host: HOST,\r\n capabilities: this.capabilities,\r\n raw,\r\n };\r\n if (typeof input.session_id === \"string\" && input.session_id !== \"\") {\r\n ctx.sessionId = input.session_id;\r\n }\r\n if (cwd !== undefined) ctx.cwd = cwd;\r\n if (model.id !== undefined || model.displayName !== undefined) ctx.model = model;\r\n if (typeof input.cost?.total_cost_usd === \"number\") {\r\n ctx.cost = { totalUsd: input.cost.total_cost_usd };\r\n }\r\n if (typeof input.transcript_path === \"string\") {\r\n ctx.transcriptPath = input.transcript_path;\r\n }\r\n return ctx;\r\n }\r\n\r\n /** Format the rendered status line into Claude's native reply: stdout = line, exit 0. */\r\n formatStatusOutput(rendered: string): HookReply {\r\n return { exitCode: 0, stdout: rendered };\r\n }\r\n\r\n /**\r\n * Back up ONE exact file (the ledger-recorded patch target, which may belong\r\n * to a different scope than the current ctx) into the standard backups dir.\r\n * Best-effort: a failed copy returns null and the caller proceeds — the\r\n * removal is already value-verified.\r\n */\r\n private backupFileForConfigPatch(filePath: string): string | null {\r\n try {\r\n ensureDir(backupsDir());\r\n const stamp = new Date().toISOString().replace(/[:.]/g, \"-\");\r\n const dest = join(backupsDir(), `${this.id}-${stamp}-${basename(filePath)}`);\r\n copyFileSync(filePath, dest);\r\n return dest;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Doctor: per-ledger-entry configPatch state for this connector —\r\n * ok → key present and still exactly what we wrote;\r\n * drifted → user changed the value (we print the manual edit, NEVER\r\n * auto-fix — sync re-asserts only absent keys);\r\n * missing → key deleted by the user; sync will re-assert it;\r\n * orphaned → ledger row whose owners' connector records are all gone.\r\n * Plus a re-print of the manual edit for declared patches that hold no\r\n * ownership (skipped at install).\r\n */\r\n private configPatchDiagnostics(ctx: InstallContext): DiagnosticResult[] {\r\n const results: DiagnosticResult[] = [];\r\n const ledger = loadConfigPatchLedger(ctx.dataRoot);\r\n const connectorId = ctx.connector.id;\r\n // EXCLUDE the statusLine row: it is owned by the statusline surface and gets\r\n // its own dedicated health check in getHealthChecks. Reporting it here too\r\n // would double-report the key and (on a user edit) print a bogus configPatch\r\n // \"drifted\" hint to restore a configPatch the connector never declared.\r\n const platformEntries = ledger.entries.filter(\r\n (e) => e.platform === this.id && e.key !== STATUSLINE_KEY,\r\n );\r\n\r\n for (const entry of platformEntries) {\r\n const ownedByThis = entry.owners.some((o) => o.connectorId === connectorId);\r\n if (!ownedByThis) {\r\n // ORPHAN check (global hygiene): every owner's connector record is gone.\r\n const orphaned =\r\n entry.owners.length === 0 ||\r\n entry.owners.every((o) => readRegisteredMeta(o.connectorId) === null);\r\n if (orphaned) {\r\n results.push({\r\n check: `${this.name}: configPatch ${entry.key}`,\r\n status: \"warn\",\r\n message:\r\n `orphaned ledger entry in ${entry.file}: owning connector record(s) ` +\r\n `gone (${entry.owners.map((o) => o.connectorId).join(\", \") || \"none\"})`,\r\n fix:\r\n `re-run \\`agent-connector uninstall <owner-id>\\` to release it, or remove ` +\r\n `${entry.key} from ${entry.file} manually`,\r\n });\r\n }\r\n continue;\r\n }\r\n\r\n const state = this.configPatchState(entry);\r\n if (state.kind === \"ok\") {\r\n results.push({\r\n check: `${this.name}: configPatch ${entry.key}`,\r\n status: \"pass\",\r\n message: `ok — ${entry.key} = ${describeJsonValue(entry.writtenValue)} (${entry.file})`,\r\n });\r\n } else if (state.kind === \"missing\") {\r\n results.push({\r\n check: `${this.name}: configPatch ${entry.key}`,\r\n status: \"warn\",\r\n message: `missing — key deleted from ${entry.file} since install`,\r\n fix: `agent-connector install (sync) will re-assert it`,\r\n fixable: true,\r\n });\r\n } else {\r\n results.push({\r\n check: `${this.name}: configPatch ${entry.key}`,\r\n status: \"warn\",\r\n message:\r\n `drifted — value changed since install (current ${describeJsonValue(state.current)}, ` +\r\n `wrote ${describeJsonValue(entry.writtenValue)}); never auto-fixed`,\r\n fix: `manual edit if wanted: set ${entry.key} = ${describeJsonValue(entry.writtenValue)} in ${entry.file}`,\r\n });\r\n }\r\n }\r\n\r\n // Declared-but-unowned patches: re-print the manual edit (the patch was\r\n // skipped at install — conflict, denylist, or simply not installed yet).\r\n const declared = ctx.connector.platforms[HOST]?.configPatch ?? [];\r\n const ownedKeys = new Set(\r\n ledgerEntriesOwnedBy(ledger, HOST, connectorId).map((e) => e.key),\r\n );\r\n for (const patch of declared) {\r\n if (ownedKeys.has(patch.key)) continue;\r\n results.push({\r\n check: `${this.name}: configPatch ${patch.key}`,\r\n status: \"warn\",\r\n message: `declared but not owned (skipped at install or not yet installed)`,\r\n fix: configPatchManualEdit(patch),\r\n });\r\n }\r\n return results;\r\n }\r\n\r\n /** Current on-disk state of one owned ledger entry. */\r\n private configPatchState(\r\n entry: ConfigPatchLedgerEntry,\r\n ): { kind: \"ok\" } | { kind: \"missing\" } | { kind: \"drifted\"; current: JsonValue } {\r\n const settings = this.readJson<Record<string, unknown>>(entry.file);\r\n if (!settings || typeof settings !== \"object\" || Array.isArray(settings)) {\r\n return { kind: \"missing\" };\r\n }\r\n const leaf = readJsonLeaf(settings, entry.key.split(\".\"));\r\n if (leaf.kind !== \"present\") return { kind: \"missing\" };\r\n if (jsonDeepEquals(leaf.value, entry.writtenValue)) return { kind: \"ok\" };\r\n return { kind: \"drifted\", current: leaf.value };\r\n }\r\n\r\n override doctor(ctx: InstallContext): DiagnosticResult[] {\r\n const results = super.doctor(ctx);\r\n results.push(...this.configPatchDiagnostics(ctx));\r\n return results;\r\n }\r\n\r\n // ── Content surfaces: commands / skills / subagents ──────────────────────\r\n // CONTENT-ONLY: pure native-file writers under <configDir>/{commands,skills,\r\n // agents}. No runtime dispatch, no home-bin pointer, no telemetry wrap. Each\r\n // method is idempotent (byte-identical → skip) via BaseAdapter.writeContentFile\r\n // and reversible via removeContentFile. Honors platforms[\"claude-code\"]\r\n // per-surface false to skip.\r\n\r\n private commandsDir(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"commands\");\r\n }\r\n private skillsDir(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"skills\");\r\n }\r\n private agentsDir(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"agents\");\r\n }\r\n\r\n /** Native command file path: <configDir>/commands/<name>.md. */\r\n private commandPath(ctx: InstallContext, name: string): string {\r\n return join(this.commandsDir(ctx), `${name}.md`);\r\n }\r\n /** Native skill dir: <configDir>/skills/<name>. */\r\n private skillDir(ctx: InstallContext, name: string): string {\r\n return join(this.skillsDir(ctx), name);\r\n }\r\n /** Native subagent file path: <configDir>/agents/<name>.md. */\r\n private subagentPath(ctx: InstallContext, name: string): string {\r\n return join(this.agentsDir(ctx), `${name}.md`);\r\n }\r\n\r\n // ── Commands ──────────────────────────────────────────────────────────────\r\n\r\n override installCommands(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.platforms[HOST]?.commands === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"commands disabled for claude-code\" }];\r\n }\r\n if (connector.commands.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\r\n }\r\n return connector.commands.map((cmd) =>\r\n this.writeContentFile(\r\n this.commandPath(ctx, cmd.name),\r\n this.renderCommand(cmd),\r\n ctx.dryRun,\r\n ),\r\n );\r\n }\r\n\r\n override uninstallCommands(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.commands.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\r\n }\r\n return connector.commands.map((cmd) =>\r\n this.removeContentFile(this.commandPath(ctx, cmd.name), ctx.dryRun),\r\n );\r\n }\r\n\r\n /** Render a command to md+frontmatter (delegates to the shared renderer). */\r\n private renderCommand(cmd: CommandDef): string {\r\n return renderCommandMd(cmd);\r\n }\r\n\r\n // ── Skills ────────────────────────────────────────────────────────────────\r\n\r\n override installSkills(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.platforms[HOST]?.skills === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"skills disabled for claude-code\" }];\r\n }\r\n if (connector.skills.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\r\n }\r\n const changes: ChangeRecord[] = [];\r\n for (const skill of connector.skills) {\r\n const dir = this.skillDir(ctx, skill.name);\r\n changes.push(\r\n this.writeContentFile(join(dir, \"SKILL.md\"), this.renderSkill(skill), ctx.dryRun),\r\n );\r\n // Bundle any resource files beside SKILL.md (relative path → contents).\r\n // Defense-in-depth: skip+warn on any key that escapes the skill dir\r\n // (config-time validation already rejects these, but never trust input).\r\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\r\n const target = this.resolveWithin(dir, rel);\r\n if (target === null) {\r\n changes.push({\r\n platform: this.id,\r\n action: \"warn\",\r\n detail: `skill resource \"${rel}\" escapes the skill dir; skipped`,\r\n });\r\n continue;\r\n }\r\n changes.push(this.writeContentFile(target, contents, ctx.dryRun));\r\n }\r\n }\r\n return changes;\r\n }\r\n\r\n override uninstallSkills(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.skills.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\r\n }\r\n const changes: ChangeRecord[] = [];\r\n for (const skill of connector.skills) {\r\n const dir = this.skillDir(ctx, skill.name);\r\n // Remove only the files we wrote (SKILL.md + declared resources), then the\r\n // skill dir itself when we own its full contents.\r\n changes.push(this.removeContentFile(join(dir, \"SKILL.md\"), ctx.dryRun));\r\n for (const rel of Object.keys(skill.resources ?? {})) {\r\n const target = this.resolveWithin(dir, rel);\r\n if (target === null) continue; // never delete outside the skill dir\r\n changes.push(this.removeContentFile(target, ctx.dryRun));\r\n }\r\n // Only remove the skill dir when WE own its full contents — never rm -rf a\r\n // dir that still holds user-added / sibling-tool / shared files.\r\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\r\n }\r\n return changes;\r\n }\r\n\r\n /** Render a skill's SKILL.md (delegates to the shared renderer). */\r\n private renderSkill(skill: SkillDef): string {\r\n return renderSkillMd(skill);\r\n }\r\n\r\n // ── Subagents ───────────────────────────────────────────────────────────────\r\n\r\n override installSubagents(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.platforms[HOST]?.subagents === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"subagents disabled for claude-code\" }];\r\n }\r\n if (connector.subagents.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\r\n }\r\n return connector.subagents.map((agent) =>\r\n this.writeContentFile(\r\n this.subagentPath(ctx, agent.name),\r\n this.renderSubagent(agent),\r\n ctx.dryRun,\r\n ),\r\n );\r\n }\r\n\r\n override uninstallSubagents(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.subagents.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\r\n }\r\n return connector.subagents.map((agent) =>\r\n this.removeContentFile(this.subagentPath(ctx, agent.name), ctx.dryRun),\r\n );\r\n }\r\n\r\n /** Render a subagent to md+frontmatter (delegates to the shared renderer). */\r\n private renderSubagent(agent: SubagentDef): string {\r\n return renderSubagentMd(agent);\r\n }\r\n\r\n // ── Memory surface: CLAUDE.md managed block + AGENTS.md interop ────────────\r\n // EXCEPTION host. Claude Code reads CLAUDE.md, NOT AGENTS.md (docs verbatim:\r\n // \"Claude Code reads CLAUDE.md, not AGENTS.md\"; no AGENTS.md support through\r\n // v2.1.172), so the base AGENTS.md-first default is overridden:\r\n // - mode \"block\" (default): the managed block goes straight into CLAUDE.md.\r\n // HTML-comment markers are CORRECT here — Claude strips HTML comments\r\n // from CLAUDE.md before context injection, so the markers and the\r\n // do-not-edit notice are INVISIBLE to the model while remaining fully\r\n // parseable by us for sync/doctor/uninstall.\r\n // - mode \"agents-import\" (opt-in via platforms[\"claude-code\"].memory.mode):\r\n // canonical block goes into AGENTS.md, plus a SHARED `@AGENTS.md` import\r\n // bridge block in CLAUDE.md (Anthropic's documented interop). Opt-in\r\n // because the import makes Claude read the ENTIRE AGENTS.md — a behavior\r\n // change agent-connector must not make silently.\r\n // - AUTO interop: when CLAUDE.md ALREADY imports `@AGENTS.md` (a line\r\n // outside code fences and outside our own blocks) or IS a symlink\r\n // resolving to AGENTS.md, the canonical block goes to AGENTS.md and\r\n // CLAUDE.md is NOT touched — the pre-existing user wiring is never\r\n // claimed as agent-connector-managed (prevents double-reads and writes\r\n // \"through\" a symlink). Order-independent: keyed off the import/symlink\r\n // existing, never off whether the AGENTS.md block was written yet.\r\n\r\n /** CLAUDE.md path: project `<projectDir>/CLAUDE.md`, user `~/.claude/CLAUDE.md`. */\r\n private claudeMdPath(ctx: InstallContext): string {\r\n return ctx.scope === \"project\"\r\n ? join(ctx.projectDir, \"CLAUDE.md\")\r\n : join(homedir(), \".claude\", \"CLAUDE.md\");\r\n }\r\n\r\n /** Sibling AGENTS.md at the same scope (agents-import / auto-interop target). */\r\n private agentsMdPath(ctx: InstallContext): string {\r\n return ctx.scope === \"project\"\r\n ? join(ctx.projectDir, \"AGENTS.md\")\r\n : join(homedir(), \".claude\", \"AGENTS.md\");\r\n }\r\n\r\n /**\r\n * True when the user ALREADY wired CLAUDE.md to AGENTS.md themselves:\r\n * an `@AGENTS.md` import line outside code fences and outside agent-connector\r\n * managed blocks (our own bridge must not count), or CLAUDE.md being a\r\n * symlink that resolves to the sibling AGENTS.md.\r\n */\r\n private claudeMdWiredToAgentsMd(ctx: InstallContext): boolean {\r\n const claudeMd = this.claudeMdPath(ctx);\r\n if (!existsSync(claudeMd)) return false;\r\n try {\r\n if (lstatSync(claudeMd).isSymbolicLink()) {\r\n const agentsMd = this.agentsMdPath(ctx);\r\n const resolved = realpathSync(claudeMd);\r\n const agentsResolved = existsSync(agentsMd) ? realpathSync(agentsMd) : agentsMd;\r\n if (resolved === agentsResolved) return true;\r\n }\r\n } catch {\r\n /* unreadable link — fall through to the content probe */\r\n }\r\n let raw: string;\r\n try {\r\n raw = readFileSync(claudeMd, \"utf8\");\r\n } catch {\r\n return false;\r\n }\r\n // Strip every agent-connector managed block first so OUR bridge import is\r\n // never mistaken for user wiring (idempotence across modes).\r\n const withoutBlocks = removeBlocksFromText(raw, { blockIdPrefix: \"\" }).text;\r\n const importRe = /(^|\\s)@(?:AGENTS\\.md|~\\/\\.claude\\/AGENTS\\.md)(\\s|$)/;\r\n return linesOutsideFences(withoutBlocks).some((line) => importRe.test(line));\r\n }\r\n\r\n /**\r\n * Effective memory mode for this install:\r\n * \"user-import\" — the user already wired CLAUDE.md→AGENTS.md (wins over\r\n * everything; we never write a duplicate or a second import);\r\n * \"agents-import\" — explicit opt-in via platforms[\"claude-code\"].memory.mode;\r\n * \"block\" — the default (managed block directly in CLAUDE.md).\r\n */\r\n private effectiveMemoryMode(ctx: InstallContext): \"block\" | \"agents-import\" | \"user-import\" {\r\n if (this.claudeMdWiredToAgentsMd(ctx)) return \"user-import\";\r\n return this.memoryOverride(ctx)?.mode === \"agents-import\" ? \"agents-import\" : \"block\";\r\n }\r\n\r\n protected override memoryTargets(ctx: InstallContext): MemoryTarget[] {\r\n // An explicit path override keeps the base resolution (escape hatch wins).\r\n if (this.memoryOverride(ctx)?.path) return super.memoryTargets(ctx);\r\n if (ctx.scope !== \"project\" && ctx.scope !== \"user\") return [];\r\n const mode = this.effectiveMemoryMode(ctx);\r\n if (mode === \"block\") {\r\n return [\r\n {\r\n path: this.claudeMdPath(ctx),\r\n reason:\r\n \"CLAUDE.md (Claude Code reads CLAUDE.md, not AGENTS.md; \" +\r\n \"HTML-comment markers are stripped from the model's context)\",\r\n },\r\n ];\r\n }\r\n return [\r\n {\r\n path: this.agentsMdPath(ctx),\r\n reason:\r\n mode === \"user-import\"\r\n ? \"AGENTS.md (CLAUDE.md already imports/symlinks it — user wiring respected)\"\r\n : \"AGENTS.md (agents-import mode; @AGENTS.md bridge managed in CLAUDE.md)\",\r\n },\r\n ];\r\n }\r\n\r\n override installMemory(ctx: InstallContext): ChangeRecord[] {\r\n const changes = super.installMemory(ctx);\r\n const { connector } = ctx;\r\n // Bridge management applies only when the generic path actually installed.\r\n if (connector.platforms[HOST]?.memory === false || (connector.memory ?? []).length === 0) {\r\n return changes;\r\n }\r\n if (ctx.scope !== \"project\" && ctx.scope !== \"user\") return changes;\r\n if (this.memoryOverride(ctx)?.path) return changes;\r\n\r\n const mode = this.effectiveMemoryMode(ctx);\r\n if (mode === \"user-import\") {\r\n changes.push({\r\n platform: this.id,\r\n action: \"skip\",\r\n path: this.claudeMdPath(ctx),\r\n detail:\r\n \"memory: CLAUDE.md already imports AGENTS.md; canonical block in AGENTS.md \" +\r\n \"suffices (pre-existing user import never claimed as managed)\",\r\n });\r\n return changes;\r\n }\r\n if (mode !== \"agents-import\") return changes;\r\n\r\n // agents-import: ensure the SHARED `@AGENTS.md` bridge block in CLAUDE.md.\r\n const claudeMd = this.claudeMdPath(ctx);\r\n const importLine = ctx.scope === \"project\" ? \"@AGENTS.md\" : \"@~/.claude/AGENTS.md\";\r\n const res = upsertManagedBlockFile(claudeMd, {\r\n blockId: CLAUDE_AGENTS_IMPORT_BLOCK_ID,\r\n connectorId: \"_shared\",\r\n content: importLine,\r\n notice:\r\n \"Managed by agent-connector (shared bridge). This import makes Claude Code read \" +\r\n \"AGENTS.md; it is removed automatically when the last agent-connector block \" +\r\n \"leaves AGENTS.md.\",\r\n force: ctx.force ?? false,\r\n dryRun: ctx.dryRun,\r\n });\r\n changes.push({\r\n platform: this.id,\r\n action: res.action,\r\n path: claudeMd,\r\n detail: `memory: ${res.detail} — @AGENTS.md import bridge (agents-import mode)`,\r\n });\r\n if (res.backupPath) {\r\n changes.push({\r\n platform: this.id,\r\n action: \"create\",\r\n path: res.backupPath,\r\n detail: \"backed up CLAUDE.md before destructive change\",\r\n });\r\n }\r\n if (res.action !== \"warn\" && !ctx.dryRun) {\r\n const ledger = loadMemoryLedger(connector.id);\r\n recordMemoryTarget(ledger, {\r\n platform: this.id,\r\n scope: ctx.scope,\r\n path: claudeMd,\r\n blockId: CLAUDE_AGENTS_IMPORT_BLOCK_ID,\r\n createdFile: res.createdFile,\r\n hash: res.hash,\r\n });\r\n saveMemoryLedger(connector.id, ledger);\r\n }\r\n return changes;\r\n }\r\n\r\n override uninstallMemory(ctx: InstallContext): ChangeRecord[] {\r\n // Capture bridge facts BEFORE super prunes this platform's ledger rows.\r\n const priorRows = loadMemoryLedger(ctx.connector.id).targets.filter(\r\n (t) => t.platform === this.id && t.blockId === CLAUDE_AGENTS_IMPORT_BLOCK_ID,\r\n );\r\n const changes = super.uninstallMemory(ctx);\r\n\r\n // Bridge candidates: the current-scope CLAUDE.md plus any CLAUDE.md the\r\n // ledger recorded a bridge in (scope drift between install and uninstall).\r\n const pairs = new Map<string, { agentsMd: string; createdFile: boolean }>();\r\n if (ctx.scope === \"project\" || ctx.scope === \"user\") {\r\n pairs.set(this.claudeMdPath(ctx), {\r\n agentsMd: this.agentsMdPath(ctx),\r\n createdFile: false,\r\n });\r\n }\r\n for (const row of priorRows) {\r\n const existing = pairs.get(row.path);\r\n pairs.set(row.path, {\r\n agentsMd: existing?.agentsMd ?? join(dirname(row.path), \"AGENTS.md\"),\r\n createdFile: (existing?.createdFile ?? false) || row.createdFile,\r\n });\r\n }\r\n for (const [claudeMd, { agentsMd, createdFile }] of pairs) {\r\n changes.push(...this.releaseAgentsImportBridge(ctx, claudeMd, agentsMd, createdFile));\r\n }\r\n return changes;\r\n }\r\n\r\n /**\r\n * Refcounted bridge release: remove the `_shared/claude-agents-import` block\r\n * from CLAUDE.md ONLY when the sibling AGENTS.md holds zero agent-connector\r\n * blocks from OTHER connectors (namespace-wide count, excluding this\r\n * connector's own blocks so the answer is identical on dry-run and real run).\r\n * A user-authored `@AGENTS.md` import (no markers) is NEVER touched.\r\n */\r\n private releaseAgentsImportBridge(\r\n ctx: InstallContext,\r\n claudeMd: string,\r\n agentsMd: string,\r\n createdFile: boolean,\r\n ): ChangeRecord[] {\r\n if (!existsSync(claudeMd)) return [];\r\n let raw: string;\r\n try {\r\n raw = readFileSync(claudeMd, \"utf8\");\r\n } catch {\r\n return [];\r\n }\r\n if (!listManagedBlocks(raw).some((b) => b.blockId === CLAUDE_AGENTS_IMPORT_BLOCK_ID)) {\r\n return []; // no managed bridge here (user wiring or block mode) — nothing to release\r\n }\r\n let remaining = 0;\r\n if (existsSync(agentsMd)) {\r\n try {\r\n remaining = listManagedBlocks(readFileSync(agentsMd, \"utf8\")).filter(\r\n (b) => !b.blockId.startsWith(`${ctx.connector.id}/`),\r\n ).length;\r\n } catch {\r\n remaining = 1; // unreadable → conservative: keep the bridge\r\n }\r\n }\r\n if (remaining > 0) {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n path: claudeMd,\r\n detail:\r\n `memory: @AGENTS.md import bridge retained — ${remaining} agent-connector ` +\r\n `block(s) from other connectors remain in ${agentsMd}`,\r\n },\r\n ];\r\n }\r\n return removeManagedBlocksFile(\r\n claudeMd,\r\n { blockId: CLAUDE_AGENTS_IMPORT_BLOCK_ID },\r\n { dryRun: ctx.dryRun, deleteFileIfCreated: createdFile },\r\n ).map((r) => ({\r\n platform: this.id,\r\n action: r.action,\r\n path: r.path,\r\n detail: `memory: ${r.detail}`,\r\n }));\r\n }\r\n\r\n /** True when a hook command references our home binary AND this connector id\r\n * (anchored so a shared-prefix id can't collide — see isHomeBinHookCommand). */\r\n private isOurCommand(command: string | undefined, ctx: InstallContext): boolean {\r\n return isHomeBinHookCommand(command, ctx.homeBinPath, ctx.connector.id);\r\n }\r\n\r\n // ── Diagnostics ──────────────────────────────────────────────────────────\r\n\r\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\r\n const settingsPath = this.getHookConfigPath(ctx);\r\n const connectorId = ctx.connector.id;\r\n const homeBin = ctx.homeBinPath;\r\n const hookEvents = ctx.connector.hookEvents;\r\n // Native passthrough hooks count toward \"declares hooks\" ONLY when declared\r\n // for this platform (the serialized meta keeps the event-name keys, so this\r\n // works for doctor's handler-less meta-derived connectors too).\r\n const declaredHookCount =\r\n hookEvents.length +\r\n Object.keys(ctx.connector.platforms[HOST]?.nativeHooks ?? {}).length;\r\n const checks: HealthCheck[] = [\r\n {\r\n name: `${this.name}: settings.json present`,\r\n check: () => {\r\n // Same \"only assert what the connector declares\" rule as the\r\n // content-surface checks below: a hookless connector never writes\r\n // hooks into settings.json, so its absence is healthy, not a failure.\r\n if (declaredHookCount === 0) {\r\n return { status: \"OK\", detail: \"no hooks declared\" };\r\n }\r\n return existsSync(settingsPath)\r\n ? { status: \"OK\", detail: settingsPath }\r\n : { status: \"FAIL\", detail: `not found: ${settingsPath}` };\r\n },\r\n },\r\n {\r\n name: `${this.name}: hook command registered`,\r\n check: () => {\r\n if (declaredHookCount === 0) {\r\n return { status: \"OK\", detail: \"no hooks declared\" };\r\n }\r\n const settings = this.readJson<{ hooks?: Record<string, ClaudeHookEntry[]> }>(\r\n settingsPath,\r\n );\r\n if (!settings) return { status: \"FAIL\", detail: `cannot read ${settingsPath}` };\r\n const hooks = settings.hooks ?? {};\r\n const registered = Object.values(hooks).some((entries) =>\r\n (entries ?? []).some((e) =>\r\n (e.hooks ?? []).some((h) =>\r\n isHomeBinHookCommand(h.command, homeBin, connectorId),\r\n ),\r\n ),\r\n );\r\n return registered\r\n ? { status: \"OK\", detail: \"hook command present\" }\r\n : {\r\n status: \"FAIL\",\r\n detail: `no hook for ${connectorId} in ${settingsPath}`,\r\n };\r\n },\r\n },\r\n ];\r\n\r\n // Content-surface checks: only assert presence of the files this connector\r\n // declares (skip silently for surfaces it never asked for).\r\n for (const cmd of ctx.connector.commands) {\r\n const p = this.commandPath(ctx, cmd.name);\r\n checks.push({\r\n name: `${this.name}: command ${cmd.name} present`,\r\n check: () =>\r\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\r\n });\r\n }\r\n for (const skill of ctx.connector.skills) {\r\n const p = join(this.skillDir(ctx, skill.name), \"SKILL.md\");\r\n checks.push({\r\n name: `${this.name}: skill ${skill.name} present`,\r\n check: () =>\r\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\r\n });\r\n }\r\n for (const agent of ctx.connector.subagents) {\r\n const p = this.subagentPath(ctx, agent.name);\r\n checks.push({\r\n name: `${this.name}: subagent ${agent.name} present`,\r\n check: () =>\r\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\r\n });\r\n }\r\n\r\n // Statusline check: only assert it when the connector declares one AND it\r\n // is not disabled for this host. settings.json.statusLine.command must be OUR\r\n // home-bin statusline command (ok); present but not ours → drifted/skip-warn\r\n // (never our concern to fix); absent → missing.\r\n // Fire the check when the connector DECLARES a statusline (the live-config\r\n // doctor path) OR when the ownership ledger holds a statusLine row this\r\n // connector owns (the REGISTERED-connector path: connectorFromMeta can't\r\n // re-expose the render fn, so statusline comes back undefined — but the\r\n // ledger row proves the surface was wired). Mirrors uninstallStatusline,\r\n // which is also ledger-keyed; without this the wired statusLine has ZERO\r\n // doctor coverage in the registered path (configPatchDiagnostics excludes it).\r\n const statuslineLedgerOwned = ledgerEntriesOwnedBy(\r\n loadConfigPatchLedger(ctx.dataRoot),\r\n HOST,\r\n connectorId,\r\n ).some((e) => e.key === STATUSLINE_KEY);\r\n if (\r\n (ctx.connector.statusline != null || statuslineLedgerOwned) &&\r\n ctx.connector.platforms[HOST]?.statusline !== false\r\n ) {\r\n checks.push({\r\n name: `${this.name}: statusline wired`,\r\n check: () => {\r\n const settings = this.readJson<{ statusLine?: { command?: unknown } }>(settingsPath);\r\n const command = settings?.statusLine?.command;\r\n if (command === undefined) {\r\n return { status: \"FAIL\", detail: `statusLine not set in ${settingsPath}` };\r\n }\r\n if (\r\n typeof command === \"string\" &&\r\n isHomeBinStatuslineCommand(command, homeBin, connectorId)\r\n ) {\r\n return { status: \"OK\", detail: \"statusLine command present\" };\r\n }\r\n // Present but not ours — a non-AC statusLine we must never clobber.\r\n return {\r\n status: \"FAIL\",\r\n detail: `statusLine in ${settingsPath} is not agent-connector's (left untouched)`,\r\n };\r\n },\r\n });\r\n }\r\n return checks;\r\n }\r\n\r\n // ── Runtime: parse Claude stdin JSON → normalized event ──────────────────\r\n\r\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\r\n const input = (raw ?? {}) as ClaudeWireInput;\r\n const connectorId = typeof input.connector === \"string\" ? input.connector : \"\";\r\n const sessionId = extractSessionId(input);\r\n const projectDir = typeof input.cwd === \"string\" ? input.cwd : undefined;\r\n\r\n const base = {\r\n hostPlatform: HOST,\r\n connectorId,\r\n sessionId,\r\n raw,\r\n ...(projectDir !== undefined ? { projectDir } : {}),\r\n } as const;\r\n\r\n switch (event) {\r\n case \"PreToolUse\": {\r\n const ev: PreToolUseEvent = {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n };\r\n return ev;\r\n }\r\n case \"PostToolUse\": {\r\n const ev: PostToolUseEvent = {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n ...(toolResponseToString(input.tool_response) !== undefined\r\n ? { toolOutput: toolResponseToString(input.tool_response) }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"SessionStart\": {\r\n const ev: SessionStartEvent = {\r\n ...base,\r\n source: normalizeSessionSource(input.source),\r\n };\r\n return ev;\r\n }\r\n case \"SessionEnd\": {\r\n const ev: SessionEndEvent = {\r\n ...base,\r\n ...(typeof input.reason === \"string\" ? { reason: input.reason } : {}),\r\n };\r\n return ev;\r\n }\r\n case \"UserPromptSubmit\": {\r\n const ev: UserPromptSubmitEvent = {\r\n ...base,\r\n prompt: typeof input.prompt === \"string\" ? input.prompt : \"\",\r\n };\r\n return ev;\r\n }\r\n case \"PreCompact\": {\r\n const ev: PreCompactEvent = {\r\n ...base,\r\n ...(input.trigger === \"auto\" || input.trigger === \"manual\"\r\n ? { trigger: input.trigger }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"Stop\": {\r\n const ev: StopEvent = {\r\n ...base,\r\n ...(typeof input.stop_hook_active === \"boolean\"\r\n ? { stopHookActive: input.stop_hook_active }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"Notification\": {\r\n const ev: NotificationEvent = {\r\n ...base,\r\n message: typeof input.message === \"string\" ? input.message : \"\",\r\n };\r\n return ev;\r\n }\r\n case \"PermissionRequest\": {\r\n const ev: PermissionRequestEvent = {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n ...(Array.isArray(input.permission_suggestions)\r\n ? { permissionSuggestions: input.permission_suggestions }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"PostToolUseFailure\": {\r\n const ev: PostToolUseFailureEvent = {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n error: typeof input.error === \"string\" ? input.error : \"\",\r\n ...(typeof input.tool_use_id === \"string\"\r\n ? { toolUseId: input.tool_use_id }\r\n : {}),\r\n ...(typeof input.is_interrupt === \"boolean\"\r\n ? { isInterrupt: input.is_interrupt }\r\n : {}),\r\n ...(typeof input.duration_ms === \"number\"\r\n ? { durationMs: input.duration_ms }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"SubagentStart\": {\r\n const ev: SubagentStartEvent = {\r\n ...base,\r\n ...(typeof input.agent_id === \"string\" ? { agentId: input.agent_id } : {}),\r\n ...(typeof input.agent_type === \"string\"\r\n ? { agentType: input.agent_type }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"SubagentStop\": {\r\n // agent_id/agent_type stay optional — the SDK does not reliably\r\n // populate agent_type on SubagentStop (real-world quirk).\r\n const ev: SubagentStopEvent = {\r\n ...base,\r\n ...(typeof input.agent_id === \"string\" ? { agentId: input.agent_id } : {}),\r\n ...(typeof input.agent_type === \"string\"\r\n ? { agentType: input.agent_type }\r\n : {}),\r\n ...(typeof input.agent_transcript_path === \"string\"\r\n ? { agentTranscriptPath: input.agent_transcript_path }\r\n : {}),\r\n ...(typeof input.last_assistant_message === \"string\"\r\n ? { lastAssistantMessage: input.last_assistant_message }\r\n : {}),\r\n ...(typeof input.stop_hook_active === \"boolean\"\r\n ? { stopHookActive: input.stop_hook_active }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"PostCompact\": {\r\n // Claude Code does NOT wire PostCompact as a normalized lifecycle hook\r\n // (capabilities.postCompact is unset, so installHooks never registers\r\n // it) — but the exhaustive guard below requires a case for every\r\n // HookEventName. This arm is a SAFE passthrough: it normalizes the\r\n // PreCompact-shaped `trigger` defensively, so a manual\r\n // `hook claude-code PostCompact` invocation normalizes instead of\r\n // throwing. It mirrors the PreCompact case byte-for-byte.\r\n const ev: PostCompactEvent = {\r\n ...base,\r\n ...(input.trigger === \"auto\" || input.trigger === \"manual\"\r\n ? { trigger: input.trigger }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n default: {\r\n // Exhaustive guard — every HookEventName is handled above.\r\n const _never: never = event;\r\n throw new Error(`unsupported claude-code hook event: ${String(_never)}`);\r\n }\r\n }\r\n }\r\n\r\n // ── Runtime: normalized response → Claude native hook reply ──────────────\r\n\r\n formatReply(event: HookEventName, response: HookResponse): HookReply {\r\n const hookEventName = event as ClaudeHookEvent;\r\n const decision = response.decision ?? \"allow\";\r\n\r\n // PermissionRequest replies use Claude's nested decision{behavior} envelope\r\n // and are the ONE event where an EXPLICIT \"allow\" is an ACTIVE grant (it\r\n // suppresses the permission dialog) rather than passthrough:\r\n // allow → decision{behavior:\"allow\"} (+updatedInput when set);\r\n // Claude still enforces its own deny rules — an allow\r\n // never overrides a matching deny rule (host-enforced).\r\n // modify → an allow grant carrying updatedInput.\r\n // deny → decision{behavior:\"deny\", message} (shown to Claude).\r\n // ask/context/void → NO decision output: fall through to the native\r\n // dialog (the dialog IS the ask).\r\n if (event === \"PermissionRequest\") {\r\n if (response.decision === \"deny\") {\r\n return this.stdout({\r\n hookSpecificOutput: {\r\n hookEventName,\r\n decision: {\r\n behavior: \"deny\",\r\n message: response.reason ?? \"Blocked by hook\",\r\n },\r\n },\r\n });\r\n }\r\n if (\r\n response.decision === \"allow\" ||\r\n (response.decision === \"modify\" && response.updatedInput)\r\n ) {\r\n return this.stdout({\r\n hookSpecificOutput: {\r\n hookEventName,\r\n decision: {\r\n behavior: \"allow\",\r\n ...(response.updatedInput\r\n ? { updatedInput: response.updatedInput }\r\n : {}),\r\n },\r\n },\r\n });\r\n }\r\n return { exitCode: 0 };\r\n }\r\n\r\n // PostToolUseFailure (feedback beside the error) and SubagentStart (context\r\n // injected at the start of the SUBAGENT's conversation) are observe/context-\r\n // only on Claude: \"context\" emits additionalContext, and a \"deny\" DEGRADES\r\n // to the same shape carrying the reason (the tool already failed / the\r\n // spawn is not blockable). Everything else passes through.\r\n if (event === \"PostToolUseFailure\" || event === \"SubagentStart\") {\r\n const context =\r\n decision === \"context\"\r\n ? response.additionalContext\r\n : decision === \"deny\"\r\n ? response.reason ?? response.additionalContext\r\n : undefined;\r\n if (context) {\r\n return this.stdout({\r\n hookSpecificOutput: { hookEventName, additionalContext: context },\r\n });\r\n }\r\n return { exitCode: 0 };\r\n }\r\n\r\n // deny → block the action with a reason (exit 0; JSON carries the decision).\r\n // Claude's deny shape is EVENT-SPECIFIC: PreToolUse uses\r\n // hookSpecificOutput.permissionDecision, but Stop / SubagentStop /\r\n // UserPromptSubmit / PostToolUse honor only the TOP-LEVEL\r\n // {\"decision\":\"block\",\"reason\"} — rendering those as permissionDecision is\r\n // silently ignored by Claude (found porting oh-my-claudecode: its ralph\r\n // persistence loop denies the Stop event, which never blocked through the\r\n // old shape). A SubagentStop block keeps the subagent running with `reason`\r\n // as its next instruction (Stop semantics).\r\n if (decision === \"deny\") {\r\n if (\r\n event === \"Stop\" ||\r\n event === \"SubagentStop\" ||\r\n event === \"UserPromptSubmit\" ||\r\n event === \"PostToolUse\"\r\n ) {\r\n return this.stdout({\r\n decision: \"block\",\r\n reason: response.reason ?? \"Blocked by hook\",\r\n });\r\n }\r\n return this.stdout({\r\n hookSpecificOutput: {\r\n hookEventName,\r\n permissionDecision: \"deny\",\r\n permissionDecisionReason: response.reason ?? \"Blocked by hook\",\r\n },\r\n });\r\n }\r\n\r\n // ask → prompt the user to confirm.\r\n if (decision === \"ask\") {\r\n return this.stdout({\r\n hookSpecificOutput: {\r\n hookEventName,\r\n permissionDecision: \"ask\",\r\n permissionDecisionReason:\r\n response.reason ?? \"Confirmation required by hook\",\r\n },\r\n });\r\n }\r\n\r\n // modify → rewrite PreToolUse input (only where Claude supports it).\r\n if (decision === \"modify\") {\r\n if (event === \"PreToolUse\" && response.updatedInput) {\r\n return this.stdout({\r\n hookSpecificOutput: { hookEventName, updatedInput: response.updatedInput },\r\n });\r\n }\r\n // Output rewrite is unsupported on Claude; fall through to allow.\r\n }\r\n\r\n // context → inject soft guidance (also the SessionStart context path).\r\n if (decision === \"context\" && response.additionalContext) {\r\n return this.stdout({\r\n hookSpecificOutput: { hookEventName, additionalContext: response.additionalContext },\r\n });\r\n }\r\n\r\n // allow / void / unsupported-degradation → pass through with exit 0.\r\n return { exitCode: 0 };\r\n }\r\n\r\n private stdout(payload: unknown): HookReply {\r\n return { exitCode: 0, stdout: JSON.stringify(payload) };\r\n }\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// configPatch: sensitive-key denylist + JSON leaf-path helpers\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * SENSITIVE-KEY DENYLIST (claude-code, v1) — THE documented list. configPatch\r\n * targeting any key below is HARD-REFUSED (warn ChangeRecord, never applied;\r\n * no override flag in v1). Rationale: configPatch writes bare host keys with\r\n * no inherent attribution, and these keys are security-relevant — permission\r\n * grants, tool allowlists, credential/auth helpers, login pinning, and any\r\n * env var that can reroute credentials or traffic. The OMC case\r\n * `env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS` passes; credential rerouting and\r\n * self-granted permissions do not. Reviewed whenever the host matrix updates.\r\n *\r\n * permissions, permissions.* — self-granted permission rules\r\n * allowedTools / disallowedTools (.*) — tool allowlist tampering\r\n * apiKey* (e.g. apiKeyHelper) — credential helpers\r\n * awsAuthRefresh / awsCredentialExport — AWS credential plumbing\r\n * forceLoginMethod / forceLoginOrgUUID — login/org pinning\r\n * otelHeadersHelper — telemetry-header (token) helper\r\n * hooks*, mcpServers* (+ enable/enabled/disabledMcpjsonServers)\r\n * — refused upstream by the\r\n * agent-connector NAMESPACE guard\r\n * env.ANTHROPIC_* — API key / base-URL rerouting\r\n * env.AWS_* — AWS credentials\r\n * env.*_PROXY — traffic interception\r\n * env.*TOKEN* / env.*KEY* / env.*SECRET* — generic credential patterns\r\n */\r\nconst SENSITIVE_KEY_RULES: ReadonlyArray<{ re: RegExp; label: string }> = [\r\n { re: /^permissions(\\.|$)/, label: \"permissions\" },\r\n { re: /^allowedTools(\\.|$)/, label: \"allowedTools\" },\r\n { re: /^disallowedTools(\\.|$)/, label: \"disallowedTools\" },\r\n { re: /^apiKey/i, label: \"apiKey*\" },\r\n { re: /^awsAuthRefresh$/, label: \"awsAuthRefresh\" },\r\n { re: /^awsCredentialExport$/, label: \"awsCredentialExport\" },\r\n { re: /^forceLoginMethod$/, label: \"forceLoginMethod\" },\r\n { re: /^forceLoginOrgUUID$/, label: \"forceLoginOrgUUID\" },\r\n { re: /^otelHeadersHelper$/, label: \"otelHeadersHelper\" },\r\n { re: /^env\\.ANTHROPIC_/, label: \"env.ANTHROPIC_*\" },\r\n { re: /^env\\.AWS_/, label: \"env.AWS_*\" },\r\n { re: /^env\\.[^.]*_PROXY(\\.|$)/i, label: \"env.*_PROXY\" },\r\n { re: /^env\\.[^.]*TOKEN/i, label: \"env.*TOKEN*\" },\r\n { re: /^env\\.[^.]*KEY/i, label: \"env.*KEY*\" },\r\n { re: /^env\\.[^.]*SECRET/i, label: \"env.*SECRET*\" },\r\n];\r\n\r\n/**\r\n * The matched denylist pattern label when `key` is sensitive on claude-code,\r\n * else null. Exported so tests and docs stay pinned to the real list.\r\n */\r\nexport function claudeSensitiveKeyViolation(key: string): string | null {\r\n for (const rule of SENSITIVE_KEY_RULES) {\r\n if (rule.re.test(key)) return rule.label;\r\n }\r\n return null;\r\n}\r\n\r\n/** Result of looking up a dotted leaf path in a parsed JSON object. */\r\ntype JsonLeafLookup =\r\n | { kind: \"absent\" }\r\n | { kind: \"present\"; value: JsonValue }\r\n | { kind: \"blocked\"; atPath: string };\r\n\r\n/**\r\n * Walk `segments` (a validated dotted leaf path) through `root`. \"blocked\"\r\n * reports the first intermediate that exists but is not a plain object —\r\n * the skip-warn case (we never replace a non-object intermediate).\r\n */\r\nfunction readJsonLeaf(root: Record<string, unknown>, segments: string[]): JsonLeafLookup {\r\n let node: Record<string, unknown> = root;\r\n for (let i = 0; i < segments.length - 1; i++) {\r\n const next = node[segments[i]!];\r\n if (next === undefined) return { kind: \"absent\" };\r\n if (next === null || typeof next !== \"object\" || Array.isArray(next)) {\r\n return { kind: \"blocked\", atPath: segments.slice(0, i + 1).join(\".\") };\r\n }\r\n node = next as Record<string, unknown>;\r\n }\r\n const leaf = node[segments[segments.length - 1]!];\r\n if (leaf === undefined) return { kind: \"absent\" };\r\n return { kind: \"present\", value: leaf as JsonValue };\r\n}\r\n\r\n/**\r\n * Write `value` at the leaf, creating ONLY absent intermediate objects along\r\n * the way (callers must have verified the path is not blocked).\r\n */\r\nfunction writeJsonLeaf(\r\n root: Record<string, unknown>,\r\n segments: string[],\r\n value: JsonValue,\r\n): void {\r\n let node: Record<string, unknown> = root;\r\n for (let i = 0; i < segments.length - 1; i++) {\r\n const seg = segments[i]!;\r\n const next = node[seg];\r\n if (next === undefined) {\r\n const created: Record<string, unknown> = {};\r\n node[seg] = created;\r\n node = created;\r\n } else {\r\n node = next as Record<string, unknown>;\r\n }\r\n }\r\n node[segments[segments.length - 1]!] = value;\r\n}\r\n\r\n/**\r\n * Delete the leaf key only. Intermediate objects — even ones we created — are\r\n * deliberately left in place (harmless; pruning risks collateral).\r\n */\r\nfunction deleteJsonLeaf(root: Record<string, unknown>, segments: string[]): void {\r\n let node: Record<string, unknown> = root;\r\n for (let i = 0; i < segments.length - 1; i++) {\r\n const next = node[segments[i]!];\r\n if (next === null || typeof next !== \"object\" || Array.isArray(next)) return;\r\n node = next as Record<string, unknown>;\r\n }\r\n delete node[segments[segments.length - 1]!];\r\n}\r\n\r\n/** Claude Code native interpolation token: `${env:VAR}` → `${VAR}`. */\r\nfunction claudeEnvToken(name: string): string {\r\n return `\\${${name}}`;\r\n}\r\n\r\nexport const adapter = new ClaudeCodeAdapter();\r\nexport default adapter;\r\n"],"mappings":"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","names":["entry"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapters/qwen-code/index.ts"],"sourcesContent":["/**\r\n * adapters/qwen-code — Qwen Code (Qwen CLI) platform adapter for agent-connector.\r\n *\r\n * Qwen Code is a Gemini-CLI-derived host, but — unlike Gemini CLI — its hook\r\n * WIRE PROTOCOL is Claude-compatible (verified against context-mode's proven\r\n * qwen-code adapter, which extends the shared ClaudeCodeBaseAdapter):\r\n *\r\n * - Hook event names are PascalCase, identical to Claude Code:\r\n * PreToolUse, PostToolUse, PreCompact, SessionStart, SessionEnd,\r\n * UserPromptSubmit, Stop, Notification — plus the E1 extension events\r\n * PermissionRequest, PostToolUseFailure, SubagentStart and SubagentStop,\r\n * all Qwen-native (verified against the upstream\r\n * docs/users/features/hooks.md: PermissionRequest takes the nested\r\n * hookSpecificOutput.decision{behavior} envelope, PostToolUseFailure /\r\n * SubagentStart are additionalContext feedback, and the Stop-class events\r\n * Stop / SubagentStop / UserPromptSubmit / PostToolUse block via the\r\n * TOP-LEVEL {\"decision\":\"block\",\"reason\"} shape — only PreToolUse uses\r\n * hookSpecificOutput.permissionDecision for deny).\r\n * (NOT Gemini's BeforeTool/AfterTool/PreCompress vocabulary.)\r\n * - Hook stdin JSON carries snake_case fields: session_id, transcript_path,\r\n * cwd, tool_name, tool_input, tool_response, source, reason, prompt,\r\n * trigger, stop_hook_active, message.\r\n * - Reply is exit-code 0 + a `hookSpecificOutput` JSON object on stdout\r\n * (permissionDecision allow|deny|ask, updatedInput, additionalContext) —\r\n * the Claude reply shape. Qwen's PreToolUse CAN rewrite tool input\r\n * (updatedInput; capabilities.canModifyArgs = true), but — verified against\r\n * qwen 0.17.1 — there is NO `updatedMCPToolOutput` honor on PostToolUse, so\r\n * this host CANNOT rewrite already-emitted tool output\r\n * (capabilities.canModifyOutput = false, like the Claude-family hosts).\r\n * - Native tool names are Qwen/Gemini-flavored (run_shell_command, read_file,\r\n * write_file, grep_search, …) — used only inside matcher strings; the wire\r\n * field names are unchanged from Claude.\r\n *\r\n * Native config (JSONC — Qwen shares Gemini's tolerant settings loader; we write\r\n * strict JSON and MERGE into any existing settings so user keys survive):\r\n * - MCP servers: user → ~/.qwen/settings.json; project → <projectDir>/.qwen/\r\n * settings.json. Root key \"mcpServers\". Qwen is a Gemini-CLI fork, so — like\r\n * Gemini — the MCP TRANSPORT IS SELECTED BY WHICH KEY IS PRESENT, not a\r\n * `type` field: stdio → {command,args,env(,cwd)}; SSE → {url, headers?};\r\n * streamable-HTTP → {httpUrl, headers?}.\r\n * - Hooks: the SAME settings.json, top-level sibling \"hooks\" key, keyed by the\r\n * PascalCase event name, each value an array of\r\n * `{ matcher, hooks:[{ type:\"command\", command }] }`.\r\n *\r\n * Env handling: Qwen's settings loader has no `${env:VAR}` interpolation of our\r\n * framework's dialect, so env / header / url refs resolve to literals at install\r\n * time via resolveEnvRefsDeep — the safe default shared with the Gemini / Codex\r\n * adapters.\r\n */\r\n\r\nimport { existsSync } from \"node:fs\";\r\nimport { homedir } from \"node:os\";\r\nimport { join } from \"node:path\";\r\n\r\nimport { BaseAdapter, type HookMergeDescriptor } from \"../base.js\";\r\nimport type { Adapter, HookReply, InstallContext, MemoryTarget, NormalizedEvent } from \"../spi.js\";\r\nimport type {\r\n ChangeRecord,\r\n CommandDef,\r\n DetectedPlatform,\r\n HealthCheck,\r\n HookEventName,\r\n HookParadigm,\r\n HookResponse,\r\n JsonValue,\r\n NotificationEvent,\r\n PermissionRequestEvent,\r\n PlatformCapabilities,\r\n PlatformId,\r\n PostToolUseEvent,\r\n PostToolUseFailureEvent,\r\n PostCompactEvent,\r\n PreCompactEvent,\r\n PreToolUseEvent,\r\n ServerDef,\r\n SessionEndEvent,\r\n SessionStartEvent,\r\n SkillDef,\r\n StatuslineContext,\r\n StopEvent,\r\n SubagentDef,\r\n SubagentStartEvent,\r\n SubagentStopEvent,\r\n Transport,\r\n UserPromptSubmitEvent,\r\n} from \"../../core/types.js\";\r\nimport { renderSkillMd } from \"../claude-code/render.js\";\r\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\r\nimport { writeTomlString } from \"../../core/toml.js\";\r\nimport {\r\n buildHomeBinStatuslineCommand,\r\n buildWrappedStdio,\r\n isHomeBinHookCommand,\r\n isHomeBinStatuslineCommand,\r\n} from \"../../core/spawn.js\";\r\nimport { normalizeSessionSource } from \"../claude-code/wire.js\";\r\nimport {\r\n type ConfigPatchLedgerEntry,\r\n addLedgerOwner,\r\n createLedgerEntry,\r\n describeJsonValue,\r\n dropLedgerEntry,\r\n findLedgerEntry,\r\n hashJsonValue,\r\n jsonDeepEquals,\r\n ledgerEntriesOwnedBy,\r\n loadConfigPatchLedger,\r\n removeLedgerOwner,\r\n saveConfigPatchLedger,\r\n} from \"../../core/config-patch-ledger.js\";\r\n\r\nconst HOST: PlatformId = \"qwen-code\";\r\nconst MCP_ROOT_KEY = \"mcpServers\";\r\n\r\n/**\r\n * settings.json leaf key the statusline surface owns on Qwen. UNLIKE claude-code\r\n * (a top-level `statusLine` leaf), Qwen nests its status-line config under `ui`\r\n * (`{ ui: { statusLine: { type:\"command\", command, refreshInterval? } } }` in\r\n * ~/.qwen/settings.json; verified against the qwen-code status-line docs and\r\n * QwenLM/qwen-code settings.md, shipped v0.14.3 / PR #2923). We own the\r\n * `ui.statusLine` leaf via the SAME refcounted ownership ledger as configPatch\r\n * (the ledger is surface-agnostic) — never clobbering a `ui.statusLine` a user\r\n * already set.\r\n */\r\nconst STATUSLINE_KEY = \"ui.statusLine\";\r\n\r\n/** A single hook registration entry as Qwen stores it (Claude-shaped, nested). */\r\ninterface QwenHookEntry {\r\n matcher: string;\r\n hooks: Array<{ type: \"command\"; command: string }>;\r\n}\r\n\r\n/** Shape of Qwen's settings.json (only the parts we touch). */\r\ninterface QwenSettingsFile {\r\n mcpServers?: Record<string, unknown>;\r\n hooks?: Record<string, QwenHookEntry[]>;\r\n [key: string]: unknown;\r\n}\r\n\r\n/**\r\n * Qwen's statusLine command stdin payload (the documented status-line input Qwen\r\n * pipes to the command, read once). Every field optional — a refresh only carries\r\n * what the host knows. Unmodeled fields (version, git, metrics, vim) stay in\r\n * StatuslineContext.raw. Sources: qwenlm.github.io/qwen-code-docs status-line page,\r\n * QwenLM/qwen-code settings.md.\r\n */\r\ninterface QwenStatuslineInput {\r\n session_id?: string;\r\n version?: string;\r\n model?: { display_name?: string };\r\n context_window?: {\r\n context_window_size?: number;\r\n used_percentage?: number;\r\n remaining_percentage?: number;\r\n current_usage?: number;\r\n total_input_tokens?: number;\r\n total_output_tokens?: number;\r\n };\r\n workspace?: { current_dir?: string };\r\n git?: { branch?: string };\r\n vim?: { mode?: string };\r\n}\r\n\r\n/**\r\n * Native MCP server entry shapes Qwen accepts under `mcpServers`. Qwen is a\r\n * Gemini-CLI fork, so the REMOTE transport is selected by WHICH KEY is present\r\n * (NOT a `type` field): SSE → `url`, streamable-HTTP → `httpUrl`. The stdio\r\n * entry keeps its (harmless, Claude-style) `type:\"stdio\"` tag — Qwen accepts it\r\n * and stdio is unambiguous by its command/args anyway.\r\n */\r\ninterface QwenStdioServer {\r\n type: \"stdio\";\r\n command: string;\r\n args: string[];\r\n env?: Record<string, string>;\r\n cwd?: string;\r\n}\r\ninterface QwenSseServer {\r\n url: string;\r\n headers?: Record<string, string>;\r\n}\r\ninterface QwenHttpServer {\r\n httpUrl: string;\r\n headers?: Record<string, string>;\r\n}\r\n\r\n/** Raw Qwen hook stdin payload (Claude-compatible snake_case wire fields). */\r\ninterface QwenWireInput {\r\n session_id?: string;\r\n transcript_path?: string;\r\n cwd?: string;\r\n hook_event_name?: string;\r\n\r\n // tool events\r\n tool_name?: string;\r\n tool_input?: Record<string, unknown>;\r\n /** PostToolUse result payload (string or structured). */\r\n tool_response?: unknown;\r\n\r\n // PermissionRequest — suggested permission entries the dialog would offer.\r\n permission_suggestions?: unknown[];\r\n\r\n // PostToolUseFailure (Qwen documents tool_use_id/error/is_interrupt; there is\r\n // no duration_ms on this host's payload).\r\n tool_use_id?: string;\r\n error?: string;\r\n is_interrupt?: boolean;\r\n\r\n // SubagentStart / SubagentStop — treat both as optional everywhere (the\r\n // Claude-family quirk: agent_type is not reliably populated on stop).\r\n agent_id?: string;\r\n agent_type?: string;\r\n // SubagentStop — the subagent's OWN transcript + its final message.\r\n agent_transcript_path?: string;\r\n last_assistant_message?: string;\r\n\r\n // SessionStart\r\n source?: string;\r\n // SessionEnd\r\n reason?: string;\r\n // UserPromptSubmit\r\n prompt?: string;\r\n // PreCompact\r\n trigger?: string;\r\n // Stop\r\n stop_hook_active?: boolean;\r\n // Notification\r\n message?: string;\r\n\r\n /** Injected by the entrypoint so the runtime knows which connector to dispatch. */\r\n connector?: unknown;\r\n}\r\n\r\nexport class QwenCodeAdapter extends BaseAdapter implements Adapter {\r\n readonly id: PlatformId = HOST;\r\n readonly name = \"Qwen CLI\";\r\n readonly paradigm: HookParadigm = \"json-stdio\";\r\n\r\n readonly capabilities: PlatformCapabilities = {\r\n // Memory surface: AGENTS.md-first managed block (project <projectDir>/AGENTS.md\r\n // via the base default — Qwen reads repo AGENTS.md natively alongside QWEN.md,\r\n // so no QWEN.md duplicate; user scope → ~/.qwen/QWEN.md below, the only\r\n // documented user-scope memory file).\r\n supportsMemory: true,\r\n preToolUse: true,\r\n postToolUse: true,\r\n preCompact: true,\r\n // Qwen fires PostCompact natively (observe-only — \"not in the decision mode\r\n // supported events list\"; QwenLM/qwen-code docs/users/features/hooks.md\r\n // \"#### PostCompact\", trigger + compact_summary payload).\r\n postCompact: true,\r\n sessionStart: true,\r\n sessionEnd: true,\r\n userPromptSubmit: true,\r\n stop: true,\r\n notification: true,\r\n // E1 events — all four are Qwen-native (its 16-event surface is strictly\r\n // wider than the canonical union).\r\n permissionRequest: true,\r\n postToolUseFailure: true,\r\n subagentStart: true,\r\n subagentStop: true,\r\n // Qwen's PreToolUse can rewrite input (updatedInput). It CANNOT rewrite\r\n // already-emitted tool output — `updatedMCPToolOutput` does not exist in\r\n // qwen 0.17.1, so canModifyOutput is false (like the Claude-family hosts).\r\n canModifyArgs: true,\r\n canModifyOutput: false,\r\n canInjectSessionContext: true,\r\n transports: [\"stdio\", \"sse\", \"http\"],\r\n // Content surfaces: Qwen ships native slash commands (TOML), subagents\r\n // (md+frontmatter), and skills (SKILL.md under .qwen/skills/<name>/).\r\n // Confirmed dir: .qwen/skills/ (project), ~/.qwen/skills/ (user scope).\r\n // Ground truth: kilo-pi-ground-truth.md § \"Already-known skills gaps\".\r\n supportsCommands: true,\r\n supportsSkills: true,\r\n supportsSubagents: true,\r\n // Statusline surface: qwen-code is the 2nd v1 host (after claude-code).\r\n // installStatusline wires settings.json `ui.statusLine` = {type:\"command\",\r\n // command:<home-bin statusline cmd>} through the SAME refcounted ownership\r\n // ledger as configPatch (never clobbers a ui.statusLine agent-connector does\r\n // not own). The key is NESTED here (`ui.statusLine`), unlike claude-code's\r\n // top-level `statusLine`. Confirmed config key + stdin payload against the\r\n // qwen-code status-line docs (shipped v0.14.3, PR #2923).\r\n supportsStatusline: true,\r\n // Native passthrough: Qwen's 16-event surface includes 3 host-specific events\r\n // with NO canonical HookEventName analog — TodoCreated / TodoCompleted /\r\n // StopFailure (QwenLM/qwen-code docs/users/features/hooks.md). A connector\r\n // reaches them via platforms[\"qwen-code\"].nativeHooks; installHooks files the\r\n // PascalCase event key VERBATIM into settings.json hooks, and the generic\r\n // uninstall reverses it.\r\n supportsNativeHooks: true,\r\n };\r\n\r\n // ── Detection ────────────────────────────────────────────────────────────\r\n\r\n detectInstalled(projectDir: string): DetectedPlatform {\r\n const userDir = join(homedir(), \".qwen\");\r\n const userSettings = join(userDir, \"settings.json\");\r\n const projectDirQwen = join(projectDir, \".qwen\");\r\n const projectSettings = join(projectDirQwen, \"settings.json\");\r\n const userInstalled = existsSync(userDir) || existsSync(userSettings);\r\n const projInstalled = existsSync(projectDirQwen) || existsSync(projectSettings);\r\n const installed = userInstalled || projInstalled;\r\n // Report the scope/path that actually matched, so a project-only install\r\n // isn't misreported as a (non-existent) user install.\r\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\r\n const configPath = scope === \"project\" ? projectSettings : userSettings;\r\n return {\r\n id: this.id,\r\n name: this.name,\r\n installed,\r\n paradigm: this.paradigm,\r\n capabilities: this.capabilities,\r\n configPath,\r\n scope,\r\n reason: installed\r\n ? scope === \"project\"\r\n ? `found project Qwen CLI config at ${projectSettings}`\r\n : `found Qwen CLI config under ${userDir}`\r\n : `no Qwen CLI config at ${userDir}`,\r\n confidence: installed ? \"high\" : \"low\",\r\n };\r\n }\r\n\r\n // ── Memory surface: ~/.qwen/QWEN.md at user scope ────────────────────────\r\n // Project scope stays on the AGENTS.md base default (Qwen reads the repo\r\n // AGENTS.md natively in ADDITION to QWEN.md — one canonical copy, never a\r\n // QWEN.md duplicate). User scope targets ~/.qwen/QWEN.md: Qwen has no\r\n // user-scope AGENTS.md, so the host's own global memory file is the only\r\n // file it actually reads there.\r\n protected override memoryTargets(ctx: InstallContext): MemoryTarget[] {\r\n if (this.memoryOverride(ctx)?.path || ctx.scope !== \"user\") {\r\n return super.memoryTargets(ctx);\r\n }\r\n return [\r\n {\r\n path: join(homedir(), \".qwen\", \"QWEN.md\"),\r\n reason: \"qwen-code global memory (~/.qwen/QWEN.md; no user-scope AGENTS.md exists)\",\r\n },\r\n ];\r\n }\r\n\r\n // ── Native paths ─────────────────────────────────────────────────────────\r\n\r\n getConfigDir(ctx: InstallContext): string {\r\n return ctx.scope === \"project\"\r\n ? join(ctx.projectDir, \".qwen\")\r\n : join(homedir(), \".qwen\");\r\n }\r\n\r\n /** MCP servers live in settings.json under `mcpServers`. */\r\n getServerConfigPath(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"settings.json\");\r\n }\r\n\r\n /** Hooks live in the SAME settings.json under the sibling `hooks` key. */\r\n getHookConfigPath(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"settings.json\");\r\n }\r\n\r\n // ── MCP server install / uninstall ───────────────────────────────────────\r\n\r\n installServer(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n const override = connector.platforms[HOST]?.server;\r\n if (!connector.server || override === false) {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n detail: connector.server\r\n ? \"server registration disabled for qwen-code\"\r\n : \"connector declares no MCP server\",\r\n },\r\n ];\r\n }\r\n\r\n // Shallow-merge any per-platform server override into the base ServerDef.\r\n const server: ServerDef =\r\n override && typeof override === \"object\"\r\n ? { ...connector.server, ...override }\r\n : connector.server;\r\n\r\n const serverPath = this.getServerConfigPath(ctx);\r\n const entry = this.renderServerEntry(ctx, server);\r\n\r\n return [\r\n this.upsertServerInJson(serverPath, MCP_ROOT_KEY, connector.id, entry, ctx.dryRun),\r\n ];\r\n }\r\n\r\n uninstallServer(ctx: InstallContext): ChangeRecord[] {\r\n const serverPath = this.getServerConfigPath(ctx);\r\n return [\r\n this.removeServerFromJson(serverPath, MCP_ROOT_KEY, ctx.connector.id, ctx.dryRun),\r\n ];\r\n }\r\n\r\n /**\r\n * Render a normalized ServerDef into Qwen's native mcpServers entry. As a\r\n * Gemini-CLI fork, the transport is encoded by WHICH KEY is present (NOT a\r\n * `type` field): command/args/env (stdio), url (sse), httpUrl (http).\r\n */\r\n private renderServerEntry(\r\n ctx: InstallContext,\r\n server: ServerDef,\r\n ): QwenStdioServer | QwenSseServer | QwenHttpServer {\r\n const transport: Transport = server.transport;\r\n\r\n if (transport === \"stdio\") {\r\n let command = server.command ?? \"\";\r\n let args = [...(server.args ?? [])];\r\n\r\n // Transparent telemetry wrapping: route the real command through\r\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\r\n ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\r\n\r\n const entry: QwenStdioServer = {\r\n type: \"stdio\",\r\n command: resolveEnvRefsDeep(command),\r\n args: args.map((a) => resolveEnvRefsDeep(a)),\r\n };\r\n const env = this.renderEnv(server.env);\r\n if (env) entry.env = env;\r\n if (server.cwd) entry.cwd = resolveEnvRefsDeep(server.cwd);\r\n return entry;\r\n }\r\n\r\n // SSE transport → `url` key.\r\n if (transport === \"sse\") {\r\n const entry: QwenSseServer = { url: resolveEnvRefsDeep(server.url ?? \"\") };\r\n const headers = this.renderEnv(server.headers);\r\n if (headers) entry.headers = headers;\r\n return entry;\r\n }\r\n\r\n // http (streamable-HTTP) and any other remote transport → `httpUrl` key.\r\n const entry: QwenHttpServer = { httpUrl: resolveEnvRefsDeep(server.url ?? \"\") };\r\n const headers = this.renderEnv(server.headers);\r\n if (headers) entry.headers = headers;\r\n return entry;\r\n }\r\n\r\n /**\r\n * Render env/header values. Qwen's settings loader does not interpret our\r\n * `${env:VAR}` dialect, so refs resolve to literals at install time — the safe\r\n * default shared with the Gemini / Codex adapters.\r\n */\r\n private renderEnv(\r\n env: Record<string, string> | undefined,\r\n ): Record<string, string> | undefined {\r\n if (!env || Object.keys(env).length === 0) return undefined;\r\n return resolveEnvRefsDeep({ ...env });\r\n }\r\n\r\n // ── Hook install / uninstall ─────────────────────────────────────────────\r\n\r\n installHooks(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n const override = connector.platforms[HOST];\r\n const hooksDisabled = override?.hooks === false;\r\n // `hooks: false` disables only the NORMALIZED events; nativeHooks is a\r\n // sibling, qwen-scoped declaration that installs regardless.\r\n const normalizedEvents = hooksDisabled ? [] : connector.hookEvents;\r\n const nativeHooks = override?.nativeHooks ?? {};\r\n const nativeEvents = Object.keys(nativeHooks);\r\n\r\n if (normalizedEvents.length === 0 && nativeEvents.length === 0) {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n detail: hooksDisabled ? \"hooks disabled for qwen-code\" : \"connector declares no hooks\",\r\n },\r\n ];\r\n }\r\n\r\n // Normalized events register their canonical PascalCase name verbatim (qwen's\r\n // hook vocabulary is Claude-identical — NO mapEvent, no warn path). Native\r\n // event-name keys ride the separate `native` pass (verbatim keys, FIRST-INNER\r\n // command match, the `(native)` detail) — see hookDescriptor + upsertHookEntries.\r\n const pending = normalizedEvents.map((event) => ({\r\n event,\r\n matcher: connector.hooks[event]?.matcher ?? \"\",\r\n }));\r\n const native = nativeEvents.map((event) => ({\r\n event,\r\n matcher: nativeHooks[event]?.matcher ?? \"\",\r\n }));\r\n return this.upsertHookEntries(\r\n ctx,\r\n this.getHookConfigPath(ctx),\r\n pending,\r\n this.hookDescriptor(ctx),\r\n native,\r\n );\r\n }\r\n\r\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\r\n return this.removeHookEntries(ctx, this.getHookConfigPath(ctx), this.hookDescriptor(ctx));\r\n }\r\n\r\n /**\r\n * Qwen's hook-merge descriptor (NESTED shape `{ matcher, hooks:[{type,command}] }`):\r\n * - NO mapEvent — qwen's events are Claude-identical, every canonical event is\r\n * supported natively, so there is no unmapped/warn path.\r\n * - install find (entryOwnsCommand) is connector-GENERIC: ANY of our commands in\r\n * the nested hooks array (= the old entryHasOurCommand).\r\n * - uninstall is NESTED: ownsEntryForRemove is never-true, so the engine only\r\n * ever runs stripInner — strip our owned inner commands, keep foreign ones,\r\n * drop entries left empty; `removed` = inner commands removed.\r\n * - the native pass uses FIRST-INNER (`hooks[0].command`) EXACT-command ownership\r\n * — qwen's exact current native match (NOT a `.some()`), distinct from the\r\n * connector-generic normalized find. qwen writes no version/envelope (no onMutate).\r\n */\r\n private hookDescriptor(ctx: InstallContext): HookMergeDescriptor<QwenHookEntry> {\r\n return {\r\n renderEntry: (_event, matcher, command) => ({\r\n matcher,\r\n hooks: [{ type: \"command\", command }],\r\n }),\r\n entryOwnsCommand: (entry, _command) =>\r\n (entry.hooks ?? []).some((h) => this.isOurCommand(h.command, ctx)),\r\n ownsEntryForRemove: () => () => false,\r\n stripInner: (c) => (entry) => {\r\n const innerBefore = entry.hooks?.length ?? 0;\r\n const inner = (entry.hooks ?? []).filter((h) => !this.isOurCommand(h.command, c));\r\n return {\r\n next: inner.length > 0 ? { matcher: entry.matcher ?? \"\", hooks: inner } : null,\r\n removed: innerBefore - inner.length,\r\n };\r\n },\r\n skipDetail: (e) => `hooks.${e} already registered`,\r\n removeDetail: (e, n) => `hooks.${e} (${n})`,\r\n absentDetail: \"no hooks section present\",\r\n noMatchDetail: \"no matching hook entries\",\r\n nativeOwnsCommand: (entry, command) => entry.hooks?.[0]?.command === command,\r\n nativeSkipDetail: (e) => `hooks.${e} (native) already registered`,\r\n nativeMutateDetail: (e) => `hooks.${e} (native)`,\r\n };\r\n }\r\n\r\n /** True when a hook command references our home binary AND this connector id\r\n * (anchored so a shared-prefix id can't collide — see isHomeBinHookCommand). */\r\n private isOurCommand(command: string | undefined, ctx: InstallContext): boolean {\r\n return isHomeBinHookCommand(command, ctx.homeBinPath, ctx.connector.id);\r\n }\r\n\r\n // ── Statusline surface (a HUD/status line) ────────────────────────────────\r\n // Wires settings.json `ui.statusLine` = { type:\"command\", command:<home-bin\r\n // statusline cmd> } through the SAME refcounted ownership ledger as configPatch\r\n // (the ledger primitives are surface-agnostic). qwen-code does NOT advertise\r\n // supportsConfigPatch, so — unlike claude-code, which routes the statusline\r\n // through its private applyConfigPatches loop — this adapter performs the nested\r\n // set-if-absent write directly with the exported ledger primitives. Semantics\r\n // are identical: never clobber a ui.statusLine agent-connector does not own\r\n // (skip-warn), record prior state + owner (refcounted across connectors),\r\n // reversible by uninstallStatusline (last-owner-verified delete). The key is\r\n // NESTED (`ui.statusLine`), so we own the `ui.statusLine` leaf — if the user\r\n // already has it, we skip-warn and never touch their value.\r\n //\r\n // The home-bin command makes Qwen exec\r\n // `<homeBin> statusline qwen-code --connector <id>` for every status refresh,\r\n // which re-imports the connector module and renders the line (runtime/\r\n // statusline-entrypoint). No telemetry in v1.\r\n\r\n /** The statusLine config object value agent-connector writes at `ui.statusLine`. */\r\n private statuslineValue(ctx: InstallContext): JsonValue {\r\n const command = buildHomeBinStatuslineCommand(ctx.homeBinPath, HOST, ctx.connector.id);\r\n return { type: \"command\", command };\r\n }\r\n\r\n override installStatusline(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.statusline == null) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no statusline\" }];\r\n }\r\n if (connector.platforms[HOST]?.statusline === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"statusline disabled for qwen-code\" }];\r\n }\r\n\r\n const filePath = this.getServerConfigPath(ctx);\r\n const symlink = this.symlinkPathWarning(filePath);\r\n if (symlink) return [symlink];\r\n\r\n // OVERWRITE GUARD (upsertServerInJson precedent): never round-trip a\r\n // present-but-unparseable settings file into `{}`.\r\n if (this.isPresentButUnparseable(filePath)) {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail: `existing ${filePath} is not parseable; statusline left unapplied (back it up / fix it, then re-run)`,\r\n },\r\n ];\r\n }\r\n const settings = this.readJson<Record<string, unknown>>(filePath) ?? {};\r\n if (typeof settings !== \"object\" || Array.isArray(settings)) {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail: `existing ${filePath} is not a JSON object; statusline left unapplied`,\r\n },\r\n ];\r\n }\r\n\r\n const ledger = loadConfigPatchLedger(ctx.dataRoot);\r\n const desired = this.statuslineValue(ctx);\r\n const segments = STATUSLINE_KEY.split(\".\");\r\n const leaf = readJsonLeaf(settings, segments);\r\n const entry = findLedgerEntry(ledger, HOST, filePath, STATUSLINE_KEY);\r\n const changes: ChangeRecord[] = [];\r\n\r\n if (leaf.kind === \"blocked\") {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail:\r\n `statusline ${STATUSLINE_KEY} skipped: \"${leaf.atPath}\" exists but is not an ` +\r\n `object — set ${STATUSLINE_KEY} manually if wanted`,\r\n },\r\n ];\r\n }\r\n\r\n if (leaf.kind === \"absent\") {\r\n // SET-IF-ABSENT: the one write path. Intermediates (`ui`) created as needed.\r\n writeJsonLeaf(settings, segments, desired);\r\n this.writeJson(filePath, settings, ctx.dryRun);\r\n if (entry) {\r\n // Stale ledger row (key deleted out from under us): re-assert the value,\r\n // keep existing owners (they still rely on the key), record what we wrote.\r\n entry.writtenValue = desired;\r\n entry.writtenValueHash = hashJsonValue(desired);\r\n addLedgerOwner(entry, connector.id, connector.version);\r\n } else {\r\n createLedgerEntry(ledger, {\r\n platform: HOST,\r\n file: filePath,\r\n key: STATUSLINE_KEY,\r\n value: desired,\r\n connectorId: connector.id,\r\n connectorVersion: connector.version,\r\n });\r\n }\r\n if (!ctx.dryRun) saveConfigPatchLedger(ctx.dataRoot, ledger);\r\n changes.push({\r\n platform: this.id,\r\n action: \"create\",\r\n path: filePath,\r\n detail: `statusline ${STATUSLINE_KEY}: <absent> → ${describeJsonValue(desired)}`,\r\n });\r\n return changes;\r\n }\r\n\r\n // Key PRESENT — never overwrite; the only question is ownership/refcount.\r\n if (!entry) {\r\n // User- (or other-tool-) owned. No ownership is taken even when the values\r\n // happen to match — uninstall must never delete a key we did not create.\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail:\r\n `statusline ${STATUSLINE_KEY} skipped: already set to ${describeJsonValue(leaf.value)} ` +\r\n `(not created by agent-connector) — left untouched`,\r\n },\r\n ];\r\n }\r\n\r\n if (!jsonDeepEquals(leaf.value, entry.writtenValue)) {\r\n // DRIFT: the user edited the value after we wrote it. Never revert.\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail:\r\n `statusline ${STATUSLINE_KEY}: value changed since install ` +\r\n `(current ${describeJsonValue(leaf.value)}, wrote ${describeJsonValue(entry.writtenValue)}); ` +\r\n `leaving in place`,\r\n },\r\n ];\r\n }\r\n\r\n if (jsonDeepEquals(desired, leaf.value)) {\r\n // Same value we own: register as co-owner (refcount++) or idempotent skip.\r\n const owners = entry.owners.map((o) => o.connectorId);\r\n if (addLedgerOwner(entry, connector.id, connector.version)) {\r\n if (!ctx.dryRun) saveConfigPatchLedger(ctx.dataRoot, ledger);\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n path: filePath,\r\n detail: `statusline ${STATUSLINE_KEY} already installed; registered as co-owner (co-owned with ${owners.join(\", \")})`,\r\n },\r\n ];\r\n }\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n path: filePath,\r\n detail: `statusline ${STATUSLINE_KEY} already installed`,\r\n },\r\n ];\r\n }\r\n\r\n // FIRST-WRITER-WINS: another connector owns the key with a different value.\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail:\r\n `statusline ${STATUSLINE_KEY} skipped: already owned by ${entry.owners\r\n .map((o) => o.connectorId)\r\n .join(\", \")} with a different value — left untouched`,\r\n },\r\n ];\r\n }\r\n\r\n override uninstallStatusline(ctx: InstallContext): ChangeRecord[] {\r\n const ledger = loadConfigPatchLedger(ctx.dataRoot);\r\n // Release ONLY the ui.statusLine ledger row this connector owns (keyed off the\r\n // ledger, not the declaration, so an id-only synthetic uninstall still reclaims\r\n // it). Last-owner-verified delete: remove the key ONLY when last-owner ∧\r\n // value-unchanged ∧ prior-absent (else skip-warn + leave the key).\r\n const owned = ledgerEntriesOwnedBy(ledger, HOST, ctx.connector.id).filter(\r\n (e) => e.key === STATUSLINE_KEY,\r\n );\r\n if (owned.length === 0) {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n detail: \"statusline: no ownership recorded; left untouched\",\r\n },\r\n ];\r\n }\r\n\r\n const changes: ChangeRecord[] = [];\r\n let ledgerMutated = false;\r\n\r\n // All rows share one file (the scope-resolved settings.json), but group by\r\n // file anyway so a scope drift between install and uninstall stays correct.\r\n const byFile = new Map<string, ConfigPatchLedgerEntry[]>();\r\n for (const entry of owned) {\r\n const bucket = byFile.get(entry.file) ?? [];\r\n bucket.push(entry);\r\n byFile.set(entry.file, bucket);\r\n }\r\n\r\n for (const [filePath, entries] of byFile) {\r\n const symlink = this.symlinkPathWarning(filePath);\r\n if (symlink) {\r\n changes.push(symlink);\r\n continue;\r\n }\r\n\r\n const unparseable = this.isPresentButUnparseable(filePath);\r\n const settings = unparseable ? null : this.readJson<Record<string, unknown>>(filePath);\r\n let fileMutated = false;\r\n\r\n for (const entry of entries) {\r\n const { lastOwner } = removeLedgerOwner(entry, ctx.connector.id);\r\n ledgerMutated = true;\r\n\r\n if (!lastOwner) {\r\n // Shared-flag case: A uninstalls, B still relies on the key.\r\n changes.push({\r\n platform: this.id,\r\n action: \"skip\",\r\n path: filePath,\r\n detail: `statusline ${entry.key} retained: still owned by ${entry.owners\r\n .map((o) => o.connectorId)\r\n .join(\", \")}`,\r\n });\r\n continue;\r\n }\r\n\r\n // Last owner out → the ledger row is dropped on every branch below; the\r\n // KEY is removed only on the fully-verified branch.\r\n dropLedgerEntry(ledger, entry);\r\n\r\n if (unparseable) {\r\n changes.push({\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail: `statusline ${entry.key}: ${filePath} is not parseable; key left in place (ownership released)`,\r\n });\r\n continue;\r\n }\r\n if (!settings || typeof settings !== \"object\" || Array.isArray(settings)) {\r\n changes.push({\r\n platform: this.id,\r\n action: \"skip\",\r\n path: filePath,\r\n detail: `statusline ${entry.key} already absent (no settings file); ownership record dropped`,\r\n });\r\n continue;\r\n }\r\n const leaf = readJsonLeaf(settings, entry.key.split(\".\"));\r\n if (leaf.kind !== \"present\") {\r\n changes.push({\r\n platform: this.id,\r\n action: \"skip\",\r\n path: filePath,\r\n detail: `statusline ${entry.key} already absent; ownership record dropped`,\r\n });\r\n continue;\r\n }\r\n if (entry.prior?.present !== false || !jsonDeepEquals(leaf.value, entry.writtenValue)) {\r\n // User edited the value after install (or the row predates the\r\n // set-if-absent guarantee): deleting would clobber them. Leave it.\r\n changes.push({\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail:\r\n `statusline ${entry.key}: value changed since install ` +\r\n `(current ${describeJsonValue(leaf.value)}, wrote ${describeJsonValue(entry.writtenValue)}); ` +\r\n `left in place`,\r\n });\r\n continue;\r\n }\r\n\r\n // VERIFIED: last owner + current === writtenValue + prior absent. Delete\r\n // the leaf key (the `ui` intermediate we may have created is left in place).\r\n deleteJsonLeaf(settings, entry.key.split(\".\"));\r\n fileMutated = true;\r\n changes.push({\r\n platform: this.id,\r\n action: \"remove\",\r\n path: filePath,\r\n detail: `statusline ${entry.key} removed (was ${describeJsonValue(entry.writtenValue)})`,\r\n });\r\n }\r\n\r\n if (fileMutated && settings) this.writeJson(filePath, settings, ctx.dryRun);\r\n }\r\n\r\n if (ledgerMutated && !ctx.dryRun) saveConfigPatchLedger(ctx.dataRoot, ledger);\r\n return changes;\r\n }\r\n\r\n /**\r\n * Parse Qwen's statusLine stdin JSON into the normalized\r\n * {@link StatuslineContext}. Qwen pipes a JSON object to the statusLine command\r\n * on stdin (model, context_window, workspace, git, …); fields the payload omits\r\n * stay undefined. `raw` keeps the verbatim payload (incl. version/git/metrics/\r\n * vim). NOTE: Qwen has NO cost analog (no cost field in the payload), so\r\n * `ctx.cost` is intentionally left undefined. Sources: qwen-code status-line\r\n * docs, QwenLM/qwen-code settings.md.\r\n */\r\n parseStatusInput(raw: unknown): StatuslineContext {\r\n const input = (raw ?? {}) as QwenStatuslineInput;\r\n\r\n const ctx: StatuslineContext = {\r\n host: HOST,\r\n capabilities: this.capabilities,\r\n raw,\r\n };\r\n if (typeof input.session_id === \"string\" && input.session_id !== \"\") {\r\n ctx.sessionId = input.session_id;\r\n }\r\n if (typeof input.workspace?.current_dir === \"string\") {\r\n ctx.cwd = input.workspace.current_dir;\r\n }\r\n if (typeof input.model?.display_name === \"string\") {\r\n ctx.model = { displayName: input.model.display_name };\r\n }\r\n const cw = input.context_window;\r\n if (cw) {\r\n const context: { usedTokens?: number; maxTokens?: number; percent?: number } = {};\r\n if (typeof cw.context_window_size === \"number\") context.maxTokens = cw.context_window_size;\r\n if (typeof cw.current_usage === \"number\") context.usedTokens = cw.current_usage;\r\n if (typeof cw.used_percentage === \"number\") context.percent = cw.used_percentage;\r\n if (\r\n context.usedTokens !== undefined ||\r\n context.maxTokens !== undefined ||\r\n context.percent !== undefined\r\n ) {\r\n ctx.context = context;\r\n }\r\n }\r\n // ctx.cost stays undefined: Qwen's status payload has no cost analog.\r\n return ctx;\r\n }\r\n\r\n /** Format the rendered status line into Qwen's native reply: stdout = line, exit 0. */\r\n formatStatusOutput(rendered: string): HookReply {\r\n return { exitCode: 0, stdout: rendered };\r\n }\r\n\r\n // ── Content surfaces: commands / subagents ───────────────────────────────\r\n // CONTENT-ONLY: pure native-file writers under <qwenDir>/{commands,agents}. No\r\n // runtime dispatch, no home-bin pointer, no telemetry wrap. Each method is\r\n // idempotent (byte-identical → skip) via BaseAdapter.writeContentFile and\r\n // reversible via removeContentFile. Honors platforms[\"qwen-code\"] per-surface\r\n // false to skip. Qwen has NO Agent-Skills surface, so skills are left to the\r\n // BaseAdapter skip/warn default (supportsSkills stays false).\r\n\r\n private commandsDir(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"commands\");\r\n }\r\n private skillsDir(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"skills\");\r\n }\r\n private agentsDir(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"agents\");\r\n }\r\n\r\n /** Native command file path: <qwenDir>/commands/<name>.toml. */\r\n private commandPath(ctx: InstallContext, name: string): string {\r\n return join(this.commandsDir(ctx), `${name}.toml`);\r\n }\r\n /** Native skill dir: <qwenDir>/skills/<name>. */\r\n private skillDir(ctx: InstallContext, name: string): string {\r\n return join(this.skillsDir(ctx), name);\r\n }\r\n /** Native subagent file path: <qwenDir>/agents/<name>.md. */\r\n private subagentPath(ctx: InstallContext, name: string): string {\r\n return join(this.agentsDir(ctx), `${name}.md`);\r\n }\r\n\r\n // ── Commands ──────────────────────────────────────────────────────────────\r\n\r\n override installCommands(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.platforms[HOST]?.commands === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"commands disabled for qwen-code\" }];\r\n }\r\n if (connector.commands.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\r\n }\r\n return connector.commands.map((cmd) =>\r\n this.writeContentFile(\r\n this.commandPath(ctx, cmd.name),\r\n this.renderCommand(cmd),\r\n ctx.dryRun,\r\n ),\r\n );\r\n }\r\n\r\n override uninstallCommands(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.commands.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\r\n }\r\n return connector.commands.map((cmd) =>\r\n this.removeContentFile(this.commandPath(ctx, cmd.name), ctx.dryRun),\r\n );\r\n }\r\n\r\n /** Render a command to Qwen's native TOML (description, prompt). */\r\n private renderCommand(cmd: CommandDef): string {\r\n const obj: Record<string, unknown> = {};\r\n if (cmd.description !== undefined) obj.description = cmd.description;\r\n obj.prompt = cmd.prompt;\r\n return writeTomlString(obj);\r\n }\r\n\r\n // ── Skills ────────────────────────────────────────────────────────────────\r\n // Qwen reads SKILL.md from <qwenDir>/skills/<name>/SKILL.md.\r\n // Project dir: <projectDir>/.qwen/skills/<name>/SKILL.md\r\n // User dir: ~/.qwen/skills/<name>/SKILL.md\r\n // Confirmed: kilo-pi-ground-truth.md § \"Already-known skills gaps\" (.qwen/skills).\r\n\r\n override installSkills(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.platforms[HOST]?.skills === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"skills disabled for qwen-code\" }];\r\n }\r\n if (connector.skills.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\r\n }\r\n const changes: ChangeRecord[] = [];\r\n for (const skill of connector.skills) {\r\n const dir = this.skillDir(ctx, skill.name);\r\n changes.push(\r\n this.writeContentFile(join(dir, \"SKILL.md\"), this.renderSkill(skill), ctx.dryRun),\r\n );\r\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\r\n const target = this.resolveWithin(dir, rel);\r\n if (target === null) {\r\n changes.push({\r\n platform: this.id,\r\n action: \"warn\",\r\n detail: `skill resource \"${rel}\" escapes the skill dir; skipped`,\r\n });\r\n continue;\r\n }\r\n changes.push(this.writeContentFile(target, contents, ctx.dryRun));\r\n }\r\n }\r\n return changes;\r\n }\r\n\r\n override uninstallSkills(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.skills.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\r\n }\r\n const changes: ChangeRecord[] = [];\r\n for (const skill of connector.skills) {\r\n const dir = this.skillDir(ctx, skill.name);\r\n changes.push(this.removeContentFile(join(dir, \"SKILL.md\"), ctx.dryRun));\r\n for (const rel of Object.keys(skill.resources ?? {})) {\r\n const target = this.resolveWithin(dir, rel);\r\n if (target === null) continue;\r\n changes.push(this.removeContentFile(target, ctx.dryRun));\r\n }\r\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\r\n }\r\n return changes;\r\n }\r\n\r\n private renderSkill(skill: SkillDef): string {\r\n return renderSkillMd(skill);\r\n }\r\n\r\n // ── Subagents ──────────────────────────────────────────────────────────────\r\n\r\n override installSubagents(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.platforms[HOST]?.subagents === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"subagents disabled for qwen-code\" }];\r\n }\r\n if (connector.subagents.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\r\n }\r\n return connector.subagents.map((agent) =>\r\n this.writeContentFile(\r\n this.subagentPath(ctx, agent.name),\r\n this.renderSubagent(agent),\r\n ctx.dryRun,\r\n ),\r\n );\r\n }\r\n\r\n override uninstallSubagents(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.subagents.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\r\n }\r\n return connector.subagents.map((agent) =>\r\n this.removeContentFile(this.subagentPath(ctx, agent.name), ctx.dryRun),\r\n );\r\n }\r\n\r\n /** Render a subagent to md+frontmatter (name, description, tools, model) + prompt body. */\r\n private renderSubagent(agent: SubagentDef): string {\r\n const frontmatter: Record<string, unknown> = {\r\n name: agent.name,\r\n description: agent.description,\r\n };\r\n const allow = agent.tools?.allow;\r\n if (allow && allow.length > 0) frontmatter.tools = allow.join(\", \");\r\n if (agent.model !== undefined) frontmatter.model = agent.model;\r\n if (agent.extra) Object.assign(frontmatter, agent.extra);\r\n return this.renderFrontmatterMd(frontmatter, agent.prompt);\r\n }\r\n\r\n // ── Diagnostics ──────────────────────────────────────────────────────────\r\n\r\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\r\n const settingsPath = this.getHookConfigPath(ctx);\r\n const connectorId = ctx.connector.id;\r\n const homeBin = ctx.homeBinPath;\r\n const hookEvents = ctx.connector.hookEvents;\r\n const checks: HealthCheck[] = [\r\n {\r\n name: `${this.name}: settings.json present`,\r\n check: () =>\r\n existsSync(settingsPath)\r\n ? { status: \"OK\", detail: settingsPath }\r\n : { status: \"FAIL\", detail: `not found: ${settingsPath}` },\r\n },\r\n {\r\n name: `${this.name}: hook command registered`,\r\n check: () => {\r\n if (hookEvents.length === 0) {\r\n return { status: \"OK\", detail: \"no hooks declared\" };\r\n }\r\n const settings = this.readJson<QwenSettingsFile>(settingsPath);\r\n if (!settings) return { status: \"FAIL\", detail: `cannot read ${settingsPath}` };\r\n const hooks = settings.hooks ?? {};\r\n const registered = Object.values(hooks).some((entries) =>\r\n (entries ?? []).some((e) =>\r\n (e.hooks ?? []).some((h) =>\r\n isHomeBinHookCommand(h.command, homeBin, connectorId),\r\n ),\r\n ),\r\n );\r\n return registered\r\n ? { status: \"OK\", detail: \"hook command present\" }\r\n : { status: \"FAIL\", detail: `no hook for ${connectorId} in ${settingsPath}` };\r\n },\r\n },\r\n ];\r\n\r\n // Content-surface checks: assert presence of all three content surfaces\r\n // (commands, skills, subagents) this connector declares.\r\n for (const cmd of ctx.connector.commands) {\r\n const p = this.commandPath(ctx, cmd.name);\r\n checks.push({\r\n name: `${this.name}: command ${cmd.name} present`,\r\n check: () =>\r\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\r\n });\r\n }\r\n for (const skill of ctx.connector.skills) {\r\n const p = join(this.skillDir(ctx, skill.name), \"SKILL.md\");\r\n checks.push({\r\n name: `${this.name}: skill ${skill.name} present`,\r\n check: () =>\r\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\r\n });\r\n }\r\n for (const agent of ctx.connector.subagents) {\r\n const p = this.subagentPath(ctx, agent.name);\r\n checks.push({\r\n name: `${this.name}: subagent ${agent.name} present`,\r\n check: () =>\r\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\r\n });\r\n }\r\n\r\n // Statusline check: assert it when the connector declares a statusline AND it\r\n // is not disabled for this host, OR when the ownership ledger holds a\r\n // ui.statusLine row this connector owns (the REGISTERED-connector path:\r\n // connectorFromMeta can't re-expose the render fn, so statusline comes back\r\n // undefined — but the ledger row proves the surface was wired). Mirrors\r\n // claude-code's \"statusline wired\" check; ui.statusLine.command must be OUR\r\n // home-bin statusline command (OK); present-but-not-ours / absent → FAIL.\r\n const statuslineLedgerOwned = ledgerEntriesOwnedBy(\r\n loadConfigPatchLedger(ctx.dataRoot),\r\n HOST,\r\n connectorId,\r\n ).some((e) => e.key === STATUSLINE_KEY);\r\n if (\r\n (ctx.connector.statusline != null || statuslineLedgerOwned) &&\r\n ctx.connector.platforms[HOST]?.statusline !== false\r\n ) {\r\n checks.push({\r\n name: `${this.name}: statusline wired`,\r\n check: () => {\r\n const settings = this.readJson<{ ui?: { statusLine?: { command?: unknown } } }>(\r\n settingsPath,\r\n );\r\n const command = settings?.ui?.statusLine?.command;\r\n if (command === undefined) {\r\n return { status: \"FAIL\", detail: `ui.statusLine not set in ${settingsPath}` };\r\n }\r\n if (\r\n typeof command === \"string\" &&\r\n isHomeBinStatuslineCommand(command, homeBin, connectorId)\r\n ) {\r\n return { status: \"OK\", detail: \"ui.statusLine command present\" };\r\n }\r\n // Present but not ours — a non-AC ui.statusLine we must never clobber.\r\n return {\r\n status: \"FAIL\",\r\n detail: `ui.statusLine in ${settingsPath} is not agent-connector's (left untouched)`,\r\n };\r\n },\r\n });\r\n }\r\n return checks;\r\n }\r\n\r\n // ── Runtime: parse Qwen stdin JSON → normalized event ────────────────────\r\n\r\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\r\n const input = (raw ?? {}) as QwenWireInput;\r\n const connectorId = typeof input.connector === \"string\" ? input.connector : \"\";\r\n const sessionId = extractSessionId(input);\r\n const projectDir = typeof input.cwd === \"string\" ? input.cwd : undefined;\r\n\r\n const base = {\r\n hostPlatform: HOST,\r\n connectorId,\r\n sessionId,\r\n raw,\r\n ...(projectDir !== undefined ? { projectDir } : {}),\r\n } as const;\r\n\r\n switch (event) {\r\n case \"PreToolUse\": {\r\n const ev: PreToolUseEvent = {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n };\r\n return ev;\r\n }\r\n case \"PostToolUse\": {\r\n const ev: PostToolUseEvent = {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n ...(toolResponseToString(input.tool_response) !== undefined\r\n ? { toolOutput: toolResponseToString(input.tool_response) }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"SessionStart\": {\r\n const ev: SessionStartEvent = {\r\n ...base,\r\n source: normalizeSessionSource(input.source),\r\n };\r\n return ev;\r\n }\r\n case \"SessionEnd\": {\r\n const ev: SessionEndEvent = {\r\n ...base,\r\n ...(typeof input.reason === \"string\" ? { reason: input.reason } : {}),\r\n };\r\n return ev;\r\n }\r\n case \"UserPromptSubmit\": {\r\n const ev: UserPromptSubmitEvent = {\r\n ...base,\r\n prompt: typeof input.prompt === \"string\" ? input.prompt : \"\",\r\n };\r\n return ev;\r\n }\r\n case \"PreCompact\": {\r\n const ev: PreCompactEvent = {\r\n ...base,\r\n ...(input.trigger === \"auto\" || input.trigger === \"manual\"\r\n ? { trigger: input.trigger }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"PostCompact\": {\r\n // Qwen fires PostCompact natively (observe-only). Parsed like PreCompact:\r\n // normalize the trigger (auto|manual); compact_summary rides on `raw`.\r\n const ev: PostCompactEvent = {\r\n ...base,\r\n ...(input.trigger === \"auto\" || input.trigger === \"manual\"\r\n ? { trigger: input.trigger }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"Stop\": {\r\n const ev: StopEvent = {\r\n ...base,\r\n ...(typeof input.stop_hook_active === \"boolean\"\r\n ? { stopHookActive: input.stop_hook_active }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"Notification\": {\r\n const ev: NotificationEvent = {\r\n ...base,\r\n message: typeof input.message === \"string\" ? input.message : \"\",\r\n };\r\n return ev;\r\n }\r\n case \"PermissionRequest\": {\r\n const ev: PermissionRequestEvent = {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n ...(Array.isArray(input.permission_suggestions)\r\n ? { permissionSuggestions: input.permission_suggestions }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"PostToolUseFailure\": {\r\n // durationMs stays unset — Qwen's failure payload has no duration_ms.\r\n const ev: PostToolUseFailureEvent = {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n error: typeof input.error === \"string\" ? input.error : \"\",\r\n ...(typeof input.tool_use_id === \"string\"\r\n ? { toolUseId: input.tool_use_id }\r\n : {}),\r\n ...(typeof input.is_interrupt === \"boolean\"\r\n ? { isInterrupt: input.is_interrupt }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"SubagentStart\": {\r\n const ev: SubagentStartEvent = {\r\n ...base,\r\n ...(typeof input.agent_id === \"string\" ? { agentId: input.agent_id } : {}),\r\n ...(typeof input.agent_type === \"string\"\r\n ? { agentType: input.agent_type }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"SubagentStop\": {\r\n // agent_id/agent_type stay optional — the Claude-family SDK does not\r\n // reliably populate agent_type on stop.\r\n const ev: SubagentStopEvent = {\r\n ...base,\r\n ...(typeof input.agent_id === \"string\" ? { agentId: input.agent_id } : {}),\r\n ...(typeof input.agent_type === \"string\"\r\n ? { agentType: input.agent_type }\r\n : {}),\r\n ...(typeof input.agent_transcript_path === \"string\"\r\n ? { agentTranscriptPath: input.agent_transcript_path }\r\n : {}),\r\n ...(typeof input.last_assistant_message === \"string\"\r\n ? { lastAssistantMessage: input.last_assistant_message }\r\n : {}),\r\n ...(typeof input.stop_hook_active === \"boolean\"\r\n ? { stopHookActive: input.stop_hook_active }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n default: {\r\n // Exhaustive guard — every HookEventName is handled above.\r\n const _never: never = event;\r\n throw new Error(`unsupported qwen-code hook event: ${String(_never)}`);\r\n }\r\n }\r\n }\r\n\r\n // ── Runtime: normalized response → Qwen native hook reply ────────────────\r\n\r\n formatReply(event: HookEventName, response: HookResponse): HookReply {\r\n const hookEventName = event;\r\n const decision = response.decision ?? \"allow\";\r\n\r\n // PermissionRequest uses Qwen's nested decision{behavior} envelope (Claude-\r\n // identical) and is the ONE event where an EXPLICIT \"allow\" is an ACTIVE\r\n // grant that suppresses the permission dialog:\r\n // allow → decision{behavior:\"allow\"} (+updatedInput when set —\r\n // Qwen honors input rewrite, canModifyArgs above);\r\n // modify → an allow grant carrying updatedInput;\r\n // deny → decision{behavior:\"deny\", message};\r\n // ask/context/void → NO decision output: fall through to the native\r\n // dialog (the dialog IS the ask).\r\n if (event === \"PermissionRequest\") {\r\n if (response.decision === \"deny\") {\r\n return this.stdout({\r\n hookSpecificOutput: {\r\n hookEventName,\r\n decision: {\r\n behavior: \"deny\",\r\n message: response.reason ?? \"Blocked by hook\",\r\n },\r\n },\r\n });\r\n }\r\n if (\r\n response.decision === \"allow\" ||\r\n (response.decision === \"modify\" && response.updatedInput)\r\n ) {\r\n return this.stdout({\r\n hookSpecificOutput: {\r\n hookEventName,\r\n decision: {\r\n behavior: \"allow\",\r\n ...(response.updatedInput\r\n ? { updatedInput: response.updatedInput }\r\n : {}),\r\n },\r\n },\r\n });\r\n }\r\n return { exitCode: 0 };\r\n }\r\n\r\n // PostToolUseFailure (feedback beside the error) and SubagentStart (context\r\n // injected into the SUBAGENT's conversation) are observe/context-only on\r\n // Qwen: \"context\" emits additionalContext, and a \"deny\" DEGRADES to the\r\n // same shape carrying the reason (the tool already failed / the spawn is\r\n // not blockable).\r\n if (event === \"PostToolUseFailure\" || event === \"SubagentStart\") {\r\n const context =\r\n decision === \"context\"\r\n ? response.additionalContext\r\n : decision === \"deny\"\r\n ? response.reason ?? response.additionalContext\r\n : undefined;\r\n if (context) {\r\n return this.stdout({\r\n hookSpecificOutput: { hookEventName, additionalContext: context },\r\n });\r\n }\r\n return { exitCode: 0 };\r\n }\r\n\r\n // deny → block the action with a reason (exit 0; JSON carries the decision).\r\n // Qwen's deny shape is EVENT-SPECIFIC (claude-wire-compatible): PreToolUse\r\n // uses hookSpecificOutput.permissionDecision, but Stop / SubagentStop /\r\n // UserPromptSubmit / PostToolUse honor only the TOP-LEVEL\r\n // {\"decision\":\"block\",\"reason\"} — those events do NOT take permissionDecision\r\n // (QwenLM/qwen-code docs/users/features/hooks.md: Stop/SubagentStop block via\r\n // {\"decision\":\"block\",\"reason\"}; UserPromptSubmit/PostToolUse output options\r\n // list top-level `decision`+`reason`, not permissionDecision — only\r\n // PreToolUse documents permissionDecision as its official interface). A\r\n // SubagentStop / Stop block keeps the agent running with `reason` as its next\r\n // instruction (Stop semantics).\r\n if (decision === \"deny\") {\r\n if (\r\n event === \"Stop\" ||\r\n event === \"SubagentStop\" ||\r\n event === \"UserPromptSubmit\" ||\r\n event === \"PostToolUse\"\r\n ) {\r\n return this.stdout({\r\n decision: \"block\",\r\n reason: response.reason ?? \"Blocked by hook\",\r\n });\r\n }\r\n return this.stdout({\r\n hookSpecificOutput: {\r\n hookEventName,\r\n permissionDecision: \"deny\",\r\n permissionDecisionReason: response.reason ?? \"Blocked by hook\",\r\n },\r\n });\r\n }\r\n\r\n // ask → prompt the user to confirm.\r\n if (decision === \"ask\") {\r\n return this.stdout({\r\n hookSpecificOutput: {\r\n hookEventName,\r\n permissionDecision: \"ask\",\r\n permissionDecisionReason: response.reason ?? \"Confirmation required by hook\",\r\n },\r\n });\r\n }\r\n\r\n // modify → rewrite PreToolUse input only. Qwen 0.17.1 has no PostToolUse\r\n // output-rewrite (`updatedMCPToolOutput` does not exist), so a modify on any\r\n // other event falls through to allow.\r\n if (decision === \"modify\") {\r\n if (event === \"PreToolUse\" && response.updatedInput) {\r\n return this.stdout({\r\n hookSpecificOutput: { hookEventName, updatedInput: response.updatedInput },\r\n });\r\n }\r\n // Nothing applicable on this event; fall through to allow.\r\n }\r\n\r\n // context → inject soft guidance (also the SessionStart context path).\r\n if (decision === \"context\" && response.additionalContext) {\r\n return this.stdout({\r\n hookSpecificOutput: { hookEventName, additionalContext: response.additionalContext },\r\n });\r\n }\r\n\r\n // allow / void / unsupported-degradation → pass through with exit 0.\r\n return { exitCode: 0 };\r\n }\r\n\r\n private stdout(payload: unknown): HookReply {\r\n return { exitCode: 0, stdout: JSON.stringify(payload) };\r\n }\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// JSON leaf-path helpers (statusline nested set-if-absent). Mirror claude-code's\r\n// file-local helpers (those are private to the claude-code module). The leaf\r\n// path here is the validated dotted `ui.statusLine`.\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** Result of looking up a dotted leaf path in a parsed JSON object. */\r\ntype JsonLeafLookup =\r\n | { kind: \"absent\" }\r\n | { kind: \"present\"; value: JsonValue }\r\n | { kind: \"blocked\"; atPath: string };\r\n\r\n/**\r\n * Walk `segments` (a dotted leaf path) through `root`. \"blocked\" reports the\r\n * first intermediate that exists but is not a plain object — the skip-warn case\r\n * (we never replace a non-object intermediate, e.g. a user's `ui: \"dark\"`).\r\n */\r\nfunction readJsonLeaf(root: Record<string, unknown>, segments: string[]): JsonLeafLookup {\r\n let node: Record<string, unknown> = root;\r\n for (let i = 0; i < segments.length - 1; i++) {\r\n const next = node[segments[i]!];\r\n if (next === undefined) return { kind: \"absent\" };\r\n if (next === null || typeof next !== \"object\" || Array.isArray(next)) {\r\n return { kind: \"blocked\", atPath: segments.slice(0, i + 1).join(\".\") };\r\n }\r\n node = next as Record<string, unknown>;\r\n }\r\n const leaf = node[segments[segments.length - 1]!];\r\n if (leaf === undefined) return { kind: \"absent\" };\r\n return { kind: \"present\", value: leaf as JsonValue };\r\n}\r\n\r\n/**\r\n * Write `value` at the leaf, creating ONLY absent intermediate objects along the\r\n * way (callers must have verified the path is not blocked).\r\n */\r\nfunction writeJsonLeaf(\r\n root: Record<string, unknown>,\r\n segments: string[],\r\n value: JsonValue,\r\n): void {\r\n let node: Record<string, unknown> = root;\r\n for (let i = 0; i < segments.length - 1; i++) {\r\n const seg = segments[i]!;\r\n const next = node[seg];\r\n if (next === undefined) {\r\n const created: Record<string, unknown> = {};\r\n node[seg] = created;\r\n node = created;\r\n } else {\r\n node = next as Record<string, unknown>;\r\n }\r\n }\r\n node[segments[segments.length - 1]!] = value;\r\n}\r\n\r\n/**\r\n * Delete the leaf key only. Intermediate objects — even ones we created (the\r\n * `ui` wrapper) — are deliberately left in place (harmless; pruning risks\r\n * clobbering sibling keys the user set under `ui`).\r\n */\r\nfunction deleteJsonLeaf(root: Record<string, unknown>, segments: string[]): void {\r\n let node: Record<string, unknown> = root;\r\n for (let i = 0; i < segments.length - 1; i++) {\r\n const next = node[segments[i]!];\r\n if (next === null || typeof next !== \"object\" || Array.isArray(next)) return;\r\n node = next as Record<string, unknown>;\r\n }\r\n delete node[segments[segments.length - 1]!];\r\n}\r\n\r\n/**\r\n * Extract a stable session id from a Qwen wire payload. Unlike Claude (which\r\n * prefers the transcript UUID), Qwen Code surfaces `session_id` directly and\r\n * prioritizes it — matching context-mode's QwenCodeAdapter.extractSessionId.\r\n * Falls back to the transcript UUID, then \"\" (no ppid fabrication — the\r\n * normalized event uses \"\" when the host provides no id).\r\n */\r\nfunction extractSessionId(input: QwenWireInput): string {\r\n if (typeof input.session_id === \"string\" && input.session_id !== \"\") {\r\n return input.session_id;\r\n }\r\n if (typeof input.transcript_path === \"string\") {\r\n const m = input.transcript_path.match(/([a-f0-9-]{36})\\.jsonl$/);\r\n if (m && m[1]) return m[1];\r\n }\r\n return \"\";\r\n}\r\n\r\n/** Coerce a Qwen PostToolUse `tool_response` into a string for the normalized event. */\r\nfunction toolResponseToString(value: unknown): string | undefined {\r\n if (value == null) return undefined;\r\n if (typeof value === \"string\") return value;\r\n try {\r\n return JSON.stringify(value);\r\n } catch {\r\n return String(value);\r\n }\r\n}\r\n\r\nexport const adapter = new QwenCodeAdapter();\r\nexport default adapter;\r\n"],"mappings":"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","names":["entry","headers"]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|