minimal-agent 0.13.0 → 0.14.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 (470) 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 +503 -0
  103. package/src/advisor/advisorCoordinator.ts +657 -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/streamJson.js +5 -6
  108. package/src/cli/streamJson.ts +8 -4
  109. package/src/cli/wizards/advisorWizard.js +4 -2
  110. package/src/cli/wizards/advisorWizard.tsx +8 -2
  111. package/src/cli/wizards/contextAdvisorWizard.js +5 -4
  112. package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
  113. package/src/collaboration/taskFlow.js +115 -0
  114. package/src/collaboration/taskFlow.ts +169 -0
  115. package/src/config/configDefaults.js +41 -1
  116. package/src/config/configDefaults.ts +43 -1
  117. package/src/config/configDiagnostics.ts +2 -2
  118. package/src/config/configFile.js +40 -9
  119. package/src/config/configFile.ts +60 -11
  120. package/src/config/configService.js +419 -74
  121. package/src/config/configService.ts +703 -145
  122. package/src/config/numericLimits.js +22 -0
  123. package/src/config/numericLimits.ts +24 -0
  124. package/src/config.js +1 -0
  125. package/src/config.ts +3 -2
  126. package/src/context/budgetPlan.js +1 -1
  127. package/src/context/budgetPlan.ts +1 -1
  128. package/src/context/compact.js +7 -2
  129. package/src/context/compact.ts +9 -2
  130. package/src/context/microCompactLite.js +212 -13
  131. package/src/context/microCompactLite.ts +261 -12
  132. package/src/context/sessionRegistry.js +8 -1
  133. package/src/context/sessionRegistry.ts +18 -5
  134. package/src/context/toolResultArchive.js +72 -0
  135. package/src/context/toolResultArchive.ts +95 -0
  136. package/src/goal/errors.js +8 -0
  137. package/src/goal/errors.ts +18 -0
  138. package/src/goal/goalRuntime.js +344 -0
  139. package/src/goal/goalRuntime.ts +466 -0
  140. package/src/goal/goalStore.js +200 -0
  141. package/src/goal/goalStore.ts +219 -0
  142. package/src/goal/index.js +4 -0
  143. package/src/goal/index.ts +4 -0
  144. package/src/goal/statusMapping.js +71 -0
  145. package/src/goal/statusMapping.ts +95 -0
  146. package/src/goal/types.js +7 -0
  147. package/src/goal/types.ts +179 -0
  148. package/src/goal/workflowController.js +306 -0
  149. package/src/goal/workflowController.ts +360 -0
  150. package/src/harness/evidenceLedger.js +2 -0
  151. package/src/harness/evidenceLedger.ts +1 -0
  152. package/src/harness/stallGuard.js +9 -3
  153. package/src/harness/stallGuard.ts +7 -3
  154. package/src/images/imageResolver.js +161 -0
  155. package/src/images/imageResolver.ts +189 -0
  156. package/src/infra/verification.js +34 -5
  157. package/src/infra/verification.ts +39 -4
  158. package/src/llm/client.js +79 -21
  159. package/src/llm/client.ts +182 -35
  160. package/src/llm/gatewayClient.js +201 -0
  161. package/src/llm/gatewayClient.ts +299 -0
  162. package/src/llm/messageProvenance.js +46 -0
  163. package/src/llm/messageProvenance.ts +58 -0
  164. package/src/llm/modelProvider.js +1 -0
  165. package/src/llm/modelProvider.ts +22 -0
  166. package/src/llm/providers/anthropicFormat.js +108 -1
  167. package/src/llm/providers/anthropicFormat.ts +115 -4
  168. package/src/llm/providers/openaiFormat.js +9 -0
  169. package/src/llm/providers/openaiFormat.ts +12 -3
  170. package/src/loop.js +319 -54
  171. package/src/loop.ts +373 -57
  172. package/src/main.js +4 -1
  173. package/src/main.tsx +4 -1
  174. package/src/managedExecution/index.js +2 -0
  175. package/src/managedExecution/index.ts +2 -0
  176. package/src/managedExecution/registry.js +15 -0
  177. package/src/managedExecution/registry.ts +20 -0
  178. package/src/managedExecution/types.js +1 -0
  179. package/src/managedExecution/types.ts +86 -0
  180. package/src/modelRef.js +9 -0
  181. package/src/modelRef.ts +31 -0
  182. package/src/multimodal.js +14 -28
  183. package/src/multimodal.ts +17 -33
  184. package/src/net/lanDiscovery.js +65 -0
  185. package/src/net/lanDiscovery.ts +82 -0
  186. package/src/plugin-sdk.js +28 -3
  187. package/src/plugin-sdk.ts +39 -6
  188. package/src/plugins/pluginApi.ts +16 -1
  189. package/src/plugins/pluginLoader.js +4 -0
  190. package/src/plugins/pluginLoader.ts +6 -0
  191. package/src/plugins/pluginRunner.js +139 -7
  192. package/src/plugins/pluginRunner.ts +173 -9
  193. package/src/plugins/slashFallback.js +113 -0
  194. package/src/plugins/slashFallback.ts +137 -0
  195. package/src/prompts/policyRegistry.js +12 -32
  196. package/src/prompts/policyRegistry.ts +15 -32
  197. package/src/prompts/promptAssembly.js +103 -12
  198. package/src/prompts/promptAssembly.ts +114 -12
  199. package/src/prompts/skillList.js +21 -3
  200. package/src/prompts/skillList.ts +27 -2
  201. package/src/prompts/stableSystemPrompt.js +18 -0
  202. package/src/prompts/stableSystemPrompt.ts +33 -0
  203. package/src/runtime/agentRuntimeContext.js +8 -2
  204. package/src/runtime/agentRuntimeContext.ts +17 -4
  205. package/src/session/runAgentTurn.js +78 -12
  206. package/src/session/runAgentTurn.ts +105 -23
  207. package/src/session/runTurn.js +10 -9
  208. package/src/session/runTurn.ts +17 -8
  209. package/src/session/sessionState.ts +2 -0
  210. package/src/team/auth.js +186 -0
  211. package/src/team/auth.ts +298 -0
  212. package/src/team/cli.js +105 -0
  213. package/src/team/cli.ts +122 -0
  214. package/src/team/onlineToolContract.js +64 -0
  215. package/src/team/onlineToolContract.ts +109 -0
  216. package/src/team/toolPolicy.js +36 -0
  217. package/src/team/toolPolicy.ts +75 -0
  218. package/src/tools/advisor/advisor.js +90 -46
  219. package/src/tools/advisor/advisor.ts +100 -47
  220. package/src/tools/advisor/advisorDecision.js +71 -0
  221. package/src/tools/advisor/advisorDecision.ts +85 -0
  222. package/src/tools/agent/agent.js +18 -5
  223. package/src/tools/agent/agent.ts +21 -7
  224. package/src/tools/agent/agentControl.js +246 -0
  225. package/src/tools/agent/agentControl.ts +284 -0
  226. package/src/tools/agent/agentTaskService.js +40 -1
  227. package/src/tools/agent/agentTaskService.ts +44 -1
  228. package/src/tools/agent/agentTypes.js +14 -2
  229. package/src/tools/agent/agentTypes.ts +15 -2
  230. package/src/tools/applypatch/applyPatch.js +362 -0
  231. package/src/tools/applypatch/applyPatch.ts +428 -0
  232. package/src/tools/bash/bash.js +22 -15
  233. package/src/tools/bash/bash.ts +23 -17
  234. package/src/tools/capabilities.js +10 -5
  235. package/src/tools/capabilities.ts +10 -5
  236. package/src/tools/computeruse/computerIntent.js +32 -0
  237. package/src/tools/computeruse/computerIntent.ts +46 -0
  238. package/src/tools/computeruse/telemetryLog.js +12 -0
  239. package/src/tools/computeruse/telemetryLog.ts +16 -0
  240. package/src/tools/computeruse/vision/telemetry.js +1 -0
  241. package/src/tools/computeruse/vision/telemetry.ts +1 -0
  242. package/src/tools/effectiveToolSet.js +4 -0
  243. package/src/tools/effectiveToolSet.ts +4 -0
  244. package/src/tools/index.js +21 -2
  245. package/src/tools/index.ts +33 -2
  246. package/src/tools/presentresult/presentresult.js +6 -15
  247. package/src/tools/presentresult/presentresult.ts +6 -15
  248. package/src/tools/read/read.js +62 -9
  249. package/src/tools/read/read.ts +63 -9
  250. package/src/tools/shared/fileUtils.js +1 -2
  251. package/src/tools/shared/fileUtils.ts +1 -2
  252. package/src/tools/shared/toolOutputStore.js +23 -1
  253. package/src/tools/shared/toolOutputStore.ts +22 -1
  254. package/src/tools/skill/skill.js +9 -3
  255. package/src/tools/skill/skill.ts +8 -4
  256. package/src/tools/toolPromptGuides.js +117 -0
  257. package/src/tools/toolPromptGuides.ts +137 -0
  258. package/src/tools/webbrowser/agentBrowserPath.js +19 -9
  259. package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
  260. package/src/tools/webbrowser/browser.js +27 -11
  261. package/src/tools/webbrowser/browser.ts +68 -24
  262. package/src/tools/webbrowser/browserAutomation.js +329 -0
  263. package/src/tools/webbrowser/browserAutomation.ts +467 -0
  264. package/src/tools/webbrowser/browserAxState.js +97 -0
  265. package/src/tools/webbrowser/browserAxState.ts +142 -0
  266. package/src/tools/webbrowser/browserBatch.js +1578 -0
  267. package/src/tools/webbrowser/browserBatch.ts +2382 -0
  268. package/src/tools/webbrowser/browserCdp.js +208 -0
  269. package/src/tools/webbrowser/browserCdp.ts +255 -0
  270. package/src/tools/webbrowser/browserConditions.js +24 -0
  271. package/src/tools/webbrowser/browserConditions.ts +45 -0
  272. package/src/tools/webbrowser/browserContent.js +281 -0
  273. package/src/tools/webbrowser/browserContent.ts +438 -0
  274. package/src/tools/webbrowser/browserControl.js +131 -34
  275. package/src/tools/webbrowser/browserControl.ts +210 -56
  276. package/src/tools/webbrowser/browserDaemon.js +22 -14
  277. package/src/tools/webbrowser/browserDaemon.ts +54 -21
  278. package/src/tools/webbrowser/browserFrames.js +47 -0
  279. package/src/tools/webbrowser/browserFrames.ts +54 -0
  280. package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
  281. package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
  282. package/src/tools/webbrowser/browserLocator.js +140 -0
  283. package/src/tools/webbrowser/browserLocator.ts +194 -0
  284. package/src/tools/webbrowser/browserOutcome.js +10 -17
  285. package/src/tools/webbrowser/browserOutcome.ts +48 -31
  286. package/src/tools/webbrowser/browserRecovery.js +58 -0
  287. package/src/tools/webbrowser/browserRecovery.ts +83 -0
  288. package/src/tools/webbrowser/browserRunRegistry.js +35 -3
  289. package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
  290. package/src/tools/webbrowser/browserService.js +28 -2
  291. package/src/tools/webbrowser/browserService.ts +49 -9
  292. package/src/tools/webbrowser/browserStream.js +132 -33
  293. package/src/tools/webbrowser/browserStream.ts +224 -50
  294. package/src/tools/webbrowser/browserTabs.js +48 -15
  295. package/src/tools/webbrowser/browserTabs.ts +178 -96
  296. package/src/tools/webbrowser/webbrowser.js +679 -144
  297. package/src/tools/webbrowser/webbrowser.ts +975 -236
  298. package/src/tools/webfetch/preapproved.js +0 -2
  299. package/src/tools/webfetch/preapproved.ts +0 -2
  300. package/src/tools/websearch/websearch.js +129 -8
  301. package/src/tools/websearch/websearch.ts +138 -6
  302. package/src/types.ts +440 -38
  303. package/src/ui/App.js +377 -58
  304. package/src/ui/App.tsx +576 -111
  305. package/src/ui/LiveArea.js +14 -8
  306. package/src/ui/LiveArea.tsx +14 -10
  307. package/src/ui/MessageList.js +63 -20
  308. package/src/ui/MessageList.tsx +101 -16
  309. package/src/ui/ModelPicker.js +7 -4
  310. package/src/ui/ModelPicker.tsx +55 -8
  311. package/src/ui/hooks/useChat.js +152 -163
  312. package/src/ui/hooks/useChat.ts +396 -334
  313. package/src/ui/loginCommand.js +56 -0
  314. package/src/ui/loginCommand.ts +63 -0
  315. package/src/ui/toolProgress.js +41 -0
  316. package/src/ui/toolProgress.ts +44 -0
  317. package/src/web/browserBridge.js +20 -2
  318. package/src/web/browserBridge.ts +20 -2
  319. package/src/web/protocol.ts +1897 -194
  320. package/workflows/adaptive-research/workflow.mjs +86 -0
  321. package/workflows/e2e-capabilities/workflow.mjs +102 -0
  322. package/workflows/e2e-llm/workflow.mjs +52 -0
  323. package/workflows/e2e-smoke/workflow.mjs +59 -0
  324. package/workflows/e2e-vision-schema/README.md +48 -0
  325. package/workflows/e2e-vision-schema/workflow.mjs +149 -0
  326. package/workflows/e2e-write-greet/workflow.mjs +37 -0
  327. package/workflows/file-census/README.md +14 -0
  328. package/workflows/file-census/scripts/.gitkeep +2 -0
  329. package/workflows/file-census/workflow.mjs +110 -0
  330. package/workflows/goal/README.md +166 -0
  331. package/workflows/goal/prompts/audit.md +57 -0
  332. package/workflows/goal/prompts/contract.md +56 -0
  333. package/workflows/goal/prompts/iterate.md +37 -0
  334. package/workflows/goal/workflow.mjs +501 -0
  335. package/workflows/illustrate/README.md +90 -0
  336. package/workflows/illustrate/assets/engines.json +20 -0
  337. package/workflows/illustrate/assets/extract-baidu.js +21 -0
  338. package/workflows/illustrate/assets/extract-bing.js +33 -0
  339. package/workflows/illustrate/assets/extract-google.js +31 -0
  340. package/workflows/illustrate/workflow.mjs +301 -0
  341. package/workflows/plan/workflow.mjs +389 -0
  342. package/workflows/question-crops/README.md +35 -0
  343. package/workflows/question-crops/prompts/inventory.md +23 -0
  344. package/workflows/question-crops/scripts/image-ops.mjs +305 -0
  345. package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
  346. package/workflows/question-crops/workflow.mjs +172 -0
  347. package/workflows/ralph-loop/workflow.mjs +162 -0
  348. package/workflows/research/README.md +74 -0
  349. package/workflows/research/prompts/s0-goal.md +43 -0
  350. package/workflows/research/prompts/s1-early-exit.md +22 -0
  351. package/workflows/research/prompts/s1-map.md +58 -0
  352. package/workflows/research/prompts/s2-options.md +53 -0
  353. package/workflows/research/prompts/s3-deep-dive.md +56 -0
  354. package/workflows/research/prompts/s4-verify.md +74 -0
  355. package/workflows/research/prompts/s5-synthesis.md +81 -0
  356. package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
  357. package/workflows/research/prompts/s6-package.md +32 -0
  358. package/workflows/research/scripts/build-report.mjs +98 -0
  359. package/workflows/research/workflow.mjs +288 -0
  360. package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
  361. package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
  362. package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
  363. package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
  364. package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
  365. package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
  366. package/workflows/wechat-reading-shots/workflow.mjs +266 -0
  367. package/workflows/wrong-question-docx/README.md +55 -0
  368. package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
  369. package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
  370. package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
  371. package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
  372. package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
  373. package/workflows/wrong-question-docx/workflow.mjs +485 -0
  374. package/plugins/workflow-runner/src/agentCommon.js +0 -354
  375. package/plugins/workflow-runner/src/agentCommon.ts +0 -435
  376. package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
  377. package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
  378. package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
  379. package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
  380. package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
  381. package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
  382. package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
  383. package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
  384. package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
  385. package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
  386. package/plugins/workflow-runner/src/dslManifest.js +0 -72
  387. package/plugins/workflow-runner/src/dslManifest.ts +0 -127
  388. package/plugins/workflow-runner/src/expressions.js +0 -639
  389. package/plugins/workflow-runner/src/expressions.ts +0 -640
  390. package/plugins/workflow-runner/src/loader.js +0 -573
  391. package/plugins/workflow-runner/src/loader.ts +0 -721
  392. package/plugins/workflow-runner/src/multimodal.js +0 -38
  393. package/plugins/workflow-runner/src/multimodal.ts +0 -64
  394. package/plugins/workflow-runner/src/recovery.js +0 -126
  395. package/plugins/workflow-runner/src/recovery.ts +0 -156
  396. package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
  397. package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
  398. package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -42
  399. package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -52
  400. package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
  401. package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
  402. package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
  403. package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
  404. package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
  405. package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
  406. package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
  407. package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
  408. package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -227
  409. package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -274
  410. package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -61
  411. package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -72
  412. package/plugins/workflow-runner/src/stepPipeline.js +0 -277
  413. package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
  414. package/plugins/workflow-runner/test/agent.test.ts +0 -587
  415. package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
  416. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
  417. package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
  418. package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -167
  419. package/plugins/workflow-runner/test/context-files.test.ts +0 -320
  420. package/plugins/workflow-runner/test/e2e.test.ts +0 -370
  421. package/plugins/workflow-runner/test/e2eNewLayout.test.ts +0 -314
  422. package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -234
  423. package/plugins/workflow-runner/test/expressions.test.ts +0 -439
  424. package/plugins/workflow-runner/test/foundation.test.ts +0 -126
  425. package/plugins/workflow-runner/test/graceful.test.ts +0 -139
  426. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
  427. package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
  428. package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
  429. package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
  430. package/plugins/workflow-runner/test/loader.test.ts +0 -617
  431. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
  432. package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
  433. package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
  434. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -106
  435. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
  436. package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
  437. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -221
  438. package/plugins/workflow-runner/test/recovery.test.ts +0 -265
  439. package/plugins/workflow-runner/test/research.load.test.ts +0 -328
  440. package/plugins/workflow-runner/test/runner.test.ts +0 -911
  441. package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -436
  442. package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
  443. package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -198
  444. package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
  445. package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -354
  446. package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -324
  447. package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +0 -221
  448. package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +0 -29
  449. package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +0 -168
  450. package/plugins/workflow-runner/test/webppt.load.test.ts +0 -250
  451. package/plugins/workflow-runner/test/word.load.test.ts +0 -208
  452. package/plugins/workflow-runner/test/workflows.smoke.test.ts +0 -76
  453. package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +0 -207
  454. package/src/advisorState.js +0 -22
  455. package/src/cli/configWizard.js +0 -293
  456. package/src/tools/toolProgressBridge.js +0 -48
  457. package/workflows/adaptive-research.yaml +0 -50
  458. package/workflows/book-review-short.yaml +0 -125
  459. package/workflows/e2e-write-greet.yaml +0 -31
  460. package/workflows/illustrate.yaml +0 -227
  461. package/workflows/plan.yaml +0 -470
  462. package/workflows/ppt.yaml +0 -1670
  463. package/workflows/ralph-loop.yaml +0 -201
  464. package/workflows/research.yaml +0 -873
  465. package/workflows/schema.json +0 -176
  466. package/workflows/webppt.yaml +0 -496
  467. package/workflows/wechat-reading-shots.yaml +0 -315
  468. package/workflows/word.yaml +0 -720
  469. package/workflows/youtube-shorts.yaml +0 -202
  470. /package/workflows/{research.md → research/DESIGN.md} +0 -0
