minimal-agent 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (573) hide show
  1. package/README.md +11 -3
  2. package/package.json +52 -5
  3. package/plugins/computer_use/.claude-plugin/plugin.json +6 -0
  4. package/plugins/computer_use/README.md +94 -0
  5. package/plugins/computer_use/app/_template.md +142 -0
  6. package/plugins/computer_use/app/chrome.md +165 -0
  7. package/plugins/computer_use/app/finder.md +76 -0
  8. package/plugins/computer_use/app/macos-system-settings.md +81 -0
  9. package/plugins/computer_use/app/microsoft-excel.md +80 -0
  10. package/plugins/computer_use/app/microsoft-powerpoint.md +80 -0
  11. package/plugins/computer_use/app/microsoft-word.md +79 -0
  12. package/plugins/computer_use/app/wechat.md +413 -0
  13. package/plugins/computer_use/app/weread.md +319 -0
  14. package/plugins/computer_use/commands/computeruse.md +25 -0
  15. package/plugins/computer_use/commands/cu.md +9 -0
  16. package/plugins/computer_use/plugin.js +26 -0
  17. package/plugins/computer_use/plugin.ts +30 -0
  18. package/plugins/computer_use/src/capture.js +90 -0
  19. package/plugins/computer_use/src/capture.ts +104 -0
  20. package/plugins/computer_use/src/commands.js +91 -0
  21. package/plugins/computer_use/src/commands.ts +103 -0
  22. package/plugins/computer_use/src/daemon.js +134 -0
  23. package/plugins/computer_use/src/daemon.ts +161 -0
  24. package/plugins/computer_use/src/manuals.js +135 -0
  25. package/plugins/computer_use/src/manuals.ts +159 -0
  26. package/plugins/computer_use/src/verify.js +168 -0
  27. package/plugins/computer_use/src/verify.ts +219 -0
  28. package/plugins/computer_use/test/commands.test.ts +73 -0
  29. package/plugins/cron-runner/plugin.ts +38 -0
  30. package/plugins/cron-runner/src/commands.ts +373 -0
  31. package/plugins/cron-runner/src/cronTime.ts +155 -0
  32. package/plugins/cron-runner/src/lock.ts +79 -0
  33. package/plugins/cron-runner/src/runs.ts +99 -0
  34. package/plugins/cron-runner/src/scheduleEngine.ts +76 -0
  35. package/plugins/cron-runner/src/scheduler.ts +376 -0
  36. package/plugins/cron-runner/src/schema.ts +139 -0
  37. package/plugins/cron-runner/src/service.ts +193 -0
  38. package/plugins/cron-runner/src/store.ts +333 -0
  39. package/plugins/cron-runner/src/types.ts +141 -0
  40. package/plugins/cron-runner/test/cronTime.test.ts +41 -0
  41. package/plugins/cron-runner/test/plugin-integration.test.ts +47 -0
  42. package/plugins/cron-runner/test/scheduleEngine.test.ts +41 -0
  43. package/plugins/cron-runner/test/service.test.ts +76 -0
  44. package/plugins/cron-runner/test/store-and-scheduler.test.ts +501 -0
  45. package/plugins/workflow-runner/plugin.js +56 -2
  46. package/plugins/workflow-runner/plugin.ts +113 -0
  47. package/plugins/workflow-runner/src/agentCommon.js +43 -4
  48. package/plugins/workflow-runner/src/agentCommon.ts +435 -0
  49. package/plugins/workflow-runner/src/controlFlow/branch.js +40 -0
  50. package/plugins/workflow-runner/src/controlFlow/branch.ts +46 -0
  51. package/plugins/workflow-runner/src/controlFlow/loop.js +211 -0
  52. package/plugins/workflow-runner/src/controlFlow/loop.ts +248 -0
  53. package/plugins/workflow-runner/src/controlFlow/pause.js +129 -0
  54. package/plugins/workflow-runner/src/controlFlow/pause.ts +141 -0
  55. package/plugins/workflow-runner/src/controlFlow/signal.js +21 -0
  56. package/plugins/workflow-runner/src/controlFlow/signal.ts +29 -0
  57. package/plugins/workflow-runner/src/controlFlow/types.js +18 -0
  58. package/plugins/workflow-runner/src/controlFlow/types.ts +63 -0
  59. package/plugins/workflow-runner/src/dslManifest.ts +127 -0
  60. package/plugins/workflow-runner/src/expressions.ts +622 -0
  61. package/plugins/workflow-runner/src/index.js +13 -4
  62. package/plugins/workflow-runner/src/index.ts +338 -0
  63. package/plugins/workflow-runner/src/jsonPayload.ts +84 -0
  64. package/plugins/workflow-runner/src/loader.js +23 -0
  65. package/plugins/workflow-runner/src/loader.ts +721 -0
  66. package/plugins/workflow-runner/src/multimodal.js +2 -1
  67. package/plugins/workflow-runner/src/multimodal.ts +64 -0
  68. package/plugins/workflow-runner/src/recovery.ts +149 -0
  69. package/plugins/workflow-runner/src/runner.js +75 -659
  70. package/plugins/workflow-runner/src/runner.ts +604 -0
  71. package/plugins/workflow-runner/src/stepExecutors/agent.ts +234 -0
  72. package/plugins/workflow-runner/src/stepExecutors/assert.ts +50 -0
  73. package/plugins/workflow-runner/src/stepExecutors/echo.js +31 -0
  74. package/plugins/workflow-runner/src/stepExecutors/echo.ts +38 -0
  75. package/plugins/workflow-runner/src/stepExecutors/llm.ts +133 -0
  76. package/plugins/workflow-runner/src/stepExecutors/set.js +49 -0
  77. package/plugins/workflow-runner/src/stepExecutors/set.ts +56 -0
  78. package/plugins/workflow-runner/src/stepExecutors/skill.js +5 -6
  79. package/plugins/workflow-runner/src/stepExecutors/skill.ts +140 -0
  80. package/plugins/workflow-runner/src/stepExecutors/tool.js +80 -8
  81. package/plugins/workflow-runner/src/stepExecutors/tool.ts +256 -0
  82. package/plugins/workflow-runner/src/stepExecutors/verify.ts +68 -0
  83. package/plugins/workflow-runner/src/stepPipeline.js +277 -0
  84. package/plugins/workflow-runner/src/stepPipeline.ts +366 -0
  85. package/plugins/workflow-runner/src/taskIdentity.ts +405 -0
  86. package/plugins/workflow-runner/src/toolRuntime.js +48 -0
  87. package/plugins/workflow-runner/src/toolRuntime.ts +64 -0
  88. package/plugins/workflow-runner/src/types.js +37 -1
  89. package/plugins/workflow-runner/src/types.ts +602 -0
  90. package/plugins/workflow-runner/src/workflowState.ts +733 -0
  91. package/plugins/workflow-runner/test/agent.test.ts +587 -0
  92. package/plugins/workflow-runner/test/agentLlmError.test.ts +373 -0
  93. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +65 -0
  94. package/plugins/workflow-runner/test/captureMisbind.test.ts +99 -0
  95. package/plugins/workflow-runner/test/cli.e2e.test.ts +147 -0
  96. package/plugins/workflow-runner/test/context-files.test.ts +320 -0
  97. package/plugins/workflow-runner/test/e2e.test.ts +370 -0
  98. package/plugins/workflow-runner/test/engineRobustness.test.ts +226 -0
  99. package/plugins/workflow-runner/test/expressions.test.ts +397 -0
  100. package/plugins/workflow-runner/test/foundation.test.ts +126 -0
  101. package/plugins/workflow-runner/test/graceful.test.ts +139 -0
  102. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +47 -0
  103. package/plugins/workflow-runner/test/hostCapability.test.ts +108 -0
  104. package/plugins/workflow-runner/test/illustrate.load.test.ts +183 -0
  105. package/plugins/workflow-runner/test/jsonPayload.test.ts +83 -0
  106. package/plugins/workflow-runner/test/loader.test.ts +617 -0
  107. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +33 -0
  108. package/plugins/workflow-runner/test/multimodal.test.ts +342 -0
  109. package/plugins/workflow-runner/test/output-schema.test.ts +213 -0
  110. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +87 -0
  111. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +269 -0
  112. package/plugins/workflow-runner/test/ppt.load.test.ts +1220 -0
  113. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +220 -0
  114. package/plugins/workflow-runner/test/recovery.test.ts +265 -0
  115. package/plugins/workflow-runner/test/runner.test.ts +911 -0
  116. package/plugins/workflow-runner/test/runnerPreflight.test.ts +379 -0
  117. package/plugins/workflow-runner/test/skillTurnDone.test.ts +71 -0
  118. package/plugins/workflow-runner/test/stateLifecycle.test.ts +150 -0
  119. package/plugins/workflow-runner/test/stepPipeline.test.ts +114 -0
  120. package/plugins/workflow-runner/test/taskArbitration.test.ts +338 -0
  121. package/plugins/workflow-runner/test/taskIdentity.test.ts +237 -0
  122. package/plugins/workflow-runner/test/taskLifecycle.test.ts +270 -0
  123. package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +221 -0
  124. package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +29 -0
  125. package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +168 -0
  126. package/plugins/workflow-runner/test/webppt.load.test.ts +250 -0
  127. package/plugins/workflow-runner/test/word.load.test.ts +208 -0
  128. package/plugins/workflow-runner/test/workflows.smoke.test.ts +76 -0
  129. package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +207 -0
  130. package/skills/browser-automation/SKILL.md +9 -19
  131. package/skills/web-crawler/SKILL.md +9 -11
  132. package/src/askBridge.ts +249 -0
  133. package/src/bootstrap/cwdArg.js +10 -3
  134. package/src/bootstrap/cwdArg.ts +31 -0
  135. package/src/bootstrap/workingDir.ts +48 -0
  136. package/src/cli/args.js +70 -7
  137. package/src/cli/args.ts +146 -0
  138. package/src/cli/computerUse.js +185 -0
  139. package/src/cli/computerUse.ts +221 -0
  140. package/src/cli/configMenu.js +274 -202
  141. package/src/cli/configMenu.tsx +521 -0
  142. package/src/cli/memoryAccess.js +45 -0
  143. package/src/cli/memoryAccess.ts +53 -0
  144. package/src/cli/print.js +119 -5
  145. package/src/cli/print.ts +597 -0
  146. package/src/cli/quickModelSetup.js +60 -0
  147. package/src/cli/quickModelSetup.tsx +96 -0
  148. package/src/cli/streamJson.js +80 -4
  149. package/src/cli/streamJson.ts +433 -0
  150. package/src/cli/wizards/advisorWizard.js +1 -0
  151. package/src/cli/wizards/advisorWizard.tsx +195 -0
  152. package/src/cli/wizards/agentRuntimeWizard.js +84 -0
  153. package/src/cli/wizards/agentRuntimeWizard.tsx +134 -0
  154. package/src/cli/wizards/browserWizard.js +55 -0
  155. package/src/cli/wizards/browserWizard.tsx +77 -0
  156. package/src/cli/wizards/contextAdvisorWizard.js +84 -0
  157. package/src/cli/wizards/contextAdvisorWizard.tsx +124 -0
  158. package/src/cli/wizards/fieldForm.js +7 -4
  159. package/src/cli/wizards/fieldForm.tsx +250 -0
  160. package/src/cli/wizards/imageWizard.js +4 -5
  161. package/src/cli/wizards/imageWizard.tsx +96 -0
  162. package/src/cli/wizards/openRouterWizard.tsx +48 -0
  163. package/src/cli/wizards/providerPresets.js +1 -8
  164. package/src/cli/wizards/providerPresets.ts +106 -0
  165. package/src/cli/wizards/providerWizard.js +152 -205
  166. package/src/cli/wizards/providerWizard.tsx +266 -0
  167. package/src/cli/wizards/searchWizard.tsx +47 -0
  168. package/src/cli/wizards/ttsWizard.js +4 -3
  169. package/src/cli/wizards/ttsWizard.tsx +61 -0
  170. package/src/config/configDefaults.js +25 -0
  171. package/src/config/configDefaults.ts +33 -0
  172. package/src/config/configDiagnostics.js +117 -0
  173. package/src/config/configDiagnostics.ts +166 -0
  174. package/src/config/configFile.js +52 -32
  175. package/src/config/configFile.ts +633 -0
  176. package/src/config/configManagement.js +126 -0
  177. package/src/config/configManagement.ts +159 -0
  178. package/src/config/configService.js +66 -11
  179. package/src/config/configService.ts +554 -0
  180. package/src/config/numericLimits.js +61 -0
  181. package/src/config/numericLimits.ts +80 -0
  182. package/src/config.ts +109 -0
  183. package/src/context/agentHome.ts +11 -0
  184. package/src/context/archive.ts +144 -0
  185. package/src/context/budgetPlan.js +54 -0
  186. package/src/context/budgetPlan.ts +88 -0
  187. package/src/context/compact.js +179 -106
  188. package/src/context/compact.ts +584 -0
  189. package/src/context/contextBundle.js +119 -0
  190. package/src/context/contextBundle.ts +176 -0
  191. package/src/context/contextLock.ts +84 -0
  192. package/src/context/microCompactLite.ts +218 -0
  193. package/src/context/persistContext.ts +177 -0
  194. package/src/context/reactiveCompact.js +19 -4
  195. package/src/context/reactiveCompact.ts +240 -0
  196. package/src/context/recentDirs.ts +42 -0
  197. package/src/context/sessionPath.ts +206 -0
  198. package/src/context/sessionRegistry.js +8 -2
  199. package/src/context/sessionRegistry.ts +414 -0
  200. package/src/context/snipCompact.ts +163 -0
  201. package/src/context/tokenCounter.ts +106 -0
  202. package/src/context/workspaceIndex.js +2 -2
  203. package/src/context/workspaceIndex.ts +751 -0
  204. package/src/entry.compiled.tsx +20 -0
  205. package/src/harness/claimValidation.js +9 -0
  206. package/src/harness/claimValidation.ts +22 -0
  207. package/src/harness/evidenceLedger.js +92 -0
  208. package/src/harness/evidenceLedger.ts +96 -0
  209. package/src/harness/stallGuard.js +60 -0
  210. package/src/harness/stallGuard.ts +81 -0
  211. package/src/humanIntervention.js +129 -0
  212. package/src/humanIntervention.ts +216 -0
  213. package/src/infra/verification.ts +295 -0
  214. package/src/irreversible/rules.js +216 -0
  215. package/src/irreversible/rules.ts +261 -0
  216. package/src/llm/client.js +40 -3
  217. package/src/llm/client.ts +621 -0
  218. package/src/llm/promptCache.js +27 -0
  219. package/src/llm/promptCache.ts +41 -0
  220. package/src/llm/providers/anthropicFormat.js +41 -5
  221. package/src/llm/providers/anthropicFormat.ts +290 -0
  222. package/src/llm/providers/openaiFormat.js +186 -8
  223. package/src/llm/providers/openaiFormat.ts +428 -0
  224. package/src/loop.js +614 -63
  225. package/src/loop.ts +1454 -0
  226. package/src/main.js +67 -10
  227. package/src/main.tsx +344 -0
  228. package/src/memory/codec.js +204 -0
  229. package/src/memory/codec.ts +249 -0
  230. package/src/memory/constants.js +34 -0
  231. package/src/memory/constants.ts +50 -0
  232. package/src/memory/episodicMemory.js +684 -0
  233. package/src/memory/episodicMemory.ts +815 -0
  234. package/src/memory/fileStore.js +148 -0
  235. package/src/memory/fileStore.ts +184 -0
  236. package/src/memory/memoryService.js +570 -0
  237. package/src/memory/memoryService.ts +859 -0
  238. package/src/memory/migration.js +128 -0
  239. package/src/memory/migration.ts +160 -0
  240. package/src/memory/repository.js +789 -0
  241. package/src/memory/repository.ts +893 -0
  242. package/src/memory/retrieval.js +108 -0
  243. package/src/memory/retrieval.ts +145 -0
  244. package/src/memory/searchIndex.js +107 -0
  245. package/src/memory/searchIndex.ts +153 -0
  246. package/src/memory/topicView.js +82 -0
  247. package/src/memory/topicView.ts +95 -0
  248. package/src/memory/turnJournal.js +95 -0
  249. package/src/memory/turnJournal.ts +120 -0
  250. package/src/memory/types.js +2 -0
  251. package/src/memory/types.ts +186 -0
  252. package/src/messageQueue.ts +123 -0
  253. package/src/multimodal.js +128 -46
  254. package/src/multimodal.ts +349 -0
  255. package/src/plugin-sdk.js +21 -1
  256. package/src/plugin-sdk.ts +134 -0
  257. package/src/plugins/builtinPluginIds.js +47 -0
  258. package/src/plugins/builtinPluginIds.ts +51 -0
  259. package/src/plugins/builtinRegistry.ts +43 -0
  260. package/src/plugins/commandRouter.js +40 -26
  261. package/src/plugins/commandRouter.ts +261 -0
  262. package/src/plugins/hookEngine.ts +341 -0
  263. package/src/plugins/pluginApi.ts +133 -0
  264. package/src/plugins/pluginLifecycle.ts +34 -0
  265. package/src/plugins/pluginLoader.ts +147 -0
  266. package/src/plugins/pluginManifest.js +127 -0
  267. package/src/plugins/pluginManifest.ts +152 -0
  268. package/src/plugins/pluginRunner.js +47 -2
  269. package/src/plugins/pluginRunner.ts +207 -0
  270. package/src/plugins/transcript.ts +208 -0
  271. package/src/prompts/lint.js +169 -0
  272. package/src/prompts/lint.ts +220 -0
  273. package/src/prompts/pluginList.js +32 -16
  274. package/src/prompts/pluginList.ts +86 -0
  275. package/src/prompts/policyRegistry.js +318 -0
  276. package/src/prompts/policyRegistry.ts +358 -0
  277. package/src/prompts/projectInstructions.js +24 -0
  278. package/src/prompts/projectInstructions.ts +81 -0
  279. package/src/prompts/promptAssembly.js +311 -202
  280. package/src/prompts/promptAssembly.ts +510 -0
  281. package/src/prompts/skillList.js +106 -45
  282. package/src/prompts/skillList.ts +198 -0
  283. package/src/prompts/system.js +31 -6
  284. package/src/prompts/system.ts +81 -0
  285. package/src/runtime/agentRuntimeContext.js +53 -0
  286. package/src/runtime/agentRuntimeContext.ts +112 -0
  287. package/src/session/runAgentTurn.js +71 -12
  288. package/src/session/runAgentTurn.ts +181 -0
  289. package/src/session/runTurn.js +29 -0
  290. package/src/session/runTurn.ts +160 -0
  291. package/src/session/runtimeStore.js +149 -0
  292. package/src/session/runtimeStore.ts +197 -0
  293. package/src/session/sessionState.js +79 -3
  294. package/src/session/sessionState.ts +134 -0
  295. package/src/toolGate.ts +50 -0
  296. package/src/tools/advisor/advisor.js +76 -15
  297. package/src/tools/advisor/advisor.ts +512 -0
  298. package/src/tools/agent/agent.js +245 -29
  299. package/src/tools/agent/agent.ts +837 -0
  300. package/src/tools/agent/agentTaskService.js +60 -0
  301. package/src/tools/agent/agentTaskService.ts +113 -0
  302. package/src/tools/agent/agentTypes.js +20 -8
  303. package/src/tools/agent/agentTypes.ts +94 -0
  304. package/src/tools/agent/coordinator.ts +111 -0
  305. package/src/tools/agent/worktree.ts +296 -0
  306. package/src/tools/ask/ask.js +17 -0
  307. package/src/tools/ask/ask.ts +122 -0
  308. package/src/tools/bash/attachImage.js +223 -0
  309. package/src/tools/bash/attachImage.ts +281 -0
  310. package/src/tools/bash/bash.js +132 -14
  311. package/src/tools/bash/bash.ts +642 -0
  312. package/src/tools/bash/semantics.ts +103 -0
  313. package/src/tools/bash/warnings.js +17 -11
  314. package/src/tools/bash/warnings.ts +117 -0
  315. package/src/tools/capabilities.js +42 -0
  316. package/src/tools/capabilities.ts +69 -0
  317. package/src/tools/computeruse/accessibilityPermission.js +261 -0
  318. package/src/tools/computeruse/accessibilityPermission.ts +294 -0
  319. package/src/tools/computeruse/axSearch.js +96 -0
  320. package/src/tools/computeruse/axSearch.ts +120 -0
  321. package/src/tools/computeruse/axSnap.js +272 -0
  322. package/src/tools/computeruse/axSnap.ts +349 -0
  323. package/src/tools/computeruse/capabilityLabels.js +95 -0
  324. package/src/tools/computeruse/capabilityLabels.ts +115 -0
  325. package/src/tools/computeruse/computerUseService.js +2235 -0
  326. package/src/tools/computeruse/computerUseService.ts +2686 -0
  327. package/src/tools/computeruse/computeruse.js +2742 -0
  328. package/src/tools/computeruse/computeruse.ts +3265 -0
  329. package/src/tools/computeruse/diagnosticTrace.js +154 -0
  330. package/src/tools/computeruse/diagnosticTrace.ts +195 -0
  331. package/src/tools/computeruse/diagnostics.js +369 -0
  332. package/src/tools/computeruse/diagnostics.ts +453 -0
  333. package/src/tools/computeruse/grants.js +53 -0
  334. package/src/tools/computeruse/grants.ts +70 -0
  335. package/src/tools/computeruse/humanBoundary.js +159 -0
  336. package/src/tools/computeruse/humanBoundary.ts +199 -0
  337. package/src/tools/computeruse/intervention.js +77 -0
  338. package/src/tools/computeruse/intervention.ts +110 -0
  339. package/src/tools/computeruse/manualSchema.js +709 -0
  340. package/src/tools/computeruse/manualSchema.ts +916 -0
  341. package/src/tools/computeruse/observationImages.js +705 -0
  342. package/src/tools/computeruse/observationImages.ts +889 -0
  343. package/src/tools/computeruse/protocol.js +60 -0
  344. package/src/tools/computeruse/protocol.ts +515 -0
  345. package/src/tools/computeruse/telemetryLog.js +57 -0
  346. package/src/tools/computeruse/telemetryLog.ts +67 -0
  347. package/src/tools/computeruse/vision/appGuide.js +325 -0
  348. package/src/tools/computeruse/vision/appGuide.ts +482 -0
  349. package/src/tools/computeruse/vision/focus.js +291 -0
  350. package/src/tools/computeruse/vision/focus.ts +382 -0
  351. package/src/tools/computeruse/vision/frames.js +248 -0
  352. package/src/tools/computeruse/vision/frames.ts +329 -0
  353. package/src/tools/computeruse/vision/geometry.js +131 -0
  354. package/src/tools/computeruse/vision/geometry.ts +163 -0
  355. package/src/tools/computeruse/vision/imaging.js +201 -0
  356. package/src/tools/computeruse/vision/imaging.ts +281 -0
  357. package/src/tools/computeruse/vision/png.js +274 -0
  358. package/src/tools/computeruse/vision/png.ts +317 -0
  359. package/src/tools/computeruse/vision/raster.js +320 -0
  360. package/src/tools/computeruse/vision/raster.ts +408 -0
  361. package/src/tools/computeruse/vision/settle.js +131 -0
  362. package/src/tools/computeruse/vision/settle.ts +220 -0
  363. package/src/tools/computeruse/vision/telemetry.js +196 -0
  364. package/src/tools/computeruse/vision/telemetry.ts +241 -0
  365. package/src/tools/computeruse/visionOcr.js +115 -0
  366. package/src/tools/computeruse/visionOcr.ts +128 -0
  367. package/src/tools/computeruse/waitFor.js +237 -0
  368. package/src/tools/computeruse/waitFor.ts +291 -0
  369. package/src/tools/download/download.js +10 -6
  370. package/src/tools/download/download.ts +187 -0
  371. package/src/tools/edit/edit.js +30 -18
  372. package/src/tools/edit/edit.ts +349 -0
  373. package/src/tools/edit/multi-edit.js +25 -14
  374. package/src/tools/edit/multi-edit.ts +223 -0
  375. package/src/tools/effectiveToolSet.js +73 -0
  376. package/src/tools/effectiveToolSet.ts +91 -0
  377. package/src/tools/genimage/genimage.ts +257 -0
  378. package/src/tools/genspeech/genspeech.ts +83 -0
  379. package/src/tools/glob/glob.js +176 -29
  380. package/src/tools/glob/glob.ts +283 -0
  381. package/src/tools/grep/grep.js +61 -19
  382. package/src/tools/grep/grep.ts +239 -0
  383. package/src/tools/grep/rgPath.ts +206 -0
  384. package/src/tools/index.js +99 -5
  385. package/src/tools/index.ts +293 -0
  386. package/src/tools/lsp/config.js +113 -0
  387. package/src/tools/lsp/config.ts +113 -0
  388. package/src/tools/lsp/lsp.js +256 -0
  389. package/src/tools/lsp/lsp.ts +274 -0
  390. package/src/tools/lsp/service.js +303 -0
  391. package/src/tools/lsp/service.ts +296 -0
  392. package/src/tools/memory/memory.js +520 -0
  393. package/src/tools/memory/memory.ts +625 -0
  394. package/src/tools/memory/policy.js +53 -0
  395. package/src/tools/memory/policy.ts +72 -0
  396. package/src/tools/notebook/notebookEdit.js +114 -0
  397. package/src/tools/notebook/notebookEdit.ts +126 -0
  398. package/src/tools/powershell/powershell.js +210 -0
  399. package/src/tools/powershell/powershell.ts +239 -0
  400. package/src/tools/presentresult/presentresult.js +145 -0
  401. package/src/tools/presentresult/presentresult.ts +156 -0
  402. package/src/tools/read/read.js +371 -163
  403. package/src/tools/read/read.ts +558 -0
  404. package/src/tools/shared/diffSummary.js +44 -0
  405. package/src/tools/shared/diffSummary.ts +63 -0
  406. package/src/tools/shared/fileActivity.js +51 -0
  407. package/src/tools/shared/fileActivity.ts +66 -0
  408. package/src/tools/shared/fileMutationBus.js +13 -0
  409. package/src/tools/shared/fileMutationBus.ts +14 -0
  410. package/src/tools/shared/fileState.js +73 -65
  411. package/src/tools/shared/fileState.ts +145 -0
  412. package/src/tools/shared/fileUtils.js +81 -4
  413. package/src/tools/shared/fileUtils.ts +504 -0
  414. package/src/tools/shared/killTree.ts +50 -0
  415. package/src/tools/shared/permanentDeleteGuard.js +26 -0
  416. package/src/tools/shared/permanentDeleteGuard.ts +34 -0
  417. package/src/tools/shared/schemas.ts +20 -0
  418. package/src/tools/shared/toolOutputStore.js +97 -0
  419. package/src/tools/shared/toolOutputStore.ts +110 -0
  420. package/src/tools/skill/skill.js +86 -0
  421. package/src/tools/skill/skill.ts +94 -0
  422. package/src/tools/snip/snip.js +67 -0
  423. package/src/tools/snip/snip.ts +80 -0
  424. package/src/tools/tasks/backgroundTaskService.js +275 -0
  425. package/src/tools/tasks/backgroundTaskService.ts +369 -0
  426. package/src/tools/tasks/processEvidence.js +24 -0
  427. package/src/tools/tasks/processEvidence.ts +34 -0
  428. package/src/tools/tasks/taskManagement.js +163 -0
  429. package/src/tools/tasks/taskManagement.ts +180 -0
  430. package/src/tools/tasks/taskOutput.js +113 -0
  431. package/src/tools/tasks/taskOutput.ts +145 -0
  432. package/src/tools/tasks/taskStop.js +74 -0
  433. package/src/tools/tasks/taskStop.ts +99 -0
  434. package/src/tools/tasks/taskStore.js +46 -0
  435. package/src/tools/tasks/taskStore.ts +77 -0
  436. package/src/tools/terminal/terminalCapture.js +167 -0
  437. package/src/tools/terminal/terminalCapture.ts +179 -0
  438. package/src/tools/trash/trash.js +233 -0
  439. package/src/tools/trash/trash.ts +283 -0
  440. package/src/tools/types.js +1 -1
  441. package/src/tools/types.ts +24 -0
  442. package/src/tools/webbrowser/agentBrowserPath.ts +286 -0
  443. package/src/tools/webbrowser/browser.js +214 -11
  444. package/src/tools/webbrowser/browser.ts +293 -0
  445. package/src/tools/webbrowser/browserControl.js +153 -48
  446. package/src/tools/webbrowser/browserControl.ts +262 -0
  447. package/src/tools/webbrowser/browserDaemon.js +147 -39
  448. package/src/tools/webbrowser/browserDaemon.ts +270 -0
  449. package/src/tools/webbrowser/browserOutcome.js +273 -0
  450. package/src/tools/webbrowser/browserOutcome.ts +306 -0
  451. package/src/tools/webbrowser/browserRunRegistry.js +150 -0
  452. package/src/tools/webbrowser/browserRunRegistry.ts +179 -0
  453. package/src/tools/webbrowser/browserService.js +20 -6
  454. package/src/tools/webbrowser/browserService.ts +56 -0
  455. package/src/tools/webbrowser/browserStream.js +30 -1
  456. package/src/tools/webbrowser/browserStream.ts +216 -0
  457. package/src/tools/webbrowser/browserTabs.js +143 -0
  458. package/src/tools/webbrowser/browserTabs.ts +210 -0
  459. package/src/tools/webbrowser/webbrowser.js +831 -150
  460. package/src/tools/webbrowser/webbrowser.ts +1537 -0
  461. package/src/tools/webfetch/preapproved.ts +274 -0
  462. package/src/tools/webfetch/webfetch.js +24 -23
  463. package/src/tools/webfetch/webfetch.ts +383 -0
  464. package/src/tools/websearch/websearch.js +12 -11
  465. package/src/tools/websearch/websearch.ts +292 -0
  466. package/src/tools/worktree/sessionWorktree.js +128 -0
  467. package/src/tools/worktree/sessionWorktree.ts +158 -0
  468. package/src/tools/write/write.js +27 -44
  469. package/src/tools/write/write.ts +136 -0
  470. package/src/types.ts +960 -0
  471. package/src/ui/App.js +216 -12
  472. package/src/ui/App.tsx +879 -0
  473. package/src/ui/AskQuestion.tsx +300 -0
  474. package/src/ui/InputBox.js +77 -1
  475. package/src/ui/InputBox.tsx +567 -0
  476. package/src/ui/LiveArea.tsx +344 -0
  477. package/src/ui/MessageList.js +27 -6
  478. package/src/ui/MessageList.tsx +559 -0
  479. package/src/ui/ModelPicker.tsx +107 -0
  480. package/src/ui/QueuedMessagesBanner.tsx +51 -0
  481. package/src/ui/Root.js +6 -8
  482. package/src/ui/Root.tsx +100 -0
  483. package/src/ui/SessionPicker.tsx +169 -0
  484. package/src/ui/StatusLine.js +22 -1
  485. package/src/ui/StatusLine.tsx +145 -0
  486. package/src/ui/WorkspacePicker.tsx +84 -0
  487. package/src/ui/advisorCommand.js +54 -0
  488. package/src/ui/advisorCommand.ts +63 -0
  489. package/src/ui/computerCommand.js +19 -0
  490. package/src/ui/computerCommand.ts +35 -0
  491. package/src/ui/figures.ts +45 -0
  492. package/src/ui/hooks/askSlot.ts +112 -0
  493. package/src/ui/hooks/useChat.js +271 -7
  494. package/src/ui/hooks/useChat.ts +1578 -0
  495. package/src/ui/hooks/useInputHistory.ts +235 -0
  496. package/src/ui/hooks/usePasteHandler.ts +220 -0
  497. package/src/ui/hooks/useTerminalSize.ts +41 -0
  498. package/src/ui/hooks/useTextBuffer.ts +108 -0
  499. package/src/ui/hooks/useTokenUsage.ts +44 -0
  500. package/src/ui/liveViewport.ts +189 -0
  501. package/src/ui/markdown.ts +230 -0
  502. package/src/ui/textBuffer.ts +239 -0
  503. package/src/ui/theme.ts +35 -0
  504. package/src/utils/clipboardImage.js +358 -0
  505. package/src/utils/clipboardImage.ts +420 -0
  506. package/src/utils/debugLog.ts +50 -0
  507. package/src/utils/greenRoot.ts +35 -0
  508. package/src/utils/packageRoot.ts +40 -0
  509. package/src/utils/pathContains.js +28 -0
  510. package/src/utils/pathContains.ts +31 -0
  511. package/src/utils/resourcePaths.ts +71 -0
  512. package/src/utils/stripThink.ts +49 -0
  513. package/src/utils/zodToJson.ts +73 -0
  514. package/src/web/browserBridge.js +365 -66
  515. package/src/web/browserBridge.ts +672 -0
  516. package/src/web/protocol.ts +1804 -0
  517. package/vendor/computer-use/arm64-darwin/cu-helperd +0 -0
  518. package/workflows/ppt.yaml +13 -2
  519. package/workflows/wechat-reading-shots.yaml +315 -0
  520. package/workflows/word.yaml +11 -1
  521. package/skills/docx/scripts/office/helpers/__pycache__/__init__.cpython-314.pyc +0 -0
  522. package/skills/docx/scripts/office/helpers/__pycache__/merge_runs.cpython-314.pyc +0 -0
  523. package/skills/docx/scripts/office/helpers/__pycache__/simplify_redlines.cpython-314.pyc +0 -0
  524. package/skills/docx/scripts/office/validators/__pycache__/__init__.cpython-314.pyc +0 -0
  525. package/skills/docx/scripts/office/validators/__pycache__/base.cpython-314.pyc +0 -0
  526. package/skills/docx/scripts/office/validators/__pycache__/docx.cpython-314.pyc +0 -0
  527. package/skills/docx/scripts/office/validators/__pycache__/pptx.cpython-314.pyc +0 -0
  528. package/skills/docx/scripts/office/validators/__pycache__/redlining.cpython-314.pyc +0 -0
  529. package/skills/image-stats/scripts/__pycache__/image_stats.cpython-314.pyc +0 -0
  530. package/skills/image-stats/scripts/__pycache__/image_stats_test.cpython-314.pyc +0 -0
  531. package/skills/ui-design/scripts/__pycache__/assemble_material.cpython-314.pyc +0 -0
  532. package/skills/ui-design/scripts/__pycache__/assemble_material_test.cpython-314.pyc +0 -0
  533. package/skills/ui-design/scripts/__pycache__/chart_sanity_check.cpython-314.pyc +0 -0
  534. package/skills/ui-design/scripts/__pycache__/check_language_policy.cpython-314.pyc +0 -0
  535. package/skills/ui-design/scripts/__pycache__/check_ui_artifact.cpython-314.pyc +0 -0
  536. package/skills/ui-design/scripts/__pycache__/check_ui_artifact_pptx_test.cpython-314.pyc +0 -0
  537. package/skills/ui-design/scripts/__pycache__/deck_pages_check.cpython-314.pyc +0 -0
  538. package/skills/ui-design/scripts/__pycache__/deck_pages_check_test.cpython-314.pyc +0 -0
  539. package/skills/ui-design/scripts/__pycache__/deck_visual_style_check.cpython-314.pyc +0 -0
  540. package/skills/ui-design/scripts/__pycache__/deck_visual_style_check_test.cpython-314.pyc +0 -0
  541. package/skills/ui-design/scripts/__pycache__/design_budget_check.cpython-314.pyc +0 -0
  542. package/skills/ui-design/scripts/__pycache__/design_budget_check_test.cpython-314.pyc +0 -0
  543. package/skills/ui-design/scripts/__pycache__/design_repair_hints.cpython-314.pyc +0 -0
  544. package/skills/ui-design/scripts/__pycache__/design_repair_hints_test.cpython-314.pyc +0 -0
  545. package/skills/ui-design/scripts/__pycache__/design_style_check.cpython-314.pyc +0 -0
  546. package/skills/ui-design/scripts/__pycache__/design_style_check_test.cpython-314.pyc +0 -0
  547. package/skills/ui-design/scripts/__pycache__/draft_coverage_check.cpython-314.pyc +0 -0
  548. package/skills/ui-design/scripts/__pycache__/extract_source_assets.cpython-314.pyc +0 -0
  549. package/skills/ui-design/scripts/__pycache__/extract_source_assets_test.cpython-314.pyc +0 -0
  550. package/skills/ui-design/scripts/__pycache__/generated_image_review_collect.cpython-314.pyc +0 -0
  551. package/skills/ui-design/scripts/__pycache__/generated_image_review_collect_test.cpython-314.pyc +0 -0
  552. package/skills/ui-design/scripts/__pycache__/image_plan_lint.cpython-314.pyc +0 -0
  553. package/skills/ui-design/scripts/__pycache__/image_plan_lint_test.cpython-314.pyc +0 -0
  554. package/skills/ui-design/scripts/__pycache__/image_prompt_rewrite.cpython-314.pyc +0 -0
  555. package/skills/ui-design/scripts/__pycache__/image_prompt_rewrite_test.cpython-314.pyc +0 -0
  556. package/skills/ui-design/scripts/__pycache__/layout_balance.cpython-314.pyc +0 -0
  557. package/skills/ui-design/scripts/__pycache__/layout_balance_test.cpython-314.pyc +0 -0
  558. package/skills/ui-design/scripts/__pycache__/normalize_design_json.cpython-314.pyc +0 -0
  559. package/skills/ui-design/scripts/__pycache__/normalize_design_json_test.cpython-314.pyc +0 -0
  560. package/skills/ui-design/scripts/__pycache__/plan_source_layout.cpython-314.pyc +0 -0
  561. package/skills/ui-design/scripts/__pycache__/plan_source_layout_test.cpython-314.pyc +0 -0
  562. package/skills/ui-design/scripts/__pycache__/resolve_source_hint.cpython-314.pyc +0 -0
  563. package/skills/ui-design/scripts/__pycache__/resolve_source_hint_test.cpython-314.pyc +0 -0
  564. package/skills/ui-design/scripts/__pycache__/resolve_source_input.cpython-314.pyc +0 -0
  565. package/skills/ui-design/scripts/__pycache__/resolve_source_input_test.cpython-314.pyc +0 -0
  566. package/skills/ui-design/scripts/__pycache__/scaffold_ui_artifact.cpython-314.pyc +0 -0
  567. package/skills/ui-design/scripts/__pycache__/source_usage_check.cpython-314.pyc +0 -0
  568. package/skills/ui-design/scripts/__pycache__/source_usage_check_test.cpython-314.pyc +0 -0
  569. package/skills/ui-design/scripts/__pycache__/text_readability_pixel.cpython-314.pyc +0 -0
  570. package/skills/ui-design/scripts/__pycache__/visual_quality_gate.cpython-314.pyc +0 -0
  571. package/skills/ui-design/scripts/__pycache__/visual_quality_gate_test.cpython-314.pyc +0 -0
  572. /package/skills/ai-image/scripts/{generate_test.mjs → generate.selftest.mjs} +0 -0
  573. /package/skills/ai-image/scripts/{generate_from_plan_test.mjs → generate_from_plan.selftest.mjs} +0 -0
