@tyvm/knowhow 0.0.159 → 0.0.161

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 (906) hide show
  1. package/README.md +6 -6
  2. package/package.json +2 -2
  3. package/ts_build/package.json +2 -2
  4. package/ts_build/src/chat/CliChatService.d.ts +2 -1
  5. package/ts_build/src/chat/CliChatService.js +29 -3
  6. package/ts_build/src/chat/CliChatService.js.map +1 -1
  7. package/ts_build/src/chat/modules/AgentModule.js +21 -17
  8. package/ts_build/src/chat/modules/AgentModule.js.map +1 -1
  9. package/ts_build/src/chat/renderer/ConsoleRenderer.js +32 -25
  10. package/ts_build/src/chat/renderer/ConsoleRenderer.js.map +1 -1
  11. package/ts_build/src/clients/anthropic.js +4 -1
  12. package/ts_build/src/clients/anthropic.js.map +1 -1
  13. package/ts_build/src/clients/contextLimits.js +13 -7
  14. package/ts_build/src/clients/contextLimits.js.map +1 -1
  15. package/ts_build/src/clients/index.js +3 -1
  16. package/ts_build/src/clients/index.js.map +1 -1
  17. package/ts_build/src/clients/openai.js +18 -5
  18. package/ts_build/src/clients/openai.js.map +1 -1
  19. package/ts_build/src/clients/pricing/anthropic.d.ts +2 -0
  20. package/ts_build/src/clients/pricing/anthropic.js +21 -1
  21. package/ts_build/src/clients/pricing/anthropic.js.map +1 -1
  22. package/ts_build/src/clients/pricing/openai.d.ts +2 -0
  23. package/ts_build/src/clients/pricing/openai.js +32 -7
  24. package/ts_build/src/clients/pricing/openai.js.map +1 -1
  25. package/ts_build/src/clients/pricing/types.d.ts +4 -0
  26. package/ts_build/src/clients/pricing/types.js.map +1 -1
  27. package/ts_build/src/clients/pricing/xai.d.ts +2 -0
  28. package/ts_build/src/clients/pricing/xai.js +13 -8
  29. package/ts_build/src/clients/pricing/xai.js.map +1 -1
  30. package/ts_build/src/clients/xai.js +20 -8
  31. package/ts_build/src/clients/xai.js.map +1 -1
  32. package/ts_build/src/commands/misc.js +15 -2
  33. package/ts_build/src/commands/misc.js.map +1 -1
  34. package/ts_build/src/logger.d.ts +1 -0
  35. package/ts_build/src/logger.js +13 -1
  36. package/ts_build/src/logger.js.map +1 -1
  37. package/ts_build/src/remotes.d.ts +2 -0
  38. package/ts_build/src/remotes.js +20 -2
  39. package/ts_build/src/remotes.js.map +1 -1
  40. package/ts_build/src/tunnel.js +7 -2
  41. package/ts_build/src/tunnel.js.map +1 -1
  42. package/ts_build/src/types.d.ts +12 -1
  43. package/ts_build/src/types.js.map +1 -1
  44. package/ts_build/src/utils/InputQueueManager.d.ts +8 -1
  45. package/ts_build/src/utils/InputQueueManager.js +74 -3
  46. package/ts_build/src/utils/InputQueueManager.js.map +1 -1
  47. package/ts_build/src/utils/index.d.ts +3 -1
  48. package/ts_build/src/utils/index.js +11 -3
  49. package/ts_build/src/utils/index.js.map +1 -1
  50. package/ts_build/src/worker.js +4 -1
  51. package/ts_build/src/worker.js.map +1 -1
  52. package/ts_build/src/workers/tools/listAllowedPorts.d.ts +2 -1
  53. package/ts_build/src/workers/tools/listAllowedPorts.js +1 -1
  54. package/ts_build/src/workers/tools/listAllowedPorts.js.map +1 -1
  55. package/CONFIG.md +0 -429
  56. package/PROCESSING.md +0 -450
  57. package/WORKER.md +0 -260
  58. package/autodoc/README.md +0 -324
  59. package/autodoc/chat-guide.md +0 -444
  60. package/autodoc/cli-reference.md +0 -720
  61. package/autodoc/config-reference.md +0 -642
  62. package/autodoc/embeddings-guide.md +0 -467
  63. package/autodoc/generate-guide.md +0 -437
  64. package/autodoc/language-plugin-guide.md +0 -417
  65. package/autodoc/modules-guide.md +0 -379
  66. package/autodoc/plugins-guide.md +0 -721
  67. package/autodoc/quickstart-guide.md +0 -126
  68. package/autodoc/skills-guide.md +0 -584
  69. package/autodoc/worker-guide.md +0 -519
  70. package/docs/input-queue-manager.md +0 -142
  71. package/docs/multi-worker-management.md +0 -142
  72. package/docs/shell-commands.md +0 -174
  73. package/jest.config.js +0 -19
  74. package/jest.manual.config.js +0 -19
  75. package/scripts/README.md +0 -119
  76. package/scripts/build-for-node.sh +0 -148
  77. package/scripts/cache-miss-debug.ts +0 -365
  78. package/scripts/check-isolated-deps.sh +0 -69
  79. package/scripts/check-model-pricing.ts +0 -509
  80. package/scripts/compare-openrouter-coverage.ts +0 -576
  81. package/scripts/migrate-usage-json.js +0 -147
  82. package/scripts/publish.sh +0 -86
  83. package/scripts/restore_keys.sh +0 -59
  84. package/scripts/test-repetition-hint.ts +0 -302
  85. package/scripts/unset_keys.sh +0 -60
  86. package/src/agents/base/base.ts +0 -1963
  87. package/src/agents/base/prompt.ts +0 -55
  88. package/src/agents/configurable/ConfigAgent.ts +0 -24
  89. package/src/agents/developer/developer.ts +0 -76
  90. package/src/agents/historyRollback.ts +0 -36
  91. package/src/agents/index.ts +0 -52
  92. package/src/agents/interface.ts +0 -11
  93. package/src/agents/patcher/codebase.md +0 -27
  94. package/src/agents/patcher/patcher.ts +0 -131
  95. package/src/agents/researcher/researcher.ts +0 -115
  96. package/src/agents/setup/setup.ts +0 -63
  97. package/src/agents/tools/addInternalTools.ts +0 -21
  98. package/src/agents/tools/agentCall.ts +0 -34
  99. package/src/agents/tools/aiClient.ts +0 -178
  100. package/src/agents/tools/askHuman.ts +0 -10
  101. package/src/agents/tools/callPlugin.ts +0 -10
  102. package/src/agents/tools/connectAgent.ts +0 -355
  103. package/src/agents/tools/embeddingSearch.ts +0 -6
  104. package/src/agents/tools/execCommand.ts +0 -162
  105. package/src/agents/tools/fileSearch.ts +0 -35
  106. package/src/agents/tools/finalAnswer.ts +0 -4
  107. package/src/agents/tools/googleSearch.ts +0 -243
  108. package/src/agents/tools/index.ts +0 -33
  109. package/src/agents/tools/language/definitions.ts +0 -105
  110. package/src/agents/tools/language/index.ts +0 -20
  111. package/src/agents/tools/lazy/definitions.ts +0 -72
  112. package/src/agents/tools/lazy/disableTools.ts +0 -16
  113. package/src/agents/tools/lazy/enableTools.ts +0 -16
  114. package/src/agents/tools/lazy/index.ts +0 -3
  115. package/src/agents/tools/lazy/listAvailableTools.ts +0 -17
  116. package/src/agents/tools/lintFile.ts +0 -19
  117. package/src/agents/tools/list.ts +0 -739
  118. package/src/agents/tools/loadImageAsBase64.ts +0 -83
  119. package/src/agents/tools/loadWebpage.ts +0 -19
  120. package/src/agents/tools/mcp/connectMcpServer.ts +0 -40
  121. package/src/agents/tools/mcp/definitions.ts +0 -67
  122. package/src/agents/tools/mcp/disconnectMcpServer.ts +0 -40
  123. package/src/agents/tools/mcp/index.ts +0 -3
  124. package/src/agents/tools/mcp/listAvailableMcpServers.ts +0 -28
  125. package/src/agents/tools/minimal/callTool.ts +0 -45
  126. package/src/agents/tools/minimal/definitions.ts +0 -50
  127. package/src/agents/tools/minimal/index.ts +0 -3
  128. package/src/agents/tools/minimal/inspectTools.ts +0 -27
  129. package/src/agents/tools/modifyFile.ts +0 -53
  130. package/src/agents/tools/observe.ts +0 -247
  131. package/src/agents/tools/patch.ts +0 -1287
  132. package/src/agents/tools/readBlocks.ts +0 -83
  133. package/src/agents/tools/readFile.ts +0 -105
  134. package/src/agents/tools/replyToParent.ts +0 -123
  135. package/src/agents/tools/runGenerate.ts +0 -210
  136. package/src/agents/tools/scanFile.ts +0 -16
  137. package/src/agents/tools/sendAgentMessage.ts +0 -139
  138. package/src/agents/tools/skills.ts +0 -79
  139. package/src/agents/tools/startAgentTask.ts +0 -393
  140. package/src/agents/tools/stringReplace.ts +0 -105
  141. package/src/agents/tools/textSearch.ts +0 -128
  142. package/src/agents/tools/types/fileblock.ts +0 -5
  143. package/src/agents/tools/visionTool.ts +0 -35
  144. package/src/agents/tools/waitForAgentCompleted.ts +0 -270
  145. package/src/agents/tools/writeFile.ts +0 -106
  146. package/src/agents/tools/ycmd/client.ts +0 -608
  147. package/src/agents/tools/ycmd/definitions.ts +0 -294
  148. package/src/agents/tools/ycmd/detection.ts +0 -211
  149. package/src/agents/tools/ycmd/index.ts +0 -11
  150. package/src/agents/tools/ycmd/installer.ts +0 -251
  151. package/src/agents/tools/ycmd/server.ts +0 -545
  152. package/src/agents/tools/ycmd/serverManager.ts +0 -316
  153. package/src/agents/tools/ycmd/tools/completion.ts +0 -113
  154. package/src/agents/tools/ycmd/tools/diagnostics.ts +0 -166
  155. package/src/agents/tools/ycmd/tools/getLocations.ts +0 -173
  156. package/src/agents/tools/ycmd/tools/goto.ts +0 -169
  157. package/src/agents/tools/ycmd/tools/refactor.ts +0 -204
  158. package/src/agents/tools/ycmd/tools/signature.ts +0 -174
  159. package/src/agents/tools/ycmd/tools/start.ts +0 -95
  160. package/src/agents/tools/ycmd/utils/pathUtils.ts +0 -59
  161. package/src/ai.ts +0 -306
  162. package/src/auth/browserLogin.ts +0 -406
  163. package/src/auth/environmentAuth.ts +0 -51
  164. package/src/auth/errors.ts +0 -6
  165. package/src/auth/jwtStore.ts +0 -70
  166. package/src/auth/keyAuth.ts +0 -142
  167. package/src/auth/keyManager.ts +0 -331
  168. package/src/auth/registerIdentity.ts +0 -67
  169. package/src/auth/spinner.ts +0 -23
  170. package/src/chat/CliChatService.ts +0 -438
  171. package/src/chat/modules/AgentModule.ts +0 -1664
  172. package/src/chat/modules/AskModule.ts +0 -98
  173. package/src/chat/modules/BaseChatModule.ts +0 -65
  174. package/src/chat/modules/ClipboardImageModule.ts +0 -136
  175. package/src/chat/modules/CustomCommandsModule.ts +0 -80
  176. package/src/chat/modules/InternalChatModule.ts +0 -216
  177. package/src/chat/modules/RemoteSyncModule.ts +0 -482
  178. package/src/chat/modules/RendererModule.ts +0 -139
  179. package/src/chat/modules/SearchModule.ts +0 -168
  180. package/src/chat/modules/SessionsModule.ts +0 -969
  181. package/src/chat/modules/SetupModule.ts +0 -185
  182. package/src/chat/modules/ShellCommandModule.ts +0 -98
  183. package/src/chat/modules/SystemModule.ts +0 -161
  184. package/src/chat/modules/ToolCommandModule.ts +0 -102
  185. package/src/chat/modules/VoiceModule.ts +0 -70
  186. package/src/chat/modules/index.ts +0 -8
  187. package/src/chat/renderer/CompactRenderer.ts +0 -229
  188. package/src/chat/renderer/ConsoleRenderer.ts +0 -160
  189. package/src/chat/renderer/FancyRenderer.ts +0 -440
  190. package/src/chat/renderer/PlainRenderer.ts +0 -218
  191. package/src/chat/renderer/index.ts +0 -6
  192. package/src/chat/renderer/loadRenderer.ts +0 -316
  193. package/src/chat/renderer/messagesToRenderEvents.ts +0 -96
  194. package/src/chat/renderer/types.ts +0 -99
  195. package/src/chat/types.ts +0 -146
  196. package/src/chat.ts +0 -140
  197. package/src/cli.ts +0 -180
  198. package/src/clients/anthropic.ts +0 -772
  199. package/src/clients/attribution.ts +0 -53
  200. package/src/clients/cerebras.ts +0 -10
  201. package/src/clients/contextLimits.ts +0 -263
  202. package/src/clients/copilot.ts +0 -23
  203. package/src/clients/deepseek.ts +0 -16
  204. package/src/clients/fireworks.ts +0 -71
  205. package/src/clients/gemini.ts +0 -1169
  206. package/src/clients/github.ts +0 -16
  207. package/src/clients/groq.ts +0 -15
  208. package/src/clients/http.ts +0 -719
  209. package/src/clients/index.ts +0 -1153
  210. package/src/clients/knowhow.ts +0 -130
  211. package/src/clients/knowhowMcp.ts +0 -118
  212. package/src/clients/llama.ts +0 -16
  213. package/src/clients/meta.ts +0 -27
  214. package/src/clients/mistral.ts +0 -16
  215. package/src/clients/nvidia.ts +0 -16
  216. package/src/clients/openai.ts +0 -1186
  217. package/src/clients/openrouter.ts +0 -24
  218. package/src/clients/pricing/anthropic.ts +0 -149
  219. package/src/clients/pricing/cerebras.ts +0 -11
  220. package/src/clients/pricing/copilot.ts +0 -60
  221. package/src/clients/pricing/deepseek.ts +0 -15
  222. package/src/clients/pricing/fireworks.ts +0 -182
  223. package/src/clients/pricing/github.ts +0 -69
  224. package/src/clients/pricing/google.ts +0 -385
  225. package/src/clients/pricing/groq.ts +0 -56
  226. package/src/clients/pricing/index.ts +0 -44
  227. package/src/clients/pricing/llama.ts +0 -18
  228. package/src/clients/pricing/meta.ts +0 -12
  229. package/src/clients/pricing/mistral.ts +0 -34
  230. package/src/clients/pricing/models.ts +0 -25
  231. package/src/clients/pricing/nvidia.ts +0 -102
  232. package/src/clients/pricing/openai.ts +0 -409
  233. package/src/clients/pricing/openrouter.ts +0 -36
  234. package/src/clients/pricing/qwen.ts +0 -80
  235. package/src/clients/pricing/types.ts +0 -125
  236. package/src/clients/pricing/xai.ts +0 -137
  237. package/src/clients/qwen.ts +0 -16
  238. package/src/clients/responseMetadata.ts +0 -221
  239. package/src/clients/types.ts +0 -531
  240. package/src/clients/withRetry.ts +0 -89
  241. package/src/clients/xai.ts +0 -693
  242. package/src/cloudWorker.ts +0 -394
  243. package/src/commands/agent.ts +0 -342
  244. package/src/commands/agents.ts +0 -1037
  245. package/src/commands/behaviors.ts +0 -47
  246. package/src/commands/convert.ts +0 -291
  247. package/src/commands/hash.ts +0 -179
  248. package/src/commands/mcp.ts +0 -743
  249. package/src/commands/misc.ts +0 -373
  250. package/src/commands/modules.ts +0 -704
  251. package/src/commands/processes.ts +0 -248
  252. package/src/commands/remote.ts +0 -77
  253. package/src/commands/replay.ts +0 -503
  254. package/src/commands/sandbox.ts +0 -566
  255. package/src/commands/services.ts +0 -168
  256. package/src/commands/skills.ts +0 -107
  257. package/src/commands/workers.ts +0 -168
  258. package/src/config.ts +0 -468
  259. package/src/conversion.ts +0 -69
  260. package/src/dataset/diffs/README.md +0 -12
  261. package/src/dataset/diffs/debug-errors.ts +0 -29
  262. package/src/dataset/diffs/debug.ts +0 -64
  263. package/src/dataset/diffs/generate.ts +0 -71
  264. package/src/dataset/diffs/jsonl.ts +0 -53
  265. package/src/dataset/diffs/test.ts +0 -194
  266. package/src/embeddings.ts +0 -494
  267. package/src/fileSync.ts +0 -369
  268. package/src/generate.ts +0 -529
  269. package/src/hashes.ts +0 -180
  270. package/src/index.ts +0 -261
  271. package/src/logger.ts +0 -197
  272. package/src/login.ts +0 -209
  273. package/src/microphone.ts +0 -141
  274. package/src/migrations.ts +0 -151
  275. package/src/plugins/AgentsMdPlugin.ts +0 -118
  276. package/src/plugins/GitPlugin.ts +0 -598
  277. package/src/plugins/LinterPlugin.ts +0 -214
  278. package/src/plugins/PluginBase.ts +0 -70
  279. package/src/plugins/SkillsPlugin.ts +0 -37
  280. package/src/plugins/embedding.ts +0 -82
  281. package/src/plugins/exec.ts +0 -70
  282. package/src/plugins/language.ts +0 -290
  283. package/src/plugins/plugins.ts +0 -175
  284. package/src/plugins/tmux.ts +0 -132
  285. package/src/plugins/types.ts +0 -36
  286. package/src/plugins/url.ts +0 -101
  287. package/src/plugins/vim.ts +0 -89
  288. package/src/processes/ProcessManager.ts +0 -96
  289. package/src/processes/managedProcessShim.ts +0 -138
  290. package/src/processors/Base64ImageDetector.ts +0 -502
  291. package/src/processors/CustomVariables.ts +0 -693
  292. package/src/processors/GemmaToolProcessor.ts +0 -163
  293. package/src/processors/HarmonyToolProcessor.ts +0 -264
  294. package/src/processors/JsonCompressor.ts +0 -510
  295. package/src/processors/MinimalToolsMessageProcessor.ts +0 -113
  296. package/src/processors/TokenCompressor.ts +0 -620
  297. package/src/processors/ToolResponseCache.ts +0 -322
  298. package/src/processors/XmlToolCallProcessor.ts +0 -533
  299. package/src/processors/index.ts +0 -14
  300. package/src/processors/tools/boundedToolResponse.ts +0 -49
  301. package/src/processors/tools/grepToolResponse.ts +0 -230
  302. package/src/processors/tools/index.ts +0 -23
  303. package/src/processors/tools/jqToolResponse.ts +0 -159
  304. package/src/processors/tools/listStoredToolResponses.ts +0 -124
  305. package/src/processors/tools/tailToolResponse.ts +0 -148
  306. package/src/prompts/BasicCodeDocumenter.ts +0 -1
  307. package/src/prompts/BasicProjectDocumenter.ts +0 -1
  308. package/src/prompts/EmbeddingSeachHelper.ts +0 -1
  309. package/src/prompts/KnowhowConfigExamples.ts +0 -376
  310. package/src/prompts/index.ts +0 -9
  311. package/src/remotes.ts +0 -110
  312. package/src/server/index.ts +0 -16
  313. package/src/services/AgentService.ts +0 -134
  314. package/src/services/AgentSyncFs.ts +0 -775
  315. package/src/services/AgentSyncKnowhowWeb.ts +0 -389
  316. package/src/services/BehaviorsService.ts +0 -466
  317. package/src/services/DockerService.ts +0 -511
  318. package/src/services/EmbeddingService.ts +0 -427
  319. package/src/services/EmbeddingsService.ts +0 -73
  320. package/src/services/EventService.ts +0 -279
  321. package/src/services/ExtensionsService.ts +0 -25
  322. package/src/services/KnowhowClient.ts +0 -928
  323. package/src/services/LazyToolsService.ts +0 -210
  324. package/src/services/Mcp.ts +0 -727
  325. package/src/services/McpServer.ts +0 -155
  326. package/src/services/McpWebsocketTransport.ts +0 -87
  327. package/src/services/MediaProcessorService.ts +0 -669
  328. package/src/services/MessageProcessor.ts +0 -114
  329. package/src/services/MinimalToolsService.ts +0 -177
  330. package/src/services/RuntimeReloadService.ts +0 -31
  331. package/src/services/S3.ts +0 -61
  332. package/src/services/SessionManager.ts +0 -358
  333. package/src/services/SkillsService.ts +0 -822
  334. package/src/services/SyncedAgentWatcher.ts +0 -124
  335. package/src/services/SyncerService.ts +0 -191
  336. package/src/services/TaskRegistry.ts +0 -110
  337. package/src/services/Tools.ts +0 -580
  338. package/src/services/TracingService.ts +0 -116
  339. package/src/services/conversion/ConversionService.ts +0 -757
  340. package/src/services/conversion/index.ts +0 -2
  341. package/src/services/conversion/types.ts +0 -87
  342. package/src/services/flags.ts +0 -51
  343. package/src/services/index.ts +0 -117
  344. package/src/services/modules/computerUse.ts +0 -218
  345. package/src/services/modules/index.ts +0 -314
  346. package/src/services/modules/types.ts +0 -109
  347. package/src/services/types.ts +0 -60
  348. package/src/services/watchers/FsSyncer.ts +0 -199
  349. package/src/services/watchers/RemoteSyncer.ts +0 -196
  350. package/src/services/watchers/index.ts +0 -2
  351. package/src/tunnel.ts +0 -243
  352. package/src/types.ts +0 -282
  353. package/src/util/Trace.ts +0 -236
  354. package/src/utils/InputQueueManager.ts +0 -493
  355. package/src/utils/errors.ts +0 -0
  356. package/src/utils/http.ts +0 -150
  357. package/src/utils/index.ts +0 -111
  358. package/src/worker.ts +0 -696
  359. package/src/workerRegistry.ts +0 -152
  360. package/src/workers/auth/PasskeySetup.ts +0 -181
  361. package/src/workers/auth/WorkerPasskeyAuth.ts +0 -190
  362. package/src/workers/auth/WsMiddleware.ts +0 -99
  363. package/src/workers/auth/authMiddleware.ts +0 -104
  364. package/src/workers/auth/types.ts +0 -70
  365. package/src/workers/tools/getChallenge.ts +0 -33
  366. package/src/workers/tools/index.ts +0 -20
  367. package/src/workers/tools/listAllowedPorts.ts +0 -30
  368. package/src/workers/tools/lock.ts +0 -31
  369. package/src/workers/tools/reloadConfig.ts +0 -84
  370. package/src/workers/tools/unlock.ts +0 -116
  371. package/tests/XmlToolCallProcessor.test.ts +0 -468
  372. package/tests/agents/interrupt.test.ts +0 -200
  373. package/tests/agents/observe-base.test.ts +0 -183
  374. package/tests/agents/tools/connectAgent.test.ts +0 -138
  375. package/tests/agents/tools/observe.test.ts +0 -179
  376. package/tests/agents/tools/readFile.test.ts +0 -88
  377. package/tests/agents/tools/replyToParent.test.ts +0 -125
  378. package/tests/agents/tools/sendAgentMessage.test.ts +0 -99
  379. package/tests/agents/tools/waitForAgentCompleted.test.ts +0 -147
  380. package/tests/chat/detach-attach-rendering.test.ts +0 -315
  381. package/tests/clients/AIClient.test.ts +0 -668
  382. package/tests/clients/anthropic.test.ts +0 -202
  383. package/tests/clients/contextLimits.test.ts +0 -97
  384. package/tests/clients/fireworks.test.ts +0 -65
  385. package/tests/clients/openai.images.test.ts +0 -105
  386. package/tests/clients/pricing.test.ts +0 -206
  387. package/tests/clients/reasoningEffort.test.ts +0 -140
  388. package/tests/compressor/bigstring.test.ts +0 -450
  389. package/tests/compressor/bigstring.txt +0 -1
  390. package/tests/compressor/githubjson.txt +0 -1
  391. package/tests/compressor/toolResponseCache.test.ts +0 -304
  392. package/tests/compressor/usageBase64.json +0 -159
  393. package/tests/compressor/usageBase64.test.ts +0 -175
  394. package/tests/fixtures/fake-secret.txt +0 -1
  395. package/tests/manual/agent-events/run-test.ts +0 -203
  396. package/tests/manual/browser-login/README.md +0 -189
  397. package/tests/manual/browser-login/test_browser_login_basic.ts +0 -115
  398. package/tests/manual/browser-login/test_cli_integration.ts +0 -169
  399. package/tests/manual/browser-login/test_cross_platform_browser.ts +0 -186
  400. package/tests/manual/browser-login/test_error_scenarios.ts +0 -223
  401. package/tests/manual/cli/no-env.sh +0 -274
  402. package/tests/manual/clients/completions.json +0 -1151
  403. package/tests/manual/clients/completions.test.ts +0 -198
  404. package/tests/manual/file-edits/figma.test.ts +0 -3
  405. package/tests/manual/file-edits/fileblocks/readwrite.test.ts +0 -100
  406. package/tests/manual/file-edits/patching/input.txt +0 -145
  407. package/tests/manual/file-edits/patching/output.txt +0 -145
  408. package/tests/manual/file-edits/patching/patch.txt +0 -15
  409. package/tests/manual/file-edits/patching/unseen.txt +0 -80
  410. package/tests/manual/file-edits/patching.test.ts +0 -139
  411. package/tests/manual/modalities/README.md +0 -157
  412. package/tests/manual/modalities/google.modalities.test.ts +0 -335
  413. package/tests/manual/modalities/openai.modalities.test.ts +0 -329
  414. package/tests/manual/modalities/streaming.test.ts +0 -260
  415. package/tests/manual/modalities/xai.modalities.test.ts +0 -294
  416. package/tests/manual/test-concurrent-ask.ts +0 -43
  417. package/tests/manual/ycmd/debug_diagnostics_test.ts +0 -127
  418. package/tests/manual/ycmd/fixtures/debug_diagnostics.ts +0 -26
  419. package/tests/manual/ycmd/fixtures/file_change_test.ts +0 -17
  420. package/tests/manual/ycmd/minimal_advanced_test.ts +0 -108
  421. package/tests/manual/ycmd/simple_diagnostics_test.ts +0 -61
  422. package/tests/manual/ycmd/simple_test.ts +0 -74
  423. package/tests/manual/ycmd/test-typescript-sample.ts +0 -34
  424. package/tests/manual/ycmd/test_advanced_features.ts +0 -407
  425. package/tests/manual/ycmd/test_advanced_with_tools.ts +0 -320
  426. package/tests/manual/ycmd/test_comprehensive_typescript.ts +0 -179
  427. package/tests/manual/ycmd/test_diagnostics_file_changes.ts +0 -249
  428. package/tests/manual/ycmd/test_diagnostics_fix.ts +0 -99
  429. package/tests/manual/ycmd/test_diagnostics_simple.ts +0 -100
  430. package/tests/manual/ycmd/test_diagnostics_timing.ts +0 -120
  431. package/tests/manual/ycmd/test_discover_commands.ts +0 -310
  432. package/tests/manual/ycmd/test_endpoints.ts +0 -115
  433. package/tests/manual/ycmd/test_final_comprehensive.ts +0 -218
  434. package/tests/manual/ycmd/test_final_validation.ts +0 -150
  435. package/tests/manual/ycmd/test_implementation.js +0 -42
  436. package/tests/manual/ycmd/test_individual_ycmd_tool.ts +0 -39
  437. package/tests/manual/ycmd/test_server_manager.ts +0 -52
  438. package/tests/manual/ycmd/test_simple_debug.ts +0 -86
  439. package/tests/manual/ycmd/test_tsserver_workflow.js +0 -83
  440. package/tests/manual/ycmd/test_tsserver_workflow.ts +0 -122
  441. package/tests/manual/ycmd/test_typescript_simple.ts +0 -48
  442. package/tests/manual/ycmd/test_typescript_ycmd.ts +0 -105
  443. package/tests/manual/ycmd/test_workspace_config.ts +0 -90
  444. package/tests/manual/ycmd/test_ycmd_auto_start.ts +0 -137
  445. package/tests/manual/ycmd/test_ycmd_comprehensive.ts +0 -73
  446. package/tests/manual/ycmd/test_ycmd_connection.py +0 -10
  447. package/tests/manual/ycmd/test_ycmd_direct.ts +0 -142
  448. package/tests/manual/ycmd/test_ycmd_experiment.ts +0 -48
  449. package/tests/manual/ycmd/test_ycmd_final.ts +0 -200
  450. package/tests/manual/ycmd/test_ycmd_fixed.py +0 -18
  451. package/tests/manual/ycmd/test_ycmd_integration.ts +0 -112
  452. package/tests/manual/ycmd/test_ycmd_simple.ts +0 -45
  453. package/tests/manual/ycmd/test_ycmd_usage.py +0 -27
  454. package/tests/manual/ycmd/working_simple_test.ts +0 -134
  455. package/tests/patching/corrupted.test.ts +0 -78
  456. package/tests/patching/fixtures/transcript-mangles/agent-sync-fs-nested-catch.json +0 -9
  457. package/tests/patching/fixtures/transcript-mangles/automation-functions-crossed.json +0 -9
  458. package/tests/patching/fixtures/transcript-mangles/fruit-ninja-confirmed-retirement.json +0 -8
  459. package/tests/patching/imports.patch.txt +0 -11
  460. package/tests/patching/imports.test.ts +0 -43
  461. package/tests/patching/imports.txt +0 -11
  462. package/tests/patching/interface.patch.txt +0 -15
  463. package/tests/patching/interface.txt +0 -7
  464. package/tests/patching/patchFileOutput.test.ts +0 -328
  465. package/tests/patching/regression-2026.test.ts +0 -752
  466. package/tests/patching/transcriptMangleRegression.test.ts +0 -125
  467. package/tests/plugins/language/languagePlugin-content-triggers.test.ts +0 -346
  468. package/tests/plugins/language/languagePlugin-integration.test.ts +0 -471
  469. package/tests/plugins/language/languagePlugin.test.ts +0 -385
  470. package/tests/processes/managedProcessShim.test.ts +0 -59
  471. package/tests/processors/Base64ImageDetector.test.ts +0 -979
  472. package/tests/processors/CustomVariables.test.ts +0 -981
  473. package/tests/processors/CustomVariablesBenchmark.test.ts +0 -237
  474. package/tests/processors/HarmonyToolProcessor.test.ts +0 -490
  475. package/tests/processors/TokenCompressor.test.ts +0 -674
  476. package/tests/processors/ToolResponseCache.test.ts +0 -864
  477. package/tests/processors/tools/boundedRetrievalTools.test.ts +0 -68
  478. package/tests/processors/tools/grepToolResponse.test.ts +0 -159
  479. package/tests/services/ConversionService.test.ts +0 -154
  480. package/tests/services/DockerService.test.ts +0 -24
  481. package/tests/services/Tools.test.ts +0 -1738
  482. package/tests/services/ToolsService.setFunction.test.ts +0 -68
  483. package/tests/services/WorkerReloadConfig.test.ts +0 -141
  484. package/tests/test.spec.ts +0 -163
  485. package/tests/unit/InputQueueManager.test.ts +0 -174
  486. package/tests/unit/McpWebsocketTransport.test.ts +0 -56
  487. package/tests/unit/agents/historyRollback.test.ts +0 -53
  488. package/tests/unit/agents/tools/loadImageAsBase64.test.ts +0 -44
  489. package/tests/unit/auth/jwtStore.test.ts +0 -55
  490. package/tests/unit/auth/keyAuth.test.ts +0 -152
  491. package/tests/unit/auth/keyManager.test.ts +0 -130
  492. package/tests/unit/auth/registerIdentity.test.ts +0 -99
  493. package/tests/unit/chat/ToolCommandModule.test.ts +0 -71
  494. package/tests/unit/chat/historyCommandArgs.test.ts +0 -37
  495. package/tests/unit/clients/AIClient.test.ts +0 -454
  496. package/tests/unit/clients/anthropic.responseMetadata.test.ts +0 -81
  497. package/tests/unit/clients/attribution.test.ts +0 -185
  498. package/tests/unit/clients/http.responseMetadata.test.ts +0 -86
  499. package/tests/unit/clients/openai.responseMetadata.test.ts +0 -90
  500. package/tests/unit/clients/responseMetadata.test.ts +0 -123
  501. package/tests/unit/clients/withRetry.test.ts +0 -319
  502. package/tests/unit/commands/agents.test.ts +0 -111
  503. package/tests/unit/commands/github-credentials.test.ts +0 -210
  504. package/tests/unit/commands/misc.test.ts +0 -85
  505. package/tests/unit/commands/remote.test.ts +0 -79
  506. package/tests/unit/commands/sandbox.test.ts +0 -350
  507. package/tests/unit/hashes.test.ts +0 -23
  508. package/tests/unit/input-queue.test.ts +0 -80
  509. package/tests/unit/login.test.ts +0 -218
  510. package/tests/unit/modules/moduleLoading.test.ts +0 -305
  511. package/tests/unit/plugins/pluginLoading.test.ts +0 -97
  512. package/tests/unit/services/AgentSyncKnowhowWeb.test.ts +0 -38
  513. package/tests/unit/services/KnowhowClient.test.ts +0 -84
  514. package/tests/unit/services/LazyToolsService.test.ts +0 -53
  515. package/tests/unit/services/Mcp.test.ts +0 -56
  516. package/tests/unit/services/MinimalToolsService.test.ts +0 -424
  517. package/tests/unit/services/RuntimeReloadService.test.ts +0 -29
  518. package/tests/unit/services/SessionManager.test.ts +0 -43
  519. package/tests/unit/services/SyncedAgentWatcher.test.ts +0 -89
  520. package/tests/unit/services/SyncerService.test.ts +0 -45
  521. package/tests/unit/tunnel.test.ts +0 -51
  522. package/tests/unit/util/Trace.test.ts +0 -119
  523. package/tests/unit/utils/http.test.ts +0 -43
  524. package/ts_build/tests/XmlToolCallProcessor.test.d.ts +0 -1
  525. package/ts_build/tests/XmlToolCallProcessor.test.js +0 -376
  526. package/ts_build/tests/XmlToolCallProcessor.test.js.map +0 -1
  527. package/ts_build/tests/agents/interrupt.test.d.ts +0 -14
  528. package/ts_build/tests/agents/interrupt.test.js +0 -136
  529. package/ts_build/tests/agents/interrupt.test.js.map +0 -1
  530. package/ts_build/tests/agents/observe-base.test.d.ts +0 -1
  531. package/ts_build/tests/agents/observe-base.test.js +0 -149
  532. package/ts_build/tests/agents/observe-base.test.js.map +0 -1
  533. package/ts_build/tests/agents/tools/connectAgent.test.d.ts +0 -1
  534. package/ts_build/tests/agents/tools/connectAgent.test.js +0 -142
  535. package/ts_build/tests/agents/tools/connectAgent.test.js.map +0 -1
  536. package/ts_build/tests/agents/tools/observe.test.d.ts +0 -1
  537. package/ts_build/tests/agents/tools/observe.test.js +0 -148
  538. package/ts_build/tests/agents/tools/observe.test.js.map +0 -1
  539. package/ts_build/tests/agents/tools/readFile.test.d.ts +0 -1
  540. package/ts_build/tests/agents/tools/readFile.test.js +0 -90
  541. package/ts_build/tests/agents/tools/readFile.test.js.map +0 -1
  542. package/ts_build/tests/agents/tools/replyToParent.test.d.ts +0 -1
  543. package/ts_build/tests/agents/tools/replyToParent.test.js +0 -116
  544. package/ts_build/tests/agents/tools/replyToParent.test.js.map +0 -1
  545. package/ts_build/tests/agents/tools/sendAgentMessage.test.d.ts +0 -1
  546. package/ts_build/tests/agents/tools/sendAgentMessage.test.js +0 -112
  547. package/ts_build/tests/agents/tools/sendAgentMessage.test.js.map +0 -1
  548. package/ts_build/tests/agents/tools/waitForAgentCompleted.test.d.ts +0 -1
  549. package/ts_build/tests/agents/tools/waitForAgentCompleted.test.js +0 -147
  550. package/ts_build/tests/agents/tools/waitForAgentCompleted.test.js.map +0 -1
  551. package/ts_build/tests/chat/detach-attach-rendering.test.d.ts +0 -1
  552. package/ts_build/tests/chat/detach-attach-rendering.test.js +0 -168
  553. package/ts_build/tests/chat/detach-attach-rendering.test.js.map +0 -1
  554. package/ts_build/tests/clients/AIClient.test.d.ts +0 -1
  555. package/ts_build/tests/clients/AIClient.test.js +0 -483
  556. package/ts_build/tests/clients/AIClient.test.js.map +0 -1
  557. package/ts_build/tests/clients/anthropic.test.d.ts +0 -1
  558. package/ts_build/tests/clients/anthropic.test.js +0 -159
  559. package/ts_build/tests/clients/anthropic.test.js.map +0 -1
  560. package/ts_build/tests/clients/contextLimits.test.d.ts +0 -1
  561. package/ts_build/tests/clients/contextLimits.test.js +0 -69
  562. package/ts_build/tests/clients/contextLimits.test.js.map +0 -1
  563. package/ts_build/tests/clients/fireworks.test.d.ts +0 -1
  564. package/ts_build/tests/clients/fireworks.test.js +0 -65
  565. package/ts_build/tests/clients/fireworks.test.js.map +0 -1
  566. package/ts_build/tests/clients/openai.images.test.d.ts +0 -1
  567. package/ts_build/tests/clients/openai.images.test.js +0 -94
  568. package/ts_build/tests/clients/openai.images.test.js.map +0 -1
  569. package/ts_build/tests/clients/pricing.test.d.ts +0 -1
  570. package/ts_build/tests/clients/pricing.test.js +0 -124
  571. package/ts_build/tests/clients/pricing.test.js.map +0 -1
  572. package/ts_build/tests/clients/reasoningEffort.test.d.ts +0 -1
  573. package/ts_build/tests/clients/reasoningEffort.test.js +0 -116
  574. package/ts_build/tests/clients/reasoningEffort.test.js.map +0 -1
  575. package/ts_build/tests/compressor/bigstring.test.d.ts +0 -1
  576. package/ts_build/tests/compressor/bigstring.test.js +0 -275
  577. package/ts_build/tests/compressor/bigstring.test.js.map +0 -1
  578. package/ts_build/tests/compressor/toolResponseCache.test.d.ts +0 -1
  579. package/ts_build/tests/compressor/toolResponseCache.test.js +0 -250
  580. package/ts_build/tests/compressor/toolResponseCache.test.js.map +0 -1
  581. package/ts_build/tests/compressor/usageBase64.test.d.ts +0 -1
  582. package/ts_build/tests/compressor/usageBase64.test.js +0 -109
  583. package/ts_build/tests/compressor/usageBase64.test.js.map +0 -1
  584. package/ts_build/tests/manual/agent-events/run-test.d.ts +0 -2
  585. package/ts_build/tests/manual/agent-events/run-test.js +0 -148
  586. package/ts_build/tests/manual/agent-events/run-test.js.map +0 -1
  587. package/ts_build/tests/manual/browser-login/test_browser_login_basic.d.ts +0 -2
  588. package/ts_build/tests/manual/browser-login/test_browser_login_basic.js +0 -118
  589. package/ts_build/tests/manual/browser-login/test_browser_login_basic.js.map +0 -1
  590. package/ts_build/tests/manual/browser-login/test_cli_integration.d.ts +0 -2
  591. package/ts_build/tests/manual/browser-login/test_cli_integration.js +0 -163
  592. package/ts_build/tests/manual/browser-login/test_cli_integration.js.map +0 -1
  593. package/ts_build/tests/manual/browser-login/test_cross_platform_browser.d.ts +0 -2
  594. package/ts_build/tests/manual/browser-login/test_cross_platform_browser.js +0 -169
  595. package/ts_build/tests/manual/browser-login/test_cross_platform_browser.js.map +0 -1
  596. package/ts_build/tests/manual/browser-login/test_error_scenarios.d.ts +0 -2
  597. package/ts_build/tests/manual/browser-login/test_error_scenarios.js +0 -207
  598. package/ts_build/tests/manual/browser-login/test_error_scenarios.js.map +0 -1
  599. package/ts_build/tests/manual/clients/completions.test.d.ts +0 -1
  600. package/ts_build/tests/manual/clients/completions.test.js +0 -151
  601. package/ts_build/tests/manual/clients/completions.test.js.map +0 -1
  602. package/ts_build/tests/manual/file-edits/figma.test.d.ts +0 -0
  603. package/ts_build/tests/manual/file-edits/figma.test.js +0 -2
  604. package/ts_build/tests/manual/file-edits/figma.test.js.map +0 -1
  605. package/ts_build/tests/manual/file-edits/fileblocks/readwrite.test.d.ts +0 -1
  606. package/ts_build/tests/manual/file-edits/fileblocks/readwrite.test.js +0 -110
  607. package/ts_build/tests/manual/file-edits/fileblocks/readwrite.test.js.map +0 -1
  608. package/ts_build/tests/manual/file-edits/patching.test.d.ts +0 -1
  609. package/ts_build/tests/manual/file-edits/patching.test.js +0 -129
  610. package/ts_build/tests/manual/file-edits/patching.test.js.map +0 -1
  611. package/ts_build/tests/manual/modalities/google.modalities.test.d.ts +0 -1
  612. package/ts_build/tests/manual/modalities/google.modalities.test.js +0 -262
  613. package/ts_build/tests/manual/modalities/google.modalities.test.js.map +0 -1
  614. package/ts_build/tests/manual/modalities/openai.modalities.test.d.ts +0 -1
  615. package/ts_build/tests/manual/modalities/openai.modalities.test.js +0 -262
  616. package/ts_build/tests/manual/modalities/openai.modalities.test.js.map +0 -1
  617. package/ts_build/tests/manual/modalities/streaming.test.d.ts +0 -1
  618. package/ts_build/tests/manual/modalities/streaming.test.js +0 -216
  619. package/ts_build/tests/manual/modalities/streaming.test.js.map +0 -1
  620. package/ts_build/tests/manual/modalities/xai.modalities.test.d.ts +0 -1
  621. package/ts_build/tests/manual/modalities/xai.modalities.test.js +0 -219
  622. package/ts_build/tests/manual/modalities/xai.modalities.test.js.map +0 -1
  623. package/ts_build/tests/manual/test-concurrent-ask.d.ts +0 -1
  624. package/ts_build/tests/manual/test-concurrent-ask.js +0 -22
  625. package/ts_build/tests/manual/test-concurrent-ask.js.map +0 -1
  626. package/ts_build/tests/manual/ycmd/debug_diagnostics_test.d.ts +0 -1
  627. package/ts_build/tests/manual/ycmd/debug_diagnostics_test.js +0 -124
  628. package/ts_build/tests/manual/ycmd/debug_diagnostics_test.js.map +0 -1
  629. package/ts_build/tests/manual/ycmd/minimal_advanced_test.d.ts +0 -2
  630. package/ts_build/tests/manual/ycmd/minimal_advanced_test.js +0 -114
  631. package/ts_build/tests/manual/ycmd/minimal_advanced_test.js.map +0 -1
  632. package/ts_build/tests/manual/ycmd/simple_diagnostics_test.d.ts +0 -1
  633. package/ts_build/tests/manual/ycmd/simple_diagnostics_test.js +0 -84
  634. package/ts_build/tests/manual/ycmd/simple_diagnostics_test.js.map +0 -1
  635. package/ts_build/tests/manual/ycmd/simple_test.d.ts +0 -2
  636. package/ts_build/tests/manual/ycmd/simple_test.js +0 -92
  637. package/ts_build/tests/manual/ycmd/simple_test.js.map +0 -1
  638. package/ts_build/tests/manual/ycmd/test-typescript-sample.d.ts +0 -14
  639. package/ts_build/tests/manual/ycmd/test-typescript-sample.js +0 -20
  640. package/ts_build/tests/manual/ycmd/test-typescript-sample.js.map +0 -1
  641. package/ts_build/tests/manual/ycmd/test_advanced_features.d.ts +0 -2
  642. package/ts_build/tests/manual/ycmd/test_advanced_features.js +0 -306
  643. package/ts_build/tests/manual/ycmd/test_advanced_features.js.map +0 -1
  644. package/ts_build/tests/manual/ycmd/test_advanced_with_tools.d.ts +0 -3
  645. package/ts_build/tests/manual/ycmd/test_advanced_with_tools.js +0 -271
  646. package/ts_build/tests/manual/ycmd/test_advanced_with_tools.js.map +0 -1
  647. package/ts_build/tests/manual/ycmd/test_comprehensive_typescript.d.ts +0 -2
  648. package/ts_build/tests/manual/ycmd/test_comprehensive_typescript.js +0 -196
  649. package/ts_build/tests/manual/ycmd/test_comprehensive_typescript.js.map +0 -1
  650. package/ts_build/tests/manual/ycmd/test_diagnostics_file_changes.d.ts +0 -1
  651. package/ts_build/tests/manual/ycmd/test_diagnostics_file_changes.js +0 -184
  652. package/ts_build/tests/manual/ycmd/test_diagnostics_file_changes.js.map +0 -1
  653. package/ts_build/tests/manual/ycmd/test_diagnostics_fix.d.ts +0 -2
  654. package/ts_build/tests/manual/ycmd/test_diagnostics_fix.js +0 -116
  655. package/ts_build/tests/manual/ycmd/test_diagnostics_fix.js.map +0 -1
  656. package/ts_build/tests/manual/ycmd/test_diagnostics_simple.d.ts +0 -1
  657. package/ts_build/tests/manual/ycmd/test_diagnostics_simple.js +0 -114
  658. package/ts_build/tests/manual/ycmd/test_diagnostics_simple.js.map +0 -1
  659. package/ts_build/tests/manual/ycmd/test_diagnostics_timing.d.ts +0 -1
  660. package/ts_build/tests/manual/ycmd/test_diagnostics_timing.js +0 -129
  661. package/ts_build/tests/manual/ycmd/test_diagnostics_timing.js.map +0 -1
  662. package/ts_build/tests/manual/ycmd/test_discover_commands.d.ts +0 -2
  663. package/ts_build/tests/manual/ycmd/test_discover_commands.js +0 -252
  664. package/ts_build/tests/manual/ycmd/test_discover_commands.js.map +0 -1
  665. package/ts_build/tests/manual/ycmd/test_endpoints.d.ts +0 -2
  666. package/ts_build/tests/manual/ycmd/test_endpoints.js +0 -130
  667. package/ts_build/tests/manual/ycmd/test_endpoints.js.map +0 -1
  668. package/ts_build/tests/manual/ycmd/test_final_comprehensive.d.ts +0 -2
  669. package/ts_build/tests/manual/ycmd/test_final_comprehensive.js +0 -231
  670. package/ts_build/tests/manual/ycmd/test_final_comprehensive.js.map +0 -1
  671. package/ts_build/tests/manual/ycmd/test_final_validation.d.ts +0 -2
  672. package/ts_build/tests/manual/ycmd/test_final_validation.js +0 -170
  673. package/ts_build/tests/manual/ycmd/test_final_validation.js.map +0 -1
  674. package/ts_build/tests/manual/ycmd/test_individual_ycmd_tool.d.ts +0 -2
  675. package/ts_build/tests/manual/ycmd/test_individual_ycmd_tool.js +0 -37
  676. package/ts_build/tests/manual/ycmd/test_individual_ycmd_tool.js.map +0 -1
  677. package/ts_build/tests/manual/ycmd/test_server_manager.d.ts +0 -1
  678. package/ts_build/tests/manual/ycmd/test_server_manager.js +0 -38
  679. package/ts_build/tests/manual/ycmd/test_server_manager.js.map +0 -1
  680. package/ts_build/tests/manual/ycmd/test_simple_debug.d.ts +0 -2
  681. package/ts_build/tests/manual/ycmd/test_simple_debug.js +0 -109
  682. package/ts_build/tests/manual/ycmd/test_simple_debug.js.map +0 -1
  683. package/ts_build/tests/manual/ycmd/test_tsserver_workflow.d.ts +0 -1
  684. package/ts_build/tests/manual/ycmd/test_tsserver_workflow.js +0 -138
  685. package/ts_build/tests/manual/ycmd/test_tsserver_workflow.js.map +0 -1
  686. package/ts_build/tests/manual/ycmd/test_typescript_simple.d.ts +0 -1
  687. package/ts_build/tests/manual/ycmd/test_typescript_simple.js +0 -76
  688. package/ts_build/tests/manual/ycmd/test_typescript_simple.js.map +0 -1
  689. package/ts_build/tests/manual/ycmd/test_typescript_ycmd.d.ts +0 -1
  690. package/ts_build/tests/manual/ycmd/test_typescript_ycmd.js +0 -115
  691. package/ts_build/tests/manual/ycmd/test_typescript_ycmd.js.map +0 -1
  692. package/ts_build/tests/manual/ycmd/test_workspace_config.d.ts +0 -1
  693. package/ts_build/tests/manual/ycmd/test_workspace_config.js +0 -99
  694. package/ts_build/tests/manual/ycmd/test_workspace_config.js.map +0 -1
  695. package/ts_build/tests/manual/ycmd/test_ycmd_auto_start.d.ts +0 -2
  696. package/ts_build/tests/manual/ycmd/test_ycmd_auto_start.js +0 -140
  697. package/ts_build/tests/manual/ycmd/test_ycmd_auto_start.js.map +0 -1
  698. package/ts_build/tests/manual/ycmd/test_ycmd_comprehensive.d.ts +0 -1
  699. package/ts_build/tests/manual/ycmd/test_ycmd_comprehensive.js +0 -93
  700. package/ts_build/tests/manual/ycmd/test_ycmd_comprehensive.js.map +0 -1
  701. package/ts_build/tests/manual/ycmd/test_ycmd_direct.d.ts +0 -2
  702. package/ts_build/tests/manual/ycmd/test_ycmd_direct.js +0 -159
  703. package/ts_build/tests/manual/ycmd/test_ycmd_direct.js.map +0 -1
  704. package/ts_build/tests/manual/ycmd/test_ycmd_experiment.d.ts +0 -15
  705. package/ts_build/tests/manual/ycmd/test_ycmd_experiment.js +0 -68
  706. package/ts_build/tests/manual/ycmd/test_ycmd_experiment.js.map +0 -1
  707. package/ts_build/tests/manual/ycmd/test_ycmd_final.d.ts +0 -2
  708. package/ts_build/tests/manual/ycmd/test_ycmd_final.js +0 -205
  709. package/ts_build/tests/manual/ycmd/test_ycmd_final.js.map +0 -1
  710. package/ts_build/tests/manual/ycmd/test_ycmd_integration.d.ts +0 -3
  711. package/ts_build/tests/manual/ycmd/test_ycmd_integration.js +0 -119
  712. package/ts_build/tests/manual/ycmd/test_ycmd_integration.js.map +0 -1
  713. package/ts_build/tests/manual/ycmd/test_ycmd_simple.d.ts +0 -2
  714. package/ts_build/tests/manual/ycmd/test_ycmd_simple.js +0 -36
  715. package/ts_build/tests/manual/ycmd/test_ycmd_simple.js.map +0 -1
  716. package/ts_build/tests/manual/ycmd/working_simple_test.d.ts +0 -2
  717. package/ts_build/tests/manual/ycmd/working_simple_test.js +0 -144
  718. package/ts_build/tests/manual/ycmd/working_simple_test.js.map +0 -1
  719. package/ts_build/tests/patching/corrupted.test.d.ts +0 -1
  720. package/ts_build/tests/patching/corrupted.test.js +0 -53
  721. package/ts_build/tests/patching/corrupted.test.js.map +0 -1
  722. package/ts_build/tests/patching/imports.test.d.ts +0 -1
  723. package/ts_build/tests/patching/imports.test.js +0 -71
  724. package/ts_build/tests/patching/imports.test.js.map +0 -1
  725. package/ts_build/tests/patching/patchFileOutput.test.d.ts +0 -1
  726. package/ts_build/tests/patching/patchFileOutput.test.js +0 -269
  727. package/ts_build/tests/patching/patchFileOutput.test.js.map +0 -1
  728. package/ts_build/tests/patching/regression-2026.test.d.ts +0 -1
  729. package/ts_build/tests/patching/regression-2026.test.js +0 -528
  730. package/ts_build/tests/patching/regression-2026.test.js.map +0 -1
  731. package/ts_build/tests/patching/transcriptMangleRegression.test.d.ts +0 -1
  732. package/ts_build/tests/patching/transcriptMangleRegression.test.js +0 -104
  733. package/ts_build/tests/patching/transcriptMangleRegression.test.js.map +0 -1
  734. package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.d.ts +0 -1
  735. package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js +0 -294
  736. package/ts_build/tests/plugins/language/languagePlugin-content-triggers.test.js.map +0 -1
  737. package/ts_build/tests/plugins/language/languagePlugin-integration.test.d.ts +0 -1
  738. package/ts_build/tests/plugins/language/languagePlugin-integration.test.js +0 -343
  739. package/ts_build/tests/plugins/language/languagePlugin-integration.test.js.map +0 -1
  740. package/ts_build/tests/plugins/language/languagePlugin.test.d.ts +0 -1
  741. package/ts_build/tests/plugins/language/languagePlugin.test.js +0 -315
  742. package/ts_build/tests/plugins/language/languagePlugin.test.js.map +0 -1
  743. package/ts_build/tests/processes/managedProcessShim.test.d.ts +0 -1
  744. package/ts_build/tests/processes/managedProcessShim.test.js +0 -92
  745. package/ts_build/tests/processes/managedProcessShim.test.js.map +0 -1
  746. package/ts_build/tests/processors/Base64ImageDetector.test.d.ts +0 -1
  747. package/ts_build/tests/processors/Base64ImageDetector.test.js +0 -792
  748. package/ts_build/tests/processors/Base64ImageDetector.test.js.map +0 -1
  749. package/ts_build/tests/processors/CustomVariables.test.d.ts +0 -1
  750. package/ts_build/tests/processors/CustomVariables.test.js +0 -764
  751. package/ts_build/tests/processors/CustomVariables.test.js.map +0 -1
  752. package/ts_build/tests/processors/CustomVariablesBenchmark.test.d.ts +0 -1
  753. package/ts_build/tests/processors/CustomVariablesBenchmark.test.js +0 -179
  754. package/ts_build/tests/processors/CustomVariablesBenchmark.test.js.map +0 -1
  755. package/ts_build/tests/processors/HarmonyToolProcessor.test.d.ts +0 -1
  756. package/ts_build/tests/processors/HarmonyToolProcessor.test.js +0 -382
  757. package/ts_build/tests/processors/HarmonyToolProcessor.test.js.map +0 -1
  758. package/ts_build/tests/processors/TokenCompressor.test.d.ts +0 -1
  759. package/ts_build/tests/processors/TokenCompressor.test.js +0 -473
  760. package/ts_build/tests/processors/TokenCompressor.test.js.map +0 -1
  761. package/ts_build/tests/processors/ToolResponseCache.test.d.ts +0 -1
  762. package/ts_build/tests/processors/ToolResponseCache.test.js +0 -657
  763. package/ts_build/tests/processors/ToolResponseCache.test.js.map +0 -1
  764. package/ts_build/tests/processors/tools/boundedRetrievalTools.test.d.ts +0 -1
  765. package/ts_build/tests/processors/tools/boundedRetrievalTools.test.js +0 -57
  766. package/ts_build/tests/processors/tools/boundedRetrievalTools.test.js.map +0 -1
  767. package/ts_build/tests/processors/tools/grepToolResponse.test.d.ts +0 -1
  768. package/ts_build/tests/processors/tools/grepToolResponse.test.js +0 -77
  769. package/ts_build/tests/processors/tools/grepToolResponse.test.js.map +0 -1
  770. package/ts_build/tests/services/ConversionService.test.d.ts +0 -1
  771. package/ts_build/tests/services/ConversionService.test.js +0 -154
  772. package/ts_build/tests/services/ConversionService.test.js.map +0 -1
  773. package/ts_build/tests/services/DockerService.test.d.ts +0 -1
  774. package/ts_build/tests/services/DockerService.test.js +0 -22
  775. package/ts_build/tests/services/DockerService.test.js.map +0 -1
  776. package/ts_build/tests/services/Tools.test.d.ts +0 -1
  777. package/ts_build/tests/services/Tools.test.js +0 -1365
  778. package/ts_build/tests/services/Tools.test.js.map +0 -1
  779. package/ts_build/tests/services/ToolsService.setFunction.test.d.ts +0 -1
  780. package/ts_build/tests/services/ToolsService.setFunction.test.js +0 -51
  781. package/ts_build/tests/services/ToolsService.setFunction.test.js.map +0 -1
  782. package/ts_build/tests/services/WorkerReloadConfig.test.d.ts +0 -1
  783. package/ts_build/tests/services/WorkerReloadConfig.test.js +0 -86
  784. package/ts_build/tests/services/WorkerReloadConfig.test.js.map +0 -1
  785. package/ts_build/tests/test.spec.d.ts +0 -1
  786. package/ts_build/tests/test.spec.js +0 -139
  787. package/ts_build/tests/test.spec.js.map +0 -1
  788. package/ts_build/tests/unit/InputQueueManager.test.d.ts +0 -1
  789. package/ts_build/tests/unit/InputQueueManager.test.js +0 -104
  790. package/ts_build/tests/unit/InputQueueManager.test.js.map +0 -1
  791. package/ts_build/tests/unit/McpWebsocketTransport.test.d.ts +0 -1
  792. package/ts_build/tests/unit/McpWebsocketTransport.test.js +0 -47
  793. package/ts_build/tests/unit/McpWebsocketTransport.test.js.map +0 -1
  794. package/ts_build/tests/unit/agents/historyRollback.test.d.ts +0 -1
  795. package/ts_build/tests/unit/agents/historyRollback.test.js +0 -42
  796. package/ts_build/tests/unit/agents/historyRollback.test.js.map +0 -1
  797. package/ts_build/tests/unit/agents/tools/loadImageAsBase64.test.d.ts +0 -1
  798. package/ts_build/tests/unit/agents/tools/loadImageAsBase64.test.js +0 -67
  799. package/ts_build/tests/unit/agents/tools/loadImageAsBase64.test.js.map +0 -1
  800. package/ts_build/tests/unit/auth/jwtStore.test.d.ts +0 -1
  801. package/ts_build/tests/unit/auth/jwtStore.test.js +0 -46
  802. package/ts_build/tests/unit/auth/jwtStore.test.js.map +0 -1
  803. package/ts_build/tests/unit/auth/keyAuth.test.d.ts +0 -1
  804. package/ts_build/tests/unit/auth/keyAuth.test.js +0 -118
  805. package/ts_build/tests/unit/auth/keyAuth.test.js.map +0 -1
  806. package/ts_build/tests/unit/auth/keyManager.test.d.ts +0 -1
  807. package/ts_build/tests/unit/auth/keyManager.test.js +0 -96
  808. package/ts_build/tests/unit/auth/keyManager.test.js.map +0 -1
  809. package/ts_build/tests/unit/auth/registerIdentity.test.d.ts +0 -1
  810. package/ts_build/tests/unit/auth/registerIdentity.test.js +0 -92
  811. package/ts_build/tests/unit/auth/registerIdentity.test.js.map +0 -1
  812. package/ts_build/tests/unit/chat/ToolCommandModule.test.d.ts +0 -1
  813. package/ts_build/tests/unit/chat/ToolCommandModule.test.js +0 -61
  814. package/ts_build/tests/unit/chat/ToolCommandModule.test.js.map +0 -1
  815. package/ts_build/tests/unit/chat/historyCommandArgs.test.d.ts +0 -1
  816. package/ts_build/tests/unit/chat/historyCommandArgs.test.js +0 -29
  817. package/ts_build/tests/unit/chat/historyCommandArgs.test.js.map +0 -1
  818. package/ts_build/tests/unit/clients/AIClient.test.d.ts +0 -1
  819. package/ts_build/tests/unit/clients/AIClient.test.js +0 -342
  820. package/ts_build/tests/unit/clients/AIClient.test.js.map +0 -1
  821. package/ts_build/tests/unit/clients/anthropic.responseMetadata.test.d.ts +0 -1
  822. package/ts_build/tests/unit/clients/anthropic.responseMetadata.test.js +0 -77
  823. package/ts_build/tests/unit/clients/anthropic.responseMetadata.test.js.map +0 -1
  824. package/ts_build/tests/unit/clients/attribution.test.d.ts +0 -1
  825. package/ts_build/tests/unit/clients/attribution.test.js +0 -153
  826. package/ts_build/tests/unit/clients/attribution.test.js.map +0 -1
  827. package/ts_build/tests/unit/clients/http.responseMetadata.test.d.ts +0 -1
  828. package/ts_build/tests/unit/clients/http.responseMetadata.test.js +0 -77
  829. package/ts_build/tests/unit/clients/http.responseMetadata.test.js.map +0 -1
  830. package/ts_build/tests/unit/clients/openai.responseMetadata.test.d.ts +0 -1
  831. package/ts_build/tests/unit/clients/openai.responseMetadata.test.js +0 -86
  832. package/ts_build/tests/unit/clients/openai.responseMetadata.test.js.map +0 -1
  833. package/ts_build/tests/unit/clients/responseMetadata.test.d.ts +0 -1
  834. package/ts_build/tests/unit/clients/responseMetadata.test.js +0 -96
  835. package/ts_build/tests/unit/clients/responseMetadata.test.js.map +0 -1
  836. package/ts_build/tests/unit/clients/withRetry.test.d.ts +0 -1
  837. package/ts_build/tests/unit/clients/withRetry.test.js +0 -225
  838. package/ts_build/tests/unit/clients/withRetry.test.js.map +0 -1
  839. package/ts_build/tests/unit/commands/agents.test.d.ts +0 -1
  840. package/ts_build/tests/unit/commands/agents.test.js +0 -119
  841. package/ts_build/tests/unit/commands/agents.test.js.map +0 -1
  842. package/ts_build/tests/unit/commands/github-credentials.test.d.ts +0 -1
  843. package/ts_build/tests/unit/commands/github-credentials.test.js +0 -145
  844. package/ts_build/tests/unit/commands/github-credentials.test.js.map +0 -1
  845. package/ts_build/tests/unit/commands/misc.test.d.ts +0 -1
  846. package/ts_build/tests/unit/commands/misc.test.js +0 -70
  847. package/ts_build/tests/unit/commands/misc.test.js.map +0 -1
  848. package/ts_build/tests/unit/commands/remote.test.d.ts +0 -1
  849. package/ts_build/tests/unit/commands/remote.test.js +0 -70
  850. package/ts_build/tests/unit/commands/remote.test.js.map +0 -1
  851. package/ts_build/tests/unit/commands/sandbox.test.d.ts +0 -1
  852. package/ts_build/tests/unit/commands/sandbox.test.js +0 -258
  853. package/ts_build/tests/unit/commands/sandbox.test.js.map +0 -1
  854. package/ts_build/tests/unit/hashes.test.d.ts +0 -1
  855. package/ts_build/tests/unit/hashes.test.js +0 -25
  856. package/ts_build/tests/unit/hashes.test.js.map +0 -1
  857. package/ts_build/tests/unit/input-queue.test.d.ts +0 -1
  858. package/ts_build/tests/unit/input-queue.test.js +0 -32
  859. package/ts_build/tests/unit/input-queue.test.js.map +0 -1
  860. package/ts_build/tests/unit/login.test.d.ts +0 -1
  861. package/ts_build/tests/unit/login.test.js +0 -166
  862. package/ts_build/tests/unit/login.test.js.map +0 -1
  863. package/ts_build/tests/unit/modules/moduleLoading.test.d.ts +0 -1
  864. package/ts_build/tests/unit/modules/moduleLoading.test.js +0 -272
  865. package/ts_build/tests/unit/modules/moduleLoading.test.js.map +0 -1
  866. package/ts_build/tests/unit/plugins/pluginLoading.test.d.ts +0 -1
  867. package/ts_build/tests/unit/plugins/pluginLoading.test.js +0 -117
  868. package/ts_build/tests/unit/plugins/pluginLoading.test.js.map +0 -1
  869. package/ts_build/tests/unit/services/AgentSyncKnowhowWeb.test.d.ts +0 -1
  870. package/ts_build/tests/unit/services/AgentSyncKnowhowWeb.test.js +0 -32
  871. package/ts_build/tests/unit/services/AgentSyncKnowhowWeb.test.js.map +0 -1
  872. package/ts_build/tests/unit/services/KnowhowClient.test.d.ts +0 -1
  873. package/ts_build/tests/unit/services/KnowhowClient.test.js +0 -69
  874. package/ts_build/tests/unit/services/KnowhowClient.test.js.map +0 -1
  875. package/ts_build/tests/unit/services/LazyToolsService.test.d.ts +0 -1
  876. package/ts_build/tests/unit/services/LazyToolsService.test.js +0 -47
  877. package/ts_build/tests/unit/services/LazyToolsService.test.js.map +0 -1
  878. package/ts_build/tests/unit/services/Mcp.test.d.ts +0 -1
  879. package/ts_build/tests/unit/services/Mcp.test.js +0 -45
  880. package/ts_build/tests/unit/services/Mcp.test.js.map +0 -1
  881. package/ts_build/tests/unit/services/MinimalToolsService.test.d.ts +0 -1
  882. package/ts_build/tests/unit/services/MinimalToolsService.test.js +0 -320
  883. package/ts_build/tests/unit/services/MinimalToolsService.test.js.map +0 -1
  884. package/ts_build/tests/unit/services/RuntimeReloadService.test.d.ts +0 -1
  885. package/ts_build/tests/unit/services/RuntimeReloadService.test.js +0 -26
  886. package/ts_build/tests/unit/services/RuntimeReloadService.test.js.map +0 -1
  887. package/ts_build/tests/unit/services/SessionManager.test.d.ts +0 -1
  888. package/ts_build/tests/unit/services/SessionManager.test.js +0 -72
  889. package/ts_build/tests/unit/services/SessionManager.test.js.map +0 -1
  890. package/ts_build/tests/unit/services/SyncedAgentWatcher.test.d.ts +0 -1
  891. package/ts_build/tests/unit/services/SyncedAgentWatcher.test.js +0 -78
  892. package/ts_build/tests/unit/services/SyncedAgentWatcher.test.js.map +0 -1
  893. package/ts_build/tests/unit/services/SyncerService.test.d.ts +0 -1
  894. package/ts_build/tests/unit/services/SyncerService.test.js +0 -40
  895. package/ts_build/tests/unit/services/SyncerService.test.js.map +0 -1
  896. package/ts_build/tests/unit/tunnel.test.d.ts +0 -1
  897. package/ts_build/tests/unit/tunnel.test.js +0 -47
  898. package/ts_build/tests/unit/tunnel.test.js.map +0 -1
  899. package/ts_build/tests/unit/util/Trace.test.d.ts +0 -1
  900. package/ts_build/tests/unit/util/Trace.test.js +0 -107
  901. package/ts_build/tests/unit/util/Trace.test.js.map +0 -1
  902. package/ts_build/tests/unit/utils/http.test.d.ts +0 -1
  903. package/ts_build/tests/unit/utils/http.test.js +0 -69
  904. package/ts_build/tests/unit/utils/http.test.js.map +0 -1
  905. package/tsconfig.json +0 -34
  906. 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
- }