@@ -8,7 +8,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
8
  * └ 内容区(0..N 行,有界):随阶段切换——
9
9
  * thinking → reasoningPreview 尾部最近 N 行(gray dim,首行 💭)
10
10
  * streaming → streamingText 尾部最近 N 行(默认亮色 = 答案是主角)
11
- * tool_executing → runningTools 逐行人话描述(gray dim)
11
+ * tool_executing →「当前正在」动作 + 可选独立进度行(gray dim)
12
12
  * compacting/idle→ 无内容行
13
13
  *
14
14
  * ★ 暂态错误行(transientError):工作流步执行中 LLM 调用失败(会被该步重试)时,
@@ -34,10 +34,11 @@ import { Box, Text } from 'ink';
34
34
  import { LIVE_RIGHT_MARGIN, clampWidthStart, wrapToDisplayLines, } from './liveViewport.js';
35
35
  import { theme } from './theme.js';
36
36
  import { figures } from './figures.js';
37
+ import { humanizeToolProgress } from './toolProgress.js';
37
38
  const STAGE_LABELS = {
38
39
  thinking: '思考中',
39
40
  streaming: '回答中',
40
- tool_executing: '调用工具',
41
+ tool_executing: '工作中',
41
42
  compacting: '压缩历史',
42
43
  };
