@ken-jo/agent-connector 0.3.1 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/README.md +180 -16
  2. package/dist/action-WT7GVRCC.js +55 -0
  3. package/dist/action-WT7GVRCC.js.map +1 -0
  4. package/dist/amazon-q-COAL3764.js +276 -0
  5. package/dist/amazon-q-COAL3764.js.map +1 -0
  6. package/dist/{amp-YGV66GJT.js → amp-4U33CU7E.js} +81 -5
  7. package/dist/amp-4U33CU7E.js.map +1 -0
  8. package/dist/{antigravity-7IBYFO6P.js → antigravity-AMKKKHS4.js} +4 -4
  9. package/dist/{antigravity-cli-JEOUP2VN.js → antigravity-cli-XERXEH5W.js} +4 -4
  10. package/dist/{chunk-3JCRUROU.js → chunk-24IDL5RW.js} +13 -4
  11. package/dist/chunk-24IDL5RW.js.map +1 -0
  12. package/dist/chunk-2AVLX7GH.js +351 -0
  13. package/dist/chunk-2AVLX7GH.js.map +1 -0
  14. package/dist/{chunk-GSGDG2BV.js → chunk-4ENJK5S2.js} +106 -176
  15. package/dist/chunk-4ENJK5S2.js.map +1 -0
  16. package/dist/{chunk-ZAM4M7LI.js → chunk-5OWS5CMA.js} +136 -296
  17. package/dist/chunk-5OWS5CMA.js.map +1 -0
  18. package/dist/{chunk-PD4VFEBY.js → chunk-CPLK7GTE.js} +79 -5
  19. package/dist/chunk-CPLK7GTE.js.map +1 -0
  20. package/dist/chunk-DCKFYWGM.js +237 -0
  21. package/dist/chunk-DCKFYWGM.js.map +1 -0
  22. package/dist/chunk-EGCBZ2DC.js +83 -0
  23. package/dist/chunk-EGCBZ2DC.js.map +1 -0
  24. package/dist/chunk-F5RX62T7.js +21 -0
  25. package/dist/chunk-F5RX62T7.js.map +1 -0
  26. package/dist/chunk-FAHIMJRU.js +177 -0
  27. package/dist/chunk-FAHIMJRU.js.map +1 -0
  28. package/dist/{chunk-MEH7GC7R.js → chunk-I5MLE6S7.js} +33 -3
  29. package/dist/chunk-I5MLE6S7.js.map +1 -0
  30. package/dist/{chunk-KVAAFYRR.js → chunk-KHO5WNTP.js} +2 -18
  31. package/dist/chunk-KHO5WNTP.js.map +1 -0
  32. package/dist/{chunk-KQSNDFBN.js → chunk-LQRAPXS4.js} +3 -3
  33. package/dist/{chunk-3RBLIHPZ.js → chunk-O5TWCIJN.js} +27 -17
  34. package/dist/chunk-O5TWCIJN.js.map +1 -0
  35. package/dist/{chunk-WNREHWKL.js → chunk-QREL7LZJ.js} +5 -4
  36. package/dist/chunk-QREL7LZJ.js.map +1 -0
  37. package/dist/{chunk-KMAKDD3Z.js → chunk-RIMVWCZY.js} +37 -12
  38. package/dist/chunk-RIMVWCZY.js.map +1 -0
  39. package/dist/{openclaw-UZ5BMCGQ.js → chunk-URHQMFB3.js} +210 -41
  40. package/dist/chunk-URHQMFB3.js.map +1 -0
  41. package/dist/chunk-WZA4CSGJ.js +28 -0
  42. package/dist/chunk-WZA4CSGJ.js.map +1 -0
  43. package/dist/chunk-XJ4S47CT.js +44 -0
  44. package/dist/chunk-XJ4S47CT.js.map +1 -0
  45. package/dist/{claude-code-4275HQU4.js → claude-code-W4PUFZL5.js} +194 -52
  46. package/dist/claude-code-W4PUFZL5.js.map +1 -0
  47. package/dist/cli/sdk.js +5 -3
  48. package/dist/cli/sdk.js.map +1 -1
  49. package/dist/cli.js +1 -1
  50. package/dist/cline-WRYMNS7Z.js +442 -0
  51. package/dist/cline-WRYMNS7Z.js.map +1 -0
  52. package/dist/{codebuff-LE3KBZGM.js → codebuff-DH5Y7GAT.js} +106 -5
  53. package/dist/codebuff-DH5Y7GAT.js.map +1 -0
  54. package/dist/{codex-4BY2ZJIW.js → codex-DDHIV767.js} +43 -11
  55. package/dist/codex-DDHIV767.js.map +1 -0
  56. package/dist/continue-K43SUHLQ.js +790 -0
  57. package/dist/continue-K43SUHLQ.js.map +1 -0
  58. package/dist/{copilot-cli-IPISKO3V.js → copilot-cli-Q3SSPT4V.js} +70 -12
  59. package/dist/copilot-cli-Q3SSPT4V.js.map +1 -0
  60. package/dist/{crush-X3E25EQG.js → crush-MBEH2R3I.js} +130 -6
  61. package/dist/crush-MBEH2R3I.js.map +1 -0
  62. package/dist/{cursor-UH3W622V.js → cursor-TMBXDYR4.js} +119 -16
  63. package/dist/cursor-TMBXDYR4.js.map +1 -0
  64. package/dist/{detect-U3E7NVNW.js → detect-KG5FG3EV.js} +5 -3
  65. package/dist/{detect-U3E7NVNW.js.map → detect-KG5FG3EV.js.map} +1 -1
  66. package/dist/{doctor-DZTWED4O.js → doctor-FLZF34Y3.js} +226 -96
  67. package/dist/doctor-FLZF34Y3.js.map +1 -0
  68. package/dist/{droid-T5VBRXZF.js → droid-JC2NT6S4.js} +298 -10
  69. package/dist/droid-JC2NT6S4.js.map +1 -0
  70. package/dist/{gemini-cli-ZSUK55UA.js → gemini-cli-ILR7M5X3.js} +62 -10
  71. package/dist/gemini-cli-ILR7M5X3.js.map +1 -0
  72. package/dist/{goose-M3RR3CZG.js → goose-SFO5BBGW.js} +112 -10
  73. package/dist/goose-SFO5BBGW.js.map +1 -0
  74. package/dist/{hermes-CUNKIAR5.js → hermes-3N7WN4WS.js} +329 -15
  75. package/dist/hermes-3N7WN4WS.js.map +1 -0
  76. package/dist/{hook-EVY7LOUQ.js → hook-XR3Z45FB.js} +16 -10
  77. package/dist/hook-XR3Z45FB.js.map +1 -0
  78. package/dist/index.d.ts +71 -3
  79. package/dist/index.js +23 -3
  80. package/dist/{install-OWAS5UIE.js → install-BSR62UHJ.js} +12 -9
  81. package/dist/{install-OWAS5UIE.js.map → install-BSR62UHJ.js.map} +1 -1
  82. package/dist/introspect-Nw8hTReX.d.ts +53 -0
  83. package/dist/{jetbrains-copilot-C3HDGGML.js → jetbrains-copilot-NRZHI5PC.js} +85 -18
  84. package/dist/jetbrains-copilot-NRZHI5PC.js.map +1 -0
  85. package/dist/{kilo-PKAJCWPX.js → kilo-5NWOXVSD.js} +16 -16
  86. package/dist/kilo-5NWOXVSD.js.map +1 -0
  87. package/dist/{kilo-cli-QWUVXG2O.js → kilo-cli-UZ7R5UOP.js} +3 -3
  88. package/dist/{kimi-EVD7YKXS.js → kimi-2YFK2GBA.js} +87 -25
  89. package/dist/kimi-2YFK2GBA.js.map +1 -0
  90. package/dist/{kiro-UQRY6EIO.js → kiro-YL6AWUYG.js} +3 -3
  91. package/dist/{leaderboard-CSWHI4UY.js → leaderboard-MJG24O35.js} +2 -2
  92. package/dist/mimo-code-FTMGSKMQ.js +790 -0
  93. package/dist/mimo-code-FTMGSKMQ.js.map +1 -0
  94. package/dist/{mux-5CI5FP2W.js → mux-5XZFB44C.js} +156 -6
  95. package/dist/mux-5XZFB44C.js.map +1 -0
  96. package/dist/nemoclaw-W5KEJ3WX.js +58 -0
  97. package/dist/nemoclaw-W5KEJ3WX.js.map +1 -0
  98. package/dist/{omp-AXA7XY22.js → omp-2QMEY6HD.js} +138 -18
  99. package/dist/omp-2QMEY6HD.js.map +1 -0
  100. package/dist/openclaw-EXJEFNZI.js +18 -0
  101. package/dist/openclaw-EXJEFNZI.js.map +1 -0
  102. package/dist/{opencode-NZBRLJN3.js → opencode-WNXYJR4X.js} +84 -27
  103. package/dist/opencode-WNXYJR4X.js.map +1 -0
  104. package/dist/{package-WFOS4QVU.js → package-ACZXJHWB.js} +8 -6
  105. package/dist/{package-WFOS4QVU.js.map → package-ACZXJHWB.js.map} +1 -1
  106. package/dist/{pi-WMTUX6ES.js → pi-PVVPVWKG.js} +3 -2
  107. package/dist/{pi-WMTUX6ES.js.map → pi-PVVPVWKG.js.map} +1 -1
  108. package/dist/{qwen-code-MRRIUQ3P.js → qwen-code-G4CXKUHR.js} +426 -10
  109. package/dist/qwen-code-G4CXKUHR.js.map +1 -0
  110. package/dist/{roo-code-NI5UU6JB.js → roo-code-67TYJIQR.js} +137 -4
  111. package/dist/roo-code-67TYJIQR.js.map +1 -0
  112. package/dist/runtime/index.d.ts +96 -2
  113. package/dist/runtime/index.js +19 -10
  114. package/dist/sdk/index.d.ts +52 -0
  115. package/dist/sdk/index.js +82 -0
  116. package/dist/sdk/index.js.map +1 -0
  117. package/dist/sdk/test.d.ts +74 -0
  118. package/dist/sdk/test.js +292 -0
  119. package/dist/sdk/test.js.map +1 -0
  120. package/dist/{serve-3C2VFPAY.js → serve-GER7URPR.js} +13 -9
  121. package/dist/{serve-3C2VFPAY.js.map → serve-GER7URPR.js.map} +1 -1
  122. package/dist/{status-MKQYX5MW.js → status-LAJE3BM5.js} +10 -7
  123. package/dist/{status-MKQYX5MW.js.map → status-LAJE3BM5.js.map} +1 -1
  124. package/dist/statusline-L376ZPZU.js +60 -0
  125. package/dist/statusline-L376ZPZU.js.map +1 -0
  126. package/dist/{telemetry-3DN6XGYB.js → telemetry-B3DX3PWU.js} +6 -4
  127. package/dist/{telemetry-3DN6XGYB.js.map → telemetry-B3DX3PWU.js.map} +1 -1
  128. package/dist/{trae-CQC72RHH.js → trae-7CZZGOGI.js} +99 -5
  129. package/dist/trae-7CZZGOGI.js.map +1 -0
  130. package/dist/{types-CNigfEuR.d.ts → types-CRVrFWeU.d.ts} +322 -18
  131. package/dist/{uninstall-WG6PFWF3.js → uninstall-ZYTW7YMZ.js} +12 -9
  132. package/dist/{uninstall-WG6PFWF3.js.map → uninstall-ZYTW7YMZ.js.map} +1 -1
  133. package/dist/{upgrade-32NC2RKI.js → upgrade-4LUEEOZW.js} +12 -9
  134. package/dist/{upgrade-32NC2RKI.js.map → upgrade-4LUEEOZW.js.map} +1 -1
  135. package/dist/{usage-CJOM2WQM.js → usage-ZFBVQF3H.js} +2 -2
  136. package/dist/{usage-event-472X3DOY.js → usage-event-GZ32AGEB.js} +12 -8
  137. package/dist/{usage-event-472X3DOY.js.map → usage-event-GZ32AGEB.js.map} +1 -1
  138. package/dist/{vscode-copilot-4RVRTCKV.js → vscode-copilot-MF2CDNMT.js} +23 -10
  139. package/dist/vscode-copilot-MF2CDNMT.js.map +1 -0
  140. package/dist/{warp-X6MB67NT.js → warp-VKG55TAT.js} +55 -4
  141. package/dist/warp-VKG55TAT.js.map +1 -0
  142. package/dist/windsurf-FU5G4SHF.js +443 -0
  143. package/dist/windsurf-FU5G4SHF.js.map +1 -0
  144. package/dist/{zed-NTCYW4V2.js → zed-SFUHL3GS.js} +3 -3
  145. package/package.json +10 -2
  146. package/dist/amp-YGV66GJT.js.map +0 -1
  147. package/dist/chunk-3JCRUROU.js.map +0 -1
  148. package/dist/chunk-3RBLIHPZ.js.map +0 -1
  149. package/dist/chunk-GSGDG2BV.js.map +0 -1
  150. package/dist/chunk-KMAKDD3Z.js.map +0 -1
  151. package/dist/chunk-KVAAFYRR.js.map +0 -1
  152. package/dist/chunk-MEH7GC7R.js.map +0 -1
  153. package/dist/chunk-NJU275US.js +0 -238
  154. package/dist/chunk-NJU275US.js.map +0 -1
  155. package/dist/chunk-PD4VFEBY.js.map +0 -1
  156. package/dist/chunk-WNREHWKL.js.map +0 -1
  157. package/dist/chunk-ZAM4M7LI.js.map +0 -1
  158. package/dist/claude-code-4275HQU4.js.map +0 -1
  159. package/dist/codebuff-LE3KBZGM.js.map +0 -1
  160. package/dist/codex-4BY2ZJIW.js.map +0 -1
  161. package/dist/copilot-cli-IPISKO3V.js.map +0 -1
  162. package/dist/crush-X3E25EQG.js.map +0 -1
  163. package/dist/cursor-UH3W622V.js.map +0 -1
  164. package/dist/doctor-DZTWED4O.js.map +0 -1
  165. package/dist/droid-T5VBRXZF.js.map +0 -1
  166. package/dist/gemini-cli-ZSUK55UA.js.map +0 -1
  167. package/dist/goose-M3RR3CZG.js.map +0 -1
  168. package/dist/hermes-CUNKIAR5.js.map +0 -1
  169. package/dist/hook-EVY7LOUQ.js.map +0 -1
  170. package/dist/jetbrains-copilot-C3HDGGML.js.map +0 -1
  171. package/dist/kilo-PKAJCWPX.js.map +0 -1
  172. package/dist/kimi-EVD7YKXS.js.map +0 -1
  173. package/dist/mux-5CI5FP2W.js.map +0 -1
  174. package/dist/omp-AXA7XY22.js.map +0 -1
  175. package/dist/openclaw-UZ5BMCGQ.js.map +0 -1
  176. package/dist/opencode-NZBRLJN3.js.map +0 -1
  177. package/dist/qwen-code-MRRIUQ3P.js.map +0 -1
  178. package/dist/roo-code-NI5UU6JB.js.map +0 -1
  179. package/dist/trae-CQC72RHH.js.map +0 -1
  180. package/dist/vscode-copilot-4RVRTCKV.js.map +0 -1
  181. package/dist/warp-X6MB67NT.js.map +0 -1
  182. /package/dist/{antigravity-7IBYFO6P.js.map → antigravity-AMKKKHS4.js.map} +0 -0
  183. /package/dist/{antigravity-cli-JEOUP2VN.js.map → antigravity-cli-XERXEH5W.js.map} +0 -0
  184. /package/dist/{chunk-KQSNDFBN.js.map → chunk-LQRAPXS4.js.map} +0 -0
  185. /package/dist/{kilo-cli-QWUVXG2O.js.map → kilo-cli-UZ7R5UOP.js.map} +0 -0
  186. /package/dist/{kiro-UQRY6EIO.js.map → kiro-YL6AWUYG.js.map} +0 -0
  187. /package/dist/{leaderboard-CSWHI4UY.js.map → leaderboard-MJG24O35.js.map} +0 -0
  188. /package/dist/{usage-CJOM2WQM.js.map → usage-ZFBVQF3H.js.map} +0 -0
  189. /package/dist/{zed-NTCYW4V2.js.map → zed-SFUHL3GS.js.map} +0 -0
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/adapters/claude-code/wire.ts
4
+ function extractSessionId(input) {
5
+ if (typeof input.transcript_path === "string") {
6
+ const m = input.transcript_path.match(/([a-f0-9-]{36})\.jsonl$/);
7
+ if (m && m[1]) return m[1];
8
+ }
9
+ if (typeof input.session_id === "string" && input.session_id !== "") {
10
+ return input.session_id;
11
+ }
12
+ return "";
13
+ }
14
+ function toolResponseToString(value) {
15
+ if (value == null) return void 0;
16
+ if (typeof value === "string") return value;
17
+ try {
18
+ return JSON.stringify(value);
19
+ } catch {
20
+ return String(value);
21
+ }
22
+ }
23
+
24
+ export {
25
+ extractSessionId,
26
+ toolResponseToString
27
+ };
28
+ //# sourceMappingURL=chunk-WZA4CSGJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/claude-code/wire.ts"],"sourcesContent":["/**\n * adapters/claude-code/wire — Claude Code hook wire protocol.\n *\n * Claude Code pipes a JSON object to a hook command on stdin and reads a JSON\n * object (or empty) from stdout, interpreting the exit code as well. This module\n * captures the exact stdin shape and the canonical reply shape so the adapter's\n * parse/format methods are a single source of truth.\n *\n * Stdin (documented Claude Code hook input):\n * {\n * session_id, transcript_path, cwd, hook_event_name,\n * tool_name, tool_input, tool_response, // tool events\n * permission_suggestions, // PermissionRequest\n * tool_use_id, error, is_interrupt, duration_ms, // PostToolUseFailure\n * agent_id, agent_type, // SubagentStart/Stop\n * agent_transcript_path, last_assistant_message, // SubagentStop\n * source, // SessionStart\n * reason, // SessionEnd\n * prompt, // UserPromptSubmit\n * trigger, // PreCompact\n * stop_hook_active, // Stop / SubagentStop\n * message // Notification\n * }\n *\n * Stdout (canonical reply): a `hookSpecificOutput` object keyed by\n * `hookEventName`, carrying `permissionDecision` (allow|deny|ask) +\n * `permissionDecisionReason`, `additionalContext`, and (PreToolUse)\n * `updatedInput`; PermissionRequest instead takes a nested\n * `decision: { behavior: \"allow\"|\"deny\", ... }`; Stop-class blocks\n * (Stop / SubagentStop / UserPromptSubmit / PostToolUse) take the TOP-LEVEL\n * `{\"decision\":\"block\",\"reason\"}`. Exit 0 = proceed; the JSON refines the\n * decision.\n */\n\n/** Canonical Claude Code hook event names (the values of `hook_event_name`). */\nexport const CLAUDE_HOOK_EVENTS = [\n \"PreToolUse\",\n \"PostToolUse\",\n \"PreCompact\",\n \"SessionStart\",\n \"SessionEnd\",\n \"UserPromptSubmit\",\n \"Stop\",\n \"Notification\",\n \"PermissionRequest\",\n \"PostToolUseFailure\",\n \"SubagentStart\",\n \"SubagentStop\",\n] as const;\n\nexport type ClaudeHookEvent = (typeof CLAUDE_HOOK_EVENTS)[number];\n\n/**\n * Raw Claude Code hook stdin payload. Every field is optional — a given event\n * only populates the subset relevant to it. `connector` is NOT a Claude field;\n * it is threaded in by the universal entrypoint so parseEvent can recover the\n * connector id (the home binary passes `--connector <id>` and may inject it).\n */\nexport interface ClaudeWireInput {\n session_id?: string;\n transcript_path?: string;\n cwd?: string;\n hook_event_name?: string;\n\n // tool events\n tool_name?: string;\n tool_input?: Record<string, unknown>;\n /** PostToolUse result payload (string or structured). */\n tool_response?: unknown;\n\n // PermissionRequest — permission-update entries the dialog would offer.\n // NOTE: the docs explicitly state PermissionRequest has NO tool_use_id.\n permission_suggestions?: unknown[];\n\n // PostToolUseFailure\n tool_use_id?: string;\n error?: string;\n is_interrupt?: boolean;\n duration_ms?: number;\n\n // SubagentStart / SubagentStop — agent_type is unreliable on SubagentStop\n // (the SDK may not populate it); treat both as optional everywhere.\n agent_id?: string;\n agent_type?: string;\n // SubagentStop — the subagent's OWN transcript (transcript_path stays the\n // parent session's) + the text of its final response.\n agent_transcript_path?: string;\n last_assistant_message?: string;\n\n // SessionStart\n source?: string;\n // SessionEnd\n reason?: string;\n // UserPromptSubmit\n prompt?: string;\n // PreCompact\n trigger?: string;\n // Stop / SubagentStop\n stop_hook_active?: boolean;\n // Notification\n message?: string;\n\n /** Injected by the entrypoint so the runtime knows which connector to dispatch. */\n connector?: string;\n}\n\n/**\n * Extract a stable session id from a Claude wire payload.\n * Priority mirrors the proven adapter: transcript UUID > session_id > \"\".\n * (The framework's normalized event uses \"\" when no id is available, per\n * core/types BaseEvent.sessionId docstring — no ppid fabrication here.)\n */\nexport function extractSessionId(input: ClaudeWireInput): string {\n if (typeof input.transcript_path === \"string\") {\n const m = input.transcript_path.match(/([a-f0-9-]{36})\\.jsonl$/);\n if (m && m[1]) return m[1];\n }\n if (typeof input.session_id === \"string\" && input.session_id !== \"\") {\n return input.session_id;\n }\n return \"\";\n}\n\n/** Coerce a Claude PostToolUse `tool_response` into a string for the normalized event. */\nexport function toolResponseToString(value: unknown): string | undefined {\n if (value == null) return undefined;\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n"],"mappings":";;;AAgHO,SAAS,iBAAiB,OAAgC;AAC/D,MAAI,OAAO,MAAM,oBAAoB,UAAU;AAC7C,UAAM,IAAI,MAAM,gBAAgB,MAAM,yBAAyB;AAC/D,QAAI,KAAK,EAAE,CAAC,EAAG,QAAO,EAAE,CAAC;AAAA,EAC3B;AACA,MAAI,OAAO,MAAM,eAAe,YAAY,MAAM,eAAe,IAAI;AACnE,WAAO,MAAM;AAAA,EACf;AACA,SAAO;AACT;AAGO,SAAS,qBAAqB,OAAoC;AACvE,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI;AACF,WAAO,KAAK,UAAU,KAAK;AAAA,EAC7B,QAAQ;AACN,WAAO,OAAO,KAAK;AAAA,EACrB;AACF;","names":[]}
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ allAdapters,
4
+ loadAdapter
5
+ } from "./chunk-DCKFYWGM.js";
6
+
7
+ // src/sdk/introspect.ts
8
+ var SURFACE_PREDICATES = {
9
+ server: (c) => c.transports.length > 0,
10
+ hooks: (c) => c.sessionStart || c.preToolUse || c.postToolUse || c.userPromptSubmit || c.stop || c.sessionEnd || c.preCompact || c.notification || (c.permissionRequest ?? false) || (c.postToolUseFailure ?? false) || (c.subagentStart ?? false) || (c.subagentStop ?? false),
11
+ commands: (c) => c.supportsCommands ?? false,
12
+ skills: (c) => c.supportsSkills ?? false,
13
+ subagents: (c) => c.supportsSubagents ?? false,
14
+ memory: (c) => c.supportsMemory ?? false,
15
+ statusline: (c) => c.supportsStatusline ?? false,
16
+ // Emitters ship on droid + hermes + warp plus the ts-plugin slash-command
17
+ // hosts omp + openclaw (+ the nemoclaw fork) — the hosts with a verifiable
18
+ // target. Every other host leaves supportsActions unset, so explain() marks
19
+ // actions skip-warn there — the honest state for a host with no emission target.
20
+ actions: (c) => c.supportsActions ?? false,
21
+ configPatch: (c) => c.supportsConfigPatch ?? false,
22
+ nativeHooks: (c) => c.supportsNativeHooks ?? false
23
+ };
24
+ async function capabilitiesOf(host) {
25
+ const adapter = await loadAdapter(host);
26
+ return adapter?.capabilities;
27
+ }
28
+ async function hostsSupporting(surface) {
29
+ const predicate = SURFACE_PREDICATES[surface];
30
+ const adapters = await allAdapters();
31
+ return adapters.filter((adapter) => predicate(adapter.capabilities)).map((adapter) => adapter.id).sort();
32
+ }
33
+ async function surfaceSupport(host, surface) {
34
+ const capabilities = await capabilitiesOf(host);
35
+ return capabilities ? SURFACE_PREDICATES[surface](capabilities) : false;
36
+ }
37
+
38
+ export {
39
+ SURFACE_PREDICATES,
40
+ capabilitiesOf,
41
+ hostsSupporting,
42
+ surfaceSupport
43
+ };
44
+ //# sourceMappingURL=chunk-XJ4S47CT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sdk/introspect.ts"],"sourcesContent":["/**\n * sdk/introspect — host-capability introspection over the adapter registry.\n *\n * A thin, READ-ONLY query layer above {@link loadAdapter} / {@link allAdapters}:\n * \"which hosts can honor surface X?\" and \"what can host Y do?\". It exists so a\n * connector author (or a docs/CLI surface) can answer those questions WITHOUT\n * reaching into adapter internals or re-deriving the per-surface capability\n * rules — the predicates below are the single source of truth for mapping the\n * raw {@link PlatformCapabilities} flags onto the developer-facing surface names.\n *\n * Everything is async because adapters load lazily (one entry per platform in\n * the registry, imported only when queried).\n */\n\nimport type { PlatformCapabilities, PlatformId } from \"../core/types.js\";\nimport { allAdapters, loadAdapter } from \"../adapters/registry.js\";\n\n/**\n * The developer-facing surface names a connector can declare. These mirror the\n * top-level {@link import(\"../core/types.js\").ConnectorConfig} keys (server,\n * hooks, commands, …) plus the platform-scoped `configPatch` / `nativeHooks`\n * escape hatches — the same vocabulary the install diff and `explain` use.\n */\nexport type SurfaceName =\n | \"server\"\n | \"hooks\"\n | \"commands\"\n | \"skills\"\n | \"subagents\"\n | \"memory\"\n | \"statusline\"\n | \"actions\"\n | \"configPatch\"\n | \"nativeHooks\";\n\n/**\n * Pure capability predicate per surface — `true` when the host can NATIVELY\n * honor that surface. The optional capability flags are read as `?? false`\n * (the supportsCommands precedent in core/types), so a host that simply leaves\n * a flag unset reports the surface as unsupported (the installer skip-warns it).\n *\n * `hooks` is satisfied by ANY normalized hook event (i.e. the host has at least\n * one event it can dispatch); the per-event flags map 1:1 onto the\n * {@link import(\"../core/types.js\").HookEventName} union.\n */\nexport const SURFACE_PREDICATES: Record<\n SurfaceName,\n (c: PlatformCapabilities) => boolean\n> = {\n server: (c) => c.transports.length > 0,\n hooks: (c) =>\n c.sessionStart ||\n c.preToolUse ||\n c.postToolUse ||\n c.userPromptSubmit ||\n c.stop ||\n c.sessionEnd ||\n c.preCompact ||\n c.notification ||\n (c.permissionRequest ?? false) ||\n (c.postToolUseFailure ?? false) ||\n (c.subagentStart ?? false) ||\n (c.subagentStop ?? false),\n commands: (c) => c.supportsCommands ?? false,\n skills: (c) => c.supportsSkills ?? false,\n subagents: (c) => c.supportsSubagents ?? false,\n memory: (c) => c.supportsMemory ?? false,\n statusline: (c) => c.supportsStatusline ?? false,\n // Emitters ship on droid + hermes + warp plus the ts-plugin slash-command\n // hosts omp + openclaw (+ the nemoclaw fork) — the hosts with a verifiable\n // target. Every other host leaves supportsActions unset, so explain() marks\n // actions skip-warn there — the honest state for a host with no emission target.\n actions: (c) => c.supportsActions ?? false,\n configPatch: (c) => c.supportsConfigPatch ?? false,\n nativeHooks: (c) => c.supportsNativeHooks ?? false,\n};\n\n/**\n * The {@link PlatformCapabilities} a host advertises, or `undefined` for an id\n * that is not in the registry (`\"unknown\"`, a usage-only id like `\"synthetic\"`,\n * or a typo) — callers branch on undefined rather than crash.\n */\nexport async function capabilitiesOf(\n host: PlatformId | string,\n): Promise<PlatformCapabilities | undefined> {\n const adapter = await loadAdapter(host);\n return adapter?.capabilities;\n}\n\n/**\n * Every registered host that can NATIVELY honor `surface`, as a sorted id list\n * (stable output for snapshots/docs). Loads all adapters in parallel and keeps\n * only those whose capabilities pass {@link SURFACE_PREDICATES}.\n */\nexport async function hostsSupporting(surface: SurfaceName): Promise<PlatformId[]> {\n const predicate = SURFACE_PREDICATES[surface];\n const adapters = await allAdapters();\n return adapters\n .filter((adapter) => predicate(adapter.capabilities))\n .map((adapter) => adapter.id)\n .sort();\n}\n\n/**\n * Convenience: does `host` natively support `surface`? `false` for an unknown\n * id (no capabilities → cannot support anything).\n */\nexport async function surfaceSupport(\n host: PlatformId | string,\n surface: SurfaceName,\n): Promise<boolean> {\n const capabilities = await capabilitiesOf(host);\n return capabilities ? SURFACE_PREDICATES[surface](capabilities) : false;\n}\n"],"mappings":";;;;;;;AA6CO,IAAM,qBAGT;AAAA,EACF,QAAQ,CAAC,MAAM,EAAE,WAAW,SAAS;AAAA,EACrC,OAAO,CAAC,MACN,EAAE,gBACF,EAAE,cACF,EAAE,eACF,EAAE,oBACF,EAAE,QACF,EAAE,cACF,EAAE,cACF,EAAE,iBACD,EAAE,qBAAqB,WACvB,EAAE,sBAAsB,WACxB,EAAE,iBAAiB,WACnB,EAAE,gBAAgB;AAAA,EACrB,UAAU,CAAC,MAAM,EAAE,oBAAoB;AAAA,EACvC,QAAQ,CAAC,MAAM,EAAE,kBAAkB;AAAA,EACnC,WAAW,CAAC,MAAM,EAAE,qBAAqB;AAAA,EACzC,QAAQ,CAAC,MAAM,EAAE,kBAAkB;AAAA,EACnC,YAAY,CAAC,MAAM,EAAE,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA,EAK3C,SAAS,CAAC,MAAM,EAAE,mBAAmB;AAAA,EACrC,aAAa,CAAC,MAAM,EAAE,uBAAuB;AAAA,EAC7C,aAAa,CAAC,MAAM,EAAE,uBAAuB;AAC/C;AAOA,eAAsB,eACpB,MAC2C;AAC3C,QAAM,UAAU,MAAM,YAAY,IAAI;AACtC,SAAO,SAAS;AAClB;AAOA,eAAsB,gBAAgB,SAA6C;AACjF,QAAM,YAAY,mBAAmB,OAAO;AAC5C,QAAM,WAAW,MAAM,YAAY;AACnC,SAAO,SACJ,OAAO,CAAC,YAAY,UAAU,QAAQ,YAAY,CAAC,EACnD,IAAI,CAAC,YAAY,QAAQ,EAAE,EAC3B,KAAK;AACV;AAMA,eAAsB,eACpB,MACA,SACkB;AAClB,QAAM,eAAe,MAAM,eAAe,IAAI;AAC9C,SAAO,eAAe,mBAAmB,OAAO,EAAE,YAAY,IAAI;AACpE;","names":[]}
@@ -1,7 +1,13 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ extractSessionId,
4
+ toolResponseToString
5
+ } from "./chunk-WZA4CSGJ.js";
2
6
  import {
3
7
  readRegisteredMeta
4
- } from "./chunk-3JCRUROU.js";
8
+ } from "./chunk-24IDL5RW.js";
9
+ import "./chunk-4ENJK5S2.js";
10
+ import "./chunk-DCKFYWGM.js";
5
11
  import {
6
12
  addLedgerOwner,
7
13
  configPatchManualEdit,
@@ -17,14 +23,14 @@ import {
17
23
  loadConfigPatchLedger,
18
24
  removeLedgerOwner,
19
25
  saveConfigPatchLedger
20
- } from "./chunk-GSGDG2BV.js";
26
+ } from "./chunk-FAHIMJRU.js";
21
27
  import {
22
28
  resolveEnvRefsDeep,
23
29
  rewriteEnvRefs
24
30
  } from "./chunk-DBQMX75U.js";
