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
|
@@ -1,7 +1,51 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import {
|
|
2
|
+
import { modelRefFromLegacy, } from '../modelRef.js';
|
|
3
|
+
import { fetchOnlineModels, loadTeamCredentials, resolveOnlineModel, } from '../team/auth.js';
|
|
4
|
+
import { DEFAULT_ADVISOR_CONFIG, DEFAULT_BROWSER_CONFIG, DEFAULT_COMPUTER_USE_CONFIG, DEFAULT_SUBAGENTS_CONFIG, defaultMaxTokens, readMinimalAgentConfig, updateMinimalAgentConfig, } from './configFile.js';
|
|
3
5
|
import { CONFIG_LIMITS, normalizeLimited } from './numericLimits.js';
|
|
4
6
|
const DEFAULT_CONTEXT_WINDOW = 128_000;
|
|
7
|
+
function gatewayFallbackReason(model, error) {
|
|
8
|
+
const state = model?.availability?.state;
|
|
9
|
+
if (state === 'quota_exhausted' || state === 'concurrency_exceeded')
|
|
10
|
+
return 'quota_exhausted';
|
|
11
|
+
if (state === 'model_disabled' || state === 'disabled')
|
|
12
|
+
return 'model_disabled';
|
|
13
|
+
if (state === 'device_expired')
|
|
14
|
+
return 'credential_expired';
|
|
15
|
+
if (state === 'not_authorized')
|
|
16
|
+
return 'grant_revoked';
|
|
17
|
+
if (state === 'server_offline' || state === 'offline')
|
|
18
|
+
return 'offline';
|
|
19
|
+
const message = error instanceof Error ? error.message : '';
|
|
20
|
+
if (message.includes('DEVICE_REVOKED') || message.includes('401'))
|
|
21
|
+
return 'credential_expired';
|
|
22
|
+
if (message.includes('MODEL_UNAVAILABLE') || message.includes('403'))
|
|
23
|
+
return 'grant_revoked';
|
|
24
|
+
return 'offline';
|
|
25
|
+
}
|
|
26
|
+
function gatewayProviderFromModel(credentials, model) {
|
|
27
|
+
return {
|
|
28
|
+
name: model.displayName || model.model,
|
|
29
|
+
source: 'gateway',
|
|
30
|
+
remoteModelId: model.id,
|
|
31
|
+
gatewayUrl: credentials.serverUrl,
|
|
32
|
+
gatewayToken: credentials.deviceToken,
|
|
33
|
+
gatewayMaxToolCategories: model.maxToolCategories,
|
|
34
|
+
gatewayDefaultToolCategories: model.defaultToolCategories,
|
|
35
|
+
// Deprecated compatibility field: before the explicit max/default/session
|
|
36
|
+
// split this field was used as the provider boundary. Keep its safe
|
|
37
|
+
// default as the server maximum; the current Session selection is applied
|
|
38
|
+
// per turn by runAgentTurn/useChat.
|
|
39
|
+
gatewayToolCategories: model.maxToolCategories,
|
|
40
|
+
model: model.model,
|
|
41
|
+
contextWindow: model.contextWindow,
|
|
42
|
+
maxTokens: model.maxTokens,
|
|
43
|
+
apiFormat: model.apiFormat,
|
|
44
|
+
supportsVision: model.supportsVision,
|
|
45
|
+
gatewayCapabilities: model.capabilities,
|
|
46
|
+
promptCache: { mode: 'disabled' },
|
|
47
|
+
};
|
|
48
|
+
}
|
|
5
49
|
function positiveInt(value, fallback) {
|
|
6
50
|
const parsed = Number.parseInt(value ?? '', 10);
|
|
7
51
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
@@ -26,14 +70,20 @@ function configFromEnv() {
|
|
|
26
70
|
return null;
|
|
27
71
|
const tools = {};
|
|
28
72
|
if (process.env.TAVILY_API_KEY)
|
|
29
|
-
tools.webSearch = {
|
|
30
|
-
|
|
73
|
+
tools.webSearch = {
|
|
74
|
+
provider: 'tavily',
|
|
75
|
+
apiKey: process.env.TAVILY_API_KEY,
|
|
76
|
+
};
|
|
77
|
+
if (process.env.OPENAI_IMAGE_BASE_URL &&
|
|
78
|
+
process.env.OPENAI_IMAGE_API_KEY &&
|
|
79
|
+
process.env.OPENAI_IMAGE_MODEL) {
|
|
31
80
|
tools.imageGeneration = {
|
|
32
81
|
provider: process.env.OPENAI_IMAGE_PROVIDER ?? 'openai',
|
|
33
82
|
baseURL: process.env.OPENAI_IMAGE_BASE_URL,
|
|
34
83
|
apiKey: process.env.OPENAI_IMAGE_API_KEY,
|
|
35
84
|
model: process.env.OPENAI_IMAGE_MODEL,
|
|
36
|
-
protocol: process.env.OPENAI_IMAGE_PROTOCOL === 'chat' ||
|
|
85
|
+
protocol: process.env.OPENAI_IMAGE_PROTOCOL === 'chat' ||
|
|
86
|
+
process.env.OPENAI_IMAGE_PROTOCOL === 'images'
|
|
37
87
|
? process.env.OPENAI_IMAGE_PROTOCOL
|
|
38
88
|
: 'auto',
|
|
39
89
|
};
|
|
@@ -41,7 +91,11 @@ function configFromEnv() {
|
|
|
41
91
|
if (process.env.OPENROUTER_API_KEY)
|
|
42
92
|
tools.openRouter = { apiKey: process.env.OPENROUTER_API_KEY };
|
|
43
93
|
if (process.env.MINIMAX_API_KEY && process.env.MINIMAX_GROUP_ID) {
|
|
44
|
-
tools.textToSpeech = {
|
|
94
|
+
tools.textToSpeech = {
|
|
95
|
+
provider: 'minimax',
|
|
96
|
+
apiKey: process.env.MINIMAX_API_KEY,
|
|
97
|
+
groupId: process.env.MINIMAX_GROUP_ID,
|
|
98
|
+
};
|
|
45
99
|
}
|
|
46
100
|
const compactRatio = Number(process.env.MINIMAL_AGENT_COMPACT_RATIO);
|
|
47
101
|
const name = process.env.MINIMAL_AGENT_PROVIDER ?? 'env';
|
|
@@ -70,13 +124,14 @@ function configFromEnv() {
|
|
|
70
124
|
version: 4,
|
|
71
125
|
models: [envModel],
|
|
72
126
|
baseModelId: envModel.id,
|
|
127
|
+
teamServerUrl: process.env.KAKADEAI_SOCIAL_SERVER_URL?.trim() || null,
|
|
73
128
|
...(compactRatio > 0 && compactRatio <= 1 ? { compactRatio } : {}),
|
|
74
129
|
subagents: {
|
|
75
130
|
...DEFAULT_SUBAGENTS_CONFIG,
|
|
76
131
|
maxCallsPerTurn: positiveInt(process.env.AGENT_TOOL_MAX_CALLS_PER_TURN, 6),
|
|
77
132
|
maxConcurrent: positiveInt(process.env.AGENT_TOOL_MAX_CONCURRENT, 3),
|
|
78
133
|
timeoutMs: positiveInt(process.env.AGENT_TOOL_TIMEOUT_MS, 1_800_000),
|
|
79
|
-
exploreMaxTurns: positiveInt(process.env.AGENT_TOOL_EXPLORE_MAX_TURNS,
|
|
134
|
+
exploreMaxTurns: positiveInt(process.env.AGENT_TOOL_EXPLORE_MAX_TURNS, 200),
|
|
80
135
|
generalMaxTurns: positiveInt(process.env.AGENT_TOOL_GENERAL_MAX_TURNS, 100),
|
|
81
136
|
},
|
|
82
137
|
browser: DEFAULT_BROWSER_CONFIG,
|
|
@@ -92,6 +147,7 @@ function configFromEnv() {
|
|
|
92
147
|
}
|
|
93
148
|
function resolveProvider(entry, compactRatio) {
|
|
94
149
|
return {
|
|
150
|
+
source: 'local',
|
|
95
151
|
name: entry.displayName ?? entry.model,
|
|
96
152
|
baseURL: entry.baseURL,
|
|
97
153
|
apiKey: entry.apiKey,
|
|
@@ -100,15 +156,26 @@ function resolveProvider(entry, compactRatio) {
|
|
|
100
156
|
maxTokens: entry.maxTokens ?? defaultMaxTokens(entry.contextWindow),
|
|
101
157
|
apiFormat: entry.apiFormat,
|
|
102
158
|
supportsVision: entry.supportsVision !== false,
|
|
159
|
+
...(entry.supportsJsonSchema !== undefined
|
|
160
|
+
? { supportsJsonSchema: entry.supportsJsonSchema }
|
|
161
|
+
: {}),
|
|
103
162
|
promptCache: entry.promptCache ?? { mode: 'auto' },
|
|
104
163
|
...(compactRatio !== undefined ? { compactRatio } : {}),
|
|
164
|
+
// cache_edits 式回收:仅 Anthropic 格式 + 显式 env 开启时生效(非公开协议,
|
|
165
|
+
// 依赖支持该扩展的网关端点;语义与默认值说明见 types.ts Provider.cacheEdits)
|
|
166
|
+
...(entry.apiFormat === 'anthropic' &&
|
|
167
|
+
process.env.MINIMAL_AGENT_CACHE_EDITS === '1'
|
|
168
|
+
? { cacheEdits: true }
|
|
169
|
+
: {}),
|
|
105
170
|
};
|
|
106
171
|
}
|
|
107
172
|
function mergeRecord(base, patch) {
|
|
108
173
|
const out = { ...(base ?? {}) };
|
|
109
174
|
for (const [key, value] of Object.entries(patch)) {
|
|
110
175
|
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
111
|
-
out[key] = mergeRecord(out[key] && typeof out[key] === 'object' && !Array.isArray(out[key])
|
|
176
|
+
out[key] = mergeRecord(out[key] && typeof out[key] === 'object' && !Array.isArray(out[key])
|
|
177
|
+
? out[key]
|
|
178
|
+
: undefined, value);
|
|
112
179
|
}
|
|
113
180
|
else if (value !== undefined)
|
|
114
181
|
out[key] = value;
|
|
@@ -118,6 +185,13 @@ function mergeRecord(base, patch) {
|
|
|
118
185
|
function hasEntries(value) {
|
|
119
186
|
return !!value && Object.keys(value).length > 0;
|
|
120
187
|
}
|
|
188
|
+
/** Remove an optional config key while keeping the persisted object sparse. */
|
|
189
|
+
function omitKey(value, key) {
|
|
190
|
+
if (!value)
|
|
191
|
+
return value;
|
|
192
|
+
const { [key]: _removed, ...rest } = value;
|
|
193
|
+
return rest;
|
|
194
|
+
}
|
|
121
195
|
function applyModelsPatch(models, ops) {
|
|
122
196
|
let out = [...models];
|
|
123
197
|
const now = Date.now();
|
|
@@ -137,9 +211,14 @@ function applyModelsPatch(models, ops) {
|
|
|
137
211
|
baseURL,
|
|
138
212
|
apiKey,
|
|
139
213
|
model: modelId,
|
|
140
|
-
contextWindow: m.contextWindow && m.contextWindow > 0
|
|
214
|
+
contextWindow: m.contextWindow && m.contextWindow > 0
|
|
215
|
+
? m.contextWindow
|
|
216
|
+
: DEFAULT_CONTEXT_WINDOW,
|
|
141
217
|
...(m.maxTokens ? { maxTokens: m.maxTokens } : {}),
|
|
142
218
|
supportsVision: m.supportsVision !== false,
|
|
219
|
+
...(m.supportsJsonSchema !== undefined
|
|
220
|
+
? { supportsJsonSchema: m.supportsJsonSchema }
|
|
221
|
+
: {}),
|
|
143
222
|
promptCache: m.promptCache ?? { mode: 'auto' },
|
|
144
223
|
enabled: m.enabled ?? true,
|
|
145
224
|
createdAt: now,
|
|
@@ -154,13 +233,26 @@ function applyModelsPatch(models, ops) {
|
|
|
154
233
|
const patch = item.patch;
|
|
155
234
|
const next = {
|
|
156
235
|
...existing,
|
|
157
|
-
...(patch.apiFormat
|
|
158
|
-
|
|
236
|
+
...(patch.apiFormat
|
|
237
|
+
? {
|
|
238
|
+
apiFormat: patch.apiFormat === 'anthropic' ? 'anthropic' : 'openai',
|
|
239
|
+
}
|
|
240
|
+
: {}),
|
|
241
|
+
...(patch.displayName !== undefined
|
|
242
|
+
? { displayName: patch.displayName.trim() || undefined }
|
|
243
|
+
: {}),
|
|
159
244
|
...(patch.baseURL?.trim() ? { baseURL: patch.baseURL.trim() } : {}),
|
|
160
245
|
...(patch.model?.trim() ? { model: patch.model.trim() } : {}),
|
|
161
246
|
...(patch.contextWindow ? { contextWindow: patch.contextWindow } : {}),
|
|
162
|
-
...(patch.maxTokens !== undefined
|
|
163
|
-
|
|
247
|
+
...(patch.maxTokens !== undefined
|
|
248
|
+
? { maxTokens: patch.maxTokens || undefined }
|
|
249
|
+
: {}),
|
|
250
|
+
...(patch.supportsVision !== undefined
|
|
251
|
+
? { supportsVision: patch.supportsVision !== false }
|
|
252
|
+
: {}),
|
|
253
|
+
...(patch.supportsJsonSchema !== undefined
|
|
254
|
+
? { supportsJsonSchema: patch.supportsJsonSchema }
|
|
255
|
+
: {}),
|
|
164
256
|
...(patch.promptCache ? { promptCache: patch.promptCache } : {}),
|
|
165
257
|
...(patch.enabled !== undefined ? { enabled: patch.enabled } : {}),
|
|
166
258
|
updatedAt: now,
|
|
@@ -187,7 +279,8 @@ function applyConfigPatch(base, patch) {
|
|
|
187
279
|
if (wasEmpty && baseModelId === null && models.length > 0)
|
|
188
280
|
baseModelId = models[0].id;
|
|
189
281
|
if (patch.baseModelId !== undefined) {
|
|
190
|
-
if (patch.baseModelId !== null &&
|
|
282
|
+
if (patch.baseModelId !== null &&
|
|
283
|
+
!models.some((entry) => entry.id === patch.baseModelId)) {
|
|
191
284
|
throw new Error('要设为基座的模型不存在');
|
|
192
285
|
}
|
|
193
286
|
baseModelId = patch.baseModelId;
|
|
@@ -200,6 +293,11 @@ function applyConfigPatch(base, patch) {
|
|
|
200
293
|
if (baseEntry.enabled === false)
|
|
201
294
|
throw new Error('不能禁用当前基座模型,请先设置其他模型为基座');
|
|
202
295
|
}
|
|
296
|
+
// 团队服务器地址:不像 baseModelId 那样要交叉校验(不引用 models[]),一个裸字符串。
|
|
297
|
+
let teamServerUrl = base?.teamServerUrl ?? null;
|
|
298
|
+
if (patch.teamServerUrl !== undefined) {
|
|
299
|
+
teamServerUrl = patch.teamServerUrl?.trim() || null;
|
|
300
|
+
}
|
|
203
301
|
let advisor = base?.advisor;
|
|
204
302
|
if (patch.advisor) {
|
|
205
303
|
if (patch.advisor.clear) {
|
|
@@ -207,85 +305,113 @@ function applyConfigPatch(base, patch) {
|
|
|
207
305
|
}
|
|
208
306
|
else {
|
|
209
307
|
advisor = {
|
|
210
|
-
enabled: patch.advisor.enabled ?? advisor?.enabled ??
|
|
308
|
+
enabled: patch.advisor.enabled ?? advisor?.enabled ?? DEFAULT_ADVISOR_CONFIG.enabled,
|
|
211
309
|
mode: patch.advisor.mode ?? advisor?.mode ?? 'auto',
|
|
212
|
-
modelId: patch.advisor.modelId !== undefined
|
|
310
|
+
modelId: patch.advisor.modelId !== undefined
|
|
311
|
+
? patch.advisor.modelId
|
|
312
|
+
: (advisor?.modelId ?? null),
|
|
213
313
|
contextPolicy: 'full-relevant',
|
|
214
314
|
shareSensitive: patch.advisor.shareSensitive ?? advisor?.shareSensitive ?? false,
|
|
215
|
-
inputTokenBudget: normalizeLimited(patch.advisor.inputTokenBudget ?? advisor?.inputTokenBudget, CONFIG_LIMITS.advisorInputTokenBudget,
|
|
216
|
-
timeoutMs: normalizeLimited(patch.advisor.timeoutMs ?? advisor?.timeoutMs, CONFIG_LIMITS.advisorTimeoutMs,
|
|
315
|
+
inputTokenBudget: normalizeLimited(patch.advisor.inputTokenBudget ?? advisor?.inputTokenBudget, CONFIG_LIMITS.advisorInputTokenBudget, DEFAULT_ADVISOR_CONFIG.inputTokenBudget),
|
|
316
|
+
timeoutMs: normalizeLimited(patch.advisor.timeoutMs ?? advisor?.timeoutMs, CONFIG_LIMITS.advisorTimeoutMs, DEFAULT_ADVISOR_CONFIG.timeoutMs),
|
|
217
317
|
};
|
|
218
318
|
}
|
|
219
319
|
}
|
|
220
320
|
// 顾问引用的模型若已被删除或禁用,级联置空(软失联——解析层已把 null/悬空 id 当
|
|
221
321
|
// 「未配置」优雅处理,不留死链接;这与基座模型的硬阻止是刻意的不对称:顾问本来就是
|
|
222
322
|
// 可降级的第二意见,不像基座那样「没有就整个应用跑不起来」)。
|
|
223
|
-
if (advisor?.modelId) {
|
|
323
|
+
if (advisor?.modelId && !advisor.modelId.startsWith('online:')) {
|
|
224
324
|
const referenced = models.find((entry) => entry.id === advisor.modelId);
|
|
225
325
|
if (!referenced || referenced.enabled === false)
|
|
226
326
|
advisor = { ...advisor, modelId: null };
|
|
227
327
|
}
|
|
328
|
+
const workflowModels = {
|
|
329
|
+
...(base?.workflowModels ?? {}),
|
|
330
|
+
};
|
|
331
|
+
for (const [role, modelId] of Object.entries(patch.workflowModels ?? {})) {
|
|
332
|
+
if (modelId)
|
|
333
|
+
workflowModels[role] = modelId;
|
|
334
|
+
else
|
|
335
|
+
delete workflowModels[role];
|
|
336
|
+
}
|
|
337
|
+
for (const role of Object.keys(workflowModels)) {
|
|
338
|
+
const modelId = workflowModels[role];
|
|
339
|
+
const configured = models.find((entry) => entry.id === modelId);
|
|
340
|
+
if (!configured || configured.enabled === false)
|
|
341
|
+
delete workflowModels[role];
|
|
342
|
+
}
|
|
228
343
|
// 比例类:保留 4 位小数(= 百分比 2 位),否则 UI 上下箭头按 0.01 步进会累加出
|
|
229
344
|
// `0.8500000000000001` 这种浮点脏值直接写进 config.json。
|
|
230
345
|
const compactRatio = patch.compactRatio !== undefined
|
|
231
|
-
?
|
|
346
|
+
? patch.compactRatio > 0 && patch.compactRatio <= 1
|
|
232
347
|
? normalizeLimited(patch.compactRatio, CONFIG_LIMITS.compactRatio, CONFIG_LIMITS.compactRatio.max)
|
|
233
|
-
: undefined
|
|
348
|
+
: undefined
|
|
234
349
|
: base?.compactRatio;
|
|
235
|
-
|
|
350
|
+
let tools = { ...(base?.tools ?? {}) };
|
|
236
351
|
const drafts = structuredClone(base?.drafts ?? {});
|
|
237
352
|
const toolPatch = patch.tools;
|
|
238
353
|
if (toolPatch?.webSearch) {
|
|
239
354
|
if (toolPatch.webSearch.clear) {
|
|
240
|
-
|
|
241
|
-
|
|
355
|
+
tools = omitKey(tools, 'webSearch') ?? {};
|
|
356
|
+
if (drafts.tools)
|
|
357
|
+
drafts.tools = omitKey(drafts.tools, 'webSearch');
|
|
242
358
|
}
|
|
243
359
|
else
|
|
244
|
-
tools.webSearch = mergeRecord(tools.webSearch, {
|
|
360
|
+
tools.webSearch = mergeRecord(tools.webSearch, {
|
|
361
|
+
provider: 'tavily',
|
|
362
|
+
...toolPatch.webSearch,
|
|
363
|
+
});
|
|
245
364
|
}
|
|
246
365
|
if (toolPatch?.imageGeneration) {
|
|
247
366
|
if (toolPatch.imageGeneration.clear) {
|
|
248
|
-
|
|
249
|
-
|
|
367
|
+
tools = omitKey(tools, 'imageGeneration') ?? {};
|
|
368
|
+
if (drafts.tools)
|
|
369
|
+
drafts.tools = omitKey(drafts.tools, 'imageGeneration');
|
|
250
370
|
}
|
|
251
371
|
else {
|
|
252
372
|
const next = mergeRecord(tools.imageGeneration, toolPatch.imageGeneration);
|
|
253
373
|
if (toolPatch.imageGeneration.clearApiKey)
|
|
254
374
|
next.apiKey = '';
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
if (!next.baseURL || !next.apiKey || !next.model)
|
|
375
|
+
const cleanNext = omitKey(omitKey(next, 'clear'), 'clearApiKey');
|
|
376
|
+
if (!cleanNext.baseURL || !cleanNext.apiKey || !cleanNext.model)
|
|
258
377
|
throw new Error('图片生成缺少 Base URL、API Key 或模型名称');
|
|
259
|
-
tools.imageGeneration =
|
|
378
|
+
tools.imageGeneration = cleanNext;
|
|
260
379
|
}
|
|
261
380
|
}
|
|
262
381
|
if (toolPatch?.openRouter) {
|
|
263
382
|
if (toolPatch.openRouter.clear) {
|
|
264
|
-
|
|
265
|
-
|
|
383
|
+
tools = omitKey(tools, 'openRouter') ?? {};
|
|
384
|
+
if (drafts.tools)
|
|
385
|
+
drafts.tools = omitKey(drafts.tools, 'openRouter');
|
|
266
386
|
}
|
|
267
387
|
else
|
|
268
388
|
tools.openRouter = mergeRecord(tools.openRouter, toolPatch.openRouter);
|
|
269
389
|
}
|
|
270
390
|
if (toolPatch?.textToSpeech) {
|
|
271
391
|
if (toolPatch.textToSpeech.clear) {
|
|
272
|
-
|
|
273
|
-
|
|
392
|
+
tools = omitKey(tools, 'textToSpeech') ?? {};
|
|
393
|
+
if (drafts.tools)
|
|
394
|
+
drafts.tools = omitKey(drafts.tools, 'textToSpeech');
|
|
274
395
|
}
|
|
275
396
|
else {
|
|
276
|
-
const next = mergeRecord(tools.textToSpeech, {
|
|
397
|
+
const next = mergeRecord(tools.textToSpeech, {
|
|
398
|
+
provider: 'minimax',
|
|
399
|
+
...toolPatch.textToSpeech,
|
|
400
|
+
});
|
|
277
401
|
if (toolPatch.textToSpeech.clearApiKey)
|
|
278
402
|
next.apiKey = '';
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
if (!next.apiKey || !next.groupId)
|
|
403
|
+
const cleanNext = omitKey(omitKey(next, 'clear'), 'clearApiKey');
|
|
404
|
+
if (!cleanNext.apiKey || !cleanNext.groupId)
|
|
282
405
|
throw new Error('MiniMax 语音缺少 API Key 或 Group ID');
|
|
283
|
-
tools.textToSpeech =
|
|
406
|
+
tools.textToSpeech = cleanNext;
|
|
284
407
|
}
|
|
285
408
|
}
|
|
286
409
|
// 数字字段必须在**写入时**就按同一份边界规整——此前这里是裸 spread,读回时才被
|
|
287
410
|
// parseSubagents 的边界收窄,于是「存进去 300、读出来 100」,UI 表现成静默变回原值。
|
|
288
|
-
const mergedSubagents = {
|
|
411
|
+
const mergedSubagents = {
|
|
412
|
+
...(base?.subagents ?? DEFAULT_SUBAGENTS_CONFIG),
|
|
413
|
+
...(patch.subagents ?? {}),
|
|
414
|
+
};
|
|
289
415
|
const subagents = {
|
|
290
416
|
...mergedSubagents,
|
|
291
417
|
maxCallsPerTurn: normalizeLimited(mergedSubagents.maxCallsPerTurn, CONFIG_LIMITS.subagentMaxCallsPerTurn, DEFAULT_SUBAGENTS_CONFIG.maxCallsPerTurn),
|
|
@@ -294,7 +420,11 @@ function applyConfigPatch(base, patch) {
|
|
|
294
420
|
exploreMaxTurns: normalizeLimited(mergedSubagents.exploreMaxTurns, CONFIG_LIMITS.subagentExploreMaxTurns, DEFAULT_SUBAGENTS_CONFIG.exploreMaxTurns),
|
|
295
421
|
generalMaxTurns: normalizeLimited(mergedSubagents.generalMaxTurns, CONFIG_LIMITS.subagentGeneralMaxTurns, DEFAULT_SUBAGENTS_CONFIG.generalMaxTurns),
|
|
296
422
|
};
|
|
297
|
-
const browser = {
|
|
423
|
+
const browser = {
|
|
424
|
+
...(base?.browser ?? DEFAULT_BROWSER_CONFIG),
|
|
425
|
+
...(patch.browser ?? {}),
|
|
426
|
+
profileId: 'default',
|
|
427
|
+
};
|
|
298
428
|
const computerUse = {
|
|
299
429
|
...(base?.computerUse ?? DEFAULT_COMPUTER_USE_CONFIG),
|
|
300
430
|
...(patch.computerUse ?? {}),
|
|
@@ -302,12 +432,34 @@ function applyConfigPatch(base, patch) {
|
|
|
302
432
|
computerUse.observationFrames = 1;
|
|
303
433
|
computerUse.maxImagePixels = normalizeLimited(computerUse.maxImagePixels, CONFIG_LIMITS.computerUseMaxImagePixels, DEFAULT_COMPUTER_USE_CONFIG.maxImagePixels);
|
|
304
434
|
if (!hasEntries(drafts.tools))
|
|
305
|
-
|
|
306
|
-
return {
|
|
435
|
+
drafts.tools = undefined;
|
|
436
|
+
return {
|
|
437
|
+
models,
|
|
438
|
+
baseModelId,
|
|
439
|
+
teamServerUrl,
|
|
440
|
+
...(compactRatio !== undefined ? { compactRatio } : {}),
|
|
441
|
+
advisor,
|
|
442
|
+
// Preserve an explicit empty object through updateMinimalAgentConfig so
|
|
443
|
+
// removing the final role is distinguishable from an unrelated mutator
|
|
444
|
+
// that omitted this optional field.
|
|
445
|
+
workflowModels,
|
|
446
|
+
subagents,
|
|
447
|
+
browser,
|
|
448
|
+
computerUse,
|
|
449
|
+
tools,
|
|
450
|
+
...(hasEntries(drafts) ? { drafts } : {}),
|
|
451
|
+
};
|
|
307
452
|
}
|
|
308
453
|
export class ConfigService {
|
|
309
|
-
snapshot = {
|
|
310
|
-
|
|
454
|
+
snapshot = {
|
|
455
|
+
source: 'none',
|
|
456
|
+
readOnly: false,
|
|
457
|
+
config: null,
|
|
458
|
+
revision: 0,
|
|
459
|
+
};
|
|
460
|
+
get revision() {
|
|
461
|
+
return this.snapshot.revision;
|
|
462
|
+
}
|
|
311
463
|
async reload() {
|
|
312
464
|
const envOnly = process.env.MINIMAL_AGENT_CONFIG_MODE === 'env';
|
|
313
465
|
const json = envOnly ? null : await readMinimalAgentConfig();
|
|
@@ -317,11 +469,14 @@ export class ConfigService {
|
|
|
317
469
|
readOnly: envOnly,
|
|
318
470
|
config: json ?? env,
|
|
319
471
|
};
|
|
320
|
-
const changed = this.snapshot.revision === 0
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
this.snapshot = {
|
|
472
|
+
const changed = this.snapshot.revision === 0 ||
|
|
473
|
+
this.snapshot.source !== next.source ||
|
|
474
|
+
this.snapshot.readOnly !== next.readOnly ||
|
|
475
|
+
JSON.stringify(this.snapshot.config) !== JSON.stringify(next.config);
|
|
476
|
+
this.snapshot = {
|
|
477
|
+
...next,
|
|
478
|
+
revision: changed ? this.snapshot.revision + 1 : this.snapshot.revision,
|
|
479
|
+
};
|
|
325
480
|
return this.getSnapshot();
|
|
326
481
|
}
|
|
327
482
|
async getSnapshot() {
|
|
@@ -336,21 +491,149 @@ export class ConfigService {
|
|
|
336
491
|
return null;
|
|
337
492
|
return resolveProvider(entry, config?.compactRatio);
|
|
338
493
|
}
|
|
494
|
+
/**
|
|
495
|
+
* 团队登录服务器的默认地址:env 优先于 config.json,跟随 minimal-desktop 的
|
|
496
|
+
* `resolve_social_server()`(`src-tauri/src/lib.rs`)已验证的同一优先级——这两个
|
|
497
|
+
* 项目共享 `KAKADEAI_SOCIAL_SERVER_URL` 这一个环境变量名,语义必须一致,不能
|
|
498
|
+
* minimal-agent 这边搞成 config 优先。
|
|
499
|
+
*
|
|
500
|
+
* ⚠️ 不能简单读 `getSnapshot().config?.teamServerUrl`:那个 snapshot 在存在
|
|
501
|
+
* config.json 时完全不看 env(`reload()` 里 `config: json ?? env`,env 只在
|
|
502
|
+
* **没有** config.json 时才整体生效),会让"config.json 存在但没配地址、同时设了
|
|
503
|
+
* env"这种常见场景里 env 被错误地忽略。这里必须独立读 `process.env`。
|
|
504
|
+
*
|
|
505
|
+
* 返回值带 `source`,供诊断和私有部署使用;正式用户不需要接触服务器地址。
|
|
506
|
+
*/
|
|
507
|
+
async resolveTeamServerUrl() {
|
|
508
|
+
const rawEnvValue = process.env.KAKADEAI_SOCIAL_SERVER_URL;
|
|
509
|
+
if (rawEnvValue !== undefined)
|
|
510
|
+
return {
|
|
511
|
+
value: rawEnvValue.trim() || null,
|
|
512
|
+
source: 'env',
|
|
513
|
+
};
|
|
514
|
+
const { config } = await this.getSnapshot();
|
|
515
|
+
const configValue = config?.teamServerUrl ?? null;
|
|
516
|
+
return configValue
|
|
517
|
+
? { value: configValue, source: 'config' }
|
|
518
|
+
: { value: 'https://kakadeai.com', source: 'default' };
|
|
519
|
+
}
|
|
339
520
|
async providerForModel(modelId) {
|
|
340
521
|
if (!modelId)
|
|
341
522
|
return this.provider();
|
|
523
|
+
const ref = modelRefFromLegacy(modelId);
|
|
524
|
+
if (ref.source === 'gateway') {
|
|
525
|
+
const resolved = await this.providerForRef(ref);
|
|
526
|
+
return resolved;
|
|
527
|
+
}
|
|
342
528
|
const { config } = await this.getSnapshot();
|
|
343
529
|
const entry = config?.models.find((m) => m.id === modelId);
|
|
344
530
|
if (!entry?.apiKey)
|
|
345
531
|
return null;
|
|
346
532
|
return resolveProvider(entry, config?.compactRatio);
|
|
347
533
|
}
|
|
534
|
+
/** Resolve a portable workflow role from fresh cross-process config. */
|
|
535
|
+
async providerForWorkflowRole(role) {
|
|
536
|
+
const { config } = await this.reload();
|
|
537
|
+
const modelId = config?.workflowModels?.[role];
|
|
538
|
+
return modelId ? this.providerForModel(modelId) : null;
|
|
539
|
+
}
|
|
540
|
+
async providerForGatewayModel(modelId) {
|
|
541
|
+
// A remembered gateway model must not make standalone mode inspect the
|
|
542
|
+
// team credential file or attempt a network request. The configured
|
|
543
|
+
// server is the explicit opt-in boundary; credentials are read only after
|
|
544
|
+
// it is present.
|
|
545
|
+
const configured = await this.resolveTeamServerUrl();
|
|
546
|
+
if (!configured.value)
|
|
547
|
+
return null;
|
|
548
|
+
const resolved = await resolveOnlineModel(modelId, configured.value ?? undefined).catch(() => null);
|
|
549
|
+
if (!resolved)
|
|
550
|
+
return null;
|
|
551
|
+
const { credentials, model } = resolved;
|
|
552
|
+
if (model.availability && model.availability.state !== 'available')
|
|
553
|
+
return null;
|
|
554
|
+
return gatewayProviderFromModel(credentials, model);
|
|
555
|
+
}
|
|
556
|
+
/** Resolve the persisted source-aware identity without making callers encode
|
|
557
|
+
* gateway selections as the legacy `online:<id>` string. */
|
|
558
|
+
async providerForRef(ref) {
|
|
559
|
+
if (!ref)
|
|
560
|
+
return this.provider();
|
|
561
|
+
return ref.source === 'gateway'
|
|
562
|
+
? this.providerForGatewayModel(ref.modelId)
|
|
563
|
+
: this.providerForModel(ref.modelId);
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Resolve a persisted model reference and retain the reason when a gateway
|
|
567
|
+
* model cannot be used. The reason is intentionally kept at the local
|
|
568
|
+
* session boundary: it is UI/selection state, not a server-side session or
|
|
569
|
+
* prompt record.
|
|
570
|
+
*/
|
|
571
|
+
async resolveModelRef(ref) {
|
|
572
|
+
if (!ref)
|
|
573
|
+
return {
|
|
574
|
+
provider: await this.providerForModel(null),
|
|
575
|
+
fallbackReason: null,
|
|
576
|
+
};
|
|
577
|
+
if (ref.source === 'local')
|
|
578
|
+
return {
|
|
579
|
+
provider: await this.providerForRef(ref),
|
|
580
|
+
fallbackReason: null,
|
|
581
|
+
};
|
|
582
|
+
const configured = await this.resolveTeamServerUrl();
|
|
583
|
+
if (!configured.value)
|
|
584
|
+
return { provider: null, fallbackReason: 'logged_out' };
|
|
585
|
+
const credentials = await loadTeamCredentials(configured.value);
|
|
586
|
+
if (!credentials)
|
|
587
|
+
return { provider: null, fallbackReason: 'logged_out' };
|
|
588
|
+
try {
|
|
589
|
+
const models = await fetchOnlineModels(credentials);
|
|
590
|
+
const model = models.find((item) => item.id === ref.modelId);
|
|
591
|
+
if (!model)
|
|
592
|
+
return { provider: null, fallbackReason: 'grant_revoked' };
|
|
593
|
+
if (model.availability?.state !== undefined &&
|
|
594
|
+
model.availability.state !== 'available')
|
|
595
|
+
return {
|
|
596
|
+
provider: null,
|
|
597
|
+
fallbackReason: gatewayFallbackReason(model),
|
|
598
|
+
};
|
|
599
|
+
return {
|
|
600
|
+
provider: gatewayProviderFromModel(credentials, model),
|
|
601
|
+
fallbackReason: null,
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
catch (error) {
|
|
605
|
+
return {
|
|
606
|
+
provider: null,
|
|
607
|
+
fallbackReason: gatewayFallbackReason(undefined, error),
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
/** Online defaults are server-owned and fetched only when team credentials
|
|
612
|
+
* exist. No standalone launch calls this path. */
|
|
613
|
+
async onlineDefaultProvider() {
|
|
614
|
+
const configured = await this.resolveTeamServerUrl();
|
|
615
|
+
if (!configured.value)
|
|
616
|
+
return null;
|
|
617
|
+
const credentials = await import('../team/auth.js')
|
|
618
|
+
.then((module) => module.loadTeamCredentials(configured.value ?? undefined))
|
|
619
|
+
.catch(() => null);
|
|
620
|
+
if (!credentials)
|
|
621
|
+
return null;
|
|
622
|
+
const models = await import('../team/auth.js')
|
|
623
|
+
.then((module) => module.fetchOnlineModels(credentials))
|
|
624
|
+
.catch(() => []);
|
|
625
|
+
const model = models.find((item) => item.isDefault &&
|
|
626
|
+
(!item.availability || item.availability.state === 'available'));
|
|
627
|
+
if (!model)
|
|
628
|
+
return null;
|
|
629
|
+
return gatewayProviderFromModel(credentials, model);
|
|
630
|
+
}
|
|
348
631
|
/** 带 apiKey 的原始列表——仅服务端内部消费(桌面端 store.ts 的 readConfig() 会脱敏成 ModelView)。 */
|
|
349
632
|
async models() {
|
|
350
633
|
return (await this.getSnapshot()).config?.models ?? [];
|
|
351
634
|
}
|
|
352
635
|
async model(id) {
|
|
353
|
-
return (await this.getSnapshot()).config?.models.find((entry) => entry.id === id) ?? null;
|
|
636
|
+
return ((await this.getSnapshot()).config?.models.find((entry) => entry.id === id) ?? null);
|
|
354
637
|
}
|
|
355
638
|
/**
|
|
356
639
|
* 保留「未启用但已配置」和「完全未配置」两种返回值的区分——advisor.ts 的两条不同报错
|
|
@@ -368,10 +651,57 @@ export class ConfigService {
|
|
|
368
651
|
const advisor = config?.advisor;
|
|
369
652
|
if (!advisor?.modelId)
|
|
370
653
|
return null;
|
|
654
|
+
const advisorRef = modelRefFromLegacy(advisor.modelId);
|
|
655
|
+
if (advisorRef.source === 'gateway') {
|
|
656
|
+
const provider = await this.providerForRef(advisorRef);
|
|
657
|
+
return provider
|
|
658
|
+
? {
|
|
659
|
+
...advisor,
|
|
660
|
+
provider,
|
|
661
|
+
supportsVision: provider.supportsVision !== false,
|
|
662
|
+
}
|
|
663
|
+
: null;
|
|
664
|
+
}
|
|
371
665
|
const entry = config.models.find((m) => m.id === advisor.modelId);
|
|
372
666
|
if (!entry?.apiKey)
|
|
373
667
|
return null;
|
|
374
|
-
return {
|
|
668
|
+
return {
|
|
669
|
+
...advisor,
|
|
670
|
+
provider: resolveProvider(entry),
|
|
671
|
+
supportsVision: entry.supportsVision !== false,
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* 同步版 advisor 可用性探测——仅用于 resolveAvailability 这类工具列表探测场景。
|
|
676
|
+
* 读当前内存快照(可能略滞后于磁盘最新值),但调用频率高、对实时性要求不高,
|
|
677
|
+
* 下一轮 LLM 请求前 configService.reload() 会刷新。
|
|
678
|
+
*
|
|
679
|
+
* 为什么不用 advisor() 的 fresh reload:
|
|
680
|
+
* resolveAvailability 是在主循环构造工具集时同步调用的,不能 await;
|
|
681
|
+
* 而且每次工具集构造都读盘的话开销太大(主循环每轮都可能构造一次)。
|
|
682
|
+
*/
|
|
683
|
+
advisorAvailabilitySync() {
|
|
684
|
+
const config = this.snapshot.config;
|
|
685
|
+
const advisor = config?.advisor;
|
|
686
|
+
if (!advisor?.modelId)
|
|
687
|
+
return { enabled: false, mode: 'auto', modelId: null, configured: false };
|
|
688
|
+
if (modelRefFromLegacy(advisor.modelId).source === 'gateway') {
|
|
689
|
+
return {
|
|
690
|
+
enabled: advisor.enabled !== false,
|
|
691
|
+
mode: advisor.mode === 'manual' ? 'manual' : 'auto',
|
|
692
|
+
modelId: advisor.modelId,
|
|
693
|
+
configured: true,
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
const entry = config?.models?.find((m) => m.id === advisor.modelId);
|
|
697
|
+
if (!entry?.apiKey)
|
|
698
|
+
return { enabled: false, mode: 'auto', modelId: null, configured: false };
|
|
699
|
+
return {
|
|
700
|
+
enabled: advisor.enabled !== false,
|
|
701
|
+
mode: advisor.mode === 'manual' ? 'manual' : 'auto',
|
|
702
|
+
modelId: advisor.modelId,
|
|
703
|
+
configured: true,
|
|
704
|
+
};
|
|
375
705
|
}
|
|
376
706
|
async subagents() {
|
|
377
707
|
return (await this.reload()).config?.subagents ?? DEFAULT_SUBAGENTS_CONFIG;
|
|
@@ -380,7 +710,7 @@ export class ConfigService {
|
|
|
380
710
|
return (await this.reload()).config?.browser ?? DEFAULT_BROWSER_CONFIG;
|
|
381
711
|
}
|
|
382
712
|
async computerUse() {
|
|
383
|
-
return (await this.reload()).config?.computerUse ?? DEFAULT_COMPUTER_USE_CONFIG;
|
|
713
|
+
return ((await this.reload()).config?.computerUse ?? DEFAULT_COMPUTER_USE_CONFIG);
|
|
384
714
|
}
|
|
385
715
|
async tool(key) {
|
|
386
716
|
return (await this.reload()).config?.tools[key];
|
|
@@ -388,10 +718,22 @@ export class ConfigService {
|
|
|
388
718
|
async toolStatus() {
|
|
389
719
|
const tools = (await this.reload()).config?.tools ?? {};
|
|
390
720
|
return {
|
|
391
|
-
webSearch: {
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
721
|
+
webSearch: {
|
|
722
|
+
state: tools.webSearch ? 'configured' : 'unconfigured',
|
|
723
|
+
configured: !!tools.webSearch,
|
|
724
|
+
},
|
|
725
|
+
imageGeneration: {
|
|
726
|
+
state: tools.imageGeneration ? 'configured' : 'unconfigured',
|
|
727
|
+
configured: !!tools.imageGeneration,
|
|
728
|
+
},
|
|
729
|
+
openRouter: {
|
|
730
|
+
state: tools.openRouter ? 'configured' : 'unconfigured',
|
|
731
|
+
configured: !!tools.openRouter,
|
|
732
|
+
},
|
|
733
|
+
textToSpeech: {
|
|
734
|
+
state: tools.textToSpeech ? 'configured' : 'unconfigured',
|
|
735
|
+
configured: !!tools.textToSpeech,
|
|
736
|
+
},
|
|
395
737
|
};
|
|
396
738
|
}
|
|
397
739
|
async savePatch(patch) {
|
|
@@ -414,33 +756,55 @@ export class ConfigService {
|
|
|
414
756
|
await updateMinimalAgentConfig((latest) => {
|
|
415
757
|
let active = latest ?? current.config;
|
|
416
758
|
if (patch.subagents)
|
|
417
|
-
active = {
|
|
759
|
+
active = {
|
|
760
|
+
version: 4,
|
|
761
|
+
...applyConfigPatch(active, { subagents: patch.subagents }),
|
|
762
|
+
savedAt: active.savedAt,
|
|
763
|
+
};
|
|
418
764
|
if (patch.computerUse)
|
|
419
|
-
active = {
|
|
765
|
+
active = {
|
|
766
|
+
version: 4,
|
|
767
|
+
...applyConfigPatch(active, { computerUse: patch.computerUse }),
|
|
768
|
+
savedAt: active.savedAt,
|
|
769
|
+
};
|
|
420
770
|
const drafts = structuredClone(active.drafts ?? {});
|
|
421
771
|
for (const key of Object.keys(patch.tools ?? {})) {
|
|
422
772
|
const rawPiece = patch.tools[key];
|
|
423
773
|
if (!rawPiece)
|
|
424
774
|
continue;
|
|
425
|
-
const previous =
|
|
775
|
+
const previous = drafts.tools?.[key];
|
|
426
776
|
const merged = mergeRecord(previous, rawPiece);
|
|
427
777
|
try {
|
|
428
|
-
active = {
|
|
429
|
-
|
|
778
|
+
active = {
|
|
779
|
+
version: 4,
|
|
780
|
+
...applyConfigPatch(active, {
|
|
781
|
+
tools: { [key]: merged },
|
|
782
|
+
}),
|
|
783
|
+
savedAt: active.savedAt,
|
|
784
|
+
};
|
|
785
|
+
drafts.tools = omitKey(drafts.tools, key);
|
|
430
786
|
}
|
|
431
787
|
catch {
|
|
432
788
|
state = 'draft';
|
|
433
789
|
draftFields.push(key);
|
|
434
|
-
|
|
790
|
+
const toolDrafts = drafts.tools ?? {};
|
|
791
|
+
toolDrafts[key] = merged;
|
|
792
|
+
drafts.tools = toolDrafts;
|
|
435
793
|
}
|
|
436
794
|
}
|
|
437
795
|
if (!hasEntries(drafts.tools))
|
|
438
|
-
|
|
796
|
+
drafts.tools = undefined;
|
|
439
797
|
return {
|
|
440
|
-
models: active.models,
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
798
|
+
models: active.models,
|
|
799
|
+
baseModelId: active.baseModelId,
|
|
800
|
+
...(active.compactRatio !== undefined
|
|
801
|
+
? { compactRatio: active.compactRatio }
|
|
802
|
+
: {}),
|
|
803
|
+
advisor: active.advisor,
|
|
804
|
+
subagents: active.subagents,
|
|
805
|
+
browser: active.browser,
|
|
806
|
+
computerUse: active.computerUse,
|
|
807
|
+
tools: active.tools,
|
|
444
808
|
...(hasEntries(drafts) ? { drafts } : {}),
|
|
445
809
|
};
|
|
446
810
|
});
|
|
@@ -449,14 +813,19 @@ export class ConfigService {
|
|
|
449
813
|
}
|
|
450
814
|
export const configService = new ConfigService();
|
|
451
815
|
export const SENSITIVE_ENV_KEYS = new Set([
|
|
452
|
-
'MINIMAL_AGENT_API_KEY',
|
|
453
|
-
'
|
|
816
|
+
'MINIMAL_AGENT_API_KEY',
|
|
817
|
+
'TAVILY_API_KEY',
|
|
818
|
+
'OPENAI_IMAGE_API_KEY',
|
|
819
|
+
'OPENROUTER_API_KEY',
|
|
820
|
+
'MINIMAX_API_KEY',
|
|
821
|
+
'MINIMAX_GROUP_ID',
|
|
454
822
|
]);
|
|
455
823
|
/** Child processes inherit normal runtime variables, never model or tool credentials. */
|
|
456
824
|
export function sanitizeCredentialEnv(source = process.env) {
|
|
457
|
-
|
|
458
|
-
for (const key of SENSITIVE_ENV_KEYS)
|
|
459
|
-
|
|
825
|
+
let env = { ...source };
|
|
826
|
+
for (const key of SENSITIVE_ENV_KEYS) {
|
|
827
|
+
env = omitKey(env, key) ?? {};
|
|
828
|
+
}
|
|
460
829
|
return env;
|
|
461
830
|
}
|
|
462
831
|
export async function trustedToolEnv(kind, service = configService) {
|
|
@@ -482,7 +851,7 @@ export async function trustedToolEnv(kind, service = configService) {
|
|
|
482
851
|
if (cfg.protocol && cfg.protocol !== 'auto')
|
|
483
852
|
env.OPENAI_IMAGE_PROTOCOL = cfg.protocol;
|
|
484
853
|
else
|
|
485
|
-
|
|
854
|
+
env.OPENAI_IMAGE_PROTOCOL = undefined;
|
|
486
855
|
}
|
|
487
856
|
}
|
|
488
857
|
else if (kind === 'openRouter') {
|