@tyvm/knowhow 0.0.159 → 0.0.160

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 (870) hide show
  1. package/package.json +1 -1
  2. package/ts_build/package.json +1 -1
  3. package/ts_build/src/chat/CliChatService.d.ts +2 -1
  4. package/ts_build/src/chat/CliChatService.js +29 -3
  5. package/ts_build/src/chat/CliChatService.js.map +1 -1
  6. package/ts_build/src/chat/modules/AgentModule.js +21 -17
  7. package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
  8. package/ts_build/src/chat/renderer/ConsoleRenderer.js +32 -25
  9. package/ts_build/src/chat/renderer/ConsoleRenderer.js.map +1 -1
  10. package/ts_build/src/logger.d.ts +1 -0
  11. package/ts_build/src/logger.js +13 -1
  12. package/ts_build/src/logger.js.map +1 -1
  13. package/ts_build/src/utils/InputQueueManager.d.ts +8 -1
  14. package/ts_build/src/utils/InputQueueManager.js +72 -2
  15. package/ts_build/src/utils/InputQueueManager.js.map +1 -1
  16. package/ts_build/src/utils/index.d.ts +3 -1
  17. package/ts_build/src/utils/index.js +11 -3
  18. package/ts_build/src/utils/index.js.map +1 -1
  19. package/CONFIG.md +0 -429
  20. package/PROCESSING.md +0 -450
  21. package/WORKER.md +0 -260
  22. package/autodoc/README.md +0 -324
  23. package/autodoc/chat-guide.md +0 -444
  24. package/autodoc/cli-reference.md +0 -720
  25. package/autodoc/config-reference.md +0 -642
  26. package/autodoc/embeddings-guide.md +0 -467
  27. package/autodoc/generate-guide.md +0 -437
  28. package/autodoc/language-plugin-guide.md +0 -417
  29. package/autodoc/modules-guide.md +0 -379
  30. package/autodoc/plugins-guide.md +0 -721
  31. package/autodoc/quickstart-guide.md +0 -126
  32. package/autodoc/skills-guide.md +0 -584
  33. package/autodoc/worker-guide.md +0 -519
  34. package/docs/input-queue-manager.md +0 -142
  35. package/docs/multi-worker-management.md +0 -142
  36. package/docs/shell-commands.md +0 -174
  37. package/jest.config.js +0 -19
  38. package/jest.manual.config.js +0 -19
  39. package/scripts/README.md +0 -119
  40. package/scripts/build-for-node.sh +0 -148
  41. package/scripts/cache-miss-debug.ts +0 -365
  42. package/scripts/check-isolated-deps.sh +0 -69
  43. package/scripts/check-model-pricing.ts +0 -509
  44. package/scripts/compare-openrouter-coverage.ts +0 -576
  45. package/scripts/migrate-usage-json.js +0 -147
  46. package/scripts/publish.sh +0 -86
  47. package/scripts/restore_keys.sh +0 -59
  48. package/scripts/test-repetition-hint.ts +0 -302
  49. package/scripts/unset_keys.sh +0 -60
  50. package/src/agents/base/base.ts +0 -1963
  51. package/src/agents/base/prompt.ts +0 -55
  52. package/src/agents/configurable/ConfigAgent.ts +0 -24
  53. package/src/agents/developer/developer.ts +0 -76
  54. package/src/agents/historyRollback.ts +0 -36
  55. package/src/agents/index.ts +0 -52
  56. package/src/agents/interface.ts +0 -11
  57. package/src/agents/patcher/codebase.md +0 -27
  58. package/src/agents/patcher/patcher.ts +0 -131
  59. package/src/agents/researcher/researcher.ts +0 -115
  60. package/src/agents/setup/setup.ts +0 -63
  61. package/src/agents/tools/addInternalTools.ts +0 -21
  62. package/src/agents/tools/agentCall.ts +0 -34
  63. package/src/agents/tools/aiClient.ts +0 -178
  64. package/src/agents/tools/askHuman.ts +0 -10
  65. package/src/agents/tools/callPlugin.ts +0 -10
  66. package/src/agents/tools/connectAgent.ts +0 -355
  67. package/src/agents/tools/embeddingSearch.ts +0 -6
  68. package/src/agents/tools/execCommand.ts +0 -162
  69. package/src/agents/tools/fileSearch.ts +0 -35
  70. package/src/agents/tools/finalAnswer.ts +0 -4
  71. package/src/agents/tools/googleSearch.ts +0 -243
  72. package/src/agents/tools/index.ts +0 -33
  73. package/src/agents/tools/language/definitions.ts +0 -105
  74. package/src/agents/tools/language/index.ts +0 -20
  75. package/src/agents/tools/lazy/definitions.ts +0 -72
  76. package/src/agents/tools/lazy/disableTools.ts +0 -16
  77. package/src/agents/tools/lazy/enableTools.ts +0 -16
  78. package/src/agents/tools/lazy/index.ts +0 -3
  79. package/src/agents/tools/lazy/listAvailableTools.ts +0 -17
  80. package/src/agents/tools/lintFile.ts +0 -19
  81. package/src/agents/tools/list.ts +0 -739
  82. package/src/agents/tools/loadImageAsBase64.ts +0 -83
  83. package/src/agents/tools/loadWebpage.ts +0 -19
  84. package/src/agents/tools/mcp/connectMcpServer.ts +0 -40
  85. package/src/agents/tools/mcp/definitions.ts +0 -67
  86. package/src/agents/tools/mcp/disconnectMcpServer.ts +0 -40
  87. package/src/agents/tools/mcp/index.ts +0 -3
  88. package/src/agents/tools/mcp/listAvailableMcpServers.ts +0 -28
  89. package/src/agents/tools/minimal/callTool.ts +0 -45
  90. package/src/agents/tools/minimal/definitions.ts +0 -50
  91. package/src/agents/tools/minimal/index.ts +0 -3
  92. package/src/agents/tools/minimal/inspectTools.ts +0 -27
  93. package/src/agents/tools/modifyFile.ts +0 -53
  94. package/src/agents/tools/observe.ts +0 -247
  95. package/src/agents/tools/patch.ts +0 -1287
  96. package/src/agents/tools/readBlocks.ts +0 -83
  97. package/src/agents/tools/readFile.ts +0 -105
  98. package/src/agents/tools/replyToParent.ts +0 -123
  99. package/src/agents/tools/runGenerate.ts +0 -210
  100. package/src/agents/tools/scanFile.ts +0 -16
  101. package/src/agents/tools/sendAgentMessage.ts +0 -139
  102. package/src/agents/tools/skills.ts +0 -79
  103. package/src/agents/tools/startAgentTask.ts +0 -393
  104. package/src/agents/tools/stringReplace.ts +0 -105
  105. package/src/agents/tools/textSearch.ts +0 -128
  106. package/src/agents/tools/types/fileblock.ts +0 -5
  107. package/src/agents/tools/visionTool.ts +0 -35
  108. package/src/agents/tools/waitForAgentCompleted.ts +0 -270
  109. package/src/agents/tools/writeFile.ts +0 -106
  110. package/src/agents/tools/ycmd/client.ts +0 -608
  111. package/src/agents/tools/ycmd/definitions.ts +0 -294
  112. package/src/agents/tools/ycmd/detection.ts +0 -211
  113. package/src/agents/tools/ycmd/index.ts +0 -11
  114. package/src/agents/tools/ycmd/installer.ts +0 -251
  115. package/src/agents/tools/ycmd/server.ts +0 -545
  116. package/src/agents/tools/ycmd/serverManager.ts +0 -316
  117. package/src/agents/tools/ycmd/tools/completion.ts +0 -113
  118. package/src/agents/tools/ycmd/tools/diagnostics.ts +0 -166
  119. package/src/agents/tools/ycmd/tools/getLocations.ts +0 -173
  120. package/src/agents/tools/ycmd/tools/goto.ts +0 -169
  121. package/src/agents/tools/ycmd/tools/refactor.ts +0 -204
  122. package/src/agents/tools/ycmd/tools/signature.ts +0 -174
  123. package/src/agents/tools/ycmd/tools/start.ts +0 -95
  124. package/src/agents/tools/ycmd/utils/pathUtils.ts +0 -59
  125. package/src/ai.ts +0 -306
  126. package/src/auth/browserLogin.ts +0 -406
  127. package/src/auth/environmentAuth.ts +0 -51
  128. package/src/auth/errors.ts +0 -6
  129. package/src/auth/jwtStore.ts +0 -70
  130. package/src/auth/keyAuth.ts +0 -142
  131. package/src/auth/keyManager.ts +0 -331
  132. package/src/auth/registerIdentity.ts +0 -67
  133. package/src/auth/spinner.ts +0 -23
  134. package/src/chat/CliChatService.ts +0 -438
  135. package/src/chat/modules/AgentModule.ts +0 -1664
  136. package/src/chat/modules/AskModule.ts +0 -98
  137. package/src/chat/modules/BaseChatModule.ts +0 -65
  138. package/src/chat/modules/ClipboardImageModule.ts +0 -136
  139. package/src/chat/modules/CustomCommandsModule.ts +0 -80
  140. package/src/chat/modules/InternalChatModule.ts +0 -216
  141. package/src/chat/modules/RemoteSyncModule.ts +0 -482
  142. package/src/chat/modules/RendererModule.ts +0 -139
  143. package/src/chat/modules/SearchModule.ts +0 -168
  144. package/src/chat/modules/SessionsModule.ts +0 -969
  145. package/src/chat/modules/SetupModule.ts +0 -185
  146. package/src/chat/modules/ShellCommandModule.ts +0 -98
  147. package/src/chat/modules/SystemModule.ts +0 -161
  148. package/src/chat/modules/ToolCommandModule.ts +0 -102
  149. package/src/chat/modules/VoiceModule.ts +0 -70
  150. package/src/chat/modules/index.ts +0 -8
  151. package/src/chat/renderer/CompactRenderer.ts +0 -229
  152. package/src/chat/renderer/ConsoleRenderer.ts +0 -160
  153. package/src/chat/renderer/FancyRenderer.ts +0 -440
  154. package/src/chat/renderer/PlainRenderer.ts +0 -218
  155. package/src/chat/renderer/index.ts +0 -6
  156. package/src/chat/renderer/loadRenderer.ts +0 -316
  157. package/src/chat/renderer/messagesToRenderEvents.ts +0 -96
  158. package/src/chat/renderer/types.ts +0 -99
  159. package/src/chat/types.ts +0 -146
  160. package/src/chat.ts +0 -140
  161. package/src/cli.ts +0 -180
  162. package/src/clients/anthropic.ts +0 -772
  163. package/src/clients/attribution.ts +0 -53
  164. package/src/clients/cerebras.ts +0 -10
  165. package/src/clients/contextLimits.ts +0 -263
  166. package/src/clients/copilot.ts +0 -23
  167. package/src/clients/deepseek.ts +0 -16
  168. package/src/clients/fireworks.ts +0 -71
  169. package/src/clients/gemini.ts +0 -1169
  170. package/src/clients/github.ts +0 -16
  171. package/src/clients/groq.ts +0 -15
  172. package/src/clients/http.ts +0 -719
  173. package/src/clients/index.ts +0 -1153
  174. package/src/clients/knowhow.ts +0 -130
  175. package/src/clients/knowhowMcp.ts +0 -118
  176. package/src/clients/llama.ts +0 -16
  177. package/src/clients/meta.ts +0 -27
  178. package/src/clients/mistral.ts +0 -16
  179. package/src/clients/nvidia.ts +0 -16
  180. package/src/clients/openai.ts +0 -1186
  181. package/src/clients/openrouter.ts +0 -24
  182. package/src/clients/pricing/anthropic.ts +0 -149
  183. package/src/clients/pricing/cerebras.ts +0 -11
  184. package/src/clients/pricing/copilot.ts +0 -60
  185. package/src/clients/pricing/deepseek.ts +0 -15
  186. package/src/clients/pricing/fireworks.ts +0 -182
  187. package/src/clients/pricing/github.ts +0 -69
  188. package/src/clients/pricing/google.ts +0 -385
  189. package/src/clients/pricing/groq.ts +0 -56
  190. package/src/clients/pricing/index.ts +0 -44
  191. package/src/clients/pricing/llama.ts +0 -18
  192. package/src/clients/pricing/meta.ts +0 -12
  193. package/src/clients/pricing/mistral.ts +0 -34
  194. package/src/clients/pricing/models.ts +0 -25
  195. package/src/clients/pricing/nvidia.ts +0 -102
  196. package/src/clients/pricing/openai.ts +0 -409
  197. package/src/clients/pricing/openrouter.ts +0 -36
  198. package/src/clients/pricing/qwen.ts +0 -80
  199. package/src/clients/pricing/types.ts +0 -125
  200. package/src/clients/pricing/xai.ts +0 -137
  201. package/src/clients/qwen.ts +0 -16
  202. package/src/clients/responseMetadata.ts +0 -221
  203. package/src/clients/types.ts +0 -531
  204. package/src/clients/withRetry.ts +0 -89
  205. package/src/clients/xai.ts +0 -693
  206. package/src/cloudWorker.ts +0 -394
  207. package/src/commands/agent.ts +0 -342
  208. package/src/commands/agents.ts +0 -1037
  209. package/src/commands/behaviors.ts +0 -47
  210. package/src/commands/convert.ts +0 -291
  211. package/src/commands/hash.ts +0 -179
  212. package/src/commands/mcp.ts +0 -743
  213. package/src/commands/misc.ts +0 -373
  214. package/src/commands/modules.ts +0 -704
  215. package/src/commands/processes.ts +0 -248
  216. package/src/commands/remote.ts +0 -77
  217. package/src/commands/replay.ts +0 -503
  218. package/src/commands/sandbox.ts +0 -566
  219. package/src/commands/services.ts +0 -168
  220. package/src/commands/skills.ts +0 -107
  221. package/src/commands/workers.ts +0 -168
  222. package/src/config.ts +0 -468
  223. package/src/conversion.ts +0 -69
  224. package/src/dataset/diffs/README.md +0 -12
  225. package/src/dataset/diffs/debug-errors.ts +0 -29
  226. package/src/dataset/diffs/debug.ts +0 -64
  227. package/src/dataset/diffs/generate.ts +0 -71
  228. package/src/dataset/diffs/jsonl.ts +0 -53
  229. package/src/dataset/diffs/test.ts +0 -194
  230. package/src/embeddings.ts +0 -494
  231. package/src/fileSync.ts +0 -369
  232. package/src/generate.ts +0 -529
  233. package/src/hashes.ts +0 -180
  234. package/src/index.ts +0 -261
  235. package/src/logger.ts +0 -197
  236. package/src/login.ts +0 -209
  237. package/src/microphone.ts +0 -141
  238. package/src/migrations.ts +0 -151
  239. package/src/plugins/AgentsMdPlugin.ts +0 -118
  240. package/src/plugins/GitPlugin.ts +0 -598
  241. package/src/plugins/LinterPlugin.ts +0 -214
  242. package/src/plugins/PluginBase.ts +0 -70
  243. package/src/plugins/SkillsPlugin.ts +0 -37
  244. package/src/plugins/embedding.ts +0 -82
  245. package/src/plugins/exec.ts +0 -70
  246. package/src/plugins/language.ts +0 -290
  247. package/src/plugins/plugins.ts +0 -175
  248. package/src/plugins/tmux.ts +0 -132
  249. package/src/plugins/types.ts +0 -36
  250. package/src/plugins/url.ts +0 -101
  251. package/src/plugins/vim.ts +0 -89
  252. package/src/processes/ProcessManager.ts +0 -96
  253. package/src/processes/managedProcessShim.ts +0 -138
  254. package/src/processors/Base64ImageDetector.ts +0 -502
  255. package/src/processors/CustomVariables.ts +0 -693
  256. package/src/processors/GemmaToolProcessor.ts +0 -163
  257. package/src/processors/HarmonyToolProcessor.ts +0 -264
  258. package/src/processors/JsonCompressor.ts +0 -510
  259. package/src/processors/MinimalToolsMessageProcessor.ts +0 -113
  260. package/src/processors/TokenCompressor.ts +0 -620
  261. package/src/processors/ToolResponseCache.ts +0 -322
  262. package/src/processors/XmlToolCallProcessor.ts +0 -533
  263. package/src/processors/index.ts +0 -14
  264. package/src/processors/tools/boundedToolResponse.ts +0 -49
  265. package/src/processors/tools/grepToolResponse.ts +0 -230
  266. package/src/processors/tools/index.ts +0 -23
  267. package/src/processors/tools/jqToolResponse.ts +0 -159
  268. package/src/processors/tools/listStoredToolResponses.ts +0 -124
  269. package/src/processors/tools/tailToolResponse.ts +0 -148
  270. package/src/prompts/BasicCodeDocumenter.ts +0 -1
  271. package/src/prompts/BasicProjectDocumenter.ts +0 -1
  272. package/src/prompts/EmbeddingSeachHelper.ts +0 -1
  273. package/src/prompts/KnowhowConfigExamples.ts +0 -376
  274. package/src/prompts/index.ts +0 -9
  275. package/src/remotes.ts +0 -110
  276. package/src/server/index.ts +0 -16
  277. package/src/services/AgentService.ts +0 -134
  278. package/src/services/AgentSyncFs.ts +0 -775
  279. package/src/services/AgentSyncKnowhowWeb.ts +0 -389
  280. package/src/services/BehaviorsService.ts +0 -466
  281. package/src/services/DockerService.ts +0 -511
  282. package/src/services/EmbeddingService.ts +0 -427
  283. package/src/services/EmbeddingsService.ts +0 -73
  284. package/src/services/EventService.ts +0 -279
  285. package/src/services/ExtensionsService.ts +0 -25
  286. package/src/services/KnowhowClient.ts +0 -928
  287. package/src/services/LazyToolsService.ts +0 -210
  288. package/src/services/Mcp.ts +0 -727
  289. package/src/services/McpServer.ts +0 -155
  290. package/src/services/McpWebsocketTransport.ts +0 -87
  291. package/src/services/MediaProcessorService.ts +0 -669
  292. package/src/services/MessageProcessor.ts +0 -114
  293. package/src/services/MinimalToolsService.ts +0 -177
  294. package/src/services/RuntimeReloadService.ts +0 -31
  295. package/src/services/S3.ts +0 -61
  296. package/src/services/SessionManager.ts +0 -358
  297. package/src/services/SkillsService.ts +0 -822
  298. package/src/services/SyncedAgentWatcher.ts +0 -124
  299. package/src/services/SyncerService.ts +0 -191
  300. package/src/services/TaskRegistry.ts +0 -110
  301. package/src/services/Tools.ts +0 -580
  302. package/src/services/TracingService.ts +0 -116
  303. package/src/services/conversion/ConversionService.ts +0 -757
  304. package/src/services/conversion/index.ts +0 -2
  305. package/src/services/conversion/types.ts +0 -87
  306. package/src/services/flags.ts +0 -51
  307. package/src/services/index.ts +0 -117
  308. package/src/services/modules/computerUse.ts +0 -218
  309. package/src/services/modules/index.ts +0 -314
  310. package/src/services/modules/types.ts +0 -109
  311. package/src/services/types.ts +0 -60
  312. package/src/services/watchers/FsSyncer.ts +0 -199
  313. package/src/services/watchers/RemoteSyncer.ts +0 -196
  314. package/src/services/watchers/index.ts +0 -2
  315. package/src/tunnel.ts +0 -243
  316. package/src/types.ts +0 -282
  317. package/src/util/Trace.ts +0 -236
  318. package/src/utils/InputQueueManager.ts +0 -493
  319. package/src/utils/errors.ts +0 -0
  320. package/src/utils/http.ts +0 -150
  321. package/src/utils/index.ts +0 -111
  322. package/src/worker.ts +0 -696
  323. package/src/workerRegistry.ts +0 -152
  324. package/src/workers/auth/PasskeySetup.ts +0 -181
  325. package/src/workers/auth/WorkerPasskeyAuth.ts +0 -190
  326. package/src/workers/auth/WsMiddleware.ts +0 -99
  327. package/src/workers/auth/authMiddleware.ts +0 -104
  328. package/src/workers/auth/types.ts +0 -70
  329. package/src/workers/tools/getChallenge.ts +0 -33
  330. package/src/workers/tools/index.ts +0 -20
  331. package/src/workers/tools/listAllowedPorts.ts +0 -30
  332. package/src/workers/tools/lock.ts +0 -31
  333. package/src/workers/tools/reloadConfig.ts +0 -84
  334. package/src/workers/tools/unlock.ts +0 -116
  335. package/tests/XmlToolCallProcessor.test.ts +0 -468
  336. package/tests/agents/interrupt.test.ts +0 -200
  337. package/tests/agents/observe-base.test.ts +0 -183
  338. package/tests/agents/tools/connectAgent.test.ts +0 -138
  339. package/tests/agents/tools/observe.test.ts +0 -179
  340. package/tests/agents/tools/readFile.test.ts +0 -88
  341. package/tests/agents/tools/replyToParent.test.ts +0 -125
  342. package/tests/agents/tools/sendAgentMessage.test.ts +0 -99
  343. package/tests/agents/tools/waitForAgentCompleted.test.ts +0 -147
  344. package/tests/chat/detach-attach-rendering.test.ts +0 -315
  345. package/tests/clients/AIClient.test.ts +0 -668
  346. package/tests/clients/anthropic.test.ts +0 -202
  347. package/tests/clients/contextLimits.test.ts +0 -97
  348. package/tests/clients/fireworks.test.ts +0 -65
  349. package/tests/clients/openai.images.test.ts +0 -105
  350. package/tests/clients/pricing.test.ts +0 -206
  351. package/tests/clients/reasoningEffort.test.ts +0 -140
  352. package/tests/compressor/bigstring.test.ts +0 -450
  353. package/tests/compressor/bigstring.txt +0 -1
  354. package/tests/compressor/githubjson.txt +0 -1
  355. package/tests/compressor/toolResponseCache.test.ts +0 -304
  356. package/tests/compressor/usageBase64.json +0 -159
  357. package/tests/compressor/usageBase64.test.ts +0 -175
  358. package/tests/fixtures/fake-secret.txt +0 -1
  359. package/tests/manual/agent-events/run-test.ts +0 -203
  360. package/tests/manual/browser-login/README.md +0 -189
  361. package/tests/manual/browser-login/test_browser_login_basic.ts +0 -115
  362. package/tests/manual/browser-login/test_cli_integration.ts +0 -169
  363. package/tests/manual/browser-login/test_cross_platform_browser.ts +0 -186
  364. package/tests/manual/browser-login/test_error_scenarios.ts +0 -223
  365. package/tests/manual/cli/no-env.sh +0 -274
  366. package/tests/manual/clients/completions.json +0 -1151
  367. package/tests/manual/clients/completions.test.ts +0 -198
  368. package/tests/manual/file-edits/figma.test.ts +0 -3
  369. package/tests/manual/file-edits/fileblocks/readwrite.test.ts +0 -100
  370. package/tests/manual/file-edits/patching/input.txt +0 -145
  371. package/tests/manual/file-edits/patching/output.txt +0 -145
  372. package/tests/manual/file-edits/patching/patch.txt +0 -15
  373. package/tests/manual/file-edits/patching/unseen.txt +0 -80
  374. package/tests/manual/file-edits/patching.test.ts +0 -139
  375. package/tests/manual/modalities/README.md +0 -157
  376. package/tests/manual/modalities/google.modalities.test.ts +0 -335
  377. package/tests/manual/modalities/openai.modalities.test.ts +0 -329
  378. package/tests/manual/modalities/streaming.test.ts +0 -260
  379. package/tests/manual/modalities/xai.modalities.test.ts +0 -294
  380. package/tests/manual/test-concurrent-ask.ts +0 -43
  381. package/tests/manual/ycmd/debug_diagnostics_test.ts +0 -127
  382. package/tests/manual/ycmd/fixtures/debug_diagnostics.ts +0 -26
  383. package/tests/manual/ycmd/fixtures/file_change_test.ts +0 -17
  384. package/tests/manual/ycmd/minimal_advanced_test.ts +0 -108
  385. package/tests/manual/ycmd/simple_diagnostics_test.ts +0 -61
  386. package/tests/manual/ycmd/simple_test.ts +0 -74
  387. package/tests/manual/ycmd/test-typescript-sample.ts +0 -34
  388. package/tests/manual/ycmd/test_advanced_features.ts +0 -407
  389. package/tests/manual/ycmd/test_advanced_with_tools.ts +0 -320
  390. package/tests/manual/ycmd/test_comprehensive_typescript.ts +0 -179
  391. package/tests/manual/ycmd/test_diagnostics_file_changes.ts +0 -249
  392. package/tests/manual/ycmd/test_diagnostics_fix.ts +0 -99
  393. package/tests/manual/ycmd/test_diagnostics_simple.ts +0 -100
  394. package/tests/manual/ycmd/test_diagnostics_timing.ts +0 -120
  395. package/tests/manual/ycmd/test_discover_commands.ts +0 -310
  396. package/tests/manual/ycmd/test_endpoints.ts +0 -115
  397. package/tests/manual/ycmd/test_final_comprehensive.ts +0 -218
  398. package/tests/manual/ycmd/test_final_validation.ts +0 -150
  399. package/tests/manual/ycmd/test_implementation.js +0 -42
  400. package/tests/manual/ycmd/test_individual_ycmd_tool.ts +0 -39
  401. package/tests/manual/ycmd/test_server_manager.ts +0 -52
  402. package/tests/manual/ycmd/test_simple_debug.ts +0 -86
  403. package/tests/manual/ycmd/test_tsserver_workflow.js +0 -83
  404. package/tests/manual/ycmd/test_tsserver_workflow.ts +0 -122
  405. package/tests/manual/ycmd/test_typescript_simple.ts +0 -48
  406. package/tests/manual/ycmd/test_typescript_ycmd.ts +0 -105
  407. package/tests/manual/ycmd/test_workspace_config.ts +0 -90
  408. package/tests/manual/ycmd/test_ycmd_auto_start.ts +0 -137
  409. package/tests/manual/ycmd/test_ycmd_comprehensive.ts +0 -73
  410. package/tests/manual/ycmd/test_ycmd_connection.py +0 -10
  411. package/tests/manual/ycmd/test_ycmd_direct.ts +0 -142
  412. package/tests/manual/ycmd/test_ycmd_experiment.ts +0 -48
  413. package/tests/manual/ycmd/test_ycmd_final.ts +0 -200
  414. package/tests/manual/ycmd/test_ycmd_fixed.py +0 -18
  415. package/tests/manual/ycmd/test_ycmd_integration.ts +0 -112
  416. package/tests/manual/ycmd/test_ycmd_simple.ts +0 -45
  417. package/tests/manual/ycmd/test_ycmd_usage.py +0 -27
  418. package/tests/manual/ycmd/working_simple_test.ts +0 -134
  419. package/tests/patching/corrupted.test.ts +0 -78
  420. package/tests/patching/fixtures/transcript-mangles/agent-sync-fs-nested-catch.json +0 -9
  421. package/tests/patching/fixtures/transcript-mangles/automation-functions-crossed.json +0 -9
  422. package/tests/patching/fixtures/transcript-mangles/fruit-ninja-confirmed-retirement.json +0 -8
  423. package/tests/patching/imports.patch.txt +0 -11
  424. package/tests/patching/imports.test.ts +0 -43
  425. package/tests/patching/imports.txt +0 -11
  426. package/tests/patching/interface.patch.txt +0 -15
  427. package/tests/patching/interface.txt +0 -7
  428. package/tests/patching/patchFileOutput.test.ts +0 -328
  429. package/tests/patching/regression-2026.test.ts +0 -752
  430. package/tests/patching/transcriptMangleRegression.test.ts +0 -125
  431. package/tests/plugins/language/languagePlugin-content-triggers.test.ts +0 -346
  432. package/tests/plugins/language/languagePlugin-integration.test.ts +0 -471
  433. package/tests/plugins/language/languagePlugin.test.ts +0 -385
  434. package/tests/processes/managedProcessShim.test.ts +0 -59
  435. package/tests/processors/Base64ImageDetector.test.ts +0 -979
  436. package/tests/processors/CustomVariables.test.ts +0 -981
  437. package/tests/processors/CustomVariablesBenchmark.test.ts +0 -237
  438. package/tests/processors/HarmonyToolProcessor.test.ts +0 -490
  439. package/tests/processors/TokenCompressor.test.ts +0 -674
  440. package/tests/processors/ToolResponseCache.test.ts +0 -864
  441. package/tests/processors/tools/boundedRetrievalTools.test.ts +0 -68
  442. package/tests/processors/tools/grepToolResponse.test.ts +0 -159
  443. package/tests/services/ConversionService.test.ts +0 -154
  444. package/tests/services/DockerService.test.ts +0 -24
  445. package/tests/services/Tools.test.ts +0 -1738
  446. package/tests/services/ToolsService.setFunction.test.ts +0 -68
  447. package/tests/services/WorkerReloadConfig.test.ts +0 -141
  448. package/tests/test.spec.ts +0 -163
  449. package/tests/unit/InputQueueManager.test.ts +0 -174
  450. package/tests/unit/McpWebsocketTransport.test.ts +0 -56
  451. package/tests/unit/agents/historyRollback.test.ts +0 -53
  452. package/tests/unit/agents/tools/loadImageAsBase64.test.ts +0 -44
  453. package/tests/unit/auth/jwtStore.test.ts +0 -55
  454. package/tests/unit/auth/keyAuth.test.ts +0 -152
  455. package/tests/unit/auth/keyManager.test.ts +0 -130
  456. package/tests/unit/auth/registerIdentity.test.ts +0 -99
  457. package/tests/unit/chat/ToolCommandModule.test.ts +0 -71
  458. package/tests/unit/chat/historyCommandArgs.test.ts +0 -37
  459. package/tests/unit/clients/AIClient.test.ts +0 -454
  460. package/tests/unit/clients/anthropic.responseMetadata.test.ts +0 -81
  461. package/tests/unit/clients/attribution.test.ts +0 -185
  462. package/tests/unit/clients/http.responseMetadata.test.ts +0 -86
  463. package/tests/unit/clients/openai.responseMetadata.test.ts +0 -90
  464. package/tests/unit/clients/responseMetadata.test.ts +0 -123
  465. package/tests/unit/clients/withRetry.test.ts +0 -319
  466. package/tests/unit/commands/agents.test.ts +0 -111
  467. package/tests/unit/commands/github-credentials.test.ts +0 -210
  468. package/tests/unit/commands/misc.test.ts +0 -85
  469. package/tests/unit/commands/remote.test.ts +0 -79
  470. package/tests/unit/commands/sandbox.test.ts +0 -350
  471. package/tests/unit/hashes.test.ts +0 -23
  472. package/tests/unit/input-queue.test.ts +0 -80
  473. package/tests/unit/login.test.ts +0 -218
  474. package/tests/unit/modules/moduleLoading.test.ts +0 -305
  475. package/tests/unit/plugins/pluginLoading.test.ts +0 -97
  476. package/tests/unit/services/AgentSyncKnowhowWeb.test.ts +0 -38
  477. package/tests/unit/services/KnowhowClient.test.ts +0 -84
  478. package/tests/unit/services/LazyToolsService.test.ts +0 -53
  479. package/tests/unit/services/Mcp.test.ts +0 -56
  480. package/tests/unit/services/MinimalToolsService.test.ts +0 -424
  481. package/tests/unit/services/RuntimeReloadService.test.ts +0 -29
  482. package/tests/unit/services/SessionManager.test.ts +0 -43
  483. package/tests/unit/services/SyncedAgentWatcher.test.ts +0 -89
  484. package/tests/unit/services/SyncerService.test.ts +0 -45
  485. package/tests/unit/tunnel.test.ts +0 -51
  486. package/tests/unit/util/Trace.test.ts +0 -119
  487. package/tests/unit/utils/http.test.ts +0 -43
  488. package/ts_build/tests/XmlToolCallProcessor.test.d.ts +0 -1
  489. package/ts_build/tests/XmlToolCallProcessor.test.js +0 -376
  490. package/ts_build/tests/XmlToolCallProcessor.test.js.map +0 -1
  491. package/ts_build/tests/agents/interrupt.test.d.ts +0 -14
  492. package/ts_build/tests/agents/interrupt.test.js +0 -136
  493. package/ts_build/tests/agents/interrupt.test.js.map +0 -1
  494. package/ts_build/tests/agents/observe-base.test.d.ts +0 -1
  495. package/ts_build/tests/agents/observe-base.test.js +0 -149
  496. package/ts_build/tests/agents/observe-base.test.js.map +0 -1
  497. package/ts_build/tests/agents/tools/connectAgent.test.d.ts +0 -1
  498. package/ts_build/tests/agents/tools/connectAgent.test.js +0 -142
  499. package/ts_build/tests/agents/tools/connectAgent.test.js.map +0 -1
  500. package/ts_build/tests/agents/tools/observe.test.d.ts +0 -1
  501. package/ts_build/tests/agents/tools/observe.test.js +0 -148
  502. package/ts_build/tests/agents/tools/observe.test.js.map +0 -1
  503. package/ts_build/tests/agents/tools/readFile.test.d.ts +0 -1
  504. package/ts_build/tests/agents/tools/readFile.test.js +0 -90
  505. package/ts_build/tests/agents/tools/readFile.test.js.map +0 -1
  506. package/ts_build/tests/agents/tools/replyToParent.test.d.ts +0 -1
  507. package/ts_build/tests/agents/tools/replyToParent.test.js +0 -116
  508. package/ts_build/tests/agents/tools/replyToParent.test.js.map +0 -1
  509. package/ts_build/tests/agents/tools/sendAgentMessage.test.d.ts +0 -1
  510. package/ts_build/tests/agents/tools/sendAgentMessage.test.js +0 -112
  511. package/ts_build/tests/agents/tools/sendAgentMessage.test.js.map +0 -1
  512. package/ts_build/tests/agents/tools/waitForAgentCompleted.test.d.ts +0 -1
  513. package/ts_build/tests/agents/tools/waitForAgentCompleted.test.js +0 -147
  514. package/ts_build/tests/agents/tools/waitForAgentCompleted.test.js.map +0 -1
  515. package/ts_build/tests/chat/detach-attach-rendering.test.d.ts +0 -1
  516. package/ts_build/tests/chat/detach-attach-rendering.test.js +0 -168
  517. package/ts_build/tests/chat/detach-attach-rendering.test.js.map +0 -1
  518. package/ts_build/tests/clients/AIClient.test.d.ts +0 -1
  519. package/ts_build/tests/clients/AIClient.test.js +0 -483
  520. package/ts_build/tests/clients/AIClient.test.js.map +0 -1
  521. package/ts_build/tests/clients/anthropic.test.d.ts +0 -1
  522. package/ts_build/tests/clients/anthropic.test.js +0 -159
  523. package/ts_build/tests/clients/anthropic.test.js.map +0 -1
  524. package/ts_build/tests/clients/contextLimits.test.d.ts +0 -1
  525. package/ts_build/tests/clients/contextLimits.test.js +0 -69
  526. package/ts_build/tests/clients/contextLimits.test.js.map +0 -1
  527. package/ts_build/tests/clients/fireworks.test.d.ts +0 -1
  528. package/ts_build/tests/clients/fireworks.test.js +0 -65
  529. package/ts_build/tests/clients/fireworks.test.js.map +0 -1
  530. package/ts_build/tests/clients/openai.images.test.d.ts +0 -1
  531. package/ts_build/tests/clients/openai.images.test.js +0 -94
  532. package/ts_build/tests/clients/openai.images.test.js.map +0 -1
  533. package/ts_build/tests/clients/pricing.test.d.ts +0 -1
  534. package/ts_build/tests/clients/pricing.test.js +0 -124
  535. package/ts_build/tests/clients/pricing.test.js.map +0 -1
  536. package/ts_build/tests/clients/reasoningEffort.test.d.ts +0 -1
  537. package/ts_build/tests/clients/reasoningEffort.test.js +0 -116
  538. package/ts_build/tests/clients/reasoningEffort.test.js.map +0 -1
  539. package/ts_build/tests/compressor/bigstring.test.d.ts +0 -1
  540. package/ts_build/tests/compressor/bigstring.test.js +0 -275
  541. package/ts_build/tests/compressor/bigstring.test.js.map +0 -1
  542. package/ts_build/tests/compressor/toolResponseCache.test.d.ts +0 -1
  543. package/ts_build/tests/compressor/toolResponseCache.test.js +0 -250
  544. package/ts_build/tests/compressor/toolResponseCache.test.js.map +0 -1
  545. package/ts_build/tests/compressor/usageBase64.test.d.ts +0 -1
  546. package/ts_build/tests/compressor/usageBase64.test.js +0 -109
  547. package/ts_build/tests/compressor/usageBase64.test.js.map +0 -1
  548. package/ts_build/tests/manual/agent-events/run-test.d.ts +0 -2
  549. package/ts_build/tests/manual/agent-events/run-test.js +0 -148
  550. package/ts_build/tests/manual/agent-events/run-test.js.map +0 -1
  551. package/ts_build/tests/manual/browser-login/test_browser_login_basic.d.ts +0 -2
  552. package/ts_build/tests/manual/browser-login/test_browser_login_basic.js +0 -118
  553. package/ts_build/tests/manual/browser-login/test_browser_login_basic.js.map +0 -1
  554. package/ts_build/tests/manual/browser-login/test_cli_integration.d.ts +0 -2
  555. package/ts_build/tests/manual/browser-login/test_cli_integration.js +0 -163
  556. package/ts_build/tests/manual/browser-login/test_cli_integration.js.map +0 -1
  557. package/ts_build/tests/manual/browser-login/test_cross_platform_browser.d.ts +0 -2
  558. package/ts_build/tests/manual/browser-login/test_cross_platform_browser.js +0 -169
  559. package/ts_build/tests/manual/browser-login/test_cross_platform_browser.js.map +0 -1
  560. package/ts_build/tests/manual/browser-login/test_error_scenarios.d.ts +0 -2
  561. package/ts_build/tests/manual/browser-login/test_error_scenarios.js +0 -207
  562. package/ts_build/tests/manual/browser-login/test_error_scenarios.js.map +0 -1
  563. package/ts_build/tests/manual/clients/completions.test.d.ts +0 -1
  564. package/ts_build/tests/manual/clients/completions.test.js +0 -151
  565. package/ts_build/tests/manual/clients/completions.test.js.map +0 -1
  566. package/ts_build/tests/manual/file-edits/figma.test.d.ts +0 -0
  567. package/ts_build/tests/manual/file-edits/figma.test.js +0 -2
  568. package/ts_build/tests/manual/file-edits/figma.test.js.map +0 -1
  569. package/ts_build/tests/manual/file-edits/fileblocks/readwrite.test.d.ts +0 -1
  570. package/ts_build/tests/manual/file-edits/fileblocks/readwrite.test.js +0 -110
  571. package/ts_build/tests/manual/file-edits/fileblocks/readwrite.test.js.map +0 -1
  572. package/ts_build/tests/manual/file-edits/patching.test.d.ts +0 -1
  573. package/ts_build/tests/manual/file-edits/patching.test.js +0 -129
  574. package/ts_build/tests/manual/file-edits/patching.test.js.map +0 -1
  575. package/ts_build/tests/manual/modalities/google.modalities.test.d.ts +0 -1
  576. package/ts_build/tests/manual/modalities/google.modalities.test.js +0 -262
  577. package/ts_build/tests/manual/modalities/google.modalities.test.js.map +0 -1
  578. package/ts_build/tests/manual/modalities/openai.modalities.test.d.ts +0 -1
  579. package/ts_build/tests/manual/modalities/openai.modalities.test.js +0 -262
  580. package/ts_build/tests/manual/modalities/openai.modalities.test.js.map +0 -1
  581. package/ts_build/tests/manual/modalities/streaming.test.d.ts +0 -1
  582. package/ts_build/tests/manual/modalities/streaming.test.js +0 -216
  583. package/ts_build/tests/manual/modalities/streaming.test.js.map +0 -1
  584. package/ts_build/tests/manual/modalities/xai.modalities.test.d.ts +0 -1
  585. package/ts_build/tests/manual/modalities/xai.modalities.test.js +0 -219
  586. package/ts_build/tests/manual/modalities/xai.modalities.test.js.map +0 -1
  587. package/ts_build/tests/manual/test-concurrent-ask.d.ts +0 -1
  588. package/ts_build/tests/manual/test-concurrent-ask.js +0 -22
  589. package/ts_build/tests/manual/test-concurrent-ask.js.map +0 -1
  590. package/ts_build/tests/manual/ycmd/debug_diagnostics_test.d.ts +0 -1
  591. package/ts_build/tests/manual/ycmd/debug_diagnostics_test.js +0 -124
  592. package/ts_build/tests/manual/ycmd/debug_diagnostics_test.js.map +0 -1
  593. package/ts_build/tests/manual/ycmd/minimal_advanced_test.d.ts +0 -2
  594. package/ts_build/tests/manual/ycmd/minimal_advanced_test.js +0 -114
  595. package/ts_build/tests/manual/ycmd/minimal_advanced_test.js.map +0 -1
  596. package/ts_build/tests/manual/ycmd/simple_diagnostics_test.d.ts +0 -1
  597. package/ts_build/tests/manual/ycmd/simple_diagnostics_test.js +0 -84
  598. package/ts_build/tests/manual/ycmd/simple_diagnostics_test.js.map +0 -1
  599. package/ts_build/tests/manual/ycmd/simple_test.d.ts +0 -2
  600. package/ts_build/tests/manual/ycmd/simple_test.js +0 -92
  601. package/ts_build/tests/manual/ycmd/simple_test.js.map +0 -1
  602. package/ts_build/tests/manual/ycmd/test-typescript-sample.d.ts +0 -14
  603. package/ts_build/tests/manual/ycmd/test-typescript-sample.js +0 -20
  604. package/ts_build/tests/manual/ycmd/test-typescript-sample.js.map +0 -1
  605. package/ts_build/tests/manual/ycmd/test_advanced_features.d.ts +0 -2
  606. package/ts_build/tests/manual/ycmd/test_advanced_features.js +0 -306
  607. package/ts_build/tests/manual/ycmd/test_advanced_features.js.map +0 -1
  608. package/ts_build/tests/manual/ycmd/test_advanced_with_tools.d.ts +0 -3
  609. package/ts_build/tests/manual/ycmd/test_advanced_with_tools.js +0 -271
  610. package/ts_build/tests/manual/ycmd/test_advanced_with_tools.js.map +0 -1
  611. package/ts_build/tests/manual/ycmd/test_comprehensive_typescript.d.ts +0 -2
  612. package/ts_build/tests/manual/ycmd/test_comprehensive_typescript.js +0 -196
  613. package/ts_build/tests/manual/ycmd/test_comprehensive_typescript.js.map +0 -1
  614. package/ts_build/tests/manual/ycmd/test_diagnostics_file_changes.d.ts +0 -1
  615. package/ts_build/tests/manual/ycmd/test_diagnostics_file_changes.js +0 -184
  616. package/ts_build/tests/manual/ycmd/test_diagnostics_file_changes.js.map +0 -1
  617. package/ts_build/tests/manual/ycmd/test_diagnostics_fix.d.ts +0 -2
  618. package/ts_build/tests/manual/ycmd/test_diagnostics_fix.js +0 -116
  619. package/ts_build/tests/manual/ycmd/test_diagnostics_fix.js.map +0 -1
  620. package/ts_build/tests/manual/ycmd/test_diagnostics_simple.d.ts +0 -1
  621. package/ts_build/tests/manual/ycmd/test_diagnostics_simple.js +0 -114
  622. package/ts_build/tests/manual/ycmd/test_diagnostics_simple.js.map +0 -1
  623. package/ts_build/tests/manual/ycmd/test_diagnostics_timing.d.ts +0 -1
  624. package/ts_build/tests/manual/ycmd/test_diagnostics_timing.js +0 -129
  625. package/ts_build/tests/manual/ycmd/test_diagnostics_timing.js.map +0 -1
  626. package/ts_build/tests/manual/ycmd/test_discover_commands.d.ts +0 -2
  627. package/ts_build/tests/manual/ycmd/test_discover_commands.js +0 -252
  628. package/ts_build/tests/manual/ycmd/test_discover_commands.js.map +0 -1
  629. package/ts_build/tests/manual/ycmd/test_endpoints.d.ts +0 -2
  630. package/ts_build/tests/manual/ycmd/test_endpoints.js +0 -130
  631. package/ts_build/tests/manual/ycmd/test_endpoints.js.map +0 -1
  632. package/ts_build/tests/manual/ycmd/test_final_comprehensive.d.ts +0 -2
  633. package/ts_build/tests/manual/ycmd/test_final_comprehensive.js +0 -231
  634. package/ts_build/tests/manual/ycmd/test_final_comprehensive.js.map +0 -1
  635. package/ts_build/tests/manual/ycmd/test_final_validation.d.ts +0 -2
  636. package/ts_build/tests/manual/ycmd/test_final_validation.js +0 -170
  637. package/ts_build/tests/manual/ycmd/test_final_validation.js.map +0 -1
  638. package/ts_build/tests/manual/ycmd/test_individual_ycmd_tool.d.ts +0 -2
  639. package/ts_build/tests/manual/ycmd/test_individual_ycmd_tool.js +0 -37
  640. package/ts_build/tests/manual/ycmd/test_individual_ycmd_tool.js.map +0 -1
  641. package/ts_build/tests/manual/ycmd/test_server_manager.d.ts +0 -1
  642. package/ts_build/tests/manual/ycmd/test_server_manager.js +0 -38
  643. package/ts_build/tests/manual/ycmd/test_server_manager.js.map +0 -1
  644. package/ts_build/tests/manual/ycmd/test_simple_debug.d.ts +0 -2
  645. package/ts_build/tests/manual/ycmd/test_simple_debug.js +0 -109
  646. package/ts_build/tests/manual/ycmd/test_simple_debug.js.map +0 -1
  647. package/ts_build/tests/manual/ycmd/test_tsserver_workflow.d.ts +0 -1
  648. package/ts_build/tests/manual/ycmd/test_tsserver_workflow.js +0 -138
  649. package/ts_build/tests/manual/ycmd/test_tsserver_workflow.js.map +0 -1
  650. package/ts_build/tests/manual/ycmd/test_typescript_simple.d.ts +0 -1
  651. package/ts_build/tests/manual/ycmd/test_typescript_simple.js +0 -76
  652. package/ts_build/tests/manual/ycmd/test_typescript_simple.js.map +0 -1
  653. package/ts_build/tests/manual/ycmd/test_typescript_ycmd.d.ts +0 -1
  654. package/ts_build/tests/manual/ycmd/test_typescript_ycmd.js +0 -115
  655. package/ts_build/tests/manual/ycmd/test_typescript_ycmd.js.map +0 -1
  656. package/ts_build/tests/manual/ycmd/test_workspace_config.d.ts +0 -1
  657. package/ts_build/tests/manual/ycmd/test_workspace_config.js +0 -99
  658. package/ts_build/tests/manual/ycmd/test_workspace_config.js.map +0 -1
  659. package/ts_build/tests/manual/ycmd/test_ycmd_auto_start.d.ts +0 -2
  660. package/ts_build/tests/manual/ycmd/test_ycmd_auto_start.js +0 -140
  661. package/ts_build/tests/manual/ycmd/test_ycmd_auto_start.js.map +0 -1
  662. package/ts_build/tests/manual/ycmd/test_ycmd_comprehensive.d.ts +0 -1
  663. package/ts_build/tests/manual/ycmd/test_ycmd_comprehensive.js +0 -93
  664. package/ts_build/tests/manual/ycmd/test_ycmd_comprehensive.js.map +0 -1
  665. package/ts_build/tests/manual/ycmd/test_ycmd_direct.d.ts +0 -2
  666. package/ts_build/tests/manual/ycmd/test_ycmd_direct.js +0 -159
  667. package/ts_build/tests/manual/ycmd/test_ycmd_direct.js.map +0 -1
  668. package/ts_build/tests/manual/ycmd/test_ycmd_experiment.d.ts +0 -15
  669. package/ts_build/tests/manual/ycmd/test_ycmd_experiment.js +0 -68
  670. package/ts_build/tests/manual/ycmd/test_ycmd_experiment.js.map +0 -1
  671. package/ts_build/tests/manual/ycmd/test_ycmd_final.d.ts +0 -2
  672. package/ts_build/tests/manual/ycmd/test_ycmd_final.js +0 -205
  673. package/ts_build/tests/manual/ycmd/test_ycmd_final.js.map +0 -1
  674. package/ts_build/tests/manual/ycmd/test_ycmd_integration.d.ts +0 -3
  675. package/ts_build/tests/manual/ycmd/test_ycmd_integration.js +0 -119
  676. package/ts_build/tests/manual/ycmd/test_ycmd_integration.js.map +0 -1
  677. package/ts_build/tests/manual/ycmd/test_ycmd_simple.d.ts +0 -2
  678. package/ts_build/tests/manual/ycmd/test_ycmd_simple.js +0 -36
  679. package/ts_build/tests/manual/ycmd/test_ycmd_simple.js.map +0 -1
  680. package/ts_build/tests/manual/ycmd/working_simple_test.d.ts +0 -2
  681. package/ts_build/tests/manual/ycmd/working_simple_test.js +0 -144
  682. package/ts_build/tests/manual/ycmd/working_simple_test.js.map +0 -1
  683. package/ts_build/tests/patching/corrupted.test.d.ts +0 -1
  684. package/ts_build/tests/patching/corrupted.test.js +0 -53
  685. package/ts_build/tests/patching/corrupted.test.js.map +0 -1
  686. package/ts_build/tests/patching/imports.test.d.ts +0 -1
  687. package/ts_build/tests/patching/imports.test.js +0 -71
  688. package/ts_build/tests/patching/imports.test.js.map +0 -1
  689. package/ts_build/tests/patching/patchFileOutput.test.d.ts +0 -1
  690. package/ts_build/tests/patching/patchFileOutput.test.js +0 -269
  691. package/ts_build/tests/patching/patchFileOutput.test.js.map +0 -1
  692. package/ts_build/tests/patching/regression-2026.test.d.ts +0 -1
  693. package/ts_build/tests/patching/regression-2026.test.js +0 -528
  694. package/ts_build/tests/patching/regression-2026.test.js.map +0 -1
  695. package/ts_build/tests/patching/transcriptMangleRegression.test.d.ts +0 -1
  696. package/ts_build/tests/patching/transcriptMangleRegression.test.js +0 -104
  697. package/ts_build/tests/patching/transcriptMangleRegression.test.js.map +0 -1
  698. package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.d.ts +0 -1
  699. package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js +0 -294
  700. package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js.map +0 -1
  701. package/ts_build/tests/plugins/language/languagePlugin-integration.test.d.ts +0 -1
  702. package/ts_build/tests/plugins/language/languagePlugin-integration.test.js +0 -343
  703. package/ts_build/tests/plugins/language/languagePlugin-integration.test.js.map +0 -1
  704. package/ts_build/tests/plugins/language/languagePlugin.test.d.ts +0 -1
  705. package/ts_build/tests/plugins/language/languagePlugin.test.js +0 -315
  706. package/ts_build/tests/plugins/language/languagePlugin.test.js.map +0 -1
  707. package/ts_build/tests/processes/managedProcessShim.test.d.ts +0 -1
  708. package/ts_build/tests/processes/managedProcessShim.test.js +0 -92
  709. package/ts_build/tests/processes/managedProcessShim.test.js.map +0 -1
  710. package/ts_build/tests/processors/Base64ImageDetector.test.d.ts +0 -1
  711. package/ts_build/tests/processors/Base64ImageDetector.test.js +0 -792
  712. package/ts_build/tests/processors/Base64ImageDetector.test.js.map +0 -1
  713. package/ts_build/tests/processors/CustomVariables.test.d.ts +0 -1
  714. package/ts_build/tests/processors/CustomVariables.test.js +0 -764
  715. package/ts_build/tests/processors/CustomVariables.test.js.map +0 -1
  716. package/ts_build/tests/processors/CustomVariablesBenchmark.test.d.ts +0 -1
  717. package/ts_build/tests/processors/CustomVariablesBenchmark.test.js +0 -179
  718. package/ts_build/tests/processors/CustomVariablesBenchmark.test.js.map +0 -1
  719. package/ts_build/tests/processors/HarmonyToolProcessor.test.d.ts +0 -1
  720. package/ts_build/tests/processors/HarmonyToolProcessor.test.js +0 -382
  721. package/ts_build/tests/processors/HarmonyToolProcessor.test.js.map +0 -1
  722. package/ts_build/tests/processors/TokenCompressor.test.d.ts +0 -1
  723. package/ts_build/tests/processors/TokenCompressor.test.js +0 -473
  724. package/ts_build/tests/processors/TokenCompressor.test.js.map +0 -1
  725. package/ts_build/tests/processors/ToolResponseCache.test.d.ts +0 -1
  726. package/ts_build/tests/processors/ToolResponseCache.test.js +0 -657
  727. package/ts_build/tests/processors/ToolResponseCache.test.js.map +0 -1
  728. package/ts_build/tests/processors/tools/boundedRetrievalTools.test.d.ts +0 -1
  729. package/ts_build/tests/processors/tools/boundedRetrievalTools.test.js +0 -57
  730. package/ts_build/tests/processors/tools/boundedRetrievalTools.test.js.map +0 -1
  731. package/ts_build/tests/processors/tools/grepToolResponse.test.d.ts +0 -1
  732. package/ts_build/tests/processors/tools/grepToolResponse.test.js +0 -77
  733. package/ts_build/tests/processors/tools/grepToolResponse.test.js.map +0 -1
  734. package/ts_build/tests/services/ConversionService.test.d.ts +0 -1
  735. package/ts_build/tests/services/ConversionService.test.js +0 -154
  736. package/ts_build/tests/services/ConversionService.test.js.map +0 -1
  737. package/ts_build/tests/services/DockerService.test.d.ts +0 -1
  738. package/ts_build/tests/services/DockerService.test.js +0 -22
  739. package/ts_build/tests/services/DockerService.test.js.map +0 -1
  740. package/ts_build/tests/services/Tools.test.d.ts +0 -1
  741. package/ts_build/tests/services/Tools.test.js +0 -1365
  742. package/ts_build/tests/services/Tools.test.js.map +0 -1
  743. package/ts_build/tests/services/ToolsService.setFunction.test.d.ts +0 -1
  744. package/ts_build/tests/services/ToolsService.setFunction.test.js +0 -51
  745. package/ts_build/tests/services/ToolsService.setFunction.test.js.map +0 -1
  746. package/ts_build/tests/services/WorkerReloadConfig.test.d.ts +0 -1
  747. package/ts_build/tests/services/WorkerReloadConfig.test.js +0 -86
  748. package/ts_build/tests/services/WorkerReloadConfig.test.js.map +0 -1
  749. package/ts_build/tests/test.spec.d.ts +0 -1
  750. package/ts_build/tests/test.spec.js +0 -139
  751. package/ts_build/tests/test.spec.js.map +0 -1
  752. package/ts_build/tests/unit/InputQueueManager.test.d.ts +0 -1
  753. package/ts_build/tests/unit/InputQueueManager.test.js +0 -104
  754. package/ts_build/tests/unit/InputQueueManager.test.js.map +0 -1
  755. package/ts_build/tests/unit/McpWebsocketTransport.test.d.ts +0 -1
  756. package/ts_build/tests/unit/McpWebsocketTransport.test.js +0 -47
  757. package/ts_build/tests/unit/McpWebsocketTransport.test.js.map +0 -1
  758. package/ts_build/tests/unit/agents/historyRollback.test.d.ts +0 -1
  759. package/ts_build/tests/unit/agents/historyRollback.test.js +0 -42
  760. package/ts_build/tests/unit/agents/historyRollback.test.js.map +0 -1
  761. package/ts_build/tests/unit/agents/tools/loadImageAsBase64.test.d.ts +0 -1
  762. package/ts_build/tests/unit/agents/tools/loadImageAsBase64.test.js +0 -67
  763. package/ts_build/tests/unit/agents/tools/loadImageAsBase64.test.js.map +0 -1
  764. package/ts_build/tests/unit/auth/jwtStore.test.d.ts +0 -1
  765. package/ts_build/tests/unit/auth/jwtStore.test.js +0 -46
  766. package/ts_build/tests/unit/auth/jwtStore.test.js.map +0 -1
  767. package/ts_build/tests/unit/auth/keyAuth.test.d.ts +0 -1
  768. package/ts_build/tests/unit/auth/keyAuth.test.js +0 -118
  769. package/ts_build/tests/unit/auth/keyAuth.test.js.map +0 -1
  770. package/ts_build/tests/unit/auth/keyManager.test.d.ts +0 -1
  771. package/ts_build/tests/unit/auth/keyManager.test.js +0 -96
  772. package/ts_build/tests/unit/auth/keyManager.test.js.map +0 -1
  773. package/ts_build/tests/unit/auth/registerIdentity.test.d.ts +0 -1
  774. package/ts_build/tests/unit/auth/registerIdentity.test.js +0 -92
  775. package/ts_build/tests/unit/auth/registerIdentity.test.js.map +0 -1
  776. package/ts_build/tests/unit/chat/ToolCommandModule.test.d.ts +0 -1
  777. package/ts_build/tests/unit/chat/ToolCommandModule.test.js +0 -61
  778. package/ts_build/tests/unit/chat/ToolCommandModule.test.js.map +0 -1
  779. package/ts_build/tests/unit/chat/historyCommandArgs.test.d.ts +0 -1
  780. package/ts_build/tests/unit/chat/historyCommandArgs.test.js +0 -29
  781. package/ts_build/tests/unit/chat/historyCommandArgs.test.js.map +0 -1
  782. package/ts_build/tests/unit/clients/AIClient.test.d.ts +0 -1
  783. package/ts_build/tests/unit/clients/AIClient.test.js +0 -342
  784. package/ts_build/tests/unit/clients/AIClient.test.js.map +0 -1
  785. package/ts_build/tests/unit/clients/anthropic.responseMetadata.test.d.ts +0 -1
  786. package/ts_build/tests/unit/clients/anthropic.responseMetadata.test.js +0 -77
  787. package/ts_build/tests/unit/clients/anthropic.responseMetadata.test.js.map +0 -1
  788. package/ts_build/tests/unit/clients/attribution.test.d.ts +0 -1
  789. package/ts_build/tests/unit/clients/attribution.test.js +0 -153
  790. package/ts_build/tests/unit/clients/attribution.test.js.map +0 -1
  791. package/ts_build/tests/unit/clients/http.responseMetadata.test.d.ts +0 -1
  792. package/ts_build/tests/unit/clients/http.responseMetadata.test.js +0 -77
  793. package/ts_build/tests/unit/clients/http.responseMetadata.test.js.map +0 -1
  794. package/ts_build/tests/unit/clients/openai.responseMetadata.test.d.ts +0 -1
  795. package/ts_build/tests/unit/clients/openai.responseMetadata.test.js +0 -86
  796. package/ts_build/tests/unit/clients/openai.responseMetadata.test.js.map +0 -1
  797. package/ts_build/tests/unit/clients/responseMetadata.test.d.ts +0 -1
  798. package/ts_build/tests/unit/clients/responseMetadata.test.js +0 -96
  799. package/ts_build/tests/unit/clients/responseMetadata.test.js.map +0 -1
  800. package/ts_build/tests/unit/clients/withRetry.test.d.ts +0 -1
  801. package/ts_build/tests/unit/clients/withRetry.test.js +0 -225
  802. package/ts_build/tests/unit/clients/withRetry.test.js.map +0 -1
  803. package/ts_build/tests/unit/commands/agents.test.d.ts +0 -1
  804. package/ts_build/tests/unit/commands/agents.test.js +0 -119
  805. package/ts_build/tests/unit/commands/agents.test.js.map +0 -1
  806. package/ts_build/tests/unit/commands/github-credentials.test.d.ts +0 -1
  807. package/ts_build/tests/unit/commands/github-credentials.test.js +0 -145
  808. package/ts_build/tests/unit/commands/github-credentials.test.js.map +0 -1
  809. package/ts_build/tests/unit/commands/misc.test.d.ts +0 -1
  810. package/ts_build/tests/unit/commands/misc.test.js +0 -70
  811. package/ts_build/tests/unit/commands/misc.test.js.map +0 -1
  812. package/ts_build/tests/unit/commands/remote.test.d.ts +0 -1
  813. package/ts_build/tests/unit/commands/remote.test.js +0 -70
  814. package/ts_build/tests/unit/commands/remote.test.js.map +0 -1
  815. package/ts_build/tests/unit/commands/sandbox.test.d.ts +0 -1
  816. package/ts_build/tests/unit/commands/sandbox.test.js +0 -258
  817. package/ts_build/tests/unit/commands/sandbox.test.js.map +0 -1
  818. package/ts_build/tests/unit/hashes.test.d.ts +0 -1
  819. package/ts_build/tests/unit/hashes.test.js +0 -25
  820. package/ts_build/tests/unit/hashes.test.js.map +0 -1
  821. package/ts_build/tests/unit/input-queue.test.d.ts +0 -1
  822. package/ts_build/tests/unit/input-queue.test.js +0 -32
  823. package/ts_build/tests/unit/input-queue.test.js.map +0 -1
  824. package/ts_build/tests/unit/login.test.d.ts +0 -1
  825. package/ts_build/tests/unit/login.test.js +0 -166
  826. package/ts_build/tests/unit/login.test.js.map +0 -1
  827. package/ts_build/tests/unit/modules/moduleLoading.test.d.ts +0 -1
  828. package/ts_build/tests/unit/modules/moduleLoading.test.js +0 -272
  829. package/ts_build/tests/unit/modules/moduleLoading.test.js.map +0 -1
  830. package/ts_build/tests/unit/plugins/pluginLoading.test.d.ts +0 -1
  831. package/ts_build/tests/unit/plugins/pluginLoading.test.js +0 -117
  832. package/ts_build/tests/unit/plugins/pluginLoading.test.js.map +0 -1
  833. package/ts_build/tests/unit/services/AgentSyncKnowhowWeb.test.d.ts +0 -1
  834. package/ts_build/tests/unit/services/AgentSyncKnowhowWeb.test.js +0 -32
  835. package/ts_build/tests/unit/services/AgentSyncKnowhowWeb.test.js.map +0 -1
  836. package/ts_build/tests/unit/services/KnowhowClient.test.d.ts +0 -1
  837. package/ts_build/tests/unit/services/KnowhowClient.test.js +0 -69
  838. package/ts_build/tests/unit/services/KnowhowClient.test.js.map +0 -1
  839. package/ts_build/tests/unit/services/LazyToolsService.test.d.ts +0 -1
  840. package/ts_build/tests/unit/services/LazyToolsService.test.js +0 -47
  841. package/ts_build/tests/unit/services/LazyToolsService.test.js.map +0 -1
  842. package/ts_build/tests/unit/services/Mcp.test.d.ts +0 -1
  843. package/ts_build/tests/unit/services/Mcp.test.js +0 -45
  844. package/ts_build/tests/unit/services/Mcp.test.js.map +0 -1
  845. package/ts_build/tests/unit/services/MinimalToolsService.test.d.ts +0 -1
  846. package/ts_build/tests/unit/services/MinimalToolsService.test.js +0 -320
  847. package/ts_build/tests/unit/services/MinimalToolsService.test.js.map +0 -1
  848. package/ts_build/tests/unit/services/RuntimeReloadService.test.d.ts +0 -1
  849. package/ts_build/tests/unit/services/RuntimeReloadService.test.js +0 -26
  850. package/ts_build/tests/unit/services/RuntimeReloadService.test.js.map +0 -1
  851. package/ts_build/tests/unit/services/SessionManager.test.d.ts +0 -1
  852. package/ts_build/tests/unit/services/SessionManager.test.js +0 -72
  853. package/ts_build/tests/unit/services/SessionManager.test.js.map +0 -1
  854. package/ts_build/tests/unit/services/SyncedAgentWatcher.test.d.ts +0 -1
  855. package/ts_build/tests/unit/services/SyncedAgentWatcher.test.js +0 -78
  856. package/ts_build/tests/unit/services/SyncedAgentWatcher.test.js.map +0 -1
  857. package/ts_build/tests/unit/services/SyncerService.test.d.ts +0 -1
  858. package/ts_build/tests/unit/services/SyncerService.test.js +0 -40
  859. package/ts_build/tests/unit/services/SyncerService.test.js.map +0 -1
  860. package/ts_build/tests/unit/tunnel.test.d.ts +0 -1
  861. package/ts_build/tests/unit/tunnel.test.js +0 -47
  862. package/ts_build/tests/unit/tunnel.test.js.map +0 -1
  863. package/ts_build/tests/unit/util/Trace.test.d.ts +0 -1
  864. package/ts_build/tests/unit/util/Trace.test.js +0 -107
  865. package/ts_build/tests/unit/util/Trace.test.js.map +0 -1
  866. package/ts_build/tests/unit/utils/http.test.d.ts +0 -1
  867. package/ts_build/tests/unit/utils/http.test.js +0 -69
  868. package/ts_build/tests/unit/utils/http.test.js.map +0 -1
  869. package/tsconfig.json +0 -34
  870. package/tslint.json +0 -11