25
31
  import {
26
32
  BaseAdapter
27
- } from "./chunk-PD4VFEBY.js";
33
+ } from "./chunk-CPLK7GTE.js";
28
34
  import {
29
35
  renderCommandMd,
30
36
  renderSkillMd,
@@ -32,10 +38,12 @@ import {
32
38
  } from "./chunk-7L6ITC4T.js";
33
39
  import {
34
40
  buildHomeBinHookCommand,
41
+ buildHomeBinStatuslineCommand,
35
42
  buildServeWrapperCommand,
36
43
  isHomeBinHookCommand,
44
+ isHomeBinStatuslineCommand,
37
45
  shouldWrapForTelemetry
38
- } from "./chunk-MEH7GC7R.js";
46
+ } from "./chunk-I5MLE6S7.js";
39
47
  import {
40
48
  linesOutsideFences,
41
49
  listManagedBlocks,
@@ -55,31 +63,9 @@ import {
55
63
  import { copyFileSync, existsSync, lstatSync, readFileSync, realpathSync } from "fs";
56
64
  import { homedir } from "os";
57
65
  import { basename, dirname, join } from "path";
58
-
59
- // src/adapters/claude-code/wire.ts
60
- function extractSessionId(input) {
61
- if (typeof input.transcript_path === "string") {
62
- const m = input.transcript_path.match(/([a-f0-9-]{36})\.jsonl$/);
63
- if (m && m[1]) return m[1];
64
- }
65
- if (typeof input.session_id === "string" && input.session_id !== "") {
66
- return input.session_id;
67
- }
68
- return "";
69
- }
70
- function toolResponseToString(value) {
71
- if (value == null) return void 0;
72
- if (typeof value === "string") return value;
73
- try {
74
- return JSON.stringify(value);
75
- } catch {
76
- return String(value);
77
- }
78
- }
79
-
80
- // src/adapters/claude-code/index.ts
81
66
  var HOST = "claude-code";
82
67
  var MCP_ROOT_KEY = "mcpServers";
68
+ var STATUSLINE_KEY = "statusLine";
83
69
  var CLAUDE_AGENTS_IMPORT_BLOCK_ID = "_shared/claude-agents-import";
84
70
  var ClaudeCodeAdapter = class extends BaseAdapter {
85
71
  id = HOST;
@@ -112,6 +98,11 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
112
98
  // (set-if-absent leaf keys in settings.json, refcounted ownership ledger,
113
99
  // sensitive-key denylist — see SENSITIVE_KEY_RULES below).
114
100
  supportsConfigPatch: true,
101
+ // Statusline surface: claude-code is the ONLY v1 host. installStatusline
102
+ // wires settings.json.statusLine = {type:"command", command:<home-bin
103
+ // statusline cmd>} through the SAME set-if-absent ownership ledger as
104
+ // configPatch (never clobbers a statusLine agent-connector does not own).
105
+ supportsStatusline: true,
115
106
  transports: ["stdio", "http"],
116
107
  // Content surfaces: Claude Code is the reference implementation for all three.
117
108
  supportsCommands: true,
@@ -374,6 +365,20 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
374
365
  { platform: this.id, action: "skip", detail: "connector declares no configPatch entries" }
375
366
  ];
376
367
  }
368
+ return this.applyConfigPatches(ctx, patches);
369
+ }
370
+ /**
371
+ * The shared set-if-absent / ownership-ledger apply loop behind BOTH
372
+ * {@link installConfigPatches} and {@link installStatusline}. Routing the
373
+ * statusline through the EXACT same path is how a connector's statusLine
374
+ * inherits the configPatch contract verbatim: never clobber a statusLine
375
+ * agent-connector does not own (skip-warn), record prior state + owner,
376
+ * refcounted across connectors, reversible by uninstallConfigPatches.
377
+ */
378
+ applyConfigPatches(ctx, patches, opts = {}) {
379
+ const surfaceLabel = opts.surfaceLabel ?? "configPatch";
380
+ const internal = surfaceLabel !== "configPatch";
381
+ const { connector } = ctx;
377
382
  const filePath = this.getPatchableConfigPath(ctx);
378
383
  if (this.isPresentButUnparseable(filePath)) {
379
384
  return [
@@ -409,14 +414,16 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
409
414
  });
410
415
  continue;
411
416
  }
