minimal-agent 0.12.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 (472) hide show
  1. package/README.md +6 -5
  2. package/package.json +62 -5
  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 +204 -185
  16. package/plugins/workflow-runner/src/index.ts +249 -224
  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 +404 -467
  28. package/plugins/workflow-runner/src/runner.ts +491 -535
  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 +172 -152
  54. package/plugins/workflow-runner/src/taskIdentity.ts +233 -200
  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 -105
  58. package/plugins/workflow-runner/src/types.ts +155 -520
  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 +542 -469
  68. package/plugins/workflow-runner/src/workflowState.ts +639 -589
  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/skill-creator/scripts/run_eval.py +3 -2
  92. package/skills/ui-design/SKILL.md +5 -2
  93. package/skills/ui-design/references/layout-composition.md +1 -1
  94. package/skills/workflow-creator/SKILL.md +344 -0
  95. package/skills/workflow-creator/assets/template/workflow.mjs +48 -0
  96. package/skills/workflow-creator/references/api.md +216 -0
  97. package/skills/workflow-creator/references/migration.md +103 -0
  98. package/skills/workflow-creator/references/patterns.md +779 -0
  99. package/skills/workflow-creator/scripts/list-resources.mjs +205 -0
  100. package/skills/workflow-creator/scripts/scaffold.mjs +148 -0
  101. package/skills/workflow-creator/scripts/validate.mjs +275 -0
  102. package/skills/workflow-creator/scripts/workflow-creator.test.mjs +82 -0
  103. package/src/advisor/advisorCoordinator.js +503 -0
  104. package/src/advisor/advisorCoordinator.ts +657 -0
  105. package/src/cli/configMenu.tsx +0 -1
  106. package/src/cli/print.js +44 -6
  107. package/src/cli/print.ts +73 -4
  108. package/src/cli/streamJson.js +5 -6
  109. package/src/cli/streamJson.ts +8 -4
  110. package/src/cli/wizards/advisorWizard.js +4 -2
  111. package/src/cli/wizards/advisorWizard.tsx +8 -2
  112. package/src/cli/wizards/contextAdvisorWizard.js +5 -4
  113. package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
  114. package/src/collaboration/taskFlow.js +115 -0
  115. package/src/collaboration/taskFlow.ts +169 -0
  116. package/src/config/configDefaults.js +41 -1
  117. package/src/config/configDefaults.ts +43 -1
  118. package/src/config/configDiagnostics.ts +2 -2
  119. package/src/config/configFile.js +40 -9
  120. package/src/config/configFile.ts +60 -11
  121. package/src/config/configService.js +443 -74
  122. package/src/config/configService.ts +723 -142
  123. package/src/config/numericLimits.js +22 -0
  124. package/src/config/numericLimits.ts +24 -0
  125. package/src/config.js +1 -0
  126. package/src/config.ts +3 -2
  127. package/src/context/budgetPlan.js +1 -1
  128. package/src/context/budgetPlan.ts +1 -1
  129. package/src/context/compact.js +7 -2
  130. package/src/context/compact.ts +9 -2
  131. package/src/context/microCompactLite.js +212 -13
  132. package/src/context/microCompactLite.ts +261 -12
  133. package/src/context/sessionRegistry.js +8 -1
  134. package/src/context/sessionRegistry.ts +18 -5
  135. package/src/context/toolResultArchive.js +72 -0
  136. package/src/context/toolResultArchive.ts +95 -0
  137. package/src/goal/errors.js +8 -0
  138. package/src/goal/errors.ts +18 -0
  139. package/src/goal/goalRuntime.js +344 -0
  140. package/src/goal/goalRuntime.ts +466 -0
  141. package/src/goal/goalStore.js +200 -0
  142. package/src/goal/goalStore.ts +219 -0
  143. package/src/goal/index.js +4 -0
  144. package/src/goal/index.ts +4 -0
  145. package/src/goal/statusMapping.js +71 -0
  146. package/src/goal/statusMapping.ts +95 -0
  147. package/src/goal/types.js +7 -0
  148. package/src/goal/types.ts +179 -0
  149. package/src/goal/workflowController.js +306 -0
  150. package/src/goal/workflowController.ts +360 -0
  151. package/src/harness/evidenceLedger.js +2 -0
  152. package/src/harness/evidenceLedger.ts +1 -0
  153. package/src/harness/stallGuard.js +9 -3
  154. package/src/harness/stallGuard.ts +7 -3
  155. package/src/images/imageResolver.js +161 -0
  156. package/src/images/imageResolver.ts +189 -0
  157. package/src/infra/verification.js +56 -20
  158. package/src/infra/verification.ts +87 -20
  159. package/src/llm/client.js +79 -21
  160. package/src/llm/client.ts +182 -35
  161. package/src/llm/gatewayClient.js +201 -0
  162. package/src/llm/gatewayClient.ts +299 -0
  163. package/src/llm/messageProvenance.js +46 -0
  164. package/src/llm/messageProvenance.ts +58 -0
  165. package/src/llm/modelProvider.js +1 -0
  166. package/src/llm/modelProvider.ts +22 -0
  167. package/src/llm/providers/anthropicFormat.js +108 -1
  168. package/src/llm/providers/anthropicFormat.ts +115 -4
  169. package/src/llm/providers/openaiFormat.js +9 -0
  170. package/src/llm/providers/openaiFormat.ts +12 -3
  171. package/src/loop.js +319 -54
  172. package/src/loop.ts +373 -57
  173. package/src/main.js +4 -1
  174. package/src/main.tsx +4 -1
  175. package/src/managedExecution/index.js +2 -0
  176. package/src/managedExecution/index.ts +2 -0
  177. package/src/managedExecution/registry.js +15 -0
  178. package/src/managedExecution/registry.ts +20 -0
  179. package/src/managedExecution/types.js +1 -0
  180. package/src/managedExecution/types.ts +86 -0
  181. package/src/modelRef.js +9 -0
  182. package/src/modelRef.ts +31 -0
  183. package/src/multimodal.js +14 -28
  184. package/src/multimodal.ts +17 -33
  185. package/src/net/lanDiscovery.js +65 -0
  186. package/src/net/lanDiscovery.ts +82 -0
  187. package/src/plugin-sdk.js +28 -3
  188. package/src/plugin-sdk.ts +39 -6
  189. package/src/plugins/pluginApi.ts +16 -1
  190. package/src/plugins/pluginLoader.js +4 -0
  191. package/src/plugins/pluginLoader.ts +6 -0
  192. package/src/plugins/pluginRunner.js +152 -9
  193. package/src/plugins/pluginRunner.ts +186 -8
  194. package/src/plugins/slashFallback.js +113 -0
  195. package/src/plugins/slashFallback.ts +137 -0
  196. package/src/prompts/policyRegistry.js +15 -8
  197. package/src/prompts/policyRegistry.ts +18 -8
  198. package/src/prompts/promptAssembly.js +103 -12
  199. package/src/prompts/promptAssembly.ts +114 -12
  200. package/src/prompts/skillList.js +21 -3
  201. package/src/prompts/skillList.ts +27 -2
  202. package/src/prompts/stableSystemPrompt.js +18 -0
  203. package/src/prompts/stableSystemPrompt.ts +33 -0
  204. package/src/runtime/agentRuntimeContext.js +8 -2
  205. package/src/runtime/agentRuntimeContext.ts +17 -4
  206. package/src/session/runAgentTurn.js +78 -12
  207. package/src/session/runAgentTurn.ts +105 -23
  208. package/src/session/runTurn.js +10 -9
  209. package/src/session/runTurn.ts +17 -8
  210. package/src/session/sessionState.ts +2 -0
  211. package/src/team/auth.js +186 -0
  212. package/src/team/auth.ts +298 -0
  213. package/src/team/cli.js +105 -0
  214. package/src/team/cli.ts +122 -0
  215. package/src/team/onlineToolContract.js +64 -0
  216. package/src/team/onlineToolContract.ts +109 -0
  217. package/src/team/toolPolicy.js +36 -0
  218. package/src/team/toolPolicy.ts +75 -0
  219. package/src/tools/advisor/advisor.js +148 -37
  220. package/src/tools/advisor/advisor.ts +161 -38
  221. package/src/tools/advisor/advisorDecision.js +71 -0
  222. package/src/tools/advisor/advisorDecision.ts +85 -0
  223. package/src/tools/agent/agent.js +18 -5
  224. package/src/tools/agent/agent.ts +21 -7
  225. package/src/tools/agent/agentControl.js +246 -0
  226. package/src/tools/agent/agentControl.ts +284 -0
  227. package/src/tools/agent/agentTaskService.js +40 -1
  228. package/src/tools/agent/agentTaskService.ts +44 -1
  229. package/src/tools/agent/agentTypes.js +14 -2
  230. package/src/tools/agent/agentTypes.ts +15 -2
  231. package/src/tools/applypatch/applyPatch.js +362 -0
  232. package/src/tools/applypatch/applyPatch.ts +428 -0
  233. package/src/tools/bash/bash.js +70 -18
  234. package/src/tools/bash/bash.ts +75 -20
  235. package/src/tools/capabilities.js +10 -5
  236. package/src/tools/capabilities.ts +10 -5
  237. package/src/tools/computeruse/computerIntent.js +32 -0
  238. package/src/tools/computeruse/computerIntent.ts +46 -0
  239. package/src/tools/computeruse/telemetryLog.js +12 -0
  240. package/src/tools/computeruse/telemetryLog.ts +16 -0
  241. package/src/tools/computeruse/vision/telemetry.js +1 -0
  242. package/src/tools/computeruse/vision/telemetry.ts +1 -0
  243. package/src/tools/effectiveToolSet.js +4 -0
  244. package/src/tools/effectiveToolSet.ts +4 -0
  245. package/src/tools/index.js +21 -2
  246. package/src/tools/index.ts +33 -2
  247. package/src/tools/powershell/powershell.js +18 -1
  248. package/src/tools/powershell/powershell.ts +18 -2
  249. package/src/tools/presentresult/presentresult.js +6 -15
  250. package/src/tools/presentresult/presentresult.ts +6 -15
  251. package/src/tools/read/read.js +69 -11
  252. package/src/tools/read/read.ts +70 -11
  253. package/src/tools/shared/fileUtils.js +1 -2
  254. package/src/tools/shared/fileUtils.ts +1 -2
  255. package/src/tools/shared/permanentDeleteGuard.js +34 -3
  256. package/src/tools/shared/permanentDeleteGuard.ts +43 -6
  257. package/src/tools/shared/toolOutputStore.js +23 -1
  258. package/src/tools/shared/toolOutputStore.ts +22 -1
  259. package/src/tools/skill/skill.js +9 -3
  260. package/src/tools/skill/skill.ts +8 -4
  261. package/src/tools/toolPromptGuides.js +117 -0
  262. package/src/tools/toolPromptGuides.ts +137 -0
  263. package/src/tools/webbrowser/agentBrowserPath.js +19 -9
  264. package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
  265. package/src/tools/webbrowser/browser.js +27 -11
  266. package/src/tools/webbrowser/browser.ts +68 -24
  267. package/src/tools/webbrowser/browserAutomation.js +329 -0
  268. package/src/tools/webbrowser/browserAutomation.ts +467 -0
  269. package/src/tools/webbrowser/browserAxState.js +97 -0
  270. package/src/tools/webbrowser/browserAxState.ts +142 -0
  271. package/src/tools/webbrowser/browserBatch.js +1578 -0
  272. package/src/tools/webbrowser/browserBatch.ts +2382 -0
  273. package/src/tools/webbrowser/browserCdp.js +208 -0
  274. package/src/tools/webbrowser/browserCdp.ts +255 -0
  275. package/src/tools/webbrowser/browserConditions.js +24 -0
  276. package/src/tools/webbrowser/browserConditions.ts +45 -0
  277. package/src/tools/webbrowser/browserContent.js +281 -0
  278. package/src/tools/webbrowser/browserContent.ts +438 -0
  279. package/src/tools/webbrowser/browserControl.js +131 -30
  280. package/src/tools/webbrowser/browserControl.ts +210 -50
  281. package/src/tools/webbrowser/browserDaemon.js +22 -14
  282. package/src/tools/webbrowser/browserDaemon.ts +54 -21
  283. package/src/tools/webbrowser/browserFrames.js +47 -0
  284. package/src/tools/webbrowser/browserFrames.ts +54 -0
  285. package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
  286. package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
  287. package/src/tools/webbrowser/browserLocator.js +140 -0
  288. package/src/tools/webbrowser/browserLocator.ts +194 -0
  289. package/src/tools/webbrowser/browserOutcome.js +10 -17
  290. package/src/tools/webbrowser/browserOutcome.ts +48 -31
  291. package/src/tools/webbrowser/browserRecovery.js +58 -0
  292. package/src/tools/webbrowser/browserRecovery.ts +83 -0
  293. package/src/tools/webbrowser/browserRunRegistry.js +35 -3
  294. package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
  295. package/src/tools/webbrowser/browserService.js +28 -2
  296. package/src/tools/webbrowser/browserService.ts +49 -9
  297. package/src/tools/webbrowser/browserStream.js +132 -33
  298. package/src/tools/webbrowser/browserStream.ts +224 -50
  299. package/src/tools/webbrowser/browserTabs.js +48 -15
  300. package/src/tools/webbrowser/browserTabs.ts +178 -96
  301. package/src/tools/webbrowser/webbrowser.js +683 -144
  302. package/src/tools/webbrowser/webbrowser.ts +979 -236
  303. package/src/tools/webfetch/preapproved.js +0 -2
  304. package/src/tools/webfetch/preapproved.ts +0 -2
  305. package/src/tools/websearch/websearch.js +129 -8
  306. package/src/tools/websearch/websearch.ts +138 -6
  307. package/src/types.ts +450 -42
  308. package/src/ui/App.js +377 -58
  309. package/src/ui/App.tsx +576 -111
  310. package/src/ui/LiveArea.js +14 -8
  311. package/src/ui/LiveArea.tsx +14 -10
  312. package/src/ui/MessageList.js +63 -20
  313. package/src/ui/MessageList.tsx +101 -16
  314. package/src/ui/ModelPicker.js +7 -4
  315. package/src/ui/ModelPicker.tsx +55 -8
  316. package/src/ui/hooks/useChat.js +152 -163
  317. package/src/ui/hooks/useChat.ts +396 -334
  318. package/src/ui/loginCommand.js +56 -0
  319. package/src/ui/loginCommand.ts +63 -0
  320. package/src/ui/toolProgress.js +41 -0
  321. package/src/ui/toolProgress.ts +44 -0
  322. package/src/web/browserBridge.js +20 -2
  323. package/src/web/browserBridge.ts +20 -2
  324. package/src/web/protocol.ts +1897 -194
  325. package/workflows/adaptive-research/workflow.mjs +86 -0
  326. package/workflows/e2e-capabilities/workflow.mjs +102 -0
  327. package/workflows/e2e-llm/workflow.mjs +52 -0
  328. package/workflows/e2e-smoke/workflow.mjs +59 -0
  329. package/workflows/e2e-vision-schema/README.md +48 -0
  330. package/workflows/e2e-vision-schema/workflow.mjs +149 -0
  331. package/workflows/e2e-write-greet/workflow.mjs +37 -0
  332. package/workflows/file-census/README.md +14 -0
  333. package/workflows/file-census/scripts/.gitkeep +2 -0
  334. package/workflows/file-census/workflow.mjs +110 -0
  335. package/workflows/goal/README.md +166 -0
  336. package/workflows/goal/prompts/audit.md +57 -0
  337. package/workflows/goal/prompts/contract.md +56 -0
  338. package/workflows/goal/prompts/iterate.md +37 -0
  339. package/workflows/goal/workflow.mjs +501 -0
  340. package/workflows/illustrate/README.md +90 -0
  341. package/workflows/illustrate/assets/engines.json +20 -0
  342. package/workflows/illustrate/assets/extract-baidu.js +21 -0
  343. package/workflows/illustrate/assets/extract-bing.js +33 -0
  344. package/workflows/illustrate/assets/extract-google.js +31 -0
  345. package/workflows/illustrate/workflow.mjs +301 -0
  346. package/workflows/plan/workflow.mjs +389 -0
  347. package/workflows/question-crops/README.md +35 -0
  348. package/workflows/question-crops/prompts/inventory.md +23 -0
  349. package/workflows/question-crops/scripts/image-ops.mjs +305 -0
  350. package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
  351. package/workflows/question-crops/workflow.mjs +172 -0
  352. package/workflows/ralph-loop/workflow.mjs +162 -0
  353. package/workflows/research/DESIGN.md +449 -0
  354. package/workflows/research/README.md +74 -0
  355. package/workflows/research/prompts/s0-goal.md +43 -0
  356. package/workflows/research/prompts/s1-early-exit.md +22 -0
  357. package/workflows/research/prompts/s1-map.md +58 -0
  358. package/workflows/research/prompts/s2-options.md +53 -0
  359. package/workflows/research/prompts/s3-deep-dive.md +56 -0
  360. package/workflows/research/prompts/s4-verify.md +74 -0
  361. package/workflows/research/prompts/s5-synthesis.md +81 -0
  362. package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
  363. package/workflows/research/prompts/s6-package.md +32 -0
  364. package/workflows/research/scripts/build-report.mjs +98 -0
  365. package/workflows/research/workflow.mjs +288 -0
  366. package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
  367. package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
  368. package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
  369. package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
  370. package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
  371. package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
  372. package/workflows/wechat-reading-shots/workflow.mjs +266 -0
  373. package/workflows/wrong-question-docx/README.md +55 -0
  374. package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
  375. package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
  376. package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
  377. package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
  378. package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
  379. package/workflows/wrong-question-docx/workflow.mjs +485 -0
  380. package/plugins/workflow-runner/src/agentCommon.js +0 -354
  381. package/plugins/workflow-runner/src/agentCommon.ts +0 -435
  382. package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
  383. package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
  384. package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
  385. package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
  386. package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
  387. package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
  388. package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
  389. package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
  390. package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
  391. package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
  392. package/plugins/workflow-runner/src/dslManifest.js +0 -72
  393. package/plugins/workflow-runner/src/dslManifest.ts +0 -127
  394. package/plugins/workflow-runner/src/expressions.js +0 -618
  395. package/plugins/workflow-runner/src/expressions.ts +0 -622
  396. package/plugins/workflow-runner/src/loader.js +0 -573
  397. package/plugins/workflow-runner/src/loader.ts +0 -721
  398. package/plugins/workflow-runner/src/multimodal.js +0 -38
  399. package/plugins/workflow-runner/src/multimodal.ts +0 -64
  400. package/plugins/workflow-runner/src/recovery.js +0 -119
  401. package/plugins/workflow-runner/src/recovery.ts +0 -149
  402. package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
  403. package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
  404. package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -41
  405. package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -50
  406. package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
  407. package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
  408. package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
  409. package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
  410. package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
  411. package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
  412. package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
  413. package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
  414. package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -208
  415. package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -256
  416. package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -58
  417. package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -68
  418. package/plugins/workflow-runner/src/stepPipeline.js +0 -277
  419. package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
  420. package/plugins/workflow-runner/test/agent.test.ts +0 -587
  421. package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
  422. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
  423. package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
  424. package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -147
  425. package/plugins/workflow-runner/test/context-files.test.ts +0 -320
  426. package/plugins/workflow-runner/test/e2e.test.ts +0 -370
  427. package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -226
  428. package/plugins/workflow-runner/test/expressions.test.ts +0 -397
  429. package/plugins/workflow-runner/test/foundation.test.ts +0 -126
  430. package/plugins/workflow-runner/test/graceful.test.ts +0 -139
  431. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
  432. package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
  433. package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
  434. package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
  435. package/plugins/workflow-runner/test/loader.test.ts +0 -617
  436. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
  437. package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
  438. package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
  439. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -87
  440. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
  441. package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
  442. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -220
  443. package/plugins/workflow-runner/test/recovery.test.ts +0 -265
  444. package/plugins/workflow-runner/test/runner.test.ts +0 -911
  445. package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -379
  446. package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
  447. package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -150
  448. package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
  449. package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -338
  450. package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -270
  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 -199
  468. package/workflows/schema.json +0 -176
  469. package/workflows/webppt.yaml +0 -496
  470. package/workflows/wechat-reading-shots.yaml +0 -315
  471. package/workflows/word.yaml +0 -720
  472. package/workflows/youtube-shorts.yaml +0 -202
@@ -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) {