minimal-agent 0.13.0 → 0.15.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 (474) hide show
  1. package/README.md +6 -5
  2. package/package.json +60 -4
  3. package/plugins/computer_use/.claude-plugin/plugin.json +1 -1
  4. package/plugins/cron-runner/src/commands.js +4 -4
  5. package/plugins/cron-runner/src/commands.ts +4 -4
  6. package/plugins/workflow-runner/.claude-plugin/plugin.json +2 -2
  7. package/plugins/workflow-runner/commands/workflow.md +57 -90
  8. package/plugins/workflow-runner/commands/workflows.md +4 -4
  9. package/plugins/workflow-runner/plugin.js +24 -13
  10. package/plugins/workflow-runner/plugin.ts +28 -13
  11. package/plugins/workflow-runner/src/discovery.js +160 -0
  12. package/plugins/workflow-runner/src/discovery.ts +194 -0
  13. package/plugins/workflow-runner/src/goalAnchor.js +53 -0
  14. package/plugins/workflow-runner/src/goalAnchor.ts +59 -0
  15. package/plugins/workflow-runner/src/index.js +197 -206
  16. package/plugins/workflow-runner/src/index.ts +248 -249
  17. package/plugins/workflow-runner/src/inputCoercion.js +40 -0
  18. package/plugins/workflow-runner/src/inputCoercion.ts +43 -0
  19. package/plugins/workflow-runner/src/journal.js +224 -0
  20. package/plugins/workflow-runner/src/journal.ts +274 -0
  21. package/plugins/workflow-runner/src/jsonSchema.js +132 -0
  22. package/plugins/workflow-runner/src/jsonSchema.ts +162 -0
  23. package/plugins/workflow-runner/src/moduleResolution.js +64 -0
  24. package/plugins/workflow-runner/src/moduleResolution.ts +71 -0
  25. package/plugins/workflow-runner/src/resourceInputs.js +220 -0
  26. package/plugins/workflow-runner/src/resourceInputs.ts +300 -0
  27. package/plugins/workflow-runner/src/runner.js +400 -489
  28. package/plugins/workflow-runner/src/runner.ts +488 -560
  29. package/plugins/workflow-runner/src/runtime/config.js +46 -0
  30. package/plugins/workflow-runner/src/runtime/config.ts +69 -0
  31. package/plugins/workflow-runner/src/runtime/context.js +1304 -0
  32. package/plugins/workflow-runner/src/runtime/context.ts +1786 -0
  33. package/plugins/workflow-runner/src/runtime/exec.js +34 -0
  34. package/plugins/workflow-runner/src/runtime/exec.ts +53 -0
  35. package/plugins/workflow-runner/src/runtime/flow.js +8 -0
  36. package/plugins/workflow-runner/src/runtime/flow.ts +12 -0
  37. package/plugins/workflow-runner/src/runtime/fs.js +27 -0
  38. package/plugins/workflow-runner/src/runtime/fs.ts +41 -0
  39. package/plugins/workflow-runner/src/runtime/model.js +6 -0
  40. package/plugins/workflow-runner/src/runtime/model.ts +8 -0
  41. package/plugins/workflow-runner/src/runtime/output.js +7 -0
  42. package/plugins/workflow-runner/src/runtime/output.ts +21 -0
  43. package/plugins/workflow-runner/src/runtime/scheduler.js +141 -0
  44. package/plugins/workflow-runner/src/runtime/scheduler.ts +166 -0
  45. package/plugins/workflow-runner/src/runtime/state.js +16 -0
  46. package/plugins/workflow-runner/src/runtime/state.ts +19 -0
  47. package/plugins/workflow-runner/src/runtime/tools.js +3 -0
  48. package/plugins/workflow-runner/src/runtime/tools.ts +6 -0
  49. package/plugins/workflow-runner/src/sandbox.js +141 -0
  50. package/plugins/workflow-runner/src/sandbox.ts +182 -0
  51. package/plugins/workflow-runner/src/scriptGuard.d.mts +38 -0
  52. package/plugins/workflow-runner/src/scriptGuard.mjs +449 -0
  53. package/plugins/workflow-runner/src/taskIdentity.js +151 -307
  54. package/plugins/workflow-runner/src/taskIdentity.ts +207 -355
  55. package/plugins/workflow-runner/src/toolRuntime.js +29 -8
  56. package/plugins/workflow-runner/src/toolRuntime.ts +36 -11
  57. package/plugins/workflow-runner/src/types.js +7 -211
  58. package/plugins/workflow-runner/src/types.ts +154 -623
  59. package/plugins/workflow-runner/src/util.js +47 -0
  60. package/plugins/workflow-runner/src/util.ts +51 -0
  61. package/plugins/workflow-runner/src/workflowContext.js +20 -0
  62. package/plugins/workflow-runner/src/workflowContext.ts +58 -0
  63. package/plugins/workflow-runner/src/workflowDependencies.js +36 -0
  64. package/plugins/workflow-runner/src/workflowDependencies.ts +59 -0
  65. package/plugins/workflow-runner/src/workflowFingerprint.js +118 -0
  66. package/plugins/workflow-runner/src/workflowFingerprint.ts +122 -0
  67. package/plugins/workflow-runner/src/workflowState.js +474 -802
  68. package/plugins/workflow-runner/src/workflowState.ts +575 -970
  69. package/plugins/workflow-runner/test/api.test.ts +223 -0
  70. package/plugins/workflow-runner/test/apiCapabilities.test.ts +614 -0
  71. package/plugins/workflow-runner/test/apiConcurrencyGate.test.ts +104 -0
  72. package/plugins/workflow-runner/test/apiEcho.test.ts +210 -0
  73. package/plugins/workflow-runner/test/apiReadText.test.ts +178 -0
  74. package/plugins/workflow-runner/test/apiResourceLedger.test.ts +184 -0
  75. package/plugins/workflow-runner/test/childWorkflow.test.ts +304 -0
  76. package/plugins/workflow-runner/test/discovery.test.ts +234 -0
  77. package/plugins/workflow-runner/test/goalAnchor.test.ts +106 -0
  78. package/plugins/workflow-runner/test/goalController.test.ts +317 -0
  79. package/plugins/workflow-runner/test/journalLanes.test.ts +198 -0
  80. package/plugins/workflow-runner/test/listResources.test.ts +106 -0
  81. package/plugins/workflow-runner/test/resourceInputs.test.ts +294 -0
  82. package/plugins/workflow-runner/test/sandbox.test.ts +126 -0
  83. package/plugins/workflow-runner/test/scheduler.test.ts +70 -0
  84. package/plugins/workflow-runner/test/scriptGuard.test.ts +276 -0
  85. package/plugins/workflow-runner/test/skillDocSync.test.ts +78 -0
  86. package/plugins/workflow-runner/test/taskIdentity.test.ts +288 -179
  87. package/plugins/workflow-runner/test/workflowFingerprint.test.ts +106 -0
  88. package/plugins/workflow-runner/test/workflowState.test.ts +429 -0
  89. package/skills/pptx/examples/assets/cover-bg.svg +23 -0
  90. package/skills/pptx/examples/assets/icon-spark.svg +5 -0
  91. package/skills/ui-design/SKILL.md +5 -2
  92. package/skills/ui-design/references/layout-composition.md +1 -1
  93. package/skills/workflow-creator/SKILL.md +344 -0
  94. package/skills/workflow-creator/assets/template/workflow.mjs +48 -0
  95. package/skills/workflow-creator/references/api.md +216 -0
  96. package/skills/workflow-creator/references/migration.md +103 -0
  97. package/skills/workflow-creator/references/patterns.md +779 -0
  98. package/skills/workflow-creator/scripts/list-resources.mjs +205 -0
  99. package/skills/workflow-creator/scripts/scaffold.mjs +148 -0
  100. package/skills/workflow-creator/scripts/validate.mjs +275 -0
  101. package/skills/workflow-creator/scripts/workflow-creator.test.mjs +82 -0
  102. package/src/advisor/advisorCoordinator.js +536 -0
  103. package/src/advisor/advisorCoordinator.ts +693 -0
  104. package/src/cli/configMenu.tsx +0 -1
  105. package/src/cli/print.js +27 -6
  106. package/src/cli/print.ts +48 -4
  107. package/src/cli/quickModelSetup.js +12 -1
  108. package/src/cli/quickModelSetup.tsx +15 -3
  109. package/src/cli/streamJson.js +5 -6
  110. package/src/cli/streamJson.ts +8 -4
  111. package/src/cli/wizards/advisorWizard.js +4 -2
  112. package/src/cli/wizards/advisorWizard.tsx +8 -2
  113. package/src/cli/wizards/contextAdvisorWizard.js +5 -4
  114. package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
  115. package/src/cli/wizards/providerPresets.js +18 -8
  116. package/src/cli/wizards/providerPresets.ts +18 -8
  117. package/src/collaboration/taskFlow.js +115 -0
  118. package/src/collaboration/taskFlow.ts +169 -0
  119. package/src/config/configDefaults.js +41 -1
  120. package/src/config/configDefaults.ts +43 -1
  121. package/src/config/configDiagnostics.ts +2 -2
  122. package/src/config/configFile.js +40 -9
  123. package/src/config/configFile.ts +60 -11
  124. package/src/config/configService.js +419 -74
  125. package/src/config/configService.ts +703 -145
  126. package/src/config/numericLimits.js +22 -0
  127. package/src/config/numericLimits.ts +24 -0
  128. package/src/config.js +1 -0
  129. package/src/config.ts +3 -2
  130. package/src/context/budgetPlan.js +1 -1
  131. package/src/context/budgetPlan.ts +1 -1
  132. package/src/context/compact.js +7 -2
  133. package/src/context/compact.ts +9 -2
  134. package/src/context/microCompactLite.js +212 -13
  135. package/src/context/microCompactLite.ts +261 -12
  136. package/src/context/sessionRegistry.js +8 -1
  137. package/src/context/sessionRegistry.ts +18 -5
  138. package/src/context/toolResultArchive.js +72 -0
  139. package/src/context/toolResultArchive.ts +95 -0
  140. package/src/goal/errors.js +8 -0
  141. package/src/goal/errors.ts +18 -0
  142. package/src/goal/goalRuntime.js +344 -0
  143. package/src/goal/goalRuntime.ts +466 -0
  144. package/src/goal/goalStore.js +200 -0
  145. package/src/goal/goalStore.ts +219 -0
  146. package/src/goal/index.js +4 -0
  147. package/src/goal/index.ts +4 -0
  148. package/src/goal/statusMapping.js +71 -0
  149. package/src/goal/statusMapping.ts +95 -0
  150. package/src/goal/types.js +7 -0
  151. package/src/goal/types.ts +179 -0
  152. package/src/goal/workflowController.js +306 -0
  153. package/src/goal/workflowController.ts +360 -0
  154. package/src/harness/evidenceLedger.js +2 -0
  155. package/src/harness/evidenceLedger.ts +1 -0
  156. package/src/harness/stallGuard.js +9 -3
  157. package/src/harness/stallGuard.ts +7 -3
  158. package/src/images/imageResolver.js +161 -0
  159. package/src/images/imageResolver.ts +189 -0
  160. package/src/infra/verification.js +34 -5
  161. package/src/infra/verification.ts +39 -4
  162. package/src/llm/client.js +79 -21
  163. package/src/llm/client.ts +182 -35
  164. package/src/llm/gatewayClient.js +201 -0
  165. package/src/llm/gatewayClient.ts +299 -0
  166. package/src/llm/messageProvenance.js +46 -0
  167. package/src/llm/messageProvenance.ts +58 -0
  168. package/src/llm/modelProvider.js +1 -0
  169. package/src/llm/modelProvider.ts +22 -0
  170. package/src/llm/providers/anthropicFormat.js +108 -1
  171. package/src/llm/providers/anthropicFormat.ts +115 -4
  172. package/src/llm/providers/openaiFormat.js +9 -0
  173. package/src/llm/providers/openaiFormat.ts +12 -3
  174. package/src/loop.js +328 -55
  175. package/src/loop.ts +382 -58
  176. package/src/main.js +4 -1
  177. package/src/main.tsx +4 -1
  178. package/src/managedExecution/index.js +2 -0
  179. package/src/managedExecution/index.ts +2 -0
  180. package/src/managedExecution/registry.js +15 -0
  181. package/src/managedExecution/registry.ts +20 -0
  182. package/src/managedExecution/types.js +1 -0
  183. package/src/managedExecution/types.ts +86 -0
  184. package/src/modelRef.js +9 -0
  185. package/src/modelRef.ts +31 -0
  186. package/src/multimodal.js +14 -28
  187. package/src/multimodal.ts +17 -33
  188. package/src/net/lanDiscovery.js +65 -0
  189. package/src/net/lanDiscovery.ts +82 -0
  190. package/src/plugin-sdk.js +28 -3
  191. package/src/plugin-sdk.ts +39 -6
  192. package/src/plugins/pluginApi.ts +16 -1
  193. package/src/plugins/pluginLoader.js +4 -0
  194. package/src/plugins/pluginLoader.ts +6 -0
  195. package/src/plugins/pluginRunner.js +139 -7
  196. package/src/plugins/pluginRunner.ts +173 -9
  197. package/src/plugins/slashFallback.js +113 -0
  198. package/src/plugins/slashFallback.ts +137 -0
  199. package/src/prompts/policyRegistry.js +12 -32
  200. package/src/prompts/policyRegistry.ts +15 -32
  201. package/src/prompts/promptAssembly.js +103 -12
  202. package/src/prompts/promptAssembly.ts +114 -12
  203. package/src/prompts/skillList.js +21 -3
  204. package/src/prompts/skillList.ts +27 -2
  205. package/src/prompts/stableSystemPrompt.js +18 -0
  206. package/src/prompts/stableSystemPrompt.ts +33 -0
  207. package/src/runtime/agentRuntimeContext.js +8 -2
  208. package/src/runtime/agentRuntimeContext.ts +17 -4
  209. package/src/session/runAgentTurn.js +78 -12
  210. package/src/session/runAgentTurn.ts +105 -23
  211. package/src/session/runTurn.js +10 -9
  212. package/src/session/runTurn.ts +17 -8
  213. package/src/session/sessionState.ts +2 -0
  214. package/src/team/auth.js +186 -0
  215. package/src/team/auth.ts +298 -0
  216. package/src/team/cli.js +105 -0
  217. package/src/team/cli.ts +122 -0
  218. package/src/team/onlineToolContract.js +64 -0
  219. package/src/team/onlineToolContract.ts +109 -0
  220. package/src/team/toolPolicy.js +36 -0
  221. package/src/team/toolPolicy.ts +75 -0
  222. package/src/tools/advisor/advisor.js +115 -50
  223. package/src/tools/advisor/advisor.ts +124 -51
  224. package/src/tools/advisor/advisorDecision.js +71 -0
  225. package/src/tools/advisor/advisorDecision.ts +85 -0
  226. package/src/tools/agent/agent.js +18 -5
  227. package/src/tools/agent/agent.ts +21 -7
  228. package/src/tools/agent/agentControl.js +246 -0
  229. package/src/tools/agent/agentControl.ts +284 -0
  230. package/src/tools/agent/agentTaskService.js +40 -1
  231. package/src/tools/agent/agentTaskService.ts +44 -1
  232. package/src/tools/agent/agentTypes.js +14 -2
  233. package/src/tools/agent/agentTypes.ts +15 -2
  234. package/src/tools/applypatch/applyPatch.js +362 -0
  235. package/src/tools/applypatch/applyPatch.ts +428 -0
  236. package/src/tools/bash/bash.js +22 -15
  237. package/src/tools/bash/bash.ts +23 -17
  238. package/src/tools/capabilities.js +10 -5
  239. package/src/tools/capabilities.ts +10 -5
  240. package/src/tools/computeruse/computerIntent.js +32 -0
  241. package/src/tools/computeruse/computerIntent.ts +46 -0
  242. package/src/tools/computeruse/telemetryLog.js +12 -0
  243. package/src/tools/computeruse/telemetryLog.ts +16 -0
  244. package/src/tools/computeruse/vision/telemetry.js +1 -0
  245. package/src/tools/computeruse/vision/telemetry.ts +1 -0
  246. package/src/tools/effectiveToolSet.js +4 -0
  247. package/src/tools/effectiveToolSet.ts +4 -0
  248. package/src/tools/index.js +21 -2
  249. package/src/tools/index.ts +33 -2
  250. package/src/tools/presentresult/presentresult.js +6 -15
  251. package/src/tools/presentresult/presentresult.ts +6 -15
  252. package/src/tools/read/read.js +62 -9
  253. package/src/tools/read/read.ts +63 -9
  254. package/src/tools/shared/fileUtils.js +1 -2
  255. package/src/tools/shared/fileUtils.ts +1 -2
  256. package/src/tools/shared/toolOutputStore.js +23 -1
  257. package/src/tools/shared/toolOutputStore.ts +22 -1
  258. package/src/tools/skill/skill.js +9 -3
  259. package/src/tools/skill/skill.ts +8 -4
  260. package/src/tools/toolPromptGuides.js +125 -0
  261. package/src/tools/toolPromptGuides.ts +146 -0
  262. package/src/tools/webbrowser/agentBrowserPath.js +19 -9
  263. package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
  264. package/src/tools/webbrowser/browser.js +27 -11
  265. package/src/tools/webbrowser/browser.ts +68 -24
  266. package/src/tools/webbrowser/browserAutomation.js +329 -0
  267. package/src/tools/webbrowser/browserAutomation.ts +467 -0
  268. package/src/tools/webbrowser/browserAxState.js +97 -0
  269. package/src/tools/webbrowser/browserAxState.ts +142 -0
  270. package/src/tools/webbrowser/browserBatch.js +1578 -0
  271. package/src/tools/webbrowser/browserBatch.ts +2382 -0
  272. package/src/tools/webbrowser/browserCdp.js +208 -0
  273. package/src/tools/webbrowser/browserCdp.ts +255 -0
  274. package/src/tools/webbrowser/browserConditions.js +24 -0
  275. package/src/tools/webbrowser/browserConditions.ts +45 -0
  276. package/src/tools/webbrowser/browserContent.js +281 -0
  277. package/src/tools/webbrowser/browserContent.ts +438 -0
  278. package/src/tools/webbrowser/browserControl.js +131 -34
  279. package/src/tools/webbrowser/browserControl.ts +210 -56
  280. package/src/tools/webbrowser/browserDaemon.js +22 -14
  281. package/src/tools/webbrowser/browserDaemon.ts +54 -21
  282. package/src/tools/webbrowser/browserFrames.js +47 -0
  283. package/src/tools/webbrowser/browserFrames.ts +54 -0
  284. package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
  285. package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
  286. package/src/tools/webbrowser/browserLocator.js +140 -0
  287. package/src/tools/webbrowser/browserLocator.ts +194 -0
  288. package/src/tools/webbrowser/browserOutcome.js +10 -17
  289. package/src/tools/webbrowser/browserOutcome.ts +48 -31
  290. package/src/tools/webbrowser/browserRecovery.js +58 -0
  291. package/src/tools/webbrowser/browserRecovery.ts +83 -0
  292. package/src/tools/webbrowser/browserRunRegistry.js +35 -3
  293. package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
  294. package/src/tools/webbrowser/browserService.js +28 -2
  295. package/src/tools/webbrowser/browserService.ts +49 -9
  296. package/src/tools/webbrowser/browserStream.js +132 -33
  297. package/src/tools/webbrowser/browserStream.ts +224 -50
  298. package/src/tools/webbrowser/browserTabs.js +48 -15
  299. package/src/tools/webbrowser/browserTabs.ts +178 -96
  300. package/src/tools/webbrowser/webbrowser.js +679 -144
  301. package/src/tools/webbrowser/webbrowser.ts +975 -236
  302. package/src/tools/webfetch/preapproved.js +0 -2
  303. package/src/tools/webfetch/preapproved.ts +0 -2
  304. package/src/tools/websearch/websearch.js +129 -8
  305. package/src/tools/websearch/websearch.ts +138 -6
  306. package/src/types.ts +459 -40
  307. package/src/ui/App.js +377 -58
  308. package/src/ui/App.tsx +576 -111
  309. package/src/ui/LiveArea.js +14 -8
  310. package/src/ui/LiveArea.tsx +14 -10
  311. package/src/ui/MessageList.js +63 -20
  312. package/src/ui/MessageList.tsx +101 -16
  313. package/src/ui/ModelPicker.js +7 -4
  314. package/src/ui/ModelPicker.tsx +55 -8
  315. package/src/ui/hooks/useChat.js +152 -163
  316. package/src/ui/hooks/useChat.ts +396 -334
  317. package/src/ui/loginCommand.js +56 -0
  318. package/src/ui/loginCommand.ts +63 -0
  319. package/src/ui/toolProgress.js +41 -0
  320. package/src/ui/toolProgress.ts +44 -0
  321. package/src/web/browserBridge.js +20 -2
  322. package/src/web/browserBridge.ts +20 -2
  323. package/src/web/protocol.ts +1897 -194
  324. package/workflows/adaptive-research/workflow.mjs +86 -0
  325. package/workflows/e2e-capabilities/workflow.mjs +102 -0
  326. package/workflows/e2e-llm/workflow.mjs +52 -0
  327. package/workflows/e2e-smoke/workflow.mjs +59 -0
  328. package/workflows/e2e-vision-schema/README.md +48 -0
  329. package/workflows/e2e-vision-schema/workflow.mjs +149 -0
  330. package/workflows/e2e-write-greet/workflow.mjs +37 -0
  331. package/workflows/file-census/README.md +14 -0
  332. package/workflows/file-census/scripts/.gitkeep +2 -0
  333. package/workflows/file-census/workflow.mjs +110 -0
  334. package/workflows/goal/README.md +166 -0
  335. package/workflows/goal/prompts/audit.md +57 -0
  336. package/workflows/goal/prompts/contract.md +56 -0
  337. package/workflows/goal/prompts/iterate.md +37 -0
  338. package/workflows/goal/workflow.mjs +501 -0
  339. package/workflows/illustrate/README.md +90 -0
  340. package/workflows/illustrate/assets/engines.json +20 -0
  341. package/workflows/illustrate/assets/extract-baidu.js +21 -0
  342. package/workflows/illustrate/assets/extract-bing.js +33 -0
  343. package/workflows/illustrate/assets/extract-google.js +31 -0
  344. package/workflows/illustrate/workflow.mjs +301 -0
  345. package/workflows/plan/workflow.mjs +389 -0
  346. package/workflows/question-crops/README.md +35 -0
  347. package/workflows/question-crops/prompts/inventory.md +23 -0
  348. package/workflows/question-crops/scripts/image-ops.mjs +305 -0
  349. package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
  350. package/workflows/question-crops/workflow.mjs +172 -0
  351. package/workflows/ralph-loop/workflow.mjs +162 -0
  352. package/workflows/research/README.md +74 -0
  353. package/workflows/research/prompts/s0-goal.md +43 -0
  354. package/workflows/research/prompts/s1-early-exit.md +22 -0
  355. package/workflows/research/prompts/s1-map.md +58 -0
  356. package/workflows/research/prompts/s2-options.md +53 -0
  357. package/workflows/research/prompts/s3-deep-dive.md +56 -0
  358. package/workflows/research/prompts/s4-verify.md +74 -0
  359. package/workflows/research/prompts/s5-synthesis.md +81 -0
  360. package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
  361. package/workflows/research/prompts/s6-package.md +32 -0
  362. package/workflows/research/scripts/build-report.mjs +98 -0
  363. package/workflows/research/workflow.mjs +288 -0
  364. package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
  365. package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
  366. package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
  367. package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
  368. package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
  369. package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
  370. package/workflows/wechat-reading-shots/workflow.mjs +266 -0
  371. package/workflows/wrong-question-docx/README.md +55 -0
  372. package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
  373. package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
  374. package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
  375. package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
  376. package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
  377. package/workflows/wrong-question-docx/workflow.mjs +485 -0
  378. package/plugins/workflow-runner/src/agentCommon.js +0 -354
  379. package/plugins/workflow-runner/src/agentCommon.ts +0 -435
  380. package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
  381. package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
  382. package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
  383. package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
  384. package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
  385. package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
  386. package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
  387. package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
  388. package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
  389. package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
  390. package/plugins/workflow-runner/src/dslManifest.js +0 -72
  391. package/plugins/workflow-runner/src/dslManifest.ts +0 -127
  392. package/plugins/workflow-runner/src/expressions.js +0 -639
  393. package/plugins/workflow-runner/src/expressions.ts +0 -640
  394. package/plugins/workflow-runner/src/loader.js +0 -573
  395. package/plugins/workflow-runner/src/loader.ts +0 -721
  396. package/plugins/workflow-runner/src/multimodal.js +0 -38
  397. package/plugins/workflow-runner/src/multimodal.ts +0 -64
  398. package/plugins/workflow-runner/src/recovery.js +0 -126
  399. package/plugins/workflow-runner/src/recovery.ts +0 -156
  400. package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
  401. package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
  402. package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -42
  403. package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -52
  404. package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
  405. package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
  406. package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
  407. package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
  408. package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
  409. package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
  410. package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
  411. package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
  412. package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -227
  413. package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -274
  414. package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -61
  415. package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -72
  416. package/plugins/workflow-runner/src/stepPipeline.js +0 -277
  417. package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
  418. package/plugins/workflow-runner/test/agent.test.ts +0 -587
  419. package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
  420. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
  421. package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
  422. package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -167
  423. package/plugins/workflow-runner/test/context-files.test.ts +0 -320
  424. package/plugins/workflow-runner/test/e2e.test.ts +0 -370
  425. package/plugins/workflow-runner/test/e2eNewLayout.test.ts +0 -314
  426. package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -234
  427. package/plugins/workflow-runner/test/expressions.test.ts +0 -439
  428. package/plugins/workflow-runner/test/foundation.test.ts +0 -126
  429. package/plugins/workflow-runner/test/graceful.test.ts +0 -139
  430. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
  431. package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
  432. package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
  433. package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
  434. package/plugins/workflow-runner/test/loader.test.ts +0 -617
  435. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
  436. package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
  437. package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
  438. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -106
  439. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
  440. package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
  441. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -221
  442. package/plugins/workflow-runner/test/recovery.test.ts +0 -265
  443. package/plugins/workflow-runner/test/research.load.test.ts +0 -328
  444. package/plugins/workflow-runner/test/runner.test.ts +0 -911
  445. package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -436
  446. package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
  447. package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -198
  448. package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
  449. package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -354
  450. package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -324
  451. package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +0 -221
  452. package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +0 -29
  453. package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +0 -168
  454. package/plugins/workflow-runner/test/webppt.load.test.ts +0 -250
  455. package/plugins/workflow-runner/test/word.load.test.ts +0 -208
  456. package/plugins/workflow-runner/test/workflows.smoke.test.ts +0 -76
  457. package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +0 -207
  458. package/src/advisorState.js +0 -22
  459. package/src/cli/configWizard.js +0 -293
  460. package/src/tools/toolProgressBridge.js +0 -48
  461. package/workflows/adaptive-research.yaml +0 -50
  462. package/workflows/book-review-short.yaml +0 -125
  463. package/workflows/e2e-write-greet.yaml +0 -31
  464. package/workflows/illustrate.yaml +0 -227
  465. package/workflows/plan.yaml +0 -470
  466. package/workflows/ppt.yaml +0 -1670
  467. package/workflows/ralph-loop.yaml +0 -201
  468. package/workflows/research.yaml +0 -873
  469. package/workflows/schema.json +0 -176
  470. package/workflows/webppt.yaml +0 -496
  471. package/workflows/wechat-reading-shots.yaml +0 -315
  472. package/workflows/word.yaml +0 -720
  473. package/workflows/youtube-shorts.yaml +0 -202
  474. /package/workflows/{research.md → research/DESIGN.md} +0 -0