43
44
  /** 动画 spinner 帧(charWidth 上界按 2 计;终端实际多为 1,算宽无害)。 */
@@ -69,15 +70,17 @@ function toolDesc(t) {
69
70
  : `${t.toolName}(${t.argsPreview.length > TOOL_ARGS_MAX
70
71
  ? `${t.argsPreview.slice(0, TOOL_ARGS_MAX - 1)}…`
71
72
  : t.argsPreview})`;
72
- return t.progress && t.progress.length > 0 ? `${base} · ${t.progress}` : base;
73
+ const readable = humanizeToolProgress(base);
74
+ return t.progress && t.progress.length > 0 ? `${readable} · ${t.progress}` : readable;
73
75
  }
74
76
  /** 不带 progress 的静态描述(蜂群树的描述行用;进度另起 ⎿ 行)。 */
75
77
  function toolDescStatic(t) {
76
- return t.argsFriendly && t.argsFriendly.length > 0
78
+ const base = t.argsFriendly && t.argsFriendly.length > 0
77
79
  ? t.argsFriendly
78
80
  : `${t.toolName}(${t.argsPreview.length > TOOL_ARGS_MAX
79
81
  ? `${t.argsPreview.slice(0, TOOL_ARGS_MAX - 1)}…`
80
82
  : t.argsPreview})`;
83
+ return humanizeToolProgress(base);
81
84
  }
