minimal-agent 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (474) hide show
  1. package/README.md +6 -5
  2. package/package.json +60 -4
  3. package/plugins/computer_use/.claude-plugin/plugin.json +1 -1
  4. package/plugins/cron-runner/src/commands.js +4 -4
  5. package/plugins/cron-runner/src/commands.ts +4 -4
  6. package/plugins/workflow-runner/.claude-plugin/plugin.json +2 -2
  7. package/plugins/workflow-runner/commands/workflow.md +57 -90
  8. package/plugins/workflow-runner/commands/workflows.md +4 -4
  9. package/plugins/workflow-runner/plugin.js +24 -13
  10. package/plugins/workflow-runner/plugin.ts +28 -13
  11. package/plugins/workflow-runner/src/discovery.js +160 -0
  12. package/plugins/workflow-runner/src/discovery.ts +194 -0
  13. package/plugins/workflow-runner/src/goalAnchor.js +53 -0
  14. package/plugins/workflow-runner/src/goalAnchor.ts +59 -0
  15. package/plugins/workflow-runner/src/index.js +197 -206
  16. package/plugins/workflow-runner/src/index.ts +248 -249
  17. package/plugins/workflow-runner/src/inputCoercion.js +40 -0
  18. package/plugins/workflow-runner/src/inputCoercion.ts +43 -0
  19. package/plugins/workflow-runner/src/journal.js +224 -0
  20. package/plugins/workflow-runner/src/journal.ts +274 -0
  21. package/plugins/workflow-runner/src/jsonSchema.js +132 -0
  22. package/plugins/workflow-runner/src/jsonSchema.ts +162 -0
  23. package/plugins/workflow-runner/src/moduleResolution.js +64 -0
  24. package/plugins/workflow-runner/src/moduleResolution.ts +71 -0
  25. package/plugins/workflow-runner/src/resourceInputs.js +220 -0
  26. package/plugins/workflow-runner/src/resourceInputs.ts +300 -0
  27. package/plugins/workflow-runner/src/runner.js +400 -489
  28. package/plugins/workflow-runner/src/runner.ts +488 -560
  29. package/plugins/workflow-runner/src/runtime/config.js +46 -0
  30. package/plugins/workflow-runner/src/runtime/config.ts +69 -0
  31. package/plugins/workflow-runner/src/runtime/context.js +1304 -0
  32. package/plugins/workflow-runner/src/runtime/context.ts +1786 -0
  33. package/plugins/workflow-runner/src/runtime/exec.js +34 -0
  34. package/plugins/workflow-runner/src/runtime/exec.ts +53 -0
  35. package/plugins/workflow-runner/src/runtime/flow.js +8 -0
  36. package/plugins/workflow-runner/src/runtime/flow.ts +12 -0
  37. package/plugins/workflow-runner/src/runtime/fs.js +27 -0
  38. package/plugins/workflow-runner/src/runtime/fs.ts +41 -0
  39. package/plugins/workflow-runner/src/runtime/model.js +6 -0
  40. package/plugins/workflow-runner/src/runtime/model.ts +8 -0
  41. package/plugins/workflow-runner/src/runtime/output.js +7 -0
  42. package/plugins/workflow-runner/src/runtime/output.ts +21 -0
  43. package/plugins/workflow-runner/src/runtime/scheduler.js +141 -0
  44. package/plugins/workflow-runner/src/runtime/scheduler.ts +166 -0
  45. package/plugins/workflow-runner/src/runtime/state.js +16 -0
  46. package/plugins/workflow-runner/src/runtime/state.ts +19 -0
  47. package/plugins/workflow-runner/src/runtime/tools.js +3 -0
  48. package/plugins/workflow-runner/src/runtime/tools.ts +6 -0
  49. package/plugins/workflow-runner/src/sandbox.js +141 -0
  50. package/plugins/workflow-runner/src/sandbox.ts +182 -0
  51. package/plugins/workflow-runner/src/scriptGuard.d.mts +38 -0
  52. package/plugins/workflow-runner/src/scriptGuard.mjs +449 -0
  53. package/plugins/workflow-runner/src/taskIdentity.js +151 -307
  54. package/plugins/workflow-runner/src/taskIdentity.ts +207 -355
  55. package/plugins/workflow-runner/src/toolRuntime.js +29 -8
  56. package/plugins/workflow-runner/src/toolRuntime.ts +36 -11
  57. package/plugins/workflow-runner/src/types.js +7 -211
  58. package/plugins/workflow-runner/src/types.ts +154 -623
  59. package/plugins/workflow-runner/src/util.js +47 -0
  60. package/plugins/workflow-runner/src/util.ts +51 -0
  61. package/plugins/workflow-runner/src/workflowContext.js +20 -0
  62. package/plugins/workflow-runner/src/workflowContext.ts +58 -0
  63. package/plugins/workflow-runner/src/workflowDependencies.js +36 -0
  64. package/plugins/workflow-runner/src/workflowDependencies.ts +59 -0
  65. package/plugins/workflow-runner/src/workflowFingerprint.js +118 -0
  66. package/plugins/workflow-runner/src/workflowFingerprint.ts +122 -0
  67. package/plugins/workflow-runner/src/workflowState.js +474 -802
  68. package/plugins/workflow-runner/src/workflowState.ts +575 -970
  69. package/plugins/workflow-runner/test/api.test.ts +223 -0
  70. package/plugins/workflow-runner/test/apiCapabilities.test.ts +614 -0
  71. package/plugins/workflow-runner/test/apiConcurrencyGate.test.ts +104 -0
  72. package/plugins/workflow-runner/test/apiEcho.test.ts +210 -0
  73. package/plugins/workflow-runner/test/apiReadText.test.ts +178 -0
  74. package/plugins/workflow-runner/test/apiResourceLedger.test.ts +184 -0
  75. package/plugins/workflow-runner/test/childWorkflow.test.ts +304 -0
  76. package/plugins/workflow-runner/test/discovery.test.ts +234 -0
  77. package/plugins/workflow-runner/test/goalAnchor.test.ts +106 -0
  78. package/plugins/workflow-runner/test/goalController.test.ts +317 -0
  79. package/plugins/workflow-runner/test/journalLanes.test.ts +198 -0
  80. package/plugins/workflow-runner/test/listResources.test.ts +106 -0
  81. package/plugins/workflow-runner/test/resourceInputs.test.ts +294 -0
  82. package/plugins/workflow-runner/test/sandbox.test.ts +126 -0
  83. package/plugins/workflow-runner/test/scheduler.test.ts +70 -0
  84. package/plugins/workflow-runner/test/scriptGuard.test.ts +276 -0
  85. package/plugins/workflow-runner/test/skillDocSync.test.ts +78 -0
  86. package/plugins/workflow-runner/test/taskIdentity.test.ts +288 -179
  87. package/plugins/workflow-runner/test/workflowFingerprint.test.ts +106 -0
  88. package/plugins/workflow-runner/test/workflowState.test.ts +429 -0
  89. package/skills/pptx/examples/assets/cover-bg.svg +23 -0
  90. package/skills/pptx/examples/assets/icon-spark.svg +5 -0
  91. package/skills/ui-design/SKILL.md +5 -2
  92. package/skills/ui-design/references/layout-composition.md +1 -1
  93. package/skills/workflow-creator/SKILL.md +344 -0
  94. package/skills/workflow-creator/assets/template/workflow.mjs +48 -0
  95. package/skills/workflow-creator/references/api.md +216 -0
  96. package/skills/workflow-creator/references/migration.md +103 -0
  97. package/skills/workflow-creator/references/patterns.md +779 -0
  98. package/skills/workflow-creator/scripts/list-resources.mjs +205 -0
  99. package/skills/workflow-creator/scripts/scaffold.mjs +148 -0
  100. package/skills/workflow-creator/scripts/validate.mjs +275 -0
  101. package/skills/workflow-creator/scripts/workflow-creator.test.mjs +82 -0
  102. package/src/advisor/advisorCoordinator.js +536 -0
  103. package/src/advisor/advisorCoordinator.ts +693 -0
  104. package/src/cli/configMenu.tsx +0 -1
  105. package/src/cli/print.js +27 -6
  106. package/src/cli/print.ts +48 -4
  107. package/src/cli/quickModelSetup.js +12 -1
  108. package/src/cli/quickModelSetup.tsx +15 -3
  109. package/src/cli/streamJson.js +5 -6
  110. package/src/cli/streamJson.ts +8 -4
  111. package/src/cli/wizards/advisorWizard.js +4 -2
  112. package/src/cli/wizards/advisorWizard.tsx +8 -2
  113. package/src/cli/wizards/contextAdvisorWizard.js +5 -4
  114. package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
  115. package/src/cli/wizards/providerPresets.js +18 -8
  116. package/src/cli/wizards/providerPresets.ts +18 -8
  117. package/src/collaboration/taskFlow.js +115 -0
  118. package/src/collaboration/taskFlow.ts +169 -0
  119. package/src/config/configDefaults.js +41 -1
  120. package/src/config/configDefaults.ts +43 -1
  121. package/src/config/configDiagnostics.ts +2 -2
  122. package/src/config/configFile.js +40 -9
  123. package/src/config/configFile.ts +60 -11
  124. package/src/config/configService.js +419 -74
  125. package/src/config/configService.ts +703 -145
  126. package/src/config/numericLimits.js +22 -0
  127. package/src/config/numericLimits.ts +24 -0
  128. package/src/config.js +1 -0
  129. package/src/config.ts +3 -2
  130. package/src/context/budgetPlan.js +1 -1
  131. package/src/context/budgetPlan.ts +1 -1
  132. package/src/context/compact.js +7 -2
  133. package/src/context/compact.ts +9 -2
  134. package/src/context/microCompactLite.js +212 -13
  135. package/src/context/microCompactLite.ts +261 -12
  136. package/src/context/sessionRegistry.js +8 -1
  137. package/src/context/sessionRegistry.ts +18 -5
  138. package/src/context/toolResultArchive.js +72 -0
  139. package/src/context/toolResultArchive.ts +95 -0
  140. package/src/goal/errors.js +8 -0
  141. package/src/goal/errors.ts +18 -0
  142. package/src/goal/goalRuntime.js +344 -0
  143. package/src/goal/goalRuntime.ts +466 -0
  144. package/src/goal/goalStore.js +200 -0
  145. package/src/goal/goalStore.ts +219 -0
  146. package/src/goal/index.js +4 -0
  147. package/src/goal/index.ts +4 -0
  148. package/src/goal/statusMapping.js +71 -0
  149. package/src/goal/statusMapping.ts +95 -0
  150. package/src/goal/types.js +7 -0
  151. package/src/goal/types.ts +179 -0
  152. package/src/goal/workflowController.js +306 -0
  153. package/src/goal/workflowController.ts +360 -0
  154. package/src/harness/evidenceLedger.js +2 -0
  155. package/src/harness/evidenceLedger.ts +1 -0
  156. package/src/harness/stallGuard.js +9 -3
  157. package/src/harness/stallGuard.ts +7 -3
  158. package/src/images/imageResolver.js +161 -0
  159. package/src/images/imageResolver.ts +189 -0
  160. package/src/infra/verification.js +34 -5
  161. package/src/infra/verification.ts +39 -4
  162. package/src/llm/client.js +79 -21
  163. package/src/llm/client.ts +182 -35
  164. package/src/llm/gatewayClient.js +201 -0
  165. package/src/llm/gatewayClient.ts +299 -0
  166. package/src/llm/messageProvenance.js +46 -0
  167. package/src/llm/messageProvenance.ts +58 -0
  168. package/src/llm/modelProvider.js +1 -0
  169. package/src/llm/modelProvider.ts +22 -0
  170. package/src/llm/providers/anthropicFormat.js +108 -1
  171. package/src/llm/providers/anthropicFormat.ts +115 -4
  172. package/src/llm/providers/openaiFormat.js +9 -0
  173. package/src/llm/providers/openaiFormat.ts +12 -3
  174. package/src/loop.js +328 -55
  175. package/src/loop.ts +382 -58
  176. package/src/main.js +4 -1
  177. package/src/main.tsx +4 -1
  178. package/src/managedExecution/index.js +2 -0
  179. package/src/managedExecution/index.ts +2 -0
  180. package/src/managedExecution/registry.js +15 -0
  181. package/src/managedExecution/registry.ts +20 -0
  182. package/src/managedExecution/types.js +1 -0
  183. package/src/managedExecution/types.ts +86 -0
  184. package/src/modelRef.js +9 -0
  185. package/src/modelRef.ts +31 -0
  186. package/src/multimodal.js +14 -28
  187. package/src/multimodal.ts +17 -33
  188. package/src/net/lanDiscovery.js +65 -0
  189. package/src/net/lanDiscovery.ts +82 -0
  190. package/src/plugin-sdk.js +28 -3
  191. package/src/plugin-sdk.ts +39 -6
  192. package/src/plugins/pluginApi.ts +16 -1
  193. package/src/plugins/pluginLoader.js +4 -0
  194. package/src/plugins/pluginLoader.ts +6 -0
  195. package/src/plugins/pluginRunner.js +139 -7
  196. package/src/plugins/pluginRunner.ts +173 -9
  197. package/src/plugins/slashFallback.js +113 -0
  198. package/src/plugins/slashFallback.ts +137 -0
  199. package/src/prompts/policyRegistry.js +12 -32
  200. package/src/prompts/policyRegistry.ts +15 -32
  201. package/src/prompts/promptAssembly.js +103 -12
  202. package/src/prompts/promptAssembly.ts +114 -12
  203. package/src/prompts/skillList.js +21 -3
  204. package/src/prompts/skillList.ts +27 -2
  205. package/src/prompts/stableSystemPrompt.js +18 -0
  206. package/src/prompts/stableSystemPrompt.ts +33 -0
  207. package/src/runtime/agentRuntimeContext.js +8 -2
  208. package/src/runtime/agentRuntimeContext.ts +17 -4
  209. package/src/session/runAgentTurn.js +78 -12
  210. package/src/session/runAgentTurn.ts +105 -23
  211. package/src/session/runTurn.js +10 -9
  212. package/src/session/runTurn.ts +17 -8
  213. package/src/session/sessionState.ts +2 -0
  214. package/src/team/auth.js +186 -0
  215. package/src/team/auth.ts +298 -0
  216. package/src/team/cli.js +105 -0
  217. package/src/team/cli.ts +122 -0
  218. package/src/team/onlineToolContract.js +64 -0
  219. package/src/team/onlineToolContract.ts +109 -0
  220. package/src/team/toolPolicy.js +36 -0
  221. package/src/team/toolPolicy.ts +75 -0
  222. package/src/tools/advisor/advisor.js +115 -50
  223. package/src/tools/advisor/advisor.ts +124 -51
  224. package/src/tools/advisor/advisorDecision.js +71 -0
  225. package/src/tools/advisor/advisorDecision.ts +85 -0
  226. package/src/tools/agent/agent.js +18 -5
  227. package/src/tools/agent/agent.ts +21 -7
  228. package/src/tools/agent/agentControl.js +246 -0
  229. package/src/tools/agent/agentControl.ts +284 -0
  230. package/src/tools/agent/agentTaskService.js +40 -1
  231. package/src/tools/agent/agentTaskService.ts +44 -1
  232. package/src/tools/agent/agentTypes.js +14 -2
  233. package/src/tools/agent/agentTypes.ts +15 -2
  234. package/src/tools/applypatch/applyPatch.js +362 -0
  235. package/src/tools/applypatch/applyPatch.ts +428 -0
  236. package/src/tools/bash/bash.js +22 -15
  237. package/src/tools/bash/bash.ts +23 -17
  238. package/src/tools/capabilities.js +10 -5
  239. package/src/tools/capabilities.ts +10 -5
  240. package/src/tools/computeruse/computerIntent.js +32 -0
  241. package/src/tools/computeruse/computerIntent.ts +46 -0
  242. package/src/tools/computeruse/telemetryLog.js +12 -0
  243. package/src/tools/computeruse/telemetryLog.ts +16 -0
  244. package/src/tools/computeruse/vision/telemetry.js +1 -0
  245. package/src/tools/computeruse/vision/telemetry.ts +1 -0
  246. package/src/tools/effectiveToolSet.js +4 -0
  247. package/src/tools/effectiveToolSet.ts +4 -0
  248. package/src/tools/index.js +21 -2
  249. package/src/tools/index.ts +33 -2
  250. package/src/tools/presentresult/presentresult.js +6 -15
  251. package/src/tools/presentresult/presentresult.ts +6 -15
  252. package/src/tools/read/read.js +62 -9
  253. package/src/tools/read/read.ts +63 -9
  254. package/src/tools/shared/fileUtils.js +1 -2
  255. package/src/tools/shared/fileUtils.ts +1 -2
  256. package/src/tools/shared/toolOutputStore.js +23 -1
  257. package/src/tools/shared/toolOutputStore.ts +22 -1
  258. package/src/tools/skill/skill.js +9 -3
  259. package/src/tools/skill/skill.ts +8 -4
  260. package/src/tools/toolPromptGuides.js +125 -0
  261. package/src/tools/toolPromptGuides.ts +146 -0
  262. package/src/tools/webbrowser/agentBrowserPath.js +19 -9
  263. package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
  264. package/src/tools/webbrowser/browser.js +27 -11
  265. package/src/tools/webbrowser/browser.ts +68 -24
  266. package/src/tools/webbrowser/browserAutomation.js +329 -0
  267. package/src/tools/webbrowser/browserAutomation.ts +467 -0
  268. package/src/tools/webbrowser/browserAxState.js +97 -0
  269. package/src/tools/webbrowser/browserAxState.ts +142 -0
  270. package/src/tools/webbrowser/browserBatch.js +1578 -0
  271. package/src/tools/webbrowser/browserBatch.ts +2382 -0
  272. package/src/tools/webbrowser/browserCdp.js +208 -0
  273. package/src/tools/webbrowser/browserCdp.ts +255 -0
  274. package/src/tools/webbrowser/browserConditions.js +24 -0
  275. package/src/tools/webbrowser/browserConditions.ts +45 -0
  276. package/src/tools/webbrowser/browserContent.js +281 -0
  277. package/src/tools/webbrowser/browserContent.ts +438 -0
  278. package/src/tools/webbrowser/browserControl.js +131 -34
  279. package/src/tools/webbrowser/browserControl.ts +210 -56
  280. package/src/tools/webbrowser/browserDaemon.js +22 -14
  281. package/src/tools/webbrowser/browserDaemon.ts +54 -21
  282. package/src/tools/webbrowser/browserFrames.js +47 -0
  283. package/src/tools/webbrowser/browserFrames.ts +54 -0
  284. package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
  285. package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
  286. package/src/tools/webbrowser/browserLocator.js +140 -0
  287. package/src/tools/webbrowser/browserLocator.ts +194 -0
  288. package/src/tools/webbrowser/browserOutcome.js +10 -17
  289. package/src/tools/webbrowser/browserOutcome.ts +48 -31
  290. package/src/tools/webbrowser/browserRecovery.js +58 -0
  291. package/src/tools/webbrowser/browserRecovery.ts +83 -0
  292. package/src/tools/webbrowser/browserRunRegistry.js +35 -3
  293. package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
  294. package/src/tools/webbrowser/browserService.js +28 -2
  295. package/src/tools/webbrowser/browserService.ts +49 -9
  296. package/src/tools/webbrowser/browserStream.js +132 -33
  297. package/src/tools/webbrowser/browserStream.ts +224 -50
  298. package/src/tools/webbrowser/browserTabs.js +48 -15
  299. package/src/tools/webbrowser/browserTabs.ts +178 -96
  300. package/src/tools/webbrowser/webbrowser.js +679 -144
  301. package/src/tools/webbrowser/webbrowser.ts +975 -236
  302. package/src/tools/webfetch/preapproved.js +0 -2
  303. package/src/tools/webfetch/preapproved.ts +0 -2
  304. package/src/tools/websearch/websearch.js +129 -8
  305. package/src/tools/websearch/websearch.ts +138 -6
  306. package/src/types.ts +459 -40
  307. package/src/ui/App.js +377 -58
  308. package/src/ui/App.tsx +576 -111
  309. package/src/ui/LiveArea.js +14 -8
  310. package/src/ui/LiveArea.tsx +14 -10
  311. package/src/ui/MessageList.js +63 -20
  312. package/src/ui/MessageList.tsx +101 -16
  313. package/src/ui/ModelPicker.js +7 -4
  314. package/src/ui/ModelPicker.tsx +55 -8
  315. package/src/ui/hooks/useChat.js +152 -163
  316. package/src/ui/hooks/useChat.ts +396 -334
  317. package/src/ui/loginCommand.js +56 -0
  318. package/src/ui/loginCommand.ts +63 -0
  319. package/src/ui/toolProgress.js +41 -0
  320. package/src/ui/toolProgress.ts +44 -0
  321. package/src/web/browserBridge.js +20 -2
  322. package/src/web/browserBridge.ts +20 -2
  323. package/src/web/protocol.ts +1897 -194
  324. package/workflows/adaptive-research/workflow.mjs +86 -0
  325. package/workflows/e2e-capabilities/workflow.mjs +102 -0
  326. package/workflows/e2e-llm/workflow.mjs +52 -0
  327. package/workflows/e2e-smoke/workflow.mjs +59 -0
  328. package/workflows/e2e-vision-schema/README.md +48 -0
  329. package/workflows/e2e-vision-schema/workflow.mjs +149 -0
  330. package/workflows/e2e-write-greet/workflow.mjs +37 -0
  331. package/workflows/file-census/README.md +14 -0
  332. package/workflows/file-census/scripts/.gitkeep +2 -0
  333. package/workflows/file-census/workflow.mjs +110 -0
  334. package/workflows/goal/README.md +166 -0
  335. package/workflows/goal/prompts/audit.md +57 -0
  336. package/workflows/goal/prompts/contract.md +56 -0
  337. package/workflows/goal/prompts/iterate.md +37 -0
  338. package/workflows/goal/workflow.mjs +501 -0
  339. package/workflows/illustrate/README.md +90 -0
  340. package/workflows/illustrate/assets/engines.json +20 -0
  341. package/workflows/illustrate/assets/extract-baidu.js +21 -0
  342. package/workflows/illustrate/assets/extract-bing.js +33 -0
  343. package/workflows/illustrate/assets/extract-google.js +31 -0
  344. package/workflows/illustrate/workflow.mjs +301 -0
  345. package/workflows/plan/workflow.mjs +389 -0
  346. package/workflows/question-crops/README.md +35 -0
  347. package/workflows/question-crops/prompts/inventory.md +23 -0
  348. package/workflows/question-crops/scripts/image-ops.mjs +305 -0
  349. package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
  350. package/workflows/question-crops/workflow.mjs +172 -0
  351. package/workflows/ralph-loop/workflow.mjs +162 -0
  352. package/workflows/research/README.md +74 -0
  353. package/workflows/research/prompts/s0-goal.md +43 -0
  354. package/workflows/research/prompts/s1-early-exit.md +22 -0
  355. package/workflows/research/prompts/s1-map.md +58 -0
  356. package/workflows/research/prompts/s2-options.md +53 -0
  357. package/workflows/research/prompts/s3-deep-dive.md +56 -0
  358. package/workflows/research/prompts/s4-verify.md +74 -0
  359. package/workflows/research/prompts/s5-synthesis.md +81 -0
  360. package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
  361. package/workflows/research/prompts/s6-package.md +32 -0
  362. package/workflows/research/scripts/build-report.mjs +98 -0
  363. package/workflows/research/workflow.mjs +288 -0
  364. package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
  365. package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
  366. package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
  367. package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
  368. package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
  369. package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
  370. package/workflows/wechat-reading-shots/workflow.mjs +266 -0
  371. package/workflows/wrong-question-docx/README.md +55 -0
  372. package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
  373. package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
  374. package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
  375. package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
  376. package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
  377. package/workflows/wrong-question-docx/workflow.mjs +485 -0
  378. package/plugins/workflow-runner/src/agentCommon.js +0 -354
  379. package/plugins/workflow-runner/src/agentCommon.ts +0 -435
  380. package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
  381. package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
  382. package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
  383. package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
  384. package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
  385. package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
  386. package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
  387. package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
  388. package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
  389. package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
  390. package/plugins/workflow-runner/src/dslManifest.js +0 -72
  391. package/plugins/workflow-runner/src/dslManifest.ts +0 -127
  392. package/plugins/workflow-runner/src/expressions.js +0 -639
  393. package/plugins/workflow-runner/src/expressions.ts +0 -640
  394. package/plugins/workflow-runner/src/loader.js +0 -573
  395. package/plugins/workflow-runner/src/loader.ts +0 -721
  396. package/plugins/workflow-runner/src/multimodal.js +0 -38
  397. package/plugins/workflow-runner/src/multimodal.ts +0 -64
  398. package/plugins/workflow-runner/src/recovery.js +0 -126
  399. package/plugins/workflow-runner/src/recovery.ts +0 -156
  400. package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
  401. package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
  402. package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -42
  403. package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -52
  404. package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
  405. package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
  406. package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
  407. package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
  408. package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
  409. package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
  410. package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
  411. package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
  412. package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -227
  413. package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -274
  414. package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -61
  415. package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -72
  416. package/plugins/workflow-runner/src/stepPipeline.js +0 -277
  417. package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
  418. package/plugins/workflow-runner/test/agent.test.ts +0 -587
  419. package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
  420. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
  421. package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
  422. package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -167
  423. package/plugins/workflow-runner/test/context-files.test.ts +0 -320
  424. package/plugins/workflow-runner/test/e2e.test.ts +0 -370
  425. package/plugins/workflow-runner/test/e2eNewLayout.test.ts +0 -314
  426. package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -234
  427. package/plugins/workflow-runner/test/expressions.test.ts +0 -439
  428. package/plugins/workflow-runner/test/foundation.test.ts +0 -126
  429. package/plugins/workflow-runner/test/graceful.test.ts +0 -139
  430. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
  431. package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
  432. package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
  433. package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
  434. package/plugins/workflow-runner/test/loader.test.ts +0 -617
  435. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
  436. package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
  437. package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
  438. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -106
  439. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
  440. package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
  441. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -221
  442. package/plugins/workflow-runner/test/recovery.test.ts +0 -265
  443. package/plugins/workflow-runner/test/research.load.test.ts +0 -328
  444. package/plugins/workflow-runner/test/runner.test.ts +0 -911
  445. package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -436
  446. package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
  447. package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -198
  448. package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
  449. package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -354
  450. package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -324
  451. package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +0 -221
  452. package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +0 -29
  453. package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +0 -168
  454. package/plugins/workflow-runner/test/webppt.load.test.ts +0 -250
  455. package/plugins/workflow-runner/test/word.load.test.ts +0 -208
  456. package/plugins/workflow-runner/test/workflows.smoke.test.ts +0 -76
  457. package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +0 -207
  458. package/src/advisorState.js +0 -22
  459. package/src/cli/configWizard.js +0 -293
  460. package/src/tools/toolProgressBridge.js +0 -48
  461. package/workflows/adaptive-research.yaml +0 -50
  462. package/workflows/book-review-short.yaml +0 -125
  463. package/workflows/e2e-write-greet.yaml +0 -31
  464. package/workflows/illustrate.yaml +0 -227
  465. package/workflows/plan.yaml +0 -470
  466. package/workflows/ppt.yaml +0 -1670
  467. package/workflows/ralph-loop.yaml +0 -201
  468. package/workflows/research.yaml +0 -873
  469. package/workflows/schema.json +0 -176
  470. package/workflows/webppt.yaml +0 -496
  471. package/workflows/wechat-reading-shots.yaml +0 -315
  472. package/workflows/word.yaml +0 -720
  473. package/workflows/youtube-shorts.yaml +0 -202
  474. /package/workflows/{research.md → research/DESIGN.md} +0 -0
