minimal-agent 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -5
- package/package.json +62 -5
- 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 +204 -185
- package/plugins/workflow-runner/src/index.ts +249 -224
- 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 +404 -467
- package/plugins/workflow-runner/src/runner.ts +491 -535
- 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 +172 -152
- package/plugins/workflow-runner/src/taskIdentity.ts +233 -200
- 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 -105
- package/plugins/workflow-runner/src/types.ts +155 -520
- 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 +542 -469
- package/plugins/workflow-runner/src/workflowState.ts +639 -589
- 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/skill-creator/scripts/run_eval.py +3 -2
- 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 +44 -6
- package/src/cli/print.ts +73 -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 +443 -74
- package/src/config/configService.ts +723 -142
- 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 +56 -20
- package/src/infra/verification.ts +87 -20
- 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 +152 -9
- package/src/plugins/pluginRunner.ts +186 -8
- package/src/plugins/slashFallback.js +113 -0
- package/src/plugins/slashFallback.ts +137 -0
- package/src/prompts/policyRegistry.js +15 -8
- package/src/prompts/policyRegistry.ts +18 -8
- 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 +148 -37
- package/src/tools/advisor/advisor.ts +161 -38
- 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 +70 -18
- package/src/tools/bash/bash.ts +75 -20
- 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/powershell/powershell.js +18 -1
- package/src/tools/powershell/powershell.ts +18 -2
- package/src/tools/presentresult/presentresult.js +6 -15
- package/src/tools/presentresult/presentresult.ts +6 -15
- package/src/tools/read/read.js +69 -11
- package/src/tools/read/read.ts +70 -11
- package/src/tools/shared/fileUtils.js +1 -2
- package/src/tools/shared/fileUtils.ts +1 -2
- package/src/tools/shared/permanentDeleteGuard.js +34 -3
- package/src/tools/shared/permanentDeleteGuard.ts +43 -6
- 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 -30
- package/src/tools/webbrowser/browserControl.ts +210 -50
- 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 +683 -144
- package/src/tools/webbrowser/webbrowser.ts +979 -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 +450 -42
- 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/DESIGN.md +449 -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 -618
- package/plugins/workflow-runner/src/expressions.ts +0 -622
- 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 -119
- package/plugins/workflow-runner/src/recovery.ts +0 -149
- 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 -41
- package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -50
- 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 -208
- package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -256
- package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -58
- package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -68
- 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 -147
- 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/engineRobustness.test.ts +0 -226
- package/plugins/workflow-runner/test/expressions.test.ts +0 -397
- 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 -87
- 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 -220
- package/plugins/workflow-runner/test/recovery.test.ts +0 -265
- package/plugins/workflow-runner/test/runner.test.ts +0 -911
- package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -379
- package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
- package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -150
- package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
- package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -338
- package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -270
- 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 -199
- 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/src/main.js
CHANGED
|
@@ -36,6 +36,7 @@ import { runPrintMode } from './cli/print.js';
|
|
|
36
36
|
import { runStreamJsonMode } from './cli/streamJson.js';
|
|
37
37
|
import { extractFlagValue, normalizeArgs } from './cli/args.js';
|
|
38
38
|
import { resolveComputerUseMode, resolveComputerUseTraceDir } from './cli/computerUse.js';
|
|
39
|
+
import { runTeamCommand } from './team/cli.js';
|
|
39
40
|
// re-export:对外保持「main.tsx 提供 extractFlagValue」的语义;实现住在 cli/args.ts,
|
|
40
41
|
// 这样单测可零副作用 import(main.tsx 顶层 main() 自调用会启动整个 app,不可被测试 import)。
|
|
41
42
|
export { extractFlagValue };
|
|
@@ -71,6 +72,8 @@ async function main() {
|
|
|
71
72
|
console.log(`minimal-agent v${pkg.version}`);
|
|
72
73
|
return;
|
|
73
74
|
}
|
|
75
|
+
if (await runTeamCommand(args))
|
|
76
|
+
return;
|
|
74
77
|
if (args.includes('--workspace-doctor')) {
|
|
75
78
|
const snapshot = await workspaceIndexService.snapshot();
|
|
76
79
|
console.log(`Workspace Index v${snapshot.version} · revision ${snapshot.revision}`);
|
|
@@ -101,7 +104,7 @@ async function main() {
|
|
|
101
104
|
: rawFormat === 'stream-json'
|
|
102
105
|
? 'stream-json'
|
|
103
106
|
: 'text';
|
|
104
|
-
// --max-turns:parseInt,非法(NaN)→ undefined(走 loop 默认
|
|
107
|
+
// --max-turns:parseInt,非法(NaN)→ undefined(走 loop 默认 200)
|
|
105
108
|
const rawMaxTurns = extractFlagValue(args, ['--max-turns']);
|
|
106
109
|
const parsedMaxTurns = rawMaxTurns !== undefined ? Number.parseInt(rawMaxTurns, 10) : Number.NaN;
|
|
107
110
|
const maxTurns = Number.isNaN(parsedMaxTurns) ? undefined : parsedMaxTurns;
|
package/src/main.tsx
CHANGED
|
@@ -66,6 +66,7 @@ import { runPrintMode } from './cli/print.js';
|
|
|
66
66
|
import { runStreamJsonMode } from './cli/streamJson.js';
|
|
67
67
|
import { extractFlagValue, normalizeArgs } from './cli/args.js';
|
|
68
68
|
import { resolveComputerUseMode, resolveComputerUseTraceDir } from './cli/computerUse.js';
|
|
69
|
+
import { runTeamCommand } from './team/cli.js';
|
|
69
70
|
|
|
70
71
|
// re-export:对外保持「main.tsx 提供 extractFlagValue」的语义;实现住在 cli/args.ts,
|
|
71
72
|
// 这样单测可零副作用 import(main.tsx 顶层 main() 自调用会启动整个 app,不可被测试 import)。
|
|
@@ -108,6 +109,8 @@ async function main(): Promise<void> {
|
|
|
108
109
|
return;
|
|
109
110
|
}
|
|
110
111
|
|
|
112
|
+
if (await runTeamCommand(args)) return;
|
|
113
|
+
|
|
111
114
|
if (args.includes('--workspace-doctor')) {
|
|
112
115
|
const snapshot = await workspaceIndexService.snapshot();
|
|
113
116
|
console.log(`Workspace Index v${snapshot.version} · revision ${snapshot.revision}`);
|
|
@@ -143,7 +146,7 @@ async function main(): Promise<void> {
|
|
|
143
146
|
: rawFormat === 'stream-json'
|
|
144
147
|
? 'stream-json'
|
|
145
148
|
: 'text';
|
|
146
|
-
// --max-turns:parseInt,非法(NaN)→ undefined(走 loop 默认
|
|
149
|
+
// --max-turns:parseInt,非法(NaN)→ undefined(走 loop 默认 200)
|
|
147
150
|
const rawMaxTurns = extractFlagValue(args, ['--max-turns']);
|
|
148
151
|
const parsedMaxTurns = rawMaxTurns !== undefined ? Number.parseInt(rawMaxTurns, 10) : Number.NaN;
|
|
149
152
|
const maxTurns = Number.isNaN(parsedMaxTurns) ? undefined : parsedMaxTurns;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { prepareGoalCommand } from '../goal/workflowController.js';
|
|
2
|
+
const CONTROLLERS = {
|
|
3
|
+
goal: (inputs, options) => {
|
|
4
|
+
const context = (options.context ?? {});
|
|
5
|
+
return prepareGoalCommand(inputs, {
|
|
6
|
+
...context,
|
|
7
|
+
cwd: options.cwd,
|
|
8
|
+
runtimeContext: options.runtimeContext,
|
|
9
|
+
});
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
/** 业务运行时注册在内核控制层;Workflow Runner 只按声明请求适配器。 */
|
|
13
|
+
export function managedCommandController(kind) {
|
|
14
|
+
return CONTROLLERS[kind] ?? null;
|
|
15
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { prepareGoalCommand } from '../goal/workflowController.js';
|
|
2
|
+
import type { ManagedCommandController } from './types.js';
|
|
3
|
+
|
|
4
|
+
const CONTROLLERS: Readonly<Record<string, ManagedCommandController>> = {
|
|
5
|
+
goal: (inputs, options) => {
|
|
6
|
+
const context = (options.context ?? {}) as Partial<
|
|
7
|
+
Parameters<typeof prepareGoalCommand>[1]
|
|
8
|
+
>;
|
|
9
|
+
return prepareGoalCommand(inputs, {
|
|
10
|
+
...context,
|
|
11
|
+
cwd: options.cwd,
|
|
12
|
+
runtimeContext: options.runtimeContext,
|
|
13
|
+
});
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/** 业务运行时注册在内核控制层;Workflow Runner 只按声明请求适配器。 */
|
|
18
|
+
export function managedCommandController(kind: string): ManagedCommandController | null {
|
|
19
|
+
return CONTROLLERS[kind] ?? null;
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { AgentRuntimeContext, LoopEvent } from '../plugin-sdk.js';
|
|
2
|
+
|
|
3
|
+
export type ManagedAttemptResult = 'stopped' | 'failed' | 'verified';
|
|
4
|
+
|
|
5
|
+
/** Workflow Runner 只认识这个通用执行租约,不认识 Goal、群任务或业务契约。 */
|
|
6
|
+
export interface ManagedExecutionContext {
|
|
7
|
+
executionId: string;
|
|
8
|
+
version: number;
|
|
9
|
+
runId: string;
|
|
10
|
+
anchor: string;
|
|
11
|
+
correlations?: Record<string, string>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 一次记账之后的累计快照。故意只有「已花多少 / 上限多少」这两件事 ——
|
|
16
|
+
* 它是**执行租约的资源核算**,不是 Goal 的业务语义,Runner 不需要知道
|
|
17
|
+
* 后面是 Goal、群任务还是别的什么。
|
|
18
|
+
*/
|
|
19
|
+
export interface ManagedResourceSnapshot {
|
|
20
|
+
inputTokens: number;
|
|
21
|
+
outputTokens: number;
|
|
22
|
+
/** `null` = 没设上限。⚠️ 不要用 0 表示无限,那会被判成「一开始就超了」。 */
|
|
23
|
+
limit: number | null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface ManagedExecutionBridge {
|
|
27
|
+
updateContract(input: unknown): Promise<{
|
|
28
|
+
version: number;
|
|
29
|
+
anchor: string;
|
|
30
|
+
value?: unknown;
|
|
31
|
+
}>;
|
|
32
|
+
/**
|
|
33
|
+
* 记一笔资源消耗,返回**累计后**的快照。
|
|
34
|
+
*
|
|
35
|
+
* ⚠️ 累计值必须由外层控制器持久化(Goal 侧是 `goal.usage`),不能只存在进程内:
|
|
36
|
+
* 断点续跑时账本重放**不会重新执行** agent/llm 调用,进程内计数会从 0 开始,
|
|
37
|
+
* 于是「已经花掉的钱」凭空消失、预算闸永远不触发。
|
|
38
|
+
*
|
|
39
|
+
* 可选:没有外层控制器时(普通 `/workflow` 调用)引擎自己在进程内累计。
|
|
40
|
+
*/
|
|
41
|
+
recordUsage?(input: {
|
|
42
|
+
inputTokens: number;
|
|
43
|
+
outputTokens: number;
|
|
44
|
+
}): Promise<ManagedResourceSnapshot>;
|
|
45
|
+
/**
|
|
46
|
+
* 收尾。返回值里的 `status` 是**外层运行时收尾后的生命周期状态**
|
|
47
|
+
* (Goal 侧就是 `Goal.status`),Runner 只把它原样透出给宿主,不解释含义。
|
|
48
|
+
*
|
|
49
|
+
* ⚠️ 它与 Runner 自己传进去的 `status`(attempt 结局)**不是一回事**:
|
|
50
|
+
* 传进去 `verified` 完全可能得到 `ready_for_acceptance` —— 机器自检通过,
|
|
51
|
+
* 但还没有人验收。宿主要区分这两者,所以必须原样透出而不是就地丢弃。
|
|
52
|
+
*/
|
|
53
|
+
finish(input: {
|
|
54
|
+
status: ManagedAttemptResult;
|
|
55
|
+
artifacts?: string[];
|
|
56
|
+
evidence?: string[];
|
|
57
|
+
blocker?: string;
|
|
58
|
+
/**
|
|
59
|
+
* 工作流脚本自己贴的结局标签(如 `'budget_limited'`)。Runner **不解释**它的含义,
|
|
60
|
+
* 原样透传——具体是谁在解释、精化成什么真实状态是外层业务运行时(Goal 等)的事。
|
|
61
|
+
* 工作流可在抛出的 Error 上挂一个 `workflowOutcome` 属性,runner 读到后原样
|
|
62
|
+
* 转发;没有这个属性就是普通失败。该通道与具体工作流业务保持无关。
|
|
63
|
+
*/
|
|
64
|
+
outcome?: string;
|
|
65
|
+
}): Promise<{ status?: string } | unknown>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface PreparedManagedCommand {
|
|
69
|
+
handled: boolean;
|
|
70
|
+
events: LoopEvent[];
|
|
71
|
+
inputs: Record<string, unknown>;
|
|
72
|
+
execution?: ManagedExecutionContext;
|
|
73
|
+
bridge?: ManagedExecutionBridge;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface ManagedCommandOptions {
|
|
77
|
+
cwd: string;
|
|
78
|
+
runtimeContext?: AgentRuntimeContext;
|
|
79
|
+
/** 外层控制器自己的不透明上下文;Runner 不读取其中字段。 */
|
|
80
|
+
context?: unknown;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export type ManagedCommandController = (
|
|
84
|
+
inputs: Record<string, unknown>,
|
|
85
|
+
options: ManagedCommandOptions,
|
|
86
|
+
) => Promise<PreparedManagedCommand>;
|
package/src/modelRef.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Compatibility is kept at the CLI/Web protocol edge only. */
|
|
2
|
+
export function modelRefFromLegacy(value, serverId = 'gateway') {
|
|
3
|
+
return value.startsWith('online:')
|
|
4
|
+
? { source: 'gateway', serverId, modelId: value.slice('online:'.length) }
|
|
5
|
+
: { source: 'local', modelId: value };
|
|
6
|
+
}
|
|
7
|
+
export function legacyModelId(ref) {
|
|
8
|
+
return ref.source === 'gateway' ? `online:${ref.modelId}` : ref.modelId;
|
|
9
|
+
}
|
package/src/modelRef.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Source-aware model identity shared by Desktop, TUI and the local Agent. */
|
|
2
|
+
export type ModelRef =
|
|
3
|
+
| { source: 'local'; modelId: string }
|
|
4
|
+
| { source: 'gateway'; serverId: string; modelId: string };
|
|
5
|
+
|
|
6
|
+
/** Compatibility is kept at the CLI/Web protocol edge only. */
|
|
7
|
+
export function modelRefFromLegacy(value: string, serverId = 'gateway'): ModelRef {
|
|
8
|
+
return value.startsWith('online:')
|
|
9
|
+
? { source: 'gateway', serverId, modelId: value.slice('online:'.length) }
|
|
10
|
+
: { source: 'local', modelId: value };
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function legacyModelId(ref: ModelRef): string {
|
|
14
|
+
return ref.source === 'gateway' ? `online:${ref.modelId}` : ref.modelId;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type ModelFallbackReason =
|
|
18
|
+
| 'offline'
|
|
19
|
+
| 'logged_out'
|
|
20
|
+
| 'grant_revoked'
|
|
21
|
+
| 'quota_exhausted'
|
|
22
|
+
| 'model_disabled'
|
|
23
|
+
| 'credential_expired'
|
|
24
|
+
| null;
|
|
25
|
+
|
|
26
|
+
export interface SessionModelPreference {
|
|
27
|
+
preferred: ModelRef | null;
|
|
28
|
+
effective: ModelRef | null;
|
|
29
|
+
fallbackReason: ModelFallbackReason;
|
|
30
|
+
restoreWhenAvailable: boolean;
|
|
31
|
+
}
|
package/src/multimodal.js
CHANGED
|
@@ -7,11 +7,12 @@
|
|
|
7
7
|
* Chat Completions 的 content blocks。
|
|
8
8
|
* ============================================================
|
|
9
9
|
*/
|
|
10
|
-
import { readFile
|
|
10
|
+
import { readFile } from 'node:fs/promises';
|
|
11
11
|
import { extname, resolve } from 'node:path';
|
|
12
12
|
import { fileURLToPath } from 'node:url';
|
|
13
13
|
import { getWorkingDir } from './bootstrap/workingDir.js';
|
|
14
14
|
import { removeManagedClipboardTemp } from './utils/clipboardImage.js';
|
|
15
|
+
import { detectImageMime, resolveLocalImage, } from './images/imageResolver.js';
|
|
15
16
|
export const MAX_IMAGE_BYTES = 10 * 1024 * 1024;
|
|
16
17
|
const IMAGE_MIME_BY_EXT = {
|
|
17
18
|
'.jpg': 'image/jpeg',
|
|
@@ -22,8 +23,14 @@ const IMAGE_MIME_BY_EXT = {
|
|
|
22
23
|
// Read can attach BMP files directly even though inline drag/drop parsing
|
|
23
24
|
// intentionally remains limited to formats accepted by most providers.
|
|
24
25
|
'.bmp': 'image/bmp',
|
|
26
|
+
'.tif': 'image/tiff',
|
|
27
|
+
'.tiff': 'image/tiff',
|
|
28
|
+
'.avif': 'image/avif',
|
|
29
|
+
'.heic': 'image/heic',
|
|
30
|
+
'.heif': 'image/heic',
|
|
31
|
+
'.svg': 'image/svg+xml',
|
|
25
32
|
};
|
|
26
|
-
const IMAGE_EXT_PATTERN = String.raw `(?:png|jpe?g|gif|webp)`;
|
|
33
|
+
const IMAGE_EXT_PATTERN = String.raw `(?:png|jpe?g|gif|webp|bmp|tiff?|avif|hei[cf]|svg)`;
|
|
27
34
|
/**
|
|
28
35
|
* 「路径 token」允许的字符:非空白,或 `\x` 这样的转义对——macOS Terminal / iTerm2
|
|
29
36
|
* 拖入文件时空格默认转义成 `\ `,不认它就会把 `/Users/me/My\ Pic.png` 切成两半。
|
|
@@ -231,39 +238,18 @@ export async function imageToContentPart(input) {
|
|
|
231
238
|
* 仅按扩展名查会误判「不支持」而拒图——魔数嗅探让任意扩展名的真图都能用。
|
|
232
239
|
*/
|
|
233
240
|
export function sniffImageMime(buf) {
|
|
234
|
-
|
|
235
|
-
return 'image/png';
|
|
236
|
-
if (buf.length >= 3 && buf[0] === 0xff && buf[1] === 0xd8 && buf[2] === 0xff)
|
|
237
|
-
return 'image/jpeg';
|
|
238
|
-
if (buf.length >= 4 && buf[0] === 0x47 && buf[1] === 0x49 && buf[2] === 0x46 && buf[3] === 0x38)
|
|
239
|
-
return 'image/gif';
|
|
240
|
-
if (buf.length >= 12 &&
|
|
241
|
-
buf.toString('ascii', 0, 4) === 'RIFF' &&
|
|
242
|
-
buf.toString('ascii', 8, 12) === 'WEBP')
|
|
243
|
-
return 'image/webp';
|
|
244
|
-
return null;
|
|
241
|
+
return detectImageMime(buf);
|
|
245
242
|
}
|
|
246
243
|
async function imageSourceToUrl(source) {
|
|
247
244
|
const clean = stripWrappingQuotes(source.trim());
|
|
248
245
|
if (isHttpUrl(clean) || clean.startsWith('data:image/'))
|
|
249
246
|
return clean;
|
|
250
247
|
const filePath = resolveImagePath(clean);
|
|
251
|
-
const
|
|
252
|
-
|
|
248
|
+
const resolved = await resolveLocalImage(filePath, {
|
|
249
|
+
maxOutputBytes: MAX_IMAGE_BYTES,
|
|
253
250
|
});
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
if (st.size > MAX_IMAGE_BYTES) {
|
|
257
|
-
throw new Error(`图片过大:${source} ${(st.size / 1024 / 1024).toFixed(1)}MB,` +
|
|
258
|
-
`OpenAI 兼容接口单图上限按 10MB 处理。`);
|
|
259
|
-
}
|
|
260
|
-
const data = await readFile(filePath);
|
|
261
|
-
// 先按扩展名查 MIME;认不出(无扩展名 / .img / 扩展名错)再按文件头魔数嗅探,都不认才拒。
|
|
262
|
-
const mime = IMAGE_MIME_BY_EXT[extname(filePath).toLowerCase()] ?? sniffImageMime(data);
|
|
263
|
-
if (!mime) {
|
|
264
|
-
throw new Error(`不支持的图片格式:${source}。仅支持 JPEG/PNG/GIF/WEBP(按扩展名与文件头都未识别)。`);
|
|
265
|
-
}
|
|
266
|
-
return `data:${mime};base64,${data.toString('base64')}`;
|
|
251
|
+
const data = await readFile(resolved.path);
|
|
252
|
+
return `data:${resolved.mime};base64,${data.toString('base64')}`;
|
|
267
253
|
}
|
|
268
254
|
function resolveImagePath(source) {
|
|
269
255
|
if (source.startsWith('file://'))
|
package/src/multimodal.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* ============================================================
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import { readFile
|
|
11
|
+
import { readFile } from 'node:fs/promises';
|
|
12
12
|
import { extname, resolve } from 'node:path';
|
|
13
13
|
import { fileURLToPath } from 'node:url';
|
|
14
14
|
|
|
@@ -20,6 +20,10 @@ import type {
|
|
|
20
20
|
Message,
|
|
21
21
|
} from './types.js';
|
|
22
22
|
import { removeManagedClipboardTemp } from './utils/clipboardImage.js';
|
|
23
|
+
import {
|
|
24
|
+
detectImageMime,
|
|
25
|
+
resolveLocalImage,
|
|
26
|
+
} from './images/imageResolver.js';
|
|
23
27
|
|
|
24
28
|
export const MAX_IMAGE_BYTES = 10 * 1024 * 1024;
|
|
25
29
|
|
|
@@ -32,9 +36,15 @@ const IMAGE_MIME_BY_EXT: Record<string, string> = {
|
|
|
32
36
|
// Read can attach BMP files directly even though inline drag/drop parsing
|
|
33
37
|
// intentionally remains limited to formats accepted by most providers.
|
|
34
38
|
'.bmp': 'image/bmp',
|
|
39
|
+
'.tif': 'image/tiff',
|
|
40
|
+
'.tiff': 'image/tiff',
|
|
41
|
+
'.avif': 'image/avif',
|
|
42
|
+
'.heic': 'image/heic',
|
|
43
|
+
'.heif': 'image/heic',
|
|
44
|
+
'.svg': 'image/svg+xml',
|
|
35
45
|
};
|
|
36
46
|
|
|
37
|
-
const IMAGE_EXT_PATTERN = String.raw`(?:png|jpe?g|gif|webp)`;
|
|
47
|
+
const IMAGE_EXT_PATTERN = String.raw`(?:png|jpe?g|gif|webp|bmp|tiff?|avif|hei[cf]|svg)`;
|
|
38
48
|
|
|
39
49
|
/**
|
|
40
50
|
* 「路径 token」允许的字符:非空白,或 `\x` 这样的转义对——macOS Terminal / iTerm2
|
|
@@ -285,18 +295,7 @@ export async function imageToContentPart(
|
|
|
285
295
|
* 仅按扩展名查会误判「不支持」而拒图——魔数嗅探让任意扩展名的真图都能用。
|
|
286
296
|
*/
|
|
287
297
|
export function sniffImageMime(buf: Buffer): string | null {
|
|
288
|
-
|
|
289
|
-
return 'image/png';
|
|
290
|
-
if (buf.length >= 3 && buf[0] === 0xff && buf[1] === 0xd8 && buf[2] === 0xff) return 'image/jpeg';
|
|
291
|
-
if (buf.length >= 4 && buf[0] === 0x47 && buf[1] === 0x49 && buf[2] === 0x46 && buf[3] === 0x38)
|
|
292
|
-
return 'image/gif';
|
|
293
|
-
if (
|
|
294
|
-
buf.length >= 12 &&
|
|
295
|
-
buf.toString('ascii', 0, 4) === 'RIFF' &&
|
|
296
|
-
buf.toString('ascii', 8, 12) === 'WEBP'
|
|
297
|
-
)
|
|
298
|
-
return 'image/webp';
|
|
299
|
-
return null;
|
|
298
|
+
return detectImageMime(buf);
|
|
300
299
|
}
|
|
301
300
|
|
|
302
301
|
async function imageSourceToUrl(source: string): Promise<string> {
|
|
@@ -304,26 +303,11 @@ async function imageSourceToUrl(source: string): Promise<string> {
|
|
|
304
303
|
if (isHttpUrl(clean) || clean.startsWith('data:image/')) return clean;
|
|
305
304
|
|
|
306
305
|
const filePath = resolveImagePath(clean);
|
|
307
|
-
const
|
|
308
|
-
|
|
306
|
+
const resolved = await resolveLocalImage(filePath, {
|
|
307
|
+
maxOutputBytes: MAX_IMAGE_BYTES,
|
|
309
308
|
});
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
throw new Error(
|
|
313
|
-
`图片过大:${source} ${(st.size / 1024 / 1024).toFixed(1)}MB,` +
|
|
314
|
-
`OpenAI 兼容接口单图上限按 10MB 处理。`,
|
|
315
|
-
);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
const data = await readFile(filePath);
|
|
319
|
-
// 先按扩展名查 MIME;认不出(无扩展名 / .img / 扩展名错)再按文件头魔数嗅探,都不认才拒。
|
|
320
|
-
const mime = IMAGE_MIME_BY_EXT[extname(filePath).toLowerCase()] ?? sniffImageMime(data);
|
|
321
|
-
if (!mime) {
|
|
322
|
-
throw new Error(
|
|
323
|
-
`不支持的图片格式:${source}。仅支持 JPEG/PNG/GIF/WEBP(按扩展名与文件头都未识别)。`,
|
|
324
|
-
);
|
|
325
|
-
}
|
|
326
|
-
return `data:${mime};base64,${data.toString('base64')}`;
|
|
309
|
+
const data = await readFile(resolved.path);
|
|
310
|
+
return `data:${resolved.mime};base64,${data.toString('base64')}`;
|
|
327
311
|
}
|
|
328
312
|
|
|
329
313
|
function resolveImagePath(source: string): string {
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 局域网发现的**线上格式**——服务端(响应器)与 Desktop(探测器)共用这一份。
|
|
3
|
+
*
|
|
4
|
+
* 为什么共享而不是各写一份:这是跨进程、跨机器的字节协议,两份编解码必然漂移,
|
|
5
|
+
* 而漂移的表现是"搜不到,但两边日志都正常",极难排查。
|
|
6
|
+
* (本仓刚因为"服务端与前端各一份任务状态机"吃过亏,同一个教训。)
|
|
7
|
+
*
|
|
8
|
+
* 形态:**响应式**,不是周期广播。
|
|
9
|
+
* 客户端 ──UDP 广播──▶ :5277 `KAKADEAI-DISCOVER/1`
|
|
10
|
+
* 服务端 ──UDP 单播──▶ `KAKADEAI-ANNOUNCE/1 {json}`
|
|
11
|
+
* 没人找的时候零流量,也不需要加入组播组(组播在很多企业交换机上被关掉)。
|
|
12
|
+
*
|
|
13
|
+
* **地址由客户端用回包的源 IP 拼**,服务端不自报地址——它不可靠地知道自己
|
|
14
|
+
* 对外是哪个网卡/哪个地址(多网卡、容器、NAT 都会让自报值是错的)。
|
|
15
|
+
*
|
|
16
|
+
* 安全口径:发现只暴露"这里有一台 minimal-server",**不授予任何访问权**,
|
|
17
|
+
* 之后仍需邀请码注册 + 登录。所以公告包里**绝不能**出现用户数据、群名、账号数量。
|
|
18
|
+
*/
|
|
19
|
+
/** 与既有端口同族:5274 web / 5276 node 控制面 / 5277 发现。 */
|
|
20
|
+
export const DISCOVERY_PORT = 5277;
|
|
21
|
+
/** UDP 上什么都可能收到,超过这个尺寸一律丢弃,不浪费 CPU 去解析。 */
|
|
22
|
+
export const MAX_PACKET_BYTES = 512;
|
|
23
|
+
const PROBE_MAGIC = 'KAKADEAI-DISCOVER/1';
|
|
24
|
+
const ANNOUNCE_MAGIC = 'KAKADEAI-ANNOUNCE/1';
|
|
25
|
+
export function encodeProbe() {
|
|
26
|
+
return Buffer.from(PROBE_MAGIC, 'utf8');
|
|
27
|
+
}
|
|
28
|
+
/** 严格相等匹配:魔数带版本号,将来改格式直接换版本,不做模糊兼容。 */
|
|
29
|
+
export function parseProbe(packet) {
|
|
30
|
+
if (packet.length === 0 || packet.length > MAX_PACKET_BYTES)
|
|
31
|
+
return false;
|
|
32
|
+
return packet.toString('utf8') === PROBE_MAGIC;
|
|
33
|
+
}
|
|
34
|
+
export function encodeAnnounce(info) {
|
|
35
|
+
return Buffer.from(`${ANNOUNCE_MAGIC} ${JSON.stringify(info)}`, 'utf8');
|
|
36
|
+
}
|
|
37
|
+
/** 解析失败一律返回 null,**绝不抛异常**:这是喂给 UDP 回调的,抛了就炸整个进程。 */
|
|
38
|
+
export function parseAnnounce(packet) {
|
|
39
|
+
if (packet.length === 0 || packet.length > MAX_PACKET_BYTES)
|
|
40
|
+
return null;
|
|
41
|
+
const text = packet.toString('utf8');
|
|
42
|
+
if (!text.startsWith(`${ANNOUNCE_MAGIC} `))
|
|
43
|
+
return null;
|
|
44
|
+
try {
|
|
45
|
+
const parsed = JSON.parse(text.slice(ANNOUNCE_MAGIC.length + 1));
|
|
46
|
+
if (!parsed || typeof parsed !== 'object')
|
|
47
|
+
return null;
|
|
48
|
+
const { name, version, protocolVersion, webPort, instanceId } = parsed;
|
|
49
|
+
// 逐字段校验:伪造包与版本漂移都会在这里被拦掉,而不是带着 undefined 往下走。
|
|
50
|
+
if (name !== 'minimal-server')
|
|
51
|
+
return null;
|
|
52
|
+
if (typeof version !== 'string' || !version)
|
|
53
|
+
return null;
|
|
54
|
+
if (typeof protocolVersion !== 'number' || !Number.isInteger(protocolVersion))
|
|
55
|
+
return null;
|
|
56
|
+
if (typeof webPort !== 'number' || !Number.isInteger(webPort) || webPort < 1 || webPort > 65535)
|
|
57
|
+
return null;
|
|
58
|
+
if (typeof instanceId !== 'string' || !instanceId)
|
|
59
|
+
return null;
|
|
60
|
+
return { name, version, protocolVersion, webPort, instanceId };
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 局域网发现的**线上格式**——服务端(响应器)与 Desktop(探测器)共用这一份。
|
|
3
|
+
*
|
|
4
|
+
* 为什么共享而不是各写一份:这是跨进程、跨机器的字节协议,两份编解码必然漂移,
|
|
5
|
+
* 而漂移的表现是"搜不到,但两边日志都正常",极难排查。
|
|
6
|
+
* (本仓刚因为"服务端与前端各一份任务状态机"吃过亏,同一个教训。)
|
|
7
|
+
*
|
|
8
|
+
* 形态:**响应式**,不是周期广播。
|
|
9
|
+
* 客户端 ──UDP 广播──▶ :5277 `KAKADEAI-DISCOVER/1`
|
|
10
|
+
* 服务端 ──UDP 单播──▶ `KAKADEAI-ANNOUNCE/1 {json}`
|
|
11
|
+
* 没人找的时候零流量,也不需要加入组播组(组播在很多企业交换机上被关掉)。
|
|
12
|
+
*
|
|
13
|
+
* **地址由客户端用回包的源 IP 拼**,服务端不自报地址——它不可靠地知道自己
|
|
14
|
+
* 对外是哪个网卡/哪个地址(多网卡、容器、NAT 都会让自报值是错的)。
|
|
15
|
+
*
|
|
16
|
+
* 安全口径:发现只暴露"这里有一台 minimal-server",**不授予任何访问权**,
|
|
17
|
+
* 之后仍需邀请码注册 + 登录。所以公告包里**绝不能**出现用户数据、群名、账号数量。
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/** 与既有端口同族:5274 web / 5276 node 控制面 / 5277 发现。 */
|
|
21
|
+
export const DISCOVERY_PORT = 5277;
|
|
22
|
+
|
|
23
|
+
/** UDP 上什么都可能收到,超过这个尺寸一律丢弃,不浪费 CPU 去解析。 */
|
|
24
|
+
export const MAX_PACKET_BYTES = 512;
|
|
25
|
+
|
|
26
|
+
const PROBE_MAGIC = 'KAKADEAI-DISCOVER/1';
|
|
27
|
+
const ANNOUNCE_MAGIC = 'KAKADEAI-ANNOUNCE/1';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 公告内容。**只允许放这几个字段**——多一个都可能变成信息泄露。
|
|
31
|
+
* 尤其不能出现用户数、群名、账号信息:发现只说明"这里有一台服务器"。
|
|
32
|
+
*/
|
|
33
|
+
export interface DiscoveryAnnounce {
|
|
34
|
+
name: 'minimal-server';
|
|
35
|
+
version: string;
|
|
36
|
+
/** 与 /api/health 的 protocolVersion 同义,供客户端判兼容性。 */
|
|
37
|
+
protocolVersion: number;
|
|
38
|
+
/** web 协作服务端口;客户端拼 `http://<回包源IP>:<webPort>`。 */
|
|
39
|
+
webPort: number;
|
|
40
|
+
/**
|
|
41
|
+
* 本次进程启动生成的随机实例标识。**唯一用途是让客户端把同一台服务器的多个网卡地址
|
|
42
|
+
* 归并成一条**——多网卡机器(VPN/VMware/WSL)会从每张网卡各回一次,
|
|
43
|
+
* 不归并的话 UI 上一台服务器显示成五条。
|
|
44
|
+
* 它不是凭据、不参与鉴权、每次重启都变,泄露无害。
|
|
45
|
+
*/
|
|
46
|
+
instanceId: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function encodeProbe(): Buffer {
|
|
50
|
+
return Buffer.from(PROBE_MAGIC, 'utf8');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** 严格相等匹配:魔数带版本号,将来改格式直接换版本,不做模糊兼容。 */
|
|
54
|
+
export function parseProbe(packet: Buffer): boolean {
|
|
55
|
+
if (packet.length === 0 || packet.length > MAX_PACKET_BYTES) return false;
|
|
56
|
+
return packet.toString('utf8') === PROBE_MAGIC;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function encodeAnnounce(info: DiscoveryAnnounce): Buffer {
|
|
60
|
+
return Buffer.from(`${ANNOUNCE_MAGIC} ${JSON.stringify(info)}`, 'utf8');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** 解析失败一律返回 null,**绝不抛异常**:这是喂给 UDP 回调的,抛了就炸整个进程。 */
|
|
64
|
+
export function parseAnnounce(packet: Buffer): DiscoveryAnnounce | null {
|
|
65
|
+
if (packet.length === 0 || packet.length > MAX_PACKET_BYTES) return null;
|
|
66
|
+
const text = packet.toString('utf8');
|
|
67
|
+
if (!text.startsWith(`${ANNOUNCE_MAGIC} `)) return null;
|
|
68
|
+
try {
|
|
69
|
+
const parsed: unknown = JSON.parse(text.slice(ANNOUNCE_MAGIC.length + 1));
|
|
70
|
+
if (!parsed || typeof parsed !== 'object') return null;
|
|
71
|
+
const { name, version, protocolVersion, webPort, instanceId } = parsed as Record<string, unknown>;
|
|
72
|
+
// 逐字段校验:伪造包与版本漂移都会在这里被拦掉,而不是带着 undefined 往下走。
|
|
73
|
+
if (name !== 'minimal-server') return null;
|
|
74
|
+
if (typeof version !== 'string' || !version) return null;
|
|
75
|
+
if (typeof protocolVersion !== 'number' || !Number.isInteger(protocolVersion)) return null;
|
|
76
|
+
if (typeof webPort !== 'number' || !Number.isInteger(webPort) || webPort < 1 || webPort > 65535) return null;
|
|
77
|
+
if (typeof instanceId !== 'string' || !instanceId) return null;
|
|
78
|
+
return { name, version, protocolVersion, webPort, instanceId };
|
|
79
|
+
} catch {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
package/src/plugin-sdk.js
CHANGED
|
@@ -44,11 +44,17 @@ export { dlog } from './utils/debugLog.js';
|
|
|
44
44
|
// <think> 思维链剥离:内核与 workflow-runner 共享(原住 agentCommon.ts,
|
|
45
45
|
// Agent 子任务工具也需要 → 上移内核,插件经此 re-export)。
|
|
46
46
|
export { stripThinkBlocks } from './utils/stripThink.js';
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
|
|
47
|
+
// 长驻宿主保持 buildBaseSystemPrompt 稳定,每回合单独传 transient bundle。
|
|
48
|
+
// (`buildTransientContext` 曾也在这里 re-export,唯一消费者是已删除的 yaml 引擎;
|
|
49
|
+
// 门面每多一个导出就多一条不能自由重构的边,没消费者就先不导出。)
|
|
50
|
+
export { buildBaseSystemPrompt, buildTransientPromptBundle, } from './prompts/system.js';
|
|
51
|
+
export { refreshStableSystemPrompt, upsertStableSystemMessage, } from './prompts/stableSystemPrompt.js';
|
|
50
52
|
export { createAgentRuntimeContext, filterToolsForRuntime, } from './runtime/agentRuntimeContext.js';
|
|
51
53
|
export { getResourceSearchPaths } from './utils/resourcePaths.js';
|
|
54
|
+
// 「这个路径在不在那个目录里」的唯一实现——已经被手写错过好几次(含
|
|
55
|
+
// workflow-runner 自己的两份,Windows 跨盘符时会误判成"在目录内")。插件凡是要
|
|
56
|
+
// 做路径包含判定,一律经这里,不要再手写一遍。
|
|
57
|
+
export { pathContains } from './utils/pathContains.js';
|
|
52
58
|
// 确定性检查设施:verify 步(shell/file_exists/file_contains/test_count)经此跑校验。
|
|
53
59
|
export { parseCheckString, runVerification } from './infra/verification.js';
|
|
54
60
|
export { triggerHook } from './plugins/hookEngine.js';
|
|
@@ -57,3 +63,22 @@ export { createSessionState } from './session/sessionState.js';
|
|
|
57
63
|
// cron-runner 等需要在发起回合前判断"绑定的 session 是否还在"时用它,
|
|
58
64
|
// 不要绕过 legacy 回退逻辑自己拼路径。
|
|
59
65
|
export { resolveSessionFile } from './context/sessionPath.js';
|
|
66
|
+
/**
|
|
67
|
+
* 按模型 id 解析出一个 Provider(工作流的 `agent(..., { model })` 用)。
|
|
68
|
+
*
|
|
69
|
+
* ⚠️ 门面只暴露这一个**语义明确的解析函数**,不暴露整个 ConfigService ——
|
|
70
|
+
* 后者带着读写配置、草稿、顾问设置一大堆能力,插件不该拿到,而门面每多一个
|
|
71
|
+
* 导出就多一条不能自由重构的边(`test/pluginSdkSurface.test.ts` 守这条)。
|
|
72
|
+
*
|
|
73
|
+
* 解析不到(id 不存在 / 该条目没填 apiKey)返回 null —— 调用方**必须**回落到
|
|
74
|
+
* 基座 provider 并如实告警,不能静默换模型。
|
|
75
|
+
*/
|
|
76
|
+
export async function resolveProviderForModel(modelId) {
|
|
77
|
+
const { configService } = await import('./config/configService.js');
|
|
78
|
+
return configService.providerForModel(modelId);
|
|
79
|
+
}
|
|
80
|
+
/** Resolve a portable workflow capability role through this machine's config. */
|
|
81
|
+
export async function resolveProviderForWorkflowRole(role) {
|
|
82
|
+
const { configService } = await import('./config/configService.js');
|
|
83
|
+
return configService.providerForWorkflowRole(role);
|
|
84
|
+
}
|