context-mode 1.0.168 → 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 (395) 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/cache-heal.d.ts +0 -48
  163. package/build/cache-heal.js +0 -150
  164. package/build/cli.d.ts +0 -34
  165. package/build/cli.js +0 -1827
  166. package/build/concurrency/runPool.d.ts +0 -36
  167. package/build/concurrency/runPool.js +0 -51
  168. package/build/db-base.d.ts +0 -179
  169. package/build/db-base.js +0 -569
  170. package/build/executor.d.ts +0 -72
  171. package/build/executor.js +0 -678
  172. package/build/exit-classify.d.ts +0 -19
  173. package/build/exit-classify.js +0 -12
  174. package/build/fetch-cache.d.ts +0 -13
  175. package/build/fetch-cache.js +0 -15
  176. package/build/lifecycle.d.ts +0 -124
  177. package/build/lifecycle.js +0 -278
  178. package/build/openclaw/mcp-tools.d.ts +0 -54
  179. package/build/openclaw/mcp-tools.js +0 -198
  180. package/build/openclaw/workspace-router.d.ts +0 -29
  181. package/build/openclaw/workspace-router.js +0 -64
  182. package/build/openclaw-plugin.d.ts +0 -130
  183. package/build/openclaw-plugin.js +0 -626
  184. package/build/opencode-plugin.d.ts +0 -122
  185. package/build/opencode-plugin.js +0 -375
  186. package/build/pi-extension.d.ts +0 -14
  187. package/build/pi-extension.js +0 -451
  188. package/build/routing-block.d.ts +0 -8
  189. package/build/routing-block.js +0 -86
  190. package/build/runPool.d.ts +0 -36
  191. package/build/runPool.js +0 -51
  192. package/build/runtime.d.ts +0 -71
  193. package/build/runtime.js +0 -659
  194. package/build/search/auto-memory.d.ts +0 -47
  195. package/build/search/auto-memory.js +0 -170
  196. package/build/search/ctx-search-schema.d.ts +0 -90
  197. package/build/search/ctx-search-schema.js +0 -135
  198. package/build/search/flood-guard.d.ts +0 -57
  199. package/build/search/flood-guard.js +0 -80
  200. package/build/search/unified.d.ts +0 -56
  201. package/build/search/unified.js +0 -104
  202. package/build/security.d.ts +0 -206
  203. package/build/security.js +0 -780
  204. package/build/server.d.ts +0 -184
  205. package/build/server.js +0 -4542
  206. package/build/session/analytics.d.ts +0 -745
  207. package/build/session/analytics.js +0 -2369
  208. package/build/session/db.d.ts +0 -468
  209. package/build/session/db.js +0 -1308
  210. package/build/session/error-classifier.d.ts +0 -87
  211. package/build/session/error-classifier.js +0 -303
  212. package/build/session/event-emit.d.ts +0 -48
  213. package/build/session/event-emit.js +0 -101
  214. package/build/session/extract.d.ts +0 -333
  215. package/build/session/extract.js +0 -2688
  216. package/build/session/model-prices.json +0 -429
  217. package/build/session/persist-tool-calls.d.ts +0 -54
  218. package/build/session/persist-tool-calls.js +0 -105
  219. package/build/session/pricing.d.ts +0 -64
  220. package/build/session/pricing.js +0 -151
  221. package/build/session/project-attribution.d.ts +0 -73
  222. package/build/session/project-attribution.js +0 -245
  223. package/build/session/purge.d.ts +0 -138
  224. package/build/session/purge.js +0 -240
  225. package/build/session/snapshot.d.ts +0 -46
  226. package/build/session/snapshot.js +0 -532
  227. package/build/store-directory.d.ts +0 -56
  228. package/build/store-directory.js +0 -254
  229. package/build/store.d.ts +0 -147
  230. package/build/store.js +0 -1714
  231. package/build/tool-naming.d.ts +0 -4
  232. package/build/tool-naming.js +0 -24
  233. package/build/truncate.d.ts +0 -57
  234. package/build/truncate.js +0 -142
  235. package/build/types.d.ts +0 -117
  236. package/build/types.js +0 -20
  237. package/build/util/claude-config.d.ts +0 -32
  238. package/build/util/claude-config.js +0 -84
  239. package/build/util/hook-config.d.ts +0 -27
  240. package/build/util/hook-config.js +0 -76
  241. package/build/util/jsonc.d.ts +0 -14
  242. package/build/util/jsonc.js +0 -104
  243. package/build/util/plugin-cache-integrity.d.ts +0 -51
  244. package/build/util/plugin-cache-integrity.js +0 -146
  245. package/build/util/project-dir.d.ts +0 -149
  246. package/build/util/project-dir.js +0 -340
  247. package/build/util/sibling-mcp.d.ts +0 -79
  248. package/build/util/sibling-mcp.js +0 -181
  249. package/cli.bundle.mjs +0 -1235
  250. package/configs/antigravity/GEMINI.md +0 -68
  251. package/configs/antigravity/mcp_config.json +0 -7
  252. package/configs/antigravity-cli/hooks/hooks.json +0 -37
  253. package/configs/antigravity-cli/hooks.json +0 -37
  254. package/configs/antigravity-cli/mcp_config.json +0 -10
  255. package/configs/antigravity-cli/plugin.json +0 -14
  256. package/configs/antigravity-cli/rules/context-mode.md +0 -77
  257. package/configs/antigravity-cli/skills/context-mode/SKILL.md +0 -77
  258. package/configs/claude-code/CLAUDE.md +0 -91
  259. package/configs/codex/AGENTS.md +0 -99
  260. package/configs/codex/config.toml +0 -8
  261. package/configs/codex/hooks.json +0 -47
  262. package/configs/copilot-cli/.github/plugin/plugin.json +0 -23
  263. package/configs/copilot-cli/.mcp.json +0 -12
  264. package/configs/copilot-cli/README.md +0 -47
  265. package/configs/copilot-cli/hooks.json +0 -41
  266. package/configs/copilot-cli/skills/context-mode/SKILL.md +0 -38
  267. package/configs/cursor/context-mode.mdc +0 -76
  268. package/configs/cursor/hooks.json +0 -21
  269. package/configs/cursor/mcp.json +0 -7
  270. package/configs/gemini-cli/GEMINI.md +0 -88
  271. package/configs/gemini-cli/mcp.json +0 -7
  272. package/configs/gemini-cli/settings.json +0 -60
  273. package/configs/jetbrains-copilot/copilot-instructions.md +0 -80
  274. package/configs/jetbrains-copilot/hooks.json +0 -16
  275. package/configs/jetbrains-copilot/mcp.json +0 -7
  276. package/configs/kilo/AGENTS.md +0 -84
  277. package/configs/kilo/kilo.json +0 -6
  278. package/configs/kimi/hooks.json +0 -54
  279. package/configs/kiro/KIRO.md +0 -84
  280. package/configs/kiro/agent.json +0 -18
  281. package/configs/kiro/mcp.json +0 -7
  282. package/configs/omp/SYSTEM.md +0 -85
  283. package/configs/omp/mcp.json +0 -7
  284. package/configs/openclaw/AGENTS.md +0 -87
  285. package/configs/openclaw/openclaw.json +0 -13
  286. package/configs/opencode/AGENTS.md +0 -84
  287. package/configs/opencode/opencode.json +0 -6
  288. package/configs/pi/AGENTS.md +0 -3
  289. package/configs/qwen-code/QWEN.md +0 -91
  290. package/configs/vscode-copilot/copilot-instructions.md +0 -80
  291. package/configs/vscode-copilot/hooks.json +0 -16
  292. package/configs/vscode-copilot/mcp.json +0 -7
  293. package/configs/zed/AGENTS.md +0 -68
  294. package/hooks/antigravity-cli/payload.mjs +0 -98
  295. package/hooks/antigravity-cli/posttooluse.mjs +0 -138
  296. package/hooks/antigravity-cli/pretooluse.mjs +0 -78
  297. package/hooks/antigravity-cli/stop.mjs +0 -58
  298. package/hooks/auto-injection.mjs +0 -102
  299. package/hooks/cache-heal-utils.mjs +0 -379
  300. package/hooks/codex/platform.mjs +0 -1
  301. package/hooks/codex/posttooluse.mjs +0 -66
  302. package/hooks/codex/precompact.mjs +0 -70
  303. package/hooks/codex/pretooluse.mjs +0 -42
  304. package/hooks/codex/sessionstart.mjs +0 -121
  305. package/hooks/codex/stop.mjs +0 -138
  306. package/hooks/codex/userpromptsubmit.mjs +0 -75
  307. package/hooks/copilot-cli/posttooluse.mjs +0 -79
  308. package/hooks/copilot-cli/precompact.mjs +0 -66
  309. package/hooks/copilot-cli/pretooluse.mjs +0 -41
  310. package/hooks/copilot-cli/sessionstart.mjs +0 -121
  311. package/hooks/copilot-cli/stop.mjs +0 -59
  312. package/hooks/copilot-cli/userpromptsubmit.mjs +0 -77
  313. package/hooks/core/codex-caps.mjs +0 -112
  314. package/hooks/core/formatters.mjs +0 -356
  315. package/hooks/core/mcp-ready.mjs +0 -109
  316. package/hooks/core/platform-detect.mjs +0 -49
  317. package/hooks/core/routing.mjs +0 -1017
  318. package/hooks/core/stdin.mjs +0 -90
  319. package/hooks/core/tool-naming.mjs +0 -57
  320. package/hooks/cursor/afteragentresponse.mjs +0 -74
  321. package/hooks/cursor/hooks.json +0 -31
  322. package/hooks/cursor/posttooluse.mjs +0 -72
  323. package/hooks/cursor/pretooluse.mjs +0 -26
  324. package/hooks/cursor/sessionstart.mjs +0 -97
  325. package/hooks/cursor/stop.mjs +0 -48
  326. package/hooks/ensure-deps.mjs +0 -254
  327. package/hooks/formatters/claude-code.mjs +0 -113
  328. package/hooks/formatters/cursor.mjs +0 -37
  329. package/hooks/formatters/gemini-cli.mjs +0 -55
  330. package/hooks/formatters/vscode-copilot.mjs +0 -55
  331. package/hooks/gemini-cli/aftermodel.mjs +0 -70
  332. package/hooks/gemini-cli/aftertool.mjs +0 -61
  333. package/hooks/gemini-cli/beforeagent.mjs +0 -99
  334. package/hooks/gemini-cli/beforetool.mjs +0 -27
  335. package/hooks/gemini-cli/precompress.mjs +0 -55
  336. package/hooks/gemini-cli/sessionstart.mjs +0 -137
  337. package/hooks/heal-partial-install.mjs +0 -712
  338. package/hooks/jetbrains-copilot/posttooluse.mjs +0 -61
  339. package/hooks/jetbrains-copilot/precompact.mjs +0 -55
  340. package/hooks/jetbrains-copilot/pretooluse.mjs +0 -27
  341. package/hooks/jetbrains-copilot/sessionstart.mjs +0 -124
  342. package/hooks/kimi/platform.mjs +0 -1
  343. package/hooks/kimi/posttooluse.mjs +0 -72
  344. package/hooks/kimi/precompact.mjs +0 -80
  345. package/hooks/kimi/pretooluse.mjs +0 -42
  346. package/hooks/kimi/sessionend.mjs +0 -61
  347. package/hooks/kimi/sessionstart.mjs +0 -113
  348. package/hooks/kimi/stop.mjs +0 -132
  349. package/hooks/kimi/userpromptsubmit.mjs +0 -90
  350. package/hooks/kiro/agentspawn.mjs +0 -97
  351. package/hooks/kiro/posttooluse.mjs +0 -51
  352. package/hooks/kiro/pretooluse.mjs +0 -64
  353. package/hooks/kiro/userpromptsubmit.mjs +0 -88
  354. package/hooks/normalize-hooks.mjs +0 -323
  355. package/hooks/platform-bridge.mjs +0 -340
  356. package/hooks/posttooluse.mjs +0 -187
  357. package/hooks/precompact.mjs +0 -100
  358. package/hooks/pretooluse.mjs +0 -227
  359. package/hooks/qwen-code/platform.mjs +0 -1
  360. package/hooks/qwen-code/stop.mjs +0 -168
  361. package/hooks/routing-block.mjs +0 -105
  362. package/hooks/run-hook.mjs +0 -95
  363. package/hooks/security.bundle.mjs +0 -2
  364. package/hooks/session-attribution.bundle.mjs +0 -1
  365. package/hooks/session-db.bundle.mjs +0 -144
  366. package/hooks/session-directive.mjs +0 -520
  367. package/hooks/session-extract.bundle.mjs +0 -3
  368. package/hooks/session-helpers.mjs +0 -428
  369. package/hooks/session-loaders.mjs +0 -448
  370. package/hooks/session-snapshot.bundle.mjs +0 -32
  371. package/hooks/sessionstart.mjs +0 -464
  372. package/hooks/stop.mjs +0 -82
  373. package/hooks/suppress-stderr.mjs +0 -25
  374. package/hooks/userpromptsubmit.mjs +0 -108
  375. package/hooks/vscode-copilot/posttooluse.mjs +0 -61
  376. package/hooks/vscode-copilot/precompact.mjs +0 -55
  377. package/hooks/vscode-copilot/pretooluse.mjs +0 -27
  378. package/hooks/vscode-copilot/sessionstart.mjs +0 -129
  379. package/openclaw.plugin.json +0 -38
  380. package/scripts/heal-better-sqlite3.mjs +0 -430
  381. package/scripts/heal-installed-plugins.mjs +0 -598
  382. package/scripts/plugin-cache-integrity.mjs +0 -248
  383. package/scripts/postinstall.mjs +0 -384
  384. package/server.bundle.mjs +0 -1161
  385. package/skills/.ignore +0 -7
  386. package/skills/context-mode/SKILL.md +0 -300
  387. package/skills/context-mode/references/anti-patterns.md +0 -283
  388. package/skills/context-mode/references/patterns-javascript.md +0 -298
  389. package/skills/context-mode/references/patterns-python.md +0 -304
  390. package/skills/context-mode/references/patterns-shell.md +0 -277
  391. package/skills/ctx-index/SKILL.md +0 -46
  392. package/skills/ctx-insight/SKILL.md +0 -24
  393. package/skills/ctx-purge/SKILL.md +0 -49
  394. package/skills/ctx-search/SKILL.md +0 -35
  395. package/start.mjs +0 -616