82
85
  /**
83
86
  * 蜂群树:runningTools 里有 ≥2 个并行的 Agent 子任务时,把 tool_executing
@@ -178,11 +181,14 @@ export function buildLiveView(props) {
178
181
  contentDim = false; // 答案 = 主角,默认亮色
179
182
  }
180
183
  else if (stage === 'tool_executing' && runningTools.length > 0) {
181
- // ≥2 个并行 Agent 子任务 → 蜂群树;否则既有扁平路径(单工具/单 Agent 不变)
184
+ // ≥2 个并行 Agent 子任务 → 蜂群树;普通工具用“当前正在”主行,长时
185
+ // progress 独占下一行,避免主行变长后把最关键的 15/31 等进度截掉。
182
186
  const swarm = buildSwarmLines(runningTools, maxWidth, maxLines);
183
- contentLines =
184
- swarm ??
185
- lastN(runningTools, maxLines).map((t) => clampWidthStart(` ${toolDesc(t)}`, maxWidth));
187
+ const flatLines = runningTools.flatMap((tool) => [
188
+ ` 当前正在:${toolDescStatic(tool)}`,
189
+ ...(tool.progress ? [` ${figures.elbow} ${tool.progress}`] : []),
190
+ ]);
191
+ contentLines = swarm ?? lastN(flatLines, maxLines).map((line) => clampWidthStart(line, maxWidth));
186
192
  contentDim = true;
187
193
  }
188
194
  return {
@@ -7,7 +7,7 @@
7
7
  * └ 内容区(0..N 行,有界):随阶段切换——
8
8
  * thinking → reasoningPreview 尾部最近 N 行(gray dim,首行 💭)
9
9
  * streaming → streamingText 尾部最近 N 行(默认亮色 = 答案是主角)
10
- * tool_executing → runningTools 逐行人话描述(gray dim)
10
+ * tool_executing →「当前正在」动作 + 可选独立进度行(gray dim)
11
11
  * compacting/idle→ 无内容行
12
12
  *
13
13
  * ★ 暂态错误行(transientError):工作流步执行中 LLM 调用失败(会被该步重试)时,
@@ -41,6 +41,7 @@ import {
41
41
  import { theme } from './theme.js';
42
42
  import { figures } from './figures.js';
43
43
  import type { PluginProgressState } from './hooks/useChat.js';
44
+ import { humanizeToolProgress } from './toolProgress.js';
44
45
 
45
46
  export interface LiveAreaProps {
46
47
  progressStage: ProgressStage;
@@ -64,7 +65,7 @@ export interface LiveAreaProps {
64
65
  const STAGE_LABELS: Record<Exclude<ProgressStage, 'idle'>, string> = {
65
66
  thinking: '思考中',
66
67
  streaming: '回答中',
67
- tool_executing: '调用工具',
68
+ tool_executing: '工作中',
68
69
  compacting: '压缩历史',
69
70
  };
70
71
 
@@ -103,18 +104,20 @@ function toolDesc(t: ToolStatusState): string {
103
104
  ? `${t.argsPreview.slice(0, TOOL_ARGS_MAX - 1)}…`
104
105
  : t.argsPreview
105
106
  })`;
106
- return t.progress && t.progress.length > 0 ? `${base} · ${t.progress}` : base;
107
+ const readable = humanizeToolProgress(base);
108
+ return t.progress && t.progress.length > 0 ? `${readable} · ${t.progress}` : readable;
107
109
  }
108
110
 
109
111
  /** 不带 progress 的静态描述(蜂群树的描述行用;进度另起 ⎿ 行)。 */
110
112
  function toolDescStatic(t: ToolStatusState): string {
111
- return t.argsFriendly && t.argsFriendly.length > 0
113
+ const base = t.argsFriendly && t.argsFriendly.length > 0
112
114
  ? t.argsFriendly
113
115
  : `${t.toolName}(${
114
116
  t.argsPreview.length > TOOL_ARGS_MAX
115
117
  ? `${t.argsPreview.slice(0, TOOL_ARGS_MAX - 1)}…`
116
118
  : t.argsPreview
117
119
  })`;
120
+ return humanizeToolProgress(base);
118
121
  }
119
122
 
120
123
  /**
@@ -259,13 +262,14 @@ export function buildLiveView(
259
262
  contentLines = lastN(wrapToDisplayLines(streamingText, maxWidth), maxLines);
260
263
  contentDim = false; // 答案 = 主角,默认亮色
261
264
  } else if (stage === 'tool_executing' && runningTools.length > 0) {
262
- // ≥2 个并行 Agent 子任务 → 蜂群树;否则既有扁平路径(单工具/单 Agent 不变)
265
+ // ≥2 个并行 Agent 子任务 → 蜂群树;普通工具用“当前正在”主行,长时
266
+ // progress 独占下一行,避免主行变长后把最关键的 15/31 等进度截掉。
263
267
  const swarm = buildSwarmLines(runningTools, maxWidth, maxLines);
264
- contentLines =
265
- swarm ??
266
- lastN(runningTools, maxLines).map((t) =>
267
- clampWidthStart(` ${toolDesc(t)}`, maxWidth),
268
- );
268
+ const flatLines = runningTools.flatMap((tool) => [
269
+ ` 当前正在:${toolDescStatic(tool)}`,
270
+ ...(tool.progress ? [` ${figures.elbow} ${tool.progress}`] : []),
271
+ ]);
272
+ contentLines = swarm ?? lastN(flatLines, maxLines).map((line) => clampWidthStart(line, maxWidth));
269
273
  contentDim = true;
270
274
  }
271
275
 
@@ -20,8 +20,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
20
20
  * v2 新增:
21
21
  * - assistant 分支渲染 reasoning_content / reasoning(💭 dim gray);
22
22
  * 窄终端(rows<28)折叠 2 行 + "▾ N 行 reasoning 折叠"
23
- * - tool 分支显示 tool_call_id 末 8 字符作为 [tool result · #abc12345],
24
- * "▾ 完整 N 行(输入 /show xxx 查看)" 提示用户用命令展开
23
+ * - 纯工具 assistant 每批只写一条「工作进展」并保留 /show 短 id;
24
+ * 成功的普通 tool result 不进入 scrollback,失败/顾问/Agent/交付仍保留
25
25
  * - user 分支前插 turn 头横线 "────── Turn N · 14:32 · 8s · 6 tools ──────",
26
26
  * turn 边界扫描结果由 useMemo 一次性算出,挂在 StaticItem 上
27
27
  *
@@ -29,7 +29,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
29
29
  * banner: 青色加粗 minimal-agent + 暗灰色 provider/快捷键提示
30
30
  * user: 整条青色 + "> " 前缀(输入;前置 turn 横线,若 turnMeta 非空)
31
31
  * assistant: reasoning 暗灰带 💭,content 绿色 ⏺ 锚点 + 默认亮色正文(输出),tool_calls 黄色
32
- * tool: 暗灰色,折叠(默认只显示前 3 行,末尾提示用 /show 查看)
32
+ * tool: 普通成功结果静默;高价值结果暗灰折叠,末尾提示用 /show 查看
33
33
  * ============================================================
34
34
  */
35
35
  import React from 'react';
@@ -40,6 +40,7 @@ import { splitThinkBlocks } from '../utils/stripThink.js';
40
40
  import { figures } from './figures.js';
41
41
  import { renderMarkdownLines } from './markdown.js';
42
42
  import { theme } from './theme.js';
43
+ import { toolBatchSummary, toolHistoryVisibility } from './toolProgress.js';
43
44
  /** 中断标记 user message 的固定内容(loop.ts 写入) */
44
45
  const INTERRUPT_USER_CONTENT = '(用户按下了 ESC/Ctrl+C 中断了任务)';
