@cjhyy/code-shell-core 0.5.0-rc.0

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 (484) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +162 -0
  3. package/dist/agent/coordinator.d.ts +49 -0
  4. package/dist/agent/coordinator.js +77 -0
  5. package/dist/arena/arena.d.ts +43 -0
  6. package/dist/arena/arena.js +334 -0
  7. package/dist/arena/context/context-tools.d.ts +16 -0
  8. package/dist/arena/context/context-tools.js +231 -0
  9. package/dist/arena/detect-mode.d.ts +20 -0
  10. package/dist/arena/detect-mode.js +78 -0
  11. package/dist/arena/digest-builder.d.ts +25 -0
  12. package/dist/arena/digest-builder.js +120 -0
  13. package/dist/arena/index.d.ts +29 -0
  14. package/dist/arena/index.js +29 -0
  15. package/dist/arena/iterate/convergence.d.ts +25 -0
  16. package/dist/arena/iterate/convergence.js +103 -0
  17. package/dist/arena/iterate/formats/index.d.ts +22 -0
  18. package/dist/arena/iterate/formats/index.js +283 -0
  19. package/dist/arena/iterate/index.d.ts +11 -0
  20. package/dist/arena/iterate/index.js +9 -0
  21. package/dist/arena/iterate/iterative-arena.d.ts +23 -0
  22. package/dist/arena/iterate/iterative-arena.js +237 -0
  23. package/dist/arena/iterate/parse.d.ts +42 -0
  24. package/dist/arena/iterate/parse.js +123 -0
  25. package/dist/arena/iterate/phases/argue.d.ts +22 -0
  26. package/dist/arena/iterate/phases/argue.js +159 -0
  27. package/dist/arena/iterate/phases/revise.d.ts +16 -0
  28. package/dist/arena/iterate/phases/revise.js +62 -0
  29. package/dist/arena/iterate/phases/tournament.d.ts +34 -0
  30. package/dist/arena/iterate/phases/tournament.js +113 -0
  31. package/dist/arena/iterate/tools/web-tools.d.ts +13 -0
  32. package/dist/arena/iterate/tools/web-tools.js +54 -0
  33. package/dist/arena/iterate/types.d.ts +152 -0
  34. package/dist/arena/iterate/types.js +8 -0
  35. package/dist/arena/ledger.d.ts +47 -0
  36. package/dist/arena/ledger.js +151 -0
  37. package/dist/arena/lenses/architecture.d.ts +5 -0
  38. package/dist/arena/lenses/architecture.js +22 -0
  39. package/dist/arena/lenses/engineering.d.ts +5 -0
  40. package/dist/arena/lenses/engineering.js +22 -0
  41. package/dist/arena/lenses/general.d.ts +5 -0
  42. package/dist/arena/lenses/general.js +20 -0
  43. package/dist/arena/lenses/index.d.ts +16 -0
  44. package/dist/arena/lenses/index.js +47 -0
  45. package/dist/arena/lenses/product.d.ts +5 -0
  46. package/dist/arena/lenses/product.js +22 -0
  47. package/dist/arena/model-presets.d.ts +23 -0
  48. package/dist/arena/model-presets.js +44 -0
  49. package/dist/arena/phases/adjudication.d.ts +24 -0
  50. package/dist/arena/phases/adjudication.js +144 -0
  51. package/dist/arena/phases/build-consensus.d.ts +29 -0
  52. package/dist/arena/phases/build-consensus.js +86 -0
  53. package/dist/arena/phases/claim-registry.d.ts +26 -0
  54. package/dist/arena/phases/claim-registry.js +60 -0
  55. package/dist/arena/phases/cross-review.d.ts +45 -0
  56. package/dist/arena/phases/cross-review.js +224 -0
  57. package/dist/arena/phases/debate-rounds.d.ts +27 -0
  58. package/dist/arena/phases/debate-rounds.js +162 -0
  59. package/dist/arena/phases/participant-research.d.ts +38 -0
  60. package/dist/arena/phases/participant-research.js +317 -0
  61. package/dist/arena/phases/planning-detail-expansion.d.ts +38 -0
  62. package/dist/arena/phases/planning-detail-expansion.js +121 -0
  63. package/dist/arena/planner.d.ts +27 -0
  64. package/dist/arena/planner.js +312 -0
  65. package/dist/arena/providers/docs.d.ts +6 -0
  66. package/dist/arena/providers/docs.js +108 -0
  67. package/dist/arena/providers/git.d.ts +8 -0
  68. package/dist/arena/providers/git.js +174 -0
  69. package/dist/arena/providers/index.d.ts +32 -0
  70. package/dist/arena/providers/index.js +132 -0
  71. package/dist/arena/providers/none.d.ts +7 -0
  72. package/dist/arena/providers/none.js +11 -0
  73. package/dist/arena/providers/repo.d.ts +6 -0
  74. package/dist/arena/providers/repo.js +255 -0
  75. package/dist/arena/render/session.d.ts +17 -0
  76. package/dist/arena/render/session.js +190 -0
  77. package/dist/arena/render/terminal.d.ts +34 -0
  78. package/dist/arena/render/terminal.js +286 -0
  79. package/dist/arena/strategies/discussion.d.ts +25 -0
  80. package/dist/arena/strategies/discussion.js +143 -0
  81. package/dist/arena/strategies/index.d.ts +15 -0
  82. package/dist/arena/strategies/index.js +28 -0
  83. package/dist/arena/strategies/language-wrapper.d.ts +17 -0
  84. package/dist/arena/strategies/language-wrapper.js +102 -0
  85. package/dist/arena/strategies/lens-wrapper.d.ts +16 -0
  86. package/dist/arena/strategies/lens-wrapper.js +236 -0
  87. package/dist/arena/strategies/planning.d.ts +30 -0
  88. package/dist/arena/strategies/planning.js +225 -0
  89. package/dist/arena/strategies/review.d.ts +26 -0
  90. package/dist/arena/strategies/review.js +168 -0
  91. package/dist/arena/strategies/utils.d.ts +39 -0
  92. package/dist/arena/strategies/utils.js +647 -0
  93. package/dist/arena/tools/selector.d.ts +17 -0
  94. package/dist/arena/tools/selector.js +61 -0
  95. package/dist/arena/transitions.d.ts +48 -0
  96. package/dist/arena/transitions.js +92 -0
  97. package/dist/arena/types.d.ts +508 -0
  98. package/dist/arena/types.js +27 -0
  99. package/dist/cli/agent-server-stdio.d.ts +32 -0
  100. package/dist/cli/agent-server-stdio.js +116 -0
  101. package/dist/colorizer.d.ts +23 -0
  102. package/dist/colorizer.js +12 -0
  103. package/dist/context/compaction.d.ts +116 -0
  104. package/dist/context/compaction.js +534 -0
  105. package/dist/context/manager.d.ts +145 -0
  106. package/dist/context/manager.js +423 -0
  107. package/dist/context/token-counter.d.ts +27 -0
  108. package/dist/context/token-counter.js +91 -0
  109. package/dist/context/tool-result-storage.d.ts +96 -0
  110. package/dist/context/tool-result-storage.js +296 -0
  111. package/dist/cost-tracker.d.ts +64 -0
  112. package/dist/cost-tracker.js +314 -0
  113. package/dist/cron/scheduler.d.ts +34 -0
  114. package/dist/cron/scheduler.js +115 -0
  115. package/dist/data/deepseek-models.json +46 -0
  116. package/dist/data/gemini-models.json +67 -0
  117. package/dist/data/openai-models.json +175 -0
  118. package/dist/data/openrouter-models.d.ts +35 -0
  119. package/dist/data/openrouter-models.js +36 -0
  120. package/dist/data/openrouter-models.json +4626 -0
  121. package/dist/data/openrouter-sync.d.ts +16 -0
  122. package/dist/data/openrouter-sync.js +53 -0
  123. package/dist/data/static-catalogs.d.ts +25 -0
  124. package/dist/data/static-catalogs.js +26 -0
  125. package/dist/data/zai-models.json +56 -0
  126. package/dist/engine/cost-store.d.ts +22 -0
  127. package/dist/engine/cost-store.js +15 -0
  128. package/dist/engine/engine.d.ts +295 -0
  129. package/dist/engine/engine.js +1467 -0
  130. package/dist/engine/model-facade.d.ts +24 -0
  131. package/dist/engine/model-facade.js +194 -0
  132. package/dist/engine/parse-task.d.ts +59 -0
  133. package/dist/engine/parse-task.js +135 -0
  134. package/dist/engine/patch-orphaned-tools.d.ts +52 -0
  135. package/dist/engine/patch-orphaned-tools.js +95 -0
  136. package/dist/engine/query.d.ts +50 -0
  137. package/dist/engine/query.js +107 -0
  138. package/dist/engine/runtime.d.ts +50 -0
  139. package/dist/engine/runtime.js +59 -0
  140. package/dist/engine/streaming-tool-queue.d.ts +34 -0
  141. package/dist/engine/streaming-tool-queue.js +61 -0
  142. package/dist/engine/token-budget.d.ts +22 -0
  143. package/dist/engine/token-budget.js +40 -0
  144. package/dist/engine/tool-summary.d.ts +13 -0
  145. package/dist/engine/tool-summary.js +35 -0
  146. package/dist/engine/turn-loop.d.ts +122 -0
  147. package/dist/engine/turn-loop.js +602 -0
  148. package/dist/engine/turn-state.d.ts +20 -0
  149. package/dist/engine/turn-state.js +17 -0
  150. package/dist/exceptions.d.ts +61 -0
  151. package/dist/exceptions.js +116 -0
  152. package/dist/git/utils.d.ts +35 -0
  153. package/dist/git/utils.js +98 -0
  154. package/dist/git/worktree.d.ts +36 -0
  155. package/dist/git/worktree.js +139 -0
  156. package/dist/hooks/events.d.ts +114 -0
  157. package/dist/hooks/events.js +4 -0
  158. package/dist/hooks/inject.d.ts +19 -0
  159. package/dist/hooks/inject.js +29 -0
  160. package/dist/hooks/registry.d.ts +15 -0
  161. package/dist/hooks/registry.js +84 -0
  162. package/dist/hooks/shell-runner.d.ts +45 -0
  163. package/dist/hooks/shell-runner.js +173 -0
  164. package/dist/index.d.ts +117 -0
  165. package/dist/index.js +145 -0
  166. package/dist/llm/api-key-sanitize.d.ts +22 -0
  167. package/dist/llm/api-key-sanitize.js +81 -0
  168. package/dist/llm/capabilities/index.d.ts +20 -0
  169. package/dist/llm/capabilities/index.js +39 -0
  170. package/dist/llm/capabilities/rules.d.ts +26 -0
  171. package/dist/llm/capabilities/rules.js +215 -0
  172. package/dist/llm/capabilities/types.d.ts +114 -0
  173. package/dist/llm/capabilities/types.js +24 -0
  174. package/dist/llm/client-base.d.ts +29 -0
  175. package/dist/llm/client-base.js +137 -0
  176. package/dist/llm/client-factory.d.ts +10 -0
  177. package/dist/llm/client-factory.js +29 -0
  178. package/dist/llm/model-cache.d.ts +21 -0
  179. package/dist/llm/model-cache.js +46 -0
  180. package/dist/llm/model-fetcher.d.ts +29 -0
  181. package/dist/llm/model-fetcher.js +282 -0
  182. package/dist/llm/model-pool.d.ts +95 -0
  183. package/dist/llm/model-pool.js +246 -0
  184. package/dist/llm/provider-catalog.d.ts +32 -0
  185. package/dist/llm/provider-catalog.js +50 -0
  186. package/dist/llm/provider-kinds.d.ts +21 -0
  187. package/dist/llm/provider-kinds.js +132 -0
  188. package/dist/llm/providers/anthropic.d.ts +19 -0
  189. package/dist/llm/providers/anthropic.js +267 -0
  190. package/dist/llm/providers/openai.d.ts +64 -0
  191. package/dist/llm/providers/openai.js +606 -0
  192. package/dist/llm/retry.d.ts +12 -0
  193. package/dist/llm/retry.js +17 -0
  194. package/dist/llm/stream-watchdog.d.ts +42 -0
  195. package/dist/llm/stream-watchdog.js +70 -0
  196. package/dist/llm/token-counter.d.ts +17 -0
  197. package/dist/llm/token-counter.js +36 -0
  198. package/dist/llm/types.d.ts +37 -0
  199. package/dist/llm/types.js +4 -0
  200. package/dist/logging/logger.d.ts +109 -0
  201. package/dist/logging/logger.js +390 -0
  202. package/dist/logging/sanitize-messages.d.ts +42 -0
  203. package/dist/logging/sanitize-messages.js +150 -0
  204. package/dist/logging/session-recorder.d.ts +90 -0
  205. package/dist/logging/session-recorder.js +304 -0
  206. package/dist/lsp/client.d.ts +41 -0
  207. package/dist/lsp/client.js +166 -0
  208. package/dist/lsp/manager.d.ts +40 -0
  209. package/dist/lsp/manager.js +124 -0
  210. package/dist/lsp/servers.d.ts +16 -0
  211. package/dist/lsp/servers.js +60 -0
  212. package/dist/migrate-models.d.ts +45 -0
  213. package/dist/migrate-models.js +179 -0
  214. package/dist/onboarding.d.ts +189 -0
  215. package/dist/onboarding.js +625 -0
  216. package/dist/plugins/gitOps.d.ts +32 -0
  217. package/dist/plugins/gitOps.js +62 -0
  218. package/dist/plugins/installedPlugins.d.ts +15 -0
  219. package/dist/plugins/installedPlugins.js +56 -0
  220. package/dist/plugins/knownMarketplaces.d.ts +10 -0
  221. package/dist/plugins/knownMarketplaces.js +46 -0
  222. package/dist/plugins/loadPluginHooks.d.ts +52 -0
  223. package/dist/plugins/loadPluginHooks.js +162 -0
  224. package/dist/plugins/marketplaceManager.d.ts +49 -0
  225. package/dist/plugins/marketplaceManager.js +142 -0
  226. package/dist/plugins/parseMarketplaceInput.d.ts +16 -0
  227. package/dist/plugins/parseMarketplaceInput.js +73 -0
  228. package/dist/plugins/pluginCommandHook.d.ts +54 -0
  229. package/dist/plugins/pluginCommandHook.js +180 -0
  230. package/dist/plugins/pluginCommandsLoader.d.ts +25 -0
  231. package/dist/plugins/pluginCommandsLoader.js +114 -0
  232. package/dist/plugins/pluginInstaller.d.ts +36 -0
  233. package/dist/plugins/pluginInstaller.js +228 -0
  234. package/dist/plugins/schemas.d.ts +9 -0
  235. package/dist/plugins/schemas.js +136 -0
  236. package/dist/plugins/types.d.ts +75 -0
  237. package/dist/plugins/types.js +7 -0
  238. package/dist/plugins/varRewrite.d.ts +42 -0
  239. package/dist/plugins/varRewrite.js +129 -0
  240. package/dist/preset/index.d.ts +60 -0
  241. package/dist/preset/index.js +159 -0
  242. package/dist/product/define.d.ts +60 -0
  243. package/dist/product/define.js +123 -0
  244. package/dist/product/index.d.ts +5 -0
  245. package/dist/product/index.js +4 -0
  246. package/dist/product/types.d.ts +111 -0
  247. package/dist/product/types.js +21 -0
  248. package/dist/prompt/composer.d.ts +49 -0
  249. package/dist/prompt/composer.js +168 -0
  250. package/dist/prompt/instruction-scanner.d.ts +54 -0
  251. package/dist/prompt/instruction-scanner.js +187 -0
  252. package/dist/prompt/section-cache.d.ts +15 -0
  253. package/dist/prompt/section-cache.js +31 -0
  254. package/dist/prompt/section-loader.d.ts +26 -0
  255. package/dist/prompt/section-loader.js +53 -0
  256. package/dist/prompt/sections/base.md +35 -0
  257. package/dist/prompt/sections/coding.md +31 -0
  258. package/dist/prompt/sections/orchestration.md +16 -0
  259. package/dist/prompt/sections/tone.md +9 -0
  260. package/dist/protocol/chat-session-manager.d.ts +33 -0
  261. package/dist/protocol/chat-session-manager.js +65 -0
  262. package/dist/protocol/chat-session.d.ts +49 -0
  263. package/dist/protocol/chat-session.js +86 -0
  264. package/dist/protocol/client.d.ts +104 -0
  265. package/dist/protocol/client.js +260 -0
  266. package/dist/protocol/factories.d.ts +93 -0
  267. package/dist/protocol/factories.js +64 -0
  268. package/dist/protocol/helpers.d.ts +42 -0
  269. package/dist/protocol/helpers.js +55 -0
  270. package/dist/protocol/index.d.ts +4 -0
  271. package/dist/protocol/index.js +4 -0
  272. package/dist/protocol/server.d.ts +80 -0
  273. package/dist/protocol/server.js +855 -0
  274. package/dist/protocol/transport.d.ts +37 -0
  275. package/dist/protocol/transport.js +85 -0
  276. package/dist/protocol/types.d.ts +221 -0
  277. package/dist/protocol/types.js +61 -0
  278. package/dist/remote/bridge.d.ts +37 -0
  279. package/dist/remote/bridge.js +103 -0
  280. package/dist/run/ArtifactTracker.d.ts +38 -0
  281. package/dist/run/ArtifactTracker.js +132 -0
  282. package/dist/run/CheckpointWriter.d.ts +53 -0
  283. package/dist/run/CheckpointWriter.js +135 -0
  284. package/dist/run/EngineRunner.d.ts +72 -0
  285. package/dist/run/EngineRunner.js +119 -0
  286. package/dist/run/Evaluator.d.ts +56 -0
  287. package/dist/run/Evaluator.js +62 -0
  288. package/dist/run/FileRunStore.d.ts +39 -0
  289. package/dist/run/FileRunStore.js +176 -0
  290. package/dist/run/Heartbeat.d.ts +54 -0
  291. package/dist/run/Heartbeat.js +123 -0
  292. package/dist/run/RunApprovalBackend.d.ts +53 -0
  293. package/dist/run/RunApprovalBackend.js +85 -0
  294. package/dist/run/RunLock.d.ts +40 -0
  295. package/dist/run/RunLock.js +98 -0
  296. package/dist/run/RunManager.d.ts +82 -0
  297. package/dist/run/RunManager.js +587 -0
  298. package/dist/run/RunQueue.d.ts +27 -0
  299. package/dist/run/RunQueue.js +73 -0
  300. package/dist/run/RunStore.d.ts +25 -0
  301. package/dist/run/RunStore.js +9 -0
  302. package/dist/run/factory.d.ts +63 -0
  303. package/dist/run/factory.js +51 -0
  304. package/dist/run/index.d.ts +17 -0
  305. package/dist/run/index.js +23 -0
  306. package/dist/run/types.d.ts +136 -0
  307. package/dist/run/types.js +28 -0
  308. package/dist/runtime/safe-spawn.d.ts +118 -0
  309. package/dist/runtime/safe-spawn.js +268 -0
  310. package/dist/services/analytics.d.ts +29 -0
  311. package/dist/services/analytics.js +84 -0
  312. package/dist/services/auto-dream.d.ts +49 -0
  313. package/dist/services/auto-dream.js +124 -0
  314. package/dist/services/diagnostics.d.ts +41 -0
  315. package/dist/services/diagnostics.js +99 -0
  316. package/dist/services/extract-memories.d.ts +31 -0
  317. package/dist/services/extract-memories.js +71 -0
  318. package/dist/services/index.d.ts +11 -0
  319. package/dist/services/index.js +17 -0
  320. package/dist/services/memory-orchestrator.d.ts +60 -0
  321. package/dist/services/memory-orchestrator.js +133 -0
  322. package/dist/services/notifier.d.ts +25 -0
  323. package/dist/services/notifier.js +69 -0
  324. package/dist/services/oauth.d.ts +27 -0
  325. package/dist/services/oauth.js +153 -0
  326. package/dist/services/session-memory.d.ts +37 -0
  327. package/dist/services/session-memory.js +81 -0
  328. package/dist/session/file-history.d.ts +41 -0
  329. package/dist/session/file-history.js +115 -0
  330. package/dist/session/memory.d.ts +104 -0
  331. package/dist/session/memory.js +310 -0
  332. package/dist/session/session-manager.d.ts +41 -0
  333. package/dist/session/session-manager.js +261 -0
  334. package/dist/session/transcript.d.ts +39 -0
  335. package/dist/session/transcript.js +186 -0
  336. package/dist/settings/manager.d.ts +36 -0
  337. package/dist/settings/manager.js +187 -0
  338. package/dist/settings/schema.d.ts +1219 -0
  339. package/dist/settings/schema.js +246 -0
  340. package/dist/skills/frontmatter.d.ts +13 -0
  341. package/dist/skills/frontmatter.js +70 -0
  342. package/dist/skills/index.d.ts +7 -0
  343. package/dist/skills/index.js +6 -0
  344. package/dist/skills/scanner.d.ts +31 -0
  345. package/dist/skills/scanner.js +171 -0
  346. package/dist/state.d.ts +160 -0
  347. package/dist/state.js +267 -0
  348. package/dist/tool-system/builtin/agent-notifications.d.ts +84 -0
  349. package/dist/tool-system/builtin/agent-notifications.js +197 -0
  350. package/dist/tool-system/builtin/agent-registry.d.ts +67 -0
  351. package/dist/tool-system/builtin/agent-registry.js +126 -0
  352. package/dist/tool-system/builtin/agent-transcript-translator.d.ts +22 -0
  353. package/dist/tool-system/builtin/agent-transcript-translator.js +160 -0
  354. package/dist/tool-system/builtin/agent.d.ts +16 -0
  355. package/dist/tool-system/builtin/agent.js +364 -0
  356. package/dist/tool-system/builtin/apply-patch/applier.d.ts +26 -0
  357. package/dist/tool-system/builtin/apply-patch/applier.js +250 -0
  358. package/dist/tool-system/builtin/apply-patch/index.d.ts +20 -0
  359. package/dist/tool-system/builtin/apply-patch/index.js +101 -0
  360. package/dist/tool-system/builtin/apply-patch/parser.d.ts +17 -0
  361. package/dist/tool-system/builtin/apply-patch/parser.js +212 -0
  362. package/dist/tool-system/builtin/apply-patch/seek-sequence.d.ts +18 -0
  363. package/dist/tool-system/builtin/apply-patch/seek-sequence.js +123 -0
  364. package/dist/tool-system/builtin/apply-patch/types.d.ts +49 -0
  365. package/dist/tool-system/builtin/apply-patch/types.js +13 -0
  366. package/dist/tool-system/builtin/arena.d.ts +31 -0
  367. package/dist/tool-system/builtin/arena.js +416 -0
  368. package/dist/tool-system/builtin/ask-user.d.ts +20 -0
  369. package/dist/tool-system/builtin/ask-user.js +99 -0
  370. package/dist/tool-system/builtin/bash.d.ts +21 -0
  371. package/dist/tool-system/builtin/bash.js +149 -0
  372. package/dist/tool-system/builtin/brief.d.ts +6 -0
  373. package/dist/tool-system/builtin/brief.js +41 -0
  374. package/dist/tool-system/builtin/config.d.ts +6 -0
  375. package/dist/tool-system/builtin/config.js +67 -0
  376. package/dist/tool-system/builtin/cron.d.ts +10 -0
  377. package/dist/tool-system/builtin/cron.js +61 -0
  378. package/dist/tool-system/builtin/edit.d.ts +6 -0
  379. package/dist/tool-system/builtin/edit.js +100 -0
  380. package/dist/tool-system/builtin/file-cache.d.ts +11 -0
  381. package/dist/tool-system/builtin/file-cache.js +39 -0
  382. package/dist/tool-system/builtin/glob.d.ts +7 -0
  383. package/dist/tool-system/builtin/glob.js +76 -0
  384. package/dist/tool-system/builtin/grep.d.ts +7 -0
  385. package/dist/tool-system/builtin/grep.js +150 -0
  386. package/dist/tool-system/builtin/index.d.ts +20 -0
  387. package/dist/tool-system/builtin/index.js +449 -0
  388. package/dist/tool-system/builtin/lsp.d.ts +6 -0
  389. package/dist/tool-system/builtin/lsp.js +141 -0
  390. package/dist/tool-system/builtin/mcp-tools.d.ts +10 -0
  391. package/dist/tool-system/builtin/mcp-tools.js +102 -0
  392. package/dist/tool-system/builtin/memory.d.ts +26 -0
  393. package/dist/tool-system/builtin/memory.js +226 -0
  394. package/dist/tool-system/builtin/notebook-edit.d.ts +6 -0
  395. package/dist/tool-system/builtin/notebook-edit.js +124 -0
  396. package/dist/tool-system/builtin/plan.d.ts +15 -0
  397. package/dist/tool-system/builtin/plan.js +55 -0
  398. package/dist/tool-system/builtin/powershell.d.ts +11 -0
  399. package/dist/tool-system/builtin/powershell.js +64 -0
  400. package/dist/tool-system/builtin/read.d.ts +6 -0
  401. package/dist/tool-system/builtin/read.js +70 -0
  402. package/dist/tool-system/builtin/remote-trigger.d.ts +6 -0
  403. package/dist/tool-system/builtin/remote-trigger.js +54 -0
  404. package/dist/tool-system/builtin/repl.d.ts +11 -0
  405. package/dist/tool-system/builtin/repl.js +82 -0
  406. package/dist/tool-system/builtin/send-message.d.ts +6 -0
  407. package/dist/tool-system/builtin/send-message.js +47 -0
  408. package/dist/tool-system/builtin/skill-prompt.d.ts +20 -0
  409. package/dist/tool-system/builtin/skill-prompt.js +52 -0
  410. package/dist/tool-system/builtin/skill.d.ts +9 -0
  411. package/dist/tool-system/builtin/skill.js +55 -0
  412. package/dist/tool-system/builtin/sleep.d.ts +6 -0
  413. package/dist/tool-system/builtin/sleep.js +33 -0
  414. package/dist/tool-system/builtin/task.d.ts +48 -0
  415. package/dist/tool-system/builtin/task.js +139 -0
  416. package/dist/tool-system/builtin/tool-search.d.ts +11 -0
  417. package/dist/tool-system/builtin/tool-search.js +90 -0
  418. package/dist/tool-system/builtin/web-fetch.d.ts +10 -0
  419. package/dist/tool-system/builtin/web-fetch.js +328 -0
  420. package/dist/tool-system/builtin/web-search.d.ts +25 -0
  421. package/dist/tool-system/builtin/web-search.js +174 -0
  422. package/dist/tool-system/builtin/worktree.d.ts +10 -0
  423. package/dist/tool-system/builtin/worktree.js +95 -0
  424. package/dist/tool-system/builtin/write.d.ts +6 -0
  425. package/dist/tool-system/builtin/write.js +36 -0
  426. package/dist/tool-system/context.d.ts +165 -0
  427. package/dist/tool-system/context.js +18 -0
  428. package/dist/tool-system/executor.d.ts +49 -0
  429. package/dist/tool-system/executor.js +495 -0
  430. package/dist/tool-system/investigation-guard.d.ts +46 -0
  431. package/dist/tool-system/investigation-guard.js +155 -0
  432. package/dist/tool-system/mcp-manager.d.ts +67 -0
  433. package/dist/tool-system/mcp-manager.js +249 -0
  434. package/dist/tool-system/permission.d.ts +111 -0
  435. package/dist/tool-system/permission.js +774 -0
  436. package/dist/tool-system/registry.d.ts +32 -0
  437. package/dist/tool-system/registry.js +131 -0
  438. package/dist/tool-system/sandbox/bwrap.d.ts +13 -0
  439. package/dist/tool-system/sandbox/bwrap.js +63 -0
  440. package/dist/tool-system/sandbox/index.d.ts +78 -0
  441. package/dist/tool-system/sandbox/index.js +222 -0
  442. package/dist/tool-system/sandbox/off.d.ts +2 -0
  443. package/dist/tool-system/sandbox/off.js +8 -0
  444. package/dist/tool-system/sandbox/seatbelt.d.ts +18 -0
  445. package/dist/tool-system/sandbox/seatbelt.js +109 -0
  446. package/dist/tool-system/task-guard.d.ts +29 -0
  447. package/dist/tool-system/task-guard.js +70 -0
  448. package/dist/tool-system/validation.d.ts +5 -0
  449. package/dist/tool-system/validation.js +39 -0
  450. package/dist/types.d.ts +376 -0
  451. package/dist/types.js +4 -0
  452. package/dist/updater.d.ts +65 -0
  453. package/dist/updater.js +405 -0
  454. package/dist/utils/debug.d.ts +41 -0
  455. package/dist/utils/debug.js +110 -0
  456. package/dist/utils/earlyInput.d.ts +43 -0
  457. package/dist/utils/earlyInput.js +166 -0
  458. package/dist/utils/env.d.ts +24 -0
  459. package/dist/utils/env.js +104 -0
  460. package/dist/utils/envUtils.d.ts +51 -0
  461. package/dist/utils/envUtils.js +135 -0
  462. package/dist/utils/execFileNoThrow.d.ts +39 -0
  463. package/dist/utils/execFileNoThrow.js +74 -0
  464. package/dist/utils/format.d.ts +44 -0
  465. package/dist/utils/format.js +236 -0
  466. package/dist/utils/intl.d.ts +22 -0
  467. package/dist/utils/intl.js +83 -0
  468. package/dist/utils/lockfile.d.ts +15 -0
  469. package/dist/utils/lockfile.js +30 -0
  470. package/dist/utils/memoize.d.ts +19 -0
  471. package/dist/utils/memoize.js +14 -0
  472. package/dist/utils/semver.d.ts +6 -0
  473. package/dist/utils/semver.js +13 -0
  474. package/dist/utils/sliceAnsi.d.ts +12 -0
  475. package/dist/utils/sliceAnsi.js +62 -0
  476. package/dist/utils/systemTheme.d.ts +40 -0
  477. package/dist/utils/systemTheme.js +108 -0
  478. package/dist/utils/task-sanitizer.d.ts +6 -0
  479. package/dist/utils/task-sanitizer.js +24 -0
  480. package/dist/utils/theme.d.ts +93 -0
  481. package/dist/utils/theme.js +544 -0
  482. package/dist/utils/toolDisplay.d.ts +31 -0
  483. package/dist/utils/toolDisplay.js +188 -0
  484. package/package.json +72 -0
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Colorizer — a minimal terminal-color interface that core formatters
3
+ * use without depending on chalk directly.
4
+ *
5
+ * UI hosts (TUI, web client, etc.) supply a real implementation. The
6
+ * default NOOP_COLORIZER returns text unchanged, so non-terminal
7
+ * consumers (web, Electron renderer, programmatic SDK use) see clean
8
+ * text without ANSI escape sequences.
9
+ */
10
+ export interface Colorizer {
11
+ dim(s: string): string;
12
+ bold(s: string): string;
13
+ red(s: string): string;
14
+ yellow(s: string): string;
15
+ green(s: string): string;
16
+ cyan(s: string): string;
17
+ white(s: string): string;
18
+ /** Composite: bold + cyan, used for section headers. */
19
+ boldCyan(s: string): string;
20
+ /** Composite: bold + white, used for sub-section headers. */
21
+ boldWhite(s: string): string;
22
+ }
23
+ export declare const NOOP_COLORIZER: Colorizer;
@@ -0,0 +1,12 @@
1
+ const identity = (s) => s;
2
+ export const NOOP_COLORIZER = {
3
+ dim: identity,
4
+ bold: identity,
5
+ red: identity,
6
+ yellow: identity,
7
+ green: identity,
8
+ cyan: identity,
9
+ white: identity,
10
+ boldCyan: identity,
11
+ boldWhite: identity,
12
+ };
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Context compaction strategies.
3
+ *
4
+ * Tier 0: truncateToolResult — truncate oversized individual results
5
+ * Tier 1: microcompact — zero-cost, clears old tool_result content
6
+ * Tier 2: LLM summary — generates summary via model call (async)
7
+ * Tier 3: window compact — keeps first + last N messages (sync fallback)
8
+ * Emergency: dropOldestRounds — progressive API-round-based truncation
9
+ *
10
+ * All slicing functions use adjustIndexToPreserveAPIInvariants()
11
+ * to prevent splitting tool_use / tool_result pairs.
12
+ */
13
+ import type { Message } from "../types.js";
14
+ /**
15
+ * Estimate token count from messages.
16
+ * Uses per-block-type estimation with 33% overhead padding.
17
+ */
18
+ export declare function estimateTokens(messages: Message[]): number;
19
+ /**
20
+ * Expand a slice start-index backwards so that every tool_result in the
21
+ * kept range has its corresponding tool_use in the kept range too.
22
+ *
23
+ * Without this, windowCompact / applySummaryCompaction can produce
24
+ * messages where tool_result references a tool_use_id that was
25
+ * compacted away, causing an API validation error.
26
+ */
27
+ export declare function adjustIndexToPreserveAPIInvariants(messages: Message[], startIndex: number): number;
28
+ /**
29
+ * Snip strategy: keep first N + last M messages, replace middle with a marker.
30
+ * Less aggressive than windowCompact — preserves initial context AND recent history.
31
+ * Uses adjustIndexToPreserveAPIInvariants on both boundaries.
32
+ */
33
+ export declare function snipCompact(messages: Message[], keepFirstN?: number, keepLastM?: number): Message[];
34
+ /**
35
+ * Window strategy: keep first message + last N messages.
36
+ * Uses adjustIndexToPreserveAPIInvariants to avoid splitting tool pairs.
37
+ */
38
+ export declare function windowCompact(messages: Message[], keepLastN: number): Message[];
39
+ /**
40
+ * Tools whose results are safe to clear during microcompact.
41
+ *
42
+ * Tracks the CC `COMPACTABLE_TOOLS` set: only "data-fetching" tools where the
43
+ * result is reconstructible (re-Read, re-Glob, re-Bash). Orchestration tools
44
+ * (TaskCreate / TaskUpdate / Agent / Skill / etc.) are excluded — their
45
+ * results carry conversation state the model needs to keep referencing.
46
+ */
47
+ export declare const COMPACTABLE_TOOL_NAMES: ReadonlySet<string>;
48
+ export interface MicrocompactOptions {
49
+ /** Keep this many most-recent compactable tool-result rounds untouched. */
50
+ keepRecentN?: number;
51
+ /** Tool names whose results may be cleared. Defaults to COMPACTABLE_TOOL_NAMES. */
52
+ compactableTools?: ReadonlySet<string>;
53
+ /** Optional callback invoked once when any clearing actually happened. */
54
+ onClear?: (info: {
55
+ clearedRounds: number;
56
+ toolNames: string[];
57
+ }) => void;
58
+ }
59
+ /**
60
+ * Remove old tool_result content (microcompact).
61
+ *
62
+ * For each tool_result block older than the most-recent N compactable rounds,
63
+ * replaces its content with a short fingerprint of the originating call
64
+ * (e.g. `[Old tool result cleared — Read file_path=/.../foo.ts]`) so the
65
+ * model can decide whether it's worth re-running the tool instead of
66
+ * guessing what it had seen.
67
+ *
68
+ * Behavior changes vs. earlier versions:
69
+ * - Only clears whitelisted tool names (Read/Glob/Bash/...). Orchestration
70
+ * tool results (TaskCreate/TaskUpdate/Agent/etc.) are left intact.
71
+ * - "Round" count is per *compactable* result, not per message with any
72
+ * tool_result. A round containing only TaskUpdate doesn't count toward N.
73
+ * - Replacement string includes tool name + key args so the model isn't
74
+ * forced into blind re-Reads (which then trip the Investigation guard).
75
+ */
76
+ export declare function microcompact(messages: Message[], options?: MicrocompactOptions): Message[];
77
+ /**
78
+ * Apply aggregate per-message tool result budget.
79
+ * When total tool_result content in a single message exceeds maxTotalChars,
80
+ * truncates the largest results first with a notice.
81
+ */
82
+ export declare function applyToolResultBudget(messages: Message[], maxTotalChars?: number): Message[];
83
+ /**
84
+ * Truncate a single tool result if it exceeds the character limit.
85
+ * Returns the truncated string with a notice.
86
+ */
87
+ export declare function truncateToolResult(result: string, maxChars?: number): string;
88
+ /**
89
+ * Build a structured summarization prompt from messages to be compacted.
90
+ * Produces a 9-section summary preserving key details.
91
+ */
92
+ export declare function buildSummarizationPrompt(messagesToSummarize: Message[], priorSummary?: string): string;
93
+ export declare function extractAnchoredSummary(messages: Message[]): string | undefined;
94
+ /**
95
+ * Apply LLM-generated summary compaction (hybrid mode).
96
+ *
97
+ * Instead of eagerly restoring file contents (wastes tokens), gives the
98
+ * model a summary + the transcript path so it can Read on demand.
99
+ * Also lists recently-referenced files so the model knows what to re-read.
100
+ */
101
+ export declare function applySummaryCompaction(messages: Message[], summary: string, keepRecentN: number, transcriptPath?: string): Message[];
102
+ /**
103
+ * Group messages by API round-trip boundaries.
104
+ * Each group represents one complete assistant response + its tool results.
105
+ */
106
+ export declare function groupMessagesByApiRound(messages: Message[]): Message[][];
107
+ /**
108
+ * Drop the oldest API rounds from messages, preserving tool pairs.
109
+ * Used for progressive prompt-too-long recovery.
110
+ */
111
+ export declare function dropOldestRounds(messages: Message[], roundsToDrop: number): Message[];
112
+ /**
113
+ * Extract file paths that were referenced (Read/Edit/Write) in compacted
114
+ * messages. Returns paths only — the model uses Read tool on demand.
115
+ */
116
+ export declare function extractReferencedFilePaths(messages: Message[]): string[];
@@ -0,0 +1,534 @@
1
+ /**
2
+ * Context compaction strategies.
3
+ *
4
+ * Tier 0: truncateToolResult — truncate oversized individual results
5
+ * Tier 1: microcompact — zero-cost, clears old tool_result content
6
+ * Tier 2: LLM summary — generates summary via model call (async)
7
+ * Tier 3: window compact — keeps first + last N messages (sync fallback)
8
+ * Emergency: dropOldestRounds — progressive API-round-based truncation
9
+ *
10
+ * All slicing functions use adjustIndexToPreserveAPIInvariants()
11
+ * to prevent splitting tool_use / tool_result pairs.
12
+ */
13
+ import { estimateMessagesTokens } from "./token-counter.js";
14
+ /**
15
+ * Estimate token count from messages.
16
+ * Uses per-block-type estimation with 33% overhead padding.
17
+ */
18
+ export function estimateTokens(messages) {
19
+ return Math.ceil(estimateMessagesTokens(messages) * (4 / 3));
20
+ }
21
+ // ─── Tool Use / Result Pair Protection ──────────────────────────────
22
+ /**
23
+ * Expand a slice start-index backwards so that every tool_result in the
24
+ * kept range has its corresponding tool_use in the kept range too.
25
+ *
26
+ * Without this, windowCompact / applySummaryCompaction can produce
27
+ * messages where tool_result references a tool_use_id that was
28
+ * compacted away, causing an API validation error.
29
+ */
30
+ export function adjustIndexToPreserveAPIInvariants(messages, startIndex) {
31
+ let adjusted = startIndex;
32
+ // Collect all tool_use_ids referenced by tool_results in the kept range
33
+ const neededToolUseIds = new Set();
34
+ for (let i = adjusted; i < messages.length; i++) {
35
+ const msg = messages[i];
36
+ if (!Array.isArray(msg.content))
37
+ continue;
38
+ for (const block of msg.content) {
39
+ if (block.type === "tool_result" && block.tool_use_id) {
40
+ neededToolUseIds.add(block.tool_use_id);
41
+ }
42
+ }
43
+ }
44
+ // Remove IDs that are already in the kept range
45
+ for (let i = adjusted; i < messages.length; i++) {
46
+ const msg = messages[i];
47
+ if (!Array.isArray(msg.content))
48
+ continue;
49
+ for (const block of msg.content) {
50
+ if (block.type === "tool_use" && block.id) {
51
+ neededToolUseIds.delete(block.id);
52
+ }
53
+ }
54
+ }
55
+ if (neededToolUseIds.size === 0)
56
+ return adjusted;
57
+ // Search backwards for assistant messages containing needed tool_use blocks
58
+ for (let i = adjusted - 1; i >= 0 && neededToolUseIds.size > 0; i--) {
59
+ const msg = messages[i];
60
+ if (msg.role !== "assistant" || !Array.isArray(msg.content))
61
+ continue;
62
+ for (const block of msg.content) {
63
+ if (block.type === "tool_use" && block.id && neededToolUseIds.has(block.id)) {
64
+ neededToolUseIds.delete(block.id);
65
+ if (i < adjusted)
66
+ adjusted = i;
67
+ }
68
+ }
69
+ }
70
+ return adjusted;
71
+ }
72
+ /**
73
+ * Snip strategy: keep first N + last M messages, replace middle with a marker.
74
+ * Less aggressive than windowCompact — preserves initial context AND recent history.
75
+ * Uses adjustIndexToPreserveAPIInvariants on both boundaries.
76
+ */
77
+ export function snipCompact(messages, keepFirstN = 3, keepLastM = 8) {
78
+ if (messages.length <= keepFirstN + keepLastM + 1)
79
+ return messages;
80
+ // Adjust last-M boundary to preserve tool pairs
81
+ let lastStart = messages.length - keepLastM;
82
+ lastStart = adjustIndexToPreserveAPIInvariants(messages, lastStart);
83
+ // Ensure we don't overlap with the first-N range
84
+ if (lastStart <= keepFirstN)
85
+ return messages;
86
+ const snippedCount = lastStart - keepFirstN;
87
+ const snipMarker = {
88
+ role: "user",
89
+ content: `<system-reminder>[${snippedCount} messages snipped to save context. ` +
90
+ `Use the transcript file to review details if needed.]</system-reminder>`,
91
+ };
92
+ return [
93
+ ...messages.slice(0, keepFirstN),
94
+ snipMarker,
95
+ ...messages.slice(lastStart),
96
+ ];
97
+ }
98
+ /**
99
+ * Window strategy: keep first message + last N messages.
100
+ * Uses adjustIndexToPreserveAPIInvariants to avoid splitting tool pairs.
101
+ */
102
+ export function windowCompact(messages, keepLastN) {
103
+ if (messages.length <= keepLastN + 1)
104
+ return messages;
105
+ let startIndex = messages.length - keepLastN;
106
+ startIndex = adjustIndexToPreserveAPIInvariants(messages, startIndex);
107
+ // Always keep first message (system context / user's initial prompt)
108
+ if (startIndex <= 1)
109
+ return messages;
110
+ return [messages[0], ...messages.slice(startIndex)];
111
+ }
112
+ /**
113
+ * Tools whose results are safe to clear during microcompact.
114
+ *
115
+ * Tracks the CC `COMPACTABLE_TOOLS` set: only "data-fetching" tools where the
116
+ * result is reconstructible (re-Read, re-Glob, re-Bash). Orchestration tools
117
+ * (TaskCreate / TaskUpdate / Agent / Skill / etc.) are excluded — their
118
+ * results carry conversation state the model needs to keep referencing.
119
+ */
120
+ export const COMPACTABLE_TOOL_NAMES = new Set([
121
+ "Read",
122
+ "Glob",
123
+ "Grep",
124
+ "Bash",
125
+ "PowerShell",
126
+ "NotebookEdit",
127
+ "WebFetch",
128
+ "WebSearch",
129
+ "REPL",
130
+ ]);
131
+ /**
132
+ * Build a tool_use_id → tool name map from the assistant messages preceding
133
+ * the tool_results. tool_use always appears before its tool_result, so this
134
+ * walk lets us decide per-result whether it's compactable.
135
+ */
136
+ function buildToolUseIdToNameMap(messages) {
137
+ const map = new Map();
138
+ for (const msg of messages) {
139
+ if (!Array.isArray(msg.content))
140
+ continue;
141
+ for (const block of msg.content) {
142
+ if (block.type === "tool_use" && block.id && block.name) {
143
+ map.set(block.id, block.name);
144
+ }
145
+ }
146
+ }
147
+ return map;
148
+ }
149
+ /**
150
+ * Short fingerprint of the original call so cleared results still tell the
151
+ * model what was here. Picks the most useful arg keys per tool, falls back
152
+ * to a generic JSON preview. Caps total length so we don't reintroduce bulk.
153
+ */
154
+ function summarizeToolCallArgs(toolName, input) {
155
+ if (!input || typeof input !== "object")
156
+ return "";
157
+ const pick = (keys) => {
158
+ const parts = [];
159
+ for (const key of keys) {
160
+ const v = input[key];
161
+ if (typeof v === "string" && v.length > 0) {
162
+ parts.push(`${key}=${v.length > 80 ? v.slice(0, 77) + "..." : v}`);
163
+ }
164
+ }
165
+ return parts.join(" ");
166
+ };
167
+ switch (toolName) {
168
+ case "Read":
169
+ case "Write":
170
+ case "Edit":
171
+ case "NotebookEdit":
172
+ return pick(["file_path", "path", "notebook_path"]);
173
+ case "Glob":
174
+ case "Grep":
175
+ return pick(["pattern", "path", "glob"]);
176
+ case "Bash":
177
+ case "PowerShell":
178
+ case "REPL":
179
+ return pick(["command"]);
180
+ case "WebFetch":
181
+ case "WebSearch":
182
+ return pick(["url", "query"]);
183
+ default: {
184
+ const json = JSON.stringify(input);
185
+ return json.length > 100 ? json.slice(0, 97) + "..." : json;
186
+ }
187
+ }
188
+ }
189
+ /**
190
+ * Remove old tool_result content (microcompact).
191
+ *
192
+ * For each tool_result block older than the most-recent N compactable rounds,
193
+ * replaces its content with a short fingerprint of the originating call
194
+ * (e.g. `[Old tool result cleared — Read file_path=/.../foo.ts]`) so the
195
+ * model can decide whether it's worth re-running the tool instead of
196
+ * guessing what it had seen.
197
+ *
198
+ * Behavior changes vs. earlier versions:
199
+ * - Only clears whitelisted tool names (Read/Glob/Bash/...). Orchestration
200
+ * tool results (TaskCreate/TaskUpdate/Agent/etc.) are left intact.
201
+ * - "Round" count is per *compactable* result, not per message with any
202
+ * tool_result. A round containing only TaskUpdate doesn't count toward N.
203
+ * - Replacement string includes tool name + key args so the model isn't
204
+ * forced into blind re-Reads (which then trip the Investigation guard).
205
+ */
206
+ export function microcompact(messages, options = {}) {
207
+ const keepRecentN = options.keepRecentN ?? 5;
208
+ const compactable = options.compactableTools ?? COMPACTABLE_TOOL_NAMES;
209
+ const idToName = buildToolUseIdToNameMap(messages);
210
+ const idToInput = new Map();
211
+ for (const msg of messages) {
212
+ if (!Array.isArray(msg.content))
213
+ continue;
214
+ for (const block of msg.content) {
215
+ if (block.type === "tool_use" && block.id) {
216
+ idToInput.set(block.id, block.input);
217
+ }
218
+ }
219
+ }
220
+ // Walk back, counting only compactable rounds. A round is a message that
221
+ // contains at least one *eligible* tool_result we haven't cleared yet.
222
+ let compactableRoundCount = 0;
223
+ const indicesToTouch = [];
224
+ for (let i = messages.length - 1; i >= 0; i--) {
225
+ const msg = messages[i];
226
+ if (!Array.isArray(msg.content))
227
+ continue;
228
+ const hasEligible = msg.content.some((b) => b.type === "tool_result" &&
229
+ b.tool_use_id != null &&
230
+ compactable.has(idToName.get(b.tool_use_id) ?? "") &&
231
+ typeof b.content === "string" &&
232
+ !b.content.startsWith("[Old tool result cleared"));
233
+ if (!hasEligible)
234
+ continue;
235
+ compactableRoundCount++;
236
+ if (compactableRoundCount > keepRecentN) {
237
+ indicesToTouch.push(i);
238
+ }
239
+ }
240
+ if (indicesToTouch.length === 0)
241
+ return messages;
242
+ const touchSet = new Set(indicesToTouch);
243
+ const clearedToolNames = new Set();
244
+ let clearedBlocks = 0;
245
+ const result = messages.map((msg, i) => {
246
+ if (!touchSet.has(i) || !Array.isArray(msg.content))
247
+ return msg;
248
+ return {
249
+ ...msg,
250
+ content: msg.content.map((block) => {
251
+ if (block.type !== "tool_result" || !block.tool_use_id)
252
+ return block;
253
+ const toolName = idToName.get(block.tool_use_id);
254
+ if (!toolName || !compactable.has(toolName))
255
+ return block;
256
+ if (typeof block.content !== "string")
257
+ return block;
258
+ if (block.content.startsWith("[Old tool result cleared"))
259
+ return block;
260
+ const argsSummary = summarizeToolCallArgs(toolName, idToInput.get(block.tool_use_id));
261
+ const fingerprint = argsSummary
262
+ ? `[Old tool result cleared — ${toolName} ${argsSummary}]`
263
+ : `[Old tool result cleared — ${toolName}]`;
264
+ clearedToolNames.add(toolName);
265
+ clearedBlocks++;
266
+ return { ...block, content: fingerprint };
267
+ }),
268
+ };
269
+ });
270
+ if (clearedBlocks > 0) {
271
+ options.onClear?.({
272
+ clearedRounds: indicesToTouch.length,
273
+ toolNames: [...clearedToolNames].sort(),
274
+ });
275
+ }
276
+ return result;
277
+ }
278
+ /**
279
+ * Apply aggregate per-message tool result budget.
280
+ * When total tool_result content in a single message exceeds maxTotalChars,
281
+ * truncates the largest results first with a notice.
282
+ */
283
+ export function applyToolResultBudget(messages, maxTotalChars = 100_000) {
284
+ return messages.map((msg) => {
285
+ if (!Array.isArray(msg.content))
286
+ return msg;
287
+ // Collect tool_result blocks with their sizes
288
+ const resultBlocks = [];
289
+ let totalSize = 0;
290
+ for (let i = 0; i < msg.content.length; i++) {
291
+ const block = msg.content[i];
292
+ if (block.type === "tool_result" && typeof block.content === "string") {
293
+ const size = block.content.length;
294
+ resultBlocks.push({ index: i, size });
295
+ totalSize += size;
296
+ }
297
+ }
298
+ if (totalSize <= maxTotalChars || resultBlocks.length === 0)
299
+ return msg;
300
+ // Sort by size descending — truncate largest first
301
+ resultBlocks.sort((a, b) => b.size - a.size);
302
+ let remaining = totalSize;
303
+ const toTruncate = new Set();
304
+ for (const rb of resultBlocks) {
305
+ if (remaining <= maxTotalChars)
306
+ break;
307
+ toTruncate.add(rb.index);
308
+ remaining -= rb.size;
309
+ remaining += 200; // truncated replacement is ~200 chars
310
+ }
311
+ if (toTruncate.size === 0)
312
+ return msg;
313
+ const newContent = msg.content.map((block, i) => {
314
+ if (!toTruncate.has(i))
315
+ return block;
316
+ const preview = typeof block.content === "string" ? block.content.slice(0, 500) : "";
317
+ const sizeKb = (block.content.length / 1000).toFixed(0);
318
+ return {
319
+ ...block,
320
+ content: `Output too large (${sizeKb}KB) — truncated to fit the per-message budget. ` +
321
+ `Re-run the originating tool if you need the full output.\n\n` +
322
+ `Preview (first 500 chars):\n${preview}`,
323
+ };
324
+ });
325
+ return { ...msg, content: newContent };
326
+ });
327
+ }
328
+ /**
329
+ * Truncate a single tool result if it exceeds the character limit.
330
+ * Returns the truncated string with a notice.
331
+ */
332
+ export function truncateToolResult(result, maxChars = 30_000) {
333
+ if (result.length <= maxChars)
334
+ return result;
335
+ // Keep head and tail for context
336
+ const headSize = Math.floor(maxChars * 0.7);
337
+ const tailSize = Math.floor(maxChars * 0.2);
338
+ const head = result.slice(0, headSize);
339
+ const tail = result.slice(-tailSize);
340
+ return (head +
341
+ `\n\n... [${result.length - headSize - tailSize} characters truncated] ...\n\n` +
342
+ tail);
343
+ }
344
+ /**
345
+ * Build a structured summarization prompt from messages to be compacted.
346
+ * Produces a 9-section summary preserving key details.
347
+ */
348
+ export function buildSummarizationPrompt(messagesToSummarize, priorSummary) {
349
+ const parts = [];
350
+ for (const msg of messagesToSummarize) {
351
+ if (typeof msg.content === "string") {
352
+ parts.push(`[${msg.role}]: ${msg.content.slice(0, 3000)}`);
353
+ }
354
+ else {
355
+ for (const block of msg.content) {
356
+ if (block.type === "text" && block.text) {
357
+ parts.push(`[${msg.role}]: ${block.text.slice(0, 3000)}`);
358
+ }
359
+ else if (block.type === "tool_use") {
360
+ const args = JSON.stringify(block.input).slice(0, 500);
361
+ parts.push(`[tool_use]: ${block.name}(${args})`);
362
+ }
363
+ else if (block.type === "tool_result") {
364
+ const content = typeof block.content === "string" ? block.content : "";
365
+ parts.push(`[tool_result]: ${content.slice(0, 1500)}`);
366
+ }
367
+ }
368
+ }
369
+ }
370
+ const sectionList = "1. **Primary Request**: What the user originally asked for\n" +
371
+ "2. **Key Concepts**: Important technical terms, patterns, file paths\n" +
372
+ "3. **Files Referenced**: List of files read/edited with key content\n" +
373
+ "4. **Errors & Fixes**: Any errors encountered and how they were resolved\n" +
374
+ "5. **Actions Taken**: Tools used and their outcomes\n" +
375
+ "6. **User Messages**: All distinct user requests (verbatim if short)\n" +
376
+ "7. **Pending Tasks**: Anything started but not finished\n" +
377
+ "8. **Current State**: Where things stand right now\n" +
378
+ "9. **Next Steps**: What should happen next\n";
379
+ if (priorSummary) {
380
+ return ("You are updating an anchored conversation summary. A prior summary is " +
381
+ "shown first, followed by NEW conversation that occurred after that " +
382
+ "summary was produced. Produce an UPDATED summary that:\n" +
383
+ "- Preserves every critical fact from the prior summary (file paths, " +
384
+ "decisions, the user's original intent, errors that were fixed)\n" +
385
+ "- Merges in new facts from the new conversation\n" +
386
+ "- Resolves contradictions in favor of the newer information\n" +
387
+ "- Stays in the same 9-section structure below\n" +
388
+ "- Is factual; preserves file paths, function names, and error " +
389
+ "messages exactly\n\n" +
390
+ sectionList +
391
+ "\n=== Prior summary ===\n" +
392
+ priorSummary +
393
+ "\n\n=== New conversation ===\n\n" +
394
+ parts.join("\n"));
395
+ }
396
+ return ("Summarize the following conversation into these sections. " +
397
+ "Be factual. Preserve file paths, function names, and error messages exactly.\n\n" +
398
+ sectionList +
399
+ "\nConversation:\n\n" +
400
+ parts.join("\n"));
401
+ }
402
+ // ─── Anchored summary marker ────────────────────────────────────────
403
+ //
404
+ // applySummaryCompaction wraps the LLM-generated summary in these tags so the
405
+ // next compaction pass can grep it out and ask the LLM to merge-update it
406
+ // (rolling summary), instead of re-summarizing from scratch each time. The
407
+ // marker also survives session resume: messages persist via the session
408
+ // transcript, so a process restart can still recover the latest summary
409
+ // without needing a side-channel state file.
410
+ const ANCHORED_OPEN = "<anchored-summary>";
411
+ const ANCHORED_CLOSE = "</anchored-summary>";
412
+ export function extractAnchoredSummary(messages) {
413
+ for (let i = messages.length - 1; i >= 0; i--) {
414
+ const msg = messages[i];
415
+ const content = typeof msg.content === "string" ? msg.content : "";
416
+ if (!content)
417
+ continue;
418
+ const start = content.indexOf(ANCHORED_OPEN);
419
+ if (start < 0)
420
+ continue;
421
+ const end = content.indexOf(ANCHORED_CLOSE, start + ANCHORED_OPEN.length);
422
+ if (end <= start)
423
+ continue;
424
+ return content.slice(start + ANCHORED_OPEN.length, end).trim();
425
+ }
426
+ return undefined;
427
+ }
428
+ /**
429
+ * Apply LLM-generated summary compaction (hybrid mode).
430
+ *
431
+ * Instead of eagerly restoring file contents (wastes tokens), gives the
432
+ * model a summary + the transcript path so it can Read on demand.
433
+ * Also lists recently-referenced files so the model knows what to re-read.
434
+ */
435
+ export function applySummaryCompaction(messages, summary, keepRecentN, transcriptPath) {
436
+ if (messages.length <= keepRecentN + 2)
437
+ return messages;
438
+ // Adjust slice point to preserve tool pairs
439
+ let startIndex = messages.length - keepRecentN;
440
+ startIndex = adjustIndexToPreserveAPIInvariants(messages, startIndex);
441
+ if (startIndex <= 1)
442
+ return messages;
443
+ const first = messages[0];
444
+ const compactedMessages = messages.slice(1, startIndex);
445
+ const recent = messages.slice(startIndex);
446
+ // Extract file paths (not contents) that were referenced before compaction
447
+ const referencedFiles = extractReferencedFilePaths(compactedMessages);
448
+ let body = `This session is being continued from a previous conversation that ran out of context. ` +
449
+ `The summary below covers the earlier portion of the conversation.\n\n` +
450
+ `${ANCHORED_OPEN}\n${summary}\n${ANCHORED_CLOSE}`;
451
+ if (transcriptPath) {
452
+ body +=
453
+ `\n\nIf you need specific details from before compaction (like exact code snippets, ` +
454
+ `error messages, or content you generated), read the full transcript at: ${transcriptPath}`;
455
+ }
456
+ if (referencedFiles.length > 0) {
457
+ body +=
458
+ `\n\nFiles referenced before compaction (use Read tool if you need their current content):\n` +
459
+ referencedFiles.map((f) => `- ${f}`).join("\n");
460
+ }
461
+ body += `\n\nRecent messages are preserved verbatim below. Continue from where you left off.`;
462
+ const summaryMsg = {
463
+ role: "user",
464
+ content: `<system-reminder>${body}</system-reminder>`,
465
+ };
466
+ return [first, summaryMsg, ...recent];
467
+ }
468
+ // ─── API Round Grouping & Progressive Recovery ──────────────────────
469
+ /**
470
+ * Group messages by API round-trip boundaries.
471
+ * Each group represents one complete assistant response + its tool results.
472
+ */
473
+ export function groupMessagesByApiRound(messages) {
474
+ const groups = [];
475
+ let current = [];
476
+ for (const msg of messages) {
477
+ if (msg.role === "assistant" && current.length > 0) {
478
+ // New assistant message = new API round
479
+ groups.push(current);
480
+ current = [msg];
481
+ }
482
+ else {
483
+ current.push(msg);
484
+ }
485
+ }
486
+ if (current.length > 0)
487
+ groups.push(current);
488
+ return groups;
489
+ }
490
+ /**
491
+ * Drop the oldest API rounds from messages, preserving tool pairs.
492
+ * Used for progressive prompt-too-long recovery.
493
+ */
494
+ export function dropOldestRounds(messages, roundsToDrop) {
495
+ const groups = groupMessagesByApiRound(messages);
496
+ if (groups.length <= roundsToDrop + 1) {
497
+ // Can't drop that many — keep at least the last group
498
+ return groups[groups.length - 1];
499
+ }
500
+ const kept = groups.slice(roundsToDrop).flat();
501
+ // Ensure tool pair safety
502
+ const safeStart = adjustIndexToPreserveAPIInvariants(kept, 0);
503
+ const result = kept.slice(safeStart);
504
+ // If first message is assistant, prepend synthetic user message
505
+ if (result.length > 0 && result[0].role === "assistant") {
506
+ result.unshift({
507
+ role: "user",
508
+ content: "<system-reminder>Earlier conversation context was removed to fit within the context window. Continue from the assistant's response below.</system-reminder>",
509
+ });
510
+ }
511
+ return result;
512
+ }
513
+ // ─── Post-Compaction: Lightweight File Path Extraction ──────────────
514
+ /**
515
+ * Extract file paths that were referenced (Read/Edit/Write) in compacted
516
+ * messages. Returns paths only — the model uses Read tool on demand.
517
+ */
518
+ export function extractReferencedFilePaths(messages) {
519
+ const paths = new Set();
520
+ const FILE_TOOLS = new Set(["Read", "Edit", "Write", "Glob", "Grep"]);
521
+ for (const msg of messages) {
522
+ if (!Array.isArray(msg.content))
523
+ continue;
524
+ for (const block of msg.content) {
525
+ if (block.type === "tool_use" && block.name && FILE_TOOLS.has(block.name) && block.input) {
526
+ const input = block.input;
527
+ const fp = (input.file_path ?? input.path);
528
+ if (fp)
529
+ paths.add(fp);
530
+ }
531
+ }
532
+ }
533
+ return [...paths];
534
+ }