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,46 @@
|
|
|
1
|
+
export type ComputerAutomationIntent =
|
|
2
|
+
| { needed: true; source: 'explicit-current' | 'continuation'; reason: string }
|
|
3
|
+
| { needed: false; source: 'none'; reason: string };
|
|
4
|
+
|
|
5
|
+
export interface ComputerAutomationContinuationState {
|
|
6
|
+
lastUsedAt: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const CONTINUATION_WINDOW_MS = 30 * 60_000;
|
|
10
|
+
const CONTINUATION_ONLY = /^(?:请)?(?:继续|接着(?:做|操作)?|重试|再试一次|往下做|恢复操作)[。!!\s]*$/i;
|
|
11
|
+
const DIRECT_DESKTOP = /(?:操作(?:电脑|桌面|屏幕|窗口|系统|本机)|电脑自动化|桌面自动化|查看(?:当前)?(?:桌面|屏幕|前台窗口)|截(?:取)?(?:当前)?屏|系统设置|控制面板|任务管理器|资源管理器|访达|Finder)/i;
|
|
12
|
+
const GUI_ACTION = /(?:点击|双击|右键|拖拽|滚动|输入|粘贴|按(?:键|快捷键)|切换|激活|关闭|移动|调整窗口|发送|发布|上传)/i;
|
|
13
|
+
const APP_TARGET = /(?:在|用|打开|切换到|进入)[^,。\n]{0,28}(?:应用|软件|客户端|微信|WeChat|钉钉|飞书|Slack|QQ|邮件|Outlook|Word|Excel|PowerPoint|设置|窗口)(?:里|中|上|内|给|向|并|,|。|\s|$)/i;
|
|
14
|
+
const DISCUSSION_ONLY = /(?:解释|介绍|讨论|分析|评审|代码|源码|实现|设计|为什么|是什么|如何实现|测试.*ComputerUse|ComputerUse.*测试)/i;
|
|
15
|
+
const DIRECT_TOOL_TASK = /(?:读取|分析|查看|理解).{0,12}(?:图片|照片|截图文件|PDF|文件|附件)|(?:搜索|修改|编写|重构|构建|运行测试|查找).{0,12}(?:代码|文件|网页)|(?:搜索网页|打开网址|访问网站|网页中)/i;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Conservative, deterministic exposure classifier. It only consumes the
|
|
19
|
+
* current human input and a short-lived record of a real prior ComputerUse
|
|
20
|
+
* call; model output, page content, and tool arguments can never enable it.
|
|
21
|
+
*/
|
|
22
|
+
export function classifyComputerAutomationIntent(
|
|
23
|
+
input: string,
|
|
24
|
+
continuation?: ComputerAutomationContinuationState,
|
|
25
|
+
now = Date.now(),
|
|
26
|
+
): ComputerAutomationIntent {
|
|
27
|
+
const text = input.trim();
|
|
28
|
+
if (
|
|
29
|
+
continuation
|
|
30
|
+
&& now - continuation.lastUsedAt <= CONTINUATION_WINDOW_MS
|
|
31
|
+
&& CONTINUATION_ONLY.test(text)
|
|
32
|
+
) {
|
|
33
|
+
return { needed: true, source: 'continuation', reason: '继续最近一次桌面自动化任务' };
|
|
34
|
+
}
|
|
35
|
+
if (!text) return { needed: false, source: 'none', reason: '没有桌面操作请求' };
|
|
36
|
+
if (DIRECT_TOOL_TASK.test(text) && !DIRECT_DESKTOP.test(text)) {
|
|
37
|
+
return { needed: false, source: 'none', reason: '专用文件、图片或 Web 工具可直接完成' };
|
|
38
|
+
}
|
|
39
|
+
if (DISCUSSION_ONLY.test(text) && !DIRECT_DESKTOP.test(text) && !GUI_ACTION.test(text)) {
|
|
40
|
+
return { needed: false, source: 'none', reason: '仅讨论桌面能力,没有要求实际操作' };
|
|
41
|
+
}
|
|
42
|
+
if (DIRECT_DESKTOP.test(text) || (GUI_ACTION.test(text) && APP_TARGET.test(text))) {
|
|
43
|
+
return { needed: true, source: 'explicit-current', reason: '用户明确要求操作原生桌面界面' };
|
|
44
|
+
}
|
|
45
|
+
return { needed: false, source: 'none', reason: '未发现明确的原生桌面操作意图' };
|
|
46
|
+
}
|
|
@@ -28,6 +28,9 @@ import { CONSECUTIVE_FAILURE_LIMIT, readRecords, record, renderReport, summarize
|
|
|
28
28
|
function logPath() {
|
|
29
29
|
return join(computerUseStateDir(), 'telemetry.jsonl');
|
|
30
30
|
}
|
|
31
|
+
function exposureLogPath() {
|
|
32
|
+
return join(computerUseStateDir(), 'exposure.jsonl');
|
|
33
|
+
}
|
|
31
34
|
/**
|
|
32
35
|
* 记一条调用元数据。
|
|
33
36
|
*
|
|
@@ -42,6 +45,15 @@ export async function recordComputerUseCall(raw) {
|
|
|
42
45
|
/* 观测失败不影响功能 */
|
|
43
46
|
}
|
|
44
47
|
}
|
|
48
|
+
/** Records only the boolean exposure decision and a bounded enum source. */
|
|
49
|
+
export async function recordComputerUseExposure(exposed, intentSource) {
|
|
50
|
+
try {
|
|
51
|
+
await record(exposureLogPath(), { exposed, intentSource });
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
/* observability must never affect a turn */
|
|
55
|
+
}
|
|
56
|
+
}
|
|
45
57
|
export { CONSECUTIVE_FAILURE_LIMIT };
|
|
46
58
|
/**
|
|
47
59
|
* 人类可读的遥测汇总,给 CLI/诊断用。
|
|
@@ -38,6 +38,10 @@ function logPath(): string {
|
|
|
38
38
|
return join(computerUseStateDir(), 'telemetry.jsonl');
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
function exposureLogPath(): string {
|
|
42
|
+
return join(computerUseStateDir(), 'exposure.jsonl');
|
|
43
|
+
}
|
|
44
|
+
|
|
41
45
|
/**
|
|
42
46
|
* 记一条调用元数据。
|
|
43
47
|
*
|
|
@@ -52,6 +56,18 @@ export async function recordComputerUseCall(raw: Record<string, unknown>): Promi
|
|
|
52
56
|
}
|
|
53
57
|
}
|
|
54
58
|
|
|
59
|
+
/** Records only the boolean exposure decision and a bounded enum source. */
|
|
60
|
+
export async function recordComputerUseExposure(
|
|
61
|
+
exposed: boolean,
|
|
62
|
+
intentSource: 'explicit-current' | 'continuation' | 'none',
|
|
63
|
+
): Promise<void> {
|
|
64
|
+
try {
|
|
65
|
+
await record(exposureLogPath(), { exposed, intentSource });
|
|
66
|
+
} catch {
|
|
67
|
+
/* observability must never affect a turn */
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
55
71
|
export { CONSECUTIVE_FAILURE_LIMIT };
|
|
56
72
|
|
|
57
73
|
/**
|
|
@@ -30,6 +30,7 @@ const ALLOWED_FIELDS = new Set([
|
|
|
30
30
|
'changeRatio', 'settled', 'stableMs', 'settleConfidence', 'focusChange',
|
|
31
31
|
'settleMode', 'interrupted', 'refused', 'ok',
|
|
32
32
|
'frames', 'axNodes', 'axTruncated',
|
|
33
|
+
'exposed', 'intentSource',
|
|
33
34
|
// 不可逆动作审批的结局(短枚举,如 irreversible_approved / irreversible_denied)。
|
|
34
35
|
//
|
|
35
36
|
// 刻意**不**复用 `refused`:那个字段参与连续失败计数,而「用户不批准这次
|
|
@@ -33,6 +33,7 @@ const ALLOWED_FIELDS = new Set([
|
|
|
33
33
|
'changeRatio', 'settled', 'stableMs', 'settleConfidence', 'focusChange',
|
|
34
34
|
'settleMode', 'interrupted', 'refused', 'ok',
|
|
35
35
|
'frames', 'axNodes', 'axTruncated',
|
|
36
|
+
'exposed', 'intentSource',
|
|
36
37
|
// 不可逆动作审批的结局(短枚举,如 irreversible_approved / irreversible_denied)。
|
|
37
38
|
//
|
|
38
39
|
// 刻意**不**复用 `refused`:那个字段参与连续失败计数,而「用户不批准这次
|
|
@@ -29,9 +29,13 @@ export function createEffectiveToolSet(input) {
|
|
|
29
29
|
input.runtime.cwd,
|
|
30
30
|
input.runtime.surface,
|
|
31
31
|
input.runtime.profile,
|
|
32
|
+
input.runtime.conversationMode ?? 'private',
|
|
32
33
|
input.runtime.memoryAccess,
|
|
33
34
|
input.runtime.browser?.supervised === true ? 'supervised-browser' : 'no-browser',
|
|
34
35
|
input.runtime.computer ? 'computer' : 'no-computer',
|
|
36
|
+
input.runtime.computerIntent?.needed === true
|
|
37
|
+
? `computer-intent:${input.runtime.computerIntent.source}`
|
|
38
|
+
: 'no-computer-intent',
|
|
35
39
|
input.availableTools.map(identity).join(','),
|
|
36
40
|
availability.join(','),
|
|
37
41
|
input.allowedNames?.join(',') ?? '*',
|
|
@@ -46,9 +46,13 @@ export function createEffectiveToolSet(input: {
|
|
|
46
46
|
input.runtime.cwd,
|
|
47
47
|
input.runtime.surface,
|
|
48
48
|
input.runtime.profile,
|
|
49
|
+
input.runtime.conversationMode ?? 'private',
|
|
49
50
|
input.runtime.memoryAccess,
|
|
50
51
|
input.runtime.browser?.supervised === true ? 'supervised-browser' : 'no-browser',
|
|
51
52
|
input.runtime.computer ? 'computer' : 'no-computer',
|
|
53
|
+
input.runtime.computerIntent?.needed === true
|
|
54
|
+
? `computer-intent:${input.runtime.computerIntent.source}`
|
|
55
|
+
: 'no-computer-intent',
|
|
52
56
|
input.availableTools.map(identity).join(','),
|
|
53
57
|
availability.join(','),
|
|
54
58
|
input.allowedNames?.join(',') ?? '*',
|
package/src/tools/index.js
CHANGED
|
@@ -13,10 +13,13 @@
|
|
|
13
13
|
* ============================================================
|
|
14
14
|
*/
|
|
15
15
|
import { advisorTool } from './advisor/advisor.js';
|
|
16
|
+
import { advisorDecisionTool } from './advisor/advisorDecision.js';
|
|
17
|
+
import { applyPatchTool } from './applypatch/applyPatch.js';
|
|
16
18
|
// ⚠️ agent.ts 与本模块构成环(tools/index → agent → loop → tools/index):
|
|
17
19
|
// agent.ts 顶层不求值本模块/loop 的任何导出、loop.ts 的工具 token 估算已懒化,
|
|
18
20
|
// 环在运行时是安全的(详见 agent.ts 文件头「循环依赖纪律」)。
|
|
19
21
|
import { agentTool } from './agent/agent.js';
|
|
22
|
+
import { agentFollowupTool, agentInterruptTool, agentListTool, agentMessageTool, agentWaitTool, } from './agent/agentControl.js';
|
|
20
23
|
import { askUserQuestionTool } from './ask/ask.js';
|
|
21
24
|
import { bashTool } from './bash/bash.js';
|
|
22
25
|
import { assertCapabilityRegistry } from './capabilities.js';
|
|
@@ -40,14 +43,17 @@ import { taskCreateTool, taskGetTool, taskListTool, taskUpdateTool, } from './ta
|
|
|
40
43
|
import { taskOutputTool } from './tasks/taskOutput.js';
|
|
41
44
|
import { taskStopTool } from './tasks/taskStop.js';
|
|
42
45
|
import { terminalCaptureTool } from './terminal/terminalCapture.js';
|
|
46
|
+
import { attachBuiltinPromptGuides } from './toolPromptGuides.js';
|
|
43
47
|
import { trashTool } from './trash/trash.js';
|
|
44
48
|
import { webbrowserTool } from './webbrowser/webbrowser.js';
|
|
49
|
+
import { browserBatchTool } from './webbrowser/browserBatch.js';
|
|
50
|
+
import { browserCdpTool } from './webbrowser/browserCdp.js';
|
|
45
51
|
import { webfetchTool } from './webfetch/webfetch.js';
|
|
46
52
|
import { webSearchTool } from './websearch/websearch.js';
|
|
47
53
|
import { enterWorktreeTool, exitWorktreeTool, } from './worktree/sessionWorktree.js';
|
|
48
54
|
import { writeTool } from './write/write.js';
|
|
49
55
|
/** 所有内置工具(顺序 = 给 LLM 呈现的顺序,不影响代码执行,但会影响模型的优先级直觉) */
|
|
50
|
-
export const ALL_TOOLS = [
|
|
56
|
+
export const ALL_TOOLS = attachBuiltinPromptGuides([
|
|
51
57
|
readTool,
|
|
52
58
|
editTool,
|
|
53
59
|
multiEditTool,
|
|
@@ -79,9 +85,15 @@ export const ALL_TOOLS = [
|
|
|
79
85
|
taskStopTool,
|
|
80
86
|
askUserQuestionTool,
|
|
81
87
|
advisorTool,
|
|
88
|
+
advisorDecisionTool,
|
|
82
89
|
computerUseTool,
|
|
83
90
|
// 追加在末尾:主循环 tools schema 的原有前缀字节不动(提示词缓存友好)
|
|
84
91
|
agentTool,
|
|
92
|
+
agentMessageTool,
|
|
93
|
+
agentListTool,
|
|
94
|
+
agentWaitTool,
|
|
95
|
+
agentInterruptTool,
|
|
96
|
+
agentFollowupTool,
|
|
85
97
|
// Product tools append at the end to preserve the existing schema prefix cache.
|
|
86
98
|
trashTool,
|
|
87
99
|
taskCreateTool,
|
|
@@ -93,7 +105,11 @@ export const ALL_TOOLS = [
|
|
|
93
105
|
exitWorktreeTool,
|
|
94
106
|
terminalCaptureTool,
|
|
95
107
|
snipTool,
|
|
96
|
-
|
|
108
|
+
applyPatchTool,
|
|
109
|
+
// Browser extensions append after the stable legacy schema prefix.
|
|
110
|
+
browserBatchTool,
|
|
111
|
+
browserCdpTool,
|
|
112
|
+
]);
|
|
97
113
|
assertCapabilityRegistry(ALL_TOOLS.map((tool) => tool.name));
|
|
98
114
|
/** 按名字查表 */
|
|
99
115
|
export function getToolByName(name) {
|
|
@@ -197,7 +213,10 @@ export { clearPersonaTool, confirmMemoryTool, forgetMemoryTool, listMemoriesTool
|
|
|
197
213
|
export { multiEditTool } from './edit/multi-edit.js';
|
|
198
214
|
export { genImageTool } from './genimage/genimage.js';
|
|
199
215
|
export { advisorTool } from './advisor/advisor.js';
|
|
216
|
+
export { advisorDecisionTool } from './advisor/advisorDecision.js';
|
|
217
|
+
export { applyPatchTool } from './applypatch/applyPatch.js';
|
|
200
218
|
export { agentTool } from './agent/agent.js';
|
|
219
|
+
export { agentFollowupTool, agentInterruptTool, agentListTool, agentMessageTool, agentWaitTool, } from './agent/agentControl.js';
|
|
201
220
|
export { createGenerateSpeechTool, generateSpeechTool, } from './genspeech/genspeech.js';
|
|
202
221
|
export { createWebSearchTool } from './websearch/websearch.js';
|
|
203
222
|
export { lspTool } from './lsp/lsp.js';
|
package/src/tools/index.ts
CHANGED
|
@@ -15,10 +15,19 @@
|
|
|
15
15
|
|
|
16
16
|
import type { Tool, ToolCallContext, ToolResult } from '../types.js';
|
|
17
17
|
import { advisorTool } from './advisor/advisor.js';
|
|
18
|
+
import { advisorDecisionTool } from './advisor/advisorDecision.js';
|
|
19
|
+
import { applyPatchTool } from './applypatch/applyPatch.js';
|
|
18
20
|
// ⚠️ agent.ts 与本模块构成环(tools/index → agent → loop → tools/index):
|
|
19
21
|
// agent.ts 顶层不求值本模块/loop 的任何导出、loop.ts 的工具 token 估算已懒化,
|
|
20
22
|
// 环在运行时是安全的(详见 agent.ts 文件头「循环依赖纪律」)。
|
|
21
23
|
import { agentTool } from './agent/agent.js';
|
|
24
|
+
import {
|
|
25
|
+
agentFollowupTool,
|
|
26
|
+
agentInterruptTool,
|
|
27
|
+
agentListTool,
|
|
28
|
+
agentMessageTool,
|
|
29
|
+
agentWaitTool,
|
|
30
|
+
} from './agent/agentControl.js';
|
|
22
31
|
import { askUserQuestionTool } from './ask/ask.js';
|
|
23
32
|
import { bashTool } from './bash/bash.js';
|
|
24
33
|
import { assertCapabilityRegistry } from './capabilities.js';
|
|
@@ -58,8 +67,11 @@ import {
|
|
|
58
67
|
import { taskOutputTool } from './tasks/taskOutput.js';
|
|
59
68
|
import { taskStopTool } from './tasks/taskStop.js';
|
|
60
69
|
import { terminalCaptureTool } from './terminal/terminalCapture.js';
|
|
70
|
+
import { attachBuiltinPromptGuides } from './toolPromptGuides.js';
|
|
61
71
|
import { trashTool } from './trash/trash.js';
|
|
62
72
|
import { webbrowserTool } from './webbrowser/webbrowser.js';
|
|
73
|
+
import { browserBatchTool } from './webbrowser/browserBatch.js';
|
|
74
|
+
import { browserCdpTool } from './webbrowser/browserCdp.js';
|
|
63
75
|
import { webfetchTool } from './webfetch/webfetch.js';
|
|
64
76
|
import { webSearchTool } from './websearch/websearch.js';
|
|
65
77
|
import {
|
|
@@ -69,7 +81,7 @@ import {
|
|
|
69
81
|
import { writeTool } from './write/write.js';
|
|
70
82
|
|
|
71
83
|
/** 所有内置工具(顺序 = 给 LLM 呈现的顺序,不影响代码执行,但会影响模型的优先级直觉) */
|
|
72
|
-
export const ALL_TOOLS: Tool[] = [
|
|
84
|
+
export const ALL_TOOLS: Tool[] = attachBuiltinPromptGuides([
|
|
73
85
|
readTool,
|
|
74
86
|
editTool,
|
|
75
87
|
multiEditTool,
|
|
@@ -101,9 +113,15 @@ export const ALL_TOOLS: Tool[] = [
|
|
|
101
113
|
taskStopTool,
|
|
102
114
|
askUserQuestionTool,
|
|
103
115
|
advisorTool,
|
|
116
|
+
advisorDecisionTool,
|
|
104
117
|
computerUseTool,
|
|
105
118
|
// 追加在末尾:主循环 tools schema 的原有前缀字节不动(提示词缓存友好)
|
|
106
119
|
agentTool,
|
|
120
|
+
agentMessageTool,
|
|
121
|
+
agentListTool,
|
|
122
|
+
agentWaitTool,
|
|
123
|
+
agentInterruptTool,
|
|
124
|
+
agentFollowupTool,
|
|
107
125
|
// Product tools append at the end to preserve the existing schema prefix cache.
|
|
108
126
|
trashTool,
|
|
109
127
|
taskCreateTool,
|
|
@@ -115,7 +133,11 @@ export const ALL_TOOLS: Tool[] = [
|
|
|
115
133
|
exitWorktreeTool,
|
|
116
134
|
terminalCaptureTool,
|
|
117
135
|
snipTool,
|
|
118
|
-
|
|
136
|
+
applyPatchTool,
|
|
137
|
+
// Browser extensions append after the stable legacy schema prefix.
|
|
138
|
+
browserBatchTool,
|
|
139
|
+
browserCdpTool,
|
|
140
|
+
]);
|
|
119
141
|
|
|
120
142
|
assertCapabilityRegistry(ALL_TOOLS.map((tool) => tool.name));
|
|
121
143
|
|
|
@@ -263,7 +285,16 @@ export {
|
|
|
263
285
|
export { multiEditTool } from './edit/multi-edit.js';
|
|
264
286
|
export { genImageTool } from './genimage/genimage.js';
|
|
265
287
|
export { advisorTool } from './advisor/advisor.js';
|
|
288
|
+
export { advisorDecisionTool } from './advisor/advisorDecision.js';
|
|
289
|
+
export { applyPatchTool } from './applypatch/applyPatch.js';
|
|
266
290
|
export { agentTool } from './agent/agent.js';
|
|
291
|
+
export {
|
|
292
|
+
agentFollowupTool,
|
|
293
|
+
agentInterruptTool,
|
|
294
|
+
agentListTool,
|
|
295
|
+
agentMessageTool,
|
|
296
|
+
agentWaitTool,
|
|
297
|
+
} from './agent/agentControl.js';
|
|
267
298
|
export {
|
|
268
299
|
createGenerateSpeechTool,
|
|
269
300
|
generateSpeechTool,
|
|
@@ -91,21 +91,12 @@ async function call(input) {
|
|
|
91
91
|
return { ok: false, error: '网页结果只支持 http 或 https 链接' };
|
|
92
92
|
}
|
|
93
93
|
const hasFailedFile = files.some((file) => file.verification === 'failed');
|
|
94
|
-
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
? 'final'
|
|
101
|
-
: files.length === 0 && links.length > 0
|
|
102
|
-
? 'final'
|
|
103
|
-
: 'draft';
|
|
104
|
-
const warnings = files.some((file) => file.verification === 'not_run')
|
|
105
|
-
? ['文件已提交,但尚未通过结构化验证。']
|
|
106
|
-
: hasFailedFile
|
|
107
|
-
? ['至少一个文件未通过结构化验证。']
|
|
108
|
-
: [];
|
|
94
|
+
// `not_run` means no *additional* format/content validator was available. It
|
|
95
|
+
// is not a failed delivery: this tool has already verified that the file exists,
|
|
96
|
+
// is inside the workspace, and captured its size and SHA-256. Only an explicit
|
|
97
|
+
// failed validator should turn an otherwise usable result into a warning.
|
|
98
|
+
const status = hasFailedFile ? 'draft' : 'final';
|
|
99
|
+
const warnings = hasFailedFile ? ['至少一个文件未通过结构化验证。'] : [];
|
|
109
100
|
const manifest = {
|
|
110
101
|
status,
|
|
111
102
|
summary: input.summary?.trim() || (files.length ? `已提交 ${files.length} 个文件` : `已提交 ${links.length} 个网页结果`),
|
|
@@ -101,21 +101,12 @@ async function call(input: PresentResultInput): Promise<ToolResult> {
|
|
|
101
101
|
return { ok: false, error: '网页结果只支持 http 或 https 链接' };
|
|
102
102
|
}
|
|
103
103
|
const hasFailedFile = files.some((file) => file.verification === 'failed');
|
|
104
|
-
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
? 'final'
|
|
111
|
-
: files.length === 0 && links.length > 0
|
|
112
|
-
? 'final'
|
|
113
|
-
: 'draft';
|
|
114
|
-
const warnings = files.some((file) => file.verification === 'not_run')
|
|
115
|
-
? ['文件已提交,但尚未通过结构化验证。']
|
|
116
|
-
: hasFailedFile
|
|
117
|
-
? ['至少一个文件未通过结构化验证。']
|
|
118
|
-
: [];
|
|
104
|
+
// `not_run` means no *additional* format/content validator was available. It
|
|
105
|
+
// is not a failed delivery: this tool has already verified that the file exists,
|
|
106
|
+
// is inside the workspace, and captured its size and SHA-256. Only an explicit
|
|
107
|
+
// failed validator should turn an otherwise usable result into a warning.
|
|
108
|
+
const status = hasFailedFile ? 'draft' : 'final';
|
|
109
|
+
const warnings = hasFailedFile ? ['至少一个文件未通过结构化验证。'] : [];
|
|
119
110
|
const manifest: DeliverableManifest = {
|
|
120
111
|
status,
|
|
121
112
|
summary: input.summary?.trim() || (files.length ? `已提交 ${files.length} 个文件` : `已提交 ${links.length} 个网页结果`),
|
package/src/tools/read/read.js
CHANGED
|
@@ -8,6 +8,7 @@ import { join } from 'node:path';
|
|
|
8
8
|
import { promisify } from 'node:util';
|
|
9
9
|
import { randomUUID } from 'node:crypto';
|
|
10
10
|
import { z } from 'zod';
|
|
11
|
+
import { dlog } from '../../utils/debugLog.js';
|
|
11
12
|
import { toToolParameters } from '../../utils/zodToJson.js';
|
|
12
13
|
import { DEFAULT_MAX_RESULT_SIZE_CHARS, MAX_FILE_SIZE_BYTES, MAX_LINES_TO_READ, } from '../types.js';
|
|
13
14
|
import { fileActivityMetadata } from '../shared/fileActivity.js';
|
|
@@ -15,6 +16,7 @@ import { hashFileBytes, recordRead, } from '../shared/fileState.js';
|
|
|
15
16
|
import { hasBinaryExtension, isBlockedDevicePath, readTextFile, resolveToolPath, } from '../shared/fileUtils.js';
|
|
16
17
|
import { filePathField } from '../shared/schemas.js';
|
|
17
18
|
import { pruneRuntimeOutputs, sessionRuntimeDir, } from '../../session/runtimeStore.js';
|
|
19
|
+
import { detectImageMime, resolveLocalImage, } from '../../images/imageResolver.js';
|
|
18
20
|
const inputSchema = z.object({
|
|
19
21
|
file_path: filePathField('读取'),
|
|
20
22
|
offset: z
|
|
@@ -46,6 +48,12 @@ const IMAGE_EXTENSIONS = new Set([
|
|
|
46
48
|
'.gif',
|
|
47
49
|
'.webp',
|
|
48
50
|
'.bmp',
|
|
51
|
+
'.tif',
|
|
52
|
+
'.tiff',
|
|
53
|
+
'.avif',
|
|
54
|
+
'.heic',
|
|
55
|
+
'.heif',
|
|
56
|
+
'.svg',
|
|
49
57
|
]);
|
|
50
58
|
const MAX_IMAGE_BYTES = 25 * 1024 * 1024;
|
|
51
59
|
const MAX_NOTEBOOK_BYTES = 32 * 1024 * 1024;
|
|
@@ -225,16 +233,29 @@ async function call(input, state, cwd, runtimeIdentity) {
|
|
|
225
233
|
};
|
|
226
234
|
}
|
|
227
235
|
}
|
|
228
|
-
|
|
236
|
+
const imageBytes = info.size <= MAX_IMAGE_BYTES
|
|
237
|
+
? await readFile(filePath).catch(() => null)
|
|
238
|
+
: null;
|
|
239
|
+
const detectedImage = imageBytes ? detectImageMime(imageBytes) : null;
|
|
240
|
+
if (IMAGE_EXTENSIONS.has(ext) || detectedImage) {
|
|
229
241
|
if (info.size > MAX_IMAGE_BYTES)
|
|
230
242
|
return { ok: false, error: `图片超过 ${MAX_IMAGE_BYTES} 字节上限` };
|
|
231
|
-
|
|
243
|
+
let resolvedImage;
|
|
244
|
+
try {
|
|
245
|
+
resolvedImage = await resolveLocalImage(filePath, {
|
|
246
|
+
maxInputBytes: MAX_IMAGE_BYTES,
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
catch (error) {
|
|
250
|
+
return { ok: false, error: `图片读取失败:${error.message}` };
|
|
251
|
+
}
|
|
252
|
+
const bytes = imageBytes ?? await readFile(filePath);
|
|
232
253
|
recordRead(filePath, { contentHash: hashFileBytes(bytes) }, state);
|
|
233
254
|
return {
|
|
234
255
|
ok: true,
|
|
235
|
-
content: `已读取图片:${filePath}(${info.size}
|
|
256
|
+
content: `已读取图片:${filePath}(${info.size} 字节,实际格式 ${resolvedImage.originalMime})${resolvedImage.transformed ? `;已规范化为 ${resolvedImage.mime}` : ''}。图像已附加供视觉模型直接检查。`,
|
|
236
257
|
metadata: await fileActivityMetadata(filePath, 'read', 'not_run', 'source', cwd),
|
|
237
|
-
visionImages: [{ source:
|
|
258
|
+
visionImages: [{ source: resolvedImage.path }],
|
|
238
259
|
visionNote: '这是 Read 工具读取的本地图片,请直接检查图像内容。',
|
|
239
260
|
};
|
|
240
261
|
}
|
|
@@ -352,10 +373,30 @@ async function renderPdfPages(document, filePath, pages, identity) {
|
|
|
352
373
|
const dynamicImport = new Function('specifier', 'return import(specifier)');
|
|
353
374
|
let createCanvas;
|
|
354
375
|
try {
|
|
355
|
-
|
|
376
|
+
const napi = await dynamicImport('@napi-rs/canvas');
|
|
377
|
+
createCanvas = napi.createCanvas;
|
|
378
|
+
// ⚠️ **必须在 pdfjs 之前把这几个全局占住**,否则 PDF 转图 100% 失败。
|
|
379
|
+
//
|
|
380
|
+
// pdfjs 的 legacy 构建在 Node 环境下自己往 globalThis 装一套 Path2D /
|
|
381
|
+
// DOMMatrix / ImageData polyfill。渲染时它 `new Path2D()` 拿到的是**它自己那份**,
|
|
382
|
+
// 转手调 `ctx.fill(path, 'evenodd')` 交给 @napi-rs/canvas —— 而 napi 的原生绑定
|
|
383
|
+
// 只认自己的 `Path`,于是每一页都抛
|
|
384
|
+
// `Value is none of these types \`String\`, \`Path\``
|
|
385
|
+
// 两份 polyfill 撞车,谁都没错,就是不是同一个对象。
|
|
386
|
+
//
|
|
387
|
+
// 实测:五种 render 参数组合(canvas / canvasContext / canvas:null / 带不带
|
|
388
|
+
// standardFontDataUrl)全部同样失败 —— 也就是说 `canvas` 那个类型错**不是**病因,
|
|
389
|
+
// 修类型并不能让它跑起来。把全局换成 napi 的实现之后第 1 页立刻渲染出 137KB PNG。
|
|
390
|
+
for (const name of ['Path2D', 'DOMMatrix', 'ImageData']) {
|
|
391
|
+
const impl = napi[name];
|
|
392
|
+
if (impl)
|
|
393
|
+
globalThis[name] = impl;
|
|
394
|
+
}
|
|
356
395
|
}
|
|
357
|
-
catch {
|
|
358
|
-
|
|
396
|
+
catch (e) {
|
|
397
|
+
// optional adapter:没装 @napi-rs/canvas 就回落 pdftoppm。
|
|
398
|
+
// 但「没装」和「装了却加载失败」对用户是两件事,别都吞成前者。
|
|
399
|
+
dlog('read:pdf', `@napi-rs/canvas 不可用:${e instanceof Error ? e.message : e}`);
|
|
359
400
|
}
|
|
360
401
|
if (createCanvas) {
|
|
361
402
|
try {
|
|
@@ -363,8 +404,13 @@ async function renderPdfPages(document, filePath, pages, identity) {
|
|
|
363
404
|
const page = await document.getPage(pageNumber);
|
|
364
405
|
const viewport = page.getViewport({ scale: 2 });
|
|
365
406
|
const canvas = createCanvas(Math.ceil(viewport.width), Math.ceil(viewport.height));
|
|
407
|
+
// ⚠️ pdfjs v6 的 RenderParameters 里 `canvas` 是**必填**、`canvasContext`
|
|
408
|
+
// 反而降级为可选且不推荐;文档明说「若必须用 context,canvas 必须为 null」。
|
|
409
|
+
// 只给 canvasContext 会类型不过(`bun run typecheck` 唯一的红)。
|
|
410
|
+
// 运行时它有默认值 `canvas = canvasContext.canvas` 所以不炸 —— 但类型要对。
|
|
366
411
|
await page.render({
|
|
367
|
-
|
|
412
|
+
canvasContext: canvas.getContext('2d'),
|
|
413
|
+
canvas: null,
|
|
368
414
|
viewport,
|
|
369
415
|
}).promise;
|
|
370
416
|
const target = join(outputDir, `${outputPrefix}-page-${pageNumber}.png`);
|
|
@@ -374,7 +420,14 @@ async function renderPdfPages(document, filePath, pages, identity) {
|
|
|
374
420
|
void pruneRuntimeOutputs();
|
|
375
421
|
return images;
|
|
376
422
|
}
|
|
377
|
-
catch {
|
|
423
|
+
catch (e) {
|
|
424
|
+
// ⚠️ 别把这里改回裸 catch。上面那个 Path2D 冲突就是被它藏住的:
|
|
425
|
+
// Canvas 每页都抛 → images 清空 → 回落 pdftoppm。装了 poppler 的机器照样
|
|
426
|
+
// 出图(只是分辨率更低、多一次进程),**完全看不出来**;没装 poppler 的机器
|
|
427
|
+
// (多数 Windows、绿色版 U 盘)则返回 `ok:true` + 0 张图 + 一句
|
|
428
|
+
// 「视觉渲染不可用(Canvas 与 pdftoppm 均不可用)」——而 Canvas 明明可用,
|
|
429
|
+
// 只是抛了。错误文案把人指向「装依赖」,真因一个字都查不到。
|
|
430
|
+
dlog('read:pdf', `Canvas 渲染失败:${e instanceof Error ? e.message : e}`);
|
|
378
431
|
images.length = 0;
|
|
379
432
|
}
|
|
380
433
|
}
|
package/src/tools/read/read.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { randomUUID } from 'node:crypto';
|
|
|
10
10
|
import { z } from 'zod';
|
|
11
11
|
|
|
12
12
|
import type { Tool, ToolCallContext, ToolResult } from '../../types.js';
|
|
13
|
+
import { dlog } from '../../utils/debugLog.js';
|
|
13
14
|
import { toToolParameters } from '../../utils/zodToJson.js';
|
|
14
15
|
import {
|
|
15
16
|
DEFAULT_MAX_RESULT_SIZE_CHARS,
|
|
@@ -34,6 +35,10 @@ import {
|
|
|
34
35
|
sessionRuntimeDir,
|
|
35
36
|
type RuntimeIdentity,
|
|
36
37
|
} from '../../session/runtimeStore.js';
|
|
38
|
+
import {
|
|
39
|
+
detectImageMime,
|
|
40
|
+
resolveLocalImage,
|
|
41
|
+
} from '../../images/imageResolver.js';
|
|
37
42
|
|
|
38
43
|
const inputSchema = z.object({
|
|
39
44
|
file_path: filePathField('读取'),
|
|
@@ -70,6 +75,12 @@ const IMAGE_EXTENSIONS = new Set([
|
|
|
70
75
|
'.gif',
|
|
71
76
|
'.webp',
|
|
72
77
|
'.bmp',
|
|
78
|
+
'.tif',
|
|
79
|
+
'.tiff',
|
|
80
|
+
'.avif',
|
|
81
|
+
'.heic',
|
|
82
|
+
'.heif',
|
|
83
|
+
'.svg',
|
|
73
84
|
]);
|
|
74
85
|
const MAX_IMAGE_BYTES = 25 * 1024 * 1024;
|
|
75
86
|
const MAX_NOTEBOOK_BYTES = 32 * 1024 * 1024;
|
|
@@ -295,14 +306,26 @@ async function call(
|
|
|
295
306
|
}
|
|
296
307
|
}
|
|
297
308
|
|
|
298
|
-
|
|
309
|
+
const imageBytes = info.size <= MAX_IMAGE_BYTES
|
|
310
|
+
? await readFile(filePath).catch(() => null)
|
|
311
|
+
: null;
|
|
312
|
+
const detectedImage = imageBytes ? detectImageMime(imageBytes) : null;
|
|
313
|
+
if (IMAGE_EXTENSIONS.has(ext) || detectedImage) {
|
|
299
314
|
if (info.size > MAX_IMAGE_BYTES)
|
|
300
315
|
return { ok: false, error: `图片超过 ${MAX_IMAGE_BYTES} 字节上限` };
|
|
301
|
-
|
|
316
|
+
let resolvedImage;
|
|
317
|
+
try {
|
|
318
|
+
resolvedImage = await resolveLocalImage(filePath, {
|
|
319
|
+
maxInputBytes: MAX_IMAGE_BYTES,
|
|
320
|
+
});
|
|
321
|
+
} catch (error) {
|
|
322
|
+
return { ok: false, error: `图片读取失败:${(error as Error).message}` };
|
|
323
|
+
}
|
|
324
|
+
const bytes = imageBytes ?? await readFile(filePath);
|
|
302
325
|
recordRead(filePath, { contentHash: hashFileBytes(bytes) }, state);
|
|
303
326
|
return {
|
|
304
327
|
ok: true,
|
|
305
|
-
content: `已读取图片:${filePath}(${info.size}
|
|
328
|
+
content: `已读取图片:${filePath}(${info.size} 字节,实际格式 ${resolvedImage.originalMime})${resolvedImage.transformed ? `;已规范化为 ${resolvedImage.mime}` : ''}。图像已附加供视觉模型直接检查。`,
|
|
306
329
|
metadata: await fileActivityMetadata(
|
|
307
330
|
filePath,
|
|
308
331
|
'read',
|
|
@@ -310,7 +333,7 @@ async function call(
|
|
|
310
333
|
'source',
|
|
311
334
|
cwd,
|
|
312
335
|
),
|
|
313
|
-
visionImages: [{ source:
|
|
336
|
+
visionImages: [{ source: resolvedImage.path }],
|
|
314
337
|
visionNote: '这是 Read 工具读取的本地图片,请直接检查图像内容。',
|
|
315
338
|
};
|
|
316
339
|
}
|
|
@@ -475,9 +498,28 @@ async function renderPdfPages(
|
|
|
475
498
|
}>;
|
|
476
499
|
let createCanvas: Awaited<ReturnType<typeof dynamicImport>>['createCanvas'];
|
|
477
500
|
try {
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
501
|
+
const napi = await dynamicImport('@napi-rs/canvas');
|
|
502
|
+
createCanvas = napi.createCanvas;
|
|
503
|
+
// ⚠️ **必须在 pdfjs 之前把这几个全局占住**,否则 PDF 转图 100% 失败。
|
|
504
|
+
//
|
|
505
|
+
// pdfjs 的 legacy 构建在 Node 环境下自己往 globalThis 装一套 Path2D /
|
|
506
|
+
// DOMMatrix / ImageData polyfill。渲染时它 `new Path2D()` 拿到的是**它自己那份**,
|
|
507
|
+
// 转手调 `ctx.fill(path, 'evenodd')` 交给 @napi-rs/canvas —— 而 napi 的原生绑定
|
|
508
|
+
// 只认自己的 `Path`,于是每一页都抛
|
|
509
|
+
// `Value is none of these types \`String\`, \`Path\``
|
|
510
|
+
// 两份 polyfill 撞车,谁都没错,就是不是同一个对象。
|
|
511
|
+
//
|
|
512
|
+
// 实测:五种 render 参数组合(canvas / canvasContext / canvas:null / 带不带
|
|
513
|
+
// standardFontDataUrl)全部同样失败 —— 也就是说 `canvas` 那个类型错**不是**病因,
|
|
514
|
+
// 修类型并不能让它跑起来。把全局换成 napi 的实现之后第 1 页立刻渲染出 137KB PNG。
|
|
515
|
+
for (const name of ['Path2D', 'DOMMatrix', 'ImageData'] as const) {
|
|
516
|
+
const impl = (napi as Record<string, unknown>)[name];
|
|
517
|
+
if (impl) (globalThis as Record<string, unknown>)[name] = impl;
|
|
518
|
+
}
|
|
519
|
+
} catch (e) {
|
|
520
|
+
// optional adapter:没装 @napi-rs/canvas 就回落 pdftoppm。
|
|
521
|
+
// 但「没装」和「装了却加载失败」对用户是两件事,别都吞成前者。
|
|
522
|
+
dlog('read:pdf', `@napi-rs/canvas 不可用:${e instanceof Error ? e.message : e}`);
|
|
481
523
|
}
|
|
482
524
|
if (createCanvas) {
|
|
483
525
|
try {
|
|
@@ -488,8 +530,13 @@ async function renderPdfPages(
|
|
|
488
530
|
Math.ceil(viewport.width),
|
|
489
531
|
Math.ceil(viewport.height),
|
|
490
532
|
);
|
|
533
|
+
// ⚠️ pdfjs v6 的 RenderParameters 里 `canvas` 是**必填**、`canvasContext`
|
|
534
|
+
// 反而降级为可选且不推荐;文档明说「若必须用 context,canvas 必须为 null」。
|
|
535
|
+
// 只给 canvasContext 会类型不过(`bun run typecheck` 唯一的红)。
|
|
536
|
+
// 运行时它有默认值 `canvas = canvasContext.canvas` 所以不炸 —— 但类型要对。
|
|
491
537
|
await page.render({
|
|
492
|
-
|
|
538
|
+
canvasContext: canvas.getContext('2d') as never,
|
|
539
|
+
canvas: null,
|
|
493
540
|
viewport,
|
|
494
541
|
}).promise;
|
|
495
542
|
const target = join(
|
|
@@ -501,7 +548,14 @@ async function renderPdfPages(
|
|
|
501
548
|
}
|
|
502
549
|
void pruneRuntimeOutputs();
|
|
503
550
|
return images;
|
|
504
|
-
} catch {
|
|
551
|
+
} catch (e) {
|
|
552
|
+
// ⚠️ 别把这里改回裸 catch。上面那个 Path2D 冲突就是被它藏住的:
|
|
553
|
+
// Canvas 每页都抛 → images 清空 → 回落 pdftoppm。装了 poppler 的机器照样
|
|
554
|
+
// 出图(只是分辨率更低、多一次进程),**完全看不出来**;没装 poppler 的机器
|
|
555
|
+
// (多数 Windows、绿色版 U 盘)则返回 `ok:true` + 0 张图 + 一句
|
|
556
|
+
// 「视觉渲染不可用(Canvas 与 pdftoppm 均不可用)」——而 Canvas 明明可用,
|
|
557
|
+
// 只是抛了。错误文案把人指向「装依赖」,真因一个字都查不到。
|
|
558
|
+
dlog('read:pdf', `Canvas 渲染失败:${e instanceof Error ? e.message : e}`);
|
|
505
559
|
images.length = 0;
|
|
506
560
|
}
|
|
507
561
|
}
|
|
@@ -115,7 +115,7 @@ export function applyLineEnding(content, ending) {
|
|
|
115
115
|
// -------------------- 3.5 二进制扩展名拦截 --------------------
|
|
116
116
|
// 上游 D:\code\kakadeai\constants\files.ts:5-112 BINARY_EXTENSIONS Set 的裁剪版:
|
|
117
117
|
// 故意剔除 .log / .csv / .tsv / .dat / .data / .lock —— 这些经常被人当文本读。
|
|
118
|
-
// 保留纯二进制:图片 / 文档 / 可执行 / 编译产物 / 压缩包 / 多媒体 / 字体 /
|
|
118
|
+
// 保留纯二进制:图片 / 文档 / 可执行 / 编译产物 / 压缩包 / 多媒体 / 字体 / wasm。
|
|
119
119
|
export const BINARY_EXTENSIONS = new Set([
|
|
120
120
|
'.png', '.jpg', '.jpeg', '.gif', '.webp', '.bmp', '.ico', '.tiff', '.tif',
|
|
121
121
|
'.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx',
|
|
@@ -124,7 +124,6 @@ export const BINARY_EXTENSIONS = new Set([
|
|
|
124
124
|
'.zip', '.tar', '.gz', '.bz2', '.7z', '.rar', '.iso',
|
|
125
125
|
'.mp3', '.mp4', '.mov', '.avi', '.mkv', '.wav', '.flac', '.ogg',
|
|
126
126
|
'.ttf', '.otf', '.woff', '.woff2',
|
|
127
|
-
'.sqlite', '.sqlite3', '.db',
|
|
128
127
|
'.psd', '.ai', '.bin', '.wasm',
|
|
129
128
|
]);
|
|
130
129
|
export function hasBinaryExtension(filePath) {
|