45
46
  const MAX_TOOL_PREVIEW_LINES = 3;
@@ -101,6 +102,16 @@ export function buildToolCallIndex(history) {
101
102
  }
102
103
  return map;
103
104
  }
105
+ /** 按 consultationId 关联持久化决定,供历史重载时在顾问卡片下恢复展示。 */
106
+ export function buildAdvisorDecisionIndex(history) {
107
+ const decisions = new Map();
108
+ for (const message of history) {
109
+ if (message.role !== 'tool' || message.display_metadata?.kind !== 'advisor_decision')
110
+ continue;
111
+ decisions.set(message.display_metadata.consultationId, message.display_metadata);
112
+ }
113
+ return decisions;
114
+ }
104
115
  /**
105
116
  * 从 Agent 子任务报告的统计尾巴(agent.ts 固定格式
106
117
  * 「(子任务「x」[type]:N 轮 · M 次工具调用,K 次失败)」)解析统计数。
@@ -217,6 +228,7 @@ export const MessageList = React.memo(function MessageList({ history, compactGen
217
228
  const items = React.useMemo(() => {
218
229
  const turnMetas = summarizeTurn(history);
219
230
  const toolIndex = buildToolCallIndex(history);
231
+ const advisorDecisions = buildAdvisorDecisionIndex(history);
220
232
  return [
221
233
  ...(bannerText
222
234
  ? [
@@ -232,6 +244,10 @@ export const MessageList = React.memo(function MessageList({ history, compactGen
232
244
  msg: m,
233
245
  turnMeta: turnMetas[idx],
234
246
  toolMeta: m.role === 'tool' ? (toolIndex.get(m.tool_call_id) ?? null) : null,
247
+ advisorDecision: m.role === 'tool'
248
+ && m.display_metadata?.kind === 'advisor_consultation'
249
+ ? (advisorDecisions.get(m.display_metadata.consultationId) ?? null)
250
+ : null,
235
251
  // 纯派生 key:有 id 用 id,没有就用 idx 兜底。绝不在 render 期 mutate 消息对象
236
252
  // (<Static> 已 commit 的行永不重绘,key 仅在 append 对账时用,idx 已足够稳定)。
237
253
  key: m.id ?? `message-${idx}`,
@@ -244,7 +260,7 @@ export const MessageList = React.memo(function MessageList({ history, compactGen
244
260
  if (item.kind === 'banner') {
245
261
  return _jsx(BannerRow, { text: item.text }, item.key);
246
262
  }
247
- return (_jsx(MessageRow, { message: item.msg, turnMeta: item.turnMeta, toolMeta: item.toolMeta, foldReasoning: foldReasoning }, item.key));
263
+ return (_jsx(MessageRow, { message: item.msg, turnMeta: item.turnMeta, toolMeta: item.toolMeta, advisorDecision: item.advisorDecision, foldReasoning: foldReasoning }, item.key));
248
264
  } }, compactGeneration));
249
265
  });
250
266
  function BannerRow({ text }) {
@@ -255,7 +271,7 @@ function BannerRow({ text }) {
255
271
  const tail = splitAt >= 0 ? text.slice(splitAt) : '';
256
272
  return (_jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { color: theme.user, bold: true, children: head }), tail.length > 0 && _jsx(Text, { color: theme.subtle, children: tail })] }));
257
273
  }
258
- function MessageRow({ message, turnMeta, toolMeta, foldReasoning, }) {
274
+ function MessageRow({ message, turnMeta, toolMeta, advisorDecision, foldReasoning, }) {
259
275
  switch (message.role) {
260
276
  case 'system': {
261
277
  // v2.x:ephemeral system message 是 UI 临时提示(slash 命令输出等),
@@ -292,10 +308,17 @@ function MessageRow({ message, turnMeta, toolMeta, foldReasoning, }) {
292
308
  truncatedCharsHint = `...(${omitted} 字省略)`;
293
309
  }
294
310
  const reasoningLines = reasoningText.length > 0 ? reasoningText.split('\n') : [];
295
- const visibleReasoningLines = foldReasoning
296
- ? reasoningLines.slice(0, 2)
297
- : reasoningLines;
298
- const hiddenReasoningCount = reasoningLines.length - visibleReasoningLines.length;
311
+ // 纯工具回合的 reasoning 已在 LiveArea 实时看过;落进 scrollback 只会把
312
+ // “工具 → 工具 → 工具”重新放大。最终回答仍保留原有 reasoning 展示。
313
+ const toolOnly = tcCount > 0 && answer.trim().length === 0;
314
+ const visibleReasoningLines = toolOnly
315
+ ? []
316
+ : foldReasoning
317
+ ? reasoningLines.slice(0, 2)
318
+ : reasoningLines;
319
+ const hiddenReasoningCount = toolOnly
320
+ ? 0
321
+ : reasoningLines.length - visibleReasoningLines.length;
299
322
  return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [visibleReasoningLines.length > 0 && (_jsxs(Box, { flexDirection: "column", children: [visibleReasoningLines.map((line, i) => (_jsx(Text, { color: theme.subtle, dimColor: true, wrap: "end", children: i === 0 ? `${figures.thought} ${line}` : ` ${line}` }, `r-${i}`))), hiddenReasoningCount > 0 && (_jsx(Text, { color: theme.subtle, dimColor: true, children: ` ${figures.fold} ${hiddenReasoningCount} 行 reasoning 折叠(终端高度 < ${NARROW_TERMINAL_ROWS})` })), truncatedCharsHint.length > 0 && (_jsx(Text, { color: theme.subtle, dimColor: true, children: ` ${truncatedCharsHint}` }))] })), buildAssistantDisplayLines(answer).map((line, i) => {
300
323
  if (line.kind === 'fence') {
301
324
  return (_jsx(Text, { color: theme.subtle, dimColor: true, wrap: line.wrap, children: line.content }, `a-${i}`));
@@ -306,33 +329,53 @@ function MessageRow({ message, turnMeta, toolMeta, foldReasoning, }) {
306
329
  return line.prefix === '⏺ ' ? (_jsxs(Box, { children: [_jsx(Text, { color: theme.anchor, bold: true, wrap: line.wrap, children: line.prefix }), _jsx(Text, { wrap: line.wrap, children: line.content.length > 0 ? line.content : ' ' })] }, `a-${i}`)) : (_jsx(Text, { wrap: line.wrap, children: `${line.prefix}${line.content}`.length > 0
307
330
  ? `${line.prefix}${line.content}`
308
331
  : ' ' }, `a-${i}`));
309
- }), tcCount > 0 && (_jsx(Text, { color: theme.warning, dimColor: true, wrap: "end", children: ` ${figures.corner} 调用了 ${tcCount} 个工具:${(message.tool_calls ?? [])
310
- .map((tc) => tc.function.name)
311
- .join(', ')}` }))] }));
332
+ }), tcCount > 0 && (_jsx(Text, { color: theme.warning, dimColor: true, wrap: "end", children: `${figures.corner} 工作进展 · ${toolBatchSummary(message.tool_calls ?? [])}` }))] }));
312
333
  }
313
334
  case 'tool': {
314
335
  const lines = message.content.split('\n');
315
336
  // 顾问意见给更高的预览上限,并用默认亮色而非 dim 灰 —— 它是另一个模型说的话,
316
337
  // 不该和 grep 输出一样被视觉降级(见 MAX_ADVISOR_PREVIEW_LINES)。
317
- const isAdvisor = toolMeta?.toolName === 'Advisor';
318
- const previewCap = toolPreviewCap(toolMeta?.toolName);
338
+ const advisorMeta = message.display_metadata?.kind === 'advisor_consultation'
339
+ ? message.display_metadata
340
+ : null;
341
+ const decisionMeta = message.display_metadata?.kind === 'advisor_decision'
342
+ ? message.display_metadata
343
+ : null;
344
+ const inferredToolName = toolMeta?.toolName
345
+ ?? (advisorMeta ? 'Advisor' : null)
346
+ ?? (decisionMeta ? 'AdvisorDecision' : null)
347
+ ?? (message.display_metadata?.kind === 'result_manifest' ? 'PresentResult' : null)
348
+ ?? (message.display_metadata?.kind === 'agent' ? 'Agent' : undefined);
349
+ const isAdvisor = inferredToolName === 'Advisor';
350
+ const isAdvisorDecision = inferredToolName === 'AdvisorDecision';
351
+ const visibility = toolHistoryVisibility(inferredToolName, message.content);
352
+ const previewCap = toolPreviewCap(inferredToolName);
319
353
  const previewLines = lines.slice(0, previewCap);
320
354
  const hidden = Math.max(0, lines.length - previewCap);
321
355
  const shortId = message.tool_call_id.slice(-8);
322
356
  // 头行升级:有 toolMeta(发起方反查命中)显示人话描述;Agent 子任务
323
357
  // 再解析统计尾巴显示 ✓ N 轮 · M 次工具。无 meta(历史重载等)兜底旧格式。
324
- const stats = toolMeta?.toolName === 'Agent' ? agentResultStats(message.content) : null;
358
+ const stats = inferredToolName === 'Agent' ? agentResultStats(message.content) : null;
325
359
  const statsTail = stats
326
360
  ? ` ${figures.ok} ${stats.turns} 轮 · ${stats.tools} 次工具${stats.failed > 0 ? `(${stats.failed} 次失败)` : ''}`
327
361
  : '';
328
362
  // 顾问头行单独成文并去掉 dim:friendlyToolDescription 没有 Advisor 分支,
329
363
  // 走兜底会显示成一串参数预览,看不出这是「第二个模型的独立意见」。
330
364
  const headText = isAdvisor
331
- ? `[顾问意见 · #${shortId}]`
332
- : toolMeta
333
- ? `[${toolMeta.friendly} · #${shortId}]${statsTail}`
334
- : `[tool result · #${shortId}]`;
335
- return (_jsx(Box, { marginBottom: 1, paddingLeft: 2, children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: theme.subtle, ...(isAdvisor ? {} : { dimColor: true }), wrap: "end", children: headText }), previewLines.map((line, i) => (_jsx(Text, { ...(isAdvisor ? {} : { color: theme.subtle }), wrap: "end", children: line.length > 0 ? line : ' ' }, `p-${i}`))), hidden > 0 && (_jsx(Text, { color: theme.subtle, dimColor: true, children: `... ${figures.fold} 完整 ${lines.length} 行(输入 /show ${shortId} 查看)` }))] }) }));
365
+ ? `[顾问意见 · ${advisorMeta?.checkpoint ?? 'manual'} · #${shortId}]`
366
+ : isAdvisorDecision
367
+ ? `[顾问意见处理 · ${decisionMeta?.decision ?? 'unknown'} · #${shortId}]`
368
+ : toolMeta
369
+ ? `[${toolMeta.friendly} · #${shortId}]${statsTail}`
370
+ : `[tool result · #${shortId}]`;
371
+ if (visibility === 'hidden')
372
+ return null;
373
+ if (visibility === 'compact') {
374
+ return (_jsx(Box, { marginBottom: 1, paddingLeft: 2, children: _jsx(Text, { color: theme.subtle, dimColor: true, wrap: "end", children: headText }) }));
375
+ }
376
+ return (_jsx(Box, { marginBottom: 1, paddingLeft: 2, children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: theme.subtle, ...(isAdvisor ? {} : { dimColor: true }), wrap: "end", children: headText }), advisorMeta && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: theme.subtle, wrap: "end", children: advisorMeta.status === 'completed'
377
+ ? `咨询 ${advisorMeta.consultationId} · 版本 ${advisorMeta.taskVersion}/${advisorMeta.workVersion}/${advisorMeta.evidenceVersion}`
378
+ : `咨询 ${advisorMeta.consultationId} 未完成,检查点已降级放行` }), advisorMeta.status === 'completed' && !advisorDecision && (_jsx(Text, { color: theme.subtle, wrap: "end", children: "\u7B49\u5F85\u4E3B Agent \u8BC4\u4F30" })), advisorDecision && (_jsx(Text, { color: theme.subtle, wrap: "end", children: `${advisorDecision.decision} · ${advisorDecision.rationale}` })), advisorDecision?.verificationPlan.map((item) => (_jsx(Text, { color: theme.subtle, wrap: "end", children: `验证:${item}` }, `advisor-card-verify-${item}`)))] })), decisionMeta && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: theme.subtle, wrap: "end", children: `关联咨询 ${decisionMeta.consultationId} · ${decisionMeta.rationale}` }), decisionMeta.verificationPlan.map((item) => (_jsx(Text, { color: theme.subtle, wrap: "end", children: `验证:${item}` }, `advisor-verify-${item}`)))] })), previewLines.map((line, i) => (_jsx(Text, { ...(isAdvisor ? {} : { color: theme.subtle }), wrap: "end", children: line.length > 0 ? line : ' ' }, `p-${i}`))), hidden > 0 && (_jsx(Text, { color: theme.subtle, dimColor: true, children: `... ${figures.fold} 完整 ${lines.length} 行(输入 /show ${shortId} 查看)` }))] }) }));
336
379
  }
337
380
  }
338
381
  }
@@ -19,8 +19,8 @@
19
19
  * v2 新增:
20
20
  * - assistant 分支渲染 reasoning_content / reasoning(💭 dim gray);
21
21
  * 窄终端(rows<28)折叠 2 行 + "▾ N 行 reasoning 折叠"
22
- * - tool 分支显示 tool_call_id 末 8 字符作为 [tool result · #abc12345],
23
- * "▾ 完整 N 行(输入 /show xxx 查看)" 提示用户用命令展开
22
+ * - 纯工具 assistant 每批只写一条「工作进展」并保留 /show 短 id;
23
+ * 成功的普通 tool result 不进入 scrollback,失败/顾问/Agent/交付仍保留
24
24
  * - user 分支前插 turn 头横线 "────── Turn N · 14:32 · 8s · 6 tools ──────",
25
25
  * turn 边界扫描结果由 useMemo 一次性算出,挂在 StaticItem 上
26
26
  *
@@ -28,7 +28,7 @@
28
28
  * banner: 青色加粗 minimal-agent + 暗灰色 provider/快捷键提示
29
29
  * user: 整条青色 + "> " 前缀(输入;前置 turn 横线,若 turnMeta 非空)
30
30
  * assistant: reasoning 暗灰带 💭,content 绿色 ⏺ 锚点 + 默认亮色正文(输出),tool_calls 黄色
31
- * tool: 暗灰色,折叠(默认只显示前 3 行,末尾提示用 /show 查看)
31
+ * tool: 普通成功结果静默;高价值结果暗灰折叠,末尾提示用 /show 查看
32
32
  * ============================================================
33
33
  */