@@ -1,76 +0,0 @@
1
- /**
2
- * ============================================================
3
- * test/workflows.smoke.test.ts
4
- * ------------------------------------------------------------
5
- * 内置工作流「解析+校验」冒烟测试 —— 守护「引擎对所有 workflows/*.yaml 的通用支持」。
6
- *
7
- * 为什么需要它(真实缺口):
8
- * `listWorkflows()` 对损坏 yaml 是**静默跳过**(loader.ts catch→warn→continue),
9
- * 而既有 loader 单测只显式校验了 book-review-short.yaml 一个内置工作流。
10
- * 于是若某次引擎/loader/schema 改动破坏了 plan / youtube-shorts / adaptive-research /
11
- * e2e-write-greet 等的结构,**没有任何测试会失败**——它只会被悄悄忽略。
12
- * 本文件把「每个内置工作流都能 parse + validate 通过」锁成不变量:任一被改坏即红。
13
- *
14
- * 隔离性(同 loader.test.ts 的教训):
15
- * 直接定位 packageRoot 的 workflows 目录 + `parseWorkflowFile()` 逐个解析,
16
- * **零依赖 getWorkingDir() 全局状态**,避免其它测试文件经 mock.module 留下的污染。
17
- * ============================================================
18
- */
19
-
20
- import { describe, expect, it } from 'bun:test';
21
- import { readdirSync } from 'node:fs';
22
- import { join } from 'node:path';
23
-
24
- import { parseWorkflowFile } from '../src/loader.js';
25
-
26
- // packageRoot 下的 workflows 目录(不依赖 getWorkingDir)。
27
- // import.meta.dir = plugins/workflow-runner/test;向上三级到 minimal-agent 根。
28
- // 兼容 Windows:用 [/\\] 同时匹配两种路径分隔符(同 loader.test.ts:94 的教训)。
29
- const WORKFLOWS_DIR = join(
30
- import.meta.dir.replace(/[/\\]test$/, ''), // plugins/workflow-runner
31
- '..', // plugins
32
- '..', // minimal-agent 根
33
- 'workflows',
34
- );
35
-
36
- // 内置工作流的「全集快照」:意外删除/改名任一个即红(防止悄悄少掉一个工作流)。
37
- const EXPECTED_WORKFLOWS = [
38
- 'adaptive-research',
39
- 'book-review-short',
40
- 'e2e-write-greet',
41
- 'plan',
42
- 'ppt',
43
- 'ralph-loop',
44
- 'webppt',
45
- 'word',
46
- 'youtube-shorts',
47
- ].sort();
48
-
49
- function yamlFiles(): string[] {
50
- return readdirSync(WORKFLOWS_DIR)
51
- .filter((f) => f.endsWith('.yaml') || f.endsWith('.yml'))
52
- .sort();
53
- }
54
-
55
- describe('内置 workflows/*.yaml 解析+校验冒烟', () => {
56
- // 逐个文件成测:哪个被改坏,失败信息直接点名是哪个工作流。
57
- for (const file of yamlFiles()) {
58
- it(`${file} 能被 parseWorkflowFile 解析且通过校验`, async () => {
59
- const def = await parseWorkflowFile(join(WORKFLOWS_DIR, file));
60
- expect(typeof def.name).toBe('string');
61
- expect(def.name.length).toBeGreaterThan(0);
62
- expect(def.description.length).toBeGreaterThan(0);
63
- expect(def.steps.length).toBeGreaterThan(0);
64
- });
65
- }
66
-
67
- it('内置工作流全集齐全(没有被悄悄删除/改名)', async () => {
68
- const defs = await Promise.all(
69
- yamlFiles().map((f) => parseWorkflowFile(join(WORKFLOWS_DIR, f))),
70
- );
71
- const names = defs.map((d) => d.name).sort();
72
- for (const expected of EXPECTED_WORKFLOWS) {
73
- expect(names).toContain(expected);
74
- }
75
- });
76
- });
@@ -1,207 +0,0 @@
1
- /**
2
- * ============================================================
3
- * 真实 yaml 的护栏条件必须真的能判真、也真的能判假
4
- * ------------------------------------------------------------
5
- * 护栏(assert / when)有一个非常隐蔽的失效模式:**永远判假,且不报任何错**。
6
- * 用户看到的是 onFail 里那段业务文案,与真实原因毫无关系,排查方向被彻底带偏。
7
- *
8
- * 实测踩到的两个源头,都只在真机跑到那一步才暴露,单测不覆盖就查不出来:
9
- *
10
- * ① **反斜杠被吃掉两层**。表达式引擎的字符串字面量吃一层,YAML 双引号标量再吃一层
11
- * —— 写 '(\w+)' 传到引擎手上变成 '(w+)',正则悄悄失配。
12
- * 对策:正则一律写字符类 [a-z] / [0-9],不用 \w / \d。
13
- *
14
- * ② **用 includes 在自由文本里找关键词会被解释性文字骗过**。
15
- * 实测:模型回「right/pagedown/space 全部无效」,`includes(pager,'right')` 判真放行,
16
- * 于是本该在探针步诚实停下的运行,一路空转到后面才崩。
17
- * 对策:让模型输出 `PAGER=xxx` 协议令牌,用 extract 精确取值。
18
- *
19
- * 所以这个测试直接读**真实 yaml 文件**,用**真实形状的捕获文本**求值每个护栏,
20
- * 正反两面都断言。不自造样本 —— 自造样本正是上面两个 bug 能溜过单测的原因。
21
- * ============================================================
22
- */
23
-
24
- import { describe, expect, test } from 'bun:test';
25
- import { readFileSync } from 'node:fs';
26
- import { join } from 'node:path';
27
- import { parse } from 'yaml';
28
- import { evalExpr } from '../src/expressions.js';
29
- import { VarStack } from '../src/types.js';
30
-
31
- const YAML_PATH = join(
32
- import.meta.dir,
33
- '..',
34
- '..',
35
- '..',
36
- 'workflows',
37
- 'wechat-reading-shots.yaml',
38
- );
39
-
40
- type Step = { id: string; condition?: string; when?: string };
41
- const def = parse(readFileSync(YAML_PATH, 'utf8')) as { steps: Step[] };
42
-
43
- function stepById(id: string): Step {
44
- const found = def.steps.find((s) => s.id === id);
45
- expect(found).toBeDefined();
46
- return found!;
47
- }
48
-
49
- function varsWith(overrides: Record<string, unknown>): VarStack {
50
- const vs = new VarStack();
51
- vs.set('cfg', { book: '某本书', page: 12, shots: 10 });
52
- vs.set('open_state', 'OPEN=ok');
53
- vs.set('cur_page', 'PAGE=11 12');
54
- for (const [k, v] of Object.entries(overrides)) vs.set(k, v);
55
- return vs;
56
- }
57
-
58
- describe('wechat-reading-shots 护栏条件', () => {
59
- test('★ 定位护栏不能被解释性文字骗过(令牌必须精确取值)', () => {
60
- // 真实形状:模型写一大段说明再给结论。若护栏写成 includes(open_state,'ok'),
61
- // 「ok 的路子都走不通」这句话里的 'ok' 会让它判真放行。
62
- const deceptive = '归位、书架、搜索都试过了,ok 的路子都走不通。\n\nOPEN=fail';
63
- expect(
64
- evalExpr(stepById('guard_open').condition!, varsWith({ open_state: deceptive })),
65
- ).toBe(false);
66
- });
67
-
68
- test('★ 定位护栏能从一大段说明文字里取出 OPEN 令牌', () => {
69
- // 反斜杠转义写错时这条会静默判假 —— onFail 会说「没能停到正文页」,
70
- // 与真实原因(正则失配)毫无关系,排查方向被彻底带偏。
71
- const verbose =
72
- '点了书架里的封面,放大镜读到「81 / 116」,已经在正文了。\n\nOPEN=ok';
73
- expect(
74
- evalExpr(stepById('guard_open').condition!, varsWith({ open_state: verbose })),
75
- ).toBe(true);
76
- });
77
-
78
- test('落点护栏:双页对开时目标落在左页或右页都算到位', () => {
79
- const cond = stepById('guard_landing').condition!;
80
- expect(evalExpr(cond, varsWith({ cur_page: 'PAGE=12 13' }))).toBe(true); // 左页命中
81
- expect(evalExpr(cond, varsWith({ cur_page: 'PAGE=11 12' }))).toBe(true); // 右页命中
82
- expect(evalExpr(cond, varsWith({ cur_page: 'PAGE=80 81' }))).toBe(false); // 差得远
83
- expect(evalExpr(cond, varsWith({ cur_page: 'PAGE=0 0' }))).toBe(false); // 读不出来
84
- });
85
-
86
- test('落点护栏不能被「112 里含 12」这类子串匹配蒙混过关', () => {
87
- // includes 写法会在这里判真('PAGE 112 113' 含 '12'),extract 精确取值不会。
88
- expect(
89
- evalExpr(stepById('guard_landing').condition!, varsWith({ cur_page: 'PAGE=112 113' })),
90
- ).toBe(false);
91
- });
92
-
93
- test('所有护栏正则都不含反斜杠转义(\\w/\\d 会被 YAML 吃掉一层)', () => {
94
- // 必须**递归进 loop 的 do[]** —— 循环体里的 when 同样是护栏,
95
- // 只扫顶层会漏掉截图循环的边界判定(那正是最容易写错的地方)。
96
- const collect = (steps: (Step & { do?: Step[] })[]): string[] =>
97
- steps.flatMap((st) => [
98
- ...[st.condition, st.when].filter((e): e is string => typeof e === 'string'),
99
- ...(Array.isArray(st.do) ? collect(st.do as (Step & { do?: Step[] })[]) : []),
100
- ]);
101
- const exprs = collect(def.steps as (Step & { do?: Step[] })[]);
102
- expect(exprs.length).toBeGreaterThan(4);
103
- for (const e of exprs) {
104
- expect(e).not.toContain('\\w');
105
- expect(e).not.toContain('\\d');
106
- expect(e).not.toContain('\\s');
107
- }
108
- });
109
- });
110
-
111
- /**
112
- * ============================================================
113
- * 循环体里 capture 出来的变量必须活到循环之外
114
- * ------------------------------------------------------------
115
- * 真实事故:seek 循环一路把书从第 84 页翻到第 12 页,循环里每轮都 capture
116
- * `cur_page`,最后一轮读到「PAGE=12 13」—— 任务其实已经成功。但 loop 每轮
117
- * `vars.push()` … `vars.pop()`,capture 写进的是**迭代帧**,循环一结束就被弹掉。
118
- * 循环外的 guard_landing 读到空串,报「没能翻到第 12 页(最后读到的页码:)」,
119
- * 把一个刚刚成功的任务判成失败,报错文案还完全指不向真因。
120
- *
121
- * 正确的语义分界:**迭代变量(as / as_idx)按帧作用域,作者显式命名的变量不按。**
122
- * ============================================================
123
- */
124
- describe('VarStack 作用域:迭代变量 vs 作者变量', () => {
125
- test('★ 循环体里 set 的作者变量,pop 之后依然在', () => {
126
- const vs = new VarStack();
127
- vs.pushIteration();
128
- vs.setIteration('i', 3); // 迭代变量
129
- vs.set('cur_page', 'PAGE=12 13'); // capture / set 步写的作者变量
130
- expect(vs.get('i')).toBe(3);
131
- vs.pop();
132
- expect(vs.get('i')).toBeUndefined(); // 迭代变量随帧消失 —— 这是对的
133
- expect(vs.get('cur_page')).toBe('PAGE=12 13'); // 作者变量必须留下
134
- });
135
-
136
- test('嵌套循环:内层写的作者变量穿透到所有循环之外', () => {
137
- const vs = new VarStack();
138
- vs.pushIteration();
139
- vs.pushIteration();
140
- vs.set('hit_edge', true);
141
- vs.pop();
142
- vs.pop();
143
- expect(vs.get('hit_edge')).toBe(true);
144
- });
145
-
146
- test('迭代变量不会互相污染:内层 pop 后外层的值还在', () => {
147
- const vs = new VarStack();
148
- vs.pushIteration();
149
- vs.setIteration('i', 1);
150
- vs.pushIteration();
151
- vs.setIteration('i', 99);
152
- expect(vs.get('i')).toBe(99);
153
- vs.pop();
154
- expect(vs.get('i')).toBe(1);
155
- });
156
-
157
- test('snapshot 里也能看到循环体写的作者变量(落盘/事件用同一份)', () => {
158
- const vs = new VarStack();
159
- vs.pushIteration();
160
- vs.set('cur_page', 'PAGE=12 13');
161
- vs.pop();
162
- expect(vs.snapshot().cur_page).toBe('PAGE=12 13');
163
- });
164
- });
165
-
166
- /**
167
- * ============================================================
168
- * 参数解析必须容忍模型的自由文本
169
- * ------------------------------------------------------------
170
- * 「最后只回复一行 JSON」是**没法强制**的约定。实测模型会在 JSON 前加一句
171
- * 「三项参数都已给出:…」,也可能套 ```json 围栏。
172
- *
173
- * 裸 `parseJson(整段文本)` 一炸,`cfg` 变成 null,下游 guard_params 报
174
- * 「参数没收齐(书名为空…)」—— 而参数其实齐了,是解析被前言撑爆的。
175
- * 又一次「报错文案指不向真因」,这类静默偏航是本项目反复踩的坑。
176
- * ============================================================
177
- */
178
- describe('参数 JSON 解析的容错', () => {
179
- const setStep = def.steps.find((s) => s.id === 'set_params') as unknown as {
180
- set: { cfg: string };
181
- };
182
- /** 取出 ${...} 里的表达式 */
183
- const expr = setStep.set.cfg.replace(/^\$\{/, '').replace(/\}$/, '');
184
-
185
- const cases: [string, string][] = [
186
- ['纯 JSON', '{"book":"a","page":12,"shots":10}'],
187
- ['带前言', '三项参数都已给出。\n\n{"book":"a","page":12,"shots":10}'],
188
- ['带 ```json 围栏', '```json\n{"book":"a","page":12,"shots":10}\n```'],
189
- ['前后都有话', '好的:\n{"book":"a","page":12,"shots":10}\n以上。'],
190
- ];
191
-
192
- for (const [name, raw] of cases) {
193
- test(`★ ${name} 都能解出参数`, () => {
194
- const vs = new VarStack();
195
- vs.set('params_json', raw);
196
- const cfg = evalExpr(expr, vs) as { book: string; page: number; shots: number };
197
- expect(cfg).toEqual({ book: 'a', page: 12, shots: 10 });
198
- });
199
- }
200
-
201
- test('解出来的 cfg 能通过 guard_params', () => {
202
- const vs = new VarStack();
203
- vs.set('params_json', '说明在前。\n{"book":"a","page":12,"shots":10}');
204
- vs.set('cfg', evalExpr(expr, vs));
205
- expect(evalExpr(stepById('guard_params').condition!, vs)).toBe(true);
206
- });
207
- });
@@ -1,22 +0,0 @@
1
- /**
2
- * ============================================================
3
- * src/advisorState.ts —— 顾问模型(Advisor 工具)开关状态
4
- * ------------------------------------------------------------
5
- * 模块级单例,镜像 askBridge.ts::setAskHandler 的简单风格——这不是按请求
6
- * 隔离的状态(不需要 AsyncLocalStorage),TUI 单进程单会话场景下一个
7
- * 进程内全局开关就够用。
8
- *
9
- * 默认 true:用户配置了 5 个 ADVISOR_AGENT_* 环境变量本身就是"我要用"的
10
- * 信号,/advisor off 是需要时的临时关闭手段。
11
- *
12
- * 纯内存,不落盘——进程重启即重置为默认值(与 sessionState.ts 的
13
- * "运行时态、不持久化"定位一致)。
14
- * ============================================================
15
- */
16
- let enabled = true;
17
- export function isAdvisorEnabled() {
18
- return enabled;
19
- }
20
- export function setAdvisorEnabled(value) {
21
- enabled = value;
22
- }
@@ -1,293 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * ============================================================
4
- * src/cli/configWizard.tsx —— 首次启动配置向导(Ink TUI)
5
- * ------------------------------------------------------------
6
- * 当 loadProviderLayered() 返回 null(env 和 ~/.minimal-agent/config.json 都没有
7
- * 完整 provider 配置)时,由 Root.tsx 渲染本组件。
8
- *
9
- * 流程:
10
- * Step 1: 选 provider 预设(minimax / openai / deepseek / kimi / custom)
11
- * Step 2: 输入 baseURL(预设有默认值,用户可改)
12
- * Step 3: 输入 apiKey(不回显,用 * 替代)
13
- * Step 4: 输入 model(预设有候选)
14
- * Step 5: 连接测试(POST /chat/completions max_tokens=5)
15
- * - 通过 → saveConfig + onSuccess(provider) → Root 切到 App
16
- * - 失败 → 显示错误 + 回到 Step 1(保留已输入的值方便修改)
17
- *
18
- * 设计取舍:
19
- * - 不引第三方 prompt 库(@inquirer/prompts 等),用 Ink + useInput 手写,
20
- * 保持"零新增依赖"承诺。
21
- * - 不做 spinner 动画,loading 时显示一行文字够用。
22
- * - 不做"返回上一步",要修改请按 ESC 退出向导重跑(简化键位逻辑)。
23
- * —— 用户中途退出 = 不写文件 = 下次启动继续向导,符合需求 "直到成功为止"。
24
- * ============================================================
25
- */
26
- import { useCallback, useMemo, useState } from 'react';
27
- import { Box, Text, useApp, useInput } from 'ink';
28
- import { saveConfig } from '../config/configFile.js';
29
- import { configService } from '../config/configService.js';
30
- // 兜底值:custom 或表外 model 都退到这里。
31
- // 与 src/config.ts 的同名常量含义对齐("既没 env、saved 也没填 contextWindow" 的最终兜底)。
32
- const FALLBACK_CONTEXT_WINDOW = 128_000;
33
- const PRESETS = [
34
- {
35
- name: 'minimax',
36
- label: 'MiniMax (海螺)',
37
- baseURL: 'https://api.minimax.chat/v1',
38
- models: ['MiniMax-M3', 'MiniMax-M2.7', 'MiniMax-M1', 'abab6.5s-chat'],
39
- contextWindow: 204_800,
40
- },
41
- {
42
- // 火山方舟 ARK Coding Plan —— 一个 endpoint 后挂多个 model id,
43
- // model 字段大小写严格匹配('glm-5.1' 而非 'GLM-5.1')。
44
- // 部分 model(如 glm-5.1)走 draft-2020-12 严校验,靠 zodToJson 的
45
- // modernizeExclusiveBounds 兼容。
46
- name: 'volces',
47
- label: '火山方舟 Coding Plan (ARK)',
48
- baseURL: 'https://ark.cn-beijing.volces.com/api/coding/v3',
49
- models: [
50
- 'doubao-seed-2.0-pro',
51
- 'doubao-seed-2.0-code',
52
- 'doubao-seed-code',
53
- 'glm-5.1',
54
- 'minimax-latest',
55
- 'deepseek-v3.2',
56
- 'kimi-k2.7-code',
57
- 'kimi-k2.6',
58
- ],
59
- contextWindow: 204_800,
60
- modelContextWindows: {
61
- 'kimi-k2.7-code': 512_000,
62
- },
63
- },
64
- {
65
- name: 'deepseek',
66
- label: 'DeepSeek',
67
- baseURL: 'https://api.deepseek.com/v1',
68
- models: ['deepseek-chat', 'deepseek-reasoner'],
69
- contextWindow: 128_000,
70
- },
71
- {
72
- name: 'openai',
73
- label: 'OpenAI',
74
- baseURL: 'https://api.openai.com/v1',
75
- models: ['gpt-4o', 'gpt-4o-mini'],
76
- contextWindow: 128_000,
77
- },
78
- {
79
- name: 'moonshot',
80
- label: 'Moonshot (Kimi)',
81
- baseURL: 'https://api.moonshot.cn/v1',
82
- models: ['moonshot-v1-8k', 'moonshot-v1-32k', 'moonshot-v1-128k'],
83
- contextWindow: 128_000,
84
- modelContextWindows: {
85
- 'moonshot-v1-8k': 8_000,
86
- 'moonshot-v1-32k': 32_000,
87
- 'moonshot-v1-128k': 128_000,
88
- },
89
- },
90
- {
91
- name: 'custom',
92
- label: '自定义(手动填 baseURL)',
93
- baseURL: '',
94
- models: [],
95
- contextWindow: FALLBACK_CONTEXT_WINDOW,
96
- },
97
- ];
98
- function resolveContextWindow(preset, model) {
99
- return (preset.modelContextWindows?.[model] ??
100
- preset.contextWindow ??
101
- FALLBACK_CONTEXT_WINDOW);
102
- }
103
- export function ConfigWizard({ onSuccess }) {
104
- const { exit } = useApp();
105
- const [step, setStep] = useState('preset');
106
- const [presetIndex, setPresetIndex] = useState(0);
107
- const [baseURL, setBaseURL] = useState('');
108
- const [apiKey, setApiKey] = useState('');
109
- const [model, setModel] = useState('');
110
- const [modelIndex, setModelIndex] = useState(0);
111
- const [draft, setDraft] = useState('');
112
- const [errorMsg, setErrorMsg] = useState(null);
113
- const preset = PRESETS[presetIndex];
114
- const enterStep = useCallback((next) => {
115
- setErrorMsg(null);
116
- if (next === 'baseURL')
117
- setDraft(baseURL || preset.baseURL);
118
- if (next === 'apiKey')
119
- setDraft('');
120
- if (next === 'model') {
121
- if (preset.models.length > 0) {
122
- setDraft(model || preset.models[0]);
123
- setModelIndex(0);
124
- }
125
- else {
126
- setDraft(model);
127
- }
128
- }
129
- setStep(next);
130
- }, [baseURL, model, preset]);
131
- // handleTest 接受 finalModel 作为参数:
132
- // Step 4 里调用方 `setModel(...) + handleTest()` 时,setModel 是异步的,handleTest
133
- // 的 closure 还引用着旧的 model state;直接传 finalModel 才能避免"首次必跑两轮"
134
- // —— 第一次发请求时 model 还是空串,API 报错,回到 Step 1 再走一遍才能成功。
135
- //
136
- // 测试通过后 **不立即** saveConfig + onSuccess,而是转去 Step 5(tavily)
137
- // 让用户决定是否一并填 Tavily key,最后在 finalize() 一次性落盘。
138
- const handleTest = useCallback(async (finalModel) => {
139
- setStep('testing');
140
- setErrorMsg(null);
141
- try {
142
- const url = `${baseURL.replace(/\/$/, '')}/chat/completions`;
143
- const resp = await fetch(url, {
144
- method: 'POST',
145
- headers: {
146
- 'Content-Type': 'application/json',
147
- Authorization: `Bearer ${apiKey}`,
148
- },
149
- body: JSON.stringify({
150
- model: finalModel,
151
- messages: [{ role: 'user', content: 'ping' }],
152
- max_tokens: 5,
153
- stream: false,
154
- }),
155
- });
156
- if (!resp.ok) {
157
- const body = await resp.text().catch(() => '');
158
- throw new Error(`HTTP ${resp.status}: ${body.slice(0, 200) || resp.statusText}`);
159
- }
160
- const data = (await resp.json());
161
- if (!Array.isArray(data.choices)) {
162
- throw new Error('响应中没有 choices 字段,可能不是 OpenAI 兼容协议');
163
- }
164
- setDraft('');
165
- setStep('tavily');
166
- }
167
- catch (e) {
168
- setErrorMsg(e.message || '连接失败');
169
- setStep('error');
170
- }
171
- }, [apiKey, baseURL]);
172
- // 落盘 + 切到 App。tavily key 为空表示用户跳过 WebSearch 配置。
173
- const finalize = useCallback(async (finalModel, tavilyApiKey) => {
174
- const contextWindow = resolveContextWindow(preset, finalModel);
175
- await saveConfig({
176
- baseURL,
177
- apiKey,
178
- model: finalModel,
179
- provider: preset.name,
180
- contextWindow,
181
- tavilyApiKey,
182
- });
183
- await configService.reload();
184
- onSuccess({
185
- name: preset.name,
186
- baseURL,
187
- apiKey,
188
- model: finalModel,
189
- contextWindow,
190
- });
191
- }, [apiKey, baseURL, onSuccess, preset]);
192
- useInput((input, key) => {
193
- if (key.escape || (key.ctrl && input === 'c')) {
194
- exit();
195
- return;
196
- }
197
- if (step === 'preset') {
198
- if (key.upArrow) {
199
- setPresetIndex((i) => (i - 1 + PRESETS.length) % PRESETS.length);
200
- }
201
- else if (key.downArrow) {
202
- setPresetIndex((i) => (i + 1) % PRESETS.length);
203
- }
204
- else if (key.return) {
205
- enterStep('baseURL');
206
- }
207
- return;
208
- }
209
- if (step === 'baseURL') {
210
- if (key.return) {
211
- if (draft.trim().length === 0)
212
- return;
213
- setBaseURL(draft.trim());
214
- enterStep('apiKey');
215
- }
216
- else if (key.backspace || key.delete) {
217
- setDraft((s) => s.slice(0, -1));
218
- }
219
- else if (input && !key.meta && !key.ctrl) {
220
- setDraft((s) => s + input);
221
- }
222
- return;
223
- }
224
- if (step === 'apiKey') {
225
- if (key.return) {
226
- if (draft.length === 0)
227
- return;
228
- setApiKey(draft);
229
- enterStep('model');
230
- }
231
- else if (key.backspace || key.delete) {
232
- setDraft((s) => s.slice(0, -1));
233
- }
234
- else if (input && !key.meta && !key.ctrl) {
235
- setDraft((s) => s + input);
236
- }
237
- return;
238
- }
239
- if (step === 'model') {
240
- if (preset.models.length > 0) {
241
- if (key.upArrow) {
242
- const ni = (modelIndex - 1 + preset.models.length) % preset.models.length;
243
- setModelIndex(ni);
244
- setDraft(preset.models[ni]);
245
- }
246
- else if (key.downArrow) {
247
- const ni = (modelIndex + 1) % preset.models.length;
248
- setModelIndex(ni);
249
- setDraft(preset.models[ni]);
250
- }
251
- else if (key.tab) {
252
- setDraft((s) => s + '');
253
- }
254
- }
255
- if (key.return) {
256
- const finalModel = draft.trim();
257
- if (finalModel.length === 0)
258
- return;
259
- setModel(finalModel);
260
- void handleTest(finalModel);
261
- }
262
- else if (key.backspace || key.delete) {
263
- setDraft((s) => s.slice(0, -1));
264
- }
265
- else if (input && !key.meta && !key.ctrl && !key.upArrow && !key.downArrow) {
266
- setDraft((s) => s + input);
267
- }
268
- return;
269
- }
270
- if (step === 'tavily') {
271
- if (key.return) {
272
- // 空 draft 表示用户跳过 WebSearch 配置(合法路径,不报错)
273
- const tavilyApiKey = draft.trim().length > 0 ? draft.trim() : undefined;
274
- void finalize(model, tavilyApiKey);
275
- }
276
- else if (key.backspace || key.delete) {
277
- setDraft((s) => s.slice(0, -1));
278
- }
279
- else if (input && !key.meta && !key.ctrl) {
280
- setDraft((s) => s + input);
281
- }
282
- return;
283
- }
284
- if (step === 'error') {
285
- if (key.return) {
286
- enterStep('preset');
287
- }
288
- return;
289
- }
290
- });
291
- const maskedApiKey = useMemo(() => '*'.repeat(Math.min(draft.length, 32)), [draft]);
292
- return (_jsxs(Box, { flexDirection: "column", paddingX: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "cyan", bold: true, children: "minimal-agent \u00B7 \u9996\u6B21\u914D\u7F6E\u5411\u5BFC" }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "gray", children: "\u6309 ESC \u6216 Ctrl+C \u9000\u51FA\uFF08\u4E0D\u5199\u914D\u7F6E\uFF0C\u4E0B\u6B21\u542F\u52A8\u7EE7\u7EED\u5411\u5BFC\uFF09" }) }), step === 'preset' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: "Step 1/5 \u00B7 \u9009\u62E9 provider \u9884\u8BBE\uFF08\u2191\u2193 \u79FB\u52A8\uFF0CEnter \u786E\u8BA4\uFF09" }), _jsx(Box, { flexDirection: "column", marginTop: 1, children: PRESETS.map((p, i) => (_jsxs(Text, { color: i === presetIndex ? 'cyan' : undefined, children: [i === presetIndex ? '> ' : ' ', p.label, p.baseURL ? ` (${p.baseURL})` : ''] }, p.name))) })] })), step === 'baseURL' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: "Step 2/5 \u00B7 \u8F93\u5165 API base URL\uFF08\u9ED8\u8BA4\u4E3A\u9884\u8BBE\u503C\uFF0C\u53EF\u6539\uFF09" }), _jsx(Box, { marginTop: 1, borderStyle: "round", borderColor: "cyan", paddingX: 1, children: _jsx(Text, { children: draft || ' ' }) }), _jsx(Text, { color: "gray", children: "Enter \u786E\u8BA4 \u00B7 Backspace \u5220\u9664" })] })), step === 'apiKey' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: "Step 3/5 \u00B7 \u8F93\u5165 API key\uFF08\u8F93\u5165\u5185\u5BB9\u4E0D\u4F1A\u663E\u793A\uFF09" }), _jsx(Box, { marginTop: 1, borderStyle: "round", borderColor: "cyan", paddingX: 1, children: _jsx(Text, { children: maskedApiKey || ' ' }) }), _jsxs(Text, { color: "gray", children: ["Enter \u786E\u8BA4 \u00B7 Backspace \u5220\u9664\uFF08\u5DF2\u8F93\u5165 ", draft.length, " \u5B57\u7B26\uFF09"] })] })), step === 'model' && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: ["Step 4/5 \u00B7 \u8F93\u5165\u6216\u9009\u62E9 model", preset.models.length > 0 ? '(↑↓ 切换预设,或直接编辑)' : ''] }), preset.models.length > 0 && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: preset.models.map((m, i) => (_jsxs(Text, { color: i === modelIndex ? 'cyan' : 'gray', children: [i === modelIndex ? '> ' : ' ', m] }, m))) })), _jsx(Box, { marginTop: 1, borderStyle: "round", borderColor: "cyan", paddingX: 1, children: _jsx(Text, { children: draft || ' ' }) }), _jsx(Text, { color: "gray", children: "Enter \u63D0\u4EA4\u5E76\u6D4B\u8BD5\u8FDE\u63A5" })] })), step === 'testing' && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: "yellow", children: ["\u23F3 \u6B63\u5728\u6D4B\u8BD5\u8FDE\u63A5 ", baseURL, " ..."] }), _jsxs(Text, { color: "gray", children: ["model = ", model] })] })), step === 'tavily' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "green", children: "\u2713 LLM \u8FDE\u63A5\u6D4B\u8BD5\u901A\u8FC7" }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { children: "Step 5/5 \u00B7 \u53EF\u9009 - Tavily API key\uFF08\u7528\u4E8E WebSearch \u5DE5\u5177\uFF09" }) }), _jsx(Box, { marginTop: 1, borderStyle: "round", borderColor: "cyan", paddingX: 1, children: _jsx(Text, { children: maskedApiKey || ' ' }) }), _jsx(Text, { color: "gray", children: "\u76F4\u63A5 Enter \u8DF3\u8FC7\uFF08\u4E4B\u540E\u53EF\u5728\u5BF9\u8BDD\u91CC\u8F93\u5165 /config \u6DFB\u52A0\uFF0C\u6216\u8BBE env TAVILY_API_KEY\uFF09" }), _jsxs(Text, { color: "gray", children: ["\u514D\u8D39 key \u7533\u8BF7\uFF1Ahttps://tavily.com/ \u00B7 \u5DF2\u8F93\u5165 ", draft.length, " \u5B57\u7B26"] })] })), step === 'error' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "red", children: "\u2717 \u8FDE\u63A5\u6D4B\u8BD5\u5931\u8D25" }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "red", children: errorMsg ?? '未知错误' }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", children: "\u5DF2\u8F93\u5165\uFF1A" }) }), _jsxs(Text, { color: "gray", children: [" provider = ", preset.name] }), _jsxs(Text, { color: "gray", children: [" baseURL = ", baseURL] }), _jsxs(Text, { color: "gray", children: [" model = ", model] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "yellow", children: "\u6309 Enter \u56DE\u5230 Step 1 \u91CD\u8BD5 \u00B7 ESC \u9000\u51FA" }) })] }))] }));
293
- }
@@ -1,48 +0,0 @@
1
- /**
2
- * ============================================================
3
- * src/tools/toolProgressBridge.ts —— 长时工具的「步内进度」宿主桥
4
- * ------------------------------------------------------------
5
- * 仿 askBridge 的宿主交互桥模式(全局 handler 注册表):
6
- * 长时工具(GenerateImage 批量生图,单步可达 10-30 分钟)在执行**中途**把
7
- * 逐项进度行发布出来,有 UI 的宿主(TUI useChat)订阅后实时上屏——
8
- * 否则整步在 LiveArea 上只有一行静态描述,十几分钟毫无变化,
9
- * 用户必然误判死机(2026-07-02 真实事故:31 张生图 ~13 分钟被当成卡死,
10
- * 差点手杀健康运行)。
11
- *
12
- * 两种宿主:
13
- * - TUI:useChat mount 时 setToolProgressHandler() 注册,更新 runningTools
14
- * 对应条目的 progress 字段 → LiveArea tool_executing 行实时显示。
15
- * - 非交互(`-p` / gateway / 子进程):没有 handler → publish 是 no-op,
16
- * 零副作用(进度对结构化结局契约不可见,不污染 stdout/stderr)。
17
- *
18
- * 工具侧只依赖本模块,不 import ui/(与 askBridge 同样的中立位置理由:
19
- * 它是工具与宿主之间的中介,避免 tools → ui 反向耦合)。
20
- * ============================================================
21
- */
22
- let handler = null;
23
- /**
24
- * 注册 / 注销宿主处理器。
25
- * TUI 的 useChat 在 mount 时注册、unmount 时传 null 注销。
26
- * 单进程单 UI,模块级单例即可(与 askBridge 一致)。
27
- */
28
- export function setToolProgressHandler(h) {
29
- handler = h;
30
- }
31
- /** 是否有宿主在场(测试 / 诊断用)。 */
32
- export function hasToolProgressHandler() {
33
- return handler !== null;
34
- }
35
- /**
36
- * 发布一条进度行。无 handler 时 no-op;handler 抛异常也吞掉——
37
- * 进度是锦上添花,绝不能让 UI 侧的 bug 反噬工具执行。
38
- */
39
- export function publishToolProgress(toolName, line) {
40
- if (!handler)
41
- return;
42
- try {
43
- handler(toolName, line);
44
- }
45
- catch {
46
- /* 进度上屏失败不阻断工具 */
47
- }
48
- }