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,254 +0,0 @@
1
- /**
2
- * walkDirectory — bounded recursive directory walker for ctx_index (#687).
3
- *
4
- * Issue: ctx_index refused directory paths via the security gate at
5
- * src/store.ts:845 ("refusing to index <path>: not a regular file"). The gate
6
- * is a TOCTOU defense from #442 round-3 and MUST be preserved — directory
7
- * support is layered as a separate concern here. Each file produced by
8
- * walkDirectory is then read via the existing per-file
9
- * `openSync + fstatSync.isFile()` invariant in `ContentStore.index()`.
10
- *
11
- * Reported by @matiasduartee across 4 clients × Windows 11.
12
- * https://github.com/anthropic-experimental/context-mode/issues/687
13
- *
14
- * Design constraints:
15
- * - No new dependencies (avoid the `ignore` package — issue #687 Diagnose).
16
- * - Cross-OS: path.sep / path.join everywhere, never raw "/" string ops.
17
- * - Symlink cycle detection via a resolved-path Set.
18
- * - Symlink-escape rejection: refuse to follow symlinks that resolve outside
19
- * the rootPath (defense-in-depth alongside per-file checkFilePathDenyPolicy).
20
- * - FTS5-blowup guard: hard cap maxFiles (default 200, per Architect).
21
- */
22
- import { readdirSync, statSync, lstatSync, realpathSync, existsSync, readFileSync, } from "node:fs";
23
- import { join, extname, relative, sep, resolve } from "node:path";
24
- const DEFAULT_EXCLUDES = [
25
- "node_modules",
26
- ".git",
27
- "dist",
28
- "build",
29
- ".next",
30
- "coverage",
31
- ".venv",
32
- "__pycache__",
33
- ".DS_Store",
34
- ];
35
- const DEFAULT_EXTENSIONS = [
36
- ".md",
37
- ".mdx",
38
- ".txt",
39
- ".json",
40
- ".yaml",
41
- ".yml",
42
- ".ts",
43
- ".tsx",
44
- ".js",
45
- ".jsx",
46
- ".py",
47
- ".rs",
48
- ".go",
49
- ".sh",
50
- ];
51
- const DEFAULT_MAX_DEPTH = 5;
52
- const DEFAULT_MAX_FILES = 200;
53
- /**
54
- * Convert a simple glob pattern (`*`, `**`, `?`) to a RegExp. Anchors at
55
- * boundaries so `node_modules` matches `node_modules` AND `node_modules/pkg`.
56
- * Patterns are matched against POSIX-style relative paths (forward slashes)
57
- * to give consistent behavior across macOS / Windows.
58
- */
59
- function globToRegExp(pattern) {
60
- // Escape regex metachars except glob ones.
61
- let re = "";
62
- for (let i = 0; i < pattern.length; i++) {
63
- const c = pattern[i];
64
- if (c === "*") {
65
- if (pattern[i + 1] === "*") {
66
- re += ".*";
67
- i++;
68
- }
69
- else {
70
- re += "[^/]*";
71
- }
72
- }
73
- else if (c === "?") {
74
- re += "[^/]";
75
- }
76
- else if ("\\^$.|+()[]{}".includes(c)) {
77
- re += "\\" + c;
78
- }
79
- else {
80
- re += c;
81
- }
82
- }
83
- return new RegExp(`^${re}$`);
84
- }
85
- /** Match a posix-style relative path against any of the patterns. */
86
- function matchesAny(relPosix, patterns) {
87
- if (patterns.length === 0)
88
- return false;
89
- const basename = relPosix.split("/").pop() ?? relPosix;
90
- for (const p of patterns) {
91
- // Bare names match basename OR any path segment.
92
- if (!p.includes("/") && !p.includes("*")) {
93
- if (basename === p)
94
- return true;
95
- if (relPosix.split("/").includes(p))
96
- return true;
97
- continue;
98
- }
99
- const re = globToRegExp(p);
100
- if (re.test(relPosix))
101
- return true;
102
- if (re.test(basename))
103
- return true;
104
- }
105
- return false;
106
- }
107
- /**
108
- * Parse a .gitignore file into a list of patterns. Comments and blank lines
109
- * are stripped. Negation (`!`) is not supported — kept conservative.
110
- */
111
- function parseGitignore(rootPath) {
112
- const giPath = join(rootPath, ".gitignore");
113
- if (!existsSync(giPath))
114
- return [];
115
- try {
116
- const text = readFileSync(giPath, "utf-8");
117
- return text
118
- .split(/\r?\n/)
119
- .map(l => l.trim())
120
- .filter(l => l.length > 0 && !l.startsWith("#") && !l.startsWith("!"))
121
- .map(l => l.replace(/^\//, "").replace(/\/$/, ""));
122
- }
123
- catch {
124
- return [];
125
- }
126
- }
127
- /**
128
- * Convert an absolute path under rootPath to a POSIX-style relative path
129
- * so glob matching is identical across macOS/Linux/Windows.
130
- */
131
- function toPosixRel(rootPath, absPath) {
132
- const rel = relative(rootPath, absPath);
133
- return rel.split(sep).join("/");
134
- }
135
- /**
136
- * Walk `rootPath` recursively under the given bounds and return absolute file
137
- * paths matching the filters. Pure synchronous traversal — no allocations
138
- * beyond the result array. Symlink cycles are detected via a resolved-path
139
- * Set; symlink escapes (resolving outside rootPath) are silently skipped.
140
- */
141
- export function walkDirectory(rootPath, opts = {}) {
142
- return walkDirectoryDetailed(rootPath, opts).files;
143
- }
144
- /**
145
- * Same as walkDirectory but returns capped + totalSeen so callers can surface
146
- * a "capped at N files" notice in their response.
147
- */
148
- export function walkDirectoryDetailed(rootPath, opts = {}) {
149
- const { include, exclude, maxDepth = DEFAULT_MAX_DEPTH, maxFiles = DEFAULT_MAX_FILES, extensions, respectGitignore = true, followSymlinks = false, } = opts;
150
- // Normalize rootPath to its real path so symlink-escape detection is sound.
151
- let rootReal;
152
- try {
153
- rootReal = realpathSync(rootPath);
154
- }
155
- catch {
156
- return { files: [], capped: false, totalSeen: 0 };
157
- }
158
- const exts = (extensions && extensions.length > 0 ? extensions : DEFAULT_EXTENSIONS)
159
- .map(e => (e.startsWith(".") ? e : "." + e).toLowerCase());
160
- const excludes = [
161
- ...DEFAULT_EXCLUDES,
162
- ...(exclude ?? []),
163
- ...(respectGitignore ? parseGitignore(rootReal) : []),
164
- ];
165
- const includes = include ?? [];
166
- const out = [];
167
- const visited = new Set([rootReal]);
168
- let totalSeen = 0;
169
- let capped = false;
170
- function walk(absDir, depth) {
171
- if (capped)
172
- return;
173
- if (depth > maxDepth)
174
- return;
175
- let entries;
176
- try {
177
- entries = readdirSync(absDir, { withFileTypes: true });
178
- }
179
- catch {
180
- return; // unreadable directory — skip silently
181
- }
182
- for (const ent of entries) {
183
- if (capped)
184
- return;
185
- const absChild = join(absDir, ent.name);
186
- const relPosix = toPosixRel(rootReal, absChild);
187
- // Exclude check applies to both files and dirs — early prune.
188
- if (matchesAny(relPosix, excludes))
189
- continue;
190
- // Include filter applies to files only — see below.
191
- // Resolve symlinks once; reject escapes; track for cycle detection.
192
- let isDirChild = ent.isDirectory();
193
- let isFileChild = ent.isFile();
194
- let isSymlink = false;
195
- try {
196
- const lst = lstatSync(absChild);
197
- isSymlink = lst.isSymbolicLink();
198
- }
199
- catch {
200
- continue;
201
- }
202
- if (isSymlink) {
203
- if (!followSymlinks)
204
- continue;
205
- let resolved;
206
- try {
207
- resolved = realpathSync(absChild);
208
- }
209
- catch {
210
- continue; // dangling
211
- }
212
- // Symlink-escape: refuse to follow if the resolved target leaves rootReal.
213
- const escapeRel = relative(rootReal, resolved);
214
- if (escapeRel.startsWith("..") || resolve(escapeRel) === resolved) {
215
- // resolve(absolute) === absolute → target is absolute outside root
216
- if (escapeRel.startsWith(".."))
217
- continue;
218
- }
219
- if (visited.has(resolved))
220
- continue;
221
- visited.add(resolved);
222
- try {
223
- const st = statSync(resolved);
224
- isDirChild = st.isDirectory();
225
- isFileChild = st.isFile();
226
- }
227
- catch {
228
- continue;
229
- }
230
- }
231
- if (isDirChild) {
232
- walk(absChild, depth + 1);
233
- continue;
234
- }
235
- if (!isFileChild)
236
- continue;
237
- // Extension filter.
238
- const ext = extname(absChild).toLowerCase();
239
- if (!exts.includes(ext))
240
- continue;
241
- // Include filter (if any): file must match at least one include pattern.
242
- if (includes.length > 0 && !matchesAny(relPosix, includes))
243
- continue;
244
- totalSeen++;
245
- if (out.length >= maxFiles) {
246
- capped = true;
247
- return;
248
- }
249
- out.push(absChild);
250
- }
251
- }
252
- walk(rootReal, 0);
253
- return { files: out, capped, totalSeen };
254
- }
package/build/store.d.ts DELETED
@@ -1,147 +0,0 @@
1
- /**
2
- * ContentStore — FTS5 BM25-based knowledge base for context-mode.
3
- *
4
- * Chunks markdown content by headings (keeping code blocks intact),
5
- * stores in SQLite FTS5, and retrieves via BM25-ranked search.
6
- *
7
- * Use for documentation, API references, and any content where
8
- * you need EXACT text later — not summaries.
9
- */
10
- import { type WalkOptions } from "./store-directory.js";
11
- type SourceMatchMode = "like" | "exact";
12
- import type { IndexResult, SearchResult, StoreStats } from "./types.js";
13
- export type { IndexResult, SearchResult, StoreStats } from "./types.js";
14
- export declare function sanitizeQuery(query: string, mode?: "AND" | "OR"): string;
15
- export declare function sanitizeTrigramQuery(query: string, mode?: "AND" | "OR"): string;
16
- /**
17
- * Remove stale DB files from previous sessions whose processes no longer exist.
18
- */
19
- export declare function cleanupStaleDBs(): number;
20
- /**
21
- * Clean up stale per-project content store DBs older than maxAgeDays.
22
- * Scans the given directory for *.db files and checks mtime.
23
- * Also detects zombie processes holding WAL locks — if a WAL file exists
24
- * but the owning PID is dead, the DB files are cleaned up regardless of age.
25
- */
26
- export declare function cleanupStaleContentDBs(contentDir: string, maxAgeDays: number): number;
27
- export declare class ContentStore {
28
- #private;
29
- static readonly OPTIMIZE_EVERY = 50;
30
- static readonly FUZZY_CACHE_SIZE = 256;
31
- constructor(dbPath?: string);
32
- /** Delete this session's DB files. Call on process exit. */
33
- cleanup(): void;
34
- /**
35
- * Register a deny-policy checker. When set, #refreshStaleSources
36
- * calls it before re-reading any file_path during auto-refresh.
37
- * Returning `true` causes the source to be skipped (kept in cache,
38
- * not re-indexed). server.ts wires this to the Read deny patterns.
39
- */
40
- setDenyChecker(fn: ((filePath: string) => boolean) | undefined): void;
41
- index(options: {
42
- content?: string;
43
- path?: string;
44
- source?: string;
45
- /**
46
- * Optional FK metadata recorded on each indexed chunk so per-session
47
- * honest-savings stats can join chunks → session_events. When omitted,
48
- * chunks fall back to empty-string columns (legacy behaviour).
49
- */
50
- attribution?: {
51
- sessionId?: string;
52
- eventId?: string;
53
- };
54
- }): IndexResult;
55
- /**
56
- * Index every file under a directory by walking it with `walkDirectory` and
57
- * delegating each discovered file to `this.index({ path })`. The per-file
58
- * `openSync + fstatSync.isFile()` security gate at line ~845 stays active
59
- * for every file — directory support never bypasses the TOCTOU defense
60
- * from #442 round-3.
61
- *
62
- * Reported by @matiasduartee in #687.
63
- */
64
- indexDirectory(opts: {
65
- path: string;
66
- source?: string;
67
- attribution?: {
68
- sessionId?: string;
69
- eventId?: string;
70
- };
71
- /** Optional per-file deny check — runs INSIDE the walk loop so a denied
72
- * file does not even open a fd. Returns true to deny. */
73
- perFileDeny?: (absPath: string) => boolean;
74
- } & WalkOptions): {
75
- filesIndexed: number;
76
- totalChunks: number;
77
- capped: boolean;
78
- totalSeen: number;
79
- denied: number;
80
- failed: number;
81
- label: string;
82
- };
83
- /**
84
- * Index plain-text output (logs, build output, test results) by splitting
85
- * into fixed-size line groups. Unlike markdown indexing, this does not
86
- * look for headings — it chunks by line count with overlap.
87
- */
88
- indexPlainText(content: string, source: string, linesPerChunk?: number, attribution?: {
89
- sessionId?: string;
90
- eventId?: string;
91
- }, maxChunkBytes?: number): IndexResult;
92
- /**
93
- * Index JSON content by walking the object tree and using key paths
94
- * as chunk titles (analogous to heading hierarchy in markdown). Objects
95
- * recurse by key; arrays batch items by size.
96
- *
97
- * Falls back to `indexPlainText` if the content is not valid JSON.
98
- */
99
- indexJSON(content: string, source: string, maxChunkBytes?: number, attribution?: {
100
- sessionId?: string;
101
- eventId?: string;
102
- }): IndexResult;
103
- search(query: string, limit?: number, source?: string, mode?: "AND" | "OR", contentType?: "code" | "prose", sourceMatchMode?: SourceMatchMode): SearchResult[];
104
- searchTrigram(query: string, limit?: number, source?: string, mode?: "AND" | "OR", contentType?: "code" | "prose", sourceMatchMode?: SourceMatchMode): SearchResult[];
105
- fuzzyCorrect(query: string): string | null;
106
- searchWithFallback(query: string, limit?: number, source?: string, contentType?: "code" | "prose", sourceMatchMode?: SourceMatchMode, sessionIdAllowSet?: Set<string>): SearchResult[];
107
- /** Number of sources auto-refreshed in the last searchWithFallback call. */
108
- lastRefreshCount: number;
109
- getSourceMeta(label: string): {
110
- label: string;
111
- chunkCount: number;
112
- codeChunkCount: number;
113
- indexedAt: string;
114
- filePath: string | null;
115
- contentHash: string | null;
116
- } | null;
117
- listSources(): Array<{
118
- label: string;
119
- chunkCount: number;
120
- }>;
121
- /**
122
- * Aggregate snapshot of the persistent content store. Returns total
123
- * chunk count, source count, and the most recent indexed_at timestamp.
124
- * Used by ctx_stats so callers can see observability state in the same
125
- * round trip instead of inferring it from snapshot diffs.
126
- */
127
- getIndexState(): {
128
- totalChunks: number;
129
- totalSources: number;
130
- lastIndexedAt?: string;
131
- };
132
- /**
133
- * Get all chunks for a given source by ID — bypasses FTS5 MATCH entirely.
134
- * Use this for inventory/listing where you need all sections, not search.
135
- */
136
- getChunksBySource(sourceId: number): SearchResult[];
137
- getDistinctiveTerms(sourceId: number, maxTerms?: number): string[];
138
- getStats(): StoreStats;
139
- /**
140
- * Delete sources (and their chunks) older than maxAgeDays.
141
- * Returns count of deleted sources.
142
- */
143
- cleanupStaleSources(maxAgeDays: number): number;
144
- /** Get DB file size in bytes. */
145
- getDBSizeBytes(): number;
146
- close(): void;
147
- }