@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,495 @@
1
+ /**
2
+ * Tool executor — orchestrates permission checks, hooks, and execution.
3
+ */
4
+ import { setMaxListeners } from "node:events";
5
+ import { logger as rootLogger, getCurrentSid } from "../logging/logger.js";
6
+ import { recordToolCall, recordToolResult } from "../logging/session-recorder.js";
7
+ import { validateToolArgs } from "./validation.js";
8
+ // A1 hardening: hooks must never promote a non-`allow` classifier
9
+ // decision to `allow`. They may otherwise adjust the decision freely
10
+ // (e.g. tighten `allow` to `deny`/`ask`, or relax `deny` to `ask` to
11
+ // request interactive confirmation — both legitimate audit patterns).
12
+ // The user remains the only source of `allow` when the classifier
13
+ // said `ask`/`deny`.
14
+ //
15
+ // See standard §S4 and spec docs/superpowers/specs/2026-05-26-a1-permission-hardening-design.md.
16
+ function clampHookDecision(classifier, hook) {
17
+ if (!hook)
18
+ return { decision: classifier, rejectedUpgrade: false };
19
+ if (hook === "allow" && classifier !== "allow") {
20
+ return { decision: classifier, rejectedUpgrade: true };
21
+ }
22
+ return { decision: hook, rejectedUpgrade: false };
23
+ }
24
+ export class ToolExecutor {
25
+ registry;
26
+ permission;
27
+ hooks;
28
+ signal;
29
+ /** Per-Engine ToolContext injected for every tool call. */
30
+ toolCtx;
31
+ /**
32
+ * Turn-scoped logger set by TurnLoop at the top of each iteration.
33
+ * Falls back to the root logger so executor calls outside the turn loop
34
+ * (tests, ad-hoc tool runs) still write log lines, just without turn tags.
35
+ */
36
+ log = rootLogger;
37
+ guard;
38
+ taskGuard;
39
+ constructor(registry, permission, hooks) {
40
+ this.registry = registry;
41
+ this.permission = permission;
42
+ this.hooks = hooks;
43
+ }
44
+ setInvestigationGuard(guard) {
45
+ this.guard = guard;
46
+ }
47
+ getInvestigationGuard() {
48
+ return this.guard;
49
+ }
50
+ setTaskGuard(guard) {
51
+ this.taskGuard = guard;
52
+ }
53
+ getTaskGuard() {
54
+ return this.taskGuard;
55
+ }
56
+ /** Set the abort signal for cascading cancellation. */
57
+ setSignal(signal) {
58
+ this.signal = signal;
59
+ // Each parallel tool call attaches its own `abort` listener to this
60
+ // session-wide signal (registry.ts:115). With 11+ concurrent tools —
61
+ // common when an Agent subagent fans out reads — Node's default
62
+ // limit of 10 fires a MaxListenersExceededWarning. The listeners are
63
+ // removed correctly in finally blocks; raise the ceiling to silence
64
+ // the noise without masking real leaks.
65
+ if (signal)
66
+ setMaxListeners(50, signal);
67
+ }
68
+ /** Set the per-Engine ToolContext (askUser, llmConfig, modelPool, etc.). */
69
+ setContext(ctx) {
70
+ this.toolCtx = ctx;
71
+ }
72
+ /** Inject a turn-scoped logger so tool-execution lines carry turn/turnId. */
73
+ setLogger(log) {
74
+ this.log = log;
75
+ this.permission.setLogger(log);
76
+ }
77
+ /** Check if a tool is safe for concurrent execution (read-only). */
78
+ isConcurrencySafe(toolName) {
79
+ const tool = this.registry.getTool(toolName);
80
+ return tool?.isConcurrencySafe ?? false;
81
+ }
82
+ async executeSingle(callIn) {
83
+ // Local `call` so we can rewrite args via pre_tool_use updatedInput
84
+ // without mutating the caller's object.
85
+ let call = callIn;
86
+ // 0. Plan mode: only allow read-only tools — no file writes at all
87
+ if (this.toolCtx?.planMode) {
88
+ const allowedInPlan = new Set([
89
+ "EnterPlanMode",
90
+ "ExitPlanMode",
91
+ "Read",
92
+ "Glob",
93
+ "Grep",
94
+ "WebSearch",
95
+ "WebFetch",
96
+ "AskUserQuestion",
97
+ "Agent",
98
+ "ToolSearch",
99
+ "TodoWrite",
100
+ ]);
101
+ if (!allowedInPlan.has(call.toolName)) {
102
+ if (call.toolName === "Bash" && this.isReadOnlyBashCommand(call.args)) {
103
+ // Read-only bash is fine
104
+ }
105
+ else {
106
+ return {
107
+ id: call.id,
108
+ toolName: call.toolName,
109
+ error: `Plan mode: ${call.toolName} is blocked. Only read-only tools (Read, Glob, Grep, WebSearch, WebFetch, Bash read-only) are allowed. You MUST output your plan as text in the conversation instead. Do NOT retry this tool call.`,
110
+ isError: true,
111
+ };
112
+ }
113
+ }
114
+ }
115
+ // 0.5. Validate tool args
116
+ const toolDef = this.registry.getTool(call.toolName);
117
+ if (toolDef?.inputSchema) {
118
+ const validationError = validateToolArgs(call.toolName, call.args, toolDef.inputSchema);
119
+ if (validationError) {
120
+ return {
121
+ id: call.id,
122
+ toolName: call.toolName,
123
+ error: `Invalid input: ${validationError}`,
124
+ isError: true,
125
+ };
126
+ }
127
+ }
128
+ // 0.6. Pre-tool-use hook (can approve/deny before execution)
129
+ const hookResult = await this.hooks.emit("pre_tool_use", {
130
+ toolName: call.toolName,
131
+ args: call.args,
132
+ toolCallId: call.id,
133
+ });
134
+ if (hookResult.decision === "deny") {
135
+ return {
136
+ id: call.id,
137
+ toolName: call.toolName,
138
+ error: `Blocked by pre_tool_use hook: ${hookResult.messages?.join(", ") ?? "denied"}`,
139
+ isError: true,
140
+ };
141
+ }
142
+ // pre_tool_use can rewrite the args for sanitizer / normalizer use
143
+ // cases. Re-validate against the schema so a malformed rewrite
144
+ // surfaces as the standard "Invalid input" error rather than
145
+ // silently corrupting downstream execution.
146
+ if (hookResult.updatedInput !== undefined) {
147
+ call = { ...call, args: hookResult.updatedInput };
148
+ if (toolDef?.inputSchema) {
149
+ const revalidation = validateToolArgs(call.toolName, call.args, toolDef.inputSchema);
150
+ if (revalidation) {
151
+ return {
152
+ id: call.id,
153
+ toolName: call.toolName,
154
+ error: `Invalid input (after pre_tool_use rewrite): ${revalidation}`,
155
+ isError: true,
156
+ };
157
+ }
158
+ }
159
+ this.log.info("hook.updated_input", {
160
+ cat: "tool",
161
+ tool: call.toolName,
162
+ toolCallId: call.id,
163
+ });
164
+ }
165
+ // A1 hardening: pre_tool_use can no longer pre-approve a tool via
166
+ // `decision === "allow"`. Hooks may relax `allow` and may force
167
+ // `ask`/`deny`, but they cannot promote a `deny`/`ask` decision to
168
+ // `allow`. The only paths to `allow` are the classifier (rules,
169
+ // safe-read, allowlist) and the user (interactive approval).
170
+ if (hookResult.decision === "allow") {
171
+ this.log.info("permission.hook_upgrade_rejected", {
172
+ cat: "permission",
173
+ tool: call.toolName,
174
+ site: "pre_tool_use",
175
+ });
176
+ }
177
+ // pre_tool_use can request interactive confirmation via
178
+ // decision: "ask". We invoke the same handleAsk path the classifier
179
+ // uses, but feed the hook's messages so the user sees the handler's
180
+ // reasoning. If the user approves, we skip the classifier below —
181
+ // the hook and the user together have decided.
182
+ if (hookResult.decision === "ask") {
183
+ const reason = hookResult.messages?.join("\n") ?? undefined;
184
+ const approved = await this.permission.handleAsk(call.toolName, call.args, reason);
185
+ if (!approved) {
186
+ return {
187
+ id: call.id,
188
+ toolName: call.toolName,
189
+ error: `Tool call denied by user (pre_tool_use ask).`,
190
+ isError: true,
191
+ };
192
+ }
193
+ }
194
+ // 0.7. Investigation guard — block redundant reads and tag soft reminders
195
+ // onto results. See investigation-guard.ts for the rules; they enforce the
196
+ // soft prompt guidance in coding.md ("never re-read", "3-call budget").
197
+ const guardDecision = this.guard?.preToolCheck(call);
198
+ if (guardDecision?.block) {
199
+ this.log.info("guard.block", { cat: "guard", tool: call.toolName, reason: guardDecision.block.slice(0, 200) });
200
+ return {
201
+ id: call.id,
202
+ toolName: call.toolName,
203
+ error: guardDecision.block,
204
+ isError: true,
205
+ };
206
+ }
207
+ // 1. Permission check — skipped only when pre_tool_use issued an
208
+ // `ask` that the user just approved (we don't double-prompt).
209
+ if (hookResult.decision !== "ask") {
210
+ const classifierDecision = this.permission.classify(call.toolName, call.args);
211
+ this.log.info("permission.classify", {
212
+ cat: "permission",
213
+ tool: call.toolName,
214
+ decision: classifierDecision,
215
+ mode: this.permission.getMode(),
216
+ });
217
+ // on_permission_check hook: lets handlers audit and *downgrade*
218
+ // the classifier decision (e.g. `allow → ask/deny`, `deny →
219
+ // ask`). Promotion to `allow` is rejected by clampHookDecision
220
+ // — only the classifier and the user can grant `allow`.
221
+ const permHook = await this.hooks.emit("on_permission_check", {
222
+ toolName: call.toolName,
223
+ args: call.args,
224
+ toolCallId: call.id,
225
+ classifierDecision,
226
+ });
227
+ // A1 hardening: clamp hook decision to downgrades only.
228
+ const clamped = clampHookDecision(classifierDecision, permHook.decision);
229
+ const decision = clamped.decision;
230
+ if (clamped.rejectedUpgrade) {
231
+ this.log.info("permission.hook_upgrade_rejected", {
232
+ cat: "permission",
233
+ tool: call.toolName,
234
+ site: "on_permission_check",
235
+ attempted: permHook.decision,
236
+ classifier: classifierDecision,
237
+ });
238
+ }
239
+ if (decision !== classifierDecision) {
240
+ this.log.info("permission.hook_override", {
241
+ cat: "permission",
242
+ tool: call.toolName,
243
+ from: classifierDecision,
244
+ to: decision,
245
+ });
246
+ }
247
+ if (decision === "deny") {
248
+ return {
249
+ id: call.id,
250
+ toolName: call.toolName,
251
+ error: `Permission denied for tool: ${call.toolName}`,
252
+ isError: true,
253
+ };
254
+ }
255
+ if (decision === "ask") {
256
+ const reason = permHook.messages?.join("\n");
257
+ const approved = await this.permission.handleAsk(call.toolName, call.args, reason);
258
+ if (!approved) {
259
+ return {
260
+ id: call.id,
261
+ toolName: call.toolName,
262
+ error: `Permission denied by user for tool: ${call.toolName}`,
263
+ isError: true,
264
+ };
265
+ }
266
+ }
267
+ }
268
+ // 2. Pre-tool hook
269
+ await this.hooks.emit("on_tool_start", {
270
+ toolName: call.toolName,
271
+ args: call.args,
272
+ toolCallId: call.id,
273
+ });
274
+ // 3. Execute. Use a span so begin/end share one cat and end carries
275
+ // duration_ms; widen args truncation from 200→2000 so Edit/Write payloads
276
+ // (file_path + a chunk of code) actually show what was changed instead of
277
+ // just the path. End-event also records a result snippet on failure for
278
+ // post-mortem without having to crack the full transcript.
279
+ const span = this.log.span("tool.exec", {
280
+ cat: "tool",
281
+ tool: call.toolName,
282
+ toolCallId: call.id,
283
+ args: JSON.stringify(call.args).slice(0, 2000),
284
+ });
285
+ const sid = getCurrentSid();
286
+ recordToolCall(sid, { id: call.id, toolName: call.toolName, args: call.args });
287
+ const toolStartedAt = Date.now();
288
+ let result;
289
+ try {
290
+ result = await this.registry.executeTool(call.toolName, call.args, {
291
+ signal: this.signal,
292
+ ctx: this.toolCtx,
293
+ });
294
+ }
295
+ catch (err) {
296
+ span.fail(err);
297
+ recordToolResult(sid, {
298
+ id: call.id,
299
+ toolName: call.toolName,
300
+ ok: false,
301
+ durationMs: Date.now() - toolStartedAt,
302
+ error: err instanceof Error ? err.stack ?? err.message : String(err),
303
+ });
304
+ throw err;
305
+ }
306
+ result.id = call.id;
307
+ // Prepend any non-blocking guard reminder onto a successful result so the
308
+ // model sees it on its next turn alongside the content it just fetched.
309
+ if (guardDecision?.prepend && !result.error && result.result) {
310
+ result.result = `${guardDecision.prepend}\n${result.result}`;
311
+ }
312
+ const payload = result.result ?? result.error ?? "";
313
+ span.end({
314
+ ok: !result.error,
315
+ chars: payload.length,
316
+ // Snippet only on failure — successful tool output can be huge and is
317
+ // already on the transcript. Failures are rare and the first 500 chars
318
+ // usually contain the message we need.
319
+ ...(result.error ? { errorSnippet: payload.slice(0, 500) } : {}),
320
+ });
321
+ recordToolResult(sid, {
322
+ id: call.id,
323
+ toolName: call.toolName,
324
+ ok: !result.error,
325
+ durationMs: Date.now() - toolStartedAt,
326
+ output: result.error ? undefined : result.result,
327
+ error: result.error,
328
+ });
329
+ // 4. Post-tool hook
330
+ await this.hooks.emit("on_tool_end", {
331
+ toolName: call.toolName,
332
+ toolCallId: call.id,
333
+ result: result.result,
334
+ error: result.error,
335
+ });
336
+ // 5. Post-tool-use hook (after execution, can observe/modify result)
337
+ const postHook = await this.hooks.emit("post_tool_use", {
338
+ toolName: call.toolName,
339
+ toolCallId: call.id,
340
+ result: result.result,
341
+ error: result.error,
342
+ });
343
+ // Append handler-supplied context (linter output, type-check result,
344
+ // etc.) onto the tool result so the model sees it on the next turn.
345
+ // Tagged with a separator so the model can tell hook output from
346
+ // tool output. Skip when the tool errored — additional context on a
347
+ // failed tool would be confusing.
348
+ if (postHook.additionalContext && !result.error) {
349
+ const tag = "--- additional context from post_tool_use hook ---";
350
+ result.result = result.result
351
+ ? `${result.result}\n\n${tag}\n${postHook.additionalContext}`
352
+ : `${tag}\n${postHook.additionalContext}`;
353
+ this.log.info("hook.additional_context", {
354
+ cat: "tool",
355
+ tool: call.toolName,
356
+ toolCallId: call.id,
357
+ chars: postHook.additionalContext.length,
358
+ });
359
+ }
360
+ // 6. file_changed hook for Write/Edit tools
361
+ if ((call.toolName === "Write" || call.toolName === "Edit") && !result.error) {
362
+ await this.hooks.emit("file_changed", {
363
+ toolName: call.toolName,
364
+ filePath: call.args.file_path,
365
+ });
366
+ }
367
+ return result;
368
+ }
369
+ isReadOnlyBashCommand(args) {
370
+ const cmd = String(args.command ?? "").trim();
371
+ // Reject shell metacharacters that could chain a write command after a
372
+ // read-only prefix: ; && || ` $(...) redirections. A single pipe (|) is
373
+ // still allowed — the per-part whitelist further down validates it.
374
+ const DANGEROUS = /;|&&|\|\||`|\$\(|>/;
375
+ if (DANGEROUS.test(cmd))
376
+ return false;
377
+ // Extract the base command (first word, ignoring env vars like VAR=val)
378
+ const baseCmd = cmd.replace(/^(\w+=\S+\s+)*/, "").split(/\s/)[0];
379
+ const readOnlyCommands = new Set([
380
+ "ls",
381
+ "find",
382
+ "cat",
383
+ "head",
384
+ "tail",
385
+ "wc",
386
+ "file",
387
+ "stat",
388
+ "tree",
389
+ "du",
390
+ "df",
391
+ "pwd",
392
+ "echo",
393
+ "which",
394
+ "type",
395
+ "env",
396
+ "printenv",
397
+ "grep",
398
+ "rg",
399
+ "ag",
400
+ "awk",
401
+ "less",
402
+ "more",
403
+ "sort",
404
+ "uniq",
405
+ "diff",
406
+ "readlink",
407
+ "realpath",
408
+ "basename",
409
+ "dirname",
410
+ "date",
411
+ "whoami",
412
+ "uname",
413
+ "hostname",
414
+ "id",
415
+ "groups",
416
+ "locale",
417
+ "uptime",
418
+ ]);
419
+ // Whitelisted read-only git/tool subcommands.
420
+ // Deliberately exclude `node -e`, `python -c`, `sed -n`, etc. — those can
421
+ // execute arbitrary code even though they "look read-only".
422
+ const readOnlyPrefixes = [
423
+ "git log",
424
+ "git status",
425
+ "git diff",
426
+ "git branch",
427
+ "git show",
428
+ "git blame",
429
+ "git remote",
430
+ "git tag",
431
+ "git stash list",
432
+ "git rev-parse",
433
+ "npx tsc --noEmit",
434
+ ];
435
+ if (readOnlyCommands.has(baseCmd))
436
+ return true;
437
+ if (readOnlyPrefixes.some((p) => cmd.startsWith(p)))
438
+ return true;
439
+ // Allow piped commands if all parts are read-only. Redirections were
440
+ // already rejected above, so a bare `|` here is a real pipeline.
441
+ if (cmd.includes("|")) {
442
+ const parts = cmd.split("|").map((p) => p.trim());
443
+ return parts.every((part) => {
444
+ const partBase = part.replace(/^(\w+=\S+\s+)*/, "").split(/\s/)[0];
445
+ return readOnlyCommands.has(partBase);
446
+ });
447
+ }
448
+ return false;
449
+ }
450
+ async executeAll(calls) {
451
+ const results = [];
452
+ // Separate safe (concurrent) and unsafe (sequential) tools
453
+ const safe = [];
454
+ const unsafe = [];
455
+ for (const call of calls) {
456
+ const tool = this.registry.getTool(call.toolName);
457
+ if (tool?.isConcurrencySafe) {
458
+ safe.push(call);
459
+ }
460
+ else {
461
+ unsafe.push(call);
462
+ }
463
+ }
464
+ // Execute safe tools concurrently
465
+ if (safe.length > 0) {
466
+ const safeResults = await Promise.all(safe.map((c) => this.executeSingle(c)));
467
+ results.push(...safeResults);
468
+ }
469
+ // Execute unsafe tools sequentially
470
+ for (const call of unsafe) {
471
+ const result = await this.executeSingle(call);
472
+ results.push(result);
473
+ }
474
+ return results;
475
+ }
476
+ /**
477
+ * Convert tool results into Message entries for the transcript.
478
+ */
479
+ resultsToMessages(toolCalls, results) {
480
+ const blocks = [];
481
+ for (const result of results) {
482
+ blocks.push({
483
+ type: "tool_result",
484
+ tool_use_id: result.id,
485
+ content: result.error ? `Error: ${result.error}` : (result.result ?? "(no output)"),
486
+ });
487
+ }
488
+ return [
489
+ {
490
+ role: "user",
491
+ content: blocks,
492
+ },
493
+ ];
494
+ }
495
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Investigation Guard — runtime enforcement of read budgets.
3
+ *
4
+ * Background: prompt rules in coding.md ("never re-read the same file",
5
+ * "after ~3 read-only calls, change strategy") describe a behavior the model
6
+ * frequently violates under context pressure. This module turns those soft
7
+ * rules into in-loop reminders/blocks delivered through tool results.
8
+ *
9
+ * Three independent counters share one guard instance per Engine:
10
+ * A) dedupe — same Read offset hit ≥2 times → reminder; ≥3 times → block
11
+ * B) read-budget — N consecutive read-only tools with no side-effecting
12
+ * tool in between → reminder on the next read
13
+ * C) silent turns — N consecutive turns of only read-only tools with no
14
+ * text output → injected into the *next* turn's user
15
+ * message by turn-loop (the guard just tracks state).
16
+ *
17
+ * Everything decays naturally on any write/Bash/AskUser tool (state reset).
18
+ */
19
+ import type { ToolCall, ToolResult } from "../types.js";
20
+ export interface GuardDecision {
21
+ block?: string;
22
+ prepend?: string;
23
+ }
24
+ export declare class InvestigationGuard {
25
+ private readHistory;
26
+ private consecutiveReads;
27
+ private silentTurns;
28
+ private turnHasText;
29
+ private turnHasSideEffect;
30
+ private lastReminderSilent;
31
+ /**
32
+ * Soft mode replaces hard blocks (3rd-read dedupe) with a stronger
33
+ * reminder. Used in headless runs (`code-shell run …`) where there is
34
+ * no human to retry the task, so an unattended automation should not
35
+ * be killed by the guard — it should still get the signal to change
36
+ * strategy, but the tool call goes through.
37
+ */
38
+ private softMode;
39
+ setSoftMode(soft: boolean): void;
40
+ preToolCheck(call: ToolCall): GuardDecision | undefined;
41
+ noteText(text: string | undefined): void;
42
+ noteToolResult(_call: ToolCall, _result: ToolResult): void;
43
+ turnEnded(turnNumber: number): string | undefined;
44
+ private isMutatingTool;
45
+ private buildKey;
46
+ }