minimal-agent 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -5
- package/package.json +60 -4
- package/plugins/computer_use/.claude-plugin/plugin.json +1 -1
- package/plugins/cron-runner/src/commands.js +4 -4
- package/plugins/cron-runner/src/commands.ts +4 -4
- package/plugins/workflow-runner/.claude-plugin/plugin.json +2 -2
- package/plugins/workflow-runner/commands/workflow.md +57 -90
- package/plugins/workflow-runner/commands/workflows.md +4 -4
- package/plugins/workflow-runner/plugin.js +24 -13
- package/plugins/workflow-runner/plugin.ts +28 -13
- package/plugins/workflow-runner/src/discovery.js +160 -0
- package/plugins/workflow-runner/src/discovery.ts +194 -0
- package/plugins/workflow-runner/src/goalAnchor.js +53 -0
- package/plugins/workflow-runner/src/goalAnchor.ts +59 -0
- package/plugins/workflow-runner/src/index.js +197 -206
- package/plugins/workflow-runner/src/index.ts +248 -249
- package/plugins/workflow-runner/src/inputCoercion.js +40 -0
- package/plugins/workflow-runner/src/inputCoercion.ts +43 -0
- package/plugins/workflow-runner/src/journal.js +224 -0
- package/plugins/workflow-runner/src/journal.ts +274 -0
- package/plugins/workflow-runner/src/jsonSchema.js +132 -0
- package/plugins/workflow-runner/src/jsonSchema.ts +162 -0
- package/plugins/workflow-runner/src/moduleResolution.js +64 -0
- package/plugins/workflow-runner/src/moduleResolution.ts +71 -0
- package/plugins/workflow-runner/src/resourceInputs.js +220 -0
- package/plugins/workflow-runner/src/resourceInputs.ts +300 -0
- package/plugins/workflow-runner/src/runner.js +400 -489
- package/plugins/workflow-runner/src/runner.ts +488 -560
- package/plugins/workflow-runner/src/runtime/config.js +46 -0
- package/plugins/workflow-runner/src/runtime/config.ts +69 -0
- package/plugins/workflow-runner/src/runtime/context.js +1304 -0
- package/plugins/workflow-runner/src/runtime/context.ts +1786 -0
- package/plugins/workflow-runner/src/runtime/exec.js +34 -0
- package/plugins/workflow-runner/src/runtime/exec.ts +53 -0
- package/plugins/workflow-runner/src/runtime/flow.js +8 -0
- package/plugins/workflow-runner/src/runtime/flow.ts +12 -0
- package/plugins/workflow-runner/src/runtime/fs.js +27 -0
- package/plugins/workflow-runner/src/runtime/fs.ts +41 -0
- package/plugins/workflow-runner/src/runtime/model.js +6 -0
- package/plugins/workflow-runner/src/runtime/model.ts +8 -0
- package/plugins/workflow-runner/src/runtime/output.js +7 -0
- package/plugins/workflow-runner/src/runtime/output.ts +21 -0
- package/plugins/workflow-runner/src/runtime/scheduler.js +141 -0
- package/plugins/workflow-runner/src/runtime/scheduler.ts +166 -0
- package/plugins/workflow-runner/src/runtime/state.js +16 -0
- package/plugins/workflow-runner/src/runtime/state.ts +19 -0
- package/plugins/workflow-runner/src/runtime/tools.js +3 -0
- package/plugins/workflow-runner/src/runtime/tools.ts +6 -0
- package/plugins/workflow-runner/src/sandbox.js +141 -0
- package/plugins/workflow-runner/src/sandbox.ts +182 -0
- package/plugins/workflow-runner/src/scriptGuard.d.mts +38 -0
- package/plugins/workflow-runner/src/scriptGuard.mjs +449 -0
- package/plugins/workflow-runner/src/taskIdentity.js +151 -307
- package/plugins/workflow-runner/src/taskIdentity.ts +207 -355
- package/plugins/workflow-runner/src/toolRuntime.js +29 -8
- package/plugins/workflow-runner/src/toolRuntime.ts +36 -11
- package/plugins/workflow-runner/src/types.js +7 -211
- package/plugins/workflow-runner/src/types.ts +154 -623
- package/plugins/workflow-runner/src/util.js +47 -0
- package/plugins/workflow-runner/src/util.ts +51 -0
- package/plugins/workflow-runner/src/workflowContext.js +20 -0
- package/plugins/workflow-runner/src/workflowContext.ts +58 -0
- package/plugins/workflow-runner/src/workflowDependencies.js +36 -0
- package/plugins/workflow-runner/src/workflowDependencies.ts +59 -0
- package/plugins/workflow-runner/src/workflowFingerprint.js +118 -0
- package/plugins/workflow-runner/src/workflowFingerprint.ts +122 -0
- package/plugins/workflow-runner/src/workflowState.js +474 -802
- package/plugins/workflow-runner/src/workflowState.ts +575 -970
- package/plugins/workflow-runner/test/api.test.ts +223 -0
- package/plugins/workflow-runner/test/apiCapabilities.test.ts +614 -0
- package/plugins/workflow-runner/test/apiConcurrencyGate.test.ts +104 -0
- package/plugins/workflow-runner/test/apiEcho.test.ts +210 -0
- package/plugins/workflow-runner/test/apiReadText.test.ts +178 -0
- package/plugins/workflow-runner/test/apiResourceLedger.test.ts +184 -0
- package/plugins/workflow-runner/test/childWorkflow.test.ts +304 -0
- package/plugins/workflow-runner/test/discovery.test.ts +234 -0
- package/plugins/workflow-runner/test/goalAnchor.test.ts +106 -0
- package/plugins/workflow-runner/test/goalController.test.ts +317 -0
- package/plugins/workflow-runner/test/journalLanes.test.ts +198 -0
- package/plugins/workflow-runner/test/listResources.test.ts +106 -0
- package/plugins/workflow-runner/test/resourceInputs.test.ts +294 -0
- package/plugins/workflow-runner/test/sandbox.test.ts +126 -0
- package/plugins/workflow-runner/test/scheduler.test.ts +70 -0
- package/plugins/workflow-runner/test/scriptGuard.test.ts +276 -0
- package/plugins/workflow-runner/test/skillDocSync.test.ts +78 -0
- package/plugins/workflow-runner/test/taskIdentity.test.ts +288 -179
- package/plugins/workflow-runner/test/workflowFingerprint.test.ts +106 -0
- package/plugins/workflow-runner/test/workflowState.test.ts +429 -0
- package/skills/pptx/examples/assets/cover-bg.svg +23 -0
- package/skills/pptx/examples/assets/icon-spark.svg +5 -0
- package/skills/ui-design/SKILL.md +5 -2
- package/skills/ui-design/references/layout-composition.md +1 -1
- package/skills/workflow-creator/SKILL.md +344 -0
- package/skills/workflow-creator/assets/template/workflow.mjs +48 -0
- package/skills/workflow-creator/references/api.md +216 -0
- package/skills/workflow-creator/references/migration.md +103 -0
- package/skills/workflow-creator/references/patterns.md +779 -0
- package/skills/workflow-creator/scripts/list-resources.mjs +205 -0
- package/skills/workflow-creator/scripts/scaffold.mjs +148 -0
- package/skills/workflow-creator/scripts/validate.mjs +275 -0
- package/skills/workflow-creator/scripts/workflow-creator.test.mjs +82 -0
- package/src/advisor/advisorCoordinator.js +503 -0
- package/src/advisor/advisorCoordinator.ts +657 -0
- package/src/cli/configMenu.tsx +0 -1
- package/src/cli/print.js +27 -6
- package/src/cli/print.ts +48 -4
- package/src/cli/streamJson.js +5 -6
- package/src/cli/streamJson.ts +8 -4
- package/src/cli/wizards/advisorWizard.js +4 -2
- package/src/cli/wizards/advisorWizard.tsx +8 -2
- package/src/cli/wizards/contextAdvisorWizard.js +5 -4
- package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
- package/src/collaboration/taskFlow.js +115 -0
- package/src/collaboration/taskFlow.ts +169 -0
- package/src/config/configDefaults.js +41 -1
- package/src/config/configDefaults.ts +43 -1
- package/src/config/configDiagnostics.ts +2 -2
- package/src/config/configFile.js +40 -9
- package/src/config/configFile.ts +60 -11
- package/src/config/configService.js +419 -74
- package/src/config/configService.ts +703 -145
- package/src/config/numericLimits.js +22 -0
- package/src/config/numericLimits.ts +24 -0
- package/src/config.js +1 -0
- package/src/config.ts +3 -2
- package/src/context/budgetPlan.js +1 -1
- package/src/context/budgetPlan.ts +1 -1
- package/src/context/compact.js +7 -2
- package/src/context/compact.ts +9 -2
- package/src/context/microCompactLite.js +212 -13
- package/src/context/microCompactLite.ts +261 -12
- package/src/context/sessionRegistry.js +8 -1
- package/src/context/sessionRegistry.ts +18 -5
- package/src/context/toolResultArchive.js +72 -0
- package/src/context/toolResultArchive.ts +95 -0
- package/src/goal/errors.js +8 -0
- package/src/goal/errors.ts +18 -0
- package/src/goal/goalRuntime.js +344 -0
- package/src/goal/goalRuntime.ts +466 -0
- package/src/goal/goalStore.js +200 -0
- package/src/goal/goalStore.ts +219 -0
- package/src/goal/index.js +4 -0
- package/src/goal/index.ts +4 -0
- package/src/goal/statusMapping.js +71 -0
- package/src/goal/statusMapping.ts +95 -0
- package/src/goal/types.js +7 -0
- package/src/goal/types.ts +179 -0
- package/src/goal/workflowController.js +306 -0
- package/src/goal/workflowController.ts +360 -0
- package/src/harness/evidenceLedger.js +2 -0
- package/src/harness/evidenceLedger.ts +1 -0
- package/src/harness/stallGuard.js +9 -3
- package/src/harness/stallGuard.ts +7 -3
- package/src/images/imageResolver.js +161 -0
- package/src/images/imageResolver.ts +189 -0
- package/src/infra/verification.js +34 -5
- package/src/infra/verification.ts +39 -4
- package/src/llm/client.js +79 -21
- package/src/llm/client.ts +182 -35
- package/src/llm/gatewayClient.js +201 -0
- package/src/llm/gatewayClient.ts +299 -0
- package/src/llm/messageProvenance.js +46 -0
- package/src/llm/messageProvenance.ts +58 -0
- package/src/llm/modelProvider.js +1 -0
- package/src/llm/modelProvider.ts +22 -0
- package/src/llm/providers/anthropicFormat.js +108 -1
- package/src/llm/providers/anthropicFormat.ts +115 -4
- package/src/llm/providers/openaiFormat.js +9 -0
- package/src/llm/providers/openaiFormat.ts +12 -3
- package/src/loop.js +319 -54
- package/src/loop.ts +373 -57
- package/src/main.js +4 -1
- package/src/main.tsx +4 -1
- package/src/managedExecution/index.js +2 -0
- package/src/managedExecution/index.ts +2 -0
- package/src/managedExecution/registry.js +15 -0
- package/src/managedExecution/registry.ts +20 -0
- package/src/managedExecution/types.js +1 -0
- package/src/managedExecution/types.ts +86 -0
- package/src/modelRef.js +9 -0
- package/src/modelRef.ts +31 -0
- package/src/multimodal.js +14 -28
- package/src/multimodal.ts +17 -33
- package/src/net/lanDiscovery.js +65 -0
- package/src/net/lanDiscovery.ts +82 -0
- package/src/plugin-sdk.js +28 -3
- package/src/plugin-sdk.ts +39 -6
- package/src/plugins/pluginApi.ts +16 -1
- package/src/plugins/pluginLoader.js +4 -0
- package/src/plugins/pluginLoader.ts +6 -0
- package/src/plugins/pluginRunner.js +139 -7
- package/src/plugins/pluginRunner.ts +173 -9
- package/src/plugins/slashFallback.js +113 -0
- package/src/plugins/slashFallback.ts +137 -0
- package/src/prompts/policyRegistry.js +12 -32
- package/src/prompts/policyRegistry.ts +15 -32
- package/src/prompts/promptAssembly.js +103 -12
- package/src/prompts/promptAssembly.ts +114 -12
- package/src/prompts/skillList.js +21 -3
- package/src/prompts/skillList.ts +27 -2
- package/src/prompts/stableSystemPrompt.js +18 -0
- package/src/prompts/stableSystemPrompt.ts +33 -0
- package/src/runtime/agentRuntimeContext.js +8 -2
- package/src/runtime/agentRuntimeContext.ts +17 -4
- package/src/session/runAgentTurn.js +78 -12
- package/src/session/runAgentTurn.ts +105 -23
- package/src/session/runTurn.js +10 -9
- package/src/session/runTurn.ts +17 -8
- package/src/session/sessionState.ts +2 -0
- package/src/team/auth.js +186 -0
- package/src/team/auth.ts +298 -0
- package/src/team/cli.js +105 -0
- package/src/team/cli.ts +122 -0
- package/src/team/onlineToolContract.js +64 -0
- package/src/team/onlineToolContract.ts +109 -0
- package/src/team/toolPolicy.js +36 -0
- package/src/team/toolPolicy.ts +75 -0
- package/src/tools/advisor/advisor.js +90 -46
- package/src/tools/advisor/advisor.ts +100 -47
- package/src/tools/advisor/advisorDecision.js +71 -0
- package/src/tools/advisor/advisorDecision.ts +85 -0
- package/src/tools/agent/agent.js +18 -5
- package/src/tools/agent/agent.ts +21 -7
- package/src/tools/agent/agentControl.js +246 -0
- package/src/tools/agent/agentControl.ts +284 -0
- package/src/tools/agent/agentTaskService.js +40 -1
- package/src/tools/agent/agentTaskService.ts +44 -1
- package/src/tools/agent/agentTypes.js +14 -2
- package/src/tools/agent/agentTypes.ts +15 -2
- package/src/tools/applypatch/applyPatch.js +362 -0
- package/src/tools/applypatch/applyPatch.ts +428 -0
- package/src/tools/bash/bash.js +22 -15
- package/src/tools/bash/bash.ts +23 -17
- package/src/tools/capabilities.js +10 -5
- package/src/tools/capabilities.ts +10 -5
- package/src/tools/computeruse/computerIntent.js +32 -0
- package/src/tools/computeruse/computerIntent.ts +46 -0
- package/src/tools/computeruse/telemetryLog.js +12 -0
- package/src/tools/computeruse/telemetryLog.ts +16 -0
- package/src/tools/computeruse/vision/telemetry.js +1 -0
- package/src/tools/computeruse/vision/telemetry.ts +1 -0
- package/src/tools/effectiveToolSet.js +4 -0
- package/src/tools/effectiveToolSet.ts +4 -0
- package/src/tools/index.js +21 -2
- package/src/tools/index.ts +33 -2
- package/src/tools/presentresult/presentresult.js +6 -15
- package/src/tools/presentresult/presentresult.ts +6 -15
- package/src/tools/read/read.js +62 -9
- package/src/tools/read/read.ts +63 -9
- package/src/tools/shared/fileUtils.js +1 -2
- package/src/tools/shared/fileUtils.ts +1 -2
- package/src/tools/shared/toolOutputStore.js +23 -1
- package/src/tools/shared/toolOutputStore.ts +22 -1
- package/src/tools/skill/skill.js +9 -3
- package/src/tools/skill/skill.ts +8 -4
- package/src/tools/toolPromptGuides.js +117 -0
- package/src/tools/toolPromptGuides.ts +137 -0
- package/src/tools/webbrowser/agentBrowserPath.js +19 -9
- package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
- package/src/tools/webbrowser/browser.js +27 -11
- package/src/tools/webbrowser/browser.ts +68 -24
- package/src/tools/webbrowser/browserAutomation.js +329 -0
- package/src/tools/webbrowser/browserAutomation.ts +467 -0
- package/src/tools/webbrowser/browserAxState.js +97 -0
- package/src/tools/webbrowser/browserAxState.ts +142 -0
- package/src/tools/webbrowser/browserBatch.js +1578 -0
- package/src/tools/webbrowser/browserBatch.ts +2382 -0
- package/src/tools/webbrowser/browserCdp.js +208 -0
- package/src/tools/webbrowser/browserCdp.ts +255 -0
- package/src/tools/webbrowser/browserConditions.js +24 -0
- package/src/tools/webbrowser/browserConditions.ts +45 -0
- package/src/tools/webbrowser/browserContent.js +281 -0
- package/src/tools/webbrowser/browserContent.ts +438 -0
- package/src/tools/webbrowser/browserControl.js +131 -34
- package/src/tools/webbrowser/browserControl.ts +210 -56
- package/src/tools/webbrowser/browserDaemon.js +22 -14
- package/src/tools/webbrowser/browserDaemon.ts +54 -21
- package/src/tools/webbrowser/browserFrames.js +47 -0
- package/src/tools/webbrowser/browserFrames.ts +54 -0
- package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
- package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
- package/src/tools/webbrowser/browserLocator.js +140 -0
- package/src/tools/webbrowser/browserLocator.ts +194 -0
- package/src/tools/webbrowser/browserOutcome.js +10 -17
- package/src/tools/webbrowser/browserOutcome.ts +48 -31
- package/src/tools/webbrowser/browserRecovery.js +58 -0
- package/src/tools/webbrowser/browserRecovery.ts +83 -0
- package/src/tools/webbrowser/browserRunRegistry.js +35 -3
- package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
- package/src/tools/webbrowser/browserService.js +28 -2
- package/src/tools/webbrowser/browserService.ts +49 -9
- package/src/tools/webbrowser/browserStream.js +132 -33
- package/src/tools/webbrowser/browserStream.ts +224 -50
- package/src/tools/webbrowser/browserTabs.js +48 -15
- package/src/tools/webbrowser/browserTabs.ts +178 -96
- package/src/tools/webbrowser/webbrowser.js +679 -144
- package/src/tools/webbrowser/webbrowser.ts +975 -236
- package/src/tools/webfetch/preapproved.js +0 -2
- package/src/tools/webfetch/preapproved.ts +0 -2
- package/src/tools/websearch/websearch.js +129 -8
- package/src/tools/websearch/websearch.ts +138 -6
- package/src/types.ts +440 -38
- package/src/ui/App.js +377 -58
- package/src/ui/App.tsx +576 -111
- package/src/ui/LiveArea.js +14 -8
- package/src/ui/LiveArea.tsx +14 -10
- package/src/ui/MessageList.js +63 -20
- package/src/ui/MessageList.tsx +101 -16
- package/src/ui/ModelPicker.js +7 -4
- package/src/ui/ModelPicker.tsx +55 -8
- package/src/ui/hooks/useChat.js +152 -163
- package/src/ui/hooks/useChat.ts +396 -334
- package/src/ui/loginCommand.js +56 -0
- package/src/ui/loginCommand.ts +63 -0
- package/src/ui/toolProgress.js +41 -0
- package/src/ui/toolProgress.ts +44 -0
- package/src/web/browserBridge.js +20 -2
- package/src/web/browserBridge.ts +20 -2
- package/src/web/protocol.ts +1897 -194
- package/workflows/adaptive-research/workflow.mjs +86 -0
- package/workflows/e2e-capabilities/workflow.mjs +102 -0
- package/workflows/e2e-llm/workflow.mjs +52 -0
- package/workflows/e2e-smoke/workflow.mjs +59 -0
- package/workflows/e2e-vision-schema/README.md +48 -0
- package/workflows/e2e-vision-schema/workflow.mjs +149 -0
- package/workflows/e2e-write-greet/workflow.mjs +37 -0
- package/workflows/file-census/README.md +14 -0
- package/workflows/file-census/scripts/.gitkeep +2 -0
- package/workflows/file-census/workflow.mjs +110 -0
- package/workflows/goal/README.md +166 -0
- package/workflows/goal/prompts/audit.md +57 -0
- package/workflows/goal/prompts/contract.md +56 -0
- package/workflows/goal/prompts/iterate.md +37 -0
- package/workflows/goal/workflow.mjs +501 -0
- package/workflows/illustrate/README.md +90 -0
- package/workflows/illustrate/assets/engines.json +20 -0
- package/workflows/illustrate/assets/extract-baidu.js +21 -0
- package/workflows/illustrate/assets/extract-bing.js +33 -0
- package/workflows/illustrate/assets/extract-google.js +31 -0
- package/workflows/illustrate/workflow.mjs +301 -0
- package/workflows/plan/workflow.mjs +389 -0
- package/workflows/question-crops/README.md +35 -0
- package/workflows/question-crops/prompts/inventory.md +23 -0
- package/workflows/question-crops/scripts/image-ops.mjs +305 -0
- package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
- package/workflows/question-crops/workflow.mjs +172 -0
- package/workflows/ralph-loop/workflow.mjs +162 -0
- package/workflows/research/README.md +74 -0
- package/workflows/research/prompts/s0-goal.md +43 -0
- package/workflows/research/prompts/s1-early-exit.md +22 -0
- package/workflows/research/prompts/s1-map.md +58 -0
- package/workflows/research/prompts/s2-options.md +53 -0
- package/workflows/research/prompts/s3-deep-dive.md +56 -0
- package/workflows/research/prompts/s4-verify.md +74 -0
- package/workflows/research/prompts/s5-synthesis.md +81 -0
- package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
- package/workflows/research/prompts/s6-package.md +32 -0
- package/workflows/research/scripts/build-report.mjs +98 -0
- package/workflows/research/workflow.mjs +288 -0
- package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
- package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
- package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
- package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
- package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
- package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
- package/workflows/wechat-reading-shots/workflow.mjs +266 -0
- package/workflows/wrong-question-docx/README.md +55 -0
- package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
- package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
- package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
- package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
- package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
- package/workflows/wrong-question-docx/workflow.mjs +485 -0
- package/plugins/workflow-runner/src/agentCommon.js +0 -354
- package/plugins/workflow-runner/src/agentCommon.ts +0 -435
- package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
- package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
- package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
- package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
- package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
- package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
- package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
- package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
- package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
- package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
- package/plugins/workflow-runner/src/dslManifest.js +0 -72
- package/plugins/workflow-runner/src/dslManifest.ts +0 -127
- package/plugins/workflow-runner/src/expressions.js +0 -639
- package/plugins/workflow-runner/src/expressions.ts +0 -640
- package/plugins/workflow-runner/src/loader.js +0 -573
- package/plugins/workflow-runner/src/loader.ts +0 -721
- package/plugins/workflow-runner/src/multimodal.js +0 -38
- package/plugins/workflow-runner/src/multimodal.ts +0 -64
- package/plugins/workflow-runner/src/recovery.js +0 -126
- package/plugins/workflow-runner/src/recovery.ts +0 -156
- package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
- package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
- package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -42
- package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -52
- package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
- package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
- package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
- package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
- package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
- package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
- package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
- package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
- package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -227
- package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -274
- package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -61
- package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -72
- package/plugins/workflow-runner/src/stepPipeline.js +0 -277
- package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
- package/plugins/workflow-runner/test/agent.test.ts +0 -587
- package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
- package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
- package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
- package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -167
- package/plugins/workflow-runner/test/context-files.test.ts +0 -320
- package/plugins/workflow-runner/test/e2e.test.ts +0 -370
- package/plugins/workflow-runner/test/e2eNewLayout.test.ts +0 -314
- package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -234
- package/plugins/workflow-runner/test/expressions.test.ts +0 -439
- package/plugins/workflow-runner/test/foundation.test.ts +0 -126
- package/plugins/workflow-runner/test/graceful.test.ts +0 -139
- package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
- package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
- package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
- package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
- package/plugins/workflow-runner/test/loader.test.ts +0 -617
- package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
- package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
- package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
- package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -106
- package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
- package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
- package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -221
- package/plugins/workflow-runner/test/recovery.test.ts +0 -265
- package/plugins/workflow-runner/test/research.load.test.ts +0 -328
- package/plugins/workflow-runner/test/runner.test.ts +0 -911
- package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -436
- package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
- package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -198
- package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
- package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -354
- package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -324
- package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +0 -221
- package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +0 -29
- package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +0 -168
- package/plugins/workflow-runner/test/webppt.load.test.ts +0 -250
- package/plugins/workflow-runner/test/word.load.test.ts +0 -208
- package/plugins/workflow-runner/test/workflows.smoke.test.ts +0 -76
- package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +0 -207
- package/src/advisorState.js +0 -22
- package/src/cli/configWizard.js +0 -293
- package/src/tools/toolProgressBridge.js +0 -48
- package/workflows/adaptive-research.yaml +0 -50
- package/workflows/book-review-short.yaml +0 -125
- package/workflows/e2e-write-greet.yaml +0 -31
- package/workflows/illustrate.yaml +0 -227
- package/workflows/plan.yaml +0 -470
- package/workflows/ppt.yaml +0 -1670
- package/workflows/ralph-loop.yaml +0 -201
- package/workflows/research.yaml +0 -873
- package/workflows/schema.json +0 -176
- package/workflows/webppt.yaml +0 -496
- package/workflows/wechat-reading-shots.yaml +0 -315
- package/workflows/word.yaml +0 -720
- package/workflows/youtube-shorts.yaml +0 -202
- /package/workflows/{research.md → research/DESIGN.md} +0 -0
package/src/llm/client.js
CHANGED
|
@@ -26,7 +26,9 @@
|
|
|
26
26
|
import { dlog } from '../utils/debugLog.js';
|
|
27
27
|
import { buildOpenAIRequest, createOpenAISSEParser, isImageInputRejected, isMaxTokensRejected, isPromptCacheKeyRejected, isResponseFormatUnsupported, } from './providers/openaiFormat.js';
|
|
28
28
|
import { promptMaterialHash, shortCacheScope } from './promptCache.js';
|
|
29
|
-
import { buildAnthropicRequest, createAnthropicSSEParser } from './providers/anthropicFormat.js';
|
|
29
|
+
import { buildAnthropicRequest, createAnthropicSSEParser, } from './providers/anthropicFormat.js';
|
|
30
|
+
import { chatGateway } from './gatewayClient.js';
|
|
31
|
+
import { prepareMessagesForProvider } from './messageProvenance.js';
|
|
30
32
|
/**
|
|
31
33
|
* 记住"这个 baseURL::model 不支持 response_format.json_schema",避免每次都先撞 400。
|
|
32
34
|
* 单进程内有效;每个 -p 子进程是全新进程 → 首个结构化调用吃一次 400 再退化,可接受。
|
|
@@ -133,7 +135,10 @@ export function _nextRetryDelayMs(retryAfterMs) {
|
|
|
133
135
|
}
|
|
134
136
|
/** 可重试的 HTTP 状态码。4xx 除 408/425/429 外不重试(重试无意义)。 */
|
|
135
137
|
function isRetryableStatus(status) {
|
|
136
|
-
return status === 408 ||
|
|
138
|
+
return (status === 408 ||
|
|
139
|
+
status === 425 ||
|
|
140
|
+
status === 429 ||
|
|
141
|
+
(status >= 500 && status < 600));
|
|
137
142
|
}
|
|
138
143
|
/** 鉴权类错误:明确告诉用户"key 失效/过期/无权访问",避免重试无意义。 */
|
|
139
144
|
function isClientAuthError(status) {
|
|
@@ -212,7 +217,9 @@ export function createIdleWatchdog(userSignal, timeoutMs = IDLE_TIMEOUT_MS) {
|
|
|
212
217
|
};
|
|
213
218
|
arm();
|
|
214
219
|
return {
|
|
215
|
-
signal: userSignal
|
|
220
|
+
signal: userSignal
|
|
221
|
+
? AbortSignal.any([userSignal, ctrl.signal])
|
|
222
|
+
: ctrl.signal,
|
|
216
223
|
kick: arm,
|
|
217
224
|
dispose: () => {
|
|
218
225
|
if (timer)
|
|
@@ -240,8 +247,34 @@ export function createIdleWatchdog(userSignal, timeoutMs = IDLE_TIMEOUT_MS) {
|
|
|
240
247
|
* }
|
|
241
248
|
* ```
|
|
242
249
|
*/
|
|
250
|
+
export function createModelProvider(provider) {
|
|
251
|
+
return {
|
|
252
|
+
source: provider.source === 'gateway' ? 'gateway' : 'local',
|
|
253
|
+
descriptor: provider,
|
|
254
|
+
stream: (request) => {
|
|
255
|
+
if (provider.source === 'gateway') {
|
|
256
|
+
if (request.responseFormat &&
|
|
257
|
+
provider.gatewayCapabilities?.structuredOutput === false) {
|
|
258
|
+
throw new Error('当前在线模型不支持结构化输出');
|
|
259
|
+
}
|
|
260
|
+
return chatGateway({
|
|
261
|
+
provider: provider,
|
|
262
|
+
messages: request.messages,
|
|
263
|
+
tools: request.tools,
|
|
264
|
+
signal: request.signal,
|
|
265
|
+
conversationMode: request.conversationMode,
|
|
266
|
+
responseFormat: request.responseFormat,
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
return streamLocal({ ...request, provider: provider });
|
|
270
|
+
},
|
|
271
|
+
};
|
|
272
|
+
}
|
|
243
273
|
export async function* chat(args) {
|
|
244
|
-
|
|
274
|
+
yield* createModelProvider(args.provider).stream(args);
|
|
275
|
+
}
|
|
276
|
+
async function* streamLocal(args) {
|
|
277
|
+
const { provider, messages, tools, signal, responseFormat, promptCache, conversationMode, cacheEdits, } = args;
|
|
245
278
|
const format = provider.apiFormat === 'anthropic' ? 'anthropic' : 'openai';
|
|
246
279
|
if (format === 'anthropic' && responseFormat) {
|
|
247
280
|
throw new Error('output_schema 结构化输出目前不支持 Anthropic Messages 格式的 provider' +
|
|
@@ -251,17 +284,14 @@ export async function* chat(args) {
|
|
|
251
284
|
// 过滤并清洁 messages 数组,剥离 timestamp, id, _ephemeral 等本地渲染元数据。
|
|
252
285
|
// 两种格式共用同一份清洗后的内部形状——Anthropic 分支的翻译(system 摘除/
|
|
253
286
|
// tool_calls→tool_use 等)在 buildAnthropicRequest 内部做,不在这里做。
|
|
254
|
-
let cleanedMessages = messages
|
|
255
|
-
.filter((m) => !(m.role === 'system' && m._ephemeral === true))
|
|
256
|
-
.map((m) => {
|
|
257
|
-
const { id, timestamp, attachments, browserReferences, display_metadata, ...rest } = m;
|
|
258
|
-
return rest;
|
|
259
|
-
});
|
|
287
|
+
let cleanedMessages = prepareMessagesForProvider(messages, conversationMode ?? 'private');
|
|
260
288
|
const includeUsage = process.env.MINIMAL_AGENT_DISABLE_USAGE !== '1';
|
|
261
289
|
const rfKey = `${provider.baseURL}::${provider.model}`;
|
|
262
290
|
// OpenAI 分支专属的「就地退化」状态;Anthropic 无此概念,两个 flag 恒为 false,
|
|
263
291
|
// 下面的退化 if 分支天然不会进入(不需要额外的 format 判断散落各处)。
|
|
264
|
-
let wantResponseFormat = format === 'openai' &&
|
|
292
|
+
let wantResponseFormat = format === 'openai' &&
|
|
293
|
+
responseFormat !== undefined &&
|
|
294
|
+
!rfUnsupported.has(rfKey);
|
|
265
295
|
let wantMaxTokens = format === 'openai' &&
|
|
266
296
|
typeof provider.maxTokens === 'number' &&
|
|
267
297
|
provider.maxTokens > 0 &&
|
|
@@ -278,7 +308,12 @@ export async function* chat(args) {
|
|
|
278
308
|
const textOnly = c.filter((p) => p.type === 'text');
|
|
279
309
|
const newContent = textOnly.length > 0
|
|
280
310
|
? textOnly.map((p) => ({ type: 'text', text: p.text }))
|
|
281
|
-
: [
|
|
311
|
+
: [
|
|
312
|
+
{
|
|
313
|
+
type: 'text',
|
|
314
|
+
text: '[图片内容未发送:当前模型不支持图片输入]',
|
|
315
|
+
},
|
|
316
|
+
];
|
|
282
317
|
return { ...m, content: newContent };
|
|
283
318
|
});
|
|
284
319
|
// 空闲 watchdog:每个 attempt 一只(重试前换新);fetch 等待期自动计时,
|
|
@@ -286,7 +321,12 @@ export async function* chat(args) {
|
|
|
286
321
|
let watchdog = createIdleWatchdog(signal);
|
|
287
322
|
const postChat = () => {
|
|
288
323
|
const req = format === 'anthropic'
|
|
289
|
-
? buildAnthropicRequest({
|
|
324
|
+
? buildAnthropicRequest({
|
|
325
|
+
provider,
|
|
326
|
+
cleanedMessages,
|
|
327
|
+
tools,
|
|
328
|
+
...(cacheEdits ? { cacheEdits } : {}),
|
|
329
|
+
})
|
|
290
330
|
: buildOpenAIRequest({
|
|
291
331
|
provider,
|
|
292
332
|
cleanedMessages,
|
|
@@ -298,7 +338,12 @@ export async function* chat(args) {
|
|
|
298
338
|
withPromptCacheKey: wantPromptCacheKey,
|
|
299
339
|
responseFormat,
|
|
300
340
|
});
|
|
301
|
-
return fetch(req.url, {
|
|
341
|
+
return fetch(req.url, {
|
|
342
|
+
method: 'POST',
|
|
343
|
+
headers: req.headers,
|
|
344
|
+
body: req.body,
|
|
345
|
+
signal: watchdog.signal,
|
|
346
|
+
});
|
|
302
347
|
};
|
|
303
348
|
const reqId = ++reqCounter;
|
|
304
349
|
dlog('llm', `req#${reqId} POST →`, {
|
|
@@ -315,7 +360,9 @@ export async function* chat(args) {
|
|
|
315
360
|
.map((message) => message.content)),
|
|
316
361
|
toolSchemaHash: promptMaterialHash(tools.map((tool) => ({
|
|
317
362
|
name: tool.name,
|
|
318
|
-
description: typeof tool.description === 'function'
|
|
363
|
+
description: typeof tool.description === 'function'
|
|
364
|
+
? tool.description()
|
|
365
|
+
: tool.description,
|
|
319
366
|
parameters: tool.parameters,
|
|
320
367
|
}))),
|
|
321
368
|
});
|
|
@@ -386,7 +433,8 @@ export async function* chat(args) {
|
|
|
386
433
|
errText = await resp.text().catch(() => '');
|
|
387
434
|
}
|
|
388
435
|
// 退化①:response_format.json_schema 不支持
|
|
389
|
-
if (wantResponseFormat &&
|
|
436
|
+
if (wantResponseFormat &&
|
|
437
|
+
isResponseFormatUnsupported(resp.status, errText)) {
|
|
390
438
|
// 记住该 model 不支持,单进程内后续结构化调用直接跳过 response_format(不再撞 400)。
|
|
391
439
|
rfUnsupported.add(rfKey);
|
|
392
440
|
console.warn(`[minimal-agent] provider model "${provider.model}" 不支持 response_format.json_schema,` +
|
|
@@ -399,7 +447,8 @@ export async function* chat(args) {
|
|
|
399
447
|
}
|
|
400
448
|
catch (e) {
|
|
401
449
|
// 退化二次 fetch 也网络错:把错误外提到外层重试循环
|
|
402
|
-
if ((await handleNetworkError(e, attempt, 'fallback fetch failed')) ===
|
|
450
|
+
if ((await handleNetworkError(e, attempt, 'fallback fetch failed')) ===
|
|
451
|
+
'break')
|
|
403
452
|
break;
|
|
404
453
|
continue;
|
|
405
454
|
}
|
|
@@ -419,7 +468,8 @@ export async function* chat(args) {
|
|
|
419
468
|
watchdog.kick();
|
|
420
469
|
}
|
|
421
470
|
catch (e) {
|
|
422
|
-
if ((await handleNetworkError(e, attempt, 'fallback fetch failed')) ===
|
|
471
|
+
if ((await handleNetworkError(e, attempt, 'fallback fetch failed')) ===
|
|
472
|
+
'break')
|
|
423
473
|
break;
|
|
424
474
|
continue;
|
|
425
475
|
}
|
|
@@ -432,9 +482,14 @@ export async function* chat(args) {
|
|
|
432
482
|
if (!imagesStripped && isImageInputRejected(resp.status, errText)) {
|
|
433
483
|
const hasImages = cleanedMessages.some((m) => {
|
|
434
484
|
const c = m.content;
|
|
435
|
-
return Array.isArray(c) &&
|
|
485
|
+
return (Array.isArray(c) &&
|
|
486
|
+
c.some((p) => p.type === 'image_url' || p.type === 'video_url'));
|
|
436
487
|
});
|
|
437
488
|
if (hasImages) {
|
|
489
|
+
if (args.visionPolicy === 'required') {
|
|
490
|
+
throw new Error(`当前模型拒绝了本轮必需的图片输入,已停止而未删除图片重试。` +
|
|
491
|
+
`请改用支持视觉的模型或检查模型配置。Provider 返回:${errText.slice(0, 500)}`);
|
|
492
|
+
}
|
|
438
493
|
console.warn(`[minimal-agent] provider model "${provider.model}" 不支持图片输入,` +
|
|
439
494
|
`已剥离图片重发(仅保留文本内容)。如该模型实际支持视觉,请在模型设置中确认。`);
|
|
440
495
|
cleanedMessages = stripImagesFromMessages(cleanedMessages);
|
|
@@ -444,7 +499,8 @@ export async function* chat(args) {
|
|
|
444
499
|
watchdog.kick();
|
|
445
500
|
}
|
|
446
501
|
catch (e) {
|
|
447
|
-
if ((await handleNetworkError(e, attempt, 'fallback fetch failed')) ===
|
|
502
|
+
if ((await handleNetworkError(e, attempt, 'fallback fetch failed')) ===
|
|
503
|
+
'break')
|
|
448
504
|
break;
|
|
449
505
|
continue;
|
|
450
506
|
}
|
|
@@ -486,7 +542,9 @@ export async function* chat(args) {
|
|
|
486
542
|
const decoder = new TextDecoder();
|
|
487
543
|
/** 临时缓冲:HTTP chunk 不一定按行切,要自己拼 */
|
|
488
544
|
let buffer = '';
|
|
489
|
-
const parser = format === 'anthropic'
|
|
545
|
+
const parser = format === 'anthropic'
|
|
546
|
+
? createAnthropicSSEParser()
|
|
547
|
+
: createOpenAISSEParser();
|
|
490
548
|
try {
|
|
491
549
|
while (true) {
|
|
492
550
|
// 每次 read 前检查 abort:用户按 ESC/Ctrl+C 时 signal.aborted 为 true。
|
package/src/llm/client.ts
CHANGED
|
@@ -24,7 +24,14 @@
|
|
|
24
24
|
* ============================================================
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
|
-
import type {
|
|
27
|
+
import type {
|
|
28
|
+
GatewayProvider,
|
|
29
|
+
LlmStreamEvent,
|
|
30
|
+
LocalProvider,
|
|
31
|
+
Message,
|
|
32
|
+
Provider,
|
|
33
|
+
Tool,
|
|
34
|
+
} from '../types.js';
|
|
28
35
|
import { dlog } from '../utils/debugLog.js';
|
|
29
36
|
import {
|
|
30
37
|
buildOpenAIRequest,
|
|
@@ -35,7 +42,13 @@ import {
|
|
|
35
42
|
isResponseFormatUnsupported,
|
|
36
43
|
} from './providers/openaiFormat.js';
|
|
37
44
|
import { promptMaterialHash, shortCacheScope } from './promptCache.js';
|
|
38
|
-
import {
|
|
45
|
+
import {
|
|
46
|
+
buildAnthropicRequest,
|
|
47
|
+
createAnthropicSSEParser,
|
|
48
|
+
} from './providers/anthropicFormat.js';
|
|
49
|
+
import { chatGateway } from './gatewayClient.js';
|
|
50
|
+
import type { ModelProvider } from './modelProvider.js';
|
|
51
|
+
import { prepareMessagesForProvider } from './messageProvenance.js';
|
|
39
52
|
|
|
40
53
|
/**
|
|
41
54
|
* 记住"这个 baseURL::model 不支持 response_format.json_schema",避免每次都先撞 400。
|
|
@@ -132,7 +145,8 @@ let backoffTier = 0;
|
|
|
132
145
|
* retryAfterMs 有值(429 的 Retry-After 头)时听服务器的(仍封顶 60s、仍抬档)。
|
|
133
146
|
*/
|
|
134
147
|
function nextRetryDelayMs(retryAfterMs?: number): number {
|
|
135
|
-
const tierMs =
|
|
148
|
+
const tierMs =
|
|
149
|
+
BACKOFF_TIERS_MS[Math.min(backoffTier, BACKOFF_TIERS_MS.length - 1)];
|
|
136
150
|
backoffTier = Math.min(backoffTier + 1, BACKOFF_TIERS_MS.length - 1);
|
|
137
151
|
if (retryAfterMs !== undefined) return Math.min(retryAfterMs, 60_000);
|
|
138
152
|
const jittered = tierMs * (0.85 + Math.random() * 0.3);
|
|
@@ -158,7 +172,12 @@ export function _nextRetryDelayMs(retryAfterMs?: number): number {
|
|
|
158
172
|
|
|
159
173
|
/** 可重试的 HTTP 状态码。4xx 除 408/425/429 外不重试(重试无意义)。 */
|
|
160
174
|
function isRetryableStatus(status: number): boolean {
|
|
161
|
-
return
|
|
175
|
+
return (
|
|
176
|
+
status === 408 ||
|
|
177
|
+
status === 425 ||
|
|
178
|
+
status === 429 ||
|
|
179
|
+
(status >= 500 && status < 600)
|
|
180
|
+
);
|
|
162
181
|
}
|
|
163
182
|
|
|
164
183
|
/** 鉴权类错误:明确告诉用户"key 失效/过期/无权访问",避免重试无意义。 */
|
|
@@ -253,7 +272,9 @@ export function createIdleWatchdog(
|
|
|
253
272
|
};
|
|
254
273
|
arm();
|
|
255
274
|
return {
|
|
256
|
-
signal: userSignal
|
|
275
|
+
signal: userSignal
|
|
276
|
+
? AbortSignal.any([userSignal, ctrl.signal])
|
|
277
|
+
: ctrl.signal,
|
|
257
278
|
kick: arm,
|
|
258
279
|
dispose: () => {
|
|
259
280
|
if (timer) clearTimeout(timer);
|
|
@@ -281,8 +302,42 @@ export function createIdleWatchdog(
|
|
|
281
302
|
* }
|
|
282
303
|
* ```
|
|
283
304
|
*/
|
|
284
|
-
export
|
|
285
|
-
|
|
305
|
+
export function createModelProvider(provider: Provider): ModelProvider {
|
|
306
|
+
return {
|
|
307
|
+
source: provider.source === 'gateway' ? 'gateway' : 'local',
|
|
308
|
+
descriptor: provider,
|
|
309
|
+
stream: (request) => {
|
|
310
|
+
if (provider.source === 'gateway') {
|
|
311
|
+
if (
|
|
312
|
+
request.responseFormat &&
|
|
313
|
+
provider.gatewayCapabilities?.structuredOutput === false
|
|
314
|
+
) {
|
|
315
|
+
throw new Error('当前在线模型不支持结构化输出');
|
|
316
|
+
}
|
|
317
|
+
return chatGateway({
|
|
318
|
+
provider: provider as GatewayProvider,
|
|
319
|
+
messages: request.messages,
|
|
320
|
+
tools: request.tools,
|
|
321
|
+
signal: request.signal,
|
|
322
|
+
conversationMode: request.conversationMode,
|
|
323
|
+
responseFormat: request.responseFormat,
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
return streamLocal({ ...request, provider: provider as LocalProvider });
|
|
327
|
+
},
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
export async function* chat(
|
|
332
|
+
args: Omit<Parameters<typeof streamLocal>[0], 'provider'> & {
|
|
333
|
+
provider: Provider;
|
|
334
|
+
},
|
|
335
|
+
): AsyncGenerator<LlmStreamEvent, void, void> {
|
|
336
|
+
yield* createModelProvider(args.provider).stream(args);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
async function* streamLocal(args: {
|
|
340
|
+
provider: LocalProvider;
|
|
286
341
|
messages: Message[];
|
|
287
342
|
tools: Tool[];
|
|
288
343
|
signal?: AbortSignal;
|
|
@@ -292,12 +347,36 @@ export async function* chat(args: {
|
|
|
292
347
|
* 传了会在发请求前直接抛错,不浪费一次网络往返。*/
|
|
293
348
|
responseFormat?: {
|
|
294
349
|
type: 'json_schema';
|
|
295
|
-
json_schema: {
|
|
350
|
+
json_schema: {
|
|
351
|
+
name: string;
|
|
352
|
+
schema: Record<string, unknown>;
|
|
353
|
+
strict?: boolean;
|
|
354
|
+
};
|
|
296
355
|
};
|
|
297
356
|
promptCache?: import('../types.js').PromptCacheContext;
|
|
357
|
+
/** 当前调用所在会话模式;群聊下未标注的旧历史按私聊数据处理。 */
|
|
358
|
+
conversationMode?: import('../runtime/agentRuntimeContext.js').ConversationMode;
|
|
359
|
+
/**
|
|
360
|
+
* cache_edits 式回收状态(Anthropic 格式 + provider.cacheEdits 开启时由 loop 传入)。
|
|
361
|
+
* 传入后 buildAnthropicRequest 会随请求发送删除指令并维护 pinned/pendingNew——
|
|
362
|
+
* 该状态有跨轮生命周期(pinned 每轮重发),调用方必须传同一份会话级对象,
|
|
363
|
+
* 并在 compact 后调 resetCacheEdits。OpenAI 格式忽略此参数。
|
|
364
|
+
*/
|
|
365
|
+
cacheEdits?: import('../types.js').CacheEditsState;
|
|
366
|
+
visionPolicy?: 'required' | 'optional-history';
|
|
298
367
|
}): AsyncGenerator<LlmStreamEvent, void, void> {
|
|
299
|
-
const {
|
|
300
|
-
|
|
368
|
+
const {
|
|
369
|
+
provider,
|
|
370
|
+
messages,
|
|
371
|
+
tools,
|
|
372
|
+
signal,
|
|
373
|
+
responseFormat,
|
|
374
|
+
promptCache,
|
|
375
|
+
conversationMode,
|
|
376
|
+
cacheEdits,
|
|
377
|
+
} = args;
|
|
378
|
+
const format: 'openai' | 'anthropic' =
|
|
379
|
+
provider.apiFormat === 'anthropic' ? 'anthropic' : 'openai';
|
|
301
380
|
|
|
302
381
|
if (format === 'anthropic' && responseFormat) {
|
|
303
382
|
throw new Error(
|
|
@@ -310,12 +389,10 @@ export async function* chat(args: {
|
|
|
310
389
|
// 过滤并清洁 messages 数组,剥离 timestamp, id, _ephemeral 等本地渲染元数据。
|
|
311
390
|
// 两种格式共用同一份清洗后的内部形状——Anthropic 分支的翻译(system 摘除/
|
|
312
391
|
// tool_calls→tool_use 等)在 buildAnthropicRequest 内部做,不在这里做。
|
|
313
|
-
let cleanedMessages: Message[] =
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
return rest;
|
|
318
|
-
});
|
|
392
|
+
let cleanedMessages: Message[] = prepareMessagesForProvider(
|
|
393
|
+
messages,
|
|
394
|
+
conversationMode ?? 'private',
|
|
395
|
+
);
|
|
319
396
|
|
|
320
397
|
const includeUsage = process.env.MINIMAL_AGENT_DISABLE_USAGE !== '1';
|
|
321
398
|
const rfKey = `${provider.baseURL}::${provider.model}`;
|
|
@@ -323,7 +400,9 @@ export async function* chat(args: {
|
|
|
323
400
|
// OpenAI 分支专属的「就地退化」状态;Anthropic 无此概念,两个 flag 恒为 false,
|
|
324
401
|
// 下面的退化 if 分支天然不会进入(不需要额外的 format 判断散落各处)。
|
|
325
402
|
let wantResponseFormat =
|
|
326
|
-
format === 'openai' &&
|
|
403
|
+
format === 'openai' &&
|
|
404
|
+
responseFormat !== undefined &&
|
|
405
|
+
!rfUnsupported.has(rfKey);
|
|
327
406
|
let wantMaxTokens =
|
|
328
407
|
format === 'openai' &&
|
|
329
408
|
typeof provider.maxTokens === 'number' &&
|
|
@@ -341,9 +420,15 @@ export async function* chat(args: {
|
|
|
341
420
|
const c = (m as { content?: unknown }).content;
|
|
342
421
|
if (!Array.isArray(c)) return m;
|
|
343
422
|
const textOnly = c.filter((p: any) => p.type === 'text');
|
|
344
|
-
const newContent =
|
|
345
|
-
|
|
346
|
-
|
|
423
|
+
const newContent =
|
|
424
|
+
textOnly.length > 0
|
|
425
|
+
? textOnly.map((p: any) => ({ type: 'text' as const, text: p.text }))
|
|
426
|
+
: [
|
|
427
|
+
{
|
|
428
|
+
type: 'text' as const,
|
|
429
|
+
text: '[图片内容未发送:当前模型不支持图片输入]',
|
|
430
|
+
},
|
|
431
|
+
];
|
|
347
432
|
return { ...m, content: newContent } as Message;
|
|
348
433
|
});
|
|
349
434
|
|
|
@@ -354,7 +439,12 @@ export async function* chat(args: {
|
|
|
354
439
|
const postChat = (): Promise<Response> => {
|
|
355
440
|
const req =
|
|
356
441
|
format === 'anthropic'
|
|
357
|
-
? buildAnthropicRequest({
|
|
442
|
+
? buildAnthropicRequest({
|
|
443
|
+
provider,
|
|
444
|
+
cleanedMessages,
|
|
445
|
+
tools,
|
|
446
|
+
...(cacheEdits ? { cacheEdits } : {}),
|
|
447
|
+
})
|
|
358
448
|
: buildOpenAIRequest({
|
|
359
449
|
provider,
|
|
360
450
|
cleanedMessages,
|
|
@@ -366,7 +456,12 @@ export async function* chat(args: {
|
|
|
366
456
|
withPromptCacheKey: wantPromptCacheKey,
|
|
367
457
|
responseFormat,
|
|
368
458
|
});
|
|
369
|
-
return fetch(req.url, {
|
|
459
|
+
return fetch(req.url, {
|
|
460
|
+
method: 'POST',
|
|
461
|
+
headers: req.headers,
|
|
462
|
+
body: req.body,
|
|
463
|
+
signal: watchdog.signal,
|
|
464
|
+
});
|
|
370
465
|
};
|
|
371
466
|
|
|
372
467
|
const reqId = ++reqCounter;
|
|
@@ -387,7 +482,10 @@ export async function* chat(args: {
|
|
|
387
482
|
toolSchemaHash: promptMaterialHash(
|
|
388
483
|
tools.map((tool) => ({
|
|
389
484
|
name: tool.name,
|
|
390
|
-
description:
|
|
485
|
+
description:
|
|
486
|
+
typeof tool.description === 'function'
|
|
487
|
+
? tool.description()
|
|
488
|
+
: tool.description,
|
|
391
489
|
parameters: tool.parameters,
|
|
392
490
|
})),
|
|
393
491
|
),
|
|
@@ -409,11 +507,16 @@ export async function* chat(args: {
|
|
|
409
507
|
): Promise<'break' | 'retry'> => {
|
|
410
508
|
if (signal?.aborted) throw makeAbortError();
|
|
411
509
|
const err = e as Error;
|
|
412
|
-
lastErr = new Error(
|
|
510
|
+
lastErr = new Error(
|
|
511
|
+
`LLM 网络错误 [${err.name ?? 'NetworkError'}]:${err.message}`,
|
|
512
|
+
);
|
|
413
513
|
dlog('llm', `req#${reqId} attempt ${attempt} ${label}:`, err.message);
|
|
414
514
|
if (attempt >= DEFAULT_RETRY.maxAttempts) return 'break';
|
|
415
515
|
const delay = nextRetryDelayMs();
|
|
416
|
-
dlog(
|
|
516
|
+
dlog(
|
|
517
|
+
'llm',
|
|
518
|
+
`req#${reqId} retry in ${delay}ms (attempt ${attempt + 1}/${DEFAULT_RETRY.maxAttempts}, tier=${backoffTier})`,
|
|
519
|
+
);
|
|
417
520
|
await sleep(delay, signal);
|
|
418
521
|
return 'retry';
|
|
419
522
|
};
|
|
@@ -435,7 +538,10 @@ export async function* chat(args: {
|
|
|
435
538
|
// 1) 用户主动 abort → handleNetworkError 里立刻抛
|
|
436
539
|
// 2) AbortSignal.timeout 触发的超时(Fetch 空闲超时还没回)
|
|
437
540
|
// 3) 其它网络错误(ECONNRESET / fetch failed / DNS 失败)→ 全部按"可重试"处理
|
|
438
|
-
if (
|
|
541
|
+
if (
|
|
542
|
+
(await handleNetworkError(e, attempt, 'failed (network)')) === 'break'
|
|
543
|
+
)
|
|
544
|
+
break;
|
|
439
545
|
continue;
|
|
440
546
|
}
|
|
441
547
|
|
|
@@ -456,7 +562,14 @@ export async function* chat(args: {
|
|
|
456
562
|
resp = await postChat();
|
|
457
563
|
watchdog.kick();
|
|
458
564
|
} catch (e) {
|
|
459
|
-
if (
|
|
565
|
+
if (
|
|
566
|
+
(await handleNetworkError(
|
|
567
|
+
e,
|
|
568
|
+
attempt,
|
|
569
|
+
'cache-key fallback fetch failed',
|
|
570
|
+
)) === 'break'
|
|
571
|
+
)
|
|
572
|
+
break;
|
|
460
573
|
continue;
|
|
461
574
|
}
|
|
462
575
|
if (resp.ok) break;
|
|
@@ -464,7 +577,10 @@ export async function* chat(args: {
|
|
|
464
577
|
}
|
|
465
578
|
|
|
466
579
|
// 退化①:response_format.json_schema 不支持
|
|
467
|
-
if (
|
|
580
|
+
if (
|
|
581
|
+
wantResponseFormat &&
|
|
582
|
+
isResponseFormatUnsupported(resp.status, errText)
|
|
583
|
+
) {
|
|
468
584
|
// 记住该 model 不支持,单进程内后续结构化调用直接跳过 response_format(不再撞 400)。
|
|
469
585
|
rfUnsupported.add(rfKey);
|
|
470
586
|
console.warn(
|
|
@@ -478,7 +594,11 @@ export async function* chat(args: {
|
|
|
478
594
|
watchdog.kick();
|
|
479
595
|
} catch (e) {
|
|
480
596
|
// 退化二次 fetch 也网络错:把错误外提到外层重试循环
|
|
481
|
-
if (
|
|
597
|
+
if (
|
|
598
|
+
(await handleNetworkError(e, attempt, 'fallback fetch failed')) ===
|
|
599
|
+
'break'
|
|
600
|
+
)
|
|
601
|
+
break;
|
|
482
602
|
continue;
|
|
483
603
|
}
|
|
484
604
|
if (resp.ok) break;
|
|
@@ -498,7 +618,11 @@ export async function* chat(args: {
|
|
|
498
618
|
resp = await postChat();
|
|
499
619
|
watchdog.kick();
|
|
500
620
|
} catch (e) {
|
|
501
|
-
if (
|
|
621
|
+
if (
|
|
622
|
+
(await handleNetworkError(e, attempt, 'fallback fetch failed')) ===
|
|
623
|
+
'break'
|
|
624
|
+
)
|
|
625
|
+
break;
|
|
502
626
|
continue;
|
|
503
627
|
}
|
|
504
628
|
if (resp.ok) break;
|
|
@@ -510,9 +634,18 @@ export async function* chat(args: {
|
|
|
510
634
|
if (!imagesStripped && isImageInputRejected(resp.status, errText)) {
|
|
511
635
|
const hasImages = cleanedMessages.some((m) => {
|
|
512
636
|
const c = (m as { content?: unknown }).content;
|
|
513
|
-
return
|
|
637
|
+
return (
|
|
638
|
+
Array.isArray(c) &&
|
|
639
|
+
c.some((p: any) => p.type === 'image_url' || p.type === 'video_url')
|
|
640
|
+
);
|
|
514
641
|
});
|
|
515
642
|
if (hasImages) {
|
|
643
|
+
if (args.visionPolicy === 'required') {
|
|
644
|
+
throw new Error(
|
|
645
|
+
`当前模型拒绝了本轮必需的图片输入,已停止而未删除图片重试。` +
|
|
646
|
+
`请改用支持视觉的模型或检查模型配置。Provider 返回:${errText.slice(0, 500)}`,
|
|
647
|
+
);
|
|
648
|
+
}
|
|
516
649
|
console.warn(
|
|
517
650
|
`[minimal-agent] provider model "${provider.model}" 不支持图片输入,` +
|
|
518
651
|
`已剥离图片重发(仅保留文本内容)。如该模型实际支持视觉,请在模型设置中确认。`,
|
|
@@ -523,7 +656,11 @@ export async function* chat(args: {
|
|
|
523
656
|
resp = await postChat();
|
|
524
657
|
watchdog.kick();
|
|
525
658
|
} catch (e) {
|
|
526
|
-
if (
|
|
659
|
+
if (
|
|
660
|
+
(await handleNetworkError(e, attempt, 'fallback fetch failed')) ===
|
|
661
|
+
'break'
|
|
662
|
+
)
|
|
663
|
+
break;
|
|
527
664
|
continue;
|
|
528
665
|
}
|
|
529
666
|
if (resp.ok) break;
|
|
@@ -538,13 +675,20 @@ export async function* chat(args: {
|
|
|
538
675
|
|
|
539
676
|
// 5xx / 408 / 425 / 429:可重试
|
|
540
677
|
lastErr = buildChatError(resp, errText);
|
|
541
|
-
dlog(
|
|
678
|
+
dlog(
|
|
679
|
+
'llm',
|
|
680
|
+
`req#${reqId} attempt ${attempt} failed [${resp.status}]:`,
|
|
681
|
+
errText.slice(0, 200),
|
|
682
|
+
);
|
|
542
683
|
if (attempt >= DEFAULT_RETRY.maxAttempts) break;
|
|
543
684
|
|
|
544
685
|
// 429 优先用 Retry-After 头,否则走自适应档位退避
|
|
545
686
|
const retryAfterMs = parseRetryAfter(resp);
|
|
546
687
|
const delay = nextRetryDelayMs(retryAfterMs);
|
|
547
|
-
dlog(
|
|
688
|
+
dlog(
|
|
689
|
+
'llm',
|
|
690
|
+
`req#${reqId} retry in ${delay}ms (attempt ${attempt + 1}/${DEFAULT_RETRY.maxAttempts}, tier=${backoffTier}, retryAfter=${retryAfterMs ?? 'tier'})`,
|
|
691
|
+
);
|
|
548
692
|
await sleep(delay, signal);
|
|
549
693
|
}
|
|
550
694
|
|
|
@@ -567,7 +711,10 @@ export async function* chat(args: {
|
|
|
567
711
|
const decoder = new TextDecoder();
|
|
568
712
|
/** 临时缓冲:HTTP chunk 不一定按行切,要自己拼 */
|
|
569
713
|
let buffer = '';
|
|
570
|
-
const parser =
|
|
714
|
+
const parser =
|
|
715
|
+
format === 'anthropic'
|
|
716
|
+
? createAnthropicSSEParser()
|
|
717
|
+
: createOpenAISSEParser();
|
|
571
718
|
|
|
572
719
|
try {
|
|
573
720
|
while (true) {
|