@@ -1,1963 +0,0 @@
1
- import { EventEmitter } from "events"; // kept for reference; agentEvents now uses EventService
2
- import {
3
- CompletionResponse,
4
- CompletionOptions,
5
- GenericClient,
6
- Message,
7
- MessageContent,
8
- OutputMessage,
9
- Tool,
10
- ToolCall,
11
- } from "../../clients/types";
12
- import { IAgent } from "../interface";
13
- import { ToolsService } from "../../services/Tools";
14
- import {
15
- mcpToolName,
16
- replaceEscapedNewLines,
17
- restoreEscapedNewLines,
18
- } from "../../utils";
19
- import { EventService } from "../../services/EventService";
20
- import { AIClient, Clients } from "../../clients";
21
- import { Models } from "../../ai";
22
- import { MessageProcessor } from "../../services/MessageProcessor";
23
- import { DEFAULT_CONTEXT_LIMIT } from "../../clients/contextLimits";
24
- import { Marked } from "../../utils";
25
- import { TraceAll } from "../../util/Trace";
26
-
27
- export { Message, Tool, ToolCall };
28
- export interface ModelPreference {
29
- model: string;
30
- provider: keyof typeof Clients.clients;
31
- reasoning_effort?: CompletionOptions["reasoning_effort"];
32
- reasoning_summary?: boolean;
33
- }
34
-
35
- export interface AgentContext {
36
- Tools?: ToolsService;
37
- Events?: EventService;
38
- messageProcessor?: MessageProcessor;
39
- Clients?: AIClient;
40
- }
41
-
42
- export interface ToolCallEvent {
43
- toolCall: ToolCall;
44
- functionResp: any;
45
- }
46
-
47
- type ChatCompletion = Parameters<GenericClient["createChatCompletion"]>[0];
48
- type CachedChatCompletion = { messages: ChatCompletion["messages"] } & Partial<
49
- Omit<ChatCompletion, "messages">
50
- >;
51
-
52
- interface CompletedCompaction {
53
- compressionEnd: number;
54
- originalPrefix: Message[];
55
- replacementPrefix: Message[];
56
- summary: string;
57
- }
58
-
59
- /**
60
- * A source is anything that can (a) start producing data, (b) hand each datum to
61
- * a callback, and (c) be torn down. This is the unified contract behind
62
- * `agent.observe()` — tool polls, events, streams, promises, peer agent threads,
63
- * file tails, etc. all become adapters that satisfy this shape.
64
- */
65
- export interface ObservationSource {
66
- /** Human-friendly label for logs / delivered messages. */
67
- label: string;
68
- /**
69
- * Begin producing. Call `emit(datum)` for each piece of data. Return a
70
- * teardown function (or void). May be sync or async.
71
- */
72
- start(
73
- emit: (datum: unknown) => void
74
- ): void | (() => void) | Promise<void | (() => void)>;
75
- }
76
-
77
- export interface ObserveOpts {
78
- /** Only deliver when the datum changed since the last emit. Default true. */
79
- onlyOnChange?: boolean;
80
- /** Max number of updates before auto-stopping. Default 20. */
81
- maxUpdates?: number;
82
- /** Max total duration in ms before auto-stopping. Default 10 min. */
83
- maxDurationMs?: number;
84
- }
85
-
86
- interface ActiveObservation {
87
- id: string;
88
- label: string;
89
- updates: number;
90
- teardownPromise: Promise<void | (() => void)>;
91
- expiry?: NodeJS.Timeout;
92
- }
93
-
94
- @TraceAll()
95
- export abstract class BaseAgent implements IAgent {
96
- abstract name: string;
97
- abstract description: string;
98
-
99
- private status = "not_started";
100
- private lastHealthCheckTime: number = 0;
101
- protected provider = "openai";
102
- protected modelName: string = Models.openai.GPT_4o;
103
- protected client: null | GenericClient = null;
104
- protected modelPreferences: ModelPreference[] = [];
105
- protected currentModelPreferenceIndex = 0;
106
- protected easyFinalAnswer = false;
107
- protected requiredToolNames = ["finalAnswer"];
108
- protected maxTurns: number | null = null;
109
- protected maxSpend: number | null = null;
110
- protected maxRunTimeMs: number | null = null;
111
- protected startTimeMs: number | null = null;
112
- protected turnCount = 0;
113
- protected totalCostUsd = 0;
114
- protected currentThread = 0;
115
- protected reasoningEffort: CompletionOptions["reasoning_effort"] | undefined =
116
- undefined;
117
- protected summarizeReasoning: boolean | undefined = undefined;
118
- protected totalInputTokens = 0;
119
- protected totalOutputTokens = 0;
120
- protected totalCacheReadTokens = 0;
121
- protected totalCacheWriteTokens = 0;
122
-
123
- // The real prompt/input token count reported by the most recent completion
124
- // response (input + cache read + cache write). This reflects exactly how many
125
- // tokens the model consumed for the last request and is far more accurate than
126
- // the whitespace-based estimate in getMessagesLength(). Used to decide when to
127
- // compact. 0 means "no real usage seen yet" (fall back to the estimate).
128
- protected lastPromptTokens = 0;
129
-
130
- protected compressThreshold = 30000;
131
- protected compressMinMessages = 30;
132
-
133
- // Set when the user manually requests compaction (e.g. via /compact while
134
- // attached). Forces the next loop iteration to compress the conversation
135
- // regardless of whether the token threshold has been reached.
136
- protected _forceCompact = false;
137
-
138
- // Compaction is intentionally detached from the main agent loop. A failed
139
- // attempt is cleared so a later turn can retry without ending the task.
140
- private _compactionPromise: Promise<void> | null = null;
141
- private _completedCompaction: CompletedCompaction | null = null;
142
- private _compactionGeneration = 0;
143
-
144
- // Interrupt support: resolves the currently awaited tool call or completion
145
- private _interruptResolve: (() => void) | null = null;
146
- // A monotonically-increasing token identifying the active interruptible window.
147
- // Used to ensure a stale (slow) operation completing in the background cannot
148
- // clobber a newer interruptible window's resolver.
149
- private _interruptToken = 0;
150
-
151
- protected threads = [] as Message[][];
152
-
153
- // Message from users
154
- protected pendingUserMessages = [] as Message[];
155
-
156
- // Internal messages
157
- protected pendingMessages = [] as Message[];
158
-
159
- // Active observations (subscriptions) owned by this agent instance. Kept
160
- // per-agent (not module scope) so stopObserving() on one agent can't clobber
161
- // another agent's observers, and so newTask() can tear them all down.
162
- protected _observations = new Map<string, ActiveObservation>();
163
- private _observationSeq = 0;
164
-
165
- protected taskBreakdown = "";
166
- protected summaries = [] as string[];
167
- protected currentTaskId: string | null = null;
168
- /**
169
- * The taskId of the parent agent that spawned this task, if any.
170
- * Used by self-referential tools (e.g. replyToParent) to know who to
171
- * report back to without relying solely on reading metadata.json off disk.
172
- */
173
- public parentTaskId: string | null = null;
174
-
175
- public agentEvents = new EventService();
176
- public eventTypes = {
177
- newThread: "new_thread",
178
- threadUpdate: "thread_update",
179
- costUpdate: "cost_update",
180
- agentLog: "agent:log",
181
- toolCall: "tool:pre_call",
182
- toolUsed: "tool:post_call",
183
- agentStatus: "agent:status",
184
- notStarted: "not_started",
185
- inProgress: "in_progress",
186
- done: "done",
187
- pause: "pause",
188
- kill: "kill",
189
- unpause: "unpause",
190
- agentMsg: "agent:msg",
191
- userSay: "user:say",
192
- agentSay: "agent:say",
193
- agentNewTask: "agent:newTask",
194
- agentTaskComplete: "agent:taskComplete",
195
- tokenUsage: "agent:tokenUsage",
196
- };
197
-
198
- public tools: ToolsService;
199
- public events: EventService;
200
- public messageProcessor: MessageProcessor;
201
- public clientService: AIClient;
202
-
203
- disabledTools = [];
204
-
205
- constructor(context: AgentContext) {
206
- this.tools = context.Tools;
207
- this.events = context.Events;
208
- this.messageProcessor = context.messageProcessor || new MessageProcessor();
209
- this.clientService = context.Clients || Clients;
210
-
211
- if (!this.tools) {
212
- throw new Error("ToolsService is required for BaseAgent");
213
- }
214
-
215
- if (!this.events) {
216
- throw new Error("EventService is required for BaseAgent");
217
- }
218
-
219
- // Subscribe to "agent:msg" events for dynamic context loading
220
- // Use setListener with a key so re-creating the agent doesn't double-subscribe
221
- this.events.setListener(
222
- {
223
- key: `agent:msg:${this.constructor.name}`,
224
- event: this.eventTypes.agentMsg,
225
- },
226
- (eventData: any) => {
227
- if (
228
- this.status === this.eventTypes.inProgress ||
229
- this.status === this.eventTypes.pause
230
- ) {
231
- const message = {
232
- role: "user",
233
- content: JSON.stringify(eventData),
234
- } as Message;
235
- this.addPendingMessage(message);
236
- }
237
- }
238
- );
239
- }
240
-
241
- protected log(
242
- message: string,
243
- level: "info" | "warn" | "error" = "info"
244
- ): void {
245
- this.agentEvents.emit(this.eventTypes.agentLog, {
246
- agentName: this.name,
247
- message,
248
- level,
249
- timestamp: Date.now(),
250
- taskId: this.currentTaskId,
251
- });
252
- }
253
-
254
- setCompressThreshold(threshold: number) {
255
- this.compressThreshold = threshold;
256
- }
257
-
258
- /**
259
- * Request that the conversation be compacted at the next loop iteration,
260
- * regardless of whether the token threshold has been reached. Combined with
261
- * an interrupt(), this lets a user force compaction on an attached agent
262
- * mid-task (e.g. via the `/compact` chat command) to drop back to a much
263
- * cheaper per-interaction context size.
264
- */
265
- requestCompact() {
266
- this._forceCompact = true;
267
- }
268
-
269
- /**
270
- * Returns the effective compress threshold for the current model.
271
- * If the user has manually set a custom threshold (different from the default 30k),
272
- * that value is used as-is. Otherwise, the threshold is dynamically computed as
273
- * 70% of the model's context window limit (or tiered-pricing threshold), falling
274
- * back to DEFAULT_CONTEXT_LIMIT. The 70% factor leaves headroom so token-count
275
- * lag doesn't push a request past the model/tier limit before compression fires.
276
- */
277
- getCompressThreshold(): number {
278
- if (this.compressThreshold !== DEFAULT_CONTEXT_LIMIT) {
279
- return this.compressThreshold;
280
- }
281
- const result = this.clientService.getContextLimit(
282
- this.getProvider() as string,
283
- this.getModel()
284
- );
285
- const contextLimit = result?.contextLimit ?? DEFAULT_CONTEXT_LIMIT;
286
- const threshold = result?.threshold ?? contextLimit;
287
- return Math.floor(threshold * 0.7);
288
- }
289
-
290
- setMaxTurns(maxTurns: number | null) {
291
- this.maxTurns = maxTurns;
292
- }
293
-
294
- setMaxSpend(maxSpend: number | null) {
295
- this.maxSpend = maxSpend;
296
- }
297
-
298
- setMaxRunTime(maxRunTimeMs: number | null) {
299
- this.maxRunTimeMs = maxRunTimeMs;
300
- }
301
-
302
- newTask(taskId?: string) {
303
- // Invalidate any detached compaction still finishing for the previous task.
304
- this._compactionGeneration++;
305
- this._compactionPromise = null;
306
- this._completedCompaction = null;
307
- this.currentThread = 0;
308
- this.threads = [];
309
- this.taskBreakdown = "";
310
- this.summaries = [];
311
- this.totalCostUsd = 0;
312
- this.totalInputTokens = 0;
313
- this.totalOutputTokens = 0;
314
- this.totalCacheReadTokens = 0;
315
- this.totalCacheWriteTokens = 0;
316
- this.lastPromptTokens = 0;
317
- this.status = this.eventTypes.inProgress;
318
- this.turnCount = 0;
319
- this.startTimeMs = Date.now();
320
- this.currentTaskId = taskId || this.startTimeMs.toString();
321
-
322
- // Reset interrupt state so a queued/stale interrupt from a prior task
323
- // can't fire against the new task.
324
- this._interruptResolve = null;
325
- this._forceCompact = false;
326
-
327
- // Tear down any observers from a prior task so they can't leak or inject
328
- // into the new task.
329
- this.stopObserving(undefined, "new task started");
330
-
331
- // Emit event for plugin integration
332
- const id = taskId || this.startTimeMs.toString();
333
- this.events.emit(this.eventTypes.agentNewTask, {
334
- taskId: id,
335
- });
336
- }
337
-
338
- register() {
339
- this.events.registerAgent(this);
340
- }
341
-
342
- setModelPreferences(value: ModelPreference[]) {
343
- this.modelPreferences = value;
344
- if (value.length) {
345
- this.updatePreferences(value[0]);
346
- }
347
- }
348
-
349
- updatePreferences(value: ModelPreference) {
350
- this.setModel(value.model);
351
- this.setProvider(value.provider);
352
- if (value.reasoning_effort !== undefined) {
353
- this.reasoningEffort = value.reasoning_effort;
354
- }
355
- if (value.reasoning_summary !== undefined) {
356
- this.summarizeReasoning = value.reasoning_summary;
357
- }
358
- }
359
-
360
- nextModel() {
361
- this.currentModelPreferenceIndex++;
362
- if (this.currentModelPreferenceIndex >= this.modelPreferences.length) {
363
- throw new Error("We have exhausted all model preferences.");
364
- }
365
- const nextModel = this.modelPreferences[this.currentModelPreferenceIndex];
366
- this.updatePreferences(nextModel);
367
- }
368
-
369
- getModel(): string {
370
- return this.modelName;
371
- }
372
-
373
- setModel(value: string) {
374
- this.modelName = value;
375
- this.client = null; // Reset client to force re-fetch
376
- }
377
-
378
- getProvider() {
379
- return this.provider;
380
- }
381
-
382
- getParentTaskId(): string | null {
383
- return this.parentTaskId;
384
- }
385
-
386
- setParentTaskId(value: string | null) {
387
- this.parentTaskId = value ?? null;
388
- }
389
-
390
- setProvider(value: keyof typeof Clients.clients) {
391
- this.provider = value;
392
- this.client = null; // Reset client to force re-fetch
393
- }
394
-
395
- setReasoningEffort(effort: CompletionOptions["reasoning_effort"]) {
396
- this.reasoningEffort = effort;
397
- }
398
-
399
- getReasoningEffort(): CompletionOptions["reasoning_effort"] {
400
- return this.reasoningEffort;
401
- }
402
-
403
- setSummarizeReasoning(value: boolean) {
404
- this.summarizeReasoning = value;
405
- }
406
-
407
- getSummarizeReasoning(): boolean | undefined {
408
- return this.summarizeReasoning;
409
- }
410
-
411
- getClient() {
412
- if (!this.client) {
413
- if (this.provider) {
414
- this.log(`Getting client for provider ${this.provider}`);
415
- const clientInfo = this.clientService.getClient(this.getProvider());
416
- if (clientInfo) {
417
- this.client = clientInfo.client;
418
- // don't set provider or model yet
419
- }
420
- }
421
-
422
- if (!this.client) {
423
- this.log(`Getting client for model ${this.modelName}`);
424
- const clientInfo = this.clientService.getClient(
425
- undefined,
426
- this.getModel()
427
- );
428
-
429
- if (clientInfo) {
430
- this.client = clientInfo.client;
431
- }
432
- }
433
- }
434
- return this.client;
435
- }
436
-
437
- setClient(client: GenericClient) {
438
- this.client = client;
439
- }
440
-
441
- setEasyFinalAnswer(value: boolean) {
442
- this.easyFinalAnswer = value;
443
- }
444
-
445
- /**
446
- * Detect if the model's response is a termination signal (e.g. "Done", "Complete", "Finished", "finalAnswer")
447
- * This handles the case where an agent refuses to call finalAnswer and just says a short termination word.
448
- */
449
- protected isTerminationResponse(content: string): boolean {
450
- const trimmed = content.trim();
451
- // Short response (≤ 3 words) that matches a termination word/phrase exactly
452
- const wordCount = trimmed.split(/\s+/).filter(Boolean).length;
453
- if (wordCount <= 3) {
454
- const terminationPattern =
455
- /^(done|complete|completed|finished|final\s*answer|task\s*complete|all\s*done|that'?s\s*(all|it)|ok(ay)?|yes)[.!]*$/i;
456
- if (terminationPattern.test(trimmed)) return true;
457
- }
458
-
459
- // Check if the first 1-3 words indicate task completion (for longer responses)
460
- // e.g. "Task complete: ...", "All done.", "No further changes needed.", "Confirmed complete."
461
- const firstWords = trimmed.split(/\s+/).slice(0, 3).join(" ");
462
- const firstWordPattern =
463
- /^(task\s*(complete|completed|done|finished)|all\s*done|no\s*(further|more|additional|changes|action)|confirmed?\s*(complete|done|finished|one\s*last)|nothing\s*(more|further|else)|standing\s*by|everything\s*is|still\s*confirmed|acknowledged|done\s*and|complete\s*(and|\.)|completed\s*successfully|no\s*additional|verified\s*and)/i;
464
- if (firstWordPattern.test(firstWords)) return true;
465
-
466
- // If easyFinalAnswer mode is on, also match response starting with "✅" or numbered confirmation lists
467
- if (this.easyFinalAnswer) {
468
- if (trimmed.startsWith("✅") || /^[\d\.\-\*]/.test(trimmed)) return true;
469
- }
470
-
471
- // Detect JSON-wrapped finalAnswer output, e.g. {"answer":"..."} or {"finalAnswer":"..."}
472
- try {
473
- const parsed = JSON.parse(trimmed);
474
- if (parsed && typeof parsed === "object") {
475
- if (typeof parsed.answer === "string") return true;
476
- if (typeof parsed.finalAnswer === "string") return true;
477
- }
478
- } catch (_) {}
479
-
480
- return false;
481
- }
482
-
483
- getEnabledTools() {
484
- return this.tools
485
- .getTools()
486
- .filter((t) => !this.disabledTools.includes(t.function.name));
487
- }
488
-
489
- getEnabledToolNames() {
490
- return this.getEnabledTools().map((t) => t.function.name);
491
- }
492
-
493
- /** Restore the exact request-visible tool list persisted for a prior run. */
494
- restoreEnabledTools(names: string[]) {
495
- const uniqueNames = [...new Set(names)];
496
- const lazyTools = this.tools as ToolsService & {
497
- enableTools?: (patterns: string[]) => unknown;
498
- restoreEnabledTools?: (names: string[]) => void;
499
- };
500
-
501
- // LazyToolsService only exposes explicitly enabled tools. Materialize the
502
- // saved concrete names before applying the agent-level exact-set filter.
503
- if (lazyTools.restoreEnabledTools) {
504
- lazyTools.restoreEnabledTools(uniqueNames);
505
- } else {
506
- lazyTools.enableTools?.(uniqueNames);
507
- }
508
- const savedNames = new Set(uniqueNames);
509
- this.disabledTools = this.tools
510
- .getTools()
511
- .map((tool) => tool.function.name)
512
- .filter((name) => !savedNames.has(name));
513
- }
514
-
515
- disableTool(toolName: string) {
516
- this.disabledTools.push(toolName);
517
- }
518
-
519
- isToolEnabled(toolName: string) {
520
- return !!this.getEnabledTools().find((t) => t.function.name === toolName);
521
- }
522
-
523
- enableTool(toolName: string) {
524
- if (!this.isToolEnabled(toolName)) {
525
- this.disabledTools = this.disabledTools.filter((t) => t !== toolName);
526
- }
527
- }
528
-
529
- private checkLimits(): boolean {
530
- // Check turn limit
531
- if (this.maxTurns !== null && this.turnCount >= this.maxTurns) {
532
- this.log(
533
- `Turn limit reached: ${this.turnCount}/${this.maxTurns}`,
534
- "warn"
535
- );
536
- return true;
537
- }
538
-
539
- // Check spend limit
540
- if (this.maxSpend !== null && this.totalCostUsd >= this.maxSpend) {
541
- this.log(
542
- `Spend limit reached: $${this.totalCostUsd.toFixed(
543
- 4
544
- )}/$${this.maxSpend.toFixed(4)}`,
545
- "warn"
546
- );
547
- return true;
548
- }
549
-
550
- // Check runtime limit
551
- if (this.maxRunTimeMs !== null && this.startTimeMs !== null) {
552
- const currentRunTimeMs = this.runTime();
553
- if (currentRunTimeMs >= this.maxRunTimeMs) {
554
- this.log(
555
- `Runtime limit reached: ${currentRunTimeMs}ms/${this.maxRunTimeMs}ms`,
556
- "warn"
557
- );
558
- return true;
559
- }
560
- }
561
-
562
- return false;
563
- }
564
-
565
- public runTime() {
566
- if (this.startTimeMs) {
567
- return Date.now() - this.startTimeMs;
568
- }
569
- return 0;
570
- }
571
-
572
- private shouldTerminateFromLimits(): boolean {
573
- return this.checkLimits();
574
- }
575
-
576
- getTurnCount(): number {
577
- return this.turnCount;
578
- }
579
-
580
- adjustTotalCostUsd(cost: number) {
581
- if (cost) {
582
- this.totalCostUsd += cost;
583
- this.agentEvents.emit(this.eventTypes.costUpdate, this.totalCostUsd);
584
- }
585
- }
586
-
587
- getTotalCostUsd() {
588
- return this.totalCostUsd;
589
- }
590
-
591
- adjustTokenUsage(
592
- usage: any,
593
- messages?: Message[],
594
- updateLastPromptTokens = true
595
- ) {
596
- if (!usage) return;
597
- // Support both OpenAI-style (prompt_tokens/completion_tokens) and Anthropic-style (input_tokens/output_tokens)
598
- const inputTokens = usage.input_tokens ?? usage.prompt_tokens ?? 0;
599
- const outputTokens = usage.output_tokens ?? usage.completion_tokens ?? 0;
600
-
601
- const cacheReadTokens =
602
- usage.cache_read_input_tokens ??
603
- usage.cache_read_tokens ??
604
- usage.prompt_tokens_details?.cached_tokens ??
605
- 0;
606
- const cacheWriteTokens =
607
- usage.cache_creation_input_tokens ?? usage.cache_write_tokens ?? 0;
608
-
609
- // Record the real prompt token count for this single completion (not the
610
- // running total). This represents the full context the model processed for
611
- // the request: fresh input + cache-read + cache-write tokens. It is used by
612
- // the compaction check as an accurate replacement for the whitespace-based
613
- // getMessagesLength() estimate. Only track it for "prompt-shaped" usage
614
- // (i.e. when there are input tokens) so a usage-less interrupt stub doesn't
615
- // reset it to 0.
616
- const promptTokens = inputTokens + cacheReadTokens + cacheWriteTokens;
617
- if (updateLastPromptTokens && promptTokens > 0) {
618
- this.lastPromptTokens = promptTokens;
619
- }
620
-
621
- this.totalInputTokens += inputTokens;
622
- this.totalOutputTokens += outputTokens;
623
- this.totalCacheReadTokens += cacheReadTokens;
624
- this.totalCacheWriteTokens += cacheWriteTokens;
625
-
626
- this.agentEvents.emit(this.eventTypes.tokenUsage, {
627
- timestamp: new Date().toISOString(),
628
- inputTokens,
629
- outputTokens,
630
- cacheReadTokens,
631
- cacheWriteTokens,
632
- totalInputTokens: this.totalInputTokens,
633
- totalOutputTokens: this.totalOutputTokens,
634
- totalCacheReadTokens: this.totalCacheReadTokens,
635
- totalCacheWriteTokens: this.totalCacheWriteTokens,
636
- messages,
637
- });
638
- }
639
-
640
- getTokenUsage() {
641
- return {
642
- totalInputTokens: this.totalInputTokens,
643
- totalOutputTokens: this.totalOutputTokens,
644
- totalCacheReadTokens: this.totalCacheReadTokens,
645
- totalCacheWriteTokens: this.totalCacheWriteTokens,
646
- };
647
- }
648
-
649
- /**
650
- * Centralized helper for making an AI completion call while ensuring
651
- * cost (totalCostUsd) and token usage (input/output/cache) are always
652
- * updated consistently, regardless of which part of the agent triggers
653
- * the completion (main call loop, task breakdown, compression, etc).
654
- *
655
- * Optionally supports being interrupted via makeInterruptible by passing
656
- * an `interruptValue` in options - if the operation is interrupted, the
657
- * interrupt value is returned and used for cost/usage tracking (which,
658
- * for a typical interrupt stub with no usage/cost, is effectively a
659
- * no-op).
660
- */
661
- protected async createAgentCompletion(
662
- params: CachedChatCompletion,
663
- options: {
664
- interruptValue?: CompletionResponse;
665
- updateLastPromptTokens?: boolean;
666
- } = {}
667
- ): Promise<CompletionResponse> {
668
- const { interruptValue, updateLastPromptTokens = true } = options;
669
-
670
- // If you change the tools, or any of this, you bust cache
671
- // only safe to change messages
672
- const defaultedParams: ChatCompletion = {
673
- model: this.getModel(),
674
- tools: this.getEnabledTools(),
675
- tool_choice: "auto",
676
- long_ttl_cache: this.runTime() > 300_000,
677
- ...(this.reasoningEffort !== undefined && {
678
- reasoning_effort: this.reasoningEffort,
679
- }),
680
- ...(this.summarizeReasoning !== undefined && {
681
- reasoning_summary: this.summarizeReasoning,
682
- }),
683
-
684
- ...params,
685
- };
686
-
687
- const callPromise = this.getClient().createChatCompletion(defaultedParams);
688
- const response = interruptValue
689
- ? await this.makeInterruptible(callPromise, interruptValue)
690
- : await callPromise;
691
-
692
- this.adjustTotalCostUsd(response?.usd_cost);
693
- this.adjustTokenUsage(
694
- response?.usage,
695
- params.messages,
696
- updateLastPromptTokens
697
- );
698
-
699
- return response;
700
- }
701
-
702
- startNewThread(messages: Message[]) {
703
- this.currentThread++;
704
- this.agentEvents.emit(this.eventTypes.newThread, messages);
705
- this.updateCurrentThread(messages);
706
- }
707
-
708
- updateCurrentThread(messages: Message[]) {
709
- this.threads[this.currentThread] = messages;
710
- this.agentEvents.emit(this.eventTypes.threadUpdate, messages);
711
- }
712
-
713
- getThreads() {
714
- return this.threads;
715
- }
716
-
717
- getSummaries() {
718
- return this.summaries;
719
- }
720
-
721
- abstract getInitialMessages(
722
- userInput: string | MessageContent[]
723
- ): Promise<Message[]>;
724
-
725
- async processToolMessages(toolCall: ToolCall) {
726
- this.agentEvents.emit(this.eventTypes.toolCall, { toolCall });
727
-
728
- const interruptMsg = `User interrupted this tool call (${toolCall.function?.name})`;
729
- const interruptResult: Awaited<ReturnType<typeof this.tools.callTool>> = {
730
- functionResp: interruptMsg,
731
- toolCallId: toolCall.id,
732
- functionName: toolCall.function?.name,
733
- functionArgs: {},
734
- toolMessages: [
735
- {
736
- role: "tool",
737
- tool_call_id: toolCall.id,
738
- name: toolCall.function?.name,
739
- content: interruptMsg,
740
- },
741
- ],
742
- };
743
-
744
- const { functionResp, toolMessages } = await this.makeInterruptible(
745
- // Pass this agent in as the per-call context (`_ctx`) so tools can be
746
- // self-referential: they can read `_ctx.caller` (this agent) and
747
- // `_ctx.taskId` to, e.g., look up the current task, send pending
748
- // messages, or subscribe to the caller's events.
749
- this.tools.callTool(toolCall, this.getEnabledToolNames(), {
750
- caller: this,
751
- taskId: this.currentTaskId,
752
- parentTaskId: this.parentTaskId ?? undefined,
753
- }),
754
- interruptResult
755
- );
756
-
757
- this.agentEvents.emit(this.eventTypes.toolUsed, {
758
- toolCall,
759
- functionResp,
760
- });
761
-
762
- return toolMessages;
763
- }
764
-
765
- logMessages(messages: Message[]) {
766
- for (const message of messages) {
767
- // Surface the model's reasoning summary (what it's "thinking") when the
768
- // provider exposes one, so it appears alongside the assistant's output.
769
- const reasoningSummary = (message as any).reasoning_summary;
770
- if (message.role === "assistant" && reasoningSummary) {
771
- this.agentEvents.emit(this.eventTypes.agentSay, {
772
- message: `💭 ${reasoningSummary}`,
773
- });
774
- }
775
- if (message.role === "assistant" && message.content) {
776
- this.agentEvents.emit(this.eventTypes.agentSay, {
777
- message: message.content,
778
- });
779
- }
780
- }
781
- }
782
-
783
- formatInputContent(userInput: string) {
784
- return replaceEscapedNewLines(userInput);
785
- }
786
-
787
- formatAiResponse(response: string) {
788
- return restoreEscapedNewLines(response);
789
- }
790
-
791
- formatInputMessages(messages: Message[]) {
792
- return messages.map((m) => ({
793
- ...m,
794
- content:
795
- typeof m.content === "string"
796
- ? this.formatInputContent(m.content)
797
- : m.content,
798
- })) as Message[];
799
- }
800
-
801
- formatOutputMessages(messages: Message[]) {
802
- return messages.map((m) => ({
803
- ...m,
804
- content:
805
- typeof m.content === "string"
806
- ? this.formatAiResponse(m.content)
807
- : m.content,
808
- })) as Message[];
809
- }
810
-
811
- async healthCheck() {
812
- try {
813
- const canCallProvider = await this.getClient().createChatCompletion({
814
- messages: [{ role: "user", content: "Hello!" }],
815
- model: this.getModel(),
816
- max_tokens: 2,
817
- });
818
- return true;
819
- } catch (e) {
820
- this.log(String(e), "error");
821
- return false;
822
- }
823
- }
824
-
825
- async selectHealthyModel() {
826
- const currentTime = Date.now();
827
- if (currentTime - this.lastHealthCheckTime < 60 * 1000) {
828
- return;
829
- }
830
-
831
- let healthy = await this.healthCheck();
832
- this.lastHealthCheckTime = Date.now();
833
- while (!healthy) {
834
- this.nextModel();
835
- healthy = await this.healthCheck();
836
- }
837
- await this.healthCheck();
838
- }
839
-
840
- isRequiredToolMissing() {
841
- const requiredToolAvailable = this.getEnabledToolNames().some(
842
- (enabled) =>
843
- this.requiredToolNames.includes(enabled) ||
844
- this.requiredToolNames.includes(mcpToolName(enabled)) ||
845
- this.requiredToolNames.some((required) => enabled.endsWith(required))
846
- );
847
-
848
- if (requiredToolAvailable) {
849
- return false;
850
- }
851
-
852
- this.log(
853
- `Required tool: [${
854
- this.requiredToolNames
855
- }] not available, checking for finalAnswer. Enabled: ${this.getEnabledToolNames().join(
856
- ", "
857
- )}`
858
- );
859
-
860
- // Otherwise we're missing the required tool, lets use finalAnswer if we have it
861
- const finalAnswer = "finalAnswer";
862
- const requiredFinalAnswer = this.requiredToolNames.includes(finalAnswer);
863
- const hasFinalAnswer = this.getEnabledToolNames().includes(finalAnswer);
864
-
865
- // We have the final answer tool, but it wasn't required
866
- if (hasFinalAnswer && !requiredFinalAnswer) {
867
- this.log(
868
- "Required tool not available, setting finalAnswer as required tool",
869
- "warn"
870
- );
871
- this.requiredToolNames.push("finalAnswer");
872
- return false;
873
- }
874
-
875
- return true;
876
- }
877
-
878
- setNotHealthy() {
879
- this.lastHealthCheckTime = 0;
880
- }
881
-
882
- pause() {
883
- this.log("Pausing agent");
884
- this.agentEvents.emit(this.eventTypes.pause, this);
885
- this.status = this.eventTypes.pause;
886
- }
887
-
888
- unpause() {
889
- this.log("Unpausing agent");
890
- this.agentEvents.emit(this.eventTypes.unpause, this);
891
- this.status = this.eventTypes.inProgress;
892
- }
893
-
894
- async unpaused() {
895
- return new Promise((resolve) => {
896
- this.log("Waiting for agent to unpause");
897
- this.agentEvents.once(this.eventTypes.unpause, () => {
898
- this.log("Agent resumed");
899
- resolve(true);
900
- });
901
- this.agentEvents.once(this.eventTypes.done, () => {
902
- resolve(true);
903
- });
904
- });
905
- }
906
-
907
- async kill() {
908
- this.log("Killing agent");
909
- if (
910
- this.status === this.eventTypes.kill ||
911
- this.status === this.eventTypes.done
912
- ) {
913
- this.log(
914
- "Agent is already being killed or done, ignoring duplicate kill()",
915
- "warn"
916
- );
917
- return;
918
- }
919
- this.agentEvents.emit(this.eventTypes.kill, this);
920
- this.status = this.eventTypes.kill;
921
-
922
- this.addPendingMessage({
923
- role: "user",
924
- content: `<Workflow>The user has requested the task to end, please call ${this.requiredToolNames} with a report of your ending state</Workflow>`,
925
- } as Message);
926
- }
927
-
928
- /**
929
- * Wrap a promise so it can be interrupted via interrupt().
930
- * If interrupt() is called while waiting, the promise resolves with the
931
- * interrupt message instead of waiting for the original operation to complete.
932
- */
933
- protected makeInterruptible<T>(
934
- promise: Promise<T>,
935
- interruptValue: T
936
- ): Promise<T> {
937
- return new Promise<T>((resolve, reject) => {
938
- // Each interruptible window gets a unique token. `settled` guards this
939
- // specific window so it can only ever resolve/reject once, and the token
940
- // ensures a stale (slow) background operation that finishes AFTER this
941
- // window was interrupted cannot clobber a NEWER window's resolver.
942
- const myToken = ++this._interruptToken;
943
- let settled = false;
944
-
945
- const finish = (fn: () => void) => {
946
- if (settled) return;
947
- settled = true;
948
- // Only clear the shared resolver if it still belongs to this window.
949
- if (this._interruptToken === myToken) {
950
- this._interruptResolve = null;
951
- }
952
- fn();
953
- };
954
-
955
- this._interruptResolve = () => finish(() => resolve(interruptValue));
956
-
957
- promise
958
- .then((result) => {
959
- // If this window was already interrupted/settled, drop the stale
960
- // result — do NOT touch _interruptResolve (it may belong to a newer
961
- // window now).
962
- finish(() => resolve(result));
963
- })
964
- .catch((err) => {
965
- // If the window was already interrupted, swallow the late error.
966
- if (settled) return;
967
- finish(() => reject(err));
968
- });
969
- });
970
- }
971
-
972
- /**
973
- * Interrupt the currently awaited tool call or AI completion.
974
- * The waiting promise will resolve immediately with an interrupt message,
975
- * allowing the agent to continue its loop with the interruption as context.
976
- */
977
- interrupt(message = "User interrupted this action you were waiting on") {
978
- this.log(`Interrupting current operation: ${message}`);
979
-
980
- // If the user supplied a real message with the poke (not the default
981
- // interrupt reason), queue it as a pending user message so the agent
982
- // actually sees what they said on its next step.
983
- if (
984
- message &&
985
- message !== "User interrupted this action you were waiting on"
986
- ) {
987
- this.addPendingUserMessage({ role: "user", content: message });
988
- }
989
-
990
- if (this._interruptResolve) {
991
- this._interruptResolve();
992
- } else {
993
- // No active interruptible window right now (we're between the AI
994
- // completion and the tool call, or in message processing). There is
995
- // nothing to interrupt, so we do NOT queue it — a queued interrupt
996
- // would pre-empt the next tool call and drop its result. Any message
997
- // supplied with the poke was already added as a pending user message
998
- // above, so the agent will still see it on its next step.
999
- this.log("No active interruptible operation to interrupt", "warn");
1000
- }
1001
- }
1002
-
1003
- async call(
1004
- userInput: string | MessageContent[],
1005
- _messages?: Message[],
1006
- retryCount = 0
1007
- ) {
1008
- if (this.status === this.eventTypes.notStarted) {
1009
- this.status = this.eventTypes.inProgress;
1010
- }
1011
-
1012
- if (this.status === this.eventTypes.pause) {
1013
- await this.unpaused();
1014
- }
1015
-
1016
- await this.selectHealthyModel();
1017
-
1018
- // Increment turn count and check limits (only for new calls, not recursive ones)
1019
- this.turnCount++;
1020
- if (this.shouldTerminateFromLimits()) {
1021
- const currentRunTimeMs = this.startTimeMs
1022
- ? Date.now() - this.startTimeMs
1023
- : 0;
1024
- const limitMsg = `Task terminated due to limits reached. Turn: ${
1025
- this.turnCount
1026
- }/${this.maxTurns || "unlimited"}, Cost: $${this.totalCostUsd.toFixed(
1027
- 4
1028
- )}/${
1029
- this.maxSpend ? "$" + this.maxSpend.toFixed(4) : "unlimited"
1030
- }, Runtime: ${currentRunTimeMs}ms/${
1031
- this.maxRunTimeMs ? this.maxRunTimeMs + "ms" : "unlimited"
1032
- }`;
1033
- this.status = this.eventTypes.done;
1034
- this.agentEvents.emit(this.eventTypes.done, limitMsg);
1035
- return limitMsg;
1036
- }
1037
-
1038
- try {
1039
- const model = this.getModel();
1040
- let messages = _messages || (await this.getInitialMessages(userInput));
1041
-
1042
- // Process initial messages if this is the first call
1043
- if (!_messages) {
1044
- messages = await this.messageProcessor.processMessages(
1045
- messages,
1046
- "initial_call"
1047
- );
1048
- }
1049
-
1050
- if (this.pendingUserMessages.length) {
1051
- messages.push(...this.pendingUserMessages);
1052
- this.pendingUserMessages = [];
1053
- }
1054
-
1055
- if (this.pendingMessages.length) {
1056
- messages.push(...this.pendingMessages);
1057
- this.pendingMessages = [];
1058
- }
1059
-
1060
- messages = this.formatInputMessages(messages);
1061
- this.updateCurrentThread(messages);
1062
- const isMissingTool = this.isRequiredToolMissing();
1063
-
1064
- // Process messages before each AI call
1065
- messages = await this.messageProcessor.processMessages(
1066
- messages,
1067
- "pre_call"
1068
- );
1069
-
1070
- const interruptResponse: CompletionResponse = {
1071
- choices: [
1072
- {
1073
- message: {
1074
- role: "assistant",
1075
- content: "User interrupted this AI completion. Please continue.",
1076
- },
1077
- },
1078
- ],
1079
- model,
1080
- usage: undefined,
1081
- usd_cost: 0,
1082
- };
1083
-
1084
- const response = await this.createAgentCompletion(
1085
- {
1086
- model,
1087
- messages,
1088
- tools: this.getEnabledTools(),
1089
- tool_choice: "auto",
1090
- long_ttl_cache: this.runTime() > 300_000,
1091
- ...(this.reasoningEffort !== undefined && {
1092
- reasoning_effort: this.reasoningEffort,
1093
- }),
1094
- ...(this.summarizeReasoning !== undefined && {
1095
- reasoning_summary: this.summarizeReasoning,
1096
- }),
1097
- },
1098
- { interruptValue: interruptResponse }
1099
- );
1100
-
1101
- // If the agent was paused while the completion was in-flight, wait here
1102
- // before processing tool calls. This allows the user to send messages
1103
- // (via addPendingUserMessage) and prevents the agent from proceeding to
1104
- // tool calls (e.g. finalAnswer) without seeing those interactions.
1105
- if (this.status === this.eventTypes.pause) {
1106
- this.log(
1107
- "Agent was paused after completion, waiting before processing tool calls"
1108
- );
1109
- await this.unpaused();
1110
- }
1111
-
1112
- if (response?.usd_cost === undefined) {
1113
- this.log(
1114
- `Response cost is undefined: ${JSON.stringify(response, null, 2)}`,
1115
- "warn"
1116
- );
1117
- const error = response as any;
1118
- if (error != null && "response" in error && "data" in error.response) {
1119
- this.log(
1120
- `Response data: ${JSON.stringify(error.response.data, null, 2)}`,
1121
- "warn"
1122
- );
1123
- }
1124
- if (!response?.choices) {
1125
- const errMsg =
1126
- (error?.error?.message ?? error?.message) ||
1127
- JSON.stringify(response);
1128
- throw new Error(`AI response error: ${errMsg}`);
1129
- }
1130
- }
1131
-
1132
- this.log("agent response cost: " + response?.usd_cost);
1133
-
1134
- // Typically, there's only one choice in the array, but you could have many
1135
- // If you set `n` to more than 1, you will get multiple choices
1136
- // Collect all tool calls across all choices up front.
1137
- // This is used by detectTruncatedToolCalls so that the size heuristic
1138
- // compares the full completion_tokens against ALL argument content,
1139
- // rather than just the current choice's single tool call (Anthropic maps
1140
- // each parallel tool_use block to a separate choice).
1141
- const allResponseToolCalls = response.choices.flatMap(
1142
- (c) => c.message.tool_calls ?? []
1143
- );
1144
- for (const choice of response.choices) {
1145
- messages.push(choice.message);
1146
-
1147
- messages = await this.messageProcessor.processMessages(
1148
- messages,
1149
- "post_call"
1150
- );
1151
-
1152
- const lastMessage = messages[messages.length - 1];
1153
-
1154
- this.logMessages([lastMessage]);
1155
-
1156
- if (lastMessage.tool_calls) {
1157
- // About to call a tool, process the messages
1158
- // We could add all the tool calls, and do this once
1159
- messages = await this.messageProcessor.processMessages(
1160
- messages,
1161
- "pre_tools"
1162
- );
1163
-
1164
- // Re-derive toolCalls from the freshly processed messages, since
1165
- // pre_tools processors (e.g. MinimalToolsMessageProcessor) may have
1166
- // rewritten the tool_calls on a deep-copied message array.
1167
- const toolCalls = messages[messages.length - 1].tool_calls;
1168
-
1169
- this.updateCurrentThread(messages);
1170
-
1171
- const truncationWarning = this.detectTruncatedToolCalls(
1172
- toolCalls,
1173
- response,
1174
- allResponseToolCalls
1175
- );
1176
- if (truncationWarning) {
1177
- messages.push(truncationWarning as Message);
1178
- this.updateCurrentThread(messages);
1179
- return this.call(userInput, messages);
1180
- }
1181
-
1182
- for (const toolCall of toolCalls) {
1183
- if (this.status === this.eventTypes.pause) {
1184
- this.log(
1185
- "Agent was paused before tool call, waiting before processing tool calls"
1186
- );
1187
- await this.unpaused();
1188
- }
1189
-
1190
- const toolMessages = await this.processToolMessages(toolCall);
1191
- // Add the tool responses to the thread
1192
- messages.push(...(toolMessages as Message[]));
1193
-
1194
- const finalMessage = toolMessages.find(
1195
- (called) =>
1196
- this.requiredToolNames.includes(called.name) ||
1197
- this.requiredToolNames.includes(mcpToolName(called.name)) ||
1198
- this.requiredToolNames.some((required) =>
1199
- called.name.endsWith(required)
1200
- )
1201
- );
1202
-
1203
- if (finalMessage) {
1204
- // If user added pending messages after finalAnswer was called,
1205
- // continue running to respond to that feedback instead of returning
1206
- if (this.pendingUserMessages.length > 0) {
1207
- this.log(
1208
- "finalAnswer called but pending user messages exist, continuing to respond to feedback"
1209
- );
1210
- messages.push(...this.pendingUserMessages);
1211
- this.pendingUserMessages = [];
1212
- this.updateCurrentThread(messages);
1213
- return this.call(userInput, messages);
1214
- }
1215
-
1216
- // Emit task completion event for plugins (like GitPlugin)
1217
- this.events.emit(this.eventTypes.agentTaskComplete, {
1218
- taskId:
1219
- this.currentTaskId ||
1220
- this.startTimeMs?.toString() ||
1221
- Date.now().toString(),
1222
- result: finalMessage.content || "Done",
1223
- });
1224
- const doneMsg = finalMessage.content || "Done";
1225
-
1226
- // Ensure the final thread state (including the finalAnswer result) is
1227
- // captured before emitting done, so syncers see the complete thread.
1228
- this.updateCurrentThread(messages);
1229
- this.agentEvents.emit(this.eventTypes.done, doneMsg);
1230
- this.status = this.eventTypes.done;
1231
- return doneMsg;
1232
- }
1233
- }
1234
- }
1235
- }
1236
-
1237
- const newToolCalls = response.choices.flatMap(
1238
- (c) => c.message.tool_calls
1239
- );
1240
- // Process messages after tool execution
1241
- if (newToolCalls && newToolCalls.length > 0) {
1242
- messages = await this.messageProcessor.processMessages(
1243
- messages,
1244
- "post_tools"
1245
- );
1246
- }
1247
-
1248
- // Early exit: not required to call tool
1249
- const firstMessage = response.choices[0].message;
1250
- // Auto-detect termination words: if the model is just saying "Done", "Complete", etc.
1251
- if (
1252
- response.choices.length === 1 &&
1253
- firstMessage.content &&
1254
- this.isTerminationResponse(firstMessage.content)
1255
- ) {
1256
- this.log(
1257
- `Termination word detected: "${firstMessage.content.trim()}", treating as finalAnswer`
1258
- );
1259
- this.status = this.eventTypes.done;
1260
- this.agentEvents.emit(this.eventTypes.done, firstMessage.content);
1261
- return firstMessage.content;
1262
- }
1263
-
1264
- if (
1265
- response.choices.length === 1 &&
1266
- firstMessage.content &&
1267
- this.easyFinalAnswer
1268
- ) {
1269
- this.status = this.eventTypes.done;
1270
- this.agentEvents.emit(this.eventTypes.done, firstMessage.content);
1271
- return firstMessage.content;
1272
- }
1273
-
1274
- // infinite loop if we cannot exit
1275
- if (isMissingTool) {
1276
- const error = `Required tool: ${JSON.stringify(
1277
- this.requiredToolNames
1278
- )} not available, options are ${this.getEnabledToolNames().join(", ")}`;
1279
- this.log(error, "error");
1280
- this.status = this.eventTypes.done;
1281
- this.agentEvents.emit(this.eventTypes.done, error);
1282
- return error;
1283
- }
1284
-
1285
- // Early exit: killed, agent was requested to wrap up
1286
- if (
1287
- this.pendingUserMessages.length === 0 &&
1288
- this.status === this.eventTypes.kill
1289
- ) {
1290
- this.log("Agent killed, stopping execution");
1291
- this.status = this.eventTypes.done;
1292
- this.agentEvents.emit(this.eventTypes.done, firstMessage.content);
1293
- return firstMessage.content;
1294
- }
1295
-
1296
- // Compress when either the token threshold is exceeded OR the user has
1297
- // manually requested compaction (e.g. via /compact on an attached agent).
1298
- // A manual request bypasses the token threshold but still respects the
1299
- // minimum-message guard so we never try to compress a tiny conversation.
1300
- //
1301
- // The size check uses getContextTokenCount(), which prefers the REAL
1302
- // prompt token count from the last completion response over the
1303
- // whitespace-based estimate — so it compares real tokens against the
1304
- // real (token-based) compress threshold.
1305
- const completedCompaction = this._completedCompaction;
1306
- this._completedCompaction = null;
1307
- let appliedCompaction = false;
1308
-
1309
- if (completedCompaction) {
1310
- const currentPrefix = messages.slice(
1311
- 0,
1312
- completedCompaction.compressionEnd
1313
- );
1314
- const prefixIsUnchanged = currentPrefix.every(
1315
- (message, index) =>
1316
- message === completedCompaction.originalPrefix[index] ||
1317
- JSON.stringify(message) ===
1318
- JSON.stringify(completedCompaction.originalPrefix[index])
1319
- );
1320
-
1321
- if (
1322
- currentPrefix.length === completedCompaction.compressionEnd &&
1323
- prefixIsUnchanged
1324
- ) {
1325
- messages = [
1326
- ...completedCompaction.replacementPrefix,
1327
- ...messages.slice(completedCompaction.compressionEnd),
1328
- ];
1329
- this.summaries.push(completedCompaction.summary);
1330
- this.startNewThread(messages);
1331
- this.lastPromptTokens = 0;
1332
- appliedCompaction = true;
1333
- } else {
1334
- this.log(
1335
- "Discarding completed compaction because its source prefix changed; a later turn will retry",
1336
- "warn"
1337
- );
1338
- }
1339
- }
1340
-
1341
- const contextTokens = this.getContextTokenCount(messages);
1342
- const overThreshold =
1343
- contextTokens > this.getCompressThreshold() &&
1344
- messages.length > this.compressMinMessages;
1345
-
1346
- if (
1347
- !appliedCompaction &&
1348
- !this._compactionPromise &&
1349
- (overThreshold || this._forceCompact)
1350
- ) {
1351
- this.log(
1352
- this._forceCompact
1353
- ? `Starting background compaction (manual /compact request): ${contextTokens} tokens`
1354
- : `Starting background compaction: ${contextTokens} tokens exceeds ${this.getCompressThreshold()}`
1355
- );
1356
- this._forceCompact = false;
1357
- this.startBackgroundCompaction(messages);
1358
- }
1359
-
1360
- if (["assistant", "tool"].includes(messages[messages.length - 1].role)) {
1361
- // sometimes the agent just says a message and doesn't call a tool, or compression ends on a tool message
1362
-
1363
- const statusMessage = this.getStatusMessage();
1364
- this.logStatus();
1365
-
1366
- const continuation = `<Workflow>
1367
- This is an automated runtime instruction, not a new user message.
1368
- The original user request remains active. Do not say that the user's
1369
- message was empty, and do not ask the user to repeat the request.
1370
-
1371
- Your previous response did not terminate the task because it did not
1372
- call one of the required tools: ${JSON.stringify(
1373
- this.requiredToolNames
1374
- )}.
1375
- If your previous response was intended as the final response, call the
1376
- appropriate required tool now with that response. Otherwise, continue
1377
- working on the original request and call an appropriate required tool
1378
- when the task is complete.
1379
-
1380
- <TaskStatus>${statusMessage}</TaskStatus>
1381
- </Workflow>`;
1382
-
1383
- messages.push({
1384
- role: "user",
1385
- content: continuation,
1386
- });
1387
- }
1388
-
1389
- this.updateCurrentThread(messages);
1390
- return this.call(userInput, messages);
1391
- } catch (e) {
1392
- if (e.toString().includes("429")) {
1393
- this.setNotHealthy();
1394
- return this.call(userInput, _messages, retryCount);
1395
- }
1396
- const errorStr = e.toString();
1397
- const isNonRetriable =
1398
- errorStr.includes("401") ||
1399
- errorStr.includes("403") ||
1400
- errorStr.includes("404");
1401
-
1402
- const isRetriable =
1403
- !isNonRetriable &&
1404
- (errorStr.match(/5\d\d/) ||
1405
- errorStr.includes("Failed to get models") ||
1406
- errorStr.includes("timeout") ||
1407
- errorStr.includes("ECONNRESET") ||
1408
- errorStr.includes("ETIMEDOUT") ||
1409
- errorStr.includes("Invalid response format from MCP"));
1410
-
1411
- if (isRetriable && retryCount < 3) {
1412
- const delay = 1000 * Math.pow(2, retryCount);
1413
- this.log(
1414
- `Agent request failed (attempt ${
1415
- retryCount + 1
1416
- }/3), retrying in ${delay}ms: ${e.message}`,
1417
- "warn"
1418
- );
1419
- await new Promise((resolve) => setTimeout(resolve, delay));
1420
- return this.call(userInput, _messages, retryCount + 1);
1421
- }
1422
-
1423
- this.log(`Agent failed: ${e}`, "error");
1424
-
1425
- if (
1426
- e != null &&
1427
- typeof e === "object" &&
1428
- "response" in e &&
1429
- "data" in (e as any).response
1430
- ) {
1431
- this.log(
1432
- `Error response data: ${JSON.stringify(e.response.data, null, 2)}`,
1433
- "error"
1434
- );
1435
- }
1436
-
1437
- this.agentEvents.emit(this.eventTypes.done, e.message);
1438
- return e.message;
1439
- }
1440
- }
1441
-
1442
- getStatusMessage() {
1443
- const baseMessage = `Task spend: $${this.getTotalCostUsd().toPrecision(
1444
- 3
1445
- )}\nElapsed: ${Math.floor(this.runTime() / 1000)}s\n`;
1446
-
1447
- const remainingTime =
1448
- this.maxRunTimeMs && this.startTimeMs
1449
- ? this.maxRunTimeMs - (Date.now() - this.startTimeMs)
1450
- : null;
1451
-
1452
- const remainingTurns = this.maxTurns
1453
- ? this.maxTurns - this.turnCount
1454
- : null;
1455
-
1456
- const timeRemainingMsg = remainingTime
1457
- ? `You have approximately ${Math.floor(
1458
- remainingTime / 1000
1459
- )} seconds remaining for this task. `
1460
- : "";
1461
-
1462
- const turnsRemainingMsg = remainingTurns
1463
- ? `You have ${remainingTurns} turns remaining. `
1464
- : "";
1465
-
1466
- const remainingBudget = this.maxSpend
1467
- ? this.maxSpend - this.totalCostUsd
1468
- : null;
1469
- const budgetRemainingMsg = remainingBudget
1470
- ? `You have $${remainingBudget.toFixed(4)} remaining in your budget.`
1471
- : "";
1472
-
1473
- const statusMessage = `${baseMessage}\n${timeRemainingMsg}\n${turnsRemainingMsg}\n${budgetRemainingMsg}`;
1474
- return statusMessage;
1475
- }
1476
-
1477
- logStatus() {
1478
- const statusMessage = this.getStatusMessage();
1479
- this.agentEvents.emit(this.eventTypes.agentStatus, {
1480
- agentName: this.name,
1481
- taskId: this.currentTaskId,
1482
- statusMessage,
1483
- details: {
1484
- totalCostUsd: this.getTotalCostUsd(),
1485
- elapsedMs: this.runTime(),
1486
- remainingTimeMs:
1487
- this.maxRunTimeMs && this.startTimeMs
1488
- ? this.maxRunTimeMs - (Date.now() - this.startTimeMs)
1489
- : undefined,
1490
- remainingTurns: this.maxTurns
1491
- ? this.maxTurns - this.turnCount
1492
- : undefined,
1493
- remainingBudget: this.maxSpend
1494
- ? this.maxSpend - this.totalCostUsd
1495
- : undefined,
1496
- },
1497
- timestamp: Date.now(),
1498
- });
1499
- }
1500
-
1501
- // A new message from system, non blocking
1502
- addPendingMessage(message: Message) {
1503
- if (this.status === this.eventTypes.done) {
1504
- this.log("Agent is done, cannot take more messages", "warn");
1505
- } else {
1506
- const pendingMessages = this.pendingMessages.map((m) => m.content);
1507
- if (pendingMessages.includes(message.content)) {
1508
- // Ignore messages we already have queue'd up
1509
- return;
1510
- }
1511
- this.pendingMessages.push(message);
1512
- }
1513
- }
1514
-
1515
- // A new message from users, blocks completion
1516
- addPendingUserMessage(message: Message) {
1517
- if (this.status === this.eventTypes.done) {
1518
- this.log("Agent is done, cannot take more messages", "warn");
1519
- } else {
1520
- const pendingMessages = this.pendingUserMessages.map((m) => m.content);
1521
- if (pendingMessages.includes(message.content)) {
1522
- // Ignore messages we already have queue'd up
1523
- return;
1524
- }
1525
- this.pendingUserMessages.push(message);
1526
- }
1527
- this.events.emit(this.eventTypes.userSay, message.content);
1528
- }
1529
-
1530
- /**
1531
- * Subscribe to any data-yielding source and stream its data into this agent's
1532
- * loop as non-blocking pending messages. This is the unified subscription
1533
- * primitive behind the `observe` tool — a tool poll, an event, a stream, a
1534
- * peer agent's thread, a file tail, etc. all become `ObservationSource`
1535
- * adapters feeding the same sink (`addPendingMessage`).
1536
- *
1537
- * Returns an observation id that can be passed to `stopObserving`. Auto-expires
1538
- * after `maxUpdates` or `maxDurationMs` so a forgotten observer never leaks.
1539
- */
1540
- observe(source: ObservationSource, opts: ObserveOpts = {}): string {
1541
- const {
1542
- onlyOnChange = true,
1543
- maxUpdates = 20,
1544
- maxDurationMs = 10 * 60 * 1000,
1545
- } = opts;
1546
-
1547
- this._observationSeq += 1;
1548
- // Keep the id free of characters that would break id-extraction regexes
1549
- // (labels can contain parens, spaces, JSON, etc).
1550
- const safeLabel = source.label.replace(/[^A-Za-z0-9]+/g, "_").slice(0, 24);
1551
- const id = `obs_${safeLabel}_${Date.now()}_${this._observationSeq}`;
1552
- let last: string | undefined;
1553
-
1554
- const emit = (datum: unknown) => {
1555
- // status gate: don't inject once the agent is done
1556
- if (this.status === this.eventTypes.done) {
1557
- this.stopObserving(id);
1558
- return;
1559
- }
1560
- const str = typeof datum === "string" ? datum : JSON.stringify(datum);
1561
- if (onlyOnChange && str === last) return; // dedupe noise
1562
- last = str;
1563
- const obs = this._observations.get(id);
1564
- if (!obs) return;
1565
- obs.updates += 1;
1566
- this.addPendingMessage({
1567
- role: "user",
1568
- content: `[observe:${id}] ${source.label} (update ${obs.updates}/${maxUpdates}):\n${str}`,
1569
- });
1570
- if (obs.updates >= maxUpdates) {
1571
- this.stopObserving(id, "max updates reached");
1572
- }
1573
- };
1574
-
1575
- const teardownPromise = Promise.resolve(source.start(emit)).catch((e) => {
1576
- this.log(
1577
- `observe(${source.label}) start failed: ${e?.message ?? e}`,
1578
- "warn"
1579
- );
1580
- return undefined;
1581
- });
1582
-
1583
- const expiry = maxDurationMs
1584
- ? setTimeout(
1585
- () => this.stopObserving(id, "max duration reached"),
1586
- maxDurationMs
1587
- )
1588
- : undefined;
1589
- if (expiry && typeof (expiry as any).unref === "function") {
1590
- (expiry as any).unref();
1591
- }
1592
-
1593
- this._observations.set(id, {
1594
- id,
1595
- label: source.label,
1596
- updates: 0,
1597
- teardownPromise,
1598
- expiry,
1599
- });
1600
- return id;
1601
- }
1602
-
1603
- /**
1604
- * Cancel one observation (by id) or all of them (no id). Companion to
1605
- * `observe`. Runs each source's teardown function if it returned one.
1606
- */
1607
- stopObserving(id?: string, reason = "stopped"): string {
1608
- const ids = id ? [id] : [...this._observations.keys()];
1609
- let stopped = 0;
1610
- for (const oid of ids) {
1611
- const obs = this._observations.get(oid);
1612
- if (!obs) continue;
1613
- if (obs.expiry) clearTimeout(obs.expiry);
1614
- Promise.resolve(obs.teardownPromise)
1615
- .then((fn) => {
1616
- if (typeof fn === "function") fn();
1617
- })
1618
- .catch(() => {});
1619
- this._observations.delete(oid);
1620
- stopped += 1;
1621
- }
1622
- return id
1623
- ? stopped
1624
- ? `Stopped observer ${id} (${reason}).`
1625
- : `No active observer found with id: ${id}.`
1626
- : `Stopped ${stopped} active observer(s) (${reason}).`;
1627
- }
1628
-
1629
- getMessagesLength(messages: Message[]) {
1630
- return JSON.stringify(messages).split(" ").length;
1631
- }
1632
-
1633
- /**
1634
- * Returns the best available estimate of how many tokens the current
1635
- * conversation occupies in the model's context window, for the purpose of
1636
- * deciding when to compact.
1637
- *
1638
- * Prefers the REAL prompt token count reported by the most recent completion
1639
- * response (lastPromptTokens) — this is exactly how many tokens the model
1640
- * consumed for the last request (fresh input + cache read + cache write), so
1641
- * it is far more accurate than the whitespace-based getMessagesLength()
1642
- * heuristic (which counts space-separated chunks of the JSON-stringified
1643
- * messages and can be off by a large factor).
1644
- *
1645
- * Falls back to the whitespace estimate when no real usage has been observed
1646
- * yet (e.g. before the first completion, or when a provider omits usage).
1647
- *
1648
- * Note: lastPromptTokens reflects the context size at the START of the last
1649
- * request, so it lags by whatever the model generated + tool results appended
1650
- * since then. That lag is intentionally covered by the 70% headroom baked
1651
- * into getCompressThreshold().
1652
- */
1653
- getContextTokenCount(messages: Message[]): number {
1654
- if (this.lastPromptTokens > 0) {
1655
- return this.lastPromptTokens;
1656
- }
1657
- return this.getMessagesLength(messages);
1658
- }
1659
-
1660
- /**
1661
- * Detects whether tool call arguments appear truncated due to hitting the output token limit.
1662
- * Two signals are checked:
1663
- * 1. Any tool call argument is empty or invalid JSON (hard truncation).
1664
- * 2. The model reported many output tokens but the total argument content received is tiny
1665
- * relative to what those tokens should represent (soft/silent truncation).
1666
- *
1667
- * @param toolCalls - The tool calls from the CURRENT choice being checked.
1668
- * @param allToolCalls - ALL tool calls across ALL choices in the response (used for the size heuristic).
1669
- * Returns a warning system message if truncation is detected, or null otherwise.
1670
- */
1671
- detectTruncatedToolCalls(
1672
- toolCalls: ToolCall[],
1673
- response: CompletionResponse,
1674
- allToolCalls?: ToolCall[]
1675
- ): { role: string; content: string } | null {
1676
- // Subtract thinking/reasoning tokens — they're billed as output tokens but
1677
- // don't produce visible argument content, so including them inflates the heuristic.
1678
- const rawOutputTokens: number = response?.usage?.completion_tokens || 0;
1679
- const thinkingTokens: number =
1680
- (response?.usage?.output_tokens_details?.thinking_tokens ?? 0) +
1681
- (response?.usage?.output_tokens_details?.reasoning_tokens ?? 0);
1682
- const outputTokens = Math.max(0, rawOutputTokens - thinkingTokens);
1683
- // Use allToolCalls for the size heuristic so that parallel tool calls from
1684
- // Anthropic (each mapped to a separate choice) are counted together. Without
1685
- // this, a response with N parallel tool calls would compare the full
1686
- // completion_tokens count against only 1/N of the actual argument content,
1687
- // causing false-positive truncation warnings.
1688
- const callsForSizeCheck = allToolCalls ?? toolCalls;
1689
- const totalArgLength = callsForSizeCheck.reduce(
1690
- (sum, tc) => sum + (tc.function?.arguments?.length || 0),
1691
- 0
1692
- );
1693
-
1694
- // Percentage-based heuristic: if actual arg chars are less than ~10% of the
1695
- // expected chars (outputTokens * 4 chars/token), the output was likely truncated.
1696
- // Only apply when outputTokens > 1000 to avoid false positives on small responses.
1697
- const expectedArgChars = outputTokens * 4;
1698
- const suspiciouslySmallArgs =
1699
- outputTokens > 1000 && totalArgLength < expectedArgChars * 0.1;
1700
-
1701
- for (const toolCall of toolCalls) {
1702
- const args = toolCall.function?.arguments || "";
1703
- let isInvalidJson = false;
1704
- try {
1705
- JSON.parse(args);
1706
- } catch {
1707
- isInvalidJson = true;
1708
- }
1709
- if (isInvalidJson || args.trim() === "" || suspiciouslySmallArgs) {
1710
- this.log(
1711
- `Tool call '${toolCall.function?.name}' has malformed/truncated arguments — likely hit output token limit (outputTokens=${outputTokens}, argLength=${args.length})`,
1712
- "warn"
1713
- );
1714
- return {
1715
- role: "user",
1716
- content:
1717
- "⚠️ Output limit warning: Your last tool call had incomplete or missing arguments, which usually means you exceeded the output token limit mid-response. The model reported " +
1718
- outputTokens +
1719
- " output tokens but only " +
1720
- totalArgLength +
1721
- " characters of tool call arguments were received. Please write smaller, more concise content in your tool calls. Aim for no more than 4000 tokens of output per response. Break large responses into smaller pieces if needed.",
1722
- };
1723
- }
1724
- }
1725
-
1726
- return null;
1727
- }
1728
-
1729
- extractContentFromMessages(messages: Message[]): string {
1730
- const content = messages
1731
- .filter((m) => typeof m.content === "string" && m.content.trim())
1732
- .map((m) => m.content);
1733
-
1734
- const finalAnswer = messages
1735
- .filter((m) => m.tool_calls?.length)
1736
- .flatMap((t) => t.tool_calls)
1737
- .filter((t) => t.function.name === "finalAnswer")
1738
- .map((t) => t.function.arguments);
1739
-
1740
- return [...content, ...finalAnswer].join("\n\n");
1741
- }
1742
-
1743
- private startBackgroundCompaction(messages: Message[]): void {
1744
- const snapshot = messages.slice();
1745
- let resumeIndex = snapshot.length - 1;
1746
- while (resumeIndex >= 0 && snapshot[resumeIndex].role !== "assistant") {
1747
- resumeIndex--;
1748
- }
1749
- const compressionEnd =
1750
- resumeIndex === -1 ? snapshot.length : resumeIndex;
1751
- const generation = this._compactionGeneration;
1752
-
1753
- const promise = (async () => {
1754
- const taskBreakdown = await this.getTaskBreakdown(snapshot, false);
1755
- if (generation !== this._compactionGeneration) return;
1756
- this.taskBreakdown = taskBreakdown;
1757
- let summary = "";
1758
- const compactedSnapshot = await this.compressMessages(
1759
- snapshot,
1760
- (generatedSummary) => {
1761
- summary = generatedSummary;
1762
- },
1763
- taskBreakdown
1764
- );
1765
- if (generation !== this._compactionGeneration) return;
1766
-
1767
- const preservedSnapshotLength = snapshot.length - compressionEnd;
1768
- this._completedCompaction = {
1769
- compressionEnd,
1770
- originalPrefix: snapshot.slice(0, compressionEnd),
1771
- replacementPrefix: compactedSnapshot.slice(
1772
- 0,
1773
- compactedSnapshot.length - preservedSnapshotLength
1774
- ),
1775
- summary,
1776
- };
1777
- this.log("Background compaction completed; it will be applied next turn");
1778
- })();
1779
-
1780
- this._compactionPromise = promise;
1781
- promise
1782
- .catch((error) => {
1783
- if (generation === this._compactionGeneration) {
1784
- this.log(
1785
- `Background compaction failed; a later turn will retry: ${error}`,
1786
- "warn"
1787
- );
1788
- }
1789
- })
1790
- .finally(() => {
1791
- if (this._compactionPromise === promise) {
1792
- this._compactionPromise = null;
1793
- }
1794
- });
1795
- }
1796
-
1797
- async getTaskBreakdown(messages: Message[], cacheResult = true) {
1798
- if (this.taskBreakdown) {
1799
- return this.taskBreakdown;
1800
- }
1801
-
1802
- const taskPrompt = `
1803
- TASK INTERRUPT. CONTEXT COMPACTION NEEDED. Analyze all previous messages.
1804
-
1805
- Generate a detailed task breakdown for this conversation, include a section for the following:
1806
- 1. Task List
1807
- 2. Completion Criteria - when the agent should stop
1808
-
1809
- Your output will be used to guide the work of the agent, and determine when we've accomplished the goal
1810
- `;
1811
-
1812
- const model = this.getModel();
1813
-
1814
- const taskBreakdownMessages = [
1815
- ...messages,
1816
- {
1817
- role: "user",
1818
- content: taskPrompt,
1819
- },
1820
- ] as Message[];
1821
-
1822
- const response = await this.createAgentCompletion(
1823
- {
1824
- messages: taskBreakdownMessages,
1825
- tool_choice: "none",
1826
- },
1827
- { updateLastPromptTokens: false }
1828
- );
1829
-
1830
- const breakdownContent = this.extractContentFromMessages(
1831
- response.choices?.map((c) => c.message)
1832
- );
1833
- // The model may return null content (e.g. when it responds with tool calls
1834
- // instead of text). Guard against storing a literal null so that template
1835
- // strings don't render "null".
1836
- if (!breakdownContent) {
1837
- console.log(JSON.stringify(response.choices, null, 2));
1838
- throw new Error(
1839
- "Compaction task-breakdown request returned no text content"
1840
- );
1841
- }
1842
-
1843
- if (cacheResult) {
1844
- this.taskBreakdown = breakdownContent;
1845
- }
1846
- this.log(`task breakdown cost: ${response.usd_cost}`);
1847
- return breakdownContent;
1848
- }
1849
-
1850
- async compressMessages(
1851
- messages: Message[],
1852
- onSummary?: (summary: string) => void,
1853
- taskBreakdown = this.taskBreakdown
1854
- ) {
1855
- // Preserve the latest agent interaction exactly. Starting the resumed thread
1856
- // at the final assistant message keeps its tool calls, every tool response,
1857
- // and any subsequent user messages together as one protocol-valid unit.
1858
- let resumeIndex = messages.length - 1;
1859
- while (resumeIndex >= 0 && messages[resumeIndex].role !== "assistant") {
1860
- resumeIndex--;
1861
- }
1862
- const compressionEnd = resumeIndex === -1 ? messages.length : resumeIndex;
1863
- const toCompress = messages.slice(0, compressionEnd);
1864
- const resumeMessages = messages.slice(compressionEnd);
1865
-
1866
- this.log(
1867
- `Compressing messages from 0 to ${compressionEnd}, resuming from ${resumeIndex}, total messages: ${messages.length}`
1868
- );
1869
- const toCompressPrompt = `TASK INTERRUPT. CONTEXT COMPACTION NEEDED.
1870
- We are compressing our conversation to save memory.
1871
- Please summarize the conversation so far, so that we may continue the original task with a smaller context
1872
-
1873
- Include the following sections:
1874
- 1. Initial Request - what this agent was originally tasked with.
1875
- 2. Progress - what has been tried so far,
1876
- 3. Next Steps - what we're about to do next to continue the user's original request.
1877
- 4. Tasks remaining - what tasks are left from the initial task breakdown.
1878
-
1879
- ${
1880
- taskBreakdown
1881
- ? `Our initial task breakdown: ${taskBreakdown}`
1882
- : ""
1883
- }
1884
-
1885
- This summary will replace the older history. The latest agent interaction will remain verbatim:
1886
-
1887
- `;
1888
-
1889
- const compressMessagesPayload = [
1890
- ...toCompress,
1891
- {
1892
- role: "user",
1893
- content: toCompressPrompt,
1894
- },
1895
- ] as Message[];
1896
-
1897
- const response = await this.createAgentCompletion(
1898
- {
1899
- messages: compressMessagesPayload,
1900
- tool_choice: "none",
1901
- },
1902
- { updateLastPromptTokens: false }
1903
- );
1904
-
1905
- const summary = this.extractContentFromMessages(
1906
- response.choices?.map((c) => c.message)
1907
- );
1908
-
1909
- if (summary.length === 0) {
1910
- console.log(JSON.stringify(response.choices, null, 2));
1911
- throw new Error("Compaction summary request returned no text content");
1912
- }
1913
-
1914
- if (onSummary) {
1915
- onSummary(summary);
1916
- } else {
1917
- this.summaries.push(summary);
1918
- }
1919
-
1920
- const startMessages = [
1921
- {
1922
- role: "user",
1923
- content: `
1924
- ${
1925
- taskBreakdown
1926
- ? `Initial task breakdown:\n ${taskBreakdown}`
1927
- : "(No task breakdown available — summarize what you know from context above)"
1928
- }
1929
-
1930
- We have just compressed the conversation to save memory:
1931
- ${
1932
- summary.length > 0
1933
- ? JSON.stringify(summary)
1934
- : "(summary unavailable — please continue from the task breakdown above)"
1935
- }
1936
-
1937
- Please continue the task from where we left off
1938
- `,
1939
- },
1940
- ] as Message[];
1941
- const systemMessages = toCompress.filter((m) => m.role === "system");
1942
-
1943
- const newMessages = [
1944
- ...systemMessages,
1945
- ...startMessages,
1946
- ...resumeMessages,
1947
- ];
1948
-
1949
- const oldLength = this.getMessagesLength(messages);
1950
- const newLength = this.getMessagesLength(newMessages);
1951
- const compressionRatio = (
1952
- ((oldLength - newLength) / oldLength) *
1953
- 100
1954
- ).toFixed(2);
1955
-
1956
- this.log(`compression cost: ${response.usd_cost}`);
1957
- this.log(
1958
- `Compressed messages from ${oldLength} to ${newLength}, ${compressionRatio}% reduction in size`
1959
- );
1960
-
1961
- return newMessages;
1962
- }
1963
- }