412
- const namespace = configPatchNamespaceViolation(patch.key);
413
- if (namespace) {
414
- changes.push({
415
- platform: this.id,
416
- action: "warn",
417
- detail: `configPatch refused: ${namespace}`
418
- });
419
- continue;
417
+ if (!internal) {
418
+ const namespace = configPatchNamespaceViolation(patch.key);
419
+ if (namespace) {
420
+ changes.push({
421
+ platform: this.id,
422
+ action: "warn",
423
+ detail: `configPatch refused: ${namespace}`
424
+ });
425
+ continue;
426
+ }
420
427
  }
421
428
  const sensitive = claudeSensitiveKeyViolation(patch.key);
422
429
  if (sensitive) {
@@ -436,7 +443,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
436
443
  platform: this.id,
437
444
  action: "warn",
438
445
  path: filePath,
439
- detail: `configPatch ${patch.key} skipped: "${leaf.atPath}" exists but is not an object \u2014 ${configPatchManualEdit(patch)}`
446
+ detail: `${surfaceLabel} ${patch.key} skipped: "${leaf.atPath}" exists but is not an object \u2014 ${configPatchManualEdit(patch)}`
440
447
  });
441
448
  continue;
442
449
  }
@@ -462,7 +469,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
462
469
  platform: this.id,
