context-mode 1.0.169 → 2.0.0-next.5

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 (379) hide show
  1. package/.claude-plugin/marketplace.json +4 -22
  2. package/.claude-plugin/plugin.json +9 -24
  3. package/SHA256SUMS +31 -0
  4. package/claude-code/skills/ctx-doctor/SKILL.md +6 -0
  5. package/claude-code/skills/ctx-stats/SKILL.md +6 -0
  6. package/claude-code/skills/ctx-upgrade/SKILL.md +6 -0
  7. package/cli.mjs +6744 -0
  8. package/copilot/plugin.json +14 -0
  9. package/fixtures/hook-roundtrip.json +22 -0
  10. package/gemini-extension.json +14 -0
  11. package/hook.mjs +202 -0
  12. package/hooks/claude-code.json +50 -0
  13. package/hooks/codex.json +50 -0
  14. package/hooks/copilot-cli.json +33 -0
  15. package/hooks/hooks.json +16 -111
  16. package/hooks/kiro.json +69 -0
  17. package/hooks/qwen.json +50 -0
  18. package/hooks/vscode.json +40 -0
  19. package/hooks/zcode.json +53 -0
  20. package/opencode/plugin.js +22456 -0
  21. package/package.json +29 -114
  22. package/pi/index.js +50841 -0
  23. package/pi/skills/ctx-doctor/SKILL.md +6 -0
  24. package/pi/skills/ctx-stats/SKILL.md +6 -0
  25. package/pi/skills/ctx-upgrade/SKILL.md +6 -0
  26. package/qwen-extension.json +15 -0
  27. package/run.mjs +5633 -0
  28. package/search.mjs +5633 -0
  29. package/server.mjs +48198 -0
  30. package/skills/ctx-doctor/SKILL.md +3 -19
  31. package/skills/ctx-stats/SKILL.md +3 -23
  32. package/skills/ctx-upgrade/SKILL.md +3 -28
  33. package/.codex-plugin/hooks.json +0 -65
  34. package/.codex-plugin/mcp.json +0 -13
  35. package/.codex-plugin/plugin.json +0 -31
  36. package/.openclaw-plugin/index.ts +0 -12
  37. package/.openclaw-plugin/openclaw.plugin.json +0 -38
  38. package/.openclaw-plugin/package.json +0 -28
  39. package/LICENSE +0 -94
  40. package/README.md +0 -1619
  41. package/bin/statusline.mjs +0 -378
  42. package/build/adapters/antigravity/index.d.ts +0 -51
  43. package/build/adapters/antigravity/index.js +0 -169
  44. package/build/adapters/antigravity-cli/index.d.ts +0 -51
  45. package/build/adapters/antigravity-cli/index.js +0 -342
  46. package/build/adapters/base.d.ts +0 -92
  47. package/build/adapters/base.js +0 -135
  48. package/build/adapters/claude-code/config.d.ts +0 -8
  49. package/build/adapters/claude-code/config.js +0 -8
  50. package/build/adapters/claude-code/hooks.d.ts +0 -106
  51. package/build/adapters/claude-code/hooks.js +0 -183
  52. package/build/adapters/claude-code/index.d.ts +0 -80
  53. package/build/adapters/claude-code/index.js +0 -569
  54. package/build/adapters/claude-code-base.d.ts +0 -49
  55. package/build/adapters/claude-code-base.js +0 -113
  56. package/build/adapters/client-map.d.ts +0 -10
  57. package/build/adapters/client-map.js +0 -42
  58. package/build/adapters/codex/config.d.ts +0 -8
  59. package/build/adapters/codex/config.js +0 -8
  60. package/build/adapters/codex/hooks.d.ts +0 -55
  61. package/build/adapters/codex/hooks.js +0 -64
  62. package/build/adapters/codex/index.d.ts +0 -87
  63. package/build/adapters/codex/index.js +0 -992
  64. package/build/adapters/codex/paths.d.ts +0 -1
  65. package/build/adapters/codex/paths.js +0 -12
  66. package/build/adapters/codex/usage.d.ts +0 -107
  67. package/build/adapters/codex/usage.js +0 -227
  68. package/build/adapters/copilot-base.d.ts +0 -94
  69. package/build/adapters/copilot-base.js +0 -297
  70. package/build/adapters/copilot-cli/hooks.d.ts +0 -33
  71. package/build/adapters/copilot-cli/hooks.js +0 -64
  72. package/build/adapters/copilot-cli/index.d.ts +0 -48
  73. package/build/adapters/copilot-cli/index.js +0 -341
  74. package/build/adapters/cursor/config.d.ts +0 -4
  75. package/build/adapters/cursor/config.js +0 -4
  76. package/build/adapters/cursor/hooks.d.ts +0 -55
  77. package/build/adapters/cursor/hooks.js +0 -82
  78. package/build/adapters/cursor/index.d.ts +0 -64
  79. package/build/adapters/cursor/index.js +0 -517
  80. package/build/adapters/detect.d.ts +0 -136
  81. package/build/adapters/detect.js +0 -623
  82. package/build/adapters/gemini-cli/config.d.ts +0 -8
  83. package/build/adapters/gemini-cli/config.js +0 -8
  84. package/build/adapters/gemini-cli/hooks.d.ts +0 -83
  85. package/build/adapters/gemini-cli/hooks.js +0 -115
  86. package/build/adapters/gemini-cli/index.d.ts +0 -80
  87. package/build/adapters/gemini-cli/index.js +0 -483
  88. package/build/adapters/jetbrains-copilot/config.d.ts +0 -8
  89. package/build/adapters/jetbrains-copilot/config.js +0 -8
  90. package/build/adapters/jetbrains-copilot/hooks.d.ts +0 -59
  91. package/build/adapters/jetbrains-copilot/hooks.js +0 -87
  92. package/build/adapters/jetbrains-copilot/index.d.ts +0 -31
  93. package/build/adapters/jetbrains-copilot/index.js +0 -131
  94. package/build/adapters/kimi/config.d.ts +0 -8
  95. package/build/adapters/kimi/config.js +0 -8
  96. package/build/adapters/kimi/hooks.d.ts +0 -28
  97. package/build/adapters/kimi/hooks.js +0 -34
  98. package/build/adapters/kimi/index.d.ts +0 -66
  99. package/build/adapters/kimi/index.js +0 -537
  100. package/build/adapters/kimi/paths.d.ts +0 -21
  101. package/build/adapters/kimi/paths.js +0 -52
  102. package/build/adapters/kimi/usage.d.ts +0 -82
  103. package/build/adapters/kimi/usage.js +0 -217
  104. package/build/adapters/kiro/hooks.d.ts +0 -61
  105. package/build/adapters/kiro/hooks.js +0 -94
  106. package/build/adapters/kiro/index.d.ts +0 -61
  107. package/build/adapters/kiro/index.js +0 -301
  108. package/build/adapters/omp/index.d.ts +0 -65
  109. package/build/adapters/omp/index.js +0 -182
  110. package/build/adapters/omp/plugin.d.ts +0 -81
  111. package/build/adapters/omp/plugin.js +0 -331
  112. package/build/adapters/omp/usage.d.ts +0 -49
  113. package/build/adapters/omp/usage.js +0 -110
  114. package/build/adapters/openclaw/config.d.ts +0 -8
  115. package/build/adapters/openclaw/config.js +0 -8
  116. package/build/adapters/openclaw/hooks.d.ts +0 -50
  117. package/build/adapters/openclaw/hooks.js +0 -61
  118. package/build/adapters/openclaw/index.d.ts +0 -74
  119. package/build/adapters/openclaw/index.js +0 -439
  120. package/build/adapters/openclaw/mcp-tools.d.ts +0 -54
  121. package/build/adapters/openclaw/mcp-tools.js +0 -207
  122. package/build/adapters/openclaw/plugin.d.ts +0 -141
  123. package/build/adapters/openclaw/plugin.js +0 -818
  124. package/build/adapters/openclaw/session-db.d.ts +0 -55
  125. package/build/adapters/openclaw/session-db.js +0 -88
  126. package/build/adapters/openclaw/usage.d.ts +0 -34
  127. package/build/adapters/openclaw/usage.js +0 -52
  128. package/build/adapters/openclaw/workspace-router.d.ts +0 -29
  129. package/build/adapters/openclaw/workspace-router.js +0 -64
  130. package/build/adapters/opencode/config.d.ts +0 -8
  131. package/build/adapters/opencode/config.js +0 -8
  132. package/build/adapters/opencode/hooks.d.ts +0 -38
  133. package/build/adapters/opencode/hooks.js +0 -50
  134. package/build/adapters/opencode/index.d.ts +0 -67
  135. package/build/adapters/opencode/index.js +0 -463
  136. package/build/adapters/opencode/plugin.d.ts +0 -184
  137. package/build/adapters/opencode/plugin.js +0 -558
  138. package/build/adapters/opencode/zod3tov4.d.ts +0 -1
  139. package/build/adapters/opencode/zod3tov4.js +0 -132
  140. package/build/adapters/pi/extension.d.ts +0 -81
  141. package/build/adapters/pi/extension.js +0 -861
  142. package/build/adapters/pi/index.d.ts +0 -57
  143. package/build/adapters/pi/index.js +0 -173
  144. package/build/adapters/pi/mcp-bridge.d.ts +0 -268
  145. package/build/adapters/pi/mcp-bridge.js +0 -894
  146. package/build/adapters/qwen-code/hooks.d.ts +0 -26
  147. package/build/adapters/qwen-code/hooks.js +0 -29
  148. package/build/adapters/qwen-code/index.d.ts +0 -40
  149. package/build/adapters/qwen-code/index.js +0 -361
  150. package/build/adapters/qwen-code/usage.d.ts +0 -90
  151. package/build/adapters/qwen-code/usage.js +0 -222
  152. package/build/adapters/types.d.ts +0 -360
  153. package/build/adapters/types.js +0 -118
  154. package/build/adapters/vscode-copilot/config.d.ts +0 -8
  155. package/build/adapters/vscode-copilot/config.js +0 -8
  156. package/build/adapters/vscode-copilot/hooks.d.ts +0 -71
  157. package/build/adapters/vscode-copilot/hooks.js +0 -98
  158. package/build/adapters/vscode-copilot/index.d.ts +0 -32
  159. package/build/adapters/vscode-copilot/index.js +0 -222
  160. package/build/adapters/zed/index.d.ts +0 -40
  161. package/build/adapters/zed/index.js +0 -163
  162. package/build/cli.d.ts +0 -34
  163. package/build/cli.js +0 -1827
  164. package/build/db-base.d.ts +0 -179
  165. package/build/db-base.js +0 -569
  166. package/build/executor.d.ts +0 -72
  167. package/build/executor.js +0 -678
  168. package/build/exit-classify.d.ts +0 -19
  169. package/build/exit-classify.js +0 -12
  170. package/build/fetch-cache.d.ts +0 -13
  171. package/build/fetch-cache.js +0 -15
  172. package/build/lifecycle.d.ts +0 -124
  173. package/build/lifecycle.js +0 -278
  174. package/build/runPool.d.ts +0 -36
  175. package/build/runPool.js +0 -51
  176. package/build/runtime.d.ts +0 -71
  177. package/build/runtime.js +0 -659
  178. package/build/search/auto-memory.d.ts +0 -47
  179. package/build/search/auto-memory.js +0 -170
  180. package/build/search/ctx-search-schema.d.ts +0 -90
  181. package/build/search/ctx-search-schema.js +0 -135
  182. package/build/search/flood-guard.d.ts +0 -57
  183. package/build/search/flood-guard.js +0 -80
  184. package/build/search/unified.d.ts +0 -56
  185. package/build/search/unified.js +0 -104
  186. package/build/security.d.ts +0 -206
  187. package/build/security.js +0 -780
  188. package/build/server.d.ts +0 -184
  189. package/build/server.js +0 -4563
  190. package/build/session/analytics.d.ts +0 -773
  191. package/build/session/analytics.js +0 -2420
  192. package/build/session/db.d.ts +0 -468
  193. package/build/session/db.js +0 -1308
  194. package/build/session/error-classifier.d.ts +0 -87
  195. package/build/session/error-classifier.js +0 -303
  196. package/build/session/event-emit.d.ts +0 -48
  197. package/build/session/event-emit.js +0 -101
  198. package/build/session/extract.d.ts +0 -333
  199. package/build/session/extract.js +0 -2688
  200. package/build/session/model-prices.json +0 -429
  201. package/build/session/persist-tool-calls.d.ts +0 -54
  202. package/build/session/persist-tool-calls.js +0 -105
  203. package/build/session/pricing.d.ts +0 -64
  204. package/build/session/pricing.js +0 -151
  205. package/build/session/project-attribution.d.ts +0 -73
  206. package/build/session/project-attribution.js +0 -245
  207. package/build/session/purge.d.ts +0 -138
  208. package/build/session/purge.js +0 -240
  209. package/build/session/retrieval-marker.d.ts +0 -39
  210. package/build/session/retrieval-marker.js +0 -65
  211. package/build/session/snapshot.d.ts +0 -46
  212. package/build/session/snapshot.js +0 -532
  213. package/build/store-directory.d.ts +0 -56
  214. package/build/store-directory.js +0 -254
  215. package/build/store.d.ts +0 -147
  216. package/build/store.js +0 -1714
  217. package/build/truncate.d.ts +0 -57
  218. package/build/truncate.js +0 -142
  219. package/build/types.d.ts +0 -117
  220. package/build/types.js +0 -20
  221. package/build/util/claude-config.d.ts +0 -32
  222. package/build/util/claude-config.js +0 -84
  223. package/build/util/hook-config.d.ts +0 -27
  224. package/build/util/hook-config.js +0 -76
  225. package/build/util/jsonc.d.ts +0 -14
  226. package/build/util/jsonc.js +0 -104
  227. package/build/util/plugin-cache-integrity.d.ts +0 -51
  228. package/build/util/plugin-cache-integrity.js +0 -146
  229. package/build/util/project-dir.d.ts +0 -149
  230. package/build/util/project-dir.js +0 -340
  231. package/build/util/sibling-mcp.d.ts +0 -79
  232. package/build/util/sibling-mcp.js +0 -181
  233. package/cli.bundle.mjs +0 -1236
  234. package/configs/antigravity/GEMINI.md +0 -68
  235. package/configs/antigravity/mcp_config.json +0 -7
  236. package/configs/antigravity-cli/hooks/hooks.json +0 -37
  237. package/configs/antigravity-cli/hooks.json +0 -37
  238. package/configs/antigravity-cli/mcp_config.json +0 -10
  239. package/configs/antigravity-cli/plugin.json +0 -14
  240. package/configs/antigravity-cli/rules/context-mode.md +0 -77
  241. package/configs/antigravity-cli/skills/context-mode/SKILL.md +0 -77
  242. package/configs/claude-code/CLAUDE.md +0 -91
  243. package/configs/codex/AGENTS.md +0 -99
  244. package/configs/codex/config.toml +0 -8
  245. package/configs/codex/hooks.json +0 -47
  246. package/configs/copilot-cli/.github/plugin/plugin.json +0 -23
  247. package/configs/copilot-cli/.mcp.json +0 -12
  248. package/configs/copilot-cli/README.md +0 -47
  249. package/configs/copilot-cli/hooks.json +0 -41
  250. package/configs/copilot-cli/skills/context-mode/SKILL.md +0 -38
  251. package/configs/cursor/context-mode.mdc +0 -76
  252. package/configs/cursor/hooks.json +0 -21
  253. package/configs/cursor/mcp.json +0 -7
  254. package/configs/gemini-cli/GEMINI.md +0 -88
  255. package/configs/gemini-cli/mcp.json +0 -7
  256. package/configs/gemini-cli/settings.json +0 -60
  257. package/configs/jetbrains-copilot/copilot-instructions.md +0 -80
  258. package/configs/jetbrains-copilot/hooks.json +0 -16
  259. package/configs/jetbrains-copilot/mcp.json +0 -7
  260. package/configs/kilo/AGENTS.md +0 -84
  261. package/configs/kilo/kilo.json +0 -6
  262. package/configs/kimi/hooks.json +0 -54
  263. package/configs/kiro/KIRO.md +0 -84
  264. package/configs/kiro/agent.json +0 -18
  265. package/configs/kiro/mcp.json +0 -7
  266. package/configs/omp/SYSTEM.md +0 -85
  267. package/configs/omp/mcp.json +0 -7
  268. package/configs/openclaw/AGENTS.md +0 -87
  269. package/configs/openclaw/openclaw.json +0 -13
  270. package/configs/opencode/AGENTS.md +0 -84
  271. package/configs/opencode/opencode.json +0 -6
  272. package/configs/pi/AGENTS.md +0 -3
  273. package/configs/qwen-code/QWEN.md +0 -91
  274. package/configs/vscode-copilot/copilot-instructions.md +0 -80
  275. package/configs/vscode-copilot/hooks.json +0 -16
  276. package/configs/vscode-copilot/mcp.json +0 -7
  277. package/configs/zed/AGENTS.md +0 -68
  278. package/hooks/antigravity-cli/payload.mjs +0 -98
  279. package/hooks/antigravity-cli/posttooluse.mjs +0 -138
  280. package/hooks/antigravity-cli/pretooluse.mjs +0 -78
  281. package/hooks/antigravity-cli/stop.mjs +0 -58
  282. package/hooks/auto-injection.mjs +0 -102
  283. package/hooks/cache-heal-utils.mjs +0 -379
  284. package/hooks/codex/platform.mjs +0 -1
  285. package/hooks/codex/posttooluse.mjs +0 -66
  286. package/hooks/codex/precompact.mjs +0 -70
  287. package/hooks/codex/pretooluse.mjs +0 -42
  288. package/hooks/codex/sessionstart.mjs +0 -121
  289. package/hooks/codex/stop.mjs +0 -138
  290. package/hooks/codex/userpromptsubmit.mjs +0 -75
  291. package/hooks/copilot-cli/posttooluse.mjs +0 -79
  292. package/hooks/copilot-cli/precompact.mjs +0 -66
  293. package/hooks/copilot-cli/pretooluse.mjs +0 -41
  294. package/hooks/copilot-cli/sessionstart.mjs +0 -121
  295. package/hooks/copilot-cli/stop.mjs +0 -59
  296. package/hooks/copilot-cli/userpromptsubmit.mjs +0 -77
  297. package/hooks/core/codex-caps.mjs +0 -112
  298. package/hooks/core/formatters.mjs +0 -356
  299. package/hooks/core/mcp-ready.mjs +0 -109
  300. package/hooks/core/platform-detect.mjs +0 -49
  301. package/hooks/core/routing.mjs +0 -1017
  302. package/hooks/core/stdin.mjs +0 -90
  303. package/hooks/core/tool-naming.mjs +0 -57
  304. package/hooks/cursor/afteragentresponse.mjs +0 -74
  305. package/hooks/cursor/hooks.json +0 -31
  306. package/hooks/cursor/posttooluse.mjs +0 -72
  307. package/hooks/cursor/pretooluse.mjs +0 -26
  308. package/hooks/cursor/sessionstart.mjs +0 -97
  309. package/hooks/cursor/stop.mjs +0 -48
  310. package/hooks/ensure-deps.mjs +0 -254
  311. package/hooks/formatters/claude-code.mjs +0 -113
  312. package/hooks/formatters/cursor.mjs +0 -37
  313. package/hooks/formatters/gemini-cli.mjs +0 -55
  314. package/hooks/formatters/vscode-copilot.mjs +0 -55
  315. package/hooks/gemini-cli/aftermodel.mjs +0 -70
  316. package/hooks/gemini-cli/aftertool.mjs +0 -61
  317. package/hooks/gemini-cli/beforeagent.mjs +0 -99
  318. package/hooks/gemini-cli/beforetool.mjs +0 -27
  319. package/hooks/gemini-cli/precompress.mjs +0 -55
  320. package/hooks/gemini-cli/sessionstart.mjs +0 -137
  321. package/hooks/heal-partial-install.mjs +0 -712
  322. package/hooks/jetbrains-copilot/posttooluse.mjs +0 -61
  323. package/hooks/jetbrains-copilot/precompact.mjs +0 -55
  324. package/hooks/jetbrains-copilot/pretooluse.mjs +0 -27
  325. package/hooks/jetbrains-copilot/sessionstart.mjs +0 -124
  326. package/hooks/kimi/platform.mjs +0 -1
  327. package/hooks/kimi/posttooluse.mjs +0 -72
  328. package/hooks/kimi/precompact.mjs +0 -80
  329. package/hooks/kimi/pretooluse.mjs +0 -42
  330. package/hooks/kimi/sessionend.mjs +0 -61
  331. package/hooks/kimi/sessionstart.mjs +0 -113
  332. package/hooks/kimi/stop.mjs +0 -132
  333. package/hooks/kimi/userpromptsubmit.mjs +0 -90
  334. package/hooks/kiro/agentspawn.mjs +0 -97
  335. package/hooks/kiro/posttooluse.mjs +0 -51
  336. package/hooks/kiro/pretooluse.mjs +0 -64
  337. package/hooks/kiro/userpromptsubmit.mjs +0 -88
  338. package/hooks/normalize-hooks.mjs +0 -323
  339. package/hooks/platform-bridge.mjs +0 -340
  340. package/hooks/posttooluse.mjs +0 -225
  341. package/hooks/precompact.mjs +0 -100
  342. package/hooks/pretooluse.mjs +0 -227
  343. package/hooks/qwen-code/platform.mjs +0 -1
  344. package/hooks/qwen-code/stop.mjs +0 -168
  345. package/hooks/routing-block.mjs +0 -105
  346. package/hooks/run-hook.mjs +0 -95
  347. package/hooks/security.bundle.mjs +0 -2
  348. package/hooks/session-attribution.bundle.mjs +0 -1
  349. package/hooks/session-db.bundle.mjs +0 -144
  350. package/hooks/session-directive.mjs +0 -520
  351. package/hooks/session-extract.bundle.mjs +0 -3
  352. package/hooks/session-helpers.mjs +0 -428
  353. package/hooks/session-loaders.mjs +0 -448
  354. package/hooks/session-snapshot.bundle.mjs +0 -32
  355. package/hooks/sessionstart.mjs +0 -464
  356. package/hooks/stop.mjs +0 -82
  357. package/hooks/suppress-stderr.mjs +0 -25
  358. package/hooks/userpromptsubmit.mjs +0 -108
  359. package/hooks/vscode-copilot/posttooluse.mjs +0 -61
  360. package/hooks/vscode-copilot/precompact.mjs +0 -55
  361. package/hooks/vscode-copilot/pretooluse.mjs +0 -27
  362. package/hooks/vscode-copilot/sessionstart.mjs +0 -129
  363. package/openclaw.plugin.json +0 -38
  364. package/scripts/heal-better-sqlite3.mjs +0 -430
  365. package/scripts/heal-installed-plugins.mjs +0 -598
  366. package/scripts/plugin-cache-integrity.mjs +0 -248
  367. package/scripts/postinstall.mjs +0 -384
  368. package/server.bundle.mjs +0 -1162
  369. package/skills/.ignore +0 -7
  370. package/skills/context-mode/SKILL.md +0 -300
  371. package/skills/context-mode/references/anti-patterns.md +0 -283
  372. package/skills/context-mode/references/patterns-javascript.md +0 -298
  373. package/skills/context-mode/references/patterns-python.md +0 -304
  374. package/skills/context-mode/references/patterns-shell.md +0 -277
  375. package/skills/ctx-index/SKILL.md +0 -46
  376. package/skills/ctx-insight/SKILL.md +0 -24
  377. package/skills/ctx-purge/SKILL.md +0 -49
  378. package/skills/ctx-search/SKILL.md +0 -35
  379. package/start.mjs +0 -616