34
34
 
@@ -37,11 +37,12 @@ import { Box, Static, Text } from 'ink';
37
37
 
38
38
  import { friendlyToolDescription } from '../loop.js';
39
39
  import { contentToDisplayText, contentToPlainText } from '../multimodal.js';
40
- import type { Message } from '../types.js';
40
+ import type { AdvisorDecisionMetadata, Message } from '../types.js';
41
41
  import { splitThinkBlocks } from '../utils/stripThink.js';
42
42
  import { figures } from './figures.js';
43
43
  import { type MdLineKind, renderMarkdownLines } from './markdown.js';
44
44
  import { theme } from './theme.js';
45
+ import { toolBatchSummary, toolHistoryVisibility } from './toolProgress.js';
45
46
 
46
47
  /**
47
48
  * Turn 元信息:每个非中断 user message 是一个 turn 的起点。
@@ -69,6 +70,7 @@ type StaticItem =
69
70
  turnMeta: TurnMeta | null;
70
71
  /** tool 消息的发起方人话描述(buildToolCallIndex 反查);其余消息 null */
71
72
  toolMeta: ToolCallMeta | null;
73
+ advisorDecision: AdvisorDecisionMetadata | null;
72
74
  key: string;
73
75
  };
74
76
 
@@ -163,6 +165,18 @@ export function buildToolCallIndex(history: Message[]): Map<string, ToolCallMeta
163
165
  return map;