463
470
  action: "create",
464
471
  path: filePath,
465
- detail: `configPatch ${patch.key}: <absent> \u2192 ${describeJsonValue(desired)} (${patch.reason})`
472
+ detail: `${surfaceLabel} ${patch.key}: <absent> \u2192 ${describeJsonValue(desired)} (${patch.reason})`
466
473
  });
467
474
  continue;
468
475
  }
@@ -471,7 +478,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
471
478
  platform: this.id,
472
479
  action: "warn",
473
480
  path: filePath,
474
- detail: `configPatch ${patch.key} skipped: already set to ${describeJsonValue(leaf.value)} (not created by agent-connector; desired ${describeJsonValue(desired)}) \u2014 ` + configPatchManualEdit(patch)
481
+ detail: `${surfaceLabel} ${patch.key} skipped: already set to ${describeJsonValue(leaf.value)} (not created by agent-connector; desired ${describeJsonValue(desired)}) \u2014 ` + configPatchManualEdit(patch)
475
482
  });
476
483
  continue;
477
484
  }
@@ -480,7 +487,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
480
487
  platform: this.id,
481
488
  action: "warn",
482
489
  path: filePath,
483
- detail: `configPatch ${patch.key}: value changed since install (current ${describeJsonValue(leaf.value)}, wrote ${describeJsonValue(entry.writtenValue)}); leaving in place \u2014 ${configPatchManualEdit(patch)}`
490
+ detail: `${surfaceLabel} ${patch.key}: value changed since install (current ${describeJsonValue(leaf.value)}, wrote ${describeJsonValue(entry.writtenValue)}); leaving in place \u2014 ${configPatchManualEdit(patch)}`
484
491
  });