@@ -0,0 +1,501 @@
1
+ export const meta = {
2
+ apiVersion: 2,
3
+ managedRuntime: 'goal',
4
+ description:
5
+ '目标驱动的自主循环:先把目标固化成可机器验证的完成契约(不清楚就问),再「执行 → 确定性硬门 → 独立审计」反复迭代,直到达成或触发停止条件;收尾出四维质量评估报告',
6
+ inputs: [
7
+ {
8
+ name: 'objective',
9
+ required: false,
10
+ greedy: true,
11
+ description: '要达成的目标(一句话自然语言即可,不会被空格拆碎)',
12
+ },
13
+ {
14
+ name: 'checks',
15
+ default: '',
16
+ description:
17
+ "已想好的退出条件,逗号分隔(如 'shell:bun test,file_exists:dist/app.js')。给了就跳过契约拟定与确认,直接开跑",
18
+ },
19
+ { name: 'max_iterations', type: 'number', default: 8, description: '最大迭代轮数' },
20
+ {
21
+ name: 'stall_rounds',
22
+ type: 'number',
23
+ default: 3,
24
+ description: '连续几轮「失败的检查完全相同」就判定卡死并停止',
25
+ },
26
+ {
27
+ name: 'interactive',
28
+ default: 'true',
29
+ description: "'false' 则跳过契约确认闸门(无人值守场景)",
30
+ },
31
+ {
32
+ name: 'action',
33
+ type: 'enum',
34
+ values: ['start', 'status', 'pause', 'resume', 'update', 'cancel', 'accept', 'rework'],
35
+ description: 'Goal Runtime 控制动作;不填时创建、查询或继续当前 Goal',
36
+ },
37
+ { name: 'reason', description: '暂停、取消或返工原因' },
38
+ {
39
+ name: 'token_budget',
40
+ type: 'number',
41
+ description:
42
+ 'token 预算上限(input+output)。缺省不限。只在每轮开始前判定,绝不打断进行中的一轮;' +
43
+ '用尽后加大预算用同一目标重跑即可从断点继续',
44
+ },
45
+ ],
46
+ artifacts: [],
47
+ }
48
+
49
+ export default async function run(wf) {
50
+ const { values: args } = wf.input
51
+ const { sessionId: session, taskId: task, workflowDir } = wf.runtime
52
+ const { generate: llm, agent } = wf.model
53
+ const { call: tool } = wf.tools
54
+ const { shell: sh } = wf.exec
55
+ const { readText, exists } = wf.fs
56
+ const { ask } = wf.flow
57
+ const { verify } = wf.check
58
+ const { budget, resetModelContext: resetContext, addGoalSupplement, syncManagedContract } = wf.state
59
+ const echo = wf.output.message
60
+ const declareArtifact = wf.output.artifact
61
+ const log = (message) => wf.output.progress({ phase: 'workflow', status: 'update', message: String(message) })
62
+
63
+ // ============================================================
64
+ // 设计出处:对齐 OpenAI Codex 的 `/goal`(其内部叫 Ralph Loop),
65
+ // 但**有意在三处不同** —— 这三处正是我们的取向:
66
+ //
67
+ // ① **Codex 不做目标澄清**,官方明确「finish line 模糊时就别用 Goals」。
68
+ // 我们有 `ask()`,所以在阶段 0 把目标**契约化**:拟不出可验证判据时反过来问用户。
69
+ // 这是社区反复吐槽的那个坑(弱目标 → 循环不收敛 → 烧 token)的正面解法。
70
+ // ⚠️ 但只在**开头问一次**,确认后全程自主 —— 循环体里绝不停下来问。
71
+ //
72
+ // ② **完成判定是两道独立的关**,不是让干活的模型自己打分:
73
+ // 先过引擎跑的确定性硬门(`verify()` 真跑命令),再过一个 `isolated: true` 的
74
+ // 审计 agent(看不见执行者的对话,只能自己去查文件系统)。
75
+ // Codex 的 completion audit 是同一个思路,社区吐槽点恰恰是「有时仍不够严格,
76
+ // 需要额外的独立 critic」—— 隔离上下文就是为这个。
77
+ //
78
+ // ③ **质量评估只报告、不阻塞**。功能达成做门,性能/易用性/鲁棒性做报告。
79
+ // 把开放式质量判断放进停止条件,循环永远不收敛(总能再挑出一条可优化的)。
80
+ // 这条在本仓库有过真实教训:PPT 视觉门一度把对比度/字号做成硬 ERROR,
81
+ // 结果是卡死重试;后来改成质量类一律 WARNING、硬 ERROR 只留确定性缺陷。
82
+ //
83
+ // 三把停止刻度(**都只在开新一轮之前求值**,绝不打断进行中的一轮):
84
+ // · 轮数 `max_iterations` —— 最粗的兜底。
85
+ // · 无进展 `stalled` —— 真正防空转烧钱的那把。纯轮数上限拦不住「反复无效尝试」,
86
+ // 它会一直跑到撞顶;连续 N 轮失败项与失败证据完全相同才判定。
87
+ // · token 预算 `budget_limited` —— 由 Goal 契约的 `tokenBudget` 设,默认不限。
88
+ //
89
+ // ⚠️ 「只在轮次边界」是产品决策,不是实现偷懒:一轮对话一旦开始,中途超额
90
+ // 也一路跑完到节点。宁可超一点预算,也不能把 agent 停在半成品状态。
91
+ // 引擎内核因此完全不做预算检查(`loop.ts` 里一行都没有),脚本层同守此约。
92
+ // ============================================================
93
+
94
+ const DIR = `out/goal/${session}/${task}`
95
+ const CONTRACT_PATH = `${DIR}/CONTRACT.md`
96
+ const STATUS_PATH = `${DIR}/STATUS.json`
97
+ const REPORT_PATH = `${DIR}/REPORT.md`
98
+ const PROMPTS = typeof workflowDir === 'string' && workflowDir ? `${workflowDir}/prompts` : 'workflows/goal/prompts'
99
+
100
+ const MAX = Math.max(1, Math.min(Number(args.max_iterations ?? 8), 50))
101
+ const STALL = Math.max(2, Number(args.stall_rounds ?? 3))
102
+ const INTERACTIVE = String(args.interactive ?? 'true') !== 'false'
103
+ const objective = String(args.objective ?? '').trim()
104
+
105
+ /** 读 prompt 模板并替换 {{占位符}}(用 {{}} 而非 ${}:模板里有 shell/JS 示例会撞)。 */
106
+ async function prompt(name, vars = {}) {
107
+ const text = await readText(`${PROMPTS}/${name}.md`)
108
+ if (text === null) throw new Error(`读不到 prompt 模板:${PROMPTS}/${name}.md`)
109
+ let out = text
110
+ for (const [k, v] of Object.entries(vars)) {
111
+ out = out.split(`{{${k}}}`).join(String(v ?? ''))
112
+ }
113
+ return out
114
+ }
115
+
116
+ const bullets = (arr, empty = '(无)') =>
117
+ Array.isArray(arr) && arr.length ? arr.map((x) => `- ${x}`).join('\n') : empty
118
+
119
+ /**
120
+ * 一条 check 的稳定标识。停滞指纹还会加入经过时间/耗时归一化的失败证据:
121
+ * 只看名字会误伤有进展的修复,只看原始输出又会被时间戳噪音干扰。
122
+ */
123
+ function checkLabel(c) {
124
+ if (!c || typeof c !== 'object') return String(c)
125
+ switch (c.type) {
126
+ case 'shell':
127
+ return `shell:${c.command}`
128
+ case 'file_exists':
129
+ return `file_exists:${c.file}`
130
+ case 'file_contains':
131
+ return `file_contains:${c.file}:${c.pattern}`
132
+ case 'test_count':
133
+ return `test_count:${c.minCount}`
134
+ default:
135
+ return JSON.stringify(c)
136
+ }
137
+ }
138
+
139
+ /** 失败项与失败证据必须同时不变才算空转,避免“尚未全过但确有进展”的误判。 */
140
+ function evidenceFingerprint(gate, failed) {
141
+ const stable = (value) => String(value ?? '')
142
+ .replace(/\b\d{4}-\d{2}-\d{2}[T ][0-9:.+-Z]+\b/g, '<time>')
143
+ .replace(/\b\d+(?:\.\d+)?(?:ms|s)\b/g, '<duration>')
144
+ .slice(0, 4000)
145
+ return JSON.stringify({
146
+ failed: failed.slice().sort(),
147
+ evidence: (gate.details ?? [])
148
+ .filter((detail) => !detail.passed)
149
+ .map((detail) => stable(detail.summary ?? detail.output ?? detail.error)),
150
+ })
151
+ }
152
+
153
+ const CONTRACT_SCHEMA = {
154
+ type: 'object',
155
+ required: ['restated_goal', 'deliverables', 'hard_checks', 'soft_criteria'],
156
+ properties: {
157
+ restated_goal: { type: 'string' },
158
+ deliverables: { type: 'array', items: { type: 'string' } },
159
+ hard_checks: { type: 'array', items: { type: 'string' }, minItems: 1 },
160
+ soft_criteria: { type: 'array', items: { type: 'string' } },
161
+ clarifications: { type: 'array', items: { type: 'string' } },
162
+ },
163
+ }
164
+
165
+ const AUDIT_SCHEMA = {
166
+ type: 'object',
167
+ required: ['achieved', 'evidence', 'blocking_reason', 'quality'],
168
+ properties: {
169
+ achieved: { type: 'boolean' },
170
+ evidence: { type: 'array', items: { type: 'string' } },
171
+ blocking_reason: { type: 'string' },
172
+ quality: {
173
+ type: 'object',
174
+ required: ['functionality', 'performance', 'usability', 'robustness', 'notes'],
175
+ properties: {
176
+ functionality: { type: 'number', minimum: 0, maximum: 10 },
177
+ performance: { type: 'number', minimum: 0, maximum: 10 },
178
+ usability: { type: 'number', minimum: 0, maximum: 10 },
179
+ robustness: { type: 'number', minimum: 0, maximum: 10 },
180
+ notes: { type: 'string' },
181
+ },
182
+ },
183
+ },
184
+ }
185
+
186
+ const READ_ONLY = ['Read', 'Glob', 'Grep', 'Bash']
187
+
188
+ await sh(`mkdir -p ${DIR}`)
189
+
190
+ // ══ 阶段 0:把目标固化成可验证的完成契约 ═══════════════════════════════
191
+ let contract
192
+
193
+ const preset = String(args.checks ?? '')
194
+ .split(',')
195
+ .map((c) => c.trim())
196
+ .filter(Boolean)
197
+
198
+ if (preset.length > 0) {
199
+ // 用户自带退出条件 —— 这是 Codex 推荐的用法(目标自带可验证判据),直接开跑。
200
+ contract = {
201
+ restated_goal: objective,
202
+ deliverables: [],
203
+ hard_checks: preset,
204
+ soft_criteria: [],
205
+ }
206
+ log(`用户已给 ${preset.length} 条退出条件,跳过契约拟定`)
207
+ } else {
208
+ contract = await llm(await prompt('contract', { objective }), {
209
+ label: '阶段0·拟定完成契约',
210
+ schema: CONTRACT_SCHEMA,
211
+ isolated: true, // 拟契约不需要看主线对话,也不该把草案污染进去
212
+ })
213
+
214
+ // ⚠️ 用**引擎自己的解析器**验格式,不要在这里再写一份正则 ——
215
+ // `verify()` 遇到无法解析的 check 串会响亮抛错,正好拿来当校验器。
216
+ // 在契约阶段暴露,总好过第一轮迭代跑到一半才炸。
217
+ for (let fix = 0; fix <= 2; fix++) {
218
+ try {
219
+ await verify(contract.hard_checks)
220
+ break // 能解析就行,这次的通过与否不重要(此刻当然大概率不通过)
221
+ } catch (e) {
222
+ if (fix === 2) {
223
+ throw new Error(
224
+ `契约里的检查项格式反复不合法,放弃:${e.message}\n` +
225
+ '可以用 --input checks="shell:...,file_exists:..." 自己指定退出条件绕过这一步。',
226
+ )
227
+ }
228
+ log(`检查项格式不合法,第 ${fix + 1}/2 次让模型修正`)
229
+ contract = await llm(
230
+ `${await prompt('contract', { objective })}\n\n` +
231
+ `⚠️ 你上次给的 hard_checks 无法被解析:${e.message}\n` +
232
+ '请只用 shell: / file_exists: / file_contains: / test_count: 四种前缀重新给出完整契约。',
233
+ { label: `阶段0·修正检查项格式 #${fix + 1}`, schema: CONTRACT_SCHEMA, isolated: true },
234
+ )
235
+ }
236
+ }
237
+
238
+ // ── 澄清 + 确认闸门:**只在开头问这一次**,之后全程自主 ────────────
239
+ if (INTERACTIVE) {
240
+ const asks = Array.isArray(contract.clarifications) ? contract.clarifications.slice(0, 3) : []
241
+ const detail =
242
+ `📋 完成契约已拟定:\n\n【目标】${contract.restated_goal}\n\n` +
243
+ `【产出物】\n${bullets(contract.deliverables)}\n\n` +
244
+ `【必须通过的检查】(循环会真跑这些命令)\n${bullets(contract.hard_checks)}\n\n` +
245
+ `【只评估不阻塞的质量维度】\n${bullets(contract.soft_criteria)}\n` +
246
+ (asks.length ? `\n【我不确定的点】\n${bullets(asks)}\n` : '') +
247
+ '\n选「开始」进入自主循环;选「取消」放弃;选「其他」输入补充要求或修改检查项。'
248
+
249
+ const fb = await ask(detail, [
250
+ { label: '开始执行 (推荐)', description: '按此契约进入自主循环,中途不再打扰' },
251
+ { label: '取消', description: '不执行,现场保留' },
252
+ ])
253
+
254
+ if (fb.includes('取消')) {
255
+ throw new Error('用户在契约确认闸门取消(现场已保留,重跑同目标可断点续跑)')
256
+ }
257
+ if (!fb.includes('开始')) {
258
+ // 自由输入 = 补充要求。经 addGoalSupplement 贯穿后续每一次调用,
259
+ // 而不只是改一下这份契约文本 —— 用户的话要一直在场。
260
+ await addGoalSupplement(fb)
261
+ log('已记入用户补充要求,据此修订契约')
262
+ contract = await llm(
263
+ `${await prompt('contract', { objective })}\n\n` +
264
+ `⚠️ 用户看过契约草案后补充了要求,**必须实质采纳**:\n${fb}\n\n` +
265
+ `原草案:${JSON.stringify(contract)}\n\n请给出修订后的完整契约。`,
266
+ { label: '阶段0·按用户补充修订契约', schema: CONTRACT_SCHEMA, isolated: true },
267
+ )
268
+ try {
269
+ await verify(contract.hard_checks)
270
+ } catch (e) {
271
+ throw new Error(`按补充要求修订后的检查项格式不合法:${e.message}`)
272
+ }
273
+ }
274
+ }
275
+ }
276
+
277
+ const hardChecks = contract.hard_checks
278
+ await syncManagedContract({
279
+ objective: contract.restated_goal,
280
+ deliverables: contract.deliverables,
281
+ acceptanceCriteria: [...contract.hard_checks, ...contract.soft_criteria],
282
+ // 预算挂在**版本化的契约**上:改预算 = 新契约版本、留痕。
283
+ // 而已消耗量挂在 Goal 上、累计不重置 —— 所以「加预算继续跑」是自然操作,
284
+ // 不会把已经花掉的偷偷清零。
285
+ tokenBudget: Number(args.token_budget) > 0 ? Number(args.token_budget) : null,
286
+ })
287
+ const contractMd =
288
+ `# 完成契约\n\n## 目标\n${contract.restated_goal}\n\n` +
289
+ `## 产出物\n${bullets(contract.deliverables)}\n\n` +
290
+ `## 确定性检查(停止条件)\n${bullets(hardChecks)}\n\n` +
291
+ `## 质量维度(只评估,不阻塞)\n${bullets(contract.soft_criteria)}\n`
292
+
293
+ await tool('Write', { file_path: CONTRACT_PATH, content: contractMd })
294
+ declareArtifact(CONTRACT_PATH)
295
+ if (!(await exists(CONTRACT_PATH))) throw new Error(`契约写入后核实失败:${CONTRACT_PATH}`)
296
+
297
+ echo(`📋 契约已固化(${hardChecks.length} 条确定性检查)→ ${CONTRACT_PATH}`)
298
+
299
+ // ══ 阶段 1..N:执行 → 硬门 → 独立审计 ════════════════════════════════
300
+ let status = 'pursuing'
301
+ let audit = null
302
+ let lastStatusText = '(第一轮,还没有历史)'
303
+ let lastFailSig = null
304
+ let stallCount = 0
305
+ let iter = 0
306
+
307
+ const deliverablesMd = bullets(contract.deliverables)
308
+ const hardChecksMd = bullets(hardChecks)
309
+ const softMd = bullets(contract.soft_criteria)
310
+
311
+ for (iter = 1; iter <= MAX; iter++) {
312
+ // ── 预算闸:只在**开新一轮之前**求值 ──────────────────────────────
313
+ // 一轮一旦开始,中途超额也一路跑完到节点 —— 引擎内核完全不做预算检查,
314
+ // 这条纪律在脚本层也要守住:宁可超一点预算,也不能把 agent 停在半成品状态。
315
+ const money = await budget()
316
+ if (money.exhausted) {
317
+ status = 'budget_limited'
318
+ lastStatusText =
319
+ `token 预算已用尽(已花 ${money.used} / 上限 ${money.limit}),停在第 ${iter - 1} 轮结束处。\n` +
320
+ '现场已保留,加预算后用同一目标重跑即可从这里继续。'
321
+ log(lastStatusText)
322
+ break
323
+ }
324
+ if (money.limit !== null && !money.trustworthy) {
325
+ // 账偏低就如实说 —— 不能让用户以为「还剩很多」。
326
+ log('⚠️ 部分调用的 provider 没回报 usage,实际消耗高于账面数字。')
327
+ }
328
+
329
+ // 每轮干净上下文:长循环里带着前几十轮对话跑,模型会被旧上下文带偏。
330
+ // 契约本身每轮都重新拼进 prompt,所以截断不会丢关键信息。
331
+ resetContext()
332
+ log(`第 ${iter}/${MAX} 轮`)
333
+
334
+ await agent(
335
+ await prompt('iterate', {
336
+ iter: String(iter),
337
+ max: String(MAX),
338
+ restated_goal: contract.restated_goal,
339
+ deliverables: deliverablesMd,
340
+ hard_checks: hardChecksMd,
341
+ supplements: '',
342
+ last_status: lastStatusText,
343
+ }),
344
+ { label: `第 ${iter}/${MAX} 轮·执行`, maxTurns: 30 },
345
+ )
346
+
347
+ // ── 关 1:确定性硬门。引擎真跑命令,不问模型 ──────────────────────
348
+ const gate = await verify(hardChecks)
349
+ const failed = gate.details.filter((d) => !d.passed).map((d) => checkLabel(d.check))
350
+
351
+ // ── 无进展检测:失败集合与证据完全没变 = 这一轮白跑了 ──────────────
352
+ const sig = gate.passed ? '' : evidenceFingerprint(gate, failed)
353
+ if (sig && sig === lastFailSig) {
354
+ stallCount++
355
+ log(`无进展 ${stallCount}/${STALL}(失败项及证据与上轮完全相同)`)
356
+ if (stallCount >= STALL) {
357
+ status = 'stalled'
358
+ lastStatusText = `连续 ${STALL} 轮卡在同样的检查上:\n${bullets(failed)}`
359
+ break
360
+ }
361
+ } else {
362
+ stallCount = 0
363
+ lastFailSig = sig
364
+ }
365
+
366
+ if (!gate.passed) {
367
+ lastStatusText =
368
+ `第 ${iter} 轮结束时,这些检查**仍未通过**(这就是你这一轮要攻的):\n${bullets(failed)}\n\n` +
369
+ `详细输出:\n${String(gate.summary ?? '').slice(0, 1500)}`
370
+ echo(` ⏳ 第 ${iter} 轮:${hardChecks.length - failed.length}/${hardChecks.length} 项检查通过`)
371
+ continue
372
+ }
373
+
374
+ // ── 关 2:独立审计。isolated —— 看不见执行者说过什么,只能自己查 ────
375
+ echo(` ✅ 第 ${iter} 轮:确定性检查全部通过,进入独立审计`)
376
+ audit = await agent(
377
+ await prompt('audit', {
378
+ restated_goal: contract.restated_goal,
379
+ deliverables: deliverablesMd,
380
+ hard_checks: hardChecksMd,
381
+ soft_criteria: softMd,
382
+ supplements: '',
383
+ }),
384
+ {
385
+ label: `第 ${iter} 轮·独立审计`,
386
+ allowedTools: READ_ONLY,
387
+ maxTurns: 20,
388
+ isolated: true,
389
+ schema: AUDIT_SCHEMA,
390
+ },
391
+ )
392
+
393
+ if (audit.achieved) {
394
+ status = 'achieved'
395
+ break
396
+ }
397
+
398
+ lastStatusText =
399
+ `第 ${iter} 轮:确定性检查全过了,但**独立审计判定目标未达成**:\n` +
400
+ `${audit.blocking_reason}\n\n` +
401
+ '⚠️ 注意:这说明检查项覆盖不全,或产出物存在但没有实质内容。' +
402
+ '这一轮要补的是审计指出的实质缺口,不是再让检查通过一遍。'
403
+ echo(` ⚠️ 第 ${iter} 轮审计未通过:${audit.blocking_reason}`)
404
+ }
405
+
406
+ if (status === 'pursuing') status = 'max_iterations'
407
+
408
+ // ══ 收尾:状态 + 四维质量报告 ════════════════════════════════════════
409
+ // 这里是 Attempt 的兼容报告状态;Goal Runtime 才是生命周期事实源。
410
+ const STATUS_TEXT = {
411
+ achieved: '✅ Agent 自检通过,等待人类验收',
412
+ stalled: '🔁 卡死(连续多轮无进展)',
413
+ max_iterations: '⏱ 轮数耗尽,目标未达成',
414
+ // ⚠️ 与 usage_limited 分工不同:这个是**用户自己设的额度**用完了(加预算即可续);
415
+ // usage_limited 是**服务端配额/授权**不给了(要去解决授权,加预算没用)。
416
+ budget_limited: '💰 token 预算用尽,已停在轮次边界',
417
+ }
418
+
419
+ await tool('Write', {
420
+ file_path: STATUS_PATH,
421
+ content: `${JSON.stringify(
422
+ {
423
+ // 这个文件只报告本次 workflow Attempt;Goal 生命周期只能由
424
+ // GoalRuntime/GoalStore 写入,工作流不得猜测 ready_for_acceptance 或 blocked。
425
+ schemaVersion: 2,
426
+ status,
427
+ outcome: status,
428
+ authority: 'workflow-attempt',
429
+ attempt_outcome: status,
430
+ objective,
431
+ restated_goal: contract.restated_goal,
432
+ iterations_used: iter > MAX ? MAX : iter,
433
+ max_iterations: MAX,
434
+ hard_checks: hardChecks,
435
+ verification_passed: status === 'achieved',
436
+ quality: audit?.quality ?? null,
437
+ blocking_reason: status === 'achieved' ? '' : (audit?.blocking_reason ?? lastStatusText),
438
+ },
439
+ null,
440
+ 2,
441
+ )}\n`,
442
+ })
443
+ declareArtifact(STATUS_PATH)
444
+
445
+ const q = audit?.quality
446
+ const qualityMd = q
447
+ ? `## 质量评估(不作为停止条件)\n\n` +
448
+ `| 维度 | 分数 |\n|---|---|\n` +
449
+ `| 功能完整度 | ${q.functionality}/10 |\n` +
450
+ `| 性能 | ${q.performance}/10 |\n` +
451
+ `| 易用性 | ${q.usability}/10 |\n` +
452
+ `| 鲁棒性 | ${q.robustness}/10 |\n\n${q.notes}\n`
453
+ : '## 质量评估\n\n未产出 —— 本次运行没有走到独立审计那一步(确定性检查从未全部通过)。\n'
454
+
455
+ await tool('Write', {
456
+ file_path: REPORT_PATH,
457
+ content:
458
+ `# 目标执行报告\n\n**结果**:${STATUS_TEXT[status] ?? status}(用了 ${iter > MAX ? MAX : iter}/${MAX} 轮)\n\n` +
459
+ `## 目标\n${contract.restated_goal}\n\n` +
460
+ `## 契约\n${bullets(hardChecks)}\n\n` +
461
+ (audit?.evidence?.length ? `## 审计证据\n${bullets(audit.evidence)}\n\n` : '') +
462
+ (status === 'achieved' ? '' : `## 未达成原因\n${audit?.blocking_reason || lastStatusText}\n\n`) +
463
+ qualityMd,
464
+ })
465
+ declareArtifact(REPORT_PATH)
466
+
467
+ echo(`\n${STATUS_TEXT[status] ?? status}(${iter > MAX ? MAX : iter}/${MAX} 轮)`)
468
+ if (q) {
469
+ echo(
470
+ ` 质量:功能 ${q.functionality} · 性能 ${q.performance} · ` +
471
+ `易用 ${q.usability} · 鲁棒 ${q.robustness}(满分 10,仅供参考不阻塞)`,
472
+ )
473
+ echo(` ${q.notes}`)
474
+ }
475
+ if (status !== 'achieved') {
476
+ echo(` ⚠️ ${audit?.blocking_reason || lastStatusText.split('\n')[0]}`)
477
+ echo(' 现场已保留:修好阻塞点后用**同一个目标**重跑即可断点续跑。')
478
+ }
479
+ echo(` 报告:${REPORT_PATH}`)
480
+
481
+ // 未达成时抛错,让宿主的退出码/结局契约如实反映"没做成"。
482
+ // ⚠️ 这一步必须在所有落盘之后 —— 报告是排障的唯一线索,不能因为抛错而丢。
483
+ if (status !== 'achieved') {
484
+ const err = new Error(`${STATUS_TEXT[status] ?? status}:${audit?.blocking_reason || '见 ' + REPORT_PATH}`)
485
+ // 用通用 Error 属性把结局标签交给 Runner 原样转发;Runner 不解释 Goal 业务。
486
+ // 给 bridge.finish(),由 Goal 侧按 statusMapping.ts::OUTCOME_TO_ATTEMPT 精化真实状态。
487
+ // 没有这一步,budget_limited 会被引擎的通用 catch 一律记成 'failed',
488
+ // Goal 也永远到不了 budget_limited(只会落在语义完全不同的 blocked)。
489
+ err.workflowOutcome = status
490
+ throw err
491
+ }
492
+
493
+ return {
494
+ status: status === 'achieved' ? 'ready_for_acceptance' : 'blocked',
495
+ iterations: iter > MAX ? MAX : iter,
496
+ report: REPORT_PATH,
497
+ quality: q ?? null,
498
+ evidence: audit?.evidence ?? [],
499
+ contract,
500
+ }
501
+ }
@@ -0,0 +1,90 @@
1
+ # illustrate —— 网上抓图配图
2
+
3
+ ## 意图
4
+
5
+ 给一个主题词,从网上抓一批候选图,**用 LLM 逐张看图打分**(相关度 / 质量 / 是不是广告图),
6
+ 选出最合适的几张落成清单,供 PPT / 文章工作流直接消费。
7
+
8
+ 不是"搜索返回前 N 张"——搜索引擎前排常常是广告图、比价图、带店铺水印的图,
9
+ 直接拿来配图会很难看。识图打分那一步就是为了把它们剔掉。
10
+
11
+ ## 输入
12
+
13
+ | 输入 | 必填 | 说明 |
14
+ |---|:---:|---|
15
+ | `topic` | ✅ | 配图主题/关键词(贪婪首参,可一句话自然语言) |
16
+ | `count` | | 最终选出的张数,默认 3 |
17
+ | `min_candidates` | | 候选下限,某家抓到少于这个数就降级到下一家,默认 6 |
18
+
19
+ ```bash
20
+ /workflow illustrate 太空探索 科技感 蓝色 --input count=5
21
+ ```
22
+
23
+ ## ⚠️ 前置条件:浏览器 Developer Mode
24
+
25
+ 本工作流靠 `WebBrowser` 的 **`eval`** 从搜索结果页抽图 URL,而 `eval` 需要:
26
+
27
+ 1. 「设置 → 浏览器」里**开启 Developer Mode**;
28
+ 2. 把 `google.com` / `bing.com` / `image.baidu.com` 加进**站点白名单**。
29
+
30
+ 这是内核刻意的安全门禁,不是配置疏漏 —— `eval` 能在页面里执行任意 JS,
31
+ 严格强于其它调试动作,所以单独设了闸。
32
+
33
+ 没授权时的表现:`navigate` 会成功(页面打开了),但 `eval` 逐家失败,
34
+ 最终报「三家都没抓到候选图」并**列出每家的真实报错**,照着提示开授权即可。
35
+
36
+ ## 流程
37
+
38
+ ```
39
+ 阶段1-3 有序降级抓候选(Google → Bing → 百度,某家被墙/不够就换下一家)
40
+ 阶段4 逐条下载(死链/防盗链跳过,不阻断)
41
+ 阶段5 逐张识图打分(relevance / quality / is_ad)
42
+ 阶段6 确定性选优:剔广告 → relevance×quality 降序 → 取前 count
43
+ ```
44
+
45
+ ## 产物
46
+
47
+ `out/illustrate/<session>/<task>/build/illustrations.json`:
48
+
49
+ ```json
50
+ {
51
+ "topic": "…", "engine_used": "google", "count": 3,
52
+ "picks": [{ "path": "…/cand_3.img", "url": "…", "relevance": 9, "quality": 8, "reason": "…" }]
53
+ }
54
+ ```
55
+
56
+ 下游工作流读 `picks[].path` 取图即可。
57
+
58
+ ## 目录结构
59
+
60
+ ```
61
+ workflows/illustrate/
62
+ ├── workflow.mjs 主入口
63
+ └── assets/
64
+ ├── engines.json 三家引擎配置(url 模板 + 抽取器文件名)
65
+ ├── extract-google.js ← 页面改版时**只改这些**
66
+ ├── extract-bing.js
67
+ └── extract-baidu.js
68
+ ```
69
+
70
+ **加一家搜索引擎** = 往 `engines.json` 加一个条目 + 写一个 `extract-*.js`,
71
+ 主脚本一行不用动。
72
+
73
+ ## 已知坑
74
+
75
+ - **抽取器随页面改版必然失效**,这是固有脆弱、与工作流引擎无关。
76
+ 失效的表现是"某家抓到 0 个候选"(日志里看得到),改对应的
77
+ `assets/extract-*.js` 即可 —— 这正是把它们拆成独立文件的理由。
78
+
79
+ - **WebBrowser eval 的结果要 `parseJson` 两层**。抽取器里 `JSON.stringify(...)`
80
+ 返回字符串,agent-browser 显示结果时又 JSON 编码了一次,于是收到的是
81
+ 「带外层引号的双编码串」。少套一层会**静默**拿到字符串而不是数组,
82
+ 后面 `.length` 变成字符数,降级判断全错。已实测确认。
83
+
84
+ - **识图只能走 `images` 通道**。内核的 tool 结果是纯字符串,
85
+ `llm(prompt, { images: [...] })` 是让模型看见图的唯一方式。
86
+
87
+ - **选优是确定性的,不要改回让 agent 做**。原 yaml 里这步是 `agent:` ——
88
+ 让模型 Glob + Read 十几个 score 文件、心算 `relevance×quality` 再排序。
89
+ 那是 DSL 表达不了数组排序的妥协,不是该让模型做的事:模型会算错乘积、
90
+ 会漏剔广告图,而且结果不可复现。
@@ -0,0 +1,20 @@
1
+ [
2
+ {
3
+ "id": "google",
4
+ "label": "Google 图片",
5
+ "url": "https://www.google.com/search?tbm=isch&hl=en&q={{query}}",
6
+ "extractor": "extract-google.js"
7
+ },
8
+ {
9
+ "id": "bing",
10
+ "label": "Bing 图片",
11
+ "url": "https://www.bing.com/images/search?q={{query}}",
12
+ "extractor": "extract-bing.js"
13
+ },
14
+ {
15
+ "id": "baidu",
16
+ "label": "百度图片",
17
+ "url": "https://image.baidu.com/search/index?tn=baiduimage&word={{query}}",
18
+ "extractor": "extract-baidu.js"
19
+ }
20
+ ]
@@ -0,0 +1,21 @@
1
+ JSON.stringify(
2
+ Array.from(
3
+ new Set(
4
+ Array.from(document.querySelectorAll('img')).map(
5
+ (image) =>
6
+ image.getAttribute('data-imgurl') ||
7
+ image.currentSrc ||
8
+ image.src ||
9
+ image.getAttribute('data-src') ||
10
+ '',
11
+ ),
12
+ ),
13
+ )
14
+ .filter(
15
+ (url) =>
16
+ /^https?:\/\//.test(url) &&
17
+ !/\.svg($|\?)/i.test(url) &&
18
+ !/baidu\.com\/(static|img|aladdin)|bdstatic\.com|w3\.org/i.test(url),
19
+ )
20
+ .slice(0, 24),
21
+ )
@@ -0,0 +1,33 @@
1
+ JSON.stringify(
2
+ Array.from(
3
+ new Set(
4
+ [].concat(
5
+ Array.from(document.querySelectorAll('a.iusc')).map((anchor) => {
6
+ try {
7
+ return JSON.parse(anchor.getAttribute('m') || '{}').murl || ''
8
+ } catch {
9
+ return ''
10
+ }
11
+ }),
12
+ Array.from(document.querySelectorAll('a')).map((anchor) => {
13
+ try {
14
+ const url = new URL(anchor.href)
15
+ return url.searchParams.get('mediaurl') || url.searchParams.get('imgurl') || ''
16
+ } catch {
17
+ return ''
18
+ }
19
+ }),
20
+ Array.from(document.querySelectorAll('img')).map(
21
+ (image) => image.currentSrc || image.src || image.getAttribute('data-src') || '',
22
+ ),
23
+ ),
24
+ ),
25
+ )
26
+ .filter(
27
+ (url) =>
28
+ /^https?:\/\//.test(url) &&
29
+ !/\.svg($|\?)/i.test(url) &&
30
+ !/bing\.com\/(rp|sa\/)|gstatic\.com|w3\.org/i.test(url),
31
+ )
32
+ .slice(0, 24),
33
+ )