@@ -1,448 +0,0 @@
1
- /**
2
- * Session module loaders — bundle-first with build/ fallback.
3
- *
4
- * All session modules are loaded from esbuild bundles (hooks/session-*.bundle.mjs).
5
- * Bundles are built by CI (bundle.yml) and shipped with every release.
6
- * Fallback: if bundles are missing (marketplace installs), try build/session/*.js.
7
- */
8
-
9
- import { join, resolve as resolvePath } from "node:path";
10
- import { pathToFileURL } from "node:url";
11
- import { existsSync, readFileSync } from "node:fs";
12
- import { tmpdir } from "node:os";
13
-
14
- import { hasPlatformConfig, maybeForward } from "./platform-bridge.mjs";
15
- import { detectPlatformFromEnv } from "./core/platform-detect.mjs";
16
-
17
- export function createSessionLoaders(hookDir) {
18
- // Auto-detect bundle directory: bundles live in hooks/ root, not platform subdirs.
19
- // If hookDir itself has bundles, use it; otherwise go up one level.
20
- const bundleDir = existsSync(join(hookDir, "session-db.bundle.mjs"))
21
- ? hookDir
22
- : join(hookDir, "..");
23
-
24
- // Fallback: if bundles missing, try build/session/*.js (marketplace installs)
25
- const pluginRoot = join(bundleDir, "..");
26
- const buildSession = join(pluginRoot, "build", "session");
27
-
28
- async function loadModule(bundleName, buildName) {
29
- const bundlePath = join(bundleDir, bundleName);
30
- if (existsSync(bundlePath)) {
31
- return await import(pathToFileURL(bundlePath).href);
32
- }
33
- const buildPath = join(buildSession, buildName);
34
- return await import(pathToFileURL(buildPath).href);
35
- }
36
-
37
- return {
38
- async loadSessionDB() {
39
- return await loadModule("session-db.bundle.mjs", "db.js");
40
- },
41
- async loadProjectAttribution() {
42
- const bundlePath = join(bundleDir, "session-attribution.bundle.mjs");
43
- if (existsSync(bundlePath)) {
44
- return await import(pathToFileURL(bundlePath).href);
45
- }
46
- const buildPath = join(buildSession, "project-attribution.js");
47
- if (existsSync(buildPath)) {
48
- return await import(pathToFileURL(buildPath).href);
49
- }
50
- // Last-resort fallback for dev environments without a fresh build.
51
- const localPath = join(bundleDir, "project-attribution.mjs");
52
- return await import(pathToFileURL(localPath).href);
53
- },
54
- async loadExtract() {
55
- return await loadModule("session-extract.bundle.mjs", "extract.js");
56
- },
57
- async loadSnapshot() {
58
- return await loadModule("session-snapshot.bundle.mjs", "snapshot.js");
59
- },
60
- };
61
- }
62
-
63
- /**
64
- * Shared helper — resolves project attributions and inserts events into the DB.
65
- * Eliminates the ~15-line attribution block duplicated across all hook files.
66
- *
67
- * @returns {Array} The resolved attributions array (useful when a subsequent
68
- * attribution block needs `lastKnownProjectDir` from the first).
69
- */
70
- export function attributeAndInsertEvents(db, sessionId, events, input, projectDir, hookName, resolveProjectAttributions) {
71
- const sessionStats = db.getSessionStats(sessionId);
72
- const lastKnownProjectDir = typeof db.getLatestAttributedProjectDir === "function"
73
- ? db.getLatestAttributedProjectDir(sessionId)
74
- : null;
75
- const attributions = resolveProjectAttributions(events, {
76
- sessionOriginDir: sessionStats?.project_dir || projectDir,
77
- inputProjectDir: projectDir,
78
- workspaceRoots: Array.isArray(input.workspace_roots) ? input.workspace_roots : [],
79
- lastKnownProjectDir,
80
- });
81
- // Build a parallel bytesList from event-level bytes_avoided (currently
82
- // populated by external_ref's ctx_fetch_and_index preamble parser). When
83
- // no event carries a positive value we leave bytesList undefined so
84
- // SessionDB falls back to its 0-default for bytes_avoided/bytes_returned
85
- // — preserves backward compat with older callers / tests.
86
- // v1.0.160: handle both bytes_avoided (saved) and bytes_returned (resume
87
- // snapshot replay) so the snapshot-consumed event from sessionstart.mjs
88
- // routes through here without losing the bytes_returned column.
89
- let bytesList;
90
- const hasBytes = events.some((e) =>
91
- (typeof e?.bytes_avoided === "number" && e.bytes_avoided > 0) ||
92
- (typeof e?.bytes_returned === "number" && e.bytes_returned > 0),
93
- );
94
- if (hasBytes) {
95
- bytesList = events.map((e) => {
96
- const avoided = typeof e?.bytes_avoided === "number" && e.bytes_avoided > 0 ? e.bytes_avoided : 0;
97
- const returned = typeof e?.bytes_returned === "number" && e.bytes_returned > 0 ? e.bytes_returned : 0;
98
- if (avoided === 0 && returned === 0) return undefined;
99
- return { bytesAvoided: avoided, bytesReturned: returned };
100
- });
101
- }
102
- // Prefer bulk path (single transaction = single WAL commit). Falls back
103
- // to per-event insert for older SessionDB instances that lack bulkInsertEvents.
104
- if (typeof db.bulkInsertEvents === "function") {
105
- db.bulkInsertEvents(sessionId, events, hookName, attributions, bytesList);
106
- } else {
107
- for (let i = 0; i < events.length; i++) {
108
- db.insertEvent(sessionId, events[i], hookName, attributions[i], bytesList?.[i]);
109
- }
110
- }
111
-
112
- // PRD-context-as-a-service §5.2 — Forwarder injection.
113
- // Gated: the per-event loop never runs when ~/.context-mode/platform.json
114
- // is missing. hasPlatformConfig() is a single cached probe (60s TTL), so
115
- // the unconfigured-user path costs at most one syscall per minute.
116
- if (hasPlatformConfig()) {
117
- const platform = detectPlatformFromEnv();
118
- // Session-wide rollup snapshot — stamped onto every outgoing event so
119
- // the analytics engine sees the seed.ts shape (tool_calls, errors,
120
- // unique_tools, ...). Defensive call: older SessionDB bundles that
121
- // predate v1.0.158 won't have getSessionRollup; fall back to null
122
- // and the bridge will still pass the per-event facts through.
123
- const rollup = typeof db.getSessionRollup === "function"
124
- ? db.getSessionRollup(sessionId)
125
- : null;
126
-
127
- // v1.0.159: Bash metadata shared across all events from this hook fire.
128
- // A single Bash tool call may emit multiple canonical events (a `git
129
- // pull` produces type=git AND type=cwd) — they all share the same
130
- // command_type / command_tool / exit_code / duration_bucket. Hook
131
- // metadata (latency, exit_code) is also per-call, not per-event.
132
- const bashMeta = deriveBashMetadata(input);
133
- // v1.0.159: latency_ms read from the PreToolUse timestamp stamp.
134
- // PreToolUse writes ms-precision Date.now() to a tmp file, PostToolUse
135
- // reads + computes delta + cleans up. Failure → undefined (no field
136
- // surfaces on the wire; Zod is optional).
137
- const latencyMs = readLatencyMs(sessionId, input?.tool_name);
138
-
139
- for (let i = 0; i < events.length; i++) {
140
- const enriched = enrichEventForPlatform(events[i], attributions[i]);
141
- const withBash = bashMeta ? { ...enriched, ...bashMeta } : enriched;
142
- const withLatency = latencyMs !== undefined
143
- ? { ...withBash, latency_ms: latencyMs, duration_bucket: bucketizeDuration(latencyMs) }
144
- : withBash;
145
- const payload = rollup ? { ...withLatency, ...rollup } : withLatency;
146
- // Forward bytes_avoided (the context-saving savings signal) so the
147
- // platform FinOps P&L can derive savings_usd = bytes/4 × price. Sourced
148
- // from the canonical per-event bytesList (with an event-field fallback);
149
- // only stamped when positive so the wire payload stays minimal.
150
- const avoidedBytes = (bytesList && bytesList[i] && bytesList[i].bytesAvoided > 0)
151
- ? bytesList[i].bytesAvoided
152
- : (typeof events[i]?.bytes_avoided === "number" && events[i].bytes_avoided > 0 ? events[i].bytes_avoided : 0);
153
- const withSavings = avoidedBytes > 0 ? { ...payload, bytes_avoided: avoidedBytes } : payload;
154
- // Forward bytes_retrieved (the OTHER half of the with/without ratio): the
155
- // tool_response size a ctx_search / ctx_fetch_and_index call paid to access
156
- // kept-out content. Mirrors the bytes_avoided stamp — positive-only guard.
157
- const retrievedBytes = typeof events[i]?.bytes_retrieved === "number" && events[i].bytes_retrieved > 0
158
- ? events[i].bytes_retrieved
159
- : 0;
160
- const withRetrieval = retrievedBytes > 0 ? { ...withSavings, bytes_retrieved: retrievedBytes } : withSavings;
161
- maybeForward({ ...withRetrieval, session_id: sessionId }, platform);
162
- }
163
- }
164
-
165
- return attributions;
166
- }
167
-
168
- // ── Per-event enrichment (seed.ts shape parity) ──────────────────────────
169
- //
170
- // Each canonical event from session-extract carries only {type, category, data}.
171
- // The platform's events table has 35 columns; the engine's aggregate SQL reads
172
- // most of them. This helper derives the per-event-derivable subset directly
173
- // from the event's own facts — no I/O, no classifier dependency, no allocation
174
- // beyond the spread. Aggregates (tool_calls, errors, ...) come from the
175
- // session rollup stamp in the caller.
176
- //
177
- // PRD-context-as-a-service §5.4 ABI: bridge stays a dumb pipe. This enrichment
178
- // runs BEFORE maybeForward so the body envelope spreads the enriched event
179
- // unchanged.
180
- function enrichEventForPlatform(event, attribution) {
181
- const error = event?.category === "error" ? 1 : 0;
182
- const dataStr = typeof event?.data === "string" ? event.data : "";
183
-
184
- const enriched = {
185
- ...event,
186
- ...attribution,
187
- error,
188
- // session_* are open-string passthroughs (ADR-0001) — let the platform
189
- // do forensic queries on the raw shape without forcing the wide→narrow
190
- // category derivation to ever round-trip.
191
- session_category: event?.category,
192
- session_type: event?.type,
193
- session_data: dataStr.length > 0 ? dataStr.slice(0, 500) : undefined,
194
- };
195
-
196
- // Error events: surface the message + classify
197
- if (error === 1) {
198
- enriched.error_message = dataStr.slice(0, 1000);
199
- const cls = classifyError(dataStr);
200
- enriched.error_category = cls.error_category;
201
- enriched.error_tool = cls.error_tool;
202
- }
203
-
204
- // blocker_status: derive from the canonical event TYPE, not lexical
205
- // pattern-matching on prose. session-extract already identifies blocker
206
- // states semantically (type='blocker' when the agent signals stuck;
207
- // type='blocker_resolved' on recovery). Regex on error_message would
208
- // false-positive on the millions of error texts in the wild — we let
209
- // the extractor's structural judgment be the source of truth.
210
- if (event?.type === "blocker") enriched.blocker_status = "open";
211
- else if (event?.type === "blocker_resolved") enriched.blocker_status = "resolved";
212
-
213
- // v1.0.161 (Bug 2): gate per-event commit_message + has_commit on
214
- // type='git_commit', NOT category='git'. Non-commit git operations
215
- // (push/diff/status) used to inflate commit_message with the operation
216
- // name and falsely raise has_commit on rows that should have remained
217
- // commit-neutral. The rollup spread now stamps both fields symmetrically
218
- // from the session's latest actual commit — see SessionDB.getSessionRollup
219
- // and src/session/extract.ts:extractGit type discriminator.
220
- if (event?.type === "git_commit" && dataStr.length > 0) {
221
- enriched.commit_message = dataStr.slice(0, 500);
222
- enriched.has_commit = 1;
223
- }
224
-
225
- // File events: ship the file path as the single-item array shape the
226
- // platform schema expects (Zod: z.array(z.string()).max(20))
227
- if (event?.category === "file" && dataStr.length > 0) {
228
- enriched.file_paths = [dataStr.slice(0, 500)];
229
- }
230
-
231
- return enriched;
232
- }
233
-
234
- // ── Inline error classifier — seed.ts ERROR_CATEGORIES parity ────────────
235
- //
236
- // Mirrors src/session/error-classifier.ts's 10-category table for runtime
237
- // callers (this is a .mjs hook file; the TS classifier ships bundled but
238
- // the bundle import path costs an extra ~20ms on first hook fire and an
239
- // extra disk read per hook subprocess. Inline keeps the hot path fast.)
240
- // If the table ever drifts from error-classifier.ts, the classifier test
241
- // suite (tests/session/classifier.test.ts) is the canonical source — sync
242
- // the patterns there first, then mirror here.
243
- function classifyError(message) {
244
- const m = String(message ?? "").toLowerCase();
245
- if (!m) return { error_category: "unknown", error_tool: "Bash" };
246
-
247
- // Order matters: timeout + git_conflict checked BEFORE test_failed so
248
- // "test timed out" and "CONFLICT … fail" land in the right bucket.
249
- if (/etimedout|timed out|timeout|deadline exceeded/.test(m)) return { error_category: "timeout", error_tool: "Bash" };
250
- if (/conflict.*(merge|rebase|git)|merge conflict|^conflict/.test(m)) return { error_category: "git_conflict", error_tool: "Bash" };
251
- if (/enoent|no such file|cannot find module|filenotfounderror/.test(m)) return { error_category: "file_not_found", error_tool: "Read" };
252
- if (/command not found|: not found|exit code 127/.test(m)) return { error_category: "command_not_found", error_tool: "Bash" };
253
- if (/old_string|could not find string|matches multiple/.test(m)) return { error_category: "edit_match_failed", error_tool: "Edit" };
254
- if (/eacces|permission denied|operation not permitted|eperm/.test(m)) return { error_category: "permission_denied", error_tool: "Bash" };
255
- if (/syntaxerror|error ts\d+|unexpected token|parse error/.test(m)) return { error_category: "syntax_error", error_tool: "Bash" };
256
- if (/typeerror|referenceerror|rangeerror|traceback|nullpointer/.test(m)) return { error_category: "runtime_error", error_tool: "Bash" };
257
- if (/test failed|fail |tests failed|assertion/.test(m)) return { error_category: "test_failed", error_tool: "Bash" };
258
- return { error_category: "unknown", error_tool: "Bash" };
259
- }
260
-
261
- // ── Bash metadata derivation — algorithmic, not enumerative ──────────────
262
- //
263
- // A single Bash tool call may emit MULTIPLE canonical events (a `git pull`
264
- // produces type='git' AND type='cwd'). The platform's command_metadata
265
- // describes the BASH CALL, not the per-event derivative — so all events
266
- // from one PostToolUse fire carry the same shape. Non-Bash tool calls
267
- // return null and the per-event fields stay undefined (Zod optional drops
268
- // them silently — no NULL noise on the wire).
269
- //
270
- // DESIGN: tool ecosystems contain millions of CLI binaries but converge on
271
- // a tiny canonical verb set (test/build/install/lint/format/run/start/
272
- // deploy/...). The classifier scans for these verbs at canonical token
273
- // positions — agnostic of which package manager / language / framework.
274
- // New tools without a registry change automatically classify correctly as
275
- // long as they use the verbs (which is the dominant ecosystem convention).
276
- // This was originally regex-table enumeration; the table never converges.
277
- const CANONICAL_VERBS = new Set([
278
- "test", "build", "install", "lint", "format", "run", "start",
279
- "deploy", "compile", "bundle", "watch", "serve", "publish",
280
- ]);
281
- // Runners that wrap the actual executable — strip them so command_tool
282
- // reflects the real binary the user invoked (`bunx pytest` → "pytest",
283
- // not "bunx"). NODE_ENV=production npm run build → "npm".
284
- const COMMAND_RUNNERS = new Set([
285
- "sudo", "doas", "env", "exec", "time",
286
- "npx", "pnpx", "bunx", "pnpm", "yarn", "bun",
287
- ]);
288
- const ENV_ASSIGN_RE = /^[A-Z_][A-Z0-9_]*=/;
289
-
290
- // Tools whose NAME directly implies their type (no subcommand needed).
291
- // Curated minimum — covers the dominant test/lint/format/build/db/http/
292
- // deploy invocations across ecosystems. New ecosystem tools land in
293
- // "other" until added — preferred to a noisy heuristic that misclassifies.
294
- // Lookup is O(1); contrast with the original regex-table approach which
295
- // scaled to no boundary and still missed unknowns.
296
- const CANONICAL_TOOLS = new Map([
297
- // test runners
298
- ["pytest", "test"], ["jest", "test"], ["vitest", "test"], ["mocha", "test"],
299
- ["ava", "test"], ["jasmine", "test"], ["rspec", "test"], ["junit", "test"],
300
- ["tap", "test"], ["karma", "test"],
301
- // linters
302
- ["eslint", "lint"], ["tslint", "lint"], ["ruff", "lint"], ["rubocop", "lint"],
303
- ["pylint", "lint"], ["flake8", "lint"], ["clippy", "lint"], ["staticcheck", "lint"],
304
- ["mypy", "lint"], ["shellcheck", "lint"],
305
- // formatters
306
- ["prettier", "format"], ["black", "format"], ["gofmt", "format"], ["rustfmt", "format"],
307
- ["autopep8", "format"], ["yapf", "format"],
308
- // bundlers / builders
309
- ["webpack", "build"], ["vite", "build"], ["rollup", "build"], ["esbuild", "build"],
310
- ["parcel", "build"], ["tsc", "build"], ["swc", "build"], ["turbo", "build"],
311
- // deploy / infra
312
- ["docker", "deploy"], ["kubectl", "deploy"], ["terraform", "deploy"], ["pulumi", "deploy"],
313
- ["ansible", "deploy"], ["helm", "deploy"], ["aws", "deploy"], ["gcloud", "deploy"], ["az", "deploy"],
314
- // databases
315
- ["psql", "database"], ["mysql", "database"], ["sqlite3", "database"],
316
- ["redis-cli", "database"], ["mongosh", "database"], ["mongo", "database"],
317
- // http
318
- ["curl", "http"], ["wget", "http"], ["httpie", "http"], ["http", "http"],
319
- ]);
320
-
321
- function deriveBashMetadata(input) {
322
- if (input?.tool_name !== "Bash") return null;
323
- const cmd = String(input?.tool_input?.command ?? "").trim();
324
- if (!cmd) return { command_type: "other", command_tool: "Bash" };
325
-
326
- const tokens = cmd.split(/\s+/);
327
- const command_tool = extractCommandTool(tokens);
328
- const command_type = classifyCommandType(tokens, command_tool);
329
- const exit_code = inferExitCode(input?.tool_response);
330
- return { command_type, command_tool, exit_code };
331
- }
332
-
333
- // Strip env-assign prefixes (`FOO=bar`), then strip runner shells,
334
- // then return the basename of the executable token.
335
- function extractCommandTool(tokens) {
336
- let i = 0;
337
- // Skip env assignments
338
- while (i < tokens.length && ENV_ASSIGN_RE.test(tokens[i])) i++;
339
- // Skip runner shells
340
- while (i < tokens.length && COMMAND_RUNNERS.has(tokens[i].toLowerCase())) {
341
- i++;
342
- // Skip subcommands like `pnpm dlx`, `pnpm exec`, `bun run`
343
- if (i < tokens.length && /^(dlx|exec|run|x)$/i.test(tokens[i])) i++;
344
- }
345
- if (i >= tokens.length) return tokens[0] || "Bash";
346
- const exe = tokens[i];
347
- // basename of path-like executables (`/usr/local/bin/foo` → "foo")
348
- const base = exe.split(/[/\\]/).pop() || "Bash";
349
- // Strip shell quoting if present
350
- return base.replace(/^['"]|['"]$/g, "");
351
- }
352
-
353
- // Type classification — priority order:
354
- // 1. Tool name implies type (curated CANONICAL_TOOLS map)
355
- // 2. Canonical verb at subcommand position (`npm test`, `cargo build`)
356
- // 3. Argument-shape heuristics (test/ dir, .test.ts suffix, --prod flag)
357
- // 4. Tool-level fallback (git → git, make → build)
358
- // 5. "other"
359
- function classifyCommandType(tokens, command_tool) {
360
- const toolLc = (command_tool || "").toLowerCase();
361
-
362
- // 1. Tool name itself names the type
363
- const fromTool = CANONICAL_TOOLS.get(toolLc);
364
- if (fromTool) return fromTool;
365
-
366
- // Skip env + runners to find subcommand position
367
- const lower = tokens.map((t) => t.toLowerCase());
368
- let start = 0;
369
- while (start < lower.length && ENV_ASSIGN_RE.test(tokens[start])) start++;
370
- while (start < lower.length && COMMAND_RUNNERS.has(lower[start])) {
371
- start++;
372
- if (start < lower.length && /^(dlx|exec|run|x)$/.test(lower[start])) start++;
373
- }
374
-
375
- // 2. Canonical verb scan within next 4 tokens
376
- const horizon = Math.min(lower.length, start + 4);
377
- for (let i = start; i < horizon; i++) {
378
- if (CANONICAL_VERBS.has(lower[i])) return lower[i];
379
- }
380
-
381
- // 3. Argument-shape heuristics
382
- const tail = tokens.slice(start).join(" ");
383
- if (/\btests?[/\\]|\bspec[/\\]|__tests__|\.(test|spec)\.[mc]?[jt]sx?\b|test_[\w-]+\.py\b|_test\.go\b/.test(tail)) return "test";
384
- if (/--(prod|production|release|optimize)\b/.test(tail)) return "build";
385
- if (/\bDockerfile\b|docker-compose/.test(tail)) return "deploy";
386
-
387
- // 4. Tool-level fallback for tools whose mere presence implies the type
388
- if (toolLc === "git") return "git";
389
- if (toolLc === "make" || toolLc === "ninja" || toolLc === "cmake") return "build";
390
-
391
- return "other";
392
- }
393
-
394
- // Exit code best-effort inference from tool_response. Hook stdin does
395
- // not carry the actual exit code on CC; we read the shape of the output
396
- // for signals. Engine treats exit_code as soft signal (Anomaly #3 — no
397
- // pattern in patterns.ts reads it today), so probabilistic stamps are
398
- // adequate. Captures named exit code when explicit.
399
- function inferExitCode(response) {
400
- const r = String(response ?? "");
401
- if (!r) return 0;
402
- // Explicit exit-code marker (some wrappers emit "exit status 137" etc.)
403
- const explicit = r.match(/\bexit (?:status|code)\s+(\d+)\b/i);
404
- if (explicit) return Number(explicit[1]);
405
- // "command not found" → POSIX standard 127
406
- if (/^bash:.*: (?:command not found|No such file)/m.test(r)) return 127;
407
- // Heuristic non-zero indicators (line-anchored to avoid false positives
408
- // inside narrative text from successful commands).
409
- if (/^(?:Error: |Traceback|FAIL\b|✗|✘)/m.test(r)) return 1;
410
- return 0;
411
- }
412
-
413
- // ── Latency timing — reads PreToolUse marker ────────────────────────────
414
- //
415
- // PreToolUse already writes `${tmpdir}/context-mode-latency-${sessionId}-
416
- // ${toolName}.txt` with the start timestamp (pretooluse.mjs:177). We
417
- // piggyback on that marker — read + compute delta, do NOT unlink (the
418
- // downstream slow-tool event emission in posttooluse.mjs:128-152 manages
419
- // the unlink lifecycle). Failure modes (missing marker, parse error,
420
- // negative delta, sanity-out-of-range) all return undefined — Zod's
421
- // optional handling drops the field silently. No NULL noise on the wire.
422
- function readLatencyMs(sessionId, toolName) {
423
- if (!sessionId || !toolName) return undefined;
424
- const markerPath = resolvePath(
425
- tmpdir(),
426
- `context-mode-latency-${sessionId}-${toolName}.txt`,
427
- );
428
- try {
429
- const start = parseInt(readFileSync(markerPath, "utf8").trim(), 10);
430
- if (!Number.isFinite(start) || start <= 0) return undefined;
431
- const delta = Date.now() - start;
432
- if (delta < 0 || delta > 24 * 3600 * 1000) return undefined;
433
- return delta;
434
- } catch {
435
- return undefined;
436
- }
437
- }
438
-
439
- // ── Duration bucket ──────────────────────────────────────────────────────
440
- //
441
- // Open-string label the platform Zod schema accepts (max 20 chars). Three
442
- // buckets cover the seed.ts shape: <5s | 5-30s | 30s+.
443
- function bucketizeDuration(ms) {
444
- if (typeof ms !== "number" || !Number.isFinite(ms) || ms < 0) return undefined;
445
- if (ms < 5_000) return "<5s";
446
- if (ms < 30_000) return "5-30s";
447
- return "30s+";
448
- }
@@ -1,32 +0,0 @@
1
- function a(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}var B=10;function h(t,r=4){return[...new Set(t.filter(o=>o.length>0))].slice(0,r).map(o=>o.length>80?o.slice(0,80):o)}function m(t,r){if(r.length===0)return"";let e=r.map(n=>`"${a(n)}"`).join(", ");return`
2
- For full details:
3
- ${a(t)}(
4
- queries: [${e}],
5
- source: "session-events"
6
- )`}function G(t,r){if(t.length===0)return"";let e=new Map;for(let f of t){let S=f.data,p=e.get(S);p||(p={ops:new Map},e.set(S,p));let d;f.type==="file_write"?d="write":f.type==="file_read"?d="read":f.type==="file_edit"?d="edit":d=f.type,p.ops.set(d,(p.ops.get(d)??0)+1)}let o=Array.from(e.entries()).slice(-B),c=[],i=[];for(let[f,{ops:S}]of o){let p=Array.from(S.entries()).map(([b,y])=>`${b}\xD7${y}`).join(", "),d=f.split("/").pop()??f;c.push(` ${a(d)} (${a(p)})`),i.push(`${d} ${Array.from(S.keys()).join(" ")}`)}let s=h(i);return[` <files count="${e.size}">`,...c,m(r,s)," </files>"].join(`
7
- `)}function J(t,r){if(t.length===0)return"";let e=[],n=[];for(let i of t)e.push(` ${a(i.data)}`),n.push(i.data);let o=h(n);return[` <errors count="${t.length}">`,...e,m(r,o)," </errors>"].join(`
8
- `)}function X(t,r){if(t.length===0)return"";let e=new Set,n=[],o=[];for(let s of t)e.has(s.data)||(e.add(s.data),n.push(` ${a(s.data)}`),o.push(s.data));if(n.length===0)return"";let c=h(o);return[` <decisions count="${n.length}">`,...n,m(r,c)," </decisions>"].join(`
9
- `)}function z(t,r){if(t.length===0)return"";let e=new Set,n=[],o=[];for(let s of t)e.has(s.data)||(e.add(s.data),s.type==="rule_content"?n.push(` ${a(s.data)}`):n.push(` ${a(s.data)}`),o.push(s.data));if(n.length===0)return"";let c=h(o);return[` <rules count="${n.length}">`,...n,m(r,c)," </rules>"].join(`
10
- `)}function P(t,r){if(t.length===0)return"";let e=[],n=[];for(let i of t)e.push(` ${a(i.data)}`),n.push(i.data);let o=h(n);return[` <git count="${t.length}">`,...e,m(r,o)," </git>"].join(`
11
- `)}function H(t){if(t.length===0)return"";let r=[],e={};for(let s of t)try{let u=JSON.parse(s.data);typeof u.subject=="string"?r.push(u.subject):typeof u.taskId=="string"&&typeof u.status=="string"&&(e[u.taskId]=u.status)}catch{}if(r.length===0)return"";let n=new Set(["completed","deleted","failed"]),o=Object.keys(e).sort((s,u)=>Number(s)-Number(u)),c=[];for(let s=0;s<r.length;s++){let u=o[s],f=u?e[u]??"pending":"pending";n.has(f)||c.push(r[s])}if(c.length===0)return"";let i=[];for(let s of c)i.push(` [pending] ${a(s)}`);return i.join(`
12
- `)}function K(t,r){let e=H(t);if(!e)return"";let n=[];for(let s of t)try{let u=JSON.parse(s.data);typeof u.subject=="string"&&n.push(u.subject)}catch{}let o=h(n);return[` <task_state count="${e.split(`
13
- `).length}">`,e,m(r,o)," </task_state>"].join(`
14
- `)}function Q(t,r,e){if(t.length===0&&r.length===0)return"";let n=[],o=[];if(t.length>0){let s=t[t.length-1];n.push(` cwd: ${a(s.data)}`),o.push("working directory")}for(let s of r)n.push(` ${a(s.data)}`),o.push(s.data);let c=h(o);return[" <environment>",...n,m(e,c)," </environment>"].join(`
15
- `)}function U(t,r){if(t.length===0)return"";let e=[],n=[];for(let i of t){let s=i.type==="subagent_completed"?"completed":i.type==="subagent_launched"?"launched":"unknown";e.push(` [${s}] ${a(i.data)}`),n.push(`subagent ${i.data}`)}let o=h(n);return[` <subagents count="${t.length}">`,...e,m(r,o)," </subagents>"].join(`
16
- `)}function V(t,r){if(t.length===0)return"";let e=new Map;for(let s of t){let u=s.data.split(":")[0].trim();e.set(u,(e.get(u)??0)+1)}let n=[],o=[];for(let[s,u]of e)n.push(` ${a(s)} (${u}\xD7)`),o.push(`skill ${s} invocation`);let c=h(o);return[` <skills count="${t.length}">`,...n,m(r,c)," </skills>"].join(`
17
- `)}function W(t,r){if(t.length===0)return"";let e=new Set,n=[],o=[];for(let s of t)e.has(s.data)||(e.add(s.data),n.push(` ${a(s.data)}`),o.push(s.data));if(n.length===0)return"";let c=h(o);return[` <roles count="${n.length}">`,...n,m(r,c)," </roles>"].join(`
18
- `)}function Y(t){if(t.length===0)return"";let r=t[t.length-1];return` <intent mode="${a(r.data)}"/>`}function Z(t){if(t.length===0)return"";let r=t[t.length-1];return[" <session_goal>"," The active objective for this session. Keep working toward it until it is met; do not ask the user to restate it.",` ${a(r.data)}`," </session_goal>"].join(`
19
- `)}var tt=3,nt=400;function et(t,r){let e=[...t];return e.length<=r?t:e.slice(0,r).join("")}function st(t){if(t.length===0)return"";let e=t.slice(-tt).map(n=>{let o=et(n.data??"",nt);return o?` <message>${a(o)}</message>`:""}).filter(Boolean);return e.length===0?"":[` <recent_user_messages count="${e.length}">`,...e," </recent_user_messages>"].join(`
20
- `)}function it(t,r){let e=r?.compactCount??1,n=r?.searchTool??"ctx_search",o=new Date().toISOString(),c=[],i=[],s=[],u=[],f=[],S=[],p=[],d=[],b=[],y=[],k=[],$=[],v=[],E=[];for(let g of t)switch(g.category){case"file":c.push(g);break;case"task":i.push(g);break;case"rule":s.push(g);break;case"decision":u.push(g);break;case"cwd":f.push(g);break;case"error":S.push(g);break;case"env":p.push(g);break;case"git":d.push(g);break;case"subagent":b.push(g);break;case"intent":y.push(g);break;case"goal":k.push(g);break;case"skill":$.push(g);break;case"role":v.push(g);break;case"user-prompt":E.push(g);break}let l=[];l.push(` <how_to_search>
21
- Each section below contains a summary of prior work.
22
- For FULL DETAILS, run the exact tool call shown under each section.
23
- Do NOT ask the user to re-explain prior work. Search first.
24
- Do NOT invent your own queries \u2014 use the ones provided.
25
- </how_to_search>`);let _=Z(k);_&&l.push(_);let w=G(c,n);w&&l.push(w);let j=J(S,n);j&&l.push(j);let q=X(u,n);q&&l.push(q);let T=z(s,n);T&&l.push(T);let L=P(d,n);L&&l.push(L);let M=K(i,n);M&&l.push(M);let C=Q(f,p,n);C&&l.push(C);let A=U(b,n);A&&l.push(A);let I=V($,n);I&&l.push(I);let N=W(v,n);N&&l.push(N);let O=Y(y);O&&l.push(O);let R=st(E);R&&l.push(R);let x=`<session_resume events="${t.length}" compact_count="${e}" generated_at="${o}">`,D="</session_resume>",F=l.join(`
26
-
27
- `);return F?`${x}
28
-
29
- ${F}
30
-
31
- ${D}`:`${x}
32
- ${D}`}export{it as buildResumeSnapshot,H as renderTaskState};