485
492
  continue;
486
493
  }
@@ -492,14 +499,14 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
492
499
  platform: this.id,
493
500
  action: "skip",
494
501
  path: filePath,
495
- detail: `configPatch ${patch.key} already installed; registered as co-owner (co-owned with ${owners.join(", ")})`
502
+ detail: `${surfaceLabel} ${patch.key} already installed; registered as co-owner (co-owned with ${owners.join(", ")})`
496
503
  });
497
504
  } else {
498
505
  changes.push({
499
506
  platform: this.id,
500
507
  action: "skip",
501
508
  path: filePath,
502
- detail: `configPatch ${patch.key} already installed`
509
+ detail: `${surfaceLabel} ${patch.key} already installed`
503
510
  });
504
511
  }
505
512
  continue;
@@ -508,7 +515,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
508
515
  platform: this.id,
509
516
  action: "warn",
510
517
  path: filePath,
511
- detail: `configPatch ${patch.key} skipped: already owned by ${entry.owners.map((o) => o.connectorId).join(", ")} with a different value (current ${describeJsonValue(leaf.value)}, desired ${describeJsonValue(desired)}) \u2014 ` + configPatchManualEdit(patch)
518
+ detail: `${surfaceLabel} ${patch.key} skipped: already owned by ${entry.owners.map((o) => o.connectorId).join(", ")} with a different value (current ${describeJsonValue(leaf.value)}, desired ${describeJsonValue(desired)}) \u2014 ` + configPatchManualEdit(patch)
512
519
  });
