@cleanslate/sdk 0.1.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 (581) hide show
  1. package/LICENSE +22 -0
  2. package/NOTICE +48 -0
  3. package/README.md +103 -0
  4. package/VENDOR.md +60 -0
  5. package/dist/agent/cleanSlateAgentExecutionPhase.d.ts +55 -0
  6. package/dist/agent/cleanSlateAgentExecutionPhase.d.ts.map +1 -0
  7. package/dist/agent/cleanSlateAgentExecutionPhase.js +474 -0
  8. package/dist/agent/cleanSlateAgentExecutionPhase.js.map +1 -0
  9. package/dist/agent/cleanSlateAgentExecutionSupport.d.ts +22 -0
  10. package/dist/agent/cleanSlateAgentExecutionSupport.d.ts.map +1 -0
  11. package/dist/agent/cleanSlateAgentExecutionSupport.js +205 -0
  12. package/dist/agent/cleanSlateAgentExecutionSupport.js.map +1 -0
  13. package/dist/agent/cleanSlateAgentParsing.d.ts +21 -0
  14. package/dist/agent/cleanSlateAgentParsing.d.ts.map +1 -0
  15. package/dist/agent/cleanSlateAgentParsing.js +106 -0
  16. package/dist/agent/cleanSlateAgentParsing.js.map +1 -0
  17. package/dist/agent/cleanSlateAgentSession.d.ts +44 -0
  18. package/dist/agent/cleanSlateAgentSession.d.ts.map +1 -0
  19. package/dist/agent/cleanSlateAgentSession.js +205 -0
  20. package/dist/agent/cleanSlateAgentSession.js.map +1 -0
  21. package/dist/agent/cleanSlateAgentTypes.d.ts +91 -0
  22. package/dist/agent/cleanSlateAgentTypes.d.ts.map +1 -0
  23. package/dist/agent/cleanSlateAgentTypes.js +27 -0
  24. package/dist/agent/cleanSlateAgentTypes.js.map +1 -0
  25. package/dist/agent/cleanSlateCommandPolicy.d.ts +12 -0
  26. package/dist/agent/cleanSlateCommandPolicy.d.ts.map +1 -0
  27. package/dist/agent/cleanSlateCommandPolicy.js +30 -0
  28. package/dist/agent/cleanSlateCommandPolicy.js.map +1 -0
  29. package/dist/agent/cleanSlateContextBudgetManager.d.ts +82 -0
  30. package/dist/agent/cleanSlateContextBudgetManager.d.ts.map +1 -0
  31. package/dist/agent/cleanSlateContextBudgetManager.js +419 -0
  32. package/dist/agent/cleanSlateContextBudgetManager.js.map +1 -0
  33. package/dist/agent/cleanSlateDomainProfile.d.ts +71 -0
  34. package/dist/agent/cleanSlateDomainProfile.d.ts.map +1 -0
  35. package/dist/agent/cleanSlateDomainProfile.js +124 -0
  36. package/dist/agent/cleanSlateDomainProfile.js.map +1 -0
  37. package/dist/agent/cleanSlateExecutionBudget.d.ts +19 -0
  38. package/dist/agent/cleanSlateExecutionBudget.d.ts.map +1 -0
  39. package/dist/agent/cleanSlateExecutionBudget.js +28 -0
  40. package/dist/agent/cleanSlateExecutionBudget.js.map +1 -0
  41. package/dist/agent/cleanSlateExecutionEditPolicy.d.ts +15 -0
  42. package/dist/agent/cleanSlateExecutionEditPolicy.d.ts.map +1 -0
  43. package/dist/agent/cleanSlateExecutionEditPolicy.js +148 -0
  44. package/dist/agent/cleanSlateExecutionEditPolicy.js.map +1 -0
  45. package/dist/agent/cleanSlateExecutionEvidenceLedger.d.ts +23 -0
  46. package/dist/agent/cleanSlateExecutionEvidenceLedger.d.ts.map +1 -0
  47. package/dist/agent/cleanSlateExecutionEvidenceLedger.js +121 -0
  48. package/dist/agent/cleanSlateExecutionEvidenceLedger.js.map +1 -0
  49. package/dist/agent/cleanSlateExecutionLoopPrompts.d.ts +5 -0
  50. package/dist/agent/cleanSlateExecutionLoopPrompts.d.ts.map +1 -0
  51. package/dist/agent/cleanSlateExecutionLoopPrompts.js +41 -0
  52. package/dist/agent/cleanSlateExecutionLoopPrompts.js.map +1 -0
  53. package/dist/agent/cleanSlateExecutionQuery.d.ts +162 -0
  54. package/dist/agent/cleanSlateExecutionQuery.d.ts.map +1 -0
  55. package/dist/agent/cleanSlateExecutionQuery.js +1448 -0
  56. package/dist/agent/cleanSlateExecutionQuery.js.map +1 -0
  57. package/dist/agent/cleanSlateFilesModifiedService.d.ts +96 -0
  58. package/dist/agent/cleanSlateFilesModifiedService.d.ts.map +1 -0
  59. package/dist/agent/cleanSlateFilesModifiedService.js +581 -0
  60. package/dist/agent/cleanSlateFilesModifiedService.js.map +1 -0
  61. package/dist/agent/cleanSlateNativeToolTranscript.d.ts +22 -0
  62. package/dist/agent/cleanSlateNativeToolTranscript.d.ts.map +1 -0
  63. package/dist/agent/cleanSlateNativeToolTranscript.js +77 -0
  64. package/dist/agent/cleanSlateNativeToolTranscript.js.map +1 -0
  65. package/dist/agent/cleanSlatePrompts.d.ts +30 -0
  66. package/dist/agent/cleanSlatePrompts.d.ts.map +1 -0
  67. package/dist/agent/cleanSlatePrompts.js +65 -0
  68. package/dist/agent/cleanSlatePrompts.js.map +1 -0
  69. package/dist/agent/cleanSlateQueryRunner.d.ts +56 -0
  70. package/dist/agent/cleanSlateQueryRunner.d.ts.map +1 -0
  71. package/dist/agent/cleanSlateQueryRunner.js +69 -0
  72. package/dist/agent/cleanSlateQueryRunner.js.map +1 -0
  73. package/dist/agent/cleanSlateRuntimePromptBuilder.d.ts +30 -0
  74. package/dist/agent/cleanSlateRuntimePromptBuilder.d.ts.map +1 -0
  75. package/dist/agent/cleanSlateRuntimePromptBuilder.js +99 -0
  76. package/dist/agent/cleanSlateRuntimePromptBuilder.js.map +1 -0
  77. package/dist/agent/cleanSlateStreamingToolExecutor.d.ts +55 -0
  78. package/dist/agent/cleanSlateStreamingToolExecutor.d.ts.map +1 -0
  79. package/dist/agent/cleanSlateStreamingToolExecutor.js +214 -0
  80. package/dist/agent/cleanSlateStreamingToolExecutor.js.map +1 -0
  81. package/dist/agent/cleanSlateToolCallLedger.d.ts +32 -0
  82. package/dist/agent/cleanSlateToolCallLedger.d.ts.map +1 -0
  83. package/dist/agent/cleanSlateToolCallLedger.js +164 -0
  84. package/dist/agent/cleanSlateToolCallLedger.js.map +1 -0
  85. package/dist/agent/cleanSlateToolResultPromptSerializer.d.ts +9 -0
  86. package/dist/agent/cleanSlateToolResultPromptSerializer.d.ts.map +1 -0
  87. package/dist/agent/cleanSlateToolResultPromptSerializer.js +184 -0
  88. package/dist/agent/cleanSlateToolResultPromptSerializer.js.map +1 -0
  89. package/dist/composer/commands/slashCommands.d.ts +8 -0
  90. package/dist/composer/commands/slashCommands.d.ts.map +1 -0
  91. package/dist/composer/commands/slashCommands.js +46 -0
  92. package/dist/composer/commands/slashCommands.js.map +1 -0
  93. package/dist/composer/instructions/baseInstructions.d.ts +3 -0
  94. package/dist/composer/instructions/baseInstructions.d.ts.map +1 -0
  95. package/dist/composer/instructions/baseInstructions.js +35 -0
  96. package/dist/composer/instructions/baseInstructions.js.map +1 -0
  97. package/dist/composer/instructions/runtimeInstructions.d.ts +11 -0
  98. package/dist/composer/instructions/runtimeInstructions.d.ts.map +1 -0
  99. package/dist/composer/instructions/runtimeInstructions.js +31 -0
  100. package/dist/composer/instructions/runtimeInstructions.js.map +1 -0
  101. package/dist/composer/kernel/coreKernel.d.ts +3 -0
  102. package/dist/composer/kernel/coreKernel.d.ts.map +1 -0
  103. package/dist/composer/kernel/coreKernel.js +11 -0
  104. package/dist/composer/kernel/coreKernel.js.map +1 -0
  105. package/dist/composer/kernel/editingRules.d.ts +3 -0
  106. package/dist/composer/kernel/editingRules.d.ts.map +1 -0
  107. package/dist/composer/kernel/editingRules.js +24 -0
  108. package/dist/composer/kernel/editingRules.js.map +1 -0
  109. package/dist/composer/kernel/toolProtocols.d.ts +2 -0
  110. package/dist/composer/kernel/toolProtocols.d.ts.map +1 -0
  111. package/dist/composer/kernel/toolProtocols.js +32 -0
  112. package/dist/composer/kernel/toolProtocols.js.map +1 -0
  113. package/dist/composer/modes/execution.mode.d.ts +2 -0
  114. package/dist/composer/modes/execution.mode.d.ts.map +1 -0
  115. package/dist/composer/modes/execution.mode.js +21 -0
  116. package/dist/composer/modes/execution.mode.js.map +1 -0
  117. package/dist/composer/modes/planning.mode.d.ts +2 -0
  118. package/dist/composer/modes/planning.mode.d.ts.map +1 -0
  119. package/dist/composer/modes/planning.mode.js +23 -0
  120. package/dist/composer/modes/planning.mode.js.map +1 -0
  121. package/dist/composer/promptComposer.d.ts +22 -0
  122. package/dist/composer/promptComposer.d.ts.map +1 -0
  123. package/dist/composer/promptComposer.js +62 -0
  124. package/dist/composer/promptComposer.js.map +1 -0
  125. package/dist/composer/registry/agentSchema.d.ts +16 -0
  126. package/dist/composer/registry/agentSchema.d.ts.map +1 -0
  127. package/dist/composer/registry/agentSchema.js +6 -0
  128. package/dist/composer/registry/agentSchema.js.map +1 -0
  129. package/dist/core/arrays.d.ts +311 -0
  130. package/dist/core/arrays.d.ts.map +1 -0
  131. package/dist/core/arrays.js +811 -0
  132. package/dist/core/arrays.js.map +1 -0
  133. package/dist/core/arraysFind.d.ts +72 -0
  134. package/dist/core/arraysFind.d.ts.map +1 -0
  135. package/dist/core/arraysFind.js +200 -0
  136. package/dist/core/arraysFind.js.map +1 -0
  137. package/dist/core/assert.d.ts +36 -0
  138. package/dist/core/assert.d.ts.map +1 -0
  139. package/dist/core/assert.js +84 -0
  140. package/dist/core/assert.js.map +1 -0
  141. package/dist/core/async.d.ts +11 -0
  142. package/dist/core/async.d.ts.map +1 -0
  143. package/dist/core/async.js +6 -0
  144. package/dist/core/async.js.map +1 -0
  145. package/dist/core/buffer.d.ts +23 -0
  146. package/dist/core/buffer.d.ts.map +1 -0
  147. package/dist/core/buffer.js +40 -0
  148. package/dist/core/buffer.js.map +1 -0
  149. package/dist/core/cancellation.d.ts +52 -0
  150. package/dist/core/cancellation.d.ts.map +1 -0
  151. package/dist/core/cancellation.js +169 -0
  152. package/dist/core/cancellation.js.map +1 -0
  153. package/dist/core/charCode.d.ts +428 -0
  154. package/dist/core/charCode.d.ts.map +1 -0
  155. package/dist/core/charCode.js +439 -0
  156. package/dist/core/charCode.js.map +1 -0
  157. package/dist/core/collections.d.ts +49 -0
  158. package/dist/core/collections.d.ts.map +1 -0
  159. package/dist/core/collections.js +132 -0
  160. package/dist/core/collections.js.map +1 -0
  161. package/dist/core/diff/diff.d.ts +151 -0
  162. package/dist/core/diff/diff.d.ts.map +1 -0
  163. package/dist/core/diff/diff.js +1076 -0
  164. package/dist/core/diff/diff.js.map +1 -0
  165. package/dist/core/diff/diffChange.d.ts +39 -0
  166. package/dist/core/diff/diffChange.d.ts.map +1 -0
  167. package/dist/core/diff/diffChange.js +37 -0
  168. package/dist/core/diff/diffChange.js.map +1 -0
  169. package/dist/core/errors.d.ts +114 -0
  170. package/dist/core/errors.d.ts.map +1 -0
  171. package/dist/core/errors.js +258 -0
  172. package/dist/core/errors.js.map +1 -0
  173. package/dist/core/event.d.ts +595 -0
  174. package/dist/core/event.d.ts.map +1 -0
  175. package/dist/core/event.js +1479 -0
  176. package/dist/core/event.js.map +1 -0
  177. package/dist/core/functional.d.ts +5 -0
  178. package/dist/core/functional.d.ts.map +1 -0
  179. package/dist/core/functional.js +35 -0
  180. package/dist/core/functional.js.map +1 -0
  181. package/dist/core/hash.d.ts +15 -0
  182. package/dist/core/hash.d.ts.map +1 -0
  183. package/dist/core/hash.js +27 -0
  184. package/dist/core/hash.js.map +1 -0
  185. package/dist/core/iterator.d.ts +33 -0
  186. package/dist/core/iterator.d.ts.map +1 -0
  187. package/dist/core/iterator.js +188 -0
  188. package/dist/core/iterator.js.map +1 -0
  189. package/dist/core/lifecycle.d.ts +313 -0
  190. package/dist/core/lifecycle.d.ts.map +1 -0
  191. package/dist/core/lifecycle.js +789 -0
  192. package/dist/core/lifecycle.js.map +1 -0
  193. package/dist/core/linkedList.d.ts +17 -0
  194. package/dist/core/linkedList.d.ts.map +1 -0
  195. package/dist/core/linkedList.js +138 -0
  196. package/dist/core/linkedList.js.map +1 -0
  197. package/dist/core/map.d.ts +175 -0
  198. package/dist/core/map.d.ts.map +1 -0
  199. package/dist/core/map.js +796 -0
  200. package/dist/core/map.js.map +1 -0
  201. package/dist/core/marshallingIds.d.ts +29 -0
  202. package/dist/core/marshallingIds.d.ts.map +1 -0
  203. package/dist/core/marshallingIds.js +38 -0
  204. package/dist/core/marshallingIds.js.map +1 -0
  205. package/dist/core/observable.d.ts +28 -0
  206. package/dist/core/observable.d.ts.map +1 -0
  207. package/dist/core/observable.js +6 -0
  208. package/dist/core/observable.js.map +1 -0
  209. package/dist/core/platform.d.ts +4 -0
  210. package/dist/core/platform.d.ts.map +1 -0
  211. package/dist/core/platform.js +17 -0
  212. package/dist/core/platform.js.map +1 -0
  213. package/dist/core/position.d.ts +91 -0
  214. package/dist/core/position.d.ts.map +1 -0
  215. package/dist/core/position.js +145 -0
  216. package/dist/core/position.js.map +1 -0
  217. package/dist/core/range.d.ts +198 -0
  218. package/dist/core/range.d.ts.map +1 -0
  219. package/dist/core/range.js +426 -0
  220. package/dist/core/range.js.map +1 -0
  221. package/dist/core/resources.d.ts +10 -0
  222. package/dist/core/resources.d.ts.map +1 -0
  223. package/dist/core/resources.js +126 -0
  224. package/dist/core/resources.js.map +1 -0
  225. package/dist/core/sequence.d.ts +20 -0
  226. package/dist/core/sequence.d.ts.map +1 -0
  227. package/dist/core/sequence.js +21 -0
  228. package/dist/core/sequence.js.map +1 -0
  229. package/dist/core/stopwatch.d.ts +11 -0
  230. package/dist/core/stopwatch.d.ts.map +1 -0
  231. package/dist/core/stopwatch.js +33 -0
  232. package/dist/core/stopwatch.js.map +1 -0
  233. package/dist/core/symbols.d.ts +5 -0
  234. package/dist/core/symbols.d.ts.map +1 -0
  235. package/dist/core/symbols.js +13 -0
  236. package/dist/core/symbols.js.map +1 -0
  237. package/dist/core/types.d.ts +229 -0
  238. package/dist/core/types.d.ts.map +1 -0
  239. package/dist/core/types.js +278 -0
  240. package/dist/core/types.js.map +1 -0
  241. package/dist/core/uint.d.ts +32 -0
  242. package/dist/core/uint.d.ts.map +1 -0
  243. package/dist/core/uint.js +57 -0
  244. package/dist/core/uint.js.map +1 -0
  245. package/dist/core/uri.d.ts +172 -0
  246. package/dist/core/uri.d.ts.map +1 -0
  247. package/dist/core/uri.js +623 -0
  248. package/dist/core/uri.js.map +1 -0
  249. package/dist/host/browserAutomation.d.ts +276 -0
  250. package/dist/host/browserAutomation.d.ts.map +1 -0
  251. package/dist/host/browserAutomation.js +6 -0
  252. package/dist/host/browserAutomation.js.map +1 -0
  253. package/dist/host/diagnostics.d.ts +68 -0
  254. package/dist/host/diagnostics.d.ts.map +1 -0
  255. package/dist/host/diagnostics.js +41 -0
  256. package/dist/host/diagnostics.js.map +1 -0
  257. package/dist/host/files.d.ts +70 -0
  258. package/dist/host/files.d.ts.map +1 -0
  259. package/dist/host/files.js +54 -0
  260. package/dist/host/files.js.map +1 -0
  261. package/dist/host/services.d.ts +106 -0
  262. package/dist/host/services.d.ts.map +1 -0
  263. package/dist/host/services.js +6 -0
  264. package/dist/host/services.js.map +1 -0
  265. package/dist/host/symbols.d.ts +45 -0
  266. package/dist/host/symbols.d.ts.map +1 -0
  267. package/dist/host/symbols.js +43 -0
  268. package/dist/host/symbols.js.map +1 -0
  269. package/dist/host/textModel.d.ts +83 -0
  270. package/dist/host/textModel.d.ts.map +1 -0
  271. package/dist/host/textModel.js +6 -0
  272. package/dist/host/textModel.js.map +1 -0
  273. package/dist/host/workspace.d.ts +123 -0
  274. package/dist/host/workspace.d.ts.map +1 -0
  275. package/dist/host/workspace.js +32 -0
  276. package/dist/host/workspace.js.map +1 -0
  277. package/dist/index.d.ts +40 -0
  278. package/dist/index.d.ts.map +1 -0
  279. package/dist/index.js +26 -0
  280. package/dist/index.js.map +1 -0
  281. package/dist/node/cleanSlateAnthropicMessageAdapter.d.ts +12 -0
  282. package/dist/node/cleanSlateAnthropicMessageAdapter.d.ts.map +1 -0
  283. package/dist/node/cleanSlateAnthropicMessageAdapter.js +130 -0
  284. package/dist/node/cleanSlateAnthropicMessageAdapter.js.map +1 -0
  285. package/dist/node/cleanSlateHeadlessRunner.d.ts +63 -0
  286. package/dist/node/cleanSlateHeadlessRunner.d.ts.map +1 -0
  287. package/dist/node/cleanSlateHeadlessRunner.js +84 -0
  288. package/dist/node/cleanSlateHeadlessRunner.js.map +1 -0
  289. package/dist/node/cleanSlateNodeAgentRuntime.d.ts +94 -0
  290. package/dist/node/cleanSlateNodeAgentRuntime.d.ts.map +1 -0
  291. package/dist/node/cleanSlateNodeAgentRuntime.js +339 -0
  292. package/dist/node/cleanSlateNodeAgentRuntime.js.map +1 -0
  293. package/dist/node/cleanSlateNodeBrowserAutomation.d.ts +279 -0
  294. package/dist/node/cleanSlateNodeBrowserAutomation.d.ts.map +1 -0
  295. package/dist/node/cleanSlateNodeBrowserAutomation.js +470 -0
  296. package/dist/node/cleanSlateNodeBrowserAutomation.js.map +1 -0
  297. package/dist/node/cleanSlateNodeCommandService.d.ts +40 -0
  298. package/dist/node/cleanSlateNodeCommandService.d.ts.map +1 -0
  299. package/dist/node/cleanSlateNodeCommandService.js +435 -0
  300. package/dist/node/cleanSlateNodeCommandService.js.map +1 -0
  301. package/dist/node/cleanSlateNodeFileServices.d.ts +68 -0
  302. package/dist/node/cleanSlateNodeFileServices.d.ts.map +1 -0
  303. package/dist/node/cleanSlateNodeFileServices.js +138 -0
  304. package/dist/node/cleanSlateNodeFileServices.js.map +1 -0
  305. package/dist/node/cleanSlateNodeIndexService.d.ts +17 -0
  306. package/dist/node/cleanSlateNodeIndexService.d.ts.map +1 -0
  307. package/dist/node/cleanSlateNodeIndexService.js +128 -0
  308. package/dist/node/cleanSlateNodeIndexService.js.map +1 -0
  309. package/dist/node/cleanSlateNodeLanguageCommands.d.ts +11 -0
  310. package/dist/node/cleanSlateNodeLanguageCommands.d.ts.map +1 -0
  311. package/dist/node/cleanSlateNodeLanguageCommands.js +146 -0
  312. package/dist/node/cleanSlateNodeLanguageCommands.js.map +1 -0
  313. package/dist/node/cleanSlateNodeMainService.d.ts +87 -0
  314. package/dist/node/cleanSlateNodeMainService.d.ts.map +1 -0
  315. package/dist/node/cleanSlateNodeMainService.js +1304 -0
  316. package/dist/node/cleanSlateNodeMainService.js.map +1 -0
  317. package/dist/node/cleanSlateNodeMcpClient.d.ts +20 -0
  318. package/dist/node/cleanSlateNodeMcpClient.d.ts.map +1 -0
  319. package/dist/node/cleanSlateNodeMcpClient.js +184 -0
  320. package/dist/node/cleanSlateNodeMcpClient.js.map +1 -0
  321. package/dist/node/cleanSlateNodeSearchService.d.ts +14 -0
  322. package/dist/node/cleanSlateNodeSearchService.d.ts.map +1 -0
  323. package/dist/node/cleanSlateNodeSearchService.js +180 -0
  324. package/dist/node/cleanSlateNodeSearchService.js.map +1 -0
  325. package/dist/node/cleanSlateNodeTextModel.d.ts +56 -0
  326. package/dist/node/cleanSlateNodeTextModel.d.ts.map +1 -0
  327. package/dist/node/cleanSlateNodeTextModel.js +127 -0
  328. package/dist/node/cleanSlateNodeTextModel.js.map +1 -0
  329. package/dist/node/cleanSlateNodeToolContext.d.ts +50 -0
  330. package/dist/node/cleanSlateNodeToolContext.d.ts.map +1 -0
  331. package/dist/node/cleanSlateNodeToolContext.js +134 -0
  332. package/dist/node/cleanSlateNodeToolContext.js.map +1 -0
  333. package/dist/node/cleanSlateNodeWebRetrieval.d.ts +20 -0
  334. package/dist/node/cleanSlateNodeWebRetrieval.d.ts.map +1 -0
  335. package/dist/node/cleanSlateNodeWebRetrieval.js +379 -0
  336. package/dist/node/cleanSlateNodeWebRetrieval.js.map +1 -0
  337. package/dist/node/cleanSlateOpenAIMessageAdapter.d.ts +8 -0
  338. package/dist/node/cleanSlateOpenAIMessageAdapter.d.ts.map +1 -0
  339. package/dist/node/cleanSlateOpenAIMessageAdapter.js +111 -0
  340. package/dist/node/cleanSlateOpenAIMessageAdapter.js.map +1 -0
  341. package/dist/node/cleanSlateProviderSchemaNormalizer.d.ts +18 -0
  342. package/dist/node/cleanSlateProviderSchemaNormalizer.d.ts.map +1 -0
  343. package/dist/node/cleanSlateProviderSchemaNormalizer.js +175 -0
  344. package/dist/node/cleanSlateProviderSchemaNormalizer.js.map +1 -0
  345. package/dist/node/index.d.ts +25 -0
  346. package/dist/node/index.d.ts.map +1 -0
  347. package/dist/node/index.js +28 -0
  348. package/dist/node/index.js.map +1 -0
  349. package/dist/protocol/cleanSlateAI.d.ts +964 -0
  350. package/dist/protocol/cleanSlateAI.d.ts.map +1 -0
  351. package/dist/protocol/cleanSlateAI.js +35 -0
  352. package/dist/protocol/cleanSlateAI.js.map +1 -0
  353. package/dist/protocol/cleanSlateModelCapabilities.d.ts +86 -0
  354. package/dist/protocol/cleanSlateModelCapabilities.d.ts.map +1 -0
  355. package/dist/protocol/cleanSlateModelCapabilities.js +1104 -0
  356. package/dist/protocol/cleanSlateModelCapabilities.js.map +1 -0
  357. package/dist/protocol/cleanSlateProviderMessageTransforms.d.ts +11 -0
  358. package/dist/protocol/cleanSlateProviderMessageTransforms.d.ts.map +1 -0
  359. package/dist/protocol/cleanSlateProviderMessageTransforms.js +178 -0
  360. package/dist/protocol/cleanSlateProviderMessageTransforms.js.map +1 -0
  361. package/dist/protocol/cleanSlateService.d.ts +68 -0
  362. package/dist/protocol/cleanSlateService.d.ts.map +1 -0
  363. package/dist/protocol/cleanSlateService.js +1149 -0
  364. package/dist/protocol/cleanSlateService.js.map +1 -0
  365. package/dist/services/cleanSlateCancellation.d.ts +7 -0
  366. package/dist/services/cleanSlateCancellation.d.ts.map +1 -0
  367. package/dist/services/cleanSlateCancellation.js +56 -0
  368. package/dist/services/cleanSlateCancellation.js.map +1 -0
  369. package/dist/services/cleanSlateCommandExecutionService.d.ts +25 -0
  370. package/dist/services/cleanSlateCommandExecutionService.d.ts.map +1 -0
  371. package/dist/services/cleanSlateCommandExecutionService.js +31 -0
  372. package/dist/services/cleanSlateCommandExecutionService.js.map +1 -0
  373. package/dist/services/cleanSlateDiffService.d.ts +62 -0
  374. package/dist/services/cleanSlateDiffService.d.ts.map +1 -0
  375. package/dist/services/cleanSlateDiffService.js +428 -0
  376. package/dist/services/cleanSlateDiffService.js.map +1 -0
  377. package/dist/services/cleanSlateEditMatchValidator.d.ts +63 -0
  378. package/dist/services/cleanSlateEditMatchValidator.d.ts.map +1 -0
  379. package/dist/services/cleanSlateEditMatchValidator.js +341 -0
  380. package/dist/services/cleanSlateEditMatchValidator.js.map +1 -0
  381. package/dist/services/cleanSlateEditService.d.ts +155 -0
  382. package/dist/services/cleanSlateEditService.d.ts.map +1 -0
  383. package/dist/services/cleanSlateEditService.js +848 -0
  384. package/dist/services/cleanSlateEditService.js.map +1 -0
  385. package/dist/services/cleanSlateFileHistory.d.ts +56 -0
  386. package/dist/services/cleanSlateFileHistory.d.ts.map +1 -0
  387. package/dist/services/cleanSlateFileHistory.js +157 -0
  388. package/dist/services/cleanSlateFileHistory.js.map +1 -0
  389. package/dist/services/cleanSlateTaskEvidenceCodec.d.ts +15 -0
  390. package/dist/services/cleanSlateTaskEvidenceCodec.d.ts.map +1 -0
  391. package/dist/services/cleanSlateTaskEvidenceCodec.js +151 -0
  392. package/dist/services/cleanSlateTaskEvidenceCodec.js.map +1 -0
  393. package/dist/services/cleanSlateTaskSessionService.d.ts +258 -0
  394. package/dist/services/cleanSlateTaskSessionService.d.ts.map +1 -0
  395. package/dist/services/cleanSlateTaskSessionService.js +1079 -0
  396. package/dist/services/cleanSlateTaskSessionService.js.map +1 -0
  397. package/dist/services/cleanSlateTaskState.d.ts +32 -0
  398. package/dist/services/cleanSlateTaskState.d.ts.map +1 -0
  399. package/dist/services/cleanSlateTaskState.js +40 -0
  400. package/dist/services/cleanSlateTaskState.js.map +1 -0
  401. package/dist/services/cleanSlateThreadService.d.ts +64 -0
  402. package/dist/services/cleanSlateThreadService.d.ts.map +1 -0
  403. package/dist/services/cleanSlateThreadService.js +188 -0
  404. package/dist/services/cleanSlateThreadService.js.map +1 -0
  405. package/dist/services/cleanSlateTools.d.ts +29 -0
  406. package/dist/services/cleanSlateTools.d.ts.map +1 -0
  407. package/dist/services/cleanSlateTools.js +38 -0
  408. package/dist/services/cleanSlateTools.js.map +1 -0
  409. package/dist/services/cleanSlateVerificationTargetTracker.d.ts +23 -0
  410. package/dist/services/cleanSlateVerificationTargetTracker.d.ts.map +1 -0
  411. package/dist/services/cleanSlateVerificationTargetTracker.js +214 -0
  412. package/dist/services/cleanSlateVerificationTargetTracker.js.map +1 -0
  413. package/dist/skills/cleanSlateSkillCatalog.d.ts +29 -0
  414. package/dist/skills/cleanSlateSkillCatalog.d.ts.map +1 -0
  415. package/dist/skills/cleanSlateSkillCatalog.js +225 -0
  416. package/dist/skills/cleanSlateSkillCatalog.js.map +1 -0
  417. package/dist/tools/ApplyEditTool.d.ts +73 -0
  418. package/dist/tools/ApplyEditTool.d.ts.map +1 -0
  419. package/dist/tools/ApplyEditTool.js +741 -0
  420. package/dist/tools/ApplyEditTool.js.map +1 -0
  421. package/dist/tools/AskQuestionTool.d.ts +3 -0
  422. package/dist/tools/AskQuestionTool.d.ts.map +1 -0
  423. package/dist/tools/AskQuestionTool.js +113 -0
  424. package/dist/tools/AskQuestionTool.js.map +1 -0
  425. package/dist/tools/BrowserAutomationTools.d.ts +28 -0
  426. package/dist/tools/BrowserAutomationTools.d.ts.map +1 -0
  427. package/dist/tools/BrowserAutomationTools.js +639 -0
  428. package/dist/tools/BrowserAutomationTools.js.map +1 -0
  429. package/dist/tools/CreateMultipleFilesTool.d.ts +6 -0
  430. package/dist/tools/CreateMultipleFilesTool.d.ts.map +1 -0
  431. package/dist/tools/CreateMultipleFilesTool.js +115 -0
  432. package/dist/tools/CreateMultipleFilesTool.js.map +1 -0
  433. package/dist/tools/ExecuteCommandTool.d.ts +12 -0
  434. package/dist/tools/ExecuteCommandTool.d.ts.map +1 -0
  435. package/dist/tools/ExecuteCommandTool.js +378 -0
  436. package/dist/tools/ExecuteCommandTool.js.map +1 -0
  437. package/dist/tools/FileHistoryRewindTool.d.ts +3 -0
  438. package/dist/tools/FileHistoryRewindTool.d.ts.map +1 -0
  439. package/dist/tools/FileHistoryRewindTool.js +45 -0
  440. package/dist/tools/FileHistoryRewindTool.js.map +1 -0
  441. package/dist/tools/FindByNameTool.d.ts +6 -0
  442. package/dist/tools/FindByNameTool.d.ts.map +1 -0
  443. package/dist/tools/FindByNameTool.js +80 -0
  444. package/dist/tools/FindByNameTool.js.map +1 -0
  445. package/dist/tools/FindReferencesTool.d.ts +3 -0
  446. package/dist/tools/FindReferencesTool.d.ts.map +1 -0
  447. package/dist/tools/FindReferencesTool.js +128 -0
  448. package/dist/tools/FindReferencesTool.js.map +1 -0
  449. package/dist/tools/GetDefinitionsTool.d.ts +3 -0
  450. package/dist/tools/GetDefinitionsTool.d.ts.map +1 -0
  451. package/dist/tools/GetDefinitionsTool.js +136 -0
  452. package/dist/tools/GetDefinitionsTool.js.map +1 -0
  453. package/dist/tools/GetOpenFilesTool.d.ts +6 -0
  454. package/dist/tools/GetOpenFilesTool.d.ts.map +1 -0
  455. package/dist/tools/GetOpenFilesTool.js +21 -0
  456. package/dist/tools/GetOpenFilesTool.js.map +1 -0
  457. package/dist/tools/GrepSearchTool.d.ts +7 -0
  458. package/dist/tools/GrepSearchTool.d.ts.map +1 -0
  459. package/dist/tools/GrepSearchTool.js +95 -0
  460. package/dist/tools/GrepSearchTool.js.map +1 -0
  461. package/dist/tools/ListDirTool.d.ts +6 -0
  462. package/dist/tools/ListDirTool.d.ts.map +1 -0
  463. package/dist/tools/ListDirTool.js +39 -0
  464. package/dist/tools/ListDirTool.js.map +1 -0
  465. package/dist/tools/MCPTools.d.ts +6 -0
  466. package/dist/tools/MCPTools.d.ts.map +1 -0
  467. package/dist/tools/MCPTools.js +103 -0
  468. package/dist/tools/MCPTools.js.map +1 -0
  469. package/dist/tools/MultiFileReplaceTool.d.ts +6 -0
  470. package/dist/tools/MultiFileReplaceTool.d.ts.map +1 -0
  471. package/dist/tools/MultiFileReplaceTool.js +345 -0
  472. package/dist/tools/MultiFileReplaceTool.js.map +1 -0
  473. package/dist/tools/ReadFileRangeTool.d.ts +6 -0
  474. package/dist/tools/ReadFileRangeTool.d.ts.map +1 -0
  475. package/dist/tools/ReadFileRangeTool.js +150 -0
  476. package/dist/tools/ReadFileRangeTool.js.map +1 -0
  477. package/dist/tools/ReadFileTool.d.ts +6 -0
  478. package/dist/tools/ReadFileTool.d.ts.map +1 -0
  479. package/dist/tools/ReadFileTool.js +183 -0
  480. package/dist/tools/ReadFileTool.js.map +1 -0
  481. package/dist/tools/ReadLintsTool.d.ts +6 -0
  482. package/dist/tools/ReadLintsTool.d.ts.map +1 -0
  483. package/dist/tools/ReadLintsTool.js +83 -0
  484. package/dist/tools/ReadLintsTool.js.map +1 -0
  485. package/dist/tools/ReadReferenceTool.d.ts +6 -0
  486. package/dist/tools/ReadReferenceTool.d.ts.map +1 -0
  487. package/dist/tools/ReadReferenceTool.js +24 -0
  488. package/dist/tools/ReadReferenceTool.js.map +1 -0
  489. package/dist/tools/ReadSymbolsTool.d.ts +3 -0
  490. package/dist/tools/ReadSymbolsTool.d.ts.map +1 -0
  491. package/dist/tools/ReadSymbolsTool.js +100 -0
  492. package/dist/tools/ReadSymbolsTool.js.map +1 -0
  493. package/dist/tools/SearchCodebaseTool.d.ts +6 -0
  494. package/dist/tools/SearchCodebaseTool.d.ts.map +1 -0
  495. package/dist/tools/SearchCodebaseTool.js +30 -0
  496. package/dist/tools/SearchCodebaseTool.js.map +1 -0
  497. package/dist/tools/SearchWorkspaceTool.d.ts +7 -0
  498. package/dist/tools/SearchWorkspaceTool.d.ts.map +1 -0
  499. package/dist/tools/SearchWorkspaceTool.js +21 -0
  500. package/dist/tools/SearchWorkspaceTool.js.map +1 -0
  501. package/dist/tools/SemanticSearchTool.d.ts +12 -0
  502. package/dist/tools/SemanticSearchTool.d.ts.map +1 -0
  503. package/dist/tools/SemanticSearchTool.js +46 -0
  504. package/dist/tools/SemanticSearchTool.js.map +1 -0
  505. package/dist/tools/SkillTools.d.ts +3 -0
  506. package/dist/tools/SkillTools.d.ts.map +1 -0
  507. package/dist/tools/SkillTools.js +108 -0
  508. package/dist/tools/SkillTools.js.map +1 -0
  509. package/dist/tools/SpawnWorkerTool.d.ts +6 -0
  510. package/dist/tools/SpawnWorkerTool.d.ts.map +1 -0
  511. package/dist/tools/SpawnWorkerTool.js +28 -0
  512. package/dist/tools/SpawnWorkerTool.js.map +1 -0
  513. package/dist/tools/SubmitArtifactTool.d.ts +3 -0
  514. package/dist/tools/SubmitArtifactTool.d.ts.map +1 -0
  515. package/dist/tools/SubmitArtifactTool.js +121 -0
  516. package/dist/tools/SubmitArtifactTool.js.map +1 -0
  517. package/dist/tools/UndoEditTool.d.ts +3 -0
  518. package/dist/tools/UndoEditTool.d.ts.map +1 -0
  519. package/dist/tools/UndoEditTool.js +66 -0
  520. package/dist/tools/UndoEditTool.js.map +1 -0
  521. package/dist/tools/UpdateTodoTool.d.ts +6 -0
  522. package/dist/tools/UpdateTodoTool.d.ts.map +1 -0
  523. package/dist/tools/UpdateTodoTool.js +116 -0
  524. package/dist/tools/UpdateTodoTool.js.map +1 -0
  525. package/dist/tools/WebRetrievalTools.d.ts +4 -0
  526. package/dist/tools/WebRetrievalTools.d.ts.map +1 -0
  527. package/dist/tools/WebRetrievalTools.js +169 -0
  528. package/dist/tools/WebRetrievalTools.js.map +1 -0
  529. package/dist/tools/WriteFileTool.d.ts +6 -0
  530. package/dist/tools/WriteFileTool.d.ts.map +1 -0
  531. package/dist/tools/WriteFileTool.js +145 -0
  532. package/dist/tools/WriteFileTool.js.map +1 -0
  533. package/dist/tools/cleanSlateFileReadPolicy.d.ts +33 -0
  534. package/dist/tools/cleanSlateFileReadPolicy.d.ts.map +1 -0
  535. package/dist/tools/cleanSlateFileReadPolicy.js +84 -0
  536. package/dist/tools/cleanSlateFileReadPolicy.js.map +1 -0
  537. package/dist/tools/cleanSlateHostTypes.d.ts +100 -0
  538. package/dist/tools/cleanSlateHostTypes.d.ts.map +1 -0
  539. package/dist/tools/cleanSlateHostTypes.js +6 -0
  540. package/dist/tools/cleanSlateHostTypes.js.map +1 -0
  541. package/dist/tools/cleanSlatePlanArtifactPolicy.d.ts +47 -0
  542. package/dist/tools/cleanSlatePlanArtifactPolicy.d.ts.map +1 -0
  543. package/dist/tools/cleanSlatePlanArtifactPolicy.js +126 -0
  544. package/dist/tools/cleanSlatePlanArtifactPolicy.js.map +1 -0
  545. package/dist/tools/cleanSlateStaleDiagnosticPolicy.d.ts +3 -0
  546. package/dist/tools/cleanSlateStaleDiagnosticPolicy.d.ts.map +1 -0
  547. package/dist/tools/cleanSlateStaleDiagnosticPolicy.js +13 -0
  548. package/dist/tools/cleanSlateStaleDiagnosticPolicy.js.map +1 -0
  549. package/dist/tools/languageFeatureActivation.d.ts +13 -0
  550. package/dist/tools/languageFeatureActivation.d.ts.map +1 -0
  551. package/dist/tools/languageFeatureActivation.js +95 -0
  552. package/dist/tools/languageFeatureActivation.js.map +1 -0
  553. package/dist/tools/registry.d.ts +5 -0
  554. package/dist/tools/registry.d.ts.map +1 -0
  555. package/dist/tools/registry.js +104 -0
  556. package/dist/tools/registry.js.map +1 -0
  557. package/dist/tools/structuredEditCanonicalizer.d.ts +11 -0
  558. package/dist/tools/structuredEditCanonicalizer.d.ts.map +1 -0
  559. package/dist/tools/structuredEditCanonicalizer.js +44 -0
  560. package/dist/tools/structuredEditCanonicalizer.js.map +1 -0
  561. package/dist/tools/symbolContext.d.ts +36 -0
  562. package/dist/tools/symbolContext.d.ts.map +1 -0
  563. package/dist/tools/symbolContext.js +146 -0
  564. package/dist/tools/symbolContext.js.map +1 -0
  565. package/dist/tools/symbolEditResolver.d.ts +11 -0
  566. package/dist/tools/symbolEditResolver.d.ts.map +1 -0
  567. package/dist/tools/symbolEditResolver.js +259 -0
  568. package/dist/tools/symbolEditResolver.js.map +1 -0
  569. package/dist/tools/symbolIndex.d.ts +18 -0
  570. package/dist/tools/symbolIndex.d.ts.map +1 -0
  571. package/dist/tools/symbolIndex.js +235 -0
  572. package/dist/tools/symbolIndex.js.map +1 -0
  573. package/dist/tools/types.d.ts +108 -0
  574. package/dist/tools/types.d.ts.map +1 -0
  575. package/dist/tools/types.js +6 -0
  576. package/dist/tools/types.js.map +1 -0
  577. package/dist/tools/utils.d.ts +56 -0
  578. package/dist/tools/utils.d.ts.map +1 -0
  579. package/dist/tools/utils.js +205 -0
  580. package/dist/tools/utils.js.map +1 -0
  581. package/package.json +71 -0