164
166
  }
165
167
 
168
+ /** 按 consultationId 关联持久化决定,供历史重载时在顾问卡片下恢复展示。 */
169
+ export function buildAdvisorDecisionIndex(
170
+ history: Message[],
171
+ ): Map<string, AdvisorDecisionMetadata> {
172
+ const decisions = new Map<string, AdvisorDecisionMetadata>();
173
+ for (const message of history) {
174
+ if (message.role !== 'tool' || message.display_metadata?.kind !== 'advisor_decision') continue;
175
+ decisions.set(message.display_metadata.consultationId, message.display_metadata);
176
+ }
177
+ return decisions;
178
+ }
179
+
166
180
  /**
167
181
  * 从 Agent 子任务报告的统计尾巴(agent.ts 固定格式
168
182
  * 「(子任务「x」[type]:N 轮 · M 次工具调用,K 次失败)」)解析统计数。
@@ -296,6 +310,7 @@ export const MessageList = React.memo(function MessageList({
296
310
  const items: StaticItem[] = React.useMemo(() => {
297
311
  const turnMetas = summarizeTurn(history);
298
312
  const toolIndex = buildToolCallIndex(history);
313
+ const advisorDecisions = buildAdvisorDecisionIndex(history);
299
314
  return [
300
315
  ...(bannerText
301
316
  ? [
@@ -311,6 +326,10 @@ export const MessageList = React.memo(function MessageList({
311
326
  msg: m,
312
327
  turnMeta: turnMetas[idx],
313
328
  toolMeta: m.role === 'tool' ? (toolIndex.get(m.tool_call_id) ?? null) : null,
329
+ advisorDecision: m.role === 'tool'
330
+ && m.display_metadata?.kind === 'advisor_consultation'
331
+ ? (advisorDecisions.get(m.display_metadata.consultationId) ?? null)
332
+ : null,
314
333
  // 纯派生 key:有 id 用 id,没有就用 idx 兜底。绝不在 render 期 mutate 消息对象
315
334
  // (<Static> 已 commit 的行永不重绘,key 仅在 append 对账时用,idx 已足够稳定)。
316
335
  key: m.id ?? `message-${idx}`,
@@ -334,6 +353,7 @@ export const MessageList = React.memo(function MessageList({
334
353
  message={item.msg}
335
354
  turnMeta={item.turnMeta}
336
355
  toolMeta={item.toolMeta}
356
+ advisorDecision={item.advisorDecision}
337
357
  foldReasoning={foldReasoning}
338
358
  />
339
359
  );
@@ -362,11 +382,13 @@ function MessageRow({
362
382
  message,
363
383
  turnMeta,
364
384
  toolMeta,
385
+ advisorDecision,
365
386
  foldReasoning,
366
387
  }: {
367
388
  message: Message;
368
389
  turnMeta: TurnMeta | null;
369
390
  toolMeta?: ToolCallMeta | null;
391
+ advisorDecision?: AdvisorDecisionMetadata | null;
370
392
  foldReasoning: boolean;
371
393
  }): JSX.Element | null {
372
394
  switch (message.role) {
@@ -436,11 +458,17 @@ function MessageRow({
436
458
  }
437
459
  const reasoningLines =
438
460
  reasoningText.length > 0 ? reasoningText.split('\n') : [];
439
- const visibleReasoningLines = foldReasoning
440
- ? reasoningLines.slice(0, 2)
441
- : reasoningLines;
442
- const hiddenReasoningCount =
443
- reasoningLines.length - visibleReasoningLines.length;
461
+ // 纯工具回合的 reasoning 已在 LiveArea 实时看过;落进 scrollback 只会把
462
+ // “工具 → 工具 → 工具”重新放大。最终回答仍保留原有 reasoning 展示。
463
+ const toolOnly = tcCount > 0 && answer.trim().length === 0;
464
+ const visibleReasoningLines = toolOnly
465
+ ? []
466
+ : foldReasoning
467
+ ? reasoningLines.slice(0, 2)
468
+ : reasoningLines;
469
+ const hiddenReasoningCount = toolOnly
470
+ ? 0
471
+ : reasoningLines.length - visibleReasoningLines.length;
444
472
 
445
473
  return (
446
474
  <Box flexDirection="column" marginBottom={1}>
@@ -503,9 +531,7 @@ function MessageRow({
503
531
  })}
504
532
  {tcCount > 0 && (
505
533
  <Text color={theme.warning} dimColor wrap="end">
506
- {` ${figures.corner} 调用了 ${tcCount} 个工具:${(message.tool_calls ?? [])
507
- .map((tc) => tc.function.name)
508
- .join(', ')}`}
534
+ {`${figures.corner} 工作进展 · ${toolBatchSummary(message.tool_calls ?? [])}`}
509
535
  </Text>
510
536
  )}
511
537
  </Box>
@@ -515,31 +541,90 @@ function MessageRow({
515
541
  const lines = message.content.split('\n');
516
542
  // 顾问意见给更高的预览上限,并用默认亮色而非 dim 灰 —— 它是另一个模型说的话,
517
543
  // 不该和 grep 输出一样被视觉降级(见 MAX_ADVISOR_PREVIEW_LINES)。
518
- const isAdvisor = toolMeta?.toolName === 'Advisor';
519
- const previewCap = toolPreviewCap(toolMeta?.toolName);
544
+ const advisorMeta = message.display_metadata?.kind === 'advisor_consultation'
545
+ ? message.display_metadata
546
+ : null;
547
+ const decisionMeta = message.display_metadata?.kind === 'advisor_decision'
548
+ ? message.display_metadata
549
+ : null;
550
+ const inferredToolName = toolMeta?.toolName
551
+ ?? (advisorMeta ? 'Advisor' : null)
552
+ ?? (decisionMeta ? 'AdvisorDecision' : null)
553
+ ?? (message.display_metadata?.kind === 'result_manifest' ? 'PresentResult' : null)
554
+ ?? (message.display_metadata?.kind === 'agent' ? 'Agent' : undefined);
555
+ const isAdvisor = inferredToolName === 'Advisor';
556
+ const isAdvisorDecision = inferredToolName === 'AdvisorDecision';
557
+ const visibility = toolHistoryVisibility(inferredToolName, message.content);
558
+ const previewCap = toolPreviewCap(inferredToolName);
520
559
  const previewLines = lines.slice(0, previewCap);
521
560
  const hidden = Math.max(0, lines.length - previewCap);
522
561
  const shortId = message.tool_call_id.slice(-8);
523
562
  // 头行升级:有 toolMeta(发起方反查命中)显示人话描述;Agent 子任务
524
563
  // 再解析统计尾巴显示 ✓ N 轮 · M 次工具。无 meta(历史重载等)兜底旧格式。
525
564
  const stats =
526
- toolMeta?.toolName === 'Agent' ? agentResultStats(message.content) : null;
565
+ inferredToolName === 'Agent' ? agentResultStats(message.content) : null;
527
566
  const statsTail = stats
528
567
  ? ` ${figures.ok} ${stats.turns} 轮 · ${stats.tools} 次工具${stats.failed > 0 ? `(${stats.failed} 次失败)` : ''}`
529
568
  : '';
530
569
  // 顾问头行单独成文并去掉 dim:friendlyToolDescription 没有 Advisor 分支,
531
570
  // 走兜底会显示成一串参数预览,看不出这是「第二个模型的独立意见」。
532
571
  const headText = isAdvisor
533
- ? `[顾问意见 · #${shortId}]`
572
+ ? `[顾问意见 · ${advisorMeta?.checkpoint ?? 'manual'} · #${shortId}]`
573
+ : isAdvisorDecision
574
+ ? `[顾问意见处理 · ${decisionMeta?.decision ?? 'unknown'} · #${shortId}]`
534
575
  : toolMeta
535
576
  ? `[${toolMeta.friendly} · #${shortId}]${statsTail}`
536
577
  : `[tool result · #${shortId}]`;
578
+ if (visibility === 'hidden') return null;
579
+ if (visibility === 'compact') {
580
+ return (
581
+ <Box marginBottom={1} paddingLeft={2}>
582
+ <Text color={theme.subtle} dimColor wrap="end">
583
+ {headText}
584
+ </Text>
585
+ </Box>
586
+ );
587
+ }
537
588
  return (
538
589
  <Box marginBottom={1} paddingLeft={2}>
539
590
  <Box flexDirection="column">
540
591
  <Text color={theme.subtle} {...(isAdvisor ? {} : { dimColor: true })} wrap="end">
541
592
  {headText}
542
593
  </Text>
594
+ {advisorMeta && (
595
+ <Box flexDirection="column">
596
+ <Text color={theme.subtle} wrap="end">
597
+ {advisorMeta.status === 'completed'
598
+ ? `咨询 ${advisorMeta.consultationId} · 版本 ${advisorMeta.taskVersion}/${advisorMeta.workVersion}/${advisorMeta.evidenceVersion}`
599
+ : `咨询 ${advisorMeta.consultationId} 未完成,检查点已降级放行`}
600
+ </Text>
601
+ {advisorMeta.status === 'completed' && !advisorDecision && (
602
+ <Text color={theme.subtle} wrap="end">等待主 Agent 评估</Text>
603
+ )}
604
+ {advisorDecision && (
605
+ <Text color={theme.subtle} wrap="end">
606
+ {`${advisorDecision.decision} · ${advisorDecision.rationale}`}
607
+ </Text>
608
+ )}
609
+ {advisorDecision?.verificationPlan.map((item) => (
610
+ <Text key={`advisor-card-verify-${item}`} color={theme.subtle} wrap="end">
611
+ {`验证:${item}`}
612
+ </Text>
613
+ ))}
614
+ </Box>
615
+ )}
616
+ {decisionMeta && (
617
+ <Box flexDirection="column">
618
+ <Text color={theme.subtle} wrap="end">
619
+ {`关联咨询 ${decisionMeta.consultationId} · ${decisionMeta.rationale}`}
620
+ </Text>
621
+ {decisionMeta.verificationPlan.map((item) => (
622
+ <Text key={`advisor-verify-${item}`} color={theme.subtle} wrap="end">
623
+ {`验证:${item}`}
624
+ </Text>
625
+ ))}
626
+ </Box>
627
+ )}
543
628
  {/* 逐行 wrap='end':整段默认 wrap 会注入真实换行,从预览复制会被硬断行 */}