513
520
  }
514
521
  if (fileMutated) this.writeJson(filePath, settings, ctx.dryRun);
@@ -518,7 +525,9 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
518
525
  uninstallConfigPatches(ctx) {
519
526
  const connectorId = ctx.connector.id;
520
527
  const ledger = loadConfigPatchLedger(ctx.dataRoot);
521
- const owned = ledgerEntriesOwnedBy(ledger, HOST, connectorId);
528
+ const owned = ledgerEntriesOwnedBy(ledger, HOST, connectorId).filter(
529
+ (e) => e.key !== STATUSLINE_KEY
530
+ );
522
531
  const declared = ctx.connector.platforms[HOST]?.configPatch ?? [];
523
532
  const changes = [];
524
533
  const ownedKeys = new Set(owned.map((e) => e.key));
@@ -532,6 +541,20 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
532
541
  }
533
542
  }
534
543
  if (owned.length === 0) return changes;
544
+ changes.push(...this.releaseOwnedConfigPatches(ctx, ledger, owned));
545
+ return changes;
546
+ }
547
+ /**
548
+ * The shared last-owner-verified release loop behind BOTH
549
+ * {@link uninstallConfigPatches} and {@link uninstallStatusline}: for each
550
+ * already-selected owned ledger entry, drop this connector's ownership and
551
+ * remove the key ONLY when last-owner ∧ value-unchanged ∧ prior-absent (else
552
+ * skip-warn + leave the key). Saves the ledger when it mutated.
553
+ */
554
+ releaseOwnedConfigPatches(ctx, ledger, owned, opts = {}) {
555
+ const surfaceLabel = opts.surfaceLabel ?? "configPatch";
556
+ const connectorId = ctx.connector.id;
557
+ const changes = [];
535
558
  let ledgerMutated = false;
536
559
  const backedUp = /* @__PURE__ */ new Set();
537
560
  const byFile = /* @__PURE__ */ new Map();
@@ -552,7 +575,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
552
575
  platform: this.id,
553
576
  action: "skip",
554
577
  path: filePath,
555
- detail: `configPatch ${entry.key} retained: still owned by ${entry.owners.map((o) => o.connectorId).join(", ")}`
578
+ detail: `${surfaceLabel} ${entry.key} retained: still owned by ${entry.owners.map((o) => o.connectorId).join(", ")}`
556
579
  });