@@ -0,0 +1,1448 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) CleanSlate. All rights reserved.
3
+ * Licensed under the MIT License. See License.txt in the project root for license information.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import { CLEANSLATE_FALLBACK_CONTEXT_WINDOW_TOKENS } from '../protocol/cleanSlateAI.js';
6
+ import { AgentPhase } from './cleanSlatePrompts.js';
7
+ import { PHASE_CONCLUSION_SIGNAL_PLAN_CREATED } from './cleanSlateAgentTypes.js';
8
+ import { CleanSlateAgentExecutionPhase } from './cleanSlateAgentExecutionPhase.js';
9
+ import { CleanSlateExecutionEvidenceLedger } from './cleanSlateExecutionEvidenceLedger.js';
10
+ import { CleanSlateFilesModifiedService } from './cleanSlateFilesModifiedService.js';
11
+ import { ALL_TOOLS } from '../tools/registry.js';
12
+ import { serializeToolResultForPrompt } from './cleanSlateToolResultPromptSerializer.js';
13
+ import { CleanSlateNativeToolTranscript } from './cleanSlateNativeToolTranscript.js';
14
+ import { CleanSlateToolCallLedger } from './cleanSlateToolCallLedger.js';
15
+ import { CleanSlateContextBudgetManager } from './cleanSlateContextBudgetManager.js';
16
+ import { buildExecutionNoProgressStopMessage, buildExecutionNoToolRecoveryPrompt, buildSerializedToolCallRecoveryPrompt, detectSerializedToolCallSyntax } from './cleanSlateExecutionLoopPrompts.js';
17
+ import { CLEANSLATE_CODING_PROFILE } from './cleanSlateDomainProfile.js';
18
+ import { extractPlanFileEntries, planEntryTargetToPath } from '../tools/cleanSlatePlanArtifactPolicy.js';
19
+ import { evaluateExecutionCommandPolicy } from './cleanSlateCommandPolicy.js';
20
+ import { getWebResearchFinalAnswerPrompt } from './cleanSlateRuntimePromptBuilder.js';
21
+ import { CleanSlateStreamingToolExecutor } from './cleanSlateStreamingToolExecutor.js';
22
+ import { CleanSlateExecutionEditPolicy } from './cleanSlateExecutionEditPolicy.js';
23
+ import { cancellationTokenFromAbortSignal } from '../services/cleanSlateCancellation.js';
24
+ import { estimateCleanSlateFileReadTokens } from '../tools/cleanSlateFileReadPolicy.js';
25
+ export class CleanSlateExecutionQueryEngine {
26
+ /** The check the loop runs itself after mutations. */
27
+ get verificationToolName() {
28
+ return this.profile.deterministicVerificationTool ?? '';
29
+ }
30
+ static { this.DEFAULT_MODEL_TURN_INTERVAL_MS = 0; }
31
+ static { this.NORMAL_MODEL_TURN_INTERVAL_MS = 0; }
32
+ static { this.PLANNING_MODEL_TURN_INTERVAL_MS = 0; }
33
+ /** Summaries are brief continuation state, not another agent turn. */
34
+ static { this.COMPACTION_MAX_OUTPUT_TOKENS = 2_000; }
35
+ /** Stop retrying a failed automatic compaction instead of burning quota repeatedly. */
36
+ static { this.MAX_CONSECUTIVE_COMPACTION_FAILURES = 3; }
37
+ /** A summary must earn back meaningful context before another automatic summary is useful. */
38
+ static { this.AUTO_COMPACTION_REGROWTH_RATIO = 1.25; }
39
+ constructor(options) {
40
+ this.options = options;
41
+ /**
42
+ * Describes what the tools in play do to the workspace, so the loop can
43
+ * reason about mutation, verification and concurrency without knowing any
44
+ * individual tool by name.
45
+ */
46
+ this.profile = CLEANSLATE_CODING_PROFILE;
47
+ this.filesModifiedService = new CleanSlateFilesModifiedService();
48
+ this.nativeToolTranscript = new CleanSlateNativeToolTranscript('execution');
49
+ this.contextBudgetManager = new CleanSlateContextBudgetManager();
50
+ this.editPolicy = new CleanSlateExecutionEditPolicy();
51
+ this.consecutiveCompactionFailures = 0;
52
+ this.executionPhase = new CleanSlateAgentExecutionPhase(options);
53
+ }
54
+ getExecutionLoopSettings() {
55
+ return this.options.parsingSupport.getExecutionLoopSettings();
56
+ }
57
+ async *run(messages, originalUserMessage, uiMode, initialContext, mentionedFiles, activeThreadService, activeTaskSessionService, signal, runOptions = {}) {
58
+ const runPhase = runOptions.phase === AgentPhase.PLANNING ? AgentPhase.PLANNING : AgentPhase.EXECUTION;
59
+ const planMode = runPhase === AgentPhase.PLANNING;
60
+ const promptMode = planMode
61
+ ? (typeof uiMode === 'string' && uiMode.trim().length > 0 ? uiMode : 'Planning')
62
+ : 'Execution';
63
+ const logLabel = runOptions.logLabel || (planMode ? 'PLANNING' : 'EXECUTION');
64
+ const markCompletedOnFinish = !runOptions.stopOnPhaseTransition;
65
+ const queryState = {
66
+ objective: originalUserMessage,
67
+ planMode,
68
+ plannedFileTargets: planMode ? [] : this.extractPlannedFileTargets(messages),
69
+ turnCount: 1,
70
+ recoveryNoToolTurns: 0,
71
+ noToolTurns: 0
72
+ };
73
+ const persistedPendingRecovery = planMode ? undefined : activeTaskSessionService.getPendingRecovery();
74
+ if (persistedPendingRecovery?.prompt) {
75
+ queryState.pendingRecoveryPrompt = persistedPendingRecovery.prompt;
76
+ }
77
+ const nativeTools = this.getNativeToolDefinitions();
78
+ const settings = this.options.parsingSupport.getExecutionLoopSettings();
79
+ const executionFlow = runOptions.executionFlow || settings.executionFlow;
80
+ const toolCallLedger = new CleanSlateToolCallLedger({
81
+ availableToolNames: nativeTools.map(tool => tool.name),
82
+ validateToolCall: toolCall => this.executionPhase.validateToolCallForPhase(AgentPhase.EXECUTION, toolCall.toolName, toolCall.input)
83
+ });
84
+ const guardState = {
85
+ touchedPaths: new Set(),
86
+ mutatedPaths: new Set(),
87
+ pendingVerificationPaths: new Set(),
88
+ executionEvidenceLedger: new CleanSlateExecutionEvidenceLedger(),
89
+ mutationSummaries: [],
90
+ verificationSummaries: [],
91
+ terminalSummaries: [],
92
+ markerBaseline: this.options.executionSupport.createMarkerBaseline(settings.failOnWarnings),
93
+ currentTurnIndex: 1,
94
+ successfulToolResultsInPhase: 0,
95
+ successfulMutationsInPhase: 0,
96
+ failOnWarnings: settings.failOnWarnings,
97
+ postEditCommandVerified: false,
98
+ postEditCommandIssues: []
99
+ };
100
+ if (activeTaskSessionService.getPhase() !== runPhase) {
101
+ activeTaskSessionService.setPhase(runPhase);
102
+ }
103
+ while (true) {
104
+ if (signal?.aborted) {
105
+ break;
106
+ }
107
+ const budgetDecision = runOptions.executionBudget?.consumeModelTurn(runPhase);
108
+ if (budgetDecision && !budgetDecision.allowed) {
109
+ const stopMessage = budgetDecision.message;
110
+ yield { type: 'chat_text', content: stopMessage, kind: 'model_terminated_pause' };
111
+ activeThreadService.addMessage('assistant', stopMessage);
112
+ activeTaskSessionService.recordAssistantSummary(stopMessage);
113
+ return;
114
+ }
115
+ const visibleTurnIndex = queryState.turnCount;
116
+ guardState.currentTurnIndex = visibleTurnIndex;
117
+ toolCallLedger.beginTurn();
118
+ await this.waitForNextModelTurn(signal, executionFlow);
119
+ console.log(`[CleanSlateAgent] [${logLabel}] Starting query turn ${visibleTurnIndex}...`);
120
+ if (this.shouldRefreshContextForTurn(visibleTurnIndex)) {
121
+ await this.prepareContext({
122
+ messages,
123
+ objective: originalUserMessage,
124
+ mode: promptMode,
125
+ planMode,
126
+ initialContext,
127
+ mentionedFiles,
128
+ deferredSemanticContext: runOptions.deferredSemanticContext,
129
+ signal
130
+ });
131
+ }
132
+ const turnId = `${runPhase}-${visibleTurnIndex}`;
133
+ let currentResponse = '';
134
+ const streamedToolCalls = [];
135
+ const streamedToolCallKeys = new Set();
136
+ const yieldedStreamingExecutions = [];
137
+ let finishedDuringModelStream = false;
138
+ let concludedWithPlanSignal = false;
139
+ let completedBlockingToolDuringModelStream = false;
140
+ let nextToolIndex = 0;
141
+ const streamingToolExecutor = new CleanSlateStreamingToolExecutor({
142
+ isConcurrencySafe: toolCall => this.isParallelToolCall(toolCall),
143
+ executeTool: (toolCall, signal) => this.streamToolExecutionParts(toolCall, signal, queryState, guardState, executionFlow, toolCallLedger, activeTaskSessionService),
144
+ signal,
145
+ emitAbortedResults: true
146
+ });
147
+ const turnNativeTools = this.getNativeToolDefinitionsForTurn(nativeTools, queryState);
148
+ const pruneResult = this.contextBudgetManager.pruneOldToolOutputs(messages);
149
+ if (pruneResult.pruned) {
150
+ console.info(`[CleanSlateAgent] [${logLabel}] Proactively pruned old tool output before turn ${visibleTurnIndex}: ${pruneResult.beforeChars} -> ${pruneResult.afterChars} chars; reclaimed=${pruneResult.reclaimedChars}; toolResults=${pruneResult.compactedToolResults}; assistantTurns=${pruneResult.compactedAssistantTurns}.`);
151
+ }
152
+ const toolDefinitionChars = this.getToolDefinitionChars(turnNativeTools);
153
+ if (this.shouldAttemptConversationCompaction(messages, toolDefinitionChars)) {
154
+ yield { type: 'context_compaction_start', turnId };
155
+ const compacted = await this.compactMessagesBeforeProviderCall(messages, visibleTurnIndex, logLabel, toolDefinitionChars, signal);
156
+ yield { type: 'context_compaction_complete', turnId, compacted };
157
+ }
158
+ const providerMessages = this.buildMessagesForProvider(messages, visibleTurnIndex, logLabel, toolDefinitionChars);
159
+ const contextUsage = this.getEstimatedContextUsage(providerMessages, toolDefinitionChars);
160
+ yield { type: 'assistant_turn_start', phase: runPhase, turnId, turnIndex: visibleTurnIndex };
161
+ yield { type: 'context_usage', turnId, ...contextUsage };
162
+ this.refreshFileReadBudget(providerMessages, turnNativeTools);
163
+ const response = await this.options.cleanSlateService.chat(providerMessages, {
164
+ tools: turnNativeTools,
165
+ sessionId: this.options.getSessionId?.(),
166
+ cancellationToken: cancellationTokenFromAbortSignal(signal)
167
+ });
168
+ const responseIterator = response[Symbol.asyncIterator]();
169
+ let nextModelPart = responseIterator.next();
170
+ let nextToolEvent;
171
+ const collectToolEventParts = (event) => {
172
+ if (!event) {
173
+ return [];
174
+ }
175
+ if (event.type === 'parts') {
176
+ return event.batch.parts;
177
+ }
178
+ yieldedStreamingExecutions.push(event.execution);
179
+ if (!this.isParallelToolCall(event.execution.toolCall)) {
180
+ completedBlockingToolDuringModelStream = true;
181
+ }
182
+ return event.execution.parts;
183
+ };
184
+ while (!signal?.aborted) {
185
+ if (!nextToolEvent && streamingToolExecutor.hasUnfinishedWork()) {
186
+ nextToolEvent = streamingToolExecutor.nextEvent();
187
+ }
188
+ const next = await Promise.race([
189
+ nextModelPart.then(result => ({ type: 'model', result })),
190
+ ...(nextToolEvent ? [nextToolEvent.then(event => ({ type: 'tool', event }))] : [])
191
+ ]);
192
+ if (next.type === 'tool') {
193
+ nextToolEvent = undefined;
194
+ for (const executionPart of collectToolEventParts(next.event)) {
195
+ yield executionPart;
196
+ if (executionPart.type === 'task_complete' || (executionPart.type === 'tool_result' && executionPart.toolName === PHASE_CONCLUSION_SIGNAL_PLAN_CREATED)) {
197
+ finishedDuringModelStream = true;
198
+ concludedWithPlanSignal = concludedWithPlanSignal || (executionPart.type === 'tool_result' && executionPart.toolName === PHASE_CONCLUSION_SIGNAL_PLAN_CREATED);
199
+ }
200
+ }
201
+ if (finishedDuringModelStream || completedBlockingToolDuringModelStream) {
202
+ if (typeof responseIterator.return === 'function') {
203
+ await responseIterator.return();
204
+ }
205
+ break;
206
+ }
207
+ continue;
208
+ }
209
+ const modelResult = next.result;
210
+ if (modelResult.done) {
211
+ break;
212
+ }
213
+ const part = modelResult.value;
214
+ nextModelPart = responseIterator.next();
215
+ if (signal?.aborted) {
216
+ break;
217
+ }
218
+ if (part.type === 'transport_status') {
219
+ yield part;
220
+ }
221
+ else if (part.type === 'reasoning') {
222
+ yield { type: 'reasoning', content: part.content };
223
+ }
224
+ else if (part.type === 'text') {
225
+ currentResponse += part.content;
226
+ // Every normal text block renders, even when a tool call
227
+ // follows it. Phase is presentation metadata, never
228
+ // permission for the host to discard assistant text.
229
+ yield {
230
+ type: 'chat_text',
231
+ content: part.content,
232
+ kind: part.phase === 'commentary'
233
+ ? 'commentary'
234
+ : part.phase === 'final_answer' ? 'final_answer' : 'assistant'
235
+ };
236
+ }
237
+ else if (part.type === 'tool_call') {
238
+ const streamedToolCall = this.parseStreamedToolCall(part.call, toolCallLedger);
239
+ if (streamedToolCall) {
240
+ const key = toolCallLedger.getTurnKey(streamedToolCall);
241
+ if (!streamedToolCallKeys.has(key) && toolCallLedger.shouldAcceptInCurrentTurn(streamedToolCall)) {
242
+ streamedToolCallKeys.add(key);
243
+ streamedToolCalls.push(streamedToolCall);
244
+ streamingToolExecutor.addTool(streamedToolCall, nextToolIndex++);
245
+ }
246
+ }
247
+ }
248
+ if (finishedDuringModelStream) {
249
+ break;
250
+ }
251
+ }
252
+ if (!finishedDuringModelStream && nextToolEvent) {
253
+ for (const executionPart of collectToolEventParts(await nextToolEvent)) {
254
+ yield executionPart;
255
+ if (executionPart.type === 'task_complete' || (executionPart.type === 'tool_result' && executionPart.toolName === PHASE_CONCLUSION_SIGNAL_PLAN_CREATED)) {
256
+ finishedDuringModelStream = true;
257
+ concludedWithPlanSignal = concludedWithPlanSignal || (executionPart.type === 'tool_result' && executionPart.toolName === PHASE_CONCLUSION_SIGNAL_PLAN_CREATED);
258
+ }
259
+ }
260
+ }
261
+ yield { type: 'assistant_turn_complete', phase: runPhase, turnId, turnIndex: visibleTurnIndex };
262
+ this.recordModelTurnCompleted();
263
+ if (finishedDuringModelStream) {
264
+ if (markCompletedOnFinish && !concludedWithPlanSignal) {
265
+ activeTaskSessionService.markCompleted();
266
+ }
267
+ return;
268
+ }
269
+ const assistantTurn = this.parseAssistantTurn(currentResponse);
270
+ const toolCalls = this.mergeToolCalls(assistantTurn.toolCalls, streamedToolCalls);
271
+ for (const toolCall of assistantTurn.toolCalls) {
272
+ const normalizedToolCall = toolCallLedger.normalizeToolCall(toolCall);
273
+ const key = toolCallLedger.getTurnKey(normalizedToolCall);
274
+ if (streamedToolCallKeys.has(key)) {
275
+ continue;
276
+ }
277
+ if (!toolCallLedger.shouldAcceptInCurrentTurn(normalizedToolCall)) {
278
+ continue;
279
+ }
280
+ streamingToolExecutor.addTool(normalizedToolCall, nextToolIndex++);
281
+ }
282
+ const assistantMemoryContent = () => this.options.parsingSupport.buildLoopAssistantMemory(currentResponse, runPhase, assistantTurn.toDoList, toolCalls);
283
+ if (toolCalls.length > 0) {
284
+ queryState.noToolTurns = 0;
285
+ messages.push(this.nativeToolTranscript.buildAssistantToolCallMessage(assistantMemoryContent(), toolCalls));
286
+ let shouldRestartAfterMutation = false;
287
+ let sawConfirmedMutation = false;
288
+ let sawUserCancelledCommand = false;
289
+ let sawToolCallLoop = false;
290
+ const recoveryPrompts = [];
291
+ for (const execution of yieldedStreamingExecutions) {
292
+ if (this.pauseForQuestion(execution.toolCall, execution.result, activeTaskSessionService)) {
293
+ return;
294
+ }
295
+ messages.push(this.nativeToolTranscript.buildToolResultMessage(execution.toolCall, execution.result));
296
+ if (this.editPolicy.isUserCancelledCommandResult(execution.toolCall, execution.result)) {
297
+ sawUserCancelledCommand = true;
298
+ }
299
+ if (this.isToolCallLoopResult(execution.result)) {
300
+ sawToolCallLoop = true;
301
+ }
302
+ if (this.shouldVerifyAfterToolResult(execution.toolCall, execution.result)) {
303
+ shouldRestartAfterMutation = true;
304
+ sawConfirmedMutation = true;
305
+ }
306
+ const recoveryPrompt = this.editPolicy.buildFailedEditRecoveryPrompt(execution.toolCall, execution.result);
307
+ if (recoveryPrompt) {
308
+ recoveryPrompts.push(recoveryPrompt);
309
+ }
310
+ }
311
+ for await (const event of streamingToolExecutor.getRemainingEvents()) {
312
+ if (event.type === 'parts') {
313
+ for (const part of event.batch.parts) {
314
+ yield part;
315
+ if (part.type === 'tool_result' && part.toolName === PHASE_CONCLUSION_SIGNAL_PLAN_CREATED) {
316
+ return;
317
+ }
318
+ if (part.type === 'task_complete') {
319
+ if (markCompletedOnFinish) {
320
+ activeTaskSessionService.markCompleted();
321
+ }
322
+ return;
323
+ }
324
+ if (part.type === 'tool_result' && this.pauseForQuestion(event.batch.toolCall, part.result, activeTaskSessionService)) {
325
+ return;
326
+ }
327
+ }
328
+ }
329
+ else {
330
+ const execution = event.execution;
331
+ for (const part of execution.parts) {
332
+ yield part;
333
+ if (part.type === 'tool_result' && part.toolName === PHASE_CONCLUSION_SIGNAL_PLAN_CREATED) {
334
+ return;
335
+ }
336
+ if (part.type === 'task_complete') {
337
+ if (markCompletedOnFinish) {
338
+ activeTaskSessionService.markCompleted();
339
+ }
340
+ return;
341
+ }
342
+ }
343
+ if (this.pauseForQuestion(execution.toolCall, execution.result, activeTaskSessionService)) {
344
+ return;
345
+ }
346
+ messages.push(this.nativeToolTranscript.buildToolResultMessage(execution.toolCall, execution.result));
347
+ if (this.editPolicy.isUserCancelledCommandResult(execution.toolCall, execution.result)) {
348
+ sawUserCancelledCommand = true;
349
+ }
350
+ if (this.isToolCallLoopResult(execution.result)) {
351
+ sawToolCallLoop = true;
352
+ }
353
+ if (this.shouldVerifyAfterToolResult(execution.toolCall, execution.result)) {
354
+ shouldRestartAfterMutation = true;
355
+ sawConfirmedMutation = true;
356
+ }
357
+ const recoveryPrompt = this.editPolicy.buildFailedEditRecoveryPrompt(execution.toolCall, execution.result);
358
+ if (recoveryPrompt) {
359
+ recoveryPrompts.push(recoveryPrompt);
360
+ }
361
+ }
362
+ }
363
+ if (sawUserCancelledCommand) {
364
+ const stopMessage = 'Command cancelled. I will not run it again unless you explicitly ask me to.';
365
+ activeTaskSessionService.markCancelled();
366
+ yield { type: 'chat_text', content: stopMessage };
367
+ yield { type: 'assistant_turn_complete', phase: runPhase, turnId, turnIndex: visibleTurnIndex };
368
+ activeThreadService.addMessage('assistant', stopMessage);
369
+ activeTaskSessionService.recordAssistantSummary(stopMessage);
370
+ return;
371
+ }
372
+ if (sawToolCallLoop) {
373
+ const stopMessage = 'Paused after the same tool call was repeated three times. Change the tool or its arguments before continuing; the workspace was not declared complete.';
374
+ yield { type: 'chat_text', content: stopMessage, kind: 'model_terminated_pause' };
375
+ activeThreadService.addMessage('assistant', stopMessage);
376
+ activeTaskSessionService.recordAssistantSummary(stopMessage);
377
+ return;
378
+ }
379
+ if (shouldRestartAfterMutation) {
380
+ if (sawConfirmedMutation && recoveryPrompts.length === 0) {
381
+ queryState.pendingRecoveryPrompt = undefined;
382
+ queryState.recoveryNoToolTurns = 0;
383
+ activeTaskSessionService.clearPendingRecovery();
384
+ }
385
+ const verificationResult = yield* this.streamPostMutationVerificationParts(signal, guardState);
386
+ if (verificationResult.result) {
387
+ messages.push({
388
+ role: 'system',
389
+ content: `Deterministic ${this.verificationToolName} verification result:\n${serializeToolResultForPrompt(this.verificationToolName, verificationResult.result)}`
390
+ });
391
+ }
392
+ const verificationFailed = verificationResult.result?.success === false;
393
+ const verificationIssues = verificationFailed
394
+ ? [String(verificationResult.result?.message ?? verificationResult.result?.error ?? 'read_lints failed.')]
395
+ : verificationResult.issues;
396
+ guardState.postEditCommandVerified = verificationIssues.length === 0;
397
+ guardState.postEditCommandIssues = verificationIssues;
398
+ if (verificationIssues.length > 0) {
399
+ messages.push({
400
+ role: 'system',
401
+ content: this.buildPostMutationVerificationPrompt(verificationIssues)
402
+ });
403
+ }
404
+ else if (recoveryPrompts.length === 0 && !queryState.pendingRecoveryPrompt) {
405
+ const finalVerificationScope = guardState.mutatedPaths.size > 0
406
+ ? guardState.mutatedPaths
407
+ : guardState.touchedPaths;
408
+ const finalIssues = await this.options.executionSupport.collectNewMarkerIssues(guardState.markerBaseline, finalVerificationScope, guardState.failOnWarnings, 40);
409
+ if (finalIssues.length === 0) {
410
+ messages.push({
411
+ role: 'system',
412
+ content: this.buildVerifiedFinishPrompt(guardState)
413
+ });
414
+ }
415
+ else {
416
+ guardState.postEditCommandVerified = false;
417
+ guardState.postEditCommandIssues = finalIssues;
418
+ messages.push({
419
+ role: 'system',
420
+ content: this.buildPostMutationVerificationPrompt(finalIssues)
421
+ });
422
+ }
423
+ }
424
+ // No re-read demand after mutations:
425
+ // apply_edit updates the host read-state with post-write
426
+ // content, and string anchors resolve against current
427
+ // content — the model's own edits never go stale on it.
428
+ }
429
+ if (recoveryPrompts.length > 0) {
430
+ for (const recoveryPrompt of recoveryPrompts) {
431
+ this.appendPendingRecoveryPrompt(queryState, recoveryPrompt);
432
+ }
433
+ activeTaskSessionService.setPendingRecovery(queryState.pendingRecoveryPrompt, { toolName: this.profile.recoveryMutationTool ?? '', code: 'recovery_required' });
434
+ messages.push({
435
+ role: 'system',
436
+ content: queryState.pendingRecoveryPrompt ?? recoveryPrompts.join('\n\n')
437
+ });
438
+ }
439
+ else if (sawConfirmedMutation) {
440
+ queryState.pendingRecoveryPrompt = undefined;
441
+ queryState.recoveryNoToolTurns = 0;
442
+ activeTaskSessionService.clearPendingRecovery();
443
+ }
444
+ queryState.turnCount++;
445
+ continue;
446
+ }
447
+ if (planMode) {
448
+ // Plan-mode stop semantics: a turn with no tool calls means the
449
+ // model stopped to talk to the user — a clarifying question, an
450
+ // intermediate report, or an answer. The turn simply ends; none
451
+ // of the execution completion machinery below applies in plan
452
+ // mode.
453
+ if (currentResponse.trim().length > 0) {
454
+ messages.push({ role: 'assistant', content: currentResponse });
455
+ activeThreadService.addMessage('assistant', currentResponse);
456
+ activeTaskSessionService.recordAssistantTurn(currentResponse);
457
+ return;
458
+ }
459
+ // A truly empty response falls through to the generic
460
+ // no-tool retry nudge — that is transport-glitch recovery,
461
+ // not completion pressure.
462
+ }
463
+ // Stop semantics:
464
+ // tool calls keep the loop alive; a non-empty assistant response
465
+ // with no tool call is the final model turn. Completion itself is
466
+ // a host lifecycle event, never a model-facing tool call.
467
+ if (!planMode && await this.canHostFinalizeProseStop(currentResponse, queryState, guardState)) {
468
+ if (markCompletedOnFinish) {
469
+ activeTaskSessionService.markCompleted();
470
+ }
471
+ messages.push({ role: 'assistant', content: currentResponse });
472
+ yield {
473
+ type: 'task_complete',
474
+ result: {
475
+ phase: AgentPhase.EXECUTION,
476
+ executionFlow,
477
+ verified: true,
478
+ completionSource: 'host_finalized',
479
+ completionState: this.buildCompletionState(guardState, currentResponse, queryState.plannedFileTargets)
480
+ }
481
+ };
482
+ return;
483
+ }
484
+ if (!planMode && currentResponse.trim().length > 0) {
485
+ messages.push({ role: 'assistant', content: currentResponse });
486
+ activeThreadService.addMessage('assistant', currentResponse);
487
+ activeTaskSessionService.recordAssistantTurn(currentResponse);
488
+ activeTaskSessionService.recordAssistantSummary(currentResponse);
489
+ activeTaskSessionService.markInterrupted();
490
+ return;
491
+ }
492
+ if (queryState.pendingRecoveryPrompt) {
493
+ queryState.recoveryNoToolTurns++;
494
+ const recoveryNudge = [
495
+ 'RECOVERY STILL REQUIRED: the previous edit failed and no recovery tool call was returned.',
496
+ queryState.pendingRecoveryPrompt,
497
+ 'Return corrected tool_calls only. Re-read only if the result reports stale content or you need more current context, then retry apply_edit with file_path, a corrected unique old_string, and new_string. Do not return a final answer until the failed edit is fixed or verified unnecessary.'
498
+ ].join('\n\n');
499
+ activeThreadService.addMessage('assistant', assistantMemoryContent(), true);
500
+ messages.push({ role: 'assistant', content: assistantMemoryContent() });
501
+ messages.push({ role: 'system', content: recoveryNudge });
502
+ if (queryState.recoveryNoToolTurns >= 4) {
503
+ const stopMessage = 'Paused execution after repeated edit-failure recovery turns returned no tool calls. The workspace was not declared complete.';
504
+ yield { type: 'chat_text', content: stopMessage, kind: 'model_terminated_pause' };
505
+ activeThreadService.addMessage('assistant', stopMessage);
506
+ activeTaskSessionService.recordAssistantSummary(stopMessage);
507
+ return;
508
+ }
509
+ queryState.turnCount++;
510
+ continue;
511
+ }
512
+ queryState.noToolTurns++;
513
+ const maxNoToolTurns = this.getNoProgressTurnLimit(AgentPhase.EXECUTION, settings.maxNoToolTurns, {
514
+ hasPhaseProgress: guardState.successfulToolResultsInPhase > 0,
515
+ hasAssistantOutput: currentResponse.trim().length > 0
516
+ });
517
+ const noToolStopLimit = executionFlow === 'normal'
518
+ ? maxNoToolTurns
519
+ : Math.max(maxNoToolTurns, 3);
520
+ if (queryState.noToolTurns >= noToolStopLimit) {
521
+ const stopMessage = this.buildNoProgressStopMessage(queryState.noToolTurns, 'the provider returned neither an executable tool call nor a final assistant answer');
522
+ yield { type: 'chat_text', content: stopMessage, kind: 'model_terminated_pause' };
523
+ activeThreadService.addMessage('assistant', stopMessage);
524
+ activeTaskSessionService.recordAssistantSummary(stopMessage);
525
+ return;
526
+ }
527
+ // A turn that serialized tool syntax into text is a specific failure
528
+ // with a specific correction — the generic "return tool calls"
529
+ // nudge leaves the model believing its call ran.
530
+ const noToolPrompt = detectSerializedToolCallSyntax(currentResponse)
531
+ ? buildSerializedToolCallRecoveryPrompt()
532
+ : this.buildNoToolRecoveryPrompt(guardState.successfulToolResultsInPhase > 0);
533
+ messages.push({ role: 'assistant', content: assistantMemoryContent() });
534
+ messages.push({ role: 'system', content: noToolPrompt });
535
+ activeThreadService.addMessage('assistant', assistantMemoryContent(), true);
536
+ activeThreadService.addMessage('system', noToolPrompt, true);
537
+ queryState.turnCount++;
538
+ continue;
539
+ }
540
+ }
541
+ shouldPauseForQuestionResult(toolName, result, inputSummary, activeTaskSessionService) {
542
+ if (toolName !== this.profile.questionTool || result?.success === false || !result?.planning_question) {
543
+ return false;
544
+ }
545
+ const summary = typeof result?.summary === 'string' && result.summary.trim().length > 0
546
+ ? result.summary.trim()
547
+ : typeof inputSummary === 'string' && inputSummary.trim().length > 0
548
+ ? inputSummary.trim()
549
+ : undefined;
550
+ activeTaskSessionService.recordAssistantSummary(summary);
551
+ return true;
552
+ }
553
+ pauseForQuestion(toolCall, result, activeTaskSessionService) {
554
+ if (!this.shouldPauseForQuestionResult(toolCall.toolName, result, toolCall.input?.summary, activeTaskSessionService)) {
555
+ return false;
556
+ }
557
+ this.options.onQuestionPaused?.(toolCall, result);
558
+ return true;
559
+ }
560
+ async waitForNextModelTurn(signal, executionFlow) {
561
+ const now = Date.now();
562
+ if (this.lastModelTurnStartedAt === undefined) {
563
+ this.lastModelTurnStartedAt = now;
564
+ return;
565
+ }
566
+ const elapsedMs = now - this.lastModelTurnStartedAt;
567
+ const intervalMs = executionFlow === 'normal'
568
+ ? CleanSlateExecutionQueryEngine.NORMAL_MODEL_TURN_INTERVAL_MS
569
+ : executionFlow === 'planning'
570
+ ? CleanSlateExecutionQueryEngine.PLANNING_MODEL_TURN_INTERVAL_MS
571
+ : CleanSlateExecutionQueryEngine.DEFAULT_MODEL_TURN_INTERVAL_MS;
572
+ const waitMs = Math.max(0, intervalMs - elapsedMs);
573
+ if (waitMs > 0) {
574
+ await this.delay(waitMs, signal);
575
+ }
576
+ this.lastModelTurnStartedAt = Date.now();
577
+ }
578
+ recordModelTurnCompleted() {
579
+ // The native loop only needs a cadence boundary; waitForNextModelTurn tracks starts.
580
+ }
581
+ async compactMessagesBeforeProviderCall(messages, visibleTurnIndex, logLabel, promptOverheadChars, signal) {
582
+ const thresholdChars = this.getConversationMessageThresholdChars(promptOverheadChars);
583
+ if (!this.contextBudgetManager.shouldCompactMessages(messages, thresholdChars)) {
584
+ return false;
585
+ }
586
+ const keepStart = this.getCompactionKeepStart(messages);
587
+ if (keepStart <= 2) {
588
+ return false;
589
+ }
590
+ const beforeChars = this.contextBudgetManager.getMessagesCharCount(messages);
591
+ const compactedHistory = messages.slice(1, keepStart);
592
+ const previousSummary = compactedHistory.find(message => this.isCompactionSummaryMessage(message));
593
+ const preservedUserMessages = compactedHistory.filter(message => message.role === 'user');
594
+ const summaryPrompt = [
595
+ {
596
+ role: 'system',
597
+ content: [
598
+ previousSummary
599
+ ? 'Update the prior continuation summary with the newer conversation history.'
600
+ : 'Create a continuation summary for the older portion of this coding-agent conversation.',
601
+ 'Use exactly these terse Markdown sections: Goal; Constraints & Preferences; Progress (Done, In Progress, Blocked); Key Decisions; Next Steps; Critical Context; Relevant Files.',
602
+ 'Preserve exact file paths, symbols, commands, error strings, edits, test outcomes, unresolved work, and unanswered user questions. Do not invent facts.',
603
+ 'Completed tool calls already ran. Record their durable outcomes so the agent does not repeat work blindly.',
604
+ previousSummary ? `Prior summary to update:\n${this.messageContentToText(previousSummary)}` : ''
605
+ ].join('\n')
606
+ },
607
+ ...compactedHistory.filter(message => !this.isCompactionSummaryMessage(message))
608
+ ];
609
+ const summaryBudget = Math.max(12_000, thresholdChars);
610
+ const projected = this.contextBudgetManager.projectMessagesForProvider(summaryPrompt, summaryBudget).messages;
611
+ try {
612
+ const response = await this.options.cleanSlateService.chat(projected, {
613
+ cancellationToken: cancellationTokenFromAbortSignal(signal),
614
+ maxOutputTokens: CleanSlateExecutionQueryEngine.COMPACTION_MAX_OUTPUT_TOKENS
615
+ });
616
+ let summary = '';
617
+ for await (const part of response) {
618
+ if (part.type === 'text') {
619
+ summary += part.content;
620
+ }
621
+ }
622
+ const normalizedSummary = summary.trim();
623
+ if (!normalizedSummary || signal?.aborted) {
624
+ if (!signal?.aborted) {
625
+ this.consecutiveCompactionFailures++;
626
+ }
627
+ return false;
628
+ }
629
+ // Replacement-history behavior: keep actual user turns intact and
630
+ // replace only older model/tool transcript with one summary.
631
+ // Recent messages (including the latest tool groups) remain untouched.
632
+ messages.splice(1, keepStart - 1, ...preservedUserMessages, {
633
+ role: 'system',
634
+ content: `[COMPACTED CONVERSATION SUMMARY]\n${normalizedSummary}`
635
+ });
636
+ this.consecutiveCompactionFailures = 0;
637
+ const afterChars = this.contextBudgetManager.getMessagesCharCount(messages);
638
+ this.lastSuccessfulCompactionChars = afterChars;
639
+ console.info(`[CleanSlateAgent] [${logLabel}] Model-compacted conversation before turn ${visibleTurnIndex}: ${beforeChars} -> ${afterChars} chars; threshold=${thresholdChars}.`);
640
+ return true;
641
+ }
642
+ catch (error) {
643
+ this.consecutiveCompactionFailures++;
644
+ if (!signal?.aborted) {
645
+ console.warn('[CleanSlateAgent] Conversation compaction failed; using a non-mutating provider projection for this turn.', error);
646
+ }
647
+ return false;
648
+ }
649
+ }
650
+ shouldAttemptConversationCompaction(messages, promptOverheadChars) {
651
+ if (this.consecutiveCompactionFailures >= CleanSlateExecutionQueryEngine.MAX_CONSECUTIVE_COMPACTION_FAILURES) {
652
+ return false;
653
+ }
654
+ const currentChars = this.contextBudgetManager.getMessagesCharCount(messages);
655
+ if (this.lastSuccessfulCompactionChars !== undefined
656
+ && currentChars < Math.ceil(this.lastSuccessfulCompactionChars * CleanSlateExecutionQueryEngine.AUTO_COMPACTION_REGROWTH_RATIO)) {
657
+ return false;
658
+ }
659
+ return this.contextBudgetManager.shouldCompactMessages(messages, this.getConversationMessageThresholdChars(promptOverheadChars)) && this.getCompactionKeepStart(messages) > 2;
660
+ }
661
+ getConversationMessageThresholdChars(promptOverheadChars) {
662
+ return Math.max(12_000, this.options.parsingSupport.getExecutionAutoCompactThresholdChars() - Math.max(0, promptOverheadChars));
663
+ }
664
+ isCompactionSummaryMessage(message) {
665
+ return message.role === 'system'
666
+ && this.messageContentToText(message).startsWith('[COMPACTED CONVERSATION SUMMARY]');
667
+ }
668
+ messageContentToText(message) {
669
+ return typeof message.content === 'string'
670
+ ? message.content
671
+ : message.content.map(part => part.type === 'text' ? part.text ?? '' : '').join('\n');
672
+ }
673
+ getCompactionKeepStart(messages) {
674
+ let keepStart = Math.max(1, messages.length - 18);
675
+ while (keepStart > 1 && messages[keepStart]?.role === 'tool') {
676
+ keepStart--;
677
+ }
678
+ return keepStart;
679
+ }
680
+ buildMessagesForProvider(messages, visibleTurnIndex, logLabel, promptOverheadChars) {
681
+ const budgetChars = Math.max(12_000, this.options.parsingSupport.getExecutionContextBudgetChars() - Math.max(0, promptOverheadChars));
682
+ const projection = this.contextBudgetManager.projectMessagesForProvider(messages, budgetChars);
683
+ if (projection.result.compacted) {
684
+ console.debug(`[CleanSlateAgent] [${logLabel}] Context budget projected for turn ${visibleTurnIndex}: ${projection.result.beforeChars} -> ${projection.result.afterChars} chars; clampedToolResults=${projection.result.clampedToolResults}; clampedAssistantTurns=${projection.result.clampedAssistantTurns}; droppedTool=${projection.result.droppedToolMessages}; droppedSystem=${projection.result.droppedSystemMessages}; droppedHistory=${projection.result.droppedHistoryMessages}`);
685
+ }
686
+ return projection.messages;
687
+ }
688
+ getEstimatedContextUsage(messages, promptOverheadChars) {
689
+ const estimatedInputTokens = Math.ceil((this.contextBudgetManager.getMessagesCharCount(messages) + Math.max(0, promptOverheadChars)) / 4);
690
+ const contextWindowTokens = Math.max(1, Math.floor(this.options.parsingSupport.getExecutionContextBudgetChars() / 4));
691
+ const autoCompactThresholdTokens = Math.max(1, Math.floor(this.options.parsingSupport.getExecutionAutoCompactThresholdChars() / 4));
692
+ return {
693
+ estimatedInputTokens,
694
+ contextWindowTokens,
695
+ autoCompactThresholdTokens,
696
+ percentage: Math.min(100, Math.round((estimatedInputTokens / contextWindowTokens) * 100))
697
+ };
698
+ }
699
+ getToolDefinitionChars(tools) {
700
+ try {
701
+ return JSON.stringify(tools).length;
702
+ }
703
+ catch {
704
+ return 0;
705
+ }
706
+ }
707
+ shouldRefreshContextForTurn(visibleTurnIndex) {
708
+ return visibleTurnIndex <= 1;
709
+ }
710
+ async prepareContext({ messages, objective, mode, planMode, initialContext, mentionedFiles, deferredSemanticContext, signal }) {
711
+ const freshContext = await this.options.cleanSlateContextService.getContext();
712
+ const promptContext = await (this.options.buildPromptContextForMode
713
+ ? this.options.buildPromptContextForMode(freshContext, mode, signal)
714
+ : this.options.buildPromptContext(freshContext, signal));
715
+ void initialContext;
716
+ const systemDirective = planMode
717
+ ? this.buildPlanModeDirective()
718
+ : this.buildSystemDirective();
719
+ if (systemDirective.trim().length > 0) {
720
+ messages.push({ role: 'system', content: systemDirective.trim() });
721
+ }
722
+ // Consume the warmed semantic retrieval only if it has already settled by
723
+ // this point (just before the model call) — never block the turn on it.
724
+ // If it isn't ready, the model retrieves via the semantic_search tool.
725
+ const semanticContext = deferredSemanticContext?.tryConsume() ?? '';
726
+ this.refreshContextMessage(messages, promptContext, `${semanticContext}${mentionedFiles}`, objective);
727
+ }
728
+ buildPlanModeDirective() {
729
+ return [
730
+ '',
731
+ '',
732
+ 'PLAN MODE:',
733
+ 'You are in plan mode. Your tools are read-only: research the workspace, read the relevant code, and design the change. You cannot edit files or run commands in this mode.',
734
+ 'Investigate with concrete read/search tool calls. Use assistant text only when you need a user decision or when presenting the completed plan.',
735
+ 'When an implementation plan is ready, call submit_artifact with the concise final plan only so it can be reviewed. The artifact is not a research log: omit deliberation, progress narration, files-inspected inventories, and repeated repo facts.',
736
+ 'Prefer a clear title plus 3-5 compact sections: Summary, grouped Implementation Changes, Test Plan, and Assumptions only when meaningful. Keep bullets short, avoid unnecessary nesting, and keep straightforward plans under roughly 40 lines.',
737
+ 'Group by behavior or subsystem instead of exhaustive file-by-file notes. Mention exact paths only where they prevent ambiguity, normally no more than three unless the task genuinely requires more.',
738
+ 'For an informational request, answer in normal assistant text and stop.',
739
+ 'If a decision genuinely belongs to the user (competing approaches with real trade-offs, missing requirements), call ask_question. If you simply need to say something to the user, write it as assistant text and stop — the turn ends and the user replies.',
740
+ 'Match the plan to the request: for changes to an existing codebase, name the exact files and changes discovered through research; for a greenfield/empty workspace, a scaffold-first plan is correct; for a broad request, scope it explicitly or ask.'
741
+ ].join('\n');
742
+ }
743
+ buildSystemDirective() {
744
+ const cliPolicy = [
745
+ 'VERIFICATION POLICY:',
746
+ 'Use host diagnostics after edits. When diagnostics do not prove the requested behavior, run a finite, scoped execute_command with an accurate intent and writesToWorkspace value.',
747
+ 'Prefer targeted tests or builds over broad project commands. Recover from a failed verification when useful, otherwise report it truthfully; partial output is not proof.',
748
+ 'Do not create walkthrough artifacts as a completion ritual. When the work is complete, write the visible final answer as normal assistant text and stop without calling a completion tool.'
749
+ ].join('\n');
750
+ return [
751
+ '',
752
+ '',
753
+ 'WEB RETRIEVAL RULE:',
754
+ 'Use web_search for internet discovery and web_fetch for specific URLs. Cite returned source URLs when relying on web evidence; do not use browser_* tools as a search-engine substitute.',
755
+ 'For explicit web research/current-information requests, do not answer from search snippets alone. Fetch the most relevant reliable result pages first, then synthesize the fetched evidence into the visible answer with citations.',
756
+ 'WEB ANSWER QUALITY:',
757
+ getWebResearchFinalAnswerPrompt(),
758
+ 'BROWSER TOOL OPT-IN:',
759
+ 'Use browser_* tools only when the current user request explicitly asks you to open a browser, preview a page, inspect DOM, capture screenshots, or perform visual/browser verification.',
760
+ 'Do not open localhost, collect browser evidence, or require browser verification only because UI files changed.',
761
+ 'When browser verification was not explicitly requested, rely on code inspection, diagnostics, tests, and concise completion reporting instead.',
762
+ 'When browser work is requested, operate the one bound live browser session: observe with browser_snapshot, choose a unique semantic locator, act, then observe the resulting URL/DOM/screenshot or diagnostics. Prefer role/name, label, placeholder, text, or testId over coordinates; use coordinates only as a visual fallback.',
763
+ 'browser_snapshot is semantic DOM text, not an image. When the user asks to inspect, test, preview, or visually verify a site, call browser_screenshot on the key page states; do not claim visual inspection from browser_snapshot alone.',
764
+ 'The visible mouse belongs only to real pointer actions such as browser_click, browser_hover, and browser_scroll. Direct navigation, DOM snapshots, and screenshots must not fabricate mouse movement.',
765
+ 'Do not reuse an elementId after navigation or material DOM change. Take a new snapshot and recover from strict-locator ambiguity by choosing a more specific locator instead of guessing.',
766
+ cliPolicy,
767
+ 'COMPLETION CONTRACT:',
768
+ 'Continue while tool calls are needed. When no more tool calls are needed, return one non-empty user-facing final assistant answer. The host emits task completion only after that natural assistant stop; reasoning, progress narration, mutations, and command output are not completion signals.'
769
+ ].join('\n');
770
+ }
771
+ parseAssistantTurn(rawResponse) {
772
+ void rawResponse;
773
+ return {
774
+ toolCalls: [],
775
+ toDoList: []
776
+ };
777
+ }
778
+ /**
779
+ * Detects arguments that must not execute: the transport's JSON parse
780
+ * failure marker, or serialized tool-call debris that a degenerate model
781
+ * merged into locator argument values. Content-bearing fields (file
782
+ * content, edit text, commands) are deliberately NOT scanned — they can
783
+ * legitimately contain these tokens when the user's code mentions them.
784
+ */
785
+ getMalformedToolArgumentsError(toolCall) {
786
+ const input = toolCall.input;
787
+ if (!input || typeof input !== 'object') {
788
+ return undefined;
789
+ }
790
+ if (typeof input.__cleanSlateArgumentsParseError === 'string') {
791
+ return input.__cleanSlateArgumentsParseError;
792
+ }
793
+ const locatorValues = [];
794
+ for (const field of ['path', 'file_path', 'pattern', 'query', 'symbol', 'directory']) {
795
+ if (typeof input[field] === 'string') {
796
+ locatorValues.push(input[field]);
797
+ }
798
+ }
799
+ if (Array.isArray(input.paths)) {
800
+ for (const entry of input.paths) {
801
+ if (typeof entry === 'string') {
802
+ locatorValues.push(entry);
803
+ }
804
+ }
805
+ }
806
+ for (const value of locatorValues) {
807
+ if (detectSerializedToolCallSyntax(value)) {
808
+ return `failed to parse function arguments: a locator argument contains serialized tool-call syntax ("${value.slice(0, 120)}").`;
809
+ }
810
+ }
811
+ return undefined;
812
+ }
813
+ parseStreamedToolCall(call, toolCallLedger) {
814
+ const toolCall = this.nativeToolTranscript.parseToolCall(call);
815
+ return toolCall ? toolCallLedger.normalizeToolCall(toolCall) : undefined;
816
+ }
817
+ mergeToolCalls(parsedToolCalls, streamedToolCalls) {
818
+ void parsedToolCalls;
819
+ const seen = new Set();
820
+ const merged = [];
821
+ for (const toolCall of streamedToolCalls) {
822
+ const key = this.getToolCallKey(toolCall);
823
+ if (!seen.has(key)) {
824
+ seen.add(key);
825
+ merged.push(toolCall);
826
+ }
827
+ }
828
+ return merged;
829
+ }
830
+ async *executeToolWithTracking(toolName, input, { signal, toolCallId } = {}) {
831
+ for await (const part of this.options.executeTool(toolName, input, toolCallId, signal)) {
832
+ if (signal?.aborted) {
833
+ break;
834
+ }
835
+ if (part.type === 'tool_result' && this.options.executionSupport.didToolSucceed(part.result)) {
836
+ try {
837
+ this.options.recordSemanticToolResult?.(toolName, input, part.result);
838
+ }
839
+ catch (error) {
840
+ console.warn('[CleanSlateAgent] Semantic graph ingestion failed:', error);
841
+ }
842
+ }
843
+ yield part;
844
+ }
845
+ }
846
+ getNoProgressTurnLimit(_phase, configuredMaxNoToolTurns, options = {}) {
847
+ const configuredLimit = Number.isFinite(configuredMaxNoToolTurns)
848
+ ? Math.max(1, Math.floor(configuredMaxNoToolTurns))
849
+ : 4;
850
+ const floor = options.hasPhaseProgress
851
+ ? (options.hasAssistantOutput ? 8 : 6)
852
+ : (options.hasAssistantOutput ? 6 : 4);
853
+ return Math.min(Math.max(configuredLimit, floor), 12);
854
+ }
855
+ refreshContextMessage(messages, promptContext, mentionedFiles, objective) {
856
+ messages.push({
857
+ role: 'system',
858
+ content: `[RUNTIME CONTEXT REMINDER]\n${promptContext}${mentionedFiles}\n\nCurrent objective: ${objective}`
859
+ });
860
+ }
861
+ getNativeToolDefinitions() {
862
+ return (this.options.getTools?.() ?? ALL_TOOLS).map(tool => ({
863
+ name: tool.name,
864
+ description: tool.description,
865
+ parametersSchema: tool.parametersSchema || { type: 'object', properties: {} }
866
+ }));
867
+ }
868
+ refreshFileReadBudget(messages, tools) {
869
+ const config = this.options.toolContext.configService.getConfiguration();
870
+ const contextWindowTokens = Math.max(1, Math.floor(config.contextWindow
871
+ ?? config.maxInputTokens
872
+ ?? CLEANSLATE_FALLBACK_CONTEXT_WINDOW_TOKENS));
873
+ // Provider tokenizers are not uniformly available. UTF-8 bytes / 3 is
874
+ // deliberately conservative for source code and works across models.
875
+ const estimatedPromptTokens = estimateCleanSlateFileReadTokens(JSON.stringify({ messages, tools }) ?? '');
876
+ this.options.toolContext.fileReadBudget = {
877
+ contextWindowTokens,
878
+ availableInputTokens: Math.max(1, contextWindowTokens - estimatedPromptTokens)
879
+ };
880
+ }
881
+ getNativeToolDefinitionsForTurn(nativeTools, queryState) {
882
+ if (!queryState.planMode) {
883
+ // The loop stops when an assistant turn contains no tool calls, and
884
+ // task-finished is emitted host-side. No model-facing completion
885
+ // tool is exposed, so normal mode receives every enabled tool.
886
+ return nativeTools;
887
+ }
888
+ return nativeTools.filter(tool => this.profile.planModeTools.has(tool.name));
889
+ }
890
+ isParallelToolCall(toolCall) {
891
+ return this.options.getToolCategory(toolCall.toolName) === 'discovery'
892
+ || this.profile.parallelSafeTools.has(toolCall.toolName);
893
+ }
894
+ async *streamToolExecutionParts(toolCall, signal, queryState, guardState, executionFlow, toolCallLedger, activeTaskSessionService) {
895
+ // A tool call with unparseable or corrupted arguments is answered with
896
+ // the parse error, never executed. This catches both the
897
+ // transport-level JSON parse failure marker and serialized-call debris
898
+ // that leaked into locator argument values (the A/B run executed
899
+ // find_by_name with "to=multi_tool_use.parallel..." merged into path).
900
+ const malformedArgumentsError = this.getMalformedToolArgumentsError(toolCall);
901
+ if (malformedArgumentsError) {
902
+ const result = {
903
+ success: false,
904
+ code: 'malformed_tool_arguments',
905
+ message: malformedArgumentsError,
906
+ recoveryHint: 'Re-issue this as a single native tool call with valid JSON arguments. Never serialize tool syntax (to=functions.*, multi_tool_use.parallel) into text or argument values.'
907
+ };
908
+ toolCallLedger.recordResult(toolCall, result);
909
+ yield this.nativeToolTranscript.attachToolCallId({
910
+ type: 'tool_result',
911
+ toolName: toolCall.toolName,
912
+ result
913
+ }, toolCall.id);
914
+ return;
915
+ }
916
+ // Plan-mode write barrier. The provider
917
+ // only sees the read-only tool list, but tool calls parsed from text
918
+ // bypass that filter — this is the hard guarantee that plan mode
919
+ // cannot mutate the workspace or run commands.
920
+ if (queryState.planMode && !this.profile.planModeTools.has(toolCall.toolName)) {
921
+ const result = {
922
+ success: false,
923
+ code: 'plan_mode_tool_blocked',
924
+ message: `Tool "${toolCall.toolName}" is not available in plan mode.`,
925
+ recoveryHint: 'Plan mode is read-only: research with discovery tools, ask_question for decisions you cannot make, and submit the plan with submit_artifact when it is ready. Implementation happens after the user approves the plan.'
926
+ };
927
+ toolCallLedger.recordResult(toolCall, result);
928
+ yield this.nativeToolTranscript.attachToolCallId({
929
+ type: 'tool_result',
930
+ toolName: toolCall.toolName,
931
+ result
932
+ }, toolCall.id);
933
+ return;
934
+ }
935
+ const decision = toolCallLedger.prepareForExecution(toolCall);
936
+ toolCall = decision.toolCall;
937
+ if (!decision.accepted) {
938
+ const result = decision.result ?? {
939
+ success: false,
940
+ code: 'tool_call_rejected',
941
+ message: `Tool call "${toolCall.toolName}" was rejected by the execution ledger.`
942
+ };
943
+ toolCallLedger.recordResult(toolCall, result);
944
+ const recoveryPrompt = this.editPolicy.buildFailedEditRecoveryPrompt(toolCall, result);
945
+ if (recoveryPrompt) {
946
+ this.appendPendingRecoveryPrompt(queryState, recoveryPrompt);
947
+ }
948
+ yield this.nativeToolTranscript.attachToolCallId({
949
+ type: 'tool_result',
950
+ toolName: toolCall.toolName,
951
+ result
952
+ }, toolCall.id);
953
+ return;
954
+ }
955
+ if (toolCall.toolName === this.profile.primaryCommandTool) {
956
+ const commandPolicy = evaluateExecutionCommandPolicy(toolCall.input);
957
+ if (!commandPolicy.allowed) {
958
+ const result = {
959
+ success: false,
960
+ code: commandPolicy.code,
961
+ message: commandPolicy.message,
962
+ recoveryHint: commandPolicy.recoveryHint
963
+ };
964
+ toolCallLedger.recordResult(toolCall, result);
965
+ yield this.nativeToolTranscript.attachToolCallId({
966
+ type: 'tool_result',
967
+ toolName: toolCall.toolName,
968
+ result
969
+ }, toolCall.id);
970
+ return;
971
+ }
972
+ }
973
+ if (queryState.pendingRecoveryPrompt
974
+ && this.profile.structuredEditTools.has(toolCall.toolName)
975
+ && this.editPolicy.countStructuredEdits(toolCall) !== 1) {
976
+ const result = {
977
+ success: false,
978
+ code: 'recovery_requires_single_edit',
979
+ message: 'A failed edit recovery is pending. Retry exactly one failed edit instead of resubmitting a batch.',
980
+ recoveryHint: queryState.pendingRecoveryPrompt
981
+ };
982
+ toolCallLedger.recordResult(toolCall, result);
983
+ yield this.nativeToolTranscript.attachToolCallId({
984
+ type: 'tool_result',
985
+ toolName: toolCall.toolName,
986
+ result
987
+ }, toolCall.id);
988
+ return;
989
+ }
990
+ const executableToolCall = this.editPolicy.withScopedReadLintsInput(toolCall, guardState);
991
+ let lastToolResult;
992
+ for await (const part of this.executeToolWithTracking(executableToolCall.toolName, executableToolCall.input, { signal, toolCallId: executableToolCall.id })) {
993
+ if (part.type === 'tool_result') {
994
+ lastToolResult = part.result;
995
+ toolCallLedger.recordResult(executableToolCall, part.result);
996
+ this.recordToolResultForGuardrails(executableToolCall, part.result, guardState);
997
+ const recoveryPrompt = this.editPolicy.buildFailedEditRecoveryPrompt(executableToolCall, part.result);
998
+ if (recoveryPrompt) {
999
+ this.appendPendingRecoveryPrompt(queryState, recoveryPrompt);
1000
+ }
1001
+ }
1002
+ yield this.nativeToolTranscript.attachToolCallId(part, executableToolCall.id);
1003
+ }
1004
+ if (queryState.planMode && executableToolCall.toolName === this.profile.completionTool) {
1005
+ const conclusion = this.resolvePlanModeConclusion(executableToolCall, lastToolResult, activeTaskSessionService);
1006
+ if (conclusion) {
1007
+ yield conclusion;
1008
+ }
1009
+ }
1010
+ }
1011
+ /**
1012
+ * Plan-mode ExitPlanMode analog: a successful submit_artifact concludes
1013
+ * the plan-mode run. An implementation plan pauses the task for user
1014
+ * approval; an explicitly requested analysis artifact finishes it.
1015
+ */
1016
+ resolvePlanModeConclusion(toolCall, result, activeTaskSessionService) {
1017
+ if (result?.success === false) {
1018
+ return undefined;
1019
+ }
1020
+ const inputType = typeof toolCall.input?.type === 'string' ? toolCall.input.type : '';
1021
+ const artifactType = typeof toolCall.input?.artifactType === 'string' ? toolCall.input.artifactType : '';
1022
+ const inputPath = typeof toolCall.input?.path === 'string' ? toolCall.input.path : '';
1023
+ const resultPath = typeof result?.path === 'string' ? result.path : '';
1024
+ const artifactPath = inputPath || resultPath;
1025
+ const normalizedArtifactPath = artifactPath.toLowerCase();
1026
+ const hasSubmittedContent = typeof toolCall.input?.content === 'string' && toolCall.input.content.trim().length > 0;
1027
+ const isAnalysisArtifact = inputType === 'analysis'
1028
+ || artifactType === 'analysis'
1029
+ || normalizedArtifactPath.includes('analysis');
1030
+ const isImplementationPlanArtifact = inputType === 'implementation_plan'
1031
+ || artifactType === 'implementation_plan'
1032
+ || normalizedArtifactPath.includes('implementation_plan')
1033
+ || (hasSubmittedContent && !isAnalysisArtifact);
1034
+ if (isImplementationPlanArtifact) {
1035
+ activeTaskSessionService.markAwaitingApproval();
1036
+ return {
1037
+ type: 'tool_result',
1038
+ toolName: PHASE_CONCLUSION_SIGNAL_PLAN_CREATED,
1039
+ result: {
1040
+ planCreated: true,
1041
+ artifactPath: artifactPath || 'implementation_plan.md',
1042
+ summary: typeof result?.summary === 'string' ? result.summary : 'Planning artifact submitted.'
1043
+ }
1044
+ };
1045
+ }
1046
+ if (isAnalysisArtifact) {
1047
+ activeTaskSessionService.setAwaitingApproval(false);
1048
+ const summary = typeof result?.summary === 'string' && result.summary.trim().length > 0
1049
+ ? result.summary.trim()
1050
+ : 'Analysis report submitted.';
1051
+ return {
1052
+ type: 'task_complete',
1053
+ result: {
1054
+ phase: AgentPhase.PLANNING,
1055
+ analysisSubmitted: true,
1056
+ artifactPath: artifactPath || 'analysis.md',
1057
+ completionSummary: {
1058
+ status: 'completed_analysis',
1059
+ summary
1060
+ }
1061
+ }
1062
+ };
1063
+ }
1064
+ return undefined;
1065
+ }
1066
+ async *streamPostMutationVerificationParts(signal, guardState) {
1067
+ const scopedPaths = Array.from(guardState.pendingVerificationPaths.size > 0
1068
+ ? guardState.pendingVerificationPaths
1069
+ : guardState.mutatedPaths.size > 0
1070
+ ? guardState.mutatedPaths
1071
+ : guardState.touchedPaths);
1072
+ if (scopedPaths.length === 0) {
1073
+ return { issues: [] };
1074
+ }
1075
+ const input = { paths: scopedPaths };
1076
+ let lastResult;
1077
+ for await (const part of this.executeToolWithTracking(this.verificationToolName, input, { signal })) {
1078
+ if (part.type === 'tool_result') {
1079
+ lastResult = part.result;
1080
+ this.recordToolResultForGuardrails({ toolName: this.verificationToolName, input }, part.result, guardState);
1081
+ }
1082
+ yield part;
1083
+ }
1084
+ const markerIssues = await this.options.executionSupport.collectNewMarkerIssues(guardState.markerBaseline, new Set(scopedPaths), guardState.failOnWarnings, 40);
1085
+ const lintIssueCount = this.countLintIssues(lastResult);
1086
+ if (markerIssues.length === 0 && lastResult?.success !== false) {
1087
+ guardState.pendingVerificationPaths.clear();
1088
+ }
1089
+ guardState.verificationSummaries.push({
1090
+ toolName: this.verificationToolName,
1091
+ paths: scopedPaths,
1092
+ passed: markerIssues.length === 0 && lastResult?.success !== false,
1093
+ lintIssueCount,
1094
+ markerIssueCount: markerIssues.length,
1095
+ message: typeof lastResult?.message === 'string' ? lastResult.message : undefined
1096
+ });
1097
+ return { result: lastResult, issues: markerIssues };
1098
+ }
1099
+ buildPostMutationVerificationPrompt(issues) {
1100
+ return [
1101
+ 'POST-MUTATION VERIFICATION FAILED: the last edit changed the workspace but diagnostics are still present.',
1102
+ ...issues.map(issue => `- ${issue}`),
1103
+ 'Fix these issues before returning the final answer. Use read_file_range/read_lints and small targeted edits.'
1104
+ ].join('\n');
1105
+ }
1106
+ buildVerifiedFinishPrompt(guardState) {
1107
+ const targetCount = guardState.mutatedPaths.size || guardState.touchedPaths.size;
1108
+ return [
1109
+ 'EXECUTION VERIFICATION COMPLETE: post-mutation verification passed.',
1110
+ `Verified target files: ${targetCount}.`,
1111
+ 'Do not stop merely because this one edit verified.',
1112
+ 'If the full user request is implemented, write the visible final answer as normal assistant text and stop without a completion tool.',
1113
+ 'If any planned work remains, continue with concrete tool_calls only.'
1114
+ ].join('\n');
1115
+ }
1116
+ async canHostFinalizeProseStop(currentResponse, queryState, guardState) {
1117
+ if (queryState.pendingRecoveryPrompt) {
1118
+ return false;
1119
+ }
1120
+ // A reasoning-only or empty provider stop is not completion. Refs emit
1121
+ // their task-finished lifecycle only after a non-empty assistant answer.
1122
+ if (this.normalizeCompletionSummary(currentResponse) === undefined) {
1123
+ return false;
1124
+ }
1125
+ if (guardState.pendingVerificationPaths.size > 0
1126
+ || guardState.postEditCommandIssues.length > 0
1127
+ || this.getUnresolvedFailedGoalCommand(guardState)
1128
+ || this.hasFailedUserRequestedOrVerificationCommand(guardState)) {
1129
+ return false;
1130
+ }
1131
+ if (guardState.mutatedPaths.size > 0 && !guardState.postEditCommandVerified) {
1132
+ return false;
1133
+ }
1134
+ const finalVerificationScope = guardState.mutatedPaths.size > 0
1135
+ ? guardState.mutatedPaths
1136
+ : guardState.touchedPaths;
1137
+ if (finalVerificationScope.size > 0) {
1138
+ const markerIssues = await this.options.executionSupport.collectNewMarkerIssues(guardState.markerBaseline, finalVerificationScope, guardState.failOnWarnings, 40);
1139
+ if (markerIssues.length > 0) {
1140
+ return false;
1141
+ }
1142
+ }
1143
+ return true;
1144
+ }
1145
+ hasFailedUserRequestedOrVerificationCommand(guardState) {
1146
+ return guardState.terminalSummaries.some(summary => summary.toolName === this.profile.primaryCommandTool
1147
+ && summary.success === false
1148
+ && (summary.intent === 'verification' || summary.intent === 'user_requested'));
1149
+ }
1150
+ isToolCallLoopResult(result) {
1151
+ return result?.code === 'tool_call_loop_detected';
1152
+ }
1153
+ buildCompletionState(guardState, finalAnswer, plannedFileTargets) {
1154
+ const proofSummaries = this.buildHostProofSummaries(guardState);
1155
+ return {
1156
+ touchedPaths: Array.from(guardState.touchedPaths),
1157
+ mutatedPaths: Array.from(guardState.mutatedPaths),
1158
+ mutationSummaries: guardState.mutationSummaries,
1159
+ terminalSummaries: guardState.terminalSummaries.slice(-4),
1160
+ proofSummaries,
1161
+ completionSource: 'host_finalized',
1162
+ verificationIssueCount: guardState.verificationSummaries.reduce((sum, summary) => sum + summary.markerIssueCount, 0),
1163
+ successfulMutationsInPhase: guardState.successfulMutationsInPhase,
1164
+ summary: this.normalizeCompletionSummary(finalAnswer),
1165
+ ...(plannedFileTargets?.length ? {
1166
+ plannedFileTargets: [...plannedFileTargets],
1167
+ unmutatedPlannedFiles: this.getUnmutatedPlannedFiles(plannedFileTargets, guardState.mutatedPaths)
1168
+ } : {})
1169
+ };
1170
+ }
1171
+ /**
1172
+ * File targets named by the approved implementation plan handed off to this
1173
+ * run. Used as audit evidence so plan-to-execution fidelity is judged (and
1174
+ * deviations must be disclosed) instead of silently forgotten.
1175
+ */
1176
+ extractPlannedFileTargets(messages) {
1177
+ for (const message of messages) {
1178
+ const text = typeof message.content === 'string' ? message.content : '';
1179
+ if (!text.includes('[APPROVED IMPLEMENTATION PLAN]')) {
1180
+ continue;
1181
+ }
1182
+ const targets = extractPlanFileEntries(text)
1183
+ .filter(entry => typeof entry.target === 'string' && entry.target.length > 0)
1184
+ .map(entry => planEntryTargetToPath(entry.target).replace(/\\/g, '/'));
1185
+ return Array.from(new Set(targets)).slice(0, 24);
1186
+ }
1187
+ return [];
1188
+ }
1189
+ getUnmutatedPlannedFiles(plannedFileTargets, mutatedPaths) {
1190
+ const mutatedBasenames = new Set(Array.from(mutatedPaths).map(path => path.replace(/\\/g, '/').toLowerCase().split('/').pop() ?? ''));
1191
+ return plannedFileTargets.filter(target => {
1192
+ const basename = target.toLowerCase().split('/').pop() ?? target.toLowerCase();
1193
+ return !mutatedBasenames.has(basename);
1194
+ });
1195
+ }
1196
+ buildHostProofSummaries(guardState) {
1197
+ const proofSummaries = [];
1198
+ for (const summary of guardState.verificationSummaries.slice(-4)) {
1199
+ const status = summary.passed ? 'passed' : 'failed';
1200
+ const paths = summary.paths.length > 0 ? ` for ${summary.paths.join(', ')}` : '';
1201
+ proofSummaries.push(`${summary.toolName} ${status}${paths}`);
1202
+ }
1203
+ for (const summary of guardState.terminalSummaries.slice(-4)) {
1204
+ if (summary.success !== true) {
1205
+ continue;
1206
+ }
1207
+ const command = summary.command ? `"${summary.command}"` : (this.profile.primaryCommandTool ?? 'the command');
1208
+ const intent = summary.intent ? ` (${summary.intent})` : '';
1209
+ proofSummaries.push(`${command} succeeded${intent}`);
1210
+ }
1211
+ return Array.from(new Set(proofSummaries));
1212
+ }
1213
+ normalizeCompletionSummary(summary) {
1214
+ if (typeof summary !== 'string') {
1215
+ return undefined;
1216
+ }
1217
+ const trimmed = summary.trim();
1218
+ if (!trimmed) {
1219
+ return undefined;
1220
+ }
1221
+ return trimmed.length > 4000 ? trimmed.slice(0, 4000) : trimmed;
1222
+ }
1223
+ getToolCallKey(toolCall) {
1224
+ return this.nativeToolTranscript.getToolCallKey(toolCall);
1225
+ }
1226
+ shouldVerifyAfterToolResult(toolCall, result) {
1227
+ return this.options.executionSupport.isConfirmedMutationResult(toolCall.toolName, toolCall.input, result)
1228
+ || this.editPolicy.isSettledEditNoOp(toolCall, result);
1229
+ }
1230
+ buildMutationSummary(toolCall, result, mutationPaths, turnIndex) {
1231
+ return {
1232
+ toolName: toolCall.toolName,
1233
+ turnIndex,
1234
+ paths: mutationPaths.length > 0 ? mutationPaths : this.editPolicy.collectMutationPaths(toolCall, result),
1235
+ fileChanges: this.filesModifiedService.buildMutationFileChanges(toolCall.toolName, toolCall.input, result),
1236
+ appliedBlocks: this.firstNumericValue(result?.appliedBlocks, result?.totalAppliedBlocks, this.sumResultField(result, 'appliedBlocks')),
1237
+ added: this.firstNumericValue(result?.added, this.sumResultField(result, 'added')),
1238
+ deleted: this.firstNumericValue(result?.deleted, this.sumResultField(result, 'deleted')),
1239
+ totalLinesChanged: this.firstNumericValue(result?.totalLinesChanged, this.sumResultField(result, 'totalLinesChanged')),
1240
+ diagnosticsCount: this.countEditDiagnostics(result),
1241
+ strategies: this.collectStrategies(result),
1242
+ message: typeof result?.message === 'string' ? result.message : undefined
1243
+ };
1244
+ }
1245
+ firstNumericValue(...values) {
1246
+ for (const value of values) {
1247
+ if (typeof value === 'number' && Number.isFinite(value)) {
1248
+ return value;
1249
+ }
1250
+ }
1251
+ return undefined;
1252
+ }
1253
+ sumResultField(result, field) {
1254
+ if (!Array.isArray(result?.results)) {
1255
+ return undefined;
1256
+ }
1257
+ let sum = 0;
1258
+ let found = false;
1259
+ for (const entry of result.results) {
1260
+ const value = entry?.[field];
1261
+ if (typeof value === 'number' && Number.isFinite(value)) {
1262
+ sum += value;
1263
+ found = true;
1264
+ }
1265
+ }
1266
+ return found ? sum : undefined;
1267
+ }
1268
+ countEditDiagnostics(result) {
1269
+ let count = 0;
1270
+ const countArray = (candidate) => {
1271
+ if (Array.isArray(candidate)) {
1272
+ count += candidate.length;
1273
+ }
1274
+ };
1275
+ countArray(result?.diagnostics);
1276
+ countArray(result?.preflightDiagnostics);
1277
+ countArray(result?.postApplyDiagnostics);
1278
+ if (Array.isArray(result?.validationDiagnostics)) {
1279
+ for (const entry of result.validationDiagnostics) {
1280
+ countArray(entry?.diagnostics);
1281
+ }
1282
+ }
1283
+ if (Array.isArray(result?.results)) {
1284
+ for (const entry of result.results) {
1285
+ countArray(entry?.diagnostics);
1286
+ }
1287
+ }
1288
+ return count;
1289
+ }
1290
+ countLintIssues(result) {
1291
+ if (Array.isArray(result?.errors)) {
1292
+ return result.errors.length;
1293
+ }
1294
+ if (Array.isArray(result?.diagnostics)) {
1295
+ return result.diagnostics.length;
1296
+ }
1297
+ return 0;
1298
+ }
1299
+ collectStrategies(result) {
1300
+ const strategies = [];
1301
+ const addStrategy = (candidate) => {
1302
+ if (typeof candidate !== 'string') {
1303
+ return;
1304
+ }
1305
+ const strategy = candidate.trim();
1306
+ if (strategy.length === 0 || strategies.includes(strategy)) {
1307
+ return;
1308
+ }
1309
+ strategies.push(strategy);
1310
+ };
1311
+ for (const strategy of Array.isArray(result?.strategies) ? result.strategies : []) {
1312
+ addStrategy(strategy);
1313
+ }
1314
+ for (const entry of Array.isArray(result?.results) ? result.results : []) {
1315
+ for (const strategy of Array.isArray(entry?.strategies) ? entry.strategies : []) {
1316
+ addStrategy(strategy);
1317
+ }
1318
+ }
1319
+ return strategies.length > 0 ? strategies : undefined;
1320
+ }
1321
+ appendPendingRecoveryPrompt(queryState, recoveryPrompt) {
1322
+ if (!queryState.pendingRecoveryPrompt) {
1323
+ queryState.pendingRecoveryPrompt = recoveryPrompt;
1324
+ queryState.recoveryNoToolTurns = 0;
1325
+ return;
1326
+ }
1327
+ if (!queryState.pendingRecoveryPrompt.includes(recoveryPrompt)) {
1328
+ queryState.pendingRecoveryPrompt = `${queryState.pendingRecoveryPrompt}\n\n${recoveryPrompt}`;
1329
+ }
1330
+ queryState.recoveryNoToolTurns = 0;
1331
+ }
1332
+ recordToolResultForGuardrails(toolCall, result, guardState) {
1333
+ this.options.executionSupport.trackTouchedPaths(toolCall.toolName, toolCall.input, result, guardState.touchedPaths);
1334
+ this.recordTerminalSummary(toolCall, result, guardState);
1335
+ const didSucceed = this.options.executionSupport.didToolSucceed(result);
1336
+ if (didSucceed) {
1337
+ guardState.successfulToolResultsInPhase++;
1338
+ }
1339
+ if (didSucceed) {
1340
+ this.executionPhase.updateExecutionEvidenceLedgerFromToolResult(guardState.executionEvidenceLedger, toolCall.toolName, toolCall.input, result);
1341
+ }
1342
+ const isConfirmedMutation = this.options.executionSupport.isConfirmedMutationResult(toolCall.toolName, toolCall.input, result);
1343
+ const isSettledNoOp = this.editPolicy.isSettledEditNoOp(toolCall, result);
1344
+ if (isConfirmedMutation || isSettledNoOp) {
1345
+ const mutationPaths = this.editPolicy.collectMutationPaths(toolCall, result);
1346
+ if (isConfirmedMutation) {
1347
+ guardState.successfulMutationsInPhase++;
1348
+ }
1349
+ guardState.postEditCommandVerified = false;
1350
+ guardState.postEditCommandIssues = [];
1351
+ guardState.mutationSummaries.push(this.buildMutationSummary(toolCall, result, mutationPaths, guardState.currentTurnIndex));
1352
+ this.executionPhase.registerPostMutationEvidence(guardState.executionEvidenceLedger, toolCall.toolName, toolCall.input);
1353
+ if (isConfirmedMutation) {
1354
+ for (const path of mutationPaths) {
1355
+ guardState.mutatedPaths.add(path);
1356
+ guardState.pendingVerificationPaths.add(path);
1357
+ }
1358
+ }
1359
+ }
1360
+ }
1361
+ recordTerminalSummary(toolCall, result, guardState) {
1362
+ if (!this.profile.commandTools.has(toolCall.toolName)) {
1363
+ return;
1364
+ }
1365
+ const command = typeof toolCall.input?.command === 'string'
1366
+ ? toolCall.input.command
1367
+ : undefined;
1368
+ const toolName = toolCall.toolName;
1369
+ const intent = typeof toolCall.input?.intent === 'string' ? toolCall.input.intent : undefined;
1370
+ const writesToWorkspace = typeof toolCall.input?.writesToWorkspace === 'boolean' ? toolCall.input.writesToWorkspace : undefined;
1371
+ const success = typeof result?.success === 'boolean'
1372
+ ? result.success
1373
+ : typeof result?.exitCode === 'number'
1374
+ ? result.exitCode === 0
1375
+ : undefined;
1376
+ const sessionId = typeof result?.processId === 'string' ? result.processId : undefined;
1377
+ const status = typeof result?.status === 'string' ? result.status : undefined;
1378
+ const exitCode = typeof result?.exitCode === 'number' ? result.exitCode : undefined;
1379
+ const output = typeof result?.output === 'string' ? result.output : undefined;
1380
+ const error = typeof result?.error === 'string' ? result.error : undefined;
1381
+ const existing = sessionId
1382
+ ? guardState.terminalSummaries.find(summary => summary.sessionId === sessionId)
1383
+ : undefined;
1384
+ const update = {
1385
+ toolName: toolName ?? existing?.toolName,
1386
+ turnIndex: guardState.currentTurnIndex,
1387
+ command: command ?? existing?.command,
1388
+ sessionId: sessionId ?? existing?.sessionId,
1389
+ intent: intent ?? existing?.intent,
1390
+ writesToWorkspace: writesToWorkspace ?? existing?.writesToWorkspace,
1391
+ success: success ?? existing?.success,
1392
+ status: status ?? existing?.status,
1393
+ exitCode: exitCode ?? existing?.exitCode,
1394
+ output: output ?? existing?.output,
1395
+ error: error ?? existing?.error
1396
+ };
1397
+ if (existing) {
1398
+ Object.assign(existing, update);
1399
+ return;
1400
+ }
1401
+ guardState.terminalSummaries.push(update);
1402
+ }
1403
+ getUnresolvedFailedGoalCommand(guardState) {
1404
+ const failedCommand = [...guardState.terminalSummaries].reverse().find(summary => summary.toolName === this.profile.primaryCommandTool
1405
+ && summary.success === false
1406
+ && this.isFailedGoalCommand(summary));
1407
+ if (!failedCommand) {
1408
+ return undefined;
1409
+ }
1410
+ return this.hasSuccessfulRecoveryAfterCommandFailure(guardState, failedCommand) ? undefined : failedCommand;
1411
+ }
1412
+ isFailedGoalCommand(summary) {
1413
+ return summary.intent === 'implementation' || summary.writesToWorkspace === true;
1414
+ }
1415
+ hasSuccessfulRecoveryAfterCommandFailure(guardState, failedCommand) {
1416
+ const failedTurnIndex = failedCommand.turnIndex ?? -1;
1417
+ const hasLaterSuccessfulCommand = guardState.terminalSummaries.some(summary => summary !== failedCommand
1418
+ && summary.success === true
1419
+ && (summary.turnIndex ?? -1) > failedTurnIndex
1420
+ && (summary.intent === failedCommand.intent
1421
+ || summary.intent === 'implementation'
1422
+ || (failedCommand.writesToWorkspace === true && summary.writesToWorkspace === true)));
1423
+ if (hasLaterSuccessfulCommand) {
1424
+ return true;
1425
+ }
1426
+ return guardState.mutationSummaries.some(summary => typeof summary.turnIndex === 'number'
1427
+ && summary.turnIndex > failedTurnIndex);
1428
+ }
1429
+ buildNoToolRecoveryPrompt(hasTechnicalProgress) {
1430
+ return buildExecutionNoToolRecoveryPrompt(hasTechnicalProgress);
1431
+ }
1432
+ buildNoProgressStopMessage(attempts, reason) {
1433
+ return buildExecutionNoProgressStopMessage(attempts, reason);
1434
+ }
1435
+ delay(milliseconds, signal) {
1436
+ if (milliseconds <= 0 || signal?.aborted) {
1437
+ return Promise.resolve();
1438
+ }
1439
+ return new Promise(resolve => {
1440
+ const timeout = setTimeout(resolve, milliseconds);
1441
+ signal?.addEventListener('abort', () => {
1442
+ clearTimeout(timeout);
1443
+ resolve();
1444
+ }, { once: true });
1445
+ });
1446
+ }
1447
+ }
1448
+ //# sourceMappingURL=cleanSlateExecutionQuery.js.map