minimal-agent 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -5
- package/package.json +60 -4
- package/plugins/computer_use/.claude-plugin/plugin.json +1 -1
- package/plugins/cron-runner/src/commands.js +4 -4
- package/plugins/cron-runner/src/commands.ts +4 -4
- package/plugins/workflow-runner/.claude-plugin/plugin.json +2 -2
- package/plugins/workflow-runner/commands/workflow.md +57 -90
- package/plugins/workflow-runner/commands/workflows.md +4 -4
- package/plugins/workflow-runner/plugin.js +24 -13
- package/plugins/workflow-runner/plugin.ts +28 -13
- package/plugins/workflow-runner/src/discovery.js +160 -0
- package/plugins/workflow-runner/src/discovery.ts +194 -0
- package/plugins/workflow-runner/src/goalAnchor.js +53 -0
- package/plugins/workflow-runner/src/goalAnchor.ts +59 -0
- package/plugins/workflow-runner/src/index.js +197 -206
- package/plugins/workflow-runner/src/index.ts +248 -249
- package/plugins/workflow-runner/src/inputCoercion.js +40 -0
- package/plugins/workflow-runner/src/inputCoercion.ts +43 -0
- package/plugins/workflow-runner/src/journal.js +224 -0
- package/plugins/workflow-runner/src/journal.ts +274 -0
- package/plugins/workflow-runner/src/jsonSchema.js +132 -0
- package/plugins/workflow-runner/src/jsonSchema.ts +162 -0
- package/plugins/workflow-runner/src/moduleResolution.js +64 -0
- package/plugins/workflow-runner/src/moduleResolution.ts +71 -0
- package/plugins/workflow-runner/src/resourceInputs.js +220 -0
- package/plugins/workflow-runner/src/resourceInputs.ts +300 -0
- package/plugins/workflow-runner/src/runner.js +400 -489
- package/plugins/workflow-runner/src/runner.ts +488 -560
- package/plugins/workflow-runner/src/runtime/config.js +46 -0
- package/plugins/workflow-runner/src/runtime/config.ts +69 -0
- package/plugins/workflow-runner/src/runtime/context.js +1304 -0
- package/plugins/workflow-runner/src/runtime/context.ts +1786 -0
- package/plugins/workflow-runner/src/runtime/exec.js +34 -0
- package/plugins/workflow-runner/src/runtime/exec.ts +53 -0
- package/plugins/workflow-runner/src/runtime/flow.js +8 -0
- package/plugins/workflow-runner/src/runtime/flow.ts +12 -0
- package/plugins/workflow-runner/src/runtime/fs.js +27 -0
- package/plugins/workflow-runner/src/runtime/fs.ts +41 -0
- package/plugins/workflow-runner/src/runtime/model.js +6 -0
- package/plugins/workflow-runner/src/runtime/model.ts +8 -0
- package/plugins/workflow-runner/src/runtime/output.js +7 -0
- package/plugins/workflow-runner/src/runtime/output.ts +21 -0
- package/plugins/workflow-runner/src/runtime/scheduler.js +141 -0
- package/plugins/workflow-runner/src/runtime/scheduler.ts +166 -0
- package/plugins/workflow-runner/src/runtime/state.js +16 -0
- package/plugins/workflow-runner/src/runtime/state.ts +19 -0
- package/plugins/workflow-runner/src/runtime/tools.js +3 -0
- package/plugins/workflow-runner/src/runtime/tools.ts +6 -0
- package/plugins/workflow-runner/src/sandbox.js +141 -0
- package/plugins/workflow-runner/src/sandbox.ts +182 -0
- package/plugins/workflow-runner/src/scriptGuard.d.mts +38 -0
- package/plugins/workflow-runner/src/scriptGuard.mjs +449 -0
- package/plugins/workflow-runner/src/taskIdentity.js +151 -307
- package/plugins/workflow-runner/src/taskIdentity.ts +207 -355
- package/plugins/workflow-runner/src/toolRuntime.js +29 -8
- package/plugins/workflow-runner/src/toolRuntime.ts +36 -11
- package/plugins/workflow-runner/src/types.js +7 -211
- package/plugins/workflow-runner/src/types.ts +154 -623
- package/plugins/workflow-runner/src/util.js +47 -0
- package/plugins/workflow-runner/src/util.ts +51 -0
- package/plugins/workflow-runner/src/workflowContext.js +20 -0
- package/plugins/workflow-runner/src/workflowContext.ts +58 -0
- package/plugins/workflow-runner/src/workflowDependencies.js +36 -0
- package/plugins/workflow-runner/src/workflowDependencies.ts +59 -0
- package/plugins/workflow-runner/src/workflowFingerprint.js +118 -0
- package/plugins/workflow-runner/src/workflowFingerprint.ts +122 -0
- package/plugins/workflow-runner/src/workflowState.js +474 -802
- package/plugins/workflow-runner/src/workflowState.ts +575 -970
- package/plugins/workflow-runner/test/api.test.ts +223 -0
- package/plugins/workflow-runner/test/apiCapabilities.test.ts +614 -0
- package/plugins/workflow-runner/test/apiConcurrencyGate.test.ts +104 -0
- package/plugins/workflow-runner/test/apiEcho.test.ts +210 -0
- package/plugins/workflow-runner/test/apiReadText.test.ts +178 -0
- package/plugins/workflow-runner/test/apiResourceLedger.test.ts +184 -0
- package/plugins/workflow-runner/test/childWorkflow.test.ts +304 -0
- package/plugins/workflow-runner/test/discovery.test.ts +234 -0
- package/plugins/workflow-runner/test/goalAnchor.test.ts +106 -0
- package/plugins/workflow-runner/test/goalController.test.ts +317 -0
- package/plugins/workflow-runner/test/journalLanes.test.ts +198 -0
- package/plugins/workflow-runner/test/listResources.test.ts +106 -0
- package/plugins/workflow-runner/test/resourceInputs.test.ts +294 -0
- package/plugins/workflow-runner/test/sandbox.test.ts +126 -0
- package/plugins/workflow-runner/test/scheduler.test.ts +70 -0
- package/plugins/workflow-runner/test/scriptGuard.test.ts +276 -0
- package/plugins/workflow-runner/test/skillDocSync.test.ts +78 -0
- package/plugins/workflow-runner/test/taskIdentity.test.ts +288 -179
- package/plugins/workflow-runner/test/workflowFingerprint.test.ts +106 -0
- package/plugins/workflow-runner/test/workflowState.test.ts +429 -0
- package/skills/pptx/examples/assets/cover-bg.svg +23 -0
- package/skills/pptx/examples/assets/icon-spark.svg +5 -0
- package/skills/ui-design/SKILL.md +5 -2
- package/skills/ui-design/references/layout-composition.md +1 -1
- package/skills/workflow-creator/SKILL.md +344 -0
- package/skills/workflow-creator/assets/template/workflow.mjs +48 -0
- package/skills/workflow-creator/references/api.md +216 -0
- package/skills/workflow-creator/references/migration.md +103 -0
- package/skills/workflow-creator/references/patterns.md +779 -0
- package/skills/workflow-creator/scripts/list-resources.mjs +205 -0
- package/skills/workflow-creator/scripts/scaffold.mjs +148 -0
- package/skills/workflow-creator/scripts/validate.mjs +275 -0
- package/skills/workflow-creator/scripts/workflow-creator.test.mjs +82 -0
- package/src/advisor/advisorCoordinator.js +503 -0
- package/src/advisor/advisorCoordinator.ts +657 -0
- package/src/cli/configMenu.tsx +0 -1
- package/src/cli/print.js +27 -6
- package/src/cli/print.ts +48 -4
- package/src/cli/streamJson.js +5 -6
- package/src/cli/streamJson.ts +8 -4
- package/src/cli/wizards/advisorWizard.js +4 -2
- package/src/cli/wizards/advisorWizard.tsx +8 -2
- package/src/cli/wizards/contextAdvisorWizard.js +5 -4
- package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
- package/src/collaboration/taskFlow.js +115 -0
- package/src/collaboration/taskFlow.ts +169 -0
- package/src/config/configDefaults.js +41 -1
- package/src/config/configDefaults.ts +43 -1
- package/src/config/configDiagnostics.ts +2 -2
- package/src/config/configFile.js +40 -9
- package/src/config/configFile.ts +60 -11
- package/src/config/configService.js +419 -74
- package/src/config/configService.ts +703 -145
- package/src/config/numericLimits.js +22 -0
- package/src/config/numericLimits.ts +24 -0
- package/src/config.js +1 -0
- package/src/config.ts +3 -2
- package/src/context/budgetPlan.js +1 -1
- package/src/context/budgetPlan.ts +1 -1
- package/src/context/compact.js +7 -2
- package/src/context/compact.ts +9 -2
- package/src/context/microCompactLite.js +212 -13
- package/src/context/microCompactLite.ts +261 -12
- package/src/context/sessionRegistry.js +8 -1
- package/src/context/sessionRegistry.ts +18 -5
- package/src/context/toolResultArchive.js +72 -0
- package/src/context/toolResultArchive.ts +95 -0
- package/src/goal/errors.js +8 -0
- package/src/goal/errors.ts +18 -0
- package/src/goal/goalRuntime.js +344 -0
- package/src/goal/goalRuntime.ts +466 -0
- package/src/goal/goalStore.js +200 -0
- package/src/goal/goalStore.ts +219 -0
- package/src/goal/index.js +4 -0
- package/src/goal/index.ts +4 -0
- package/src/goal/statusMapping.js +71 -0
- package/src/goal/statusMapping.ts +95 -0
- package/src/goal/types.js +7 -0
- package/src/goal/types.ts +179 -0
- package/src/goal/workflowController.js +306 -0
- package/src/goal/workflowController.ts +360 -0
- package/src/harness/evidenceLedger.js +2 -0
- package/src/harness/evidenceLedger.ts +1 -0
- package/src/harness/stallGuard.js +9 -3
- package/src/harness/stallGuard.ts +7 -3
- package/src/images/imageResolver.js +161 -0
- package/src/images/imageResolver.ts +189 -0
- package/src/infra/verification.js +34 -5
- package/src/infra/verification.ts +39 -4
- package/src/llm/client.js +79 -21
- package/src/llm/client.ts +182 -35
- package/src/llm/gatewayClient.js +201 -0
- package/src/llm/gatewayClient.ts +299 -0
- package/src/llm/messageProvenance.js +46 -0
- package/src/llm/messageProvenance.ts +58 -0
- package/src/llm/modelProvider.js +1 -0
- package/src/llm/modelProvider.ts +22 -0
- package/src/llm/providers/anthropicFormat.js +108 -1
- package/src/llm/providers/anthropicFormat.ts +115 -4
- package/src/llm/providers/openaiFormat.js +9 -0
- package/src/llm/providers/openaiFormat.ts +12 -3
- package/src/loop.js +319 -54
- package/src/loop.ts +373 -57
- package/src/main.js +4 -1
- package/src/main.tsx +4 -1
- package/src/managedExecution/index.js +2 -0
- package/src/managedExecution/index.ts +2 -0
- package/src/managedExecution/registry.js +15 -0
- package/src/managedExecution/registry.ts +20 -0
- package/src/managedExecution/types.js +1 -0
- package/src/managedExecution/types.ts +86 -0
- package/src/modelRef.js +9 -0
- package/src/modelRef.ts +31 -0
- package/src/multimodal.js +14 -28
- package/src/multimodal.ts +17 -33
- package/src/net/lanDiscovery.js +65 -0
- package/src/net/lanDiscovery.ts +82 -0
- package/src/plugin-sdk.js +28 -3
- package/src/plugin-sdk.ts +39 -6
- package/src/plugins/pluginApi.ts +16 -1
- package/src/plugins/pluginLoader.js +4 -0
- package/src/plugins/pluginLoader.ts +6 -0
- package/src/plugins/pluginRunner.js +139 -7
- package/src/plugins/pluginRunner.ts +173 -9
- package/src/plugins/slashFallback.js +113 -0
- package/src/plugins/slashFallback.ts +137 -0
- package/src/prompts/policyRegistry.js +12 -32
- package/src/prompts/policyRegistry.ts +15 -32
- package/src/prompts/promptAssembly.js +103 -12
- package/src/prompts/promptAssembly.ts +114 -12
- package/src/prompts/skillList.js +21 -3
- package/src/prompts/skillList.ts +27 -2
- package/src/prompts/stableSystemPrompt.js +18 -0
- package/src/prompts/stableSystemPrompt.ts +33 -0
- package/src/runtime/agentRuntimeContext.js +8 -2
- package/src/runtime/agentRuntimeContext.ts +17 -4
- package/src/session/runAgentTurn.js +78 -12
- package/src/session/runAgentTurn.ts +105 -23
- package/src/session/runTurn.js +10 -9
- package/src/session/runTurn.ts +17 -8
- package/src/session/sessionState.ts +2 -0
- package/src/team/auth.js +186 -0
- package/src/team/auth.ts +298 -0
- package/src/team/cli.js +105 -0
- package/src/team/cli.ts +122 -0
- package/src/team/onlineToolContract.js +64 -0
- package/src/team/onlineToolContract.ts +109 -0
- package/src/team/toolPolicy.js +36 -0
- package/src/team/toolPolicy.ts +75 -0
- package/src/tools/advisor/advisor.js +90 -46
- package/src/tools/advisor/advisor.ts +100 -47
- package/src/tools/advisor/advisorDecision.js +71 -0
- package/src/tools/advisor/advisorDecision.ts +85 -0
- package/src/tools/agent/agent.js +18 -5
- package/src/tools/agent/agent.ts +21 -7
- package/src/tools/agent/agentControl.js +246 -0
- package/src/tools/agent/agentControl.ts +284 -0
- package/src/tools/agent/agentTaskService.js +40 -1
- package/src/tools/agent/agentTaskService.ts +44 -1
- package/src/tools/agent/agentTypes.js +14 -2
- package/src/tools/agent/agentTypes.ts +15 -2
- package/src/tools/applypatch/applyPatch.js +362 -0
- package/src/tools/applypatch/applyPatch.ts +428 -0
- package/src/tools/bash/bash.js +22 -15
- package/src/tools/bash/bash.ts +23 -17
- package/src/tools/capabilities.js +10 -5
- package/src/tools/capabilities.ts +10 -5
- package/src/tools/computeruse/computerIntent.js +32 -0
- package/src/tools/computeruse/computerIntent.ts +46 -0
- package/src/tools/computeruse/telemetryLog.js +12 -0
- package/src/tools/computeruse/telemetryLog.ts +16 -0
- package/src/tools/computeruse/vision/telemetry.js +1 -0
- package/src/tools/computeruse/vision/telemetry.ts +1 -0
- package/src/tools/effectiveToolSet.js +4 -0
- package/src/tools/effectiveToolSet.ts +4 -0
- package/src/tools/index.js +21 -2
- package/src/tools/index.ts +33 -2
- package/src/tools/presentresult/presentresult.js +6 -15
- package/src/tools/presentresult/presentresult.ts +6 -15
- package/src/tools/read/read.js +62 -9
- package/src/tools/read/read.ts +63 -9
- package/src/tools/shared/fileUtils.js +1 -2
- package/src/tools/shared/fileUtils.ts +1 -2
- package/src/tools/shared/toolOutputStore.js +23 -1
- package/src/tools/shared/toolOutputStore.ts +22 -1
- package/src/tools/skill/skill.js +9 -3
- package/src/tools/skill/skill.ts +8 -4
- package/src/tools/toolPromptGuides.js +117 -0
- package/src/tools/toolPromptGuides.ts +137 -0
- package/src/tools/webbrowser/agentBrowserPath.js +19 -9
- package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
- package/src/tools/webbrowser/browser.js +27 -11
- package/src/tools/webbrowser/browser.ts +68 -24
- package/src/tools/webbrowser/browserAutomation.js +329 -0
- package/src/tools/webbrowser/browserAutomation.ts +467 -0
- package/src/tools/webbrowser/browserAxState.js +97 -0
- package/src/tools/webbrowser/browserAxState.ts +142 -0
- package/src/tools/webbrowser/browserBatch.js +1578 -0
- package/src/tools/webbrowser/browserBatch.ts +2382 -0
- package/src/tools/webbrowser/browserCdp.js +208 -0
- package/src/tools/webbrowser/browserCdp.ts +255 -0
- package/src/tools/webbrowser/browserConditions.js +24 -0
- package/src/tools/webbrowser/browserConditions.ts +45 -0
- package/src/tools/webbrowser/browserContent.js +281 -0
- package/src/tools/webbrowser/browserContent.ts +438 -0
- package/src/tools/webbrowser/browserControl.js +131 -34
- package/src/tools/webbrowser/browserControl.ts +210 -56
- package/src/tools/webbrowser/browserDaemon.js +22 -14
- package/src/tools/webbrowser/browserDaemon.ts +54 -21
- package/src/tools/webbrowser/browserFrames.js +47 -0
- package/src/tools/webbrowser/browserFrames.ts +54 -0
- package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
- package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
- package/src/tools/webbrowser/browserLocator.js +140 -0
- package/src/tools/webbrowser/browserLocator.ts +194 -0
- package/src/tools/webbrowser/browserOutcome.js +10 -17
- package/src/tools/webbrowser/browserOutcome.ts +48 -31
- package/src/tools/webbrowser/browserRecovery.js +58 -0
- package/src/tools/webbrowser/browserRecovery.ts +83 -0
- package/src/tools/webbrowser/browserRunRegistry.js +35 -3
- package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
- package/src/tools/webbrowser/browserService.js +28 -2
- package/src/tools/webbrowser/browserService.ts +49 -9
- package/src/tools/webbrowser/browserStream.js +132 -33
- package/src/tools/webbrowser/browserStream.ts +224 -50
- package/src/tools/webbrowser/browserTabs.js +48 -15
- package/src/tools/webbrowser/browserTabs.ts +178 -96
- package/src/tools/webbrowser/webbrowser.js +679 -144
- package/src/tools/webbrowser/webbrowser.ts +975 -236
- package/src/tools/webfetch/preapproved.js +0 -2
- package/src/tools/webfetch/preapproved.ts +0 -2
- package/src/tools/websearch/websearch.js +129 -8
- package/src/tools/websearch/websearch.ts +138 -6
- package/src/types.ts +440 -38
- package/src/ui/App.js +377 -58
- package/src/ui/App.tsx +576 -111
- package/src/ui/LiveArea.js +14 -8
- package/src/ui/LiveArea.tsx +14 -10
- package/src/ui/MessageList.js +63 -20
- package/src/ui/MessageList.tsx +101 -16
- package/src/ui/ModelPicker.js +7 -4
- package/src/ui/ModelPicker.tsx +55 -8
- package/src/ui/hooks/useChat.js +152 -163
- package/src/ui/hooks/useChat.ts +396 -334
- package/src/ui/loginCommand.js +56 -0
- package/src/ui/loginCommand.ts +63 -0
- package/src/ui/toolProgress.js +41 -0
- package/src/ui/toolProgress.ts +44 -0
- package/src/web/browserBridge.js +20 -2
- package/src/web/browserBridge.ts +20 -2
- package/src/web/protocol.ts +1897 -194
- package/workflows/adaptive-research/workflow.mjs +86 -0
- package/workflows/e2e-capabilities/workflow.mjs +102 -0
- package/workflows/e2e-llm/workflow.mjs +52 -0
- package/workflows/e2e-smoke/workflow.mjs +59 -0
- package/workflows/e2e-vision-schema/README.md +48 -0
- package/workflows/e2e-vision-schema/workflow.mjs +149 -0
- package/workflows/e2e-write-greet/workflow.mjs +37 -0
- package/workflows/file-census/README.md +14 -0
- package/workflows/file-census/scripts/.gitkeep +2 -0
- package/workflows/file-census/workflow.mjs +110 -0
- package/workflows/goal/README.md +166 -0
- package/workflows/goal/prompts/audit.md +57 -0
- package/workflows/goal/prompts/contract.md +56 -0
- package/workflows/goal/prompts/iterate.md +37 -0
- package/workflows/goal/workflow.mjs +501 -0
- package/workflows/illustrate/README.md +90 -0
- package/workflows/illustrate/assets/engines.json +20 -0
- package/workflows/illustrate/assets/extract-baidu.js +21 -0
- package/workflows/illustrate/assets/extract-bing.js +33 -0
- package/workflows/illustrate/assets/extract-google.js +31 -0
- package/workflows/illustrate/workflow.mjs +301 -0
- package/workflows/plan/workflow.mjs +389 -0
- package/workflows/question-crops/README.md +35 -0
- package/workflows/question-crops/prompts/inventory.md +23 -0
- package/workflows/question-crops/scripts/image-ops.mjs +305 -0
- package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
- package/workflows/question-crops/workflow.mjs +172 -0
- package/workflows/ralph-loop/workflow.mjs +162 -0
- package/workflows/research/README.md +74 -0
- package/workflows/research/prompts/s0-goal.md +43 -0
- package/workflows/research/prompts/s1-early-exit.md +22 -0
- package/workflows/research/prompts/s1-map.md +58 -0
- package/workflows/research/prompts/s2-options.md +53 -0
- package/workflows/research/prompts/s3-deep-dive.md +56 -0
- package/workflows/research/prompts/s4-verify.md +74 -0
- package/workflows/research/prompts/s5-synthesis.md +81 -0
- package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
- package/workflows/research/prompts/s6-package.md +32 -0
- package/workflows/research/scripts/build-report.mjs +98 -0
- package/workflows/research/workflow.mjs +288 -0
- package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
- package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
- package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
- package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
- package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
- package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
- package/workflows/wechat-reading-shots/workflow.mjs +266 -0
- package/workflows/wrong-question-docx/README.md +55 -0
- package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
- package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
- package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
- package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
- package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
- package/workflows/wrong-question-docx/workflow.mjs +485 -0
- package/plugins/workflow-runner/src/agentCommon.js +0 -354
- package/plugins/workflow-runner/src/agentCommon.ts +0 -435
- package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
- package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
- package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
- package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
- package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
- package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
- package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
- package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
- package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
- package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
- package/plugins/workflow-runner/src/dslManifest.js +0 -72
- package/plugins/workflow-runner/src/dslManifest.ts +0 -127
- package/plugins/workflow-runner/src/expressions.js +0 -639
- package/plugins/workflow-runner/src/expressions.ts +0 -640
- package/plugins/workflow-runner/src/loader.js +0 -573
- package/plugins/workflow-runner/src/loader.ts +0 -721
- package/plugins/workflow-runner/src/multimodal.js +0 -38
- package/plugins/workflow-runner/src/multimodal.ts +0 -64
- package/plugins/workflow-runner/src/recovery.js +0 -126
- package/plugins/workflow-runner/src/recovery.ts +0 -156
- package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
- package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
- package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -42
- package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -52
- package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
- package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
- package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
- package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
- package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
- package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
- package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
- package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
- package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -227
- package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -274
- package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -61
- package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -72
- package/plugins/workflow-runner/src/stepPipeline.js +0 -277
- package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
- package/plugins/workflow-runner/test/agent.test.ts +0 -587
- package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
- package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
- package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
- package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -167
- package/plugins/workflow-runner/test/context-files.test.ts +0 -320
- package/plugins/workflow-runner/test/e2e.test.ts +0 -370
- package/plugins/workflow-runner/test/e2eNewLayout.test.ts +0 -314
- package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -234
- package/plugins/workflow-runner/test/expressions.test.ts +0 -439
- package/plugins/workflow-runner/test/foundation.test.ts +0 -126
- package/plugins/workflow-runner/test/graceful.test.ts +0 -139
- package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
- package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
- package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
- package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
- package/plugins/workflow-runner/test/loader.test.ts +0 -617
- package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
- package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
- package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
- package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -106
- package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
- package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
- package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -221
- package/plugins/workflow-runner/test/recovery.test.ts +0 -265
- package/plugins/workflow-runner/test/research.load.test.ts +0 -328
- package/plugins/workflow-runner/test/runner.test.ts +0 -911
- package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -436
- package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
- package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -198
- package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
- package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -354
- package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -324
- package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +0 -221
- package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +0 -29
- package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +0 -168
- package/plugins/workflow-runner/test/webppt.load.test.ts +0 -250
- package/plugins/workflow-runner/test/word.load.test.ts +0 -208
- package/plugins/workflow-runner/test/workflows.smoke.test.ts +0 -76
- package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +0 -207
- package/src/advisorState.js +0 -22
- package/src/cli/configWizard.js +0 -293
- package/src/tools/toolProgressBridge.js +0 -48
- package/workflows/adaptive-research.yaml +0 -50
- package/workflows/book-review-short.yaml +0 -125
- package/workflows/e2e-write-greet.yaml +0 -31
- package/workflows/illustrate.yaml +0 -227
- package/workflows/plan.yaml +0 -470
- package/workflows/ppt.yaml +0 -1670
- package/workflows/ralph-loop.yaml +0 -201
- package/workflows/research.yaml +0 -873
- package/workflows/schema.json +0 -176
- package/workflows/webppt.yaml +0 -496
- package/workflows/wechat-reading-shots.yaml +0 -315
- package/workflows/word.yaml +0 -720
- package/workflows/youtube-shorts.yaml +0 -202
- /package/workflows/{research.md → research/DESIGN.md} +0 -0
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { readFile, realpath, rm } from 'node:fs/promises';
|
|
3
|
+
import { dirname, isAbsolute, relative, resolve, sep } from 'node:path';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
|
|
6
|
+
import { getWorkingDir } from '../../bootstrap/workingDir.js';
|
|
7
|
+
import type {
|
|
8
|
+
FileActivityMetadata,
|
|
9
|
+
Tool,
|
|
10
|
+
ToolCallContext,
|
|
11
|
+
ToolResult,
|
|
12
|
+
} from '../../types.js';
|
|
13
|
+
import { buildPatchSummary } from '../shared/diffSummary.js';
|
|
14
|
+
import { fileActivityMetadata } from '../shared/fileActivity.js';
|
|
15
|
+
import { emitFileMutation } from '../shared/fileMutationBus.js';
|
|
16
|
+
import { hashFileBytes, recordRead } from '../shared/fileState.js';
|
|
17
|
+
import {
|
|
18
|
+
type FileBomEncoding,
|
|
19
|
+
applyLineEnding,
|
|
20
|
+
atomicWriteFile,
|
|
21
|
+
encodeTextFile,
|
|
22
|
+
hasBinaryExtension,
|
|
23
|
+
readTextFile,
|
|
24
|
+
} from '../shared/fileUtils.js';
|
|
25
|
+
import { DEFAULT_MAX_RESULT_SIZE_CHARS } from '../types.js';
|
|
26
|
+
|
|
27
|
+
interface PatchHunk {
|
|
28
|
+
header: string;
|
|
29
|
+
oldStart?: number;
|
|
30
|
+
lines: Array<{ kind: 'context' | 'add' | 'delete'; text: string }>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type PatchOperation =
|
|
34
|
+
| { kind: 'add'; path: string; content: string }
|
|
35
|
+
| { kind: 'delete'; path: string }
|
|
36
|
+
| { kind: 'update'; path: string; moveTo?: string; hunks: PatchHunk[] };
|
|
37
|
+
|
|
38
|
+
const schema = z.object({
|
|
39
|
+
patch: z.string().min(1).max(10_000_000),
|
|
40
|
+
});
|
|
41
|
+
type ApplyPatchInput = z.infer<typeof schema>;
|
|
42
|
+
|
|
43
|
+
function fail(message: string): never {
|
|
44
|
+
throw new Error(message);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Parse the Codex apply_patch envelope without invoking a platform patch binary. */
|
|
48
|
+
export function parseApplyPatch(input: string): PatchOperation[] {
|
|
49
|
+
const lines = input.replaceAll('\r\n', '\n').split('\n');
|
|
50
|
+
if (lines[0] !== '*** Begin Patch') fail('补丁必须以 *** Begin Patch 开始');
|
|
51
|
+
const operations: PatchOperation[] = [];
|
|
52
|
+
let index = 1;
|
|
53
|
+
while (index < lines.length) {
|
|
54
|
+
const line = lines[index]!;
|
|
55
|
+
if (line === '*** End Patch') {
|
|
56
|
+
if (lines.slice(index + 1).some((item) => item.trim()))
|
|
57
|
+
fail('*** End Patch 后不能再有内容');
|
|
58
|
+
if (!operations.length) fail('补丁中没有文件操作');
|
|
59
|
+
return operations;
|
|
60
|
+
}
|
|
61
|
+
if (line.startsWith('*** Add File: ')) {
|
|
62
|
+
const path = line.slice('*** Add File: '.length);
|
|
63
|
+
index += 1;
|
|
64
|
+
const added: string[] = [];
|
|
65
|
+
while (index < lines.length && !lines[index]!.startsWith('*** ')) {
|
|
66
|
+
const contentLine = lines[index]!;
|
|
67
|
+
if (!contentLine.startsWith('+'))
|
|
68
|
+
fail(`Add File ${path} 的内容行必须以 + 开头(第 ${index + 1} 行)`);
|
|
69
|
+
added.push(contentLine.slice(1));
|
|
70
|
+
index += 1;
|
|
71
|
+
}
|
|
72
|
+
operations.push({
|
|
73
|
+
kind: 'add',
|
|
74
|
+
path,
|
|
75
|
+
content: added.length ? `${added.join('\n')}\n` : '',
|
|
76
|
+
});
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (line.startsWith('*** Delete File: ')) {
|
|
80
|
+
operations.push({
|
|
81
|
+
kind: 'delete',
|
|
82
|
+
path: line.slice('*** Delete File: '.length),
|
|
83
|
+
});
|
|
84
|
+
index += 1;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (line.startsWith('*** Update File: ')) {
|
|
88
|
+
const path = line.slice('*** Update File: '.length);
|
|
89
|
+
index += 1;
|
|
90
|
+
let moveTo: string | undefined;
|
|
91
|
+
if (lines[index]?.startsWith('*** Move to: ')) {
|
|
92
|
+
moveTo = lines[index]!.slice('*** Move to: '.length);
|
|
93
|
+
index += 1;
|
|
94
|
+
}
|
|
95
|
+
const hunks: PatchHunk[] = [];
|
|
96
|
+
while (index < lines.length && !lines[index]!.startsWith('*** ')) {
|
|
97
|
+
const headerLine = lines[index]!;
|
|
98
|
+
if (!headerLine.startsWith('@@'))
|
|
99
|
+
fail(`Update File ${path} 缺少 @@ hunk 头(第 ${index + 1} 行)`);
|
|
100
|
+
const match = /^@@(?: -(\d+)(?:,\d+)? \+\d+(?:,\d+)?)? @@\s*(.*)$/.exec(
|
|
101
|
+
headerLine,
|
|
102
|
+
);
|
|
103
|
+
const header = match
|
|
104
|
+
? match[2]!
|
|
105
|
+
: headerLine.slice(2).replace(/^\s+|\s+$/g, '');
|
|
106
|
+
const oldStart = match?.[1] ? Number(match[1]) : undefined;
|
|
107
|
+
index += 1;
|
|
108
|
+
const hunkLines: PatchHunk['lines'] = [];
|
|
109
|
+
while (
|
|
110
|
+
index < lines.length &&
|
|
111
|
+
!lines[index]!.startsWith('@@') &&
|
|
112
|
+
(!lines[index]!.startsWith('*** ') ||
|
|
113
|
+
lines[index] === '*** End of File')
|
|
114
|
+
) {
|
|
115
|
+
const hunkLine = lines[index]!;
|
|
116
|
+
if (hunkLine === '*** End of File') {
|
|
117
|
+
index += 1;
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
const prefix = hunkLine[0];
|
|
121
|
+
if (prefix !== ' ' && prefix !== '+' && prefix !== '-')
|
|
122
|
+
fail(`hunk 内容行必须以空格、+ 或 - 开头(第 ${index + 1} 行)`);
|
|
123
|
+
hunkLines.push({
|
|
124
|
+
kind:
|
|
125
|
+
prefix === ' ' ? 'context' : prefix === '+' ? 'add' : 'delete',
|
|
126
|
+
text: hunkLine.slice(1),
|
|
127
|
+
});
|
|
128
|
+
index += 1;
|
|
129
|
+
}
|
|
130
|
+
if (!hunkLines.length) fail(`Update File ${path} 包含空 hunk`);
|
|
131
|
+
hunks.push({ header, oldStart, lines: hunkLines });
|
|
132
|
+
}
|
|
133
|
+
if (!hunks.length && !moveTo) fail(`Update File ${path} 没有 hunk`);
|
|
134
|
+
operations.push({
|
|
135
|
+
kind: 'update',
|
|
136
|
+
path,
|
|
137
|
+
...(moveTo ? { moveTo } : {}),
|
|
138
|
+
hunks,
|
|
139
|
+
});
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
fail(`无法识别补丁指令(第 ${index + 1} 行):${line}`);
|
|
143
|
+
}
|
|
144
|
+
fail('补丁缺少 *** End Patch');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function within(root: string, candidate: string): boolean {
|
|
148
|
+
const rel = relative(root, candidate);
|
|
149
|
+
return (
|
|
150
|
+
rel === '' ||
|
|
151
|
+
(!isAbsolute(rel) && rel !== '..' && !rel.startsWith(`..${sep}`))
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
async function nearestExistingAncestor(path: string): Promise<string> {
|
|
156
|
+
let current = path;
|
|
157
|
+
while (!existsSync(current)) {
|
|
158
|
+
const parent = dirname(current);
|
|
159
|
+
if (parent === current) break;
|
|
160
|
+
current = parent;
|
|
161
|
+
}
|
|
162
|
+
return realpath(current);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async function workspacePath(raw: string, cwd: string): Promise<string> {
|
|
166
|
+
if (!raw || isAbsolute(raw) || raw.includes('\0'))
|
|
167
|
+
fail(`补丁路径必须是非空的工作区相对路径:${raw}`);
|
|
168
|
+
const absolute = resolve(cwd, raw);
|
|
169
|
+
const rel = relative(resolve(cwd), absolute);
|
|
170
|
+
if (rel === '..' || rel.startsWith(`..${sep}`) || isAbsolute(rel))
|
|
171
|
+
fail(`补丁路径越过工作区边界:${raw}`);
|
|
172
|
+
const physicalRoot = await realpath(resolve(cwd)).catch(() => resolve(cwd));
|
|
173
|
+
const physicalBoundary = existsSync(absolute)
|
|
174
|
+
? await realpath(absolute)
|
|
175
|
+
: await nearestExistingAncestor(dirname(absolute));
|
|
176
|
+
if (!within(physicalRoot, physicalBoundary))
|
|
177
|
+
fail(`补丁路径通过符号链接越过工作区边界:${raw}`);
|
|
178
|
+
if (hasBinaryExtension(absolute)) fail(`ApplyPatch 不支持二进制文件:${raw}`);
|
|
179
|
+
return absolute;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export function applyHunks(original: string, hunks: PatchHunk[]): string {
|
|
183
|
+
const normalized = original.replaceAll('\r\n', '\n');
|
|
184
|
+
const trailingNewline = normalized.endsWith('\n');
|
|
185
|
+
const lines = normalized.split('\n');
|
|
186
|
+
if (trailingNewline) lines.pop();
|
|
187
|
+
let cursor = 0;
|
|
188
|
+
for (const hunk of hunks) {
|
|
189
|
+
if (hunk.header) {
|
|
190
|
+
const anchor = lines.findIndex(
|
|
191
|
+
(line, index) => index >= cursor && line.includes(hunk.header),
|
|
192
|
+
);
|
|
193
|
+
if (anchor < 0) fail(`找不到 hunk 锚点:${hunk.header}`);
|
|
194
|
+
cursor = anchor;
|
|
195
|
+
}
|
|
196
|
+
const before = hunk.lines
|
|
197
|
+
.filter((line) => line.kind !== 'add')
|
|
198
|
+
.map((line) => line.text);
|
|
199
|
+
const after = hunk.lines
|
|
200
|
+
.filter((line) => line.kind !== 'delete')
|
|
201
|
+
.map((line) => line.text);
|
|
202
|
+
const matchesAt = (start: number) =>
|
|
203
|
+
before.every((line, offset) => lines[start + offset] === line);
|
|
204
|
+
let at = -1;
|
|
205
|
+
if (!before.length) {
|
|
206
|
+
at =
|
|
207
|
+
hunk.oldStart === undefined
|
|
208
|
+
? cursor
|
|
209
|
+
: Math.max(cursor, Math.min(lines.length, hunk.oldStart - 1));
|
|
210
|
+
} else {
|
|
211
|
+
for (
|
|
212
|
+
let index = cursor;
|
|
213
|
+
index <= lines.length - before.length;
|
|
214
|
+
index += 1
|
|
215
|
+
) {
|
|
216
|
+
if (matchesAt(index)) {
|
|
217
|
+
at = index;
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (at < 0 && cursor > 0) {
|
|
222
|
+
const matches: number[] = [];
|
|
223
|
+
for (let index = 0; index <= lines.length - before.length; index += 1)
|
|
224
|
+
if (matchesAt(index)) matches.push(index);
|
|
225
|
+
if (matches.length === 1) at = matches[0]!;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (at < 0)
|
|
229
|
+
fail(`hunk 上下文与当前文件不匹配:${before.join('\n').slice(0, 240)}`);
|
|
230
|
+
lines.splice(at, before.length, ...after);
|
|
231
|
+
cursor = at + after.length;
|
|
232
|
+
}
|
|
233
|
+
return `${lines.join('\n')}${trailingNewline ? '\n' : ''}`;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
interface StagedFile {
|
|
237
|
+
path: string;
|
|
238
|
+
label: string;
|
|
239
|
+
before?: Buffer;
|
|
240
|
+
beforeText: string;
|
|
241
|
+
after?: string;
|
|
242
|
+
encoding: FileBomEncoding;
|
|
243
|
+
activity: 'created' | 'modified' | 'deleted';
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
async function stagePatch(
|
|
247
|
+
operations: PatchOperation[],
|
|
248
|
+
cwd: string,
|
|
249
|
+
): Promise<StagedFile[]> {
|
|
250
|
+
const staged: StagedFile[] = [];
|
|
251
|
+
const touched = new Set<string>();
|
|
252
|
+
const claim = (path: string) => {
|
|
253
|
+
if (touched.has(path)) fail(`同一补丁不能重复操作同一路径:${path}`);
|
|
254
|
+
touched.add(path);
|
|
255
|
+
};
|
|
256
|
+
for (const operation of operations) {
|
|
257
|
+
const path = await workspacePath(operation.path, cwd);
|
|
258
|
+
claim(path);
|
|
259
|
+
if (operation.kind === 'add') {
|
|
260
|
+
if (existsSync(path)) fail(`Add File 目标已存在:${operation.path}`);
|
|
261
|
+
staged.push({
|
|
262
|
+
path,
|
|
263
|
+
label: operation.path,
|
|
264
|
+
beforeText: '',
|
|
265
|
+
after: operation.content,
|
|
266
|
+
encoding: 'utf8',
|
|
267
|
+
activity: 'created',
|
|
268
|
+
});
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
if (!existsSync(path))
|
|
272
|
+
fail(
|
|
273
|
+
`${operation.kind === 'delete' ? 'Delete' : 'Update'} File 不存在:${operation.path}`,
|
|
274
|
+
);
|
|
275
|
+
const snapshot = await readTextFile(path);
|
|
276
|
+
if (operation.kind === 'delete') {
|
|
277
|
+
staged.push({
|
|
278
|
+
path,
|
|
279
|
+
label: operation.path,
|
|
280
|
+
before: snapshot.bytes,
|
|
281
|
+
beforeText: snapshot.content,
|
|
282
|
+
encoding: snapshot.encoding,
|
|
283
|
+
activity: 'deleted',
|
|
284
|
+
});
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
const updated = applyLineEnding(
|
|
288
|
+
applyHunks(snapshot.content, operation.hunks),
|
|
289
|
+
snapshot.lineEnding,
|
|
290
|
+
);
|
|
291
|
+
if (operation.moveTo) {
|
|
292
|
+
const target = await workspacePath(operation.moveTo, cwd);
|
|
293
|
+
claim(target);
|
|
294
|
+
if (existsSync(target)) fail(`Move to 目标已存在:${operation.moveTo}`);
|
|
295
|
+
staged.push({
|
|
296
|
+
path,
|
|
297
|
+
label: operation.path,
|
|
298
|
+
before: snapshot.bytes,
|
|
299
|
+
beforeText: snapshot.content,
|
|
300
|
+
encoding: snapshot.encoding,
|
|
301
|
+
activity: 'deleted',
|
|
302
|
+
});
|
|
303
|
+
staged.push({
|
|
304
|
+
path: target,
|
|
305
|
+
label: operation.moveTo,
|
|
306
|
+
beforeText: '',
|
|
307
|
+
after: updated,
|
|
308
|
+
encoding: snapshot.encoding,
|
|
309
|
+
activity: 'created',
|
|
310
|
+
});
|
|
311
|
+
} else {
|
|
312
|
+
staged.push({
|
|
313
|
+
path,
|
|
314
|
+
label: operation.path,
|
|
315
|
+
before: snapshot.bytes,
|
|
316
|
+
beforeText: snapshot.content,
|
|
317
|
+
after: updated,
|
|
318
|
+
encoding: snapshot.encoding,
|
|
319
|
+
activity: 'modified',
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return staged;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
async function commit(staged: StagedFile[]): Promise<void> {
|
|
327
|
+
const committed: StagedFile[] = [];
|
|
328
|
+
try {
|
|
329
|
+
for (const file of staged) {
|
|
330
|
+
if (file.after === undefined) await rm(file.path);
|
|
331
|
+
else await atomicWriteFile(file.path, file.after, file.encoding);
|
|
332
|
+
committed.push(file);
|
|
333
|
+
}
|
|
334
|
+
} catch (error) {
|
|
335
|
+
const rollbackErrors: string[] = [];
|
|
336
|
+
for (const file of committed.reverse()) {
|
|
337
|
+
try {
|
|
338
|
+
if (file.before) await atomicWriteFile(file.path, file.before);
|
|
339
|
+
else await rm(file.path, { force: true });
|
|
340
|
+
} catch (rollbackError) {
|
|
341
|
+
rollbackErrors.push(
|
|
342
|
+
`${file.label}: ${(rollbackError as Error).message}`,
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
const suffix = rollbackErrors.length
|
|
347
|
+
? `;回滚也有失败:${rollbackErrors.join(';')}`
|
|
348
|
+
: ';已回滚本次已落盘文件';
|
|
349
|
+
throw new Error(`${(error as Error).message}${suffix}`);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
async function call(
|
|
354
|
+
input: ApplyPatchInput,
|
|
355
|
+
context?: ToolCallContext,
|
|
356
|
+
): Promise<ToolResult> {
|
|
357
|
+
const cwd = context?.cwd ?? getWorkingDir();
|
|
358
|
+
let operations: PatchOperation[];
|
|
359
|
+
let staged: StagedFile[];
|
|
360
|
+
try {
|
|
361
|
+
operations = parseApplyPatch(input.patch);
|
|
362
|
+
staged = await stagePatch(operations, cwd);
|
|
363
|
+
await commit(staged);
|
|
364
|
+
} catch (error) {
|
|
365
|
+
return { ok: false, error: `ApplyPatch 失败:${(error as Error).message}` };
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const files: FileActivityMetadata['files'] = [];
|
|
369
|
+
const summaries: string[] = [];
|
|
370
|
+
for (const file of staged) {
|
|
371
|
+
const afterText = file.after ?? '';
|
|
372
|
+
const patch = buildPatchSummary(file.beforeText, afterText, file.label);
|
|
373
|
+
const metadata = await fileActivityMetadata(
|
|
374
|
+
file.path,
|
|
375
|
+
file.activity,
|
|
376
|
+
'not_run',
|
|
377
|
+
'support',
|
|
378
|
+
cwd,
|
|
379
|
+
patch,
|
|
380
|
+
);
|
|
381
|
+
if (metadata) files.push(...metadata.files);
|
|
382
|
+
if (file.after === undefined)
|
|
383
|
+
context?.sessionState?.fileReads.entries.delete(file.path);
|
|
384
|
+
else
|
|
385
|
+
recordRead(
|
|
386
|
+
file.path,
|
|
387
|
+
{
|
|
388
|
+
contentHash: hashFileBytes(encodeTextFile(file.after, file.encoding)),
|
|
389
|
+
},
|
|
390
|
+
context?.sessionState?.fileReads,
|
|
391
|
+
);
|
|
392
|
+
emitFileMutation(file.path);
|
|
393
|
+
summaries.push(
|
|
394
|
+
`${file.activity}: ${file.label} (+${patch.additions} -${patch.deletions})`,
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
return {
|
|
398
|
+
ok: true,
|
|
399
|
+
content: `已应用补丁:\n${summaries.map((line) => `- ${line}`).join('\n')}`,
|
|
400
|
+
...(files.length
|
|
401
|
+
? { metadata: { kind: 'file_activity', files } as FileActivityMetadata }
|
|
402
|
+
: {}),
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
export const applyPatchTool: Tool<ApplyPatchInput> = {
|
|
407
|
+
name: 'ApplyPatch',
|
|
408
|
+
description:
|
|
409
|
+
'Applies one Codex-style *** Begin Patch / *** End Patch transaction across text files. ' +
|
|
410
|
+
'Supports Add File, Update File, Delete File and Move to. All operations are parsed and validated before writing; runtime failures roll back files already changed by this call. Paths must stay inside the workspace.',
|
|
411
|
+
inputSchema: schema,
|
|
412
|
+
parameters: {
|
|
413
|
+
type: 'object',
|
|
414
|
+
properties: {
|
|
415
|
+
patch: {
|
|
416
|
+
type: 'string',
|
|
417
|
+
description: 'Complete Codex-style patch envelope',
|
|
418
|
+
},
|
|
419
|
+
},
|
|
420
|
+
required: ['patch'],
|
|
421
|
+
},
|
|
422
|
+
isReadOnly: false,
|
|
423
|
+
isConcurrencySafe: false,
|
|
424
|
+
maxResultSizeChars: DEFAULT_MAX_RESULT_SIZE_CHARS,
|
|
425
|
+
interruptBehavior: () => 'block',
|
|
426
|
+
call: (input) => call(input),
|
|
427
|
+
callWithContext: (input, _signal, context) => call(input, context),
|
|
428
|
+
};
|
package/src/tools/bash/bash.js
CHANGED
|
@@ -115,6 +115,26 @@ const WIN_BASH = detectWindowsBash();
|
|
|
115
115
|
function effectiveShellKind() {
|
|
116
116
|
return process.platform === 'win32' && !WIN_BASH ? 'cmd' : 'bash';
|
|
117
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* 每台机器不同、只能运行时探测的 shell 方言警告(K1 事故修复的核心内容)。
|
|
120
|
+
* 单一出处:完整 description(下方)和 toolPromptGuides.ts 的压缩 override
|
|
121
|
+
* 都调这个函数,不允许各自抄一份文案——否则「压缩省 token」的那份会在
|
|
122
|
+
* 无 Git Bash 的机器上悄悄丢掉这条警告,模型照抄 POSIX 语法必挂
|
|
123
|
+
* (`mkdir -p` 在 cmd.exe 下不生成中间目录、`$VAR`/`export` 不存在)。
|
|
124
|
+
*/
|
|
125
|
+
export function bashShellNotice() {
|
|
126
|
+
if (process.platform !== 'win32')
|
|
127
|
+
return '';
|
|
128
|
+
return WIN_BASH
|
|
129
|
+
? `# Shell (this machine)
|
|
130
|
+
Commands run in a real bash (Git Bash at ${WIN_BASH}). POSIX syntax works: \`mkdir -p\`, \`$VAR\`, \`$(...)\`, \`&&\`, \`[ -f x ]\` are all fine. Note the working directory is a Windows path — both \`D:\\path\` and \`/d/path\` forms work in this bash.`
|
|
131
|
+
: `# Shell (this machine) — IMPORTANT
|
|
132
|
+
No bash found on this Windows machine: commands run in cmd.exe (UTF-8 enforced). POSIX syntax does NOT work here:
|
|
133
|
+
- NO \`mkdir -p\` — cmd's \`mkdir a\\b\\c\` creates intermediate directories by default; better: the Write tool auto-creates parent directories
|
|
134
|
+
- NO \`$VAR\` / \`$(...)\` / \`[ -f x ]\` / \`export\` — use \`%VAR%\`, \`if exist\`, \`set\`
|
|
135
|
+
- Use \`dir\` / \`copy\` / \`del\` / \`type\` instead of \`ls\` / \`cp\` / \`rm\` / \`cat\`
|
|
136
|
+
\`&&\` and \`;\`-style chaining: \`&&\` works in cmd; \`;\` does not (use \`&\`).`;
|
|
137
|
+
}
|
|
118
138
|
/**
|
|
119
139
|
* G1:stdout / stderr 即时缓冲上限(各自)。命令狂输出(如 cat 大文件 / yes)时,
|
|
120
140
|
* 在最终统一截断之前先把内存封顶,防 OOM。取最终展示截断阈值的 2 倍 —— 正常输出不受影响,
|
|
@@ -278,6 +298,7 @@ const parameters = toToolParameters(inputSchema);
|
|
|
278
298
|
// - 先点明"专用工具优先"的原则,把每类操作映射到对应工具
|
|
279
299
|
// - 再列 Bash 自身的使用规范(绝对路径 / 不 cd / 超时 / 多命令并行...)
|
|
280
300
|
// - 最后强调安全黑名单(让模型知道哪些命令会被拒,避免反复试)
|
|
301
|
+
const shellNotice = bashShellNotice();
|
|
281
302
|
const description = `Executes a given bash command and returns its output.
|
|
282
303
|
|
|
283
304
|
The working directory persists between commands, but shell state does not. The shell environment is initialized from the user's profile.
|
|
@@ -363,21 +384,7 @@ These execute normally; a \`⚠️ 警告:\` line is prepended to the output as
|
|
|
363
384
|
- \`DELETE FROM ...\` (SQL row deletion; DROP/TRUNCATE are in level 2)
|
|
364
385
|
- \`kubectl delete\`, \`terraform destroy\`
|
|
365
386
|
|
|
366
|
-
Regular Git operations (commit, add, status, log, diff, pull, fetch, checkout <branch>, merge, rebase, etc.) run without extra restrictions.${
|
|
367
|
-
? ''
|
|
368
|
-
: WIN_BASH
|
|
369
|
-
? `
|
|
370
|
-
|
|
371
|
-
# Shell (this machine)
|
|
372
|
-
Commands run in a real bash (Git Bash at ${WIN_BASH}). POSIX syntax works: \`mkdir -p\`, \`$VAR\`, \`$(...)\`, \`&&\`, \`[ -f x ]\` are all fine. Note the working directory is a Windows path — both \`D:\\path\` and \`/d/path\` forms work in this bash.`
|
|
373
|
-
: `
|
|
374
|
-
|
|
375
|
-
# Shell (this machine) — IMPORTANT
|
|
376
|
-
No bash found on this Windows machine: commands run in cmd.exe (UTF-8 enforced). POSIX syntax does NOT work here:
|
|
377
|
-
- NO \`mkdir -p\` — cmd's \`mkdir a\\b\\c\` creates intermediate directories by default; better: the Write tool auto-creates parent directories
|
|
378
|
-
- NO \`$VAR\` / \`$(...)\` / \`[ -f x ]\` / \`export\` — use \`%VAR%\`, \`if exist\`, \`set\`
|
|
379
|
-
- Use \`dir\` / \`copy\` / \`del\` / \`type\` instead of \`ls\` / \`cp\` / \`rm\` / \`cat\`
|
|
380
|
-
\`&&\` and \`;\`-style chaining: \`&&\` works in cmd; \`;\` does not (use \`&\`).`}`;
|
|
387
|
+
Regular Git operations (commit, add, status, log, diff, pull, fetch, checkout <branch>, merge, rebase, etc.) run without extra restrictions.${shellNotice ? `\n\n${shellNotice}` : ''}`;
|
|
381
388
|
// ---------------- 4. call() —— 真正干活 ----------------
|
|
382
389
|
async function call(input, signal, context) {
|
|
383
390
|
const command = input.command;
|
package/src/tools/bash/bash.ts
CHANGED
|
@@ -126,6 +126,26 @@ function effectiveShellKind(): ShellKind {
|
|
|
126
126
|
return process.platform === 'win32' && !WIN_BASH ? 'cmd' : 'bash';
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
+
/**
|
|
130
|
+
* 每台机器不同、只能运行时探测的 shell 方言警告(K1 事故修复的核心内容)。
|
|
131
|
+
* 单一出处:完整 description(下方)和 toolPromptGuides.ts 的压缩 override
|
|
132
|
+
* 都调这个函数,不允许各自抄一份文案——否则「压缩省 token」的那份会在
|
|
133
|
+
* 无 Git Bash 的机器上悄悄丢掉这条警告,模型照抄 POSIX 语法必挂
|
|
134
|
+
* (`mkdir -p` 在 cmd.exe 下不生成中间目录、`$VAR`/`export` 不存在)。
|
|
135
|
+
*/
|
|
136
|
+
export function bashShellNotice(): string {
|
|
137
|
+
if (process.platform !== 'win32') return '';
|
|
138
|
+
return WIN_BASH
|
|
139
|
+
? `# Shell (this machine)
|
|
140
|
+
Commands run in a real bash (Git Bash at ${WIN_BASH}). POSIX syntax works: \`mkdir -p\`, \`$VAR\`, \`$(...)\`, \`&&\`, \`[ -f x ]\` are all fine. Note the working directory is a Windows path — both \`D:\\path\` and \`/d/path\` forms work in this bash.`
|
|
141
|
+
: `# Shell (this machine) — IMPORTANT
|
|
142
|
+
No bash found on this Windows machine: commands run in cmd.exe (UTF-8 enforced). POSIX syntax does NOT work here:
|
|
143
|
+
- NO \`mkdir -p\` — cmd's \`mkdir a\\b\\c\` creates intermediate directories by default; better: the Write tool auto-creates parent directories
|
|
144
|
+
- NO \`$VAR\` / \`$(...)\` / \`[ -f x ]\` / \`export\` — use \`%VAR%\`, \`if exist\`, \`set\`
|
|
145
|
+
- Use \`dir\` / \`copy\` / \`del\` / \`type\` instead of \`ls\` / \`cp\` / \`rm\` / \`cat\`
|
|
146
|
+
\`&&\` and \`;\`-style chaining: \`&&\` works in cmd; \`;\` does not (use \`&\`).`;
|
|
147
|
+
}
|
|
148
|
+
|
|
129
149
|
/**
|
|
130
150
|
* G1:stdout / stderr 即时缓冲上限(各自)。命令狂输出(如 cat 大文件 / yes)时,
|
|
131
151
|
* 在最终统一截断之前先把内存封顶,防 OOM。取最终展示截断阈值的 2 倍 —— 正常输出不受影响,
|
|
@@ -303,6 +323,8 @@ const parameters = toToolParameters(inputSchema);
|
|
|
303
323
|
// - 先点明"专用工具优先"的原则,把每类操作映射到对应工具
|
|
304
324
|
// - 再列 Bash 自身的使用规范(绝对路径 / 不 cd / 超时 / 多命令并行...)
|
|
305
325
|
// - 最后强调安全黑名单(让模型知道哪些命令会被拒,避免反复试)
|
|
326
|
+
const shellNotice = bashShellNotice();
|
|
327
|
+
|
|
306
328
|
const description = `Executes a given bash command and returns its output.
|
|
307
329
|
|
|
308
330
|
The working directory persists between commands, but shell state does not. The shell environment is initialized from the user's profile.
|
|
@@ -388,23 +410,7 @@ These execute normally; a \`⚠️ 警告:\` line is prepended to the output as
|
|
|
388
410
|
- \`DELETE FROM ...\` (SQL row deletion; DROP/TRUNCATE are in level 2)
|
|
389
411
|
- \`kubectl delete\`, \`terraform destroy\`
|
|
390
412
|
|
|
391
|
-
Regular Git operations (commit, add, status, log, diff, pull, fetch, checkout <branch>, merge, rebase, etc.) run without extra restrictions.${
|
|
392
|
-
process.platform !== 'win32'
|
|
393
|
-
? ''
|
|
394
|
-
: WIN_BASH
|
|
395
|
-
? `
|
|
396
|
-
|
|
397
|
-
# Shell (this machine)
|
|
398
|
-
Commands run in a real bash (Git Bash at ${WIN_BASH}). POSIX syntax works: \`mkdir -p\`, \`$VAR\`, \`$(...)\`, \`&&\`, \`[ -f x ]\` are all fine. Note the working directory is a Windows path — both \`D:\\path\` and \`/d/path\` forms work in this bash.`
|
|
399
|
-
: `
|
|
400
|
-
|
|
401
|
-
# Shell (this machine) — IMPORTANT
|
|
402
|
-
No bash found on this Windows machine: commands run in cmd.exe (UTF-8 enforced). POSIX syntax does NOT work here:
|
|
403
|
-
- NO \`mkdir -p\` — cmd's \`mkdir a\\b\\c\` creates intermediate directories by default; better: the Write tool auto-creates parent directories
|
|
404
|
-
- NO \`$VAR\` / \`$(...)\` / \`[ -f x ]\` / \`export\` — use \`%VAR%\`, \`if exist\`, \`set\`
|
|
405
|
-
- Use \`dir\` / \`copy\` / \`del\` / \`type\` instead of \`ls\` / \`cp\` / \`rm\` / \`cat\`
|
|
406
|
-
\`&&\` and \`;\`-style chaining: \`&&\` works in cmd; \`;\` does not (use \`&\`).`
|
|
407
|
-
}`;
|
|
413
|
+
Regular Git operations (commit, add, status, log, diff, pull, fetch, checkout <branch>, merge, rebase, etc.) run without extra restrictions.${shellNotice ? `\n\n${shellNotice}` : ''}`;
|
|
408
414
|
|
|
409
415
|
// ---------------- 4. call() —— 真正干活 ----------------
|
|
410
416
|
async function call(input: BashInput, signal?: AbortSignal, context?: ToolCallContext): Promise<ToolResult> {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const TOOL_CAPABILITIES = Object.freeze({
|
|
2
2
|
Read: 'files.read', Glob: 'files.read', Grep: 'files.read',
|
|
3
3
|
Snip: 'files.read',
|
|
4
|
-
Edit: 'files.write', MultiEdit: 'files.write', Write: 'files.write',
|
|
4
|
+
Edit: 'files.write', MultiEdit: 'files.write', Write: 'files.write', ApplyPatch: 'files.write',
|
|
5
5
|
Bash: 'shell',
|
|
6
6
|
PowerShell: 'shell', TaskOutput: 'background.process', TaskStop: 'background.process',
|
|
7
7
|
Trash: 'files.trash',
|
|
@@ -9,9 +9,11 @@ const TOOL_CAPABILITIES = Object.freeze({
|
|
|
9
9
|
Skill: 'skill.invoke', EnterWorktree: 'worktree.session', ExitWorktree: 'worktree.session',
|
|
10
10
|
TerminalCapture: 'terminal.capture',
|
|
11
11
|
LSP: 'code.intelligence', NotebookEdit: 'files.write',
|
|
12
|
-
WebSearch: 'web.search', WebFetch: 'web.fetch', WebBrowser: 'web.browser',
|
|
12
|
+
WebSearch: 'web.search', WebFetch: 'web.fetch', WebBrowser: 'web.browser', BrowserBatch: 'web.browser', BrowserCDP: 'web.browser',
|
|
13
13
|
Download: 'network.download',
|
|
14
|
-
ComputerUse: 'computer.use', AskUserQuestion: 'ask', Advisor: 'advisor',
|
|
14
|
+
ComputerUse: 'computer.use', AskUserQuestion: 'ask', Advisor: 'advisor', AdvisorDecision: 'advisor',
|
|
15
|
+
Agent: 'subagent', AgentMessage: 'subagent', AgentList: 'subagent', AgentWait: 'subagent',
|
|
16
|
+
AgentInterrupt: 'subagent', AgentFollowup: 'subagent',
|
|
15
17
|
PresentResult: 'delivery', GenerateImage: 'media', GenerateSpeech: 'media',
|
|
16
18
|
RecallMemory: 'memory', RememberMemory: 'memory', UpdateMemory: 'memory',
|
|
17
19
|
ListMemories: 'memory', ForgetMemory: 'memory', SetPersona: 'memory',
|
|
@@ -19,9 +21,12 @@ const TOOL_CAPABILITIES = Object.freeze({
|
|
|
19
21
|
SearchConversations: 'memory',
|
|
20
22
|
});
|
|
21
23
|
const CORE_TOOLS = new Set([
|
|
22
|
-
'Read', 'Glob', 'Grep', 'Edit', 'MultiEdit', 'Write', 'NotebookEdit', 'Bash',
|
|
24
|
+
'Read', 'Glob', 'Grep', 'Edit', 'MultiEdit', 'Write', 'ApplyPatch', 'NotebookEdit', 'Bash',
|
|
25
|
+
]);
|
|
26
|
+
const AUXILIARY_TOOLS = new Set([
|
|
27
|
+
'Advisor', 'AdvisorDecision', 'Agent', 'AgentMessage', 'AgentList',
|
|
28
|
+
'AgentWait', 'AgentInterrupt', 'AgentFollowup',
|
|
23
29
|
]);
|
|
24
|
-
const AUXILIARY_TOOLS = new Set(['Advisor', 'Agent']);
|
|
25
30
|
export function budgetClassForToolName(name) {
|
|
26
31
|
if (CORE_TOOLS.has(name))
|
|
27
32
|
return 'core';
|
|
@@ -26,7 +26,7 @@ export type ToolBudgetClass = 'core' | 'task' | 'auxiliary';
|
|
|
26
26
|
const TOOL_CAPABILITIES: Readonly<Record<string, CapabilityId>> = Object.freeze({
|
|
27
27
|
Read: 'files.read', Glob: 'files.read', Grep: 'files.read',
|
|
28
28
|
Snip: 'files.read',
|
|
29
|
-
Edit: 'files.write', MultiEdit: 'files.write', Write: 'files.write',
|
|
29
|
+
Edit: 'files.write', MultiEdit: 'files.write', Write: 'files.write', ApplyPatch: 'files.write',
|
|
30
30
|
Bash: 'shell',
|
|
31
31
|
PowerShell: 'shell', TaskOutput: 'background.process', TaskStop: 'background.process',
|
|
32
32
|
Trash: 'files.trash',
|
|
@@ -34,9 +34,11 @@ const TOOL_CAPABILITIES: Readonly<Record<string, CapabilityId>> = Object.freeze(
|
|
|
34
34
|
Skill: 'skill.invoke', EnterWorktree: 'worktree.session', ExitWorktree: 'worktree.session',
|
|
35
35
|
TerminalCapture: 'terminal.capture',
|
|
36
36
|
LSP: 'code.intelligence', NotebookEdit: 'files.write',
|
|
37
|
-
WebSearch: 'web.search', WebFetch: 'web.fetch', WebBrowser: 'web.browser',
|
|
37
|
+
WebSearch: 'web.search', WebFetch: 'web.fetch', WebBrowser: 'web.browser', BrowserBatch: 'web.browser', BrowserCDP: 'web.browser',
|
|
38
38
|
Download: 'network.download',
|
|
39
|
-
ComputerUse: 'computer.use', AskUserQuestion: 'ask', Advisor: 'advisor',
|
|
39
|
+
ComputerUse: 'computer.use', AskUserQuestion: 'ask', Advisor: 'advisor', AdvisorDecision: 'advisor',
|
|
40
|
+
Agent: 'subagent', AgentMessage: 'subagent', AgentList: 'subagent', AgentWait: 'subagent',
|
|
41
|
+
AgentInterrupt: 'subagent', AgentFollowup: 'subagent',
|
|
40
42
|
PresentResult: 'delivery', GenerateImage: 'media', GenerateSpeech: 'media',
|
|
41
43
|
RecallMemory: 'memory', RememberMemory: 'memory', UpdateMemory: 'memory',
|
|
42
44
|
ListMemories: 'memory', ForgetMemory: 'memory', SetPersona: 'memory',
|
|
@@ -45,9 +47,12 @@ const TOOL_CAPABILITIES: Readonly<Record<string, CapabilityId>> = Object.freeze(
|
|
|
45
47
|
});
|
|
46
48
|
|
|
47
49
|
const CORE_TOOLS = new Set([
|
|
48
|
-
'Read', 'Glob', 'Grep', 'Edit', 'MultiEdit', 'Write', 'NotebookEdit', 'Bash',
|
|
50
|
+
'Read', 'Glob', 'Grep', 'Edit', 'MultiEdit', 'Write', 'ApplyPatch', 'NotebookEdit', 'Bash',
|
|
51
|
+
]);
|
|
52
|
+
const AUXILIARY_TOOLS = new Set([
|
|
53
|
+
'Advisor', 'AdvisorDecision', 'Agent', 'AgentMessage', 'AgentList',
|
|
54
|
+
'AgentWait', 'AgentInterrupt', 'AgentFollowup',
|
|
49
55
|
]);
|
|
50
|
-
const AUXILIARY_TOOLS = new Set(['Advisor', 'Agent']);
|
|
51
56
|
|
|
52
57
|
export function budgetClassForToolName(name: string): ToolBudgetClass {
|
|
53
58
|
if (CORE_TOOLS.has(name)) return 'core';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const CONTINUATION_WINDOW_MS = 30 * 60_000;
|
|
2
|
+
const CONTINUATION_ONLY = /^(?:请)?(?:继续|接着(?:做|操作)?|重试|再试一次|往下做|恢复操作)[。!!\s]*$/i;
|
|
3
|
+
const DIRECT_DESKTOP = /(?:操作(?:电脑|桌面|屏幕|窗口|系统|本机)|电脑自动化|桌面自动化|查看(?:当前)?(?:桌面|屏幕|前台窗口)|截(?:取)?(?:当前)?屏|系统设置|控制面板|任务管理器|资源管理器|访达|Finder)/i;
|
|
4
|
+
const GUI_ACTION = /(?:点击|双击|右键|拖拽|滚动|输入|粘贴|按(?:键|快捷键)|切换|激活|关闭|移动|调整窗口|发送|发布|上传)/i;
|
|
5
|
+
const APP_TARGET = /(?:在|用|打开|切换到|进入)[^,。\n]{0,28}(?:应用|软件|客户端|微信|WeChat|钉钉|飞书|Slack|QQ|邮件|Outlook|Word|Excel|PowerPoint|设置|窗口)(?:里|中|上|内|给|向|并|,|。|\s|$)/i;
|
|
6
|
+
const DISCUSSION_ONLY = /(?:解释|介绍|讨论|分析|评审|代码|源码|实现|设计|为什么|是什么|如何实现|测试.*ComputerUse|ComputerUse.*测试)/i;
|
|
7
|
+
const DIRECT_TOOL_TASK = /(?:读取|分析|查看|理解).{0,12}(?:图片|照片|截图文件|PDF|文件|附件)|(?:搜索|修改|编写|重构|构建|运行测试|查找).{0,12}(?:代码|文件|网页)|(?:搜索网页|打开网址|访问网站|网页中)/i;
|
|
8
|
+
/**
|
|
9
|
+
* Conservative, deterministic exposure classifier. It only consumes the
|
|
10
|
+
* current human input and a short-lived record of a real prior ComputerUse
|
|
11
|
+
* call; model output, page content, and tool arguments can never enable it.
|
|
12
|
+
*/
|
|
13
|
+
export function classifyComputerAutomationIntent(input, continuation, now = Date.now()) {
|
|
14
|
+
const text = input.trim();
|
|
15
|
+
if (continuation
|
|
16
|
+
&& now - continuation.lastUsedAt <= CONTINUATION_WINDOW_MS
|
|
17
|
+
&& CONTINUATION_ONLY.test(text)) {
|
|
18
|
+
return { needed: true, source: 'continuation', reason: '继续最近一次桌面自动化任务' };
|
|
19
|
+
}
|
|
20
|
+
if (!text)
|
|
21
|
+
return { needed: false, source: 'none', reason: '没有桌面操作请求' };
|
|
22
|
+
if (DIRECT_TOOL_TASK.test(text) && !DIRECT_DESKTOP.test(text)) {
|
|
23
|
+
return { needed: false, source: 'none', reason: '专用文件、图片或 Web 工具可直接完成' };
|
|
24
|
+
}
|
|
25
|
+
if (DISCUSSION_ONLY.test(text) && !DIRECT_DESKTOP.test(text) && !GUI_ACTION.test(text)) {
|
|
26
|
+
return { needed: false, source: 'none', reason: '仅讨论桌面能力,没有要求实际操作' };
|
|
27
|
+
}
|
|
28
|
+
if (DIRECT_DESKTOP.test(text) || (GUI_ACTION.test(text) && APP_TARGET.test(text))) {
|
|
29
|
+
return { needed: true, source: 'explicit-current', reason: '用户明确要求操作原生桌面界面' };
|
|
30
|
+
}
|
|
31
|
+
return { needed: false, source: 'none', reason: '未发现明确的原生桌面操作意图' };
|
|
32
|
+
}
|