557
580
  continue;
558
581
  }
@@ -562,7 +585,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
562
585
  platform: this.id,
563
586
  action: "warn",
564
587
  path: filePath,
565
- detail: `configPatch ${entry.key}: ${filePath} is not parseable; key left in place (ownership released)`
588
+ detail: `${surfaceLabel} ${entry.key}: ${filePath} is not parseable; key left in place (ownership released)`
566
589
  });
567
590
  continue;
568
591
  }
@@ -571,7 +594,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
571
594
  platform: this.id,
572
595
  action: "skip",
573
596
  path: filePath,
574
- detail: `configPatch ${entry.key} already absent (no settings file); ownership record dropped`
597
+ detail: `${surfaceLabel} ${entry.key} already absent (no settings file); ownership record dropped`
575
598
  });
576
599
  continue;
577
600
  }
@@ -581,7 +604,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
581
604
  platform: this.id,
582
605
  action: "skip",
583
606
  path: filePath,
584
- detail: `configPatch ${entry.key} already absent; ownership record dropped`
607
+ detail: `${surfaceLabel} ${entry.key} already absent; ownership record dropped`
585
608
  });
586
609
  continue;
587
610
  }
@@ -590,7 +613,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
590
613
  platform: this.id,
591
614
  action: "warn",
592
615
  path: filePath,
593
- detail: `configPatch ${entry.key}: value changed since install (current ${describeJsonValue(leaf.value)}, wrote ${describeJsonValue(entry.writtenValue)}); left in place`
616
+ detail: `${surfaceLabel} ${entry.key}: value changed since install (current ${describeJsonValue(leaf.value)}, wrote ${describeJsonValue(entry.writtenValue)}); left in place`
594
617
  });
595
618
  continue;
596
619
  }
@@ -612,7 +635,7 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
612
635
  platform: this.id,
613
636
  action: "remove",
614
637
  path: filePath,
615
- detail: `configPatch ${entry.key} removed (was ${describeJsonValue(entry.writtenValue)})`
638
+ detail: `${surfaceLabel} ${entry.key} removed (was ${describeJsonValue(entry.writtenValue)})`
616
639
  });
617
640
  }
618
641
  if (fileMutated && settings) this.writeJson(filePath, settings, ctx.dryRun);
@@ -620,6 +643,91 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
620
643
  if (ledgerMutated && !ctx.dryRun) saveConfigPatchLedger(ctx.dataRoot, ledger);
621
644
  return changes;
622
645
  }