@@ -1,569 +0,0 @@
1
- /**
2
- * adapters/claude-code — Claude Code platform adapter.
3
- *
4
- * Extends ClaudeCodeBaseAdapter (shared wire-protocol parse/format methods)
5
- * with Claude Code-specific configuration, diagnostics, and upgrade logic.
6
- *
7
- * Claude Code hook specifics:
8
- * - Session ID: transcript_path UUID > session_id > CLAUDE_SESSION_ID > ppid
9
- * - Config root: $CLAUDE_CONFIG_DIR (when set) or ~/.claude
10
- * - Settings: <configDir>/settings.json
11
- * - Session dir: <configDir>/context-mode/sessions/
12
- * - Plugin registry: <configDir>/plugins/installed_plugins.json
13
- */
14
- import { readFileSync, writeFileSync, existsSync, readdirSync, chmodSync, accessSync, mkdirSync, constants, } from "node:fs";
15
- import { resolve, join } from "node:path";
16
- import { homedir } from "node:os";
17
- import { ClaudeCodeBaseAdapter } from "../claude-code-base.js";
18
- import { resolveContextModeDataRoot } from "../base.js";
19
- import { resolveClaudeConfigDir } from "../../util/claude-config.js";
20
- import { checkPluginCacheIntegritySync } from "../../util/plugin-cache-integrity.js";
21
- import { buildHookRuntimeCommand, } from "../types.js";
22
- import { HOOK_TYPES, HOOK_SCRIPTS, REQUIRED_HOOKS, PRE_TOOL_USE_MATCHERS, PRE_TOOL_USE_MATCHER_PATTERN, isContextModeHook, isAnyContextModeHook, extractHookScriptPath, buildHookCommand, } from "./hooks.js";
23
- // ─────────────────────────────────────────────────────────
24
- // Adapter implementation
25
- // ─────────────────────────────────────────────────────────
26
- export class ClaudeCodeAdapter extends ClaudeCodeBaseAdapter {
27
- constructor() {
28
- super([".claude"]);
29
- }
30
- name = "Claude Code";
31
- paradigm = "json-stdio";
32
- projectDirEnvVar = "CLAUDE_PROJECT_DIR";
33
- capabilities = {
34
- preToolUse: true,
35
- postToolUse: true,
36
- preCompact: true,
37
- sessionStart: true,
38
- canModifyArgs: true,
39
- canModifyOutput: true,
40
- canInjectSessionContext: true,
41
- };
42
- // ── Configuration ──────────────────────────────────────
43
- /**
44
- * Honor `CLAUDE_CONFIG_DIR` (the canonical Claude Code config root) before
45
- * falling back to `~/.claude`. Mirrors the contract that
46
- * `hooks/session-helpers.mjs::resolveConfigDir` already follows — including
47
- * tilde expansion for shells that pass `~/foo` through unchanged — so server
48
- * and hooks agree on where session-scoped state lives. See issue #453.
49
- *
50
- * Tilde regex `/^~[/\\]?/` only handles the current-user form (`~`, `~/`,
51
- * `~\`); `~user/` is NOT expanded to a per-user homedir (matches
52
- * `resolveConfigDir`). Non-tilde values are run through `resolve()` to
53
- * normalize relative paths to absolute against cwd; the hook helper
54
- * intentionally leaves them raw, but the adapter contract guarantees an
55
- * absolute path (BaseAdapter.getConfigDir docstring).
56
- *
57
- * Issue #460 round-3: routed through the canonical
58
- * `resolveClaudeConfigDir` util so server, CLI, security, and adapter
59
- * agree byte-for-byte (incl. empty/whitespace-only env fallback).
60
- */
61
- getConfigDir(_projectDir) {
62
- return resolveClaudeConfigDir();
63
- }
64
- getSessionDir() {
65
- // Issue #649: honor CONTEXT_MODE_DATA_DIR universal storage override
66
- // before falling back to the Claude-rooted default. The override moves
67
- // ONLY context-mode-owned state; settings.json + CLAUDE_CONFIG_DIR stay
68
- // intact below.
69
- const override = resolveContextModeDataRoot();
70
- const dir = override
71
- ? join(override, "context-mode", "sessions")
72
- : join(this.getConfigDir(), "context-mode", "sessions");
73
- mkdirSync(dir, { recursive: true });
74
- return dir;
75
- }
76
- getSettingsPath() {
77
- return join(this.getConfigDir(), "settings.json");
78
- }
79
- generateHookConfig(pluginRoot) {
80
- // Algo-D3: every command flows through `buildHookRuntimeCommand`
81
- // (defined in src/adapters/types.ts), which:
82
- // - quotes both runtime path and scriptPath (#548 — Windows
83
- // pluginRoots with spaces no longer fall through
84
- // extractHookScriptPath's ambiguous-tail fallback),
85
- // - swaps backslashes for forward slashes (#372 MSYS path mangling),
86
- // - resolves the JS runtime via `resolveHookRuntime`: Bun ≥1.0 when
87
- // available, else `process.execPath` (#369 PATH resolution on Git
88
- // Bash, #738 bun cold-start win).
89
- // Pre-D3 we hand-rolled `node "${pluginRoot}/hooks/X.mjs"` for all
90
- // six events; bare `node` made claude-code the lone outlier and
91
- // dropping the execPath swap re-opened the Windows class. Algo-D3.5
92
- // (CI invariant in tests/adapters/claude-code.test.ts) locks this in
93
- // for adapter #16.
94
- const preToolUseCommand = buildHookRuntimeCommand(`${pluginRoot}/hooks/pretooluse.mjs`);
95
- const preToolUseMatchers = [...PRE_TOOL_USE_MATCHERS];
96
- return {
97
- PreToolUse: preToolUseMatchers.map((matcher) => ({
98
- matcher,
99
- hooks: [{ type: "command", command: preToolUseCommand }],
100
- })),
101
- PostToolUse: [
102
- {
103
- matcher: "",
104
- hooks: [
105
- {
106
- type: "command",
107
- command: buildHookRuntimeCommand(`${pluginRoot}/hooks/posttooluse.mjs`),
108
- },
109
- ],
110
- },
111
- ],
112
- PreCompact: [
113
- {
114
- matcher: "",
115
- hooks: [
116
- {
117
- type: "command",
118
- command: buildHookRuntimeCommand(`${pluginRoot}/hooks/precompact.mjs`),
119
- },
120
- ],
121
- },
122
- ],
123
- UserPromptSubmit: [
124
- {
125
- matcher: "",
126
- hooks: [
127
- {
128
- type: "command",
129
- command: buildHookRuntimeCommand(`${pluginRoot}/hooks/userpromptsubmit.mjs`),
130
- },
131
- ],
132
- },
133
- ],
134
- SessionStart: [
135
- {
136
- matcher: "",
137
- hooks: [
138
- {
139
- type: "command",
140
- command: buildHookRuntimeCommand(`${pluginRoot}/hooks/sessionstart.mjs`),
141
- },
142
- ],
143
- },
144
- ],
145
- Stop: [
146
- {
147
- matcher: "",
148
- hooks: [
149
- {
150
- type: "command",
151
- command: buildHookRuntimeCommand(`${pluginRoot}/hooks/stop.mjs`),
152
- },
153
- ],
154
- },
155
- ],
156
- };
157
- }
158
- readSettings() {
159
- try {
160
- const raw = readFileSync(this.getSettingsPath(), "utf-8");
161
- return JSON.parse(raw);
162
- }
163
- catch {
164
- return null;
165
- }
166
- }
167
- writeSettings(settings) {
168
- writeFileSync(this.getSettingsPath(), JSON.stringify(settings, null, 2) + "\n", "utf-8");
169
- }
170
- // ── Diagnostics (doctor) ─────────────────────────────────
171
- validateHooks(pluginRoot) {
172
- const results = [];
173
- const settings = this.readSettings();
174
- if (!settings) {
175
- results.push({
176
- check: "PreToolUse hook",
177
- status: "fail",
178
- message: `Could not read ${this.getSettingsPath()}`,
179
- fix: "context-mode upgrade",
180
- });
181
- return results;
182
- }
183
- const hooks = settings.hooks;
184
- // Read plugin hooks.json as fallback (Issue #94: plugin installs
185
- // register hooks in hooks/hooks.json, not in settings.json)
186
- const pluginHooks = this.readPluginHooks(pluginRoot);
187
- // Check PreToolUse (settings.json first, then plugin hooks.json fallback)
188
- const hasPreToolUse = this.checkHookType(hooks, pluginHooks, HOOK_TYPES.PRE_TOOL_USE);
189
- results.push({
190
- check: "PreToolUse hook",
191
- status: hasPreToolUse ? "pass" : "fail",
192
- message: hasPreToolUse
193
- ? "PreToolUse hook configured"
194
- : "No PreToolUse hooks found",
195
- fix: hasPreToolUse ? undefined : "context-mode upgrade",
196
- });
197
- // Check SessionStart (settings.json first, then plugin hooks.json fallback)
198
- const hasSessionStart = this.checkHookType(hooks, pluginHooks, HOOK_TYPES.SESSION_START);
199
- results.push({
200
- check: "SessionStart hook",
201
- status: hasSessionStart ? "pass" : "fail",
202
- message: hasSessionStart
203
- ? "SessionStart hook configured"
204
- : "No SessionStart hooks found",
205
- fix: hasSessionStart ? undefined : "context-mode upgrade",
206
- });
207
- return results;
208
- }
209
- /**
210
- * Adapter-defined health checks (Algo-D1 + Algo-D5).
211
- *
212
- * For each entry in HOOK_SCRIPTS (the canonical hookType → scriptName
213
- * map), emit a HealthCheck that joins `pluginRoot + "hooks" +
214
- * scriptName` and probes via `existsSync`. Crucially, this NEVER
215
- * parses a hook command — pluginRoot and scriptName are both in our
216
- * hand, so the regex round-trip that produced the #548 doubled-path
217
- * FAIL is bypassed entirely.
218
- *
219
- * The hook check derives from HOOK_SCRIPTS (single source of truth in
220
- * src/adapters/claude-code/hooks.ts), so adding a new hook event in
221
- * that map auto-extends doctor coverage — no parallel hardcoded list
222
- * to maintain.
223
- *
224
- * Algo-D5: appends a single "Plugin cache integrity" check that
225
- * delegates to the same helper start.mjs uses at boot
226
- * (scripts/plugin-cache-integrity.mjs::assertPluginCacheIntegrity).
227
- * Same code, two callsites — boot fail-fast and doctor diagnostic
228
- * agree byte-for-byte. Users hitting #550 get the actionable signal
229
- * without restarting the MCP server.
230
- */
231
- getHealthChecks(pluginRoot) {
232
- const hookChecks = Object.entries(HOOK_SCRIPTS).map(([hookType, scriptName]) => {
233
- const absolutePath = join(pluginRoot, "hooks", scriptName);
234
- return {
235
- name: `Hook script: ${hookType} (${scriptName})`,
236
- check: () => {
237
- // Direct existsSync — no hook-command parsing, no regex.
238
- // pluginRoot is the value the doctor was invoked with;
239
- // scriptName comes from the canonical HOOK_SCRIPTS map.
240
- if (existsSync(absolutePath)) {
241
- return { status: "OK", detail: absolutePath };
242
- }
243
- return {
244
- status: "FAIL",
245
- detail: `not found at ${absolutePath}`,
246
- };
247
- },
248
- };
249
- });
250
- const integrityCheck = {
251
- name: "Plugin cache integrity",
252
- check: () => checkPluginCacheIntegritySync(pluginRoot),
253
- };
254
- return [...hookChecks, integrityCheck];
255
- }
256
- /** Read plugin hooks from hooks/hooks.json or .claude-plugin/hooks/hooks.json */
257
- readPluginHooks(pluginRoot) {
258
- const candidates = [
259
- join(pluginRoot, "hooks", "hooks.json"),
260
- join(pluginRoot, ".claude-plugin", "hooks", "hooks.json"),
261
- ];
262
- for (const candidate of candidates) {
263
- try {
264
- const raw = readFileSync(candidate, "utf-8");
265
- const parsed = JSON.parse(raw);
266
- if (parsed.hooks)
267
- return parsed.hooks;
268
- }
269
- catch { /* not available */ }
270
- }
271
- return undefined;
272
- }
273
- /** Check if a hook type is configured in either settings.json or plugin hooks */
274
- checkHookType(settingsHooks, pluginHooks, hookType) {
275
- // Check settings.json
276
- const fromSettings = settingsHooks?.[hookType];
277
- if (fromSettings && fromSettings.length > 0) {
278
- if (fromSettings.some((entry) => isContextModeHook(entry, hookType))) {
279
- return true;
280
- }
281
- }
282
- // Fallback: check plugin hooks.json
283
- const fromPlugin = pluginHooks?.[hookType];
284
- if (fromPlugin && fromPlugin.length > 0) {
285
- if (fromPlugin.some((entry) => isContextModeHook(entry, hookType))) {
286
- return true;
287
- }
288
- }
289
- return false;
290
- }
291
- checkPluginRegistration() {
292
- const settings = this.readSettings();
293
- if (!settings) {
294
- return {
295
- check: "Plugin registration",
296
- status: "warn",
297
- message: "Could not read settings.json",
298
- };
299
- }
300
- const enabledPlugins = settings.enabledPlugins;
301
- if (!enabledPlugins) {
302
- return {
303
- check: "Plugin registration",
304
- status: "warn",
305
- message: "No enabledPlugins section found (might be using standalone MCP mode)",
306
- };
307
- }
308
- const pluginKey = Object.keys(enabledPlugins).find((k) => k.startsWith("context-mode"));
309
- if (pluginKey && enabledPlugins[pluginKey]) {
310
- return {
311
- check: "Plugin registration",
312
- status: "pass",
313
- message: `Plugin enabled: ${pluginKey}`,
314
- };
315
- }
316
- return {
317
- check: "Plugin registration",
318
- status: "warn",
319
- message: "context-mode not in enabledPlugins (might be using standalone MCP mode)",
320
- };
321
- }
322
- getInstalledVersion() {
323
- // Primary: read from installed_plugins.json
324
- try {
325
- const ipPath = join(this.getConfigDir(), "plugins", "installed_plugins.json");
326
- const ipRaw = JSON.parse(readFileSync(ipPath, "utf-8"));
327
- const plugins = ipRaw.plugins ?? {};
328
- for (const [key, entries] of Object.entries(plugins)) {
329
- if (!key.toLowerCase().includes("context-mode"))
330
- continue;
331
- const arr = entries;
332
- if (arr.length > 0 && typeof arr[0].version === "string") {
333
- return arr[0].version;
334
- }
335
- }
336
- }
337
- catch {
338
- /* fallback below */
339
- }
340
- // Fallback: scan common plugin cache locations.
341
- // `resolveClaudeConfigDir` honors $CLAUDE_CONFIG_DIR; the literal
342
- // `~/.claude` is also retained as a hard floor so environments that
343
- // misconfigure the env still find the canonical dir if it exists.
344
- const bases = Array.from(new Set([
345
- this.getConfigDir(),
346
- resolveClaudeConfigDir(),
347
- resolve(homedir(), ".claude"),
348
- resolve(homedir(), ".config", "claude"),
349
- ]));
350
- for (const base of bases) {
351
- const cacheDir = resolve(base, "plugins", "cache", "context-mode", "context-mode");
352
- try {
353
- const entries = readdirSync(cacheDir);
354
- const versions = entries
355
- .filter((e) => /^\d+\.\d+\.\d+/.test(e))
356
- .sort((a, b) => {
357
- const pa = a.split(".").map(Number);
358
- const pb = b.split(".").map(Number);
359
- for (let i = 0; i < 3; i++) {
360
- if ((pa[i] ?? 0) !== (pb[i] ?? 0))
361
- return (pa[i] ?? 0) - (pb[i] ?? 0);
362
- }
363
- return 0;
364
- });
365
- if (versions.length > 0)
366
- return versions[versions.length - 1];
367
- }
368
- catch {
369
- /* continue */
370
- }
371
- }
372
- return "not installed";
373
- }
374
- // ── Upgrade ────────────────────────────────────────────
375
- configureAllHooks(pluginRoot) {
376
- const settings = this.readSettings() ?? {};
377
- const hooks = (settings.hooks ?? {});
378
- const changes = [];
379
- // Remove stale context-mode hook entries across ALL hook types (fixes #187).
380
- // After a marketplace auto-update or version change, settings.json may contain
381
- // hardcoded paths pointing to deleted version directories (e.g., .../0.9.17/hooks/...).
382
- // Clean these before registering fresh entries to prevent SessionStart errors.
383
- for (const hookType of Object.keys(hooks)) {
384
- const entries = hooks[hookType];
385
- if (!Array.isArray(entries))
386
- continue;
387
- const filtered = entries.filter((entry) => {
388
- const typedEntry = entry;
389
- if (!isAnyContextModeHook(typedEntry))
390
- return true; // preserve non-context-mode hooks
391
- // Keep CLI dispatcher entries (path-independent, never stale)
392
- const commands = typedEntry.hooks ?? [];
393
- const hasOnlyDispatcherCommands = commands.every((h) => !h.command || !extractHookScriptPath(h.command));
394
- if (hasOnlyDispatcherCommands)
395
- return true;
396
- // For node path commands, check if the referenced script file exists
397
- return commands.every((h) => {
398
- const scriptPath = h.command ? extractHookScriptPath(h.command) : null;
399
- if (!scriptPath)
400
- return true; // not a path-based command
401
- return existsSync(scriptPath);
402
- });
403
- });
404
- const removed = entries.length - filtered.length;
405
- if (removed > 0) {
406
- hooks[hookType] = filtered;
407
- changes.push(`Removed ${removed} stale ${hookType} hook(s)`);
408
- }
409
- }
410
- // If plugin hooks.json already covers all required hooks AND context-mode is
411
- // actually installed as a Claude Code plugin (present in enabledPlugins), skip
412
- // settings.json registration — hooks.json with ${CLAUDE_PLUGIN_ROOT} is the
413
- // source of truth for plugin installs (Issue #198).
414
- //
415
- // Standalone / MacPorts installs are NOT in enabledPlugins. For those, the
416
- // hooks/hooks.json shipped in the npm package is never consulted by Claude Code
417
- // (it uses ${CLAUDE_PLUGIN_ROOT} which is only set in plugin mode). We must
418
- // always write absolute-path hook commands to settings.json in that case.
419
- const pluginRegistration = this.checkPluginRegistration();
420
- const isPluginInstall = pluginRegistration.status === "pass";
421
- const pluginHooks = isPluginInstall ? this.readPluginHooks(pluginRoot) : undefined;
422
- if (pluginHooks) {
423
- const allCovered = REQUIRED_HOOKS.every((ht) => this.checkHookType(undefined, pluginHooks, ht));
424
- if (allCovered) {
425
- // Strip ONLY the inner context-mode hook commands from each matcher entry —
426
- // hooks.json is the source of truth for ctx-mode. User hooks co-located in
427
- // the same matcher entry MUST be preserved (#415: entry-level filter wiped
428
- // every co-located user hook). After stripping, prune entries whose `hooks`
429
- // array becomes empty.
430
- const ctxScriptNames = Object.values(HOOK_SCRIPTS);
431
- const isCtxModeCommand = (cmd) => cmd != null &&
432
- (ctxScriptNames.some((s) => cmd.includes(s)) ||
433
- cmd.includes("context-mode hook"));
434
- for (const hookType of Object.keys(hooks)) {
435
- const entries = hooks[hookType];
436
- if (!Array.isArray(entries))
437
- continue;
438
- let totalRemoved = 0;
439
- for (const entry of entries) {
440
- const typedEntry = entry;
441
- const innerHooks = typedEntry.hooks ?? [];
442
- const before = innerHooks.length;
443
- typedEntry.hooks = innerHooks.filter((h) => !isCtxModeCommand(h.command));
444
- totalRemoved += before - typedEntry.hooks.length;
445
- }
446
- const pruned = entries.filter((e) => {
447
- const ih = e.hooks;
448
- return Array.isArray(ih) && ih.length > 0;
449
- });
450
- if (totalRemoved > 0 || pruned.length !== entries.length) {
451
- hooks[hookType] = pruned;
452
- if (totalRemoved > 0) {
453
- changes.push(`Removed ${totalRemoved} duplicate ${hookType} hook(s) — covered by plugin hooks.json`);
454
- }
455
- }
456
- }
457
- settings.hooks = hooks;
458
- this.writeSettings(settings);
459
- changes.push("Skipped settings.json registration — plugin hooks.json is sufficient");
460
- return changes;
461
- }
462
- }
463
- // Register fresh hooks for required hook types
464
- const hookTypes = [
465
- HOOK_TYPES.PRE_TOOL_USE,
466
- HOOK_TYPES.SESSION_START,
467
- ];
468
- for (const hookType of hookTypes) {
469
- const command = buildHookCommand(hookType, pluginRoot);
470
- if (hookType === HOOK_TYPES.PRE_TOOL_USE) {
471
- const entry = {
472
- matcher: PRE_TOOL_USE_MATCHER_PATTERN,
473
- hooks: [{ type: "command", command }],
474
- };
475
- const existing = hooks.PreToolUse;
476
- if (existing && Array.isArray(existing)) {
477
- const idx = existing.findIndex((e) => isContextModeHook(e, hookType));
478
- if (idx >= 0) {
479
- existing[idx] = entry;
480
- changes.push(`Updated existing ${hookType} hook entry`);
481
- }
482
- else {
483
- existing.push(entry);
484
- changes.push(`Added ${hookType} hook entry`);
485
- }
486
- hooks.PreToolUse = existing;
487
- }
488
- else {
489
- hooks.PreToolUse = [entry];
490
- changes.push(`Created ${hookType} hooks section`);
491
- }
492
- }
493
- else {
494
- const entry = {
495
- matcher: "",
496
- hooks: [{ type: "command", command }],
497
- };
498
- const existing = hooks[hookType];
499
- if (existing && Array.isArray(existing)) {
500
- const idx = existing.findIndex((e) => isContextModeHook(e, hookType));
501
- if (idx >= 0) {
502
- existing[idx] = entry;
503
- changes.push(`Updated existing ${hookType} hook entry`);
504
- }
505
- else {
506
- existing.push(entry);
507
- changes.push(`Added ${hookType} hook entry`);
508
- }
509
- hooks[hookType] = existing;
510
- }
511
- else {
512
- hooks[hookType] = [entry];
513
- changes.push(`Created ${hookType} hooks section`);
514
- }
515
- }
516
- }
517
- settings.hooks = hooks;
518
- this.writeSettings(settings);
519
- return changes;
520
- }
521
- setHookPermissions(pluginRoot) {
522
- const set = [];
523
- for (const [, scriptName] of Object.entries(HOOK_SCRIPTS)) {
524
- const scriptPath = resolve(pluginRoot, "hooks", scriptName);
525
- try {
526
- accessSync(scriptPath, constants.R_OK);
527
- chmodSync(scriptPath, 0o755);
528
- set.push(scriptPath);
529
- }
530
- catch {
531
- /* skip missing scripts */
532
- }
533
- }
534
- return set;
535
- }
536
- updatePluginRegistry(pluginRoot, version) {
537
- try {
538
- const ipPath = join(this.getConfigDir(), "plugins", "installed_plugins.json");
539
- const ipRaw = JSON.parse(readFileSync(ipPath, "utf-8"));
540
- for (const [key, entries] of Object.entries(ipRaw.plugins || {})) {
541
- if (!key.toLowerCase().includes("context-mode"))
542
- continue;
543
- for (const entry of entries) {
544
- entry.installPath = pluginRoot;
545
- entry.version = version;
546
- entry.lastUpdated = new Date().toISOString();
547
- }
548
- }
549
- writeFileSync(ipPath, JSON.stringify(ipRaw, null, 2) + "\n", "utf-8");
550
- }
551
- catch {
552
- /* best effort */
553
- }
554
- }
555
- // ── Session ID extraction ───────────────────────────────
556
- // Claude Code priority: transcript_path UUID > session_id > CLAUDE_SESSION_ID > ppid
557
- extractSessionId(input) {
558
- if (input.transcript_path) {
559
- const match = input.transcript_path.match(/([a-f0-9-]{36})\.jsonl$/);
560
- if (match)
561
- return match[1];
562
- }
563
- if (input.session_id)
564
- return input.session_id;
565
- if (process.env.CLAUDE_SESSION_ID)
566
- return process.env.CLAUDE_SESSION_ID;
567
- return `pid-${process.ppid}`;
568
- }
569
- }
@@ -1,49 +0,0 @@
1
- /**
2
- * adapters/claude-code-base — Shared base for Claude Code wire-protocol adapters.
3
- *
4
- * Claude Code and Qwen Code use the identical JSON stdin/stdout hook protocol:
5
- * - Input fields: tool_name, tool_input, tool_output, is_error, session_id,
6
- * transcript_path, source
7
- * - Blocking: `permissionDecision: "deny"` in response
8
- * - Arg modification: `updatedInput` field in response
9
- * - Output modification: `updatedMCPToolOutput` field in response
10
- * - Context injection: `additionalContext` at response root (not wrapped)
11
- * - PreCompact/SessionStart: stdout on exit 0
12
- *
13
- * This base class implements the 8 shared parse/format methods.
14
- * Subclasses provide platform-specific config (env vars, settings path,
15
- * session ID priority, hook config, diagnostics, upgrade).
16
- */
17
- import { BaseAdapter } from "./base.js";
18
- import type { PreToolUseEvent, PostToolUseEvent, PreCompactEvent, SessionStartEvent, PreToolUseResponse, PostToolUseResponse, PreCompactResponse, SessionStartResponse } from "./types.js";
19
- export interface ClaudeCodeWireInput {
20
- tool_name?: string;
21
- tool_input?: Record<string, unknown>;
22
- tool_output?: string;
23
- is_error?: boolean;
24
- session_id?: string;
25
- transcript_path?: string;
26
- source?: string;
27
- }
28
- export declare abstract class ClaudeCodeBaseAdapter extends BaseAdapter {
29
- /**
30
- * Environment variable name for the project directory.
31
- * Claude Code: "CLAUDE_PROJECT_DIR", Qwen Code: "QWEN_PROJECT_DIR"
32
- */
33
- protected abstract readonly projectDirEnvVar: string;
34
- parsePreToolUseInput(raw: unknown): PreToolUseEvent;
35
- parsePostToolUseInput(raw: unknown): PostToolUseEvent;
36
- parsePreCompactInput(raw: unknown): PreCompactEvent;
37
- parseSessionStartInput(raw: unknown): SessionStartEvent;
38
- formatPreToolUseResponse(response: PreToolUseResponse): unknown;
39
- formatPostToolUseResponse(response: PostToolUseResponse): unknown;
40
- formatPreCompactResponse(response: PreCompactResponse): unknown;
41
- formatSessionStartResponse(response: SessionStartResponse): unknown;
42
- /**
43
- * Extract session ID from wire input. Default priority (Claude Code):
44
- * transcript_path UUID > session_id > env var > ppid fallback
45
- *
46
- * Override in subclasses for different priority (e.g., Qwen: session_id first).
47
- */
48
- protected abstract extractSessionId(input: ClaudeCodeWireInput): string;
49
- }