@@ -0,0 +1,292 @@
1
+ /**
2
+ * ============================================================
3
+ * src/tools/websearch.ts —— WebSearch 工具(联网搜索)
4
+ * ------------------------------------------------------------
5
+ * 底层调用 Tavily Search API(https://tavily.com/)。
6
+ * 发请求带退避重试(见下「4b. 退避重试」):并发突发 + dev/免费 key 被前端切 socket
7
+ * 的瞬态不再直接当失败喂回 LLM。次数由 TAVILY_MAX_RETRIES 控(默认 3)。
8
+ *
9
+ * 为什么选 Tavily:
10
+ * - LLM 友好:返回结构化 JSON,自带 content 摘要;不用我们再去抓 HTML
11
+ * - 接口简单:一个 POST + JSON body 搞定,不用 OAuth / 翻墙
12
+ * - 免费额度:每月 1000 次足够学习用
13
+ *
14
+ * Key 配置:
15
+ * 在项目根 .env 里加:
16
+ * TAVILY_API_KEY=
17
+ * 没设的话,工具会返回友好错误(不影响 agent 启动)。
18
+ *
19
+ * 输入:
20
+ * query 必填,搜索关键词
21
+ * max_results 可选,默认 5(Tavily 上限 20)
22
+ * search_depth 可选 'basic' | 'advanced',默认 basic
23
+ * topic 可选 'general' | 'news',默认 general
24
+ *
25
+ * 输出:
26
+ * 每条结果一段:
27
+ * [1] 标题
28
+ * URL: https://...
29
+ * 内容摘要(content)
30
+ * 如有 answer 字段(advanced 才返回),先列在最上面。
31
+ * ============================================================
32
+ */
33
+
34
+ import { z } from 'zod';
35
+
36
+ import type { Tool, ToolResult } from '../../types.js';
37
+ import { configService } from '../../config/configService.js';
38
+ import { DEFAULT_MAX_RESULT_SIZE_CHARS } from '../types.js';
39
+ import { toToolParameters } from '../../utils/zodToJson.js';
40
+
41
+ // ---------------- 1. Zod 输入 schema ----------------
42
+ const inputSchema = z.object({
43
+ query: z
44
+ .string()
45
+ .min(1, '必须提供搜索关键词')
46
+ .max(400, '搜索关键词太长(>400 字)')
47
+ .describe('搜索关键词,建议自然语言描述需要查的信息'),
48
+ max_results: z
49
+ .number()
50
+ .int()
51
+ .min(1)
52
+ .max(20)
53
+ .optional()
54
+ .describe('返回结果数量,1-20,默认 5'),
55
+ search_depth: z
56
+ .enum(['basic', 'advanced'])
57
+ .optional()
58
+ .describe('basic 快但浅;advanced 慢但深(含 answer 摘要),默认 basic'),
59
+ topic: z
60
+ .enum(['general', 'news'])
61
+ .optional()
62
+ .describe('general=通用网页;news=偏新闻源;默认 general'),
63
+ });
64
+ type WebSearchInput = z.infer<typeof inputSchema>;
65
+
66
+ // ---------------- 2. JSON Schema(由 Zod 自动派生) ----------------
67
+ const parameters = toToolParameters(inputSchema);
68
+
69
+ // ---------------- 3. Description(给 LLM 看的工具说明) ----------------
70
+ const description = `Searches the public web through Tavily and returns structured source candidates.
71
+ - Use it to discover sources, verify current information, compare multiple sources, or locate current documentation.
72
+ - It does not open or operate a browser. Use returned URLs with WebFetch when full source text is needed.
73
+ - Results contain title, URL and a text snippet. They are discovery evidence, not a substitute for reading a high-value source in full.
74
+ - Keep each query focused on one sub-question. When another search is needed, change the keywords, source, or angle instead of repeating the same query.
75
+ - Add an explicit date or year only when recency matters; stable concepts and exact names should remain exact.
76
+ - \`search_depth: "advanced"\` is slower but can return a synthesized answer; \`topic: "news"\` favors news sources.
77
+ - Requires a configured Tavily API key.`;
78
+
79
+ // ---------------- 4. Tavily 响应类型(仅取我们用到的字段) ----------------
80
+ interface TavilyResult {
81
+ title: string;
82
+ url: string;
83
+ content: string;
84
+ score?: number;
85
+ published_date?: string;
86
+ }
87
+ interface TavilyResponse {
88
+ query?: string;
89
+ answer?: string;
90
+ results?: TavilyResult[];
91
+ }
92
+
93
+ // ---------------- 4b. 退避重试 ----------------
94
+ //
95
+ // 为什么需要(与单发 fetch 零重试的旧行为对比):WebSearch 是 isConcurrencySafe 工具,
96
+ // 主循环把同一轮的多个 WebSearch 调用 **并行**发火(loop.ts,Promise.all)。研究类
97
+ // prompt 又常让模型「围绕 3–6 个子问题分别检索」——于是一瞬间 3~6 条连接同时打向
98
+ // 同一个 Tavily key。dev / 免费 ティア 的并发/速率上限被触发时,CDN 前端常**直接切断
99
+ // socket** 而非返回干净的 429(错误落进 fetch 的 catch:「socket connection closed
100
+ // unexpectedly」)。旧代码单发 fetch、零重试,这类瞬态会被直接当失败喂回 LLM ——
101
+ // 表现为「突然连续搜索失败,但单发检索仍通」。
102
+ //
103
+ // 对策与 llm/client.ts 的自适应退避同思想(本地、有界、带抖动):
104
+ // 可重试:fetch 抛错(socket 切断/超时)+ HTTP 429 + 5xx(尊重 Retry-After)。
105
+ // 不重试:用户中断(signal)、其它 4xx(401 key 错 / 400 参数错,重试无意义)、
106
+ // JSON 解析失败(body 已到、重发大概率同样坏)。
107
+ // 次数:默认 3 次重试(共 4 次尝试),可用 TAVILY_MAX_RETRIES 覆盖。
108
+ // 抖动:±15% 把并发重试**散开**,避免落 socket 的几条同时再殺到、又一起被切。
109
+
110
+ const TAVILY_ENDPOINT = 'https://api.tavily.com/search';
111
+
112
+ function tavilyMaxRetries(): number {
113
+ const n = Number(process.env.TAVILY_MAX_RETRIES);
114
+ return Number.isFinite(n) && n >= 0 ? Math.floor(n) : 3;
115
+ }
116
+
117
+ /** 退避时长(ms):优先 Retry-After;否则指数 500·2^n 封顶 8s,再叠 ±15% 抖动。 */
118
+ function backoffDelayMs(attempt: number, retryAfterMs?: number): number {
119
+ if (retryAfterMs && retryAfterMs > 0) return Math.min(retryAfterMs, 15000);
120
+ const capped = Math.min(500 * 2 ** attempt, 8000);
121
+ return Math.round(capped * (0.85 + Math.random() * 0.3));
122
+ }
123
+
124
+ /** Retry-After 头解析(秒数 或 HTTP-date)→ ms;无法解析返回 undefined。 */
125
+ function parseRetryAfter(h: string | null): number | undefined {
126
+ if (!h) return undefined;
127
+ const secs = Number(h);
128
+ if (Number.isFinite(secs)) return Math.max(0, secs * 1000);
129
+ const at = Date.parse(h);
130
+ return Number.isNaN(at) ? undefined : Math.max(0, at - Date.now());
131
+ }
132
+
133
+ /** 可中断退避:signal abort 时立即 resolve(让外层据 signal 收口,不在这里抛)。 */
134
+ function sleep(ms: number, signal?: AbortSignal): Promise<void> {
135
+ return new Promise((resolve) => {
136
+ if (signal?.aborted) return resolve();
137
+ const onAbort = (): void => {
138
+ clearTimeout(timer);
139
+ resolve();
140
+ };
141
+ const timer = setTimeout(() => {
142
+ signal?.removeEventListener('abort', onAbort);
143
+ resolve();
144
+ }, ms);
145
+ signal?.addEventListener('abort', onAbort, { once: true });
146
+ });
147
+ }
148
+
149
+ /** 发 Tavily 请求并按上述策略重试。成功返回已解析的 data,失败返回 friendly error。 */
150
+ async function fetchTavilyWithRetry(
151
+ body: unknown,
152
+ signal?: AbortSignal,
153
+ ): Promise<{ ok: true; data: TavilyResponse } | { ok: false; error: string }> {
154
+ const maxRetries = tavilyMaxRetries();
155
+ let lastErr = '';
156
+
157
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
158
+ if (signal?.aborted) return { ok: false, error: '搜索已被中断' };
159
+
160
+ let res: Response;
161
+ try {
162
+ res = await fetch(TAVILY_ENDPOINT, {
163
+ method: 'POST',
164
+ headers: { 'content-type': 'application/json' },
165
+ body: JSON.stringify(body),
166
+ signal,
167
+ });
168
+ } catch (e) {
169
+ if (signal?.aborted) return { ok: false, error: '搜索已被中断' };
170
+ lastErr = `调用 Tavily 失败(网络):${(e as Error).message}`;
171
+ if (attempt < maxRetries) {
172
+ await sleep(backoffDelayMs(attempt), signal);
173
+ continue;
174
+ }
175
+ break;
176
+ }
177
+
178
+ // 429 / 5xx:服务端瞬态(限流 / 过载 / 切 socket 后偶发的 5xx)→ 可重试
179
+ if (res.status === 429 || res.status >= 500) {
180
+ const text = await res.text().catch(() => '');
181
+ lastErr = `Tavily HTTP ${res.status}:${text.slice(0, 300)}`;
182
+ if (attempt < maxRetries) {
183
+ const wait = backoffDelayMs(attempt, parseRetryAfter(res.headers.get('retry-after')));
184
+ await sleep(wait, signal);
185
+ continue;
186
+ }
187
+ break;
188
+ }
189
+
190
+ // 其它 4xx(401 key 无效 / 400 参数错…):重试无意义,立即返回
191
+ if (!res.ok) {
192
+ const text = await res.text().catch(() => '');
193
+ return { ok: false, error: `Tavily HTTP ${res.status}:${text.slice(0, 500)}` };
194
+ }
195
+
196
+ // 解析 JSON(坏响应不重试——body 已到、重发大概率同样坏)
197
+ try {
198
+ const data = (await res.json()) as TavilyResponse;
199
+ return { ok: true, data };
200
+ } catch (e) {
201
+ return { ok: false, error: `Tavily 响应不是合法 JSON:${(e as Error).message}` };
202
+ }
203
+ }
204
+
205
+ return {
206
+ ok: false,
207
+ error:
208
+ `${lastErr}(已重试 ${maxRetries} 次仍失败——并发突发下 dev/免费 key 易被前端切 socket;` +
209
+ `可减少同轮并发检索数、调大 TAVILY_MAX_RETRIES,或升级 Tavily key)`,
210
+ };
211
+ }
212
+
213
+ // ---------------- 5. call() ----------------
214
+ async function call(
215
+ input: WebSearchInput,
216
+ signal?: AbortSignal,
217
+ getApiKey: () => Promise<string | undefined> = async () => (await configService.tool('webSearch'))?.apiKey,
218
+ ): Promise<ToolResult> {
219
+ // 5a. 取 key
220
+ const apiKey = await getApiKey();
221
+ if (!apiKey) {
222
+ return {
223
+ ok: false,
224
+ error:
225
+ 'WebSearch 不可用:尚未配置 Tavily API Key。\n' +
226
+ '请在 KakadeAI 设置 → 工具 → 联网搜索中配置,或在 env 模式提供 TAVILY_API_KEY。',
227
+ };
228
+ }
229
+
230
+ const body = {
231
+ api_key: apiKey,
232
+ // Preserve the exact research query. The prompt layer adds a date only
233
+ // when recency matters; unconditional mutation hurts exact names,
234
+ // historical topics, and stable technical documentation.
235
+ query: input.query,
236
+ max_results: input.max_results ?? 5,
237
+ search_depth: input.search_depth ?? 'basic',
238
+ topic: input.topic ?? 'general',
239
+ // 让 advanced 模式自动给 answer;basic 不会有
240
+ include_answer: input.search_depth === 'advanced',
241
+ };
242
+
243
+ // 5c. 发请求(带退避重试,吸收 dev/免费 key 在并发突发下的 socket 切断 + 429/5xx)
244
+ const fetched = await fetchTavilyWithRetry(body, signal);
245
+ if (!fetched.ok) return { ok: false, error: fetched.error };
246
+ const data = fetched.data;
247
+
248
+ // 5d. 取结果
249
+ const results = data.results ?? [];
250
+ if (results.length === 0) {
251
+ return {
252
+ ok: true,
253
+ content: `(no results for "${input.query}")`,
254
+ };
255
+ }
256
+
257
+ // 5e. 拼输出
258
+ const parts: string[] = [];
259
+ if (data.answer) {
260
+ parts.push(`【综合回答】\n${data.answer}\n`);
261
+ }
262
+ parts.push(`【共 ${results.length} 条结果】`);
263
+ results.forEach((r, i) => {
264
+ const date = r.published_date ? `(${r.published_date})` : '';
265
+ parts.push(
266
+ `\n[${i + 1}] ${r.title}${date}\nURL: ${r.url}\n${(r.content ?? '').trim()}`,
267
+ );
268
+ });
269
+
270
+ let content = parts.join('\n');
271
+ if (content.length > DEFAULT_MAX_RESULT_SIZE_CHARS) {
272
+ content =
273
+ content.slice(0, DEFAULT_MAX_RESULT_SIZE_CHARS) +
274
+ `\n\n... (输出超过 ${DEFAULT_MAX_RESULT_SIZE_CHARS} 字符,已截断)`;
275
+ }
276
+
277
+ return { ok: true, content };
278
+ }
279
+
280
+ // ---------------- 6. 导出 ----------------
281
+ export function createWebSearchTool(
282
+ getApiKey: () => Promise<string | undefined> = async () => (await configService.tool('webSearch'))?.apiKey,
283
+ ): Tool<WebSearchInput> {
284
+ return {
285
+ name: 'WebSearch', description, inputSchema, parameters, isReadOnly: true,
286
+ isConcurrencySafe: true, maxResultSizeChars: DEFAULT_MAX_RESULT_SIZE_CHARS,
287
+ interruptBehavior: () => 'cancel',
288
+ call: (input, signal) => call(input, signal, getApiKey),
289
+ };
290
+ }
291
+
292
+ export const webSearchTool = createWebSearchTool();
@@ -0,0 +1,128 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { z } from 'zod';
3
+ import { toToolParameters } from '../../utils/zodToJson.js';
4
+ import { join } from 'node:path';
5
+ import { readRuntimeJson, sessionRuntimeDir, writeRuntimeJson, } from '../../session/runtimeStore.js';
6
+ import { applyAgentWorktree, commitWorktreeChanges, createAgentWorktree, hasWorktreeChanges, removeAgentWorktree, } from '../agent/worktree.js';
7
+ const enterSchema = z.object({
8
+ name: z
9
+ .string()
10
+ .regex(/^[a-zA-Z0-9._-]{1,48}$/)
11
+ .optional(),
12
+ });
13
+ const exitSchema = z.object({ action: z.enum(['apply', 'keep', 'discard']) });
14
+ async function persist(ctx, state) {
15
+ await writeRuntimeJson(join(sessionRuntimeDir(ctx), 'worktree.json'), {
16
+ active: state ?? null,
17
+ });
18
+ }
19
+ export async function hydrateSessionWorktree(ctx) {
20
+ if (!ctx.sessionState || ctx.sessionState.activeWorktree)
21
+ return;
22
+ const saved = await readRuntimeJson(join(sessionRuntimeDir(ctx), 'worktree.json'), {});
23
+ if (saved.active)
24
+ ctx.sessionState.activeWorktree = saved.active;
25
+ }
26
+ async function enter(input, ctx) {
27
+ const state = ctx.sessionState;
28
+ if (!state)
29
+ return { ok: false, error: 'EnterWorktree 需要会话状态' };
30
+ if (state.activeWorktree)
31
+ return {
32
+ ok: true,
33
+ content: `当前已在 worktree ${state.activeWorktree.path}`,
34
+ };
35
+ const slug = `session-${input.name ?? randomUUID().slice(0, 8)}`;
36
+ const wt = await createAgentWorktree(slug, ctx.cwd);
37
+ if (!wt.ok)
38
+ return wt;
39
+ state.activeWorktree = {
40
+ id: slug,
41
+ path: wt.path,
42
+ branch: wt.branch,
43
+ baseSha: wt.baseSha,
44
+ gitRoot: wt.gitRoot,
45
+ };
46
+ await persist(ctx, state.activeWorktree);
47
+ return {
48
+ ok: true,
49
+ content: `已进入主 Agent 隔离 worktree:${wt.path}\n分支:${wt.branch}\n后续工具调用立即使用该目录。`,
50
+ };
51
+ }
52
+ async function exit(input, ctx) {
53
+ const state = ctx.sessionState, wt = state?.activeWorktree;
54
+ if (!state || !wt)
55
+ return { ok: false, error: '当前会话没有活动 worktree' };
56
+ if (input.action === 'keep') {
57
+ state.activeWorktree = undefined;
58
+ await persist(ctx, undefined);
59
+ return {
60
+ ok: true,
61
+ content: `已退出有效 cwd,但保留 worktree:${wt.path}\n分支:${wt.branch}`,
62
+ };
63
+ }
64
+ const changed = await hasWorktreeChanges(wt.path, wt.baseSha);
65
+ if (input.action === 'discard' && changed) {
66
+ const committed = await commitWorktreeChanges(wt.path, `archive: preserve discarded session ${wt.id}`);
67
+ if (committed.ok) {
68
+ state.activeWorktree = undefined;
69
+ await persist(ctx, undefined);
70
+ }
71
+ return committed.ok
72
+ ? {
73
+ ok: true,
74
+ content: `检测到成果,未永久删除。已归档到分支 ${wt.branch},worktree 保留在 ${wt.path}。`,
75
+ }
76
+ : {
77
+ ok: false,
78
+ error: `无法安全归档,worktree 保持活动:${committed.error}`,
79
+ };
80
+ }
81
+ if (input.action === 'discard') {
82
+ await removeAgentWorktree(wt.path, wt.branch, wt.gitRoot);
83
+ state.activeWorktree = undefined;
84
+ await persist(ctx, undefined);
85
+ return {
86
+ ok: true,
87
+ content: 'worktree 无改动,已通过 Git worktree 管理安全清理。',
88
+ };
89
+ }
90
+ const committed = await commitWorktreeChanges(wt.path, `minimal-agent: apply session ${wt.id}`);
91
+ if (!committed.ok)
92
+ return {
93
+ ok: false,
94
+ error: `提交隔离改动失败,worktree 保持活动:${committed.error}`,
95
+ };
96
+ const applied = await applyAgentWorktree(wt.gitRoot, wt.id);
97
+ if (!applied.ok)
98
+ return {
99
+ ok: false,
100
+ error: `应用检查失败,worktree 保持活动:${applied.error}`,
101
+ };
102
+ state.activeWorktree = undefined;
103
+ await persist(ctx, undefined);
104
+ return {
105
+ ok: true,
106
+ content: `已通过 git apply --check 并将变更应用到原工作区;未自动提交。`,
107
+ };
108
+ }
109
+ export const enterWorktreeTool = {
110
+ name: 'EnterWorktree',
111
+ description: 'Creates and enters a session-scoped Git worktree for the main Agent. Later tool calls use it immediately while project memory keeps the original workspace identity.',
112
+ inputSchema: enterSchema,
113
+ parameters: toToolParameters(enterSchema),
114
+ isReadOnly: false,
115
+ isConcurrencySafe: false,
116
+ call: async () => ({ ok: false, error: 'requires session context' }),
117
+ callWithContext: (i, _s, c) => enter(i, c),
118
+ };
119
+ export const exitWorktreeTool = {
120
+ name: 'ExitWorktree',
121
+ description: 'Leaves the current session worktree. apply checks and applies its patch to the original workspace; keep preserves it; discard never destroys uncommitted results and archives changed work.',
122
+ inputSchema: exitSchema,
123
+ parameters: toToolParameters(exitSchema),
124
+ isReadOnly: false,
125
+ isConcurrencySafe: false,
126
+ call: async () => ({ ok: false, error: 'requires session context' }),
127
+ callWithContext: (i, _s, c) => exit(i, c),
128
+ };
@@ -0,0 +1,158 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { z } from 'zod';
3
+ import type { SessionState } from '../../session/sessionState.js';
4
+ import type { Tool, ToolCallContext, ToolResult } from '../../types.js';
5
+ import { toToolParameters } from '../../utils/zodToJson.js';
6
+ import { join } from 'node:path';
7
+ import {
8
+ readRuntimeJson,
9
+ sessionRuntimeDir,
10
+ writeRuntimeJson,
11
+ } from '../../session/runtimeStore.js';
12
+ import {
13
+ applyAgentWorktree,
14
+ commitWorktreeChanges,
15
+ createAgentWorktree,
16
+ hasWorktreeChanges,
17
+ removeAgentWorktree,
18
+ } from '../agent/worktree.js';
19
+
20
+ const enterSchema = z.object({
21
+ name: z
22
+ .string()
23
+ .regex(/^[a-zA-Z0-9._-]{1,48}$/)
24
+ .optional(),
25
+ });
26
+ const exitSchema = z.object({ action: z.enum(['apply', 'keep', 'discard']) });
27
+ async function persist(
28
+ ctx: ToolCallContext,
29
+ state: SessionState['activeWorktree'],
30
+ ) {
31
+ await writeRuntimeJson(join(sessionRuntimeDir(ctx), 'worktree.json'), {
32
+ active: state ?? null,
33
+ });
34
+ }
35
+ export async function hydrateSessionWorktree(
36
+ ctx: ToolCallContext,
37
+ ): Promise<void> {
38
+ if (!ctx.sessionState || ctx.sessionState.activeWorktree) return;
39
+ const saved = await readRuntimeJson<{
40
+ active?: NonNullable<SessionState['activeWorktree']> | null;
41
+ }>(join(sessionRuntimeDir(ctx), 'worktree.json'), {});
42
+ if (saved.active) ctx.sessionState.activeWorktree = saved.active;
43
+ }
44
+ async function enter(
45
+ input: z.infer<typeof enterSchema>,
46
+ ctx: ToolCallContext,
47
+ ): Promise<ToolResult> {
48
+ const state = ctx.sessionState;
49
+ if (!state) return { ok: false, error: 'EnterWorktree 需要会话状态' };
50
+ if (state.activeWorktree)
51
+ return {
52
+ ok: true,
53
+ content: `当前已在 worktree ${state.activeWorktree.path}`,
54
+ };
55
+ const slug = `session-${input.name ?? randomUUID().slice(0, 8)}`;
56
+ const wt = await createAgentWorktree(slug, ctx.cwd);
57
+ if (!wt.ok) return wt;
58
+ state.activeWorktree = {
59
+ id: slug,
60
+ path: wt.path,
61
+ branch: wt.branch,
62
+ baseSha: wt.baseSha,
63
+ gitRoot: wt.gitRoot,
64
+ };
65
+ await persist(ctx, state.activeWorktree);
66
+ return {
67
+ ok: true,
68
+ content: `已进入主 Agent 隔离 worktree:${wt.path}\n分支:${wt.branch}\n后续工具调用立即使用该目录。`,
69
+ };
70
+ }
71
+ async function exit(
72
+ input: z.infer<typeof exitSchema>,
73
+ ctx: ToolCallContext,
74
+ ): Promise<ToolResult> {
75
+ const state = ctx.sessionState,
76
+ wt = state?.activeWorktree;
77
+ if (!state || !wt) return { ok: false, error: '当前会话没有活动 worktree' };
78
+ if (input.action === 'keep') {
79
+ state.activeWorktree = undefined;
80
+ await persist(ctx, undefined);
81
+ return {
82
+ ok: true,
83
+ content: `已退出有效 cwd,但保留 worktree:${wt.path}\n分支:${wt.branch}`,
84
+ };
85
+ }
86
+ const changed = await hasWorktreeChanges(wt.path, wt.baseSha);
87
+ if (input.action === 'discard' && changed) {
88
+ const committed = await commitWorktreeChanges(
89
+ wt.path,
90
+ `archive: preserve discarded session ${wt.id}`,
91
+ );
92
+ if (committed.ok) {
93
+ state.activeWorktree = undefined;
94
+ await persist(ctx, undefined);
95
+ }
96
+ return committed.ok
97
+ ? {
98
+ ok: true,
99
+ content: `检测到成果,未永久删除。已归档到分支 ${wt.branch},worktree 保留在 ${wt.path}。`,
100
+ }
101
+ : {
102
+ ok: false,
103
+ error: `无法安全归档,worktree 保持活动:${committed.error}`,
104
+ };
105
+ }
106
+ if (input.action === 'discard') {
107
+ await removeAgentWorktree(wt.path, wt.branch, wt.gitRoot);
108
+ state.activeWorktree = undefined;
109
+ await persist(ctx, undefined);
110
+ return {
111
+ ok: true,
112
+ content: 'worktree 无改动,已通过 Git worktree 管理安全清理。',
113
+ };
114
+ }
115
+ const committed = await commitWorktreeChanges(
116
+ wt.path,
117
+ `minimal-agent: apply session ${wt.id}`,
118
+ );
119
+ if (!committed.ok)
120
+ return {
121
+ ok: false,
122
+ error: `提交隔离改动失败,worktree 保持活动:${committed.error}`,
123
+ };
124
+ const applied = await applyAgentWorktree(wt.gitRoot, wt.id);
125
+ if (!applied.ok)
126
+ return {
127
+ ok: false,
128
+ error: `应用检查失败,worktree 保持活动:${applied.error}`,
129
+ };
130
+ state.activeWorktree = undefined;
131
+ await persist(ctx, undefined);
132
+ return {
133
+ ok: true,
134
+ content: `已通过 git apply --check 并将变更应用到原工作区;未自动提交。`,
135
+ };
136
+ }
137
+ export const enterWorktreeTool: Tool<z.infer<typeof enterSchema>> = {
138
+ name: 'EnterWorktree',
139
+ description:
140
+ 'Creates and enters a session-scoped Git worktree for the main Agent. Later tool calls use it immediately while project memory keeps the original workspace identity.',
141
+ inputSchema: enterSchema,
142
+ parameters: toToolParameters(enterSchema),
143
+ isReadOnly: false,
144
+ isConcurrencySafe: false,
145
+ call: async () => ({ ok: false, error: 'requires session context' }),
146
+ callWithContext: (i, _s, c) => enter(i, c),
147
+ };
148
+ export const exitWorktreeTool: Tool<z.infer<typeof exitSchema>> = {
149
+ name: 'ExitWorktree',
150
+ description:
151
+ 'Leaves the current session worktree. apply checks and applies its patch to the original workspace; keep preserves it; discard never destroys uncommitted results and archives changed work.',
152
+ inputSchema: exitSchema,
153
+ parameters: toToolParameters(exitSchema),
154
+ isReadOnly: false,
155
+ isConcurrencySafe: false,
156
+ call: async () => ({ ok: false, error: 'requires session context' }),
157
+ callWithContext: (i, _s, c) => exit(i, c),
158
+ };