646
+ // ── Statusline surface (a HUD/status line) ────────────────────────────────
647
+ // Wires settings.json.statusLine = { type:"command", command:<home-bin
648
+ // statusline cmd> } through the SAME ownership ledger as configPatch: a
649
+ // synthetic ConfigPatchDef routed through applyConfigPatches, so the statusLine
650
+ // inherits the full set-if-absent contract verbatim — never clobbers a
651
+ // statusLine agent-connector does not own (skip-warn), records prior state +
652
+ // owner, reversible. The home-bin command makes the host exec
653
+ // `<homeBin> statusline claude-code --connector <id>` for every status refresh,
654
+ // which re-imports the connector module and renders the line (runtime/
655
+ // statusline-entrypoint). No telemetry in v1.
656
+ /** The synthetic statusLine configPatch this connector would write. */
657
+ statuslineConfigPatch(ctx) {
658
+ const command = buildHomeBinStatuslineCommand(ctx.homeBinPath, HOST, ctx.connector.id);
659
+ return {
660
+ key: STATUSLINE_KEY,
661
+ value: { type: "command", command },
662
+ reason: "agent-connector statusline surface"
663
+ };
664
+ }
665
+ installStatusline(ctx) {
666
+ const { connector } = ctx;
667
+ if (connector.statusline == null) {
668
+ return [{ platform: this.id, action: "skip", detail: "connector declares no statusline" }];
669
+ }
670
+ if (connector.platforms[HOST]?.statusline === false) {
671
+ return [{ platform: this.id, action: "skip", detail: "statusline disabled for claude-code" }];
672
+ }
673
+ return this.applyConfigPatches(ctx, [this.statuslineConfigPatch(ctx)], {
674
+ surfaceLabel: "statusline"
675
+ });
676
+ }
677
+ uninstallStatusline(ctx) {
678
+ const ledger = loadConfigPatchLedger(ctx.dataRoot);
679
+ const owned = ledgerEntriesOwnedBy(ledger, HOST, ctx.connector.id).filter(
680
+ (e) => e.key === STATUSLINE_KEY
681
+ );
682
+ if (owned.length === 0) {
683
+ return [
684
+ {
685
+ platform: this.id,
686
+ action: "skip",
687
+ detail: "statusline: no ownership recorded; left untouched"
688
+ }
689
+ ];
690
+ }
691
+ return this.releaseOwnedConfigPatches(ctx, ledger, owned, {
692
+ surfaceLabel: "statusline"
693
+ });
694
+ }
695
+ /**
696
+ * Parse Claude Code's statusLine stdin JSON into the normalized
697
+ * {@link StatuslineContext}. Claude pipes a JSON object to the statusLine
698
+ * command on stdin (model, workspace, cost, etc.); fields the payload omits
699
+ * stay undefined. `raw` keeps the verbatim payload (incl. `version`).
700
+ */
701
+ parseStatusInput(raw) {
702
+ const input = raw ?? {};
703
+ const model = {};
704
+ if (typeof input.model?.id === "string") model.id = input.model.id;
705
+ if (typeof input.model?.display_name === "string") {
706
+ model.displayName = input.model.display_name;
707
+ }
708
+ const cwd = typeof input.cwd === "string" ? input.cwd : typeof input.workspace?.current_dir === "string" ? input.workspace.current_dir : void 0;
709
+ const ctx = {
710
+ host: HOST,
711
+ capabilities: this.capabilities,
712
+ raw
713
+ };
714
+ if (typeof input.session_id === "string" && input.session_id !== "") {
715
+ ctx.sessionId = input.session_id;
716
+ }
717
+ if (cwd !== void 0) ctx.cwd = cwd;
718
+ if (model.id !== void 0 || model.displayName !== void 0) ctx.model = model;
719
+ if (typeof input.cost?.total_cost_usd === "number") {
720
+ ctx.cost = { totalUsd: input.cost.total_cost_usd };
721
+ }
722
+ if (typeof input.transcript_path === "string") {
723
+ ctx.transcriptPath = input.transcript_path;
724
+ }
725
+ return ctx;
726
+ }
727
+ /** Format the rendered status line into Claude's native reply: stdout = line, exit 0. */
728
+ formatStatusOutput(rendered) {
729
+ return { exitCode: 0, stdout: rendered };
730
+ }
623
731
  /**
624
732
  * Back up ONE exact file (the ledger-recorded patch target, which may belong
625
733
  * to a different scope than the current ctx) into the standard backups dir.
@@ -651,7 +759,9 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
651
759
  const results = [];
652
760
  const ledger = loadConfigPatchLedger(ctx.dataRoot);
653
761
  const connectorId = ctx.connector.id;
654
- const platformEntries = ledger.entries.filter((e) => e.platform === this.id);
762
+ const platformEntries = ledger.entries.filter(
763
+ (e) => e.platform === this.id && e.key !== STATUSLINE_KEY
764
+ );
655
765
  for (const entry of platformEntries) {
656
766
  const ownedByThis = entry.owners.some((o) => o.connectorId === connectorId);
657
767
  if (!ownedByThis) {
@@ -678,7 +788,8 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
678
788
  check: `${this.name}: configPatch ${entry.key}`,
679
789
  status: "warn",
680
790
  message: `missing \u2014 key deleted from ${entry.file} since install`,
681
- fix: `agent-connector install (sync) will re-assert it`
791
+ fix: `agent-connector install (sync) will re-assert it`,
792
+ fixable: true
682
793
  });
683
794
  } else {
684
795
  results.push({
@@ -1144,6 +1255,30 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
1144
1255
  check: () => existsSync(p) ? { status: "OK", detail: p } : { status: "FAIL", detail: `not found: ${p}` }
1145
1256
  });
1146
1257
  }
1258
+ const statuslineLedgerOwned = ledgerEntriesOwnedBy(
1259
+ loadConfigPatchLedger(ctx.dataRoot),
1260
+ HOST,
1261
+ connectorId
1262
+ ).some((e) => e.key === STATUSLINE_KEY);
1263
+ if ((ctx.connector.statusline != null || statuslineLedgerOwned) && ctx.connector.platforms[HOST]?.statusline !== false) {
1264
+ checks.push({
1265
+ name: `${this.name}: statusline wired`,
1266
+ check: () => {
1267
+ const settings = this.readJson(settingsPath);
1268
+ const command = settings?.statusLine?.command;
1269
+ if (command === void 0) {
1270
+ return { status: "FAIL", detail: `statusLine not set in ${settingsPath}` };
1271
+ }
1272
+ if (typeof command === "string" && isHomeBinStatuslineCommand(command, homeBin, connectorId)) {
1273
+ return { status: "OK", detail: "statusLine command present" };
1274
+ }
1275
+ return {
1276
+ status: "FAIL",
1277
+ detail: `statusLine in ${settingsPath} is not agent-connector's (left untouched)`
1278
+ };
1279
+ }
1280
+ });
1281
+ }
1147
1282
  return checks;
1148
1283
  }
1149
1284
  // ── Runtime: parse Claude stdin JSON → normalized event ──────────────────
@@ -1259,6 +1394,13 @@ var ClaudeCodeAdapter = class extends BaseAdapter {
1259
1394
  };
1260
1395
  return ev;
1261
1396
  }
1397
+ case "PostCompact": {
1398
+ const ev = {
1399
+ ...base,
1400
+ ...input.trigger === "auto" || input.trigger === "manual" ? { trigger: input.trigger } : {}
1401
+ };
1402
+ return ev;
1403
+ }
1262
1404
  default: {
1263
1405
  const _never = event;
1264
1406
  throw new Error(`unsupported claude-code hook event: ${String(_never)}`);
@@ -1429,4 +1571,4 @@ export {
1429
1571
  claudeSensitiveKeyViolation,
1430
1572
  claude_code_default as default
1431
1573
  };
1432
- //# sourceMappingURL=claude-code-4275HQU4.js.map
1574
+ //# sourceMappingURL=claude-code-W4PUFZL5.js.map