544
629
  {previewLines.map((line, i) => (
545
630
  <Text key={`p-${i}`} {...(isAdvisor ? {} : { color: theme.subtle })} wrap="end">
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState } from 'react';
3
2
  import { Box, Text, useInput } from 'ink';
3
+ import { useState } from 'react';
4
4
  import { theme } from './theme.js';
5
5
  export function ModelPicker({ models, currentModelId, title, nullOptionLabel, onSelect, onCancel, }) {
6
- const enabledModels = models.filter((m) => m.enabled && m.apiKey);
6
+ const enabledModels = models.filter((m) => m.enabled && (m.source === 'gateway' || m.apiKey));
7
7
  const hasNullOption = Boolean(nullOptionLabel);
8
8
  const nullIndex = hasNullOption ? enabledModels.length : -1;
9
9
  const listLength = enabledModels.length + (hasNullOption ? 1 : 0);
@@ -35,7 +35,10 @@ export function ModelPicker({ models, currentModelId, title, nullOptionLabel, on
35
35
  }
36
36
  else {
37
37
  const target = enabledModels[idx];
38
- if (target)
38
+ if (target &&
39
+ (target.source !== 'gateway' ||
40
+ !target.availability ||
41
+ target.availability.state === 'available'))
39
42
  onSelect(target.id);
40
43
  }
41
44
  }
@@ -44,7 +47,7 @@ export function ModelPicker({ models, currentModelId, title, nullOptionLabel, on
44
47
  const active = i === idx;
45
48
  const isCurrent = m.id === currentModelId;
46
49
  const displayName = m.displayName || m.model;
47
- return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: active ? theme.user : undefined, children: [active ? '> ' : ' ', isCurrent ? '✓ ' : ' ', _jsx(Text, { color: active ? theme.user : undefined, bold: isCurrent, children: displayName }), isCurrent ? _jsx(Text, { color: theme.subtle, children: " \uFF08\u5F53\u524D\uFF09" }) : null] }), _jsxs(Text, { color: theme.subtle, children: [' ', m.model, " \u00B7 ", formatContextWindow(m.contextWindow)] })] }, m.id));
50
+ return (_jsxs(Box, { flexDirection: "column", children: [i > 0 && enabledModels[i - 1]?.source !== m.source ? (_jsxs(Text, { color: theme.subtle, children: [' ', "\u2500\u2500 ", m.source === 'gateway' ? '团队在线模型' : '本机模型', " \u2500\u2500"] })) : null, _jsxs(Text, { color: active ? theme.user : undefined, children: [active ? '> ' : ' ', isCurrent ? '✓ ' : ' ', _jsxs(Text, { color: active ? theme.user : undefined, bold: isCurrent, children: [m.source === 'gateway' ? '🌐 ' : '', displayName, m.isDefault ? ' · 默认' : '', m.availability?.reason ? ` · ${m.availability.reason}` : ''] }), isCurrent ? _jsx(Text, { color: theme.subtle, children: " \uFF08\u5F53\u524D\uFF09" }) : null] }), _jsxs(Text, { color: theme.subtle, children: [' ', m.model, " \u00B7 ", formatContextWindow(m.contextWindow)] })] }, m.id));
48
51
  }), hasNullOption && (_jsxs(Text, { color: idx === nullIndex ? theme.user : theme.subtle, children: [idx === nullIndex ? '> ' : ' ', !currentModelId ? '✓ ' : ' ', nullOptionLabel] }))] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: theme.subtle, children: "\u2191\u2193 \u9009\u62E9 \u00B7 Enter \u786E\u8BA4 \u00B7 ESC \u53D6\u6D88" }) })] }));
49
52
  }
50
53
  function formatContextWindow(tokens) {