minimal-agent 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -5
- package/package.json +62 -5
- package/plugins/computer_use/.claude-plugin/plugin.json +1 -1
- package/plugins/cron-runner/src/commands.js +4 -4
- package/plugins/cron-runner/src/commands.ts +4 -4
- package/plugins/workflow-runner/.claude-plugin/plugin.json +2 -2
- package/plugins/workflow-runner/commands/workflow.md +57 -90
- package/plugins/workflow-runner/commands/workflows.md +4 -4
- package/plugins/workflow-runner/plugin.js +24 -13
- package/plugins/workflow-runner/plugin.ts +28 -13
- package/plugins/workflow-runner/src/discovery.js +160 -0
- package/plugins/workflow-runner/src/discovery.ts +194 -0
- package/plugins/workflow-runner/src/goalAnchor.js +53 -0
- package/plugins/workflow-runner/src/goalAnchor.ts +59 -0
- package/plugins/workflow-runner/src/index.js +204 -185
- package/plugins/workflow-runner/src/index.ts +249 -224
- package/plugins/workflow-runner/src/inputCoercion.js +40 -0
- package/plugins/workflow-runner/src/inputCoercion.ts +43 -0
- package/plugins/workflow-runner/src/journal.js +224 -0
- package/plugins/workflow-runner/src/journal.ts +274 -0
- package/plugins/workflow-runner/src/jsonSchema.js +132 -0
- package/plugins/workflow-runner/src/jsonSchema.ts +162 -0
- package/plugins/workflow-runner/src/moduleResolution.js +64 -0
- package/plugins/workflow-runner/src/moduleResolution.ts +71 -0
- package/plugins/workflow-runner/src/resourceInputs.js +220 -0
- package/plugins/workflow-runner/src/resourceInputs.ts +300 -0
- package/plugins/workflow-runner/src/runner.js +404 -467
- package/plugins/workflow-runner/src/runner.ts +491 -535
- package/plugins/workflow-runner/src/runtime/config.js +46 -0
- package/plugins/workflow-runner/src/runtime/config.ts +69 -0
- package/plugins/workflow-runner/src/runtime/context.js +1304 -0
- package/plugins/workflow-runner/src/runtime/context.ts +1786 -0
- package/plugins/workflow-runner/src/runtime/exec.js +34 -0
- package/plugins/workflow-runner/src/runtime/exec.ts +53 -0
- package/plugins/workflow-runner/src/runtime/flow.js +8 -0
- package/plugins/workflow-runner/src/runtime/flow.ts +12 -0
- package/plugins/workflow-runner/src/runtime/fs.js +27 -0
- package/plugins/workflow-runner/src/runtime/fs.ts +41 -0
- package/plugins/workflow-runner/src/runtime/model.js +6 -0
- package/plugins/workflow-runner/src/runtime/model.ts +8 -0
- package/plugins/workflow-runner/src/runtime/output.js +7 -0
- package/plugins/workflow-runner/src/runtime/output.ts +21 -0
- package/plugins/workflow-runner/src/runtime/scheduler.js +141 -0
- package/plugins/workflow-runner/src/runtime/scheduler.ts +166 -0
- package/plugins/workflow-runner/src/runtime/state.js +16 -0
- package/plugins/workflow-runner/src/runtime/state.ts +19 -0
- package/plugins/workflow-runner/src/runtime/tools.js +3 -0
- package/plugins/workflow-runner/src/runtime/tools.ts +6 -0
- package/plugins/workflow-runner/src/sandbox.js +141 -0
- package/plugins/workflow-runner/src/sandbox.ts +182 -0
- package/plugins/workflow-runner/src/scriptGuard.d.mts +38 -0
- package/plugins/workflow-runner/src/scriptGuard.mjs +449 -0
- package/plugins/workflow-runner/src/taskIdentity.js +172 -152
- package/plugins/workflow-runner/src/taskIdentity.ts +233 -200
- package/plugins/workflow-runner/src/toolRuntime.js +29 -8
- package/plugins/workflow-runner/src/toolRuntime.ts +36 -11
- package/plugins/workflow-runner/src/types.js +7 -105
- package/plugins/workflow-runner/src/types.ts +155 -520
- package/plugins/workflow-runner/src/util.js +47 -0
- package/plugins/workflow-runner/src/util.ts +51 -0
- package/plugins/workflow-runner/src/workflowContext.js +20 -0
- package/plugins/workflow-runner/src/workflowContext.ts +58 -0
- package/plugins/workflow-runner/src/workflowDependencies.js +36 -0
- package/plugins/workflow-runner/src/workflowDependencies.ts +59 -0
- package/plugins/workflow-runner/src/workflowFingerprint.js +118 -0
- package/plugins/workflow-runner/src/workflowFingerprint.ts +122 -0
- package/plugins/workflow-runner/src/workflowState.js +542 -469
- package/plugins/workflow-runner/src/workflowState.ts +639 -589
- package/plugins/workflow-runner/test/api.test.ts +223 -0
- package/plugins/workflow-runner/test/apiCapabilities.test.ts +614 -0
- package/plugins/workflow-runner/test/apiConcurrencyGate.test.ts +104 -0
- package/plugins/workflow-runner/test/apiEcho.test.ts +210 -0
- package/plugins/workflow-runner/test/apiReadText.test.ts +178 -0
- package/plugins/workflow-runner/test/apiResourceLedger.test.ts +184 -0
- package/plugins/workflow-runner/test/childWorkflow.test.ts +304 -0
- package/plugins/workflow-runner/test/discovery.test.ts +234 -0
- package/plugins/workflow-runner/test/goalAnchor.test.ts +106 -0
- package/plugins/workflow-runner/test/goalController.test.ts +317 -0
- package/plugins/workflow-runner/test/journalLanes.test.ts +198 -0
- package/plugins/workflow-runner/test/listResources.test.ts +106 -0
- package/plugins/workflow-runner/test/resourceInputs.test.ts +294 -0
- package/plugins/workflow-runner/test/sandbox.test.ts +126 -0
- package/plugins/workflow-runner/test/scheduler.test.ts +70 -0
- package/plugins/workflow-runner/test/scriptGuard.test.ts +276 -0
- package/plugins/workflow-runner/test/skillDocSync.test.ts +78 -0
- package/plugins/workflow-runner/test/taskIdentity.test.ts +288 -179
- package/plugins/workflow-runner/test/workflowFingerprint.test.ts +106 -0
- package/plugins/workflow-runner/test/workflowState.test.ts +429 -0
- package/skills/pptx/examples/assets/cover-bg.svg +23 -0
- package/skills/pptx/examples/assets/icon-spark.svg +5 -0
- package/skills/skill-creator/scripts/run_eval.py +3 -2
- package/skills/ui-design/SKILL.md +5 -2
- package/skills/ui-design/references/layout-composition.md +1 -1
- package/skills/workflow-creator/SKILL.md +344 -0
- package/skills/workflow-creator/assets/template/workflow.mjs +48 -0
- package/skills/workflow-creator/references/api.md +216 -0
- package/skills/workflow-creator/references/migration.md +103 -0
- package/skills/workflow-creator/references/patterns.md +779 -0
- package/skills/workflow-creator/scripts/list-resources.mjs +205 -0
- package/skills/workflow-creator/scripts/scaffold.mjs +148 -0
- package/skills/workflow-creator/scripts/validate.mjs +275 -0
- package/skills/workflow-creator/scripts/workflow-creator.test.mjs +82 -0
- package/src/advisor/advisorCoordinator.js +503 -0
- package/src/advisor/advisorCoordinator.ts +657 -0
- package/src/cli/configMenu.tsx +0 -1
- package/src/cli/print.js +44 -6
- package/src/cli/print.ts +73 -4
- package/src/cli/streamJson.js +5 -6
- package/src/cli/streamJson.ts +8 -4
- package/src/cli/wizards/advisorWizard.js +4 -2
- package/src/cli/wizards/advisorWizard.tsx +8 -2
- package/src/cli/wizards/contextAdvisorWizard.js +5 -4
- package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
- package/src/collaboration/taskFlow.js +115 -0
- package/src/collaboration/taskFlow.ts +169 -0
- package/src/config/configDefaults.js +41 -1
- package/src/config/configDefaults.ts +43 -1
- package/src/config/configDiagnostics.ts +2 -2
- package/src/config/configFile.js +40 -9
- package/src/config/configFile.ts +60 -11
- package/src/config/configService.js +443 -74
- package/src/config/configService.ts +723 -142
- package/src/config/numericLimits.js +22 -0
- package/src/config/numericLimits.ts +24 -0
- package/src/config.js +1 -0
- package/src/config.ts +3 -2
- package/src/context/budgetPlan.js +1 -1
- package/src/context/budgetPlan.ts +1 -1
- package/src/context/compact.js +7 -2
- package/src/context/compact.ts +9 -2
- package/src/context/microCompactLite.js +212 -13
- package/src/context/microCompactLite.ts +261 -12
- package/src/context/sessionRegistry.js +8 -1
- package/src/context/sessionRegistry.ts +18 -5
- package/src/context/toolResultArchive.js +72 -0
- package/src/context/toolResultArchive.ts +95 -0
- package/src/goal/errors.js +8 -0
- package/src/goal/errors.ts +18 -0
- package/src/goal/goalRuntime.js +344 -0
- package/src/goal/goalRuntime.ts +466 -0
- package/src/goal/goalStore.js +200 -0
- package/src/goal/goalStore.ts +219 -0
- package/src/goal/index.js +4 -0
- package/src/goal/index.ts +4 -0
- package/src/goal/statusMapping.js +71 -0
- package/src/goal/statusMapping.ts +95 -0
- package/src/goal/types.js +7 -0
- package/src/goal/types.ts +179 -0
- package/src/goal/workflowController.js +306 -0
- package/src/goal/workflowController.ts +360 -0
- package/src/harness/evidenceLedger.js +2 -0
- package/src/harness/evidenceLedger.ts +1 -0
- package/src/harness/stallGuard.js +9 -3
- package/src/harness/stallGuard.ts +7 -3
- package/src/images/imageResolver.js +161 -0
- package/src/images/imageResolver.ts +189 -0
- package/src/infra/verification.js +56 -20
- package/src/infra/verification.ts +87 -20
- package/src/llm/client.js +79 -21
- package/src/llm/client.ts +182 -35
- package/src/llm/gatewayClient.js +201 -0
- package/src/llm/gatewayClient.ts +299 -0
- package/src/llm/messageProvenance.js +46 -0
- package/src/llm/messageProvenance.ts +58 -0
- package/src/llm/modelProvider.js +1 -0
- package/src/llm/modelProvider.ts +22 -0
- package/src/llm/providers/anthropicFormat.js +108 -1
- package/src/llm/providers/anthropicFormat.ts +115 -4
- package/src/llm/providers/openaiFormat.js +9 -0
- package/src/llm/providers/openaiFormat.ts +12 -3
- package/src/loop.js +319 -54
- package/src/loop.ts +373 -57
- package/src/main.js +4 -1
- package/src/main.tsx +4 -1
- package/src/managedExecution/index.js +2 -0
- package/src/managedExecution/index.ts +2 -0
- package/src/managedExecution/registry.js +15 -0
- package/src/managedExecution/registry.ts +20 -0
- package/src/managedExecution/types.js +1 -0
- package/src/managedExecution/types.ts +86 -0
- package/src/modelRef.js +9 -0
- package/src/modelRef.ts +31 -0
- package/src/multimodal.js +14 -28
- package/src/multimodal.ts +17 -33
- package/src/net/lanDiscovery.js +65 -0
- package/src/net/lanDiscovery.ts +82 -0
- package/src/plugin-sdk.js +28 -3
- package/src/plugin-sdk.ts +39 -6
- package/src/plugins/pluginApi.ts +16 -1
- package/src/plugins/pluginLoader.js +4 -0
- package/src/plugins/pluginLoader.ts +6 -0
- package/src/plugins/pluginRunner.js +152 -9
- package/src/plugins/pluginRunner.ts +186 -8
- package/src/plugins/slashFallback.js +113 -0
- package/src/plugins/slashFallback.ts +137 -0
- package/src/prompts/policyRegistry.js +15 -8
- package/src/prompts/policyRegistry.ts +18 -8
- package/src/prompts/promptAssembly.js +103 -12
- package/src/prompts/promptAssembly.ts +114 -12
- package/src/prompts/skillList.js +21 -3
- package/src/prompts/skillList.ts +27 -2
- package/src/prompts/stableSystemPrompt.js +18 -0
- package/src/prompts/stableSystemPrompt.ts +33 -0
- package/src/runtime/agentRuntimeContext.js +8 -2
- package/src/runtime/agentRuntimeContext.ts +17 -4
- package/src/session/runAgentTurn.js +78 -12
- package/src/session/runAgentTurn.ts +105 -23
- package/src/session/runTurn.js +10 -9
- package/src/session/runTurn.ts +17 -8
- package/src/session/sessionState.ts +2 -0
- package/src/team/auth.js +186 -0
- package/src/team/auth.ts +298 -0
- package/src/team/cli.js +105 -0
- package/src/team/cli.ts +122 -0
- package/src/team/onlineToolContract.js +64 -0
- package/src/team/onlineToolContract.ts +109 -0
- package/src/team/toolPolicy.js +36 -0
- package/src/team/toolPolicy.ts +75 -0
- package/src/tools/advisor/advisor.js +148 -37
- package/src/tools/advisor/advisor.ts +161 -38
- package/src/tools/advisor/advisorDecision.js +71 -0
- package/src/tools/advisor/advisorDecision.ts +85 -0
- package/src/tools/agent/agent.js +18 -5
- package/src/tools/agent/agent.ts +21 -7
- package/src/tools/agent/agentControl.js +246 -0
- package/src/tools/agent/agentControl.ts +284 -0
- package/src/tools/agent/agentTaskService.js +40 -1
- package/src/tools/agent/agentTaskService.ts +44 -1
- package/src/tools/agent/agentTypes.js +14 -2
- package/src/tools/agent/agentTypes.ts +15 -2
- package/src/tools/applypatch/applyPatch.js +362 -0
- package/src/tools/applypatch/applyPatch.ts +428 -0
- package/src/tools/bash/bash.js +70 -18
- package/src/tools/bash/bash.ts +75 -20
- package/src/tools/capabilities.js +10 -5
- package/src/tools/capabilities.ts +10 -5
- package/src/tools/computeruse/computerIntent.js +32 -0
- package/src/tools/computeruse/computerIntent.ts +46 -0
- package/src/tools/computeruse/telemetryLog.js +12 -0
- package/src/tools/computeruse/telemetryLog.ts +16 -0
- package/src/tools/computeruse/vision/telemetry.js +1 -0
- package/src/tools/computeruse/vision/telemetry.ts +1 -0
- package/src/tools/effectiveToolSet.js +4 -0
- package/src/tools/effectiveToolSet.ts +4 -0
- package/src/tools/index.js +21 -2
- package/src/tools/index.ts +33 -2
- package/src/tools/powershell/powershell.js +18 -1
- package/src/tools/powershell/powershell.ts +18 -2
- package/src/tools/presentresult/presentresult.js +6 -15
- package/src/tools/presentresult/presentresult.ts +6 -15
- package/src/tools/read/read.js +69 -11
- package/src/tools/read/read.ts +70 -11
- package/src/tools/shared/fileUtils.js +1 -2
- package/src/tools/shared/fileUtils.ts +1 -2
- package/src/tools/shared/permanentDeleteGuard.js +34 -3
- package/src/tools/shared/permanentDeleteGuard.ts +43 -6
- package/src/tools/shared/toolOutputStore.js +23 -1
- package/src/tools/shared/toolOutputStore.ts +22 -1
- package/src/tools/skill/skill.js +9 -3
- package/src/tools/skill/skill.ts +8 -4
- package/src/tools/toolPromptGuides.js +117 -0
- package/src/tools/toolPromptGuides.ts +137 -0
- package/src/tools/webbrowser/agentBrowserPath.js +19 -9
- package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
- package/src/tools/webbrowser/browser.js +27 -11
- package/src/tools/webbrowser/browser.ts +68 -24
- package/src/tools/webbrowser/browserAutomation.js +329 -0
- package/src/tools/webbrowser/browserAutomation.ts +467 -0
- package/src/tools/webbrowser/browserAxState.js +97 -0
- package/src/tools/webbrowser/browserAxState.ts +142 -0
- package/src/tools/webbrowser/browserBatch.js +1578 -0
- package/src/tools/webbrowser/browserBatch.ts +2382 -0
- package/src/tools/webbrowser/browserCdp.js +208 -0
- package/src/tools/webbrowser/browserCdp.ts +255 -0
- package/src/tools/webbrowser/browserConditions.js +24 -0
- package/src/tools/webbrowser/browserConditions.ts +45 -0
- package/src/tools/webbrowser/browserContent.js +281 -0
- package/src/tools/webbrowser/browserContent.ts +438 -0
- package/src/tools/webbrowser/browserControl.js +131 -30
- package/src/tools/webbrowser/browserControl.ts +210 -50
- package/src/tools/webbrowser/browserDaemon.js +22 -14
- package/src/tools/webbrowser/browserDaemon.ts +54 -21
- package/src/tools/webbrowser/browserFrames.js +47 -0
- package/src/tools/webbrowser/browserFrames.ts +54 -0
- package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
- package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
- package/src/tools/webbrowser/browserLocator.js +140 -0
- package/src/tools/webbrowser/browserLocator.ts +194 -0
- package/src/tools/webbrowser/browserOutcome.js +10 -17
- package/src/tools/webbrowser/browserOutcome.ts +48 -31
- package/src/tools/webbrowser/browserRecovery.js +58 -0
- package/src/tools/webbrowser/browserRecovery.ts +83 -0
- package/src/tools/webbrowser/browserRunRegistry.js +35 -3
- package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
- package/src/tools/webbrowser/browserService.js +28 -2
- package/src/tools/webbrowser/browserService.ts +49 -9
- package/src/tools/webbrowser/browserStream.js +132 -33
- package/src/tools/webbrowser/browserStream.ts +224 -50
- package/src/tools/webbrowser/browserTabs.js +48 -15
- package/src/tools/webbrowser/browserTabs.ts +178 -96
- package/src/tools/webbrowser/webbrowser.js +683 -144
- package/src/tools/webbrowser/webbrowser.ts +979 -236
- package/src/tools/webfetch/preapproved.js +0 -2
- package/src/tools/webfetch/preapproved.ts +0 -2
- package/src/tools/websearch/websearch.js +129 -8
- package/src/tools/websearch/websearch.ts +138 -6
- package/src/types.ts +450 -42
- package/src/ui/App.js +377 -58
- package/src/ui/App.tsx +576 -111
- package/src/ui/LiveArea.js +14 -8
- package/src/ui/LiveArea.tsx +14 -10
- package/src/ui/MessageList.js +63 -20
- package/src/ui/MessageList.tsx +101 -16
- package/src/ui/ModelPicker.js +7 -4
- package/src/ui/ModelPicker.tsx +55 -8
- package/src/ui/hooks/useChat.js +152 -163
- package/src/ui/hooks/useChat.ts +396 -334
- package/src/ui/loginCommand.js +56 -0
- package/src/ui/loginCommand.ts +63 -0
- package/src/ui/toolProgress.js +41 -0
- package/src/ui/toolProgress.ts +44 -0
- package/src/web/browserBridge.js +20 -2
- package/src/web/browserBridge.ts +20 -2
- package/src/web/protocol.ts +1897 -194
- package/workflows/adaptive-research/workflow.mjs +86 -0
- package/workflows/e2e-capabilities/workflow.mjs +102 -0
- package/workflows/e2e-llm/workflow.mjs +52 -0
- package/workflows/e2e-smoke/workflow.mjs +59 -0
- package/workflows/e2e-vision-schema/README.md +48 -0
- package/workflows/e2e-vision-schema/workflow.mjs +149 -0
- package/workflows/e2e-write-greet/workflow.mjs +37 -0
- package/workflows/file-census/README.md +14 -0
- package/workflows/file-census/scripts/.gitkeep +2 -0
- package/workflows/file-census/workflow.mjs +110 -0
- package/workflows/goal/README.md +166 -0
- package/workflows/goal/prompts/audit.md +57 -0
- package/workflows/goal/prompts/contract.md +56 -0
- package/workflows/goal/prompts/iterate.md +37 -0
- package/workflows/goal/workflow.mjs +501 -0
- package/workflows/illustrate/README.md +90 -0
- package/workflows/illustrate/assets/engines.json +20 -0
- package/workflows/illustrate/assets/extract-baidu.js +21 -0
- package/workflows/illustrate/assets/extract-bing.js +33 -0
- package/workflows/illustrate/assets/extract-google.js +31 -0
- package/workflows/illustrate/workflow.mjs +301 -0
- package/workflows/plan/workflow.mjs +389 -0
- package/workflows/question-crops/README.md +35 -0
- package/workflows/question-crops/prompts/inventory.md +23 -0
- package/workflows/question-crops/scripts/image-ops.mjs +305 -0
- package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
- package/workflows/question-crops/workflow.mjs +172 -0
- package/workflows/ralph-loop/workflow.mjs +162 -0
- package/workflows/research/DESIGN.md +449 -0
- package/workflows/research/README.md +74 -0
- package/workflows/research/prompts/s0-goal.md +43 -0
- package/workflows/research/prompts/s1-early-exit.md +22 -0
- package/workflows/research/prompts/s1-map.md +58 -0
- package/workflows/research/prompts/s2-options.md +53 -0
- package/workflows/research/prompts/s3-deep-dive.md +56 -0
- package/workflows/research/prompts/s4-verify.md +74 -0
- package/workflows/research/prompts/s5-synthesis.md +81 -0
- package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
- package/workflows/research/prompts/s6-package.md +32 -0
- package/workflows/research/scripts/build-report.mjs +98 -0
- package/workflows/research/workflow.mjs +288 -0
- package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
- package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
- package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
- package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
- package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
- package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
- package/workflows/wechat-reading-shots/workflow.mjs +266 -0
- package/workflows/wrong-question-docx/README.md +55 -0
- package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
- package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
- package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
- package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
- package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
- package/workflows/wrong-question-docx/workflow.mjs +485 -0
- package/plugins/workflow-runner/src/agentCommon.js +0 -354
- package/plugins/workflow-runner/src/agentCommon.ts +0 -435
- package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
- package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
- package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
- package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
- package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
- package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
- package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
- package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
- package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
- package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
- package/plugins/workflow-runner/src/dslManifest.js +0 -72
- package/plugins/workflow-runner/src/dslManifest.ts +0 -127
- package/plugins/workflow-runner/src/expressions.js +0 -618
- package/plugins/workflow-runner/src/expressions.ts +0 -622
- package/plugins/workflow-runner/src/loader.js +0 -573
- package/plugins/workflow-runner/src/loader.ts +0 -721
- package/plugins/workflow-runner/src/multimodal.js +0 -38
- package/plugins/workflow-runner/src/multimodal.ts +0 -64
- package/plugins/workflow-runner/src/recovery.js +0 -119
- package/plugins/workflow-runner/src/recovery.ts +0 -149
- package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
- package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
- package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -41
- package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -50
- package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
- package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
- package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
- package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
- package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
- package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
- package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
- package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
- package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -208
- package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -256
- package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -58
- package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -68
- package/plugins/workflow-runner/src/stepPipeline.js +0 -277
- package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
- package/plugins/workflow-runner/test/agent.test.ts +0 -587
- package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
- package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
- package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
- package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -147
- package/plugins/workflow-runner/test/context-files.test.ts +0 -320
- package/plugins/workflow-runner/test/e2e.test.ts +0 -370
- package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -226
- package/plugins/workflow-runner/test/expressions.test.ts +0 -397
- package/plugins/workflow-runner/test/foundation.test.ts +0 -126
- package/plugins/workflow-runner/test/graceful.test.ts +0 -139
- package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
- package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
- package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
- package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
- package/plugins/workflow-runner/test/loader.test.ts +0 -617
- package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
- package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
- package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
- package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -87
- package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
- package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
- package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -220
- package/plugins/workflow-runner/test/recovery.test.ts +0 -265
- package/plugins/workflow-runner/test/runner.test.ts +0 -911
- package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -379
- package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
- package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -150
- package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
- package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -338
- package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -270
- package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +0 -221
- package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +0 -29
- package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +0 -168
- package/plugins/workflow-runner/test/webppt.load.test.ts +0 -250
- package/plugins/workflow-runner/test/word.load.test.ts +0 -208
- package/plugins/workflow-runner/test/workflows.smoke.test.ts +0 -76
- package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +0 -207
- package/src/advisorState.js +0 -22
- package/src/cli/configWizard.js +0 -293
- package/src/tools/toolProgressBridge.js +0 -48
- package/workflows/adaptive-research.yaml +0 -50
- package/workflows/book-review-short.yaml +0 -125
- package/workflows/e2e-write-greet.yaml +0 -31
- package/workflows/illustrate.yaml +0 -227
- package/workflows/plan.yaml +0 -470
- package/workflows/ppt.yaml +0 -1670
- package/workflows/ralph-loop.yaml +0 -199
- package/workflows/schema.json +0 -176
- package/workflows/webppt.yaml +0 -496
- package/workflows/wechat-reading-shots.yaml +0 -315
- package/workflows/word.yaml +0 -720
- package/workflows/youtube-shorts.yaml +0 -202
|
@@ -21,6 +21,9 @@
|
|
|
21
21
|
* max_results 可选,默认 5(Tavily 上限 20)
|
|
22
22
|
* search_depth 可选 'basic' | 'advanced',默认 basic
|
|
23
23
|
* topic 可选 'general' | 'news',默认 general
|
|
24
|
+
* recency 可选自动/相对/本年时间窗口
|
|
25
|
+
* start_date 可选 YYYY-MM-DD 绝对起始日期
|
|
26
|
+
* end_date 可选 YYYY-MM-DD 绝对结束日期
|
|
24
27
|
*
|
|
25
28
|
* 输出:
|
|
26
29
|
* 每条结果一段:
|
|
@@ -35,6 +38,16 @@ import { configService } from '../../config/configService.js';
|
|
|
35
38
|
import { DEFAULT_MAX_RESULT_SIZE_CHARS } from '../types.js';
|
|
36
39
|
import { toToolParameters } from '../../utils/zodToJson.js';
|
|
37
40
|
// ---------------- 1. Zod 输入 schema ----------------
|
|
41
|
+
const ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;
|
|
42
|
+
function isValidIsoDate(value) {
|
|
43
|
+
if (!ISO_DATE.test(value))
|
|
44
|
+
return false;
|
|
45
|
+
const [year, month, day] = value.split('-').map(Number);
|
|
46
|
+
const date = new Date(Date.UTC(year, month - 1, day));
|
|
47
|
+
return date.getUTCFullYear() === year
|
|
48
|
+
&& date.getUTCMonth() === month - 1
|
|
49
|
+
&& date.getUTCDate() === day;
|
|
50
|
+
}
|
|
38
51
|
const inputSchema = z.object({
|
|
39
52
|
query: z
|
|
40
53
|
.string()
|
|
@@ -56,6 +69,27 @@ const inputSchema = z.object({
|
|
|
56
69
|
.enum(['general', 'news'])
|
|
57
70
|
.optional()
|
|
58
71
|
.describe('general=通用网页;news=偏新闻源;默认 general'),
|
|
72
|
+
recency: z
|
|
73
|
+
.enum(['auto', 'none', 'day', 'week', 'month', 'year', 'current_year'])
|
|
74
|
+
.optional()
|
|
75
|
+
.describe('时效范围:auto 根据查询识别;none 不限时间;day/week/month/year 为相对窗口;current_year 今年优先且结果不足时扩展到去年'),
|
|
76
|
+
start_date: z
|
|
77
|
+
.string()
|
|
78
|
+
.refine(isValidIsoDate, 'start_date 必须是有效的 YYYY-MM-DD 日期')
|
|
79
|
+
.optional()
|
|
80
|
+
.describe('只返回该日期之后发布或更新的结果;与 end_date 配合使用'),
|
|
81
|
+
end_date: z
|
|
82
|
+
.string()
|
|
83
|
+
.refine(isValidIsoDate, 'end_date 必须是有效的 YYYY-MM-DD 日期')
|
|
84
|
+
.optional()
|
|
85
|
+
.describe('只返回该日期之前发布或更新的结果;与 start_date 配合使用'),
|
|
86
|
+
}).superRefine((input, ctx) => {
|
|
87
|
+
if (input.start_date && input.end_date && input.start_date > input.end_date) {
|
|
88
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['end_date'], message: 'end_date 不能早于 start_date' });
|
|
89
|
+
}
|
|
90
|
+
if ((input.start_date || input.end_date) && input.recency && !['auto', 'none'].includes(input.recency)) {
|
|
91
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['recency'], message: '绝对日期范围与相对 recency 不能同时使用' });
|
|
92
|
+
}
|
|
59
93
|
});
|
|
60
94
|
// ---------------- 2. JSON Schema(由 Zod 自动派生) ----------------
|
|
61
95
|
const parameters = toToolParameters(inputSchema);
|
|
@@ -65,9 +99,62 @@ const description = `Searches the public web through Tavily and returns structur
|
|
|
65
99
|
- It does not open or operate a browser. Use returned URLs with WebFetch when full source text is needed.
|
|
66
100
|
- Results contain title, URL and a text snippet. They are discovery evidence, not a substitute for reading a high-value source in full.
|
|
67
101
|
- Keep each query focused on one sub-question. When another search is needed, change the keywords, source, or angle instead of repeating the same query.
|
|
68
|
-
-
|
|
102
|
+
- Stable concepts and explicit historical queries remain unfiltered. Use recency="day" for today, and recency="current_year" for current/latest/this-year facts; current-year searches widen to the previous year only when the current-year result set is sparse. recency="auto" is a convenience classifier when the query still contains its temporal wording.
|
|
103
|
+
- Use recency="none" to explicitly disable automatic freshness, or start_date/end_date for an exact historical range.
|
|
69
104
|
- \`search_depth: "advanced"\` is slower but can return a synthesized answer; \`topic: "news"\` favors news sources.
|
|
70
105
|
- Requires a configured Tavily API key.`;
|
|
106
|
+
function localIsoDate(now) {
|
|
107
|
+
const parts = new Intl.DateTimeFormat('en-CA', {
|
|
108
|
+
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
109
|
+
year: 'numeric', month: '2-digit', day: '2-digit',
|
|
110
|
+
}).formatToParts(now);
|
|
111
|
+
const part = (type) => parts.find((item) => item.type === type)?.value ?? '';
|
|
112
|
+
return `${part('year')}-${part('month')}-${part('day')}`;
|
|
113
|
+
}
|
|
114
|
+
function resolveSearchWindow(input, now) {
|
|
115
|
+
if (input.start_date || input.end_date) {
|
|
116
|
+
return {
|
|
117
|
+
...(input.start_date ? { startDate: input.start_date } : {}),
|
|
118
|
+
...(input.end_date ? { endDate: input.end_date } : {}),
|
|
119
|
+
label: `${input.start_date ?? '最早'} 至 ${input.end_date ?? '今天'}`,
|
|
120
|
+
source: 'explicit',
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const requested = input.recency ?? 'auto';
|
|
124
|
+
if (requested === 'none')
|
|
125
|
+
return { source: 'none' };
|
|
126
|
+
const today = localIsoDate(now);
|
|
127
|
+
const year = Number(today.slice(0, 4));
|
|
128
|
+
const makeCurrentYear = (source) => ({
|
|
129
|
+
startDate: `${year}-01-01`, endDate: today,
|
|
130
|
+
currentYearFallback: { expandedStartDate: `${year - 1}-01-01`, minimumResults: 3 },
|
|
131
|
+
label: `${year}-01-01 至 ${today}`,
|
|
132
|
+
source,
|
|
133
|
+
});
|
|
134
|
+
if (requested === 'current_year')
|
|
135
|
+
return makeCurrentYear('explicit');
|
|
136
|
+
const relativeLabel = (range) => ({
|
|
137
|
+
day: '最近一天', week: '最近一周', month: '最近一个月', year: '最近一年',
|
|
138
|
+
})[range];
|
|
139
|
+
if (requested !== 'auto')
|
|
140
|
+
return { timeRange: requested, label: relativeLabel(requested), source: 'explicit' };
|
|
141
|
+
const query = input.query.toLowerCase();
|
|
142
|
+
// An explicit past year means the user is asking about history; do not let a
|
|
143
|
+
// nearby word such as "current comparison" erase that requested period.
|
|
144
|
+
const explicitYears = [...query.matchAll(/(?:19|20)\d{2}/g)].map((match) => Number(match[0]));
|
|
145
|
+
if (explicitYears.some((value) => value !== year))
|
|
146
|
+
return { source: 'none' };
|
|
147
|
+
if (/(?:今天|今日|当天|\btoday\b)/i.test(query))
|
|
148
|
+
return { timeRange: 'day', label: relativeLabel('day'), source: 'auto' };
|
|
149
|
+
if (/(?:本周|这周|最近一周|\bthis week\b|\bpast week\b)/i.test(query))
|
|
150
|
+
return { timeRange: 'week', label: relativeLabel('week'), source: 'auto' };
|
|
151
|
+
if (/(?:本月|这个月|最近一个月|近期|\bthis month\b|\bpast month\b|\brecent(?:ly)?\b)/i.test(query))
|
|
152
|
+
return { timeRange: 'month', label: relativeLabel('month'), source: 'auto' };
|
|
153
|
+
if (/(?:今年|本年|当前|目前|现任|最新|最新版|实时|截至现在|\bthis year\b|\bcurrent\b|\blatest\b|\bnewest\b|\bup[- ]to[- ]date\b)/i.test(query)) {
|
|
154
|
+
return makeCurrentYear('auto');
|
|
155
|
+
}
|
|
156
|
+
return { source: 'none' };
|
|
157
|
+
}
|
|
71
158
|
// ---------------- 4b. 退避重试 ----------------
|
|
72
159
|
//
|
|
73
160
|
// 为什么需要(与单发 fetch 零重试的旧行为对比):WebSearch 是 isConcurrencySafe 工具,
|
|
@@ -180,7 +267,7 @@ async function fetchTavilyWithRetry(body, signal) {
|
|
|
180
267
|
};
|
|
181
268
|
}
|
|
182
269
|
// ---------------- 5. call() ----------------
|
|
183
|
-
async function call(input, signal, getApiKey = async () => (await configService.tool('webSearch'))?.apiKey) {
|
|
270
|
+
async function call(input, signal, getApiKey = async () => (await configService.tool('webSearch'))?.apiKey, now = () => new Date()) {
|
|
184
271
|
// 5a. 取 key
|
|
185
272
|
const apiKey = await getApiKey();
|
|
186
273
|
if (!apiKey) {
|
|
@@ -190,7 +277,8 @@ async function call(input, signal, getApiKey = async () => (await configService.
|
|
|
190
277
|
'请在 KakadeAI 设置 → 工具 → 联网搜索中配置,或在 env 模式提供 TAVILY_API_KEY。',
|
|
191
278
|
};
|
|
192
279
|
}
|
|
193
|
-
const
|
|
280
|
+
const window = resolveSearchWindow(input, now());
|
|
281
|
+
const baseBody = {
|
|
194
282
|
api_key: apiKey,
|
|
195
283
|
// Preserve the exact research query. The prompt layer adds a date only
|
|
196
284
|
// when recency matters; unconditional mutation hurts exact names,
|
|
@@ -202,21 +290,53 @@ async function call(input, signal, getApiKey = async () => (await configService.
|
|
|
202
290
|
// 让 advanced 模式自动给 answer;basic 不会有
|
|
203
291
|
include_answer: input.search_depth === 'advanced',
|
|
204
292
|
};
|
|
293
|
+
const buildBody = (selected) => ({
|
|
294
|
+
...baseBody,
|
|
295
|
+
...(selected.timeRange ? { time_range: selected.timeRange } : {}),
|
|
296
|
+
...(selected.startDate ? { start_date: selected.startDate } : {}),
|
|
297
|
+
...(selected.endDate ? { end_date: selected.endDate } : {}),
|
|
298
|
+
});
|
|
205
299
|
// 5c. 发请求(带退避重试,吸收 dev/免费 key 在并发突发下的 socket 切断 + 429/5xx)
|
|
206
|
-
const fetched = await fetchTavilyWithRetry(
|
|
300
|
+
const fetched = await fetchTavilyWithRetry(buildBody(window), signal);
|
|
207
301
|
if (!fetched.ok)
|
|
208
302
|
return { ok: false, error: fetched.error };
|
|
209
|
-
|
|
303
|
+
let data = fetched.data;
|
|
304
|
+
let effectiveWindow = window;
|
|
305
|
+
let fallbackNote = '';
|
|
306
|
+
const fallback = window.currentYearFallback;
|
|
307
|
+
const minimumResults = Math.min(fallback?.minimumResults ?? 0, input.max_results ?? 5);
|
|
308
|
+
if (fallback && (data.results?.length ?? 0) < minimumResults) {
|
|
309
|
+
const expanded = {
|
|
310
|
+
...window,
|
|
311
|
+
startDate: fallback.expandedStartDate,
|
|
312
|
+
label: `${fallback.expandedStartDate} 至 ${window.endDate}`,
|
|
313
|
+
};
|
|
314
|
+
const wider = await fetchTavilyWithRetry(buildBody(expanded), signal);
|
|
315
|
+
if (wider.ok) {
|
|
316
|
+
data = wider.data;
|
|
317
|
+
effectiveWindow = expanded;
|
|
318
|
+
fallbackNote = `今年结果不足 ${minimumResults} 条,已自动扩展到上一年。`;
|
|
319
|
+
}
|
|
320
|
+
else if ((data.results?.length ?? 0) === 0) {
|
|
321
|
+
return { ok: false, error: wider.error };
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
fallbackNote = `今年结果不足 ${minimumResults} 条;扩展到上一年的检索失败,以下保留今年结果。`;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
210
327
|
// 5d. 取结果
|
|
211
328
|
const results = data.results ?? [];
|
|
212
329
|
if (results.length === 0) {
|
|
213
330
|
return {
|
|
214
331
|
ok: true,
|
|
215
|
-
content: `(no results for "${input.query}")`,
|
|
332
|
+
content: `${effectiveWindow.label ? `【检索时间范围】${effectiveWindow.label}\n` : ''}(no results for "${input.query}")`,
|
|
216
333
|
};
|
|
217
334
|
}
|
|
218
335
|
// 5e. 拼输出
|
|
219
336
|
const parts = [];
|
|
337
|
+
if (effectiveWindow.label) {
|
|
338
|
+
parts.push(`【检索时间范围】${effectiveWindow.label}${fallbackNote ? `;${fallbackNote}` : ''}`);
|
|
339
|
+
}
|
|
220
340
|
if (data.answer) {
|
|
221
341
|
parts.push(`【综合回答】\n${data.answer}\n`);
|
|
222
342
|
}
|
|
@@ -234,12 +354,13 @@ async function call(input, signal, getApiKey = async () => (await configService.
|
|
|
234
354
|
return { ok: true, content };
|
|
235
355
|
}
|
|
236
356
|
// ---------------- 6. 导出 ----------------
|
|
237
|
-
export function createWebSearchTool(getApiKey = async () => (await configService.tool('webSearch'))?.apiKey) {
|
|
357
|
+
export function createWebSearchTool(getApiKey = async () => (await configService.tool('webSearch'))?.apiKey, now = () => new Date()) {
|
|
238
358
|
return {
|
|
239
359
|
name: 'WebSearch', description, inputSchema, parameters, isReadOnly: true,
|
|
240
360
|
isConcurrencySafe: true, maxResultSizeChars: DEFAULT_MAX_RESULT_SIZE_CHARS,
|
|
241
361
|
interruptBehavior: () => 'cancel',
|
|
242
|
-
call: (input, signal) => call(input, signal, getApiKey),
|
|
362
|
+
call: (input, signal) => call(input, signal, getApiKey, now),
|
|
243
363
|
};
|
|
244
364
|
}
|
|
245
365
|
export const webSearchTool = createWebSearchTool();
|
|
366
|
+
export { resolveSearchWindow as _resolveSearchWindow };
|
|
@@ -21,6 +21,9 @@
|
|
|
21
21
|
* max_results 可选,默认 5(Tavily 上限 20)
|
|
22
22
|
* search_depth 可选 'basic' | 'advanced',默认 basic
|
|
23
23
|
* topic 可选 'general' | 'news',默认 general
|
|
24
|
+
* recency 可选自动/相对/本年时间窗口
|
|
25
|
+
* start_date 可选 YYYY-MM-DD 绝对起始日期
|
|
26
|
+
* end_date 可选 YYYY-MM-DD 绝对结束日期
|
|
24
27
|
*
|
|
25
28
|
* 输出:
|
|
26
29
|
* 每条结果一段:
|
|
@@ -39,6 +42,17 @@ import { DEFAULT_MAX_RESULT_SIZE_CHARS } from '../types.js';
|
|
|
39
42
|
import { toToolParameters } from '../../utils/zodToJson.js';
|
|
40
43
|
|
|
41
44
|
// ---------------- 1. Zod 输入 schema ----------------
|
|
45
|
+
const ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;
|
|
46
|
+
|
|
47
|
+
function isValidIsoDate(value: string): boolean {
|
|
48
|
+
if (!ISO_DATE.test(value)) return false;
|
|
49
|
+
const [year, month, day] = value.split('-').map(Number);
|
|
50
|
+
const date = new Date(Date.UTC(year!, month! - 1, day));
|
|
51
|
+
return date.getUTCFullYear() === year
|
|
52
|
+
&& date.getUTCMonth() === month! - 1
|
|
53
|
+
&& date.getUTCDate() === day;
|
|
54
|
+
}
|
|
55
|
+
|
|
42
56
|
const inputSchema = z.object({
|
|
43
57
|
query: z
|
|
44
58
|
.string()
|
|
@@ -60,6 +74,27 @@ const inputSchema = z.object({
|
|
|
60
74
|
.enum(['general', 'news'])
|
|
61
75
|
.optional()
|
|
62
76
|
.describe('general=通用网页;news=偏新闻源;默认 general'),
|
|
77
|
+
recency: z
|
|
78
|
+
.enum(['auto', 'none', 'day', 'week', 'month', 'year', 'current_year'])
|
|
79
|
+
.optional()
|
|
80
|
+
.describe('时效范围:auto 根据查询识别;none 不限时间;day/week/month/year 为相对窗口;current_year 今年优先且结果不足时扩展到去年'),
|
|
81
|
+
start_date: z
|
|
82
|
+
.string()
|
|
83
|
+
.refine(isValidIsoDate, 'start_date 必须是有效的 YYYY-MM-DD 日期')
|
|
84
|
+
.optional()
|
|
85
|
+
.describe('只返回该日期之后发布或更新的结果;与 end_date 配合使用'),
|
|
86
|
+
end_date: z
|
|
87
|
+
.string()
|
|
88
|
+
.refine(isValidIsoDate, 'end_date 必须是有效的 YYYY-MM-DD 日期')
|
|
89
|
+
.optional()
|
|
90
|
+
.describe('只返回该日期之前发布或更新的结果;与 start_date 配合使用'),
|
|
91
|
+
}).superRefine((input, ctx) => {
|
|
92
|
+
if (input.start_date && input.end_date && input.start_date > input.end_date) {
|
|
93
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['end_date'], message: 'end_date 不能早于 start_date' });
|
|
94
|
+
}
|
|
95
|
+
if ((input.start_date || input.end_date) && input.recency && !['auto', 'none'].includes(input.recency)) {
|
|
96
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['recency'], message: '绝对日期范围与相对 recency 不能同时使用' });
|
|
97
|
+
}
|
|
63
98
|
});
|
|
64
99
|
type WebSearchInput = z.infer<typeof inputSchema>;
|
|
65
100
|
|
|
@@ -72,7 +107,8 @@ const description = `Searches the public web through Tavily and returns structur
|
|
|
72
107
|
- It does not open or operate a browser. Use returned URLs with WebFetch when full source text is needed.
|
|
73
108
|
- Results contain title, URL and a text snippet. They are discovery evidence, not a substitute for reading a high-value source in full.
|
|
74
109
|
- Keep each query focused on one sub-question. When another search is needed, change the keywords, source, or angle instead of repeating the same query.
|
|
75
|
-
-
|
|
110
|
+
- Stable concepts and explicit historical queries remain unfiltered. Use recency="day" for today, and recency="current_year" for current/latest/this-year facts; current-year searches widen to the previous year only when the current-year result set is sparse. recency="auto" is a convenience classifier when the query still contains its temporal wording.
|
|
111
|
+
- Use recency="none" to explicitly disable automatic freshness, or start_date/end_date for an exact historical range.
|
|
76
112
|
- \`search_depth: "advanced"\` is slower but can return a synthesized answer; \`topic: "news"\` favors news sources.
|
|
77
113
|
- Requires a configured Tavily API key.`;
|
|
78
114
|
|
|
@@ -90,6 +126,65 @@ interface TavilyResponse {
|
|
|
90
126
|
results?: TavilyResult[];
|
|
91
127
|
}
|
|
92
128
|
|
|
129
|
+
type RelativeRange = 'day' | 'week' | 'month' | 'year';
|
|
130
|
+
type SearchWindow = {
|
|
131
|
+
timeRange?: RelativeRange;
|
|
132
|
+
startDate?: string;
|
|
133
|
+
endDate?: string;
|
|
134
|
+
currentYearFallback?: { expandedStartDate: string; minimumResults: number };
|
|
135
|
+
label?: string;
|
|
136
|
+
source: 'none' | 'auto' | 'explicit';
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
function localIsoDate(now: Date): string {
|
|
140
|
+
const parts = new Intl.DateTimeFormat('en-CA', {
|
|
141
|
+
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
142
|
+
year: 'numeric', month: '2-digit', day: '2-digit',
|
|
143
|
+
}).formatToParts(now);
|
|
144
|
+
const part = (type: Intl.DateTimeFormatPartTypes): string =>
|
|
145
|
+
parts.find((item) => item.type === type)?.value ?? '';
|
|
146
|
+
return `${part('year')}-${part('month')}-${part('day')}`;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function resolveSearchWindow(input: WebSearchInput, now: Date): SearchWindow {
|
|
150
|
+
if (input.start_date || input.end_date) {
|
|
151
|
+
return {
|
|
152
|
+
...(input.start_date ? { startDate: input.start_date } : {}),
|
|
153
|
+
...(input.end_date ? { endDate: input.end_date } : {}),
|
|
154
|
+
label: `${input.start_date ?? '最早'} 至 ${input.end_date ?? '今天'}`,
|
|
155
|
+
source: 'explicit',
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
const requested = input.recency ?? 'auto';
|
|
159
|
+
if (requested === 'none') return { source: 'none' };
|
|
160
|
+
const today = localIsoDate(now);
|
|
161
|
+
const year = Number(today.slice(0, 4));
|
|
162
|
+
const makeCurrentYear = (source: SearchWindow['source']): SearchWindow => ({
|
|
163
|
+
startDate: `${year}-01-01`, endDate: today,
|
|
164
|
+
currentYearFallback: { expandedStartDate: `${year - 1}-01-01`, minimumResults: 3 },
|
|
165
|
+
label: `${year}-01-01 至 ${today}`,
|
|
166
|
+
source,
|
|
167
|
+
});
|
|
168
|
+
if (requested === 'current_year') return makeCurrentYear('explicit');
|
|
169
|
+
const relativeLabel = (range: RelativeRange): string => ({
|
|
170
|
+
day: '最近一天', week: '最近一周', month: '最近一个月', year: '最近一年',
|
|
171
|
+
})[range];
|
|
172
|
+
if (requested !== 'auto') return { timeRange: requested, label: relativeLabel(requested), source: 'explicit' };
|
|
173
|
+
|
|
174
|
+
const query = input.query.toLowerCase();
|
|
175
|
+
// An explicit past year means the user is asking about history; do not let a
|
|
176
|
+
// nearby word such as "current comparison" erase that requested period.
|
|
177
|
+
const explicitYears = [...query.matchAll(/(?:19|20)\d{2}/g)].map((match) => Number(match[0]));
|
|
178
|
+
if (explicitYears.some((value) => value !== year)) return { source: 'none' };
|
|
179
|
+
if (/(?:今天|今日|当天|\btoday\b)/i.test(query)) return { timeRange: 'day', label: relativeLabel('day'), source: 'auto' };
|
|
180
|
+
if (/(?:本周|这周|最近一周|\bthis week\b|\bpast week\b)/i.test(query)) return { timeRange: 'week', label: relativeLabel('week'), source: 'auto' };
|
|
181
|
+
if (/(?:本月|这个月|最近一个月|近期|\bthis month\b|\bpast month\b|\brecent(?:ly)?\b)/i.test(query)) return { timeRange: 'month', label: relativeLabel('month'), source: 'auto' };
|
|
182
|
+
if (/(?:今年|本年|当前|目前|现任|最新|最新版|实时|截至现在|\bthis year\b|\bcurrent\b|\blatest\b|\bnewest\b|\bup[- ]to[- ]date\b)/i.test(query)) {
|
|
183
|
+
return makeCurrentYear('auto');
|
|
184
|
+
}
|
|
185
|
+
return { source: 'none' };
|
|
186
|
+
}
|
|
187
|
+
|
|
93
188
|
// ---------------- 4b. 退避重试 ----------------
|
|
94
189
|
//
|
|
95
190
|
// 为什么需要(与单发 fetch 零重试的旧行为对比):WebSearch 是 isConcurrencySafe 工具,
|
|
@@ -215,6 +310,7 @@ async function call(
|
|
|
215
310
|
input: WebSearchInput,
|
|
216
311
|
signal?: AbortSignal,
|
|
217
312
|
getApiKey: () => Promise<string | undefined> = async () => (await configService.tool('webSearch'))?.apiKey,
|
|
313
|
+
now: () => Date = () => new Date(),
|
|
218
314
|
): Promise<ToolResult> {
|
|
219
315
|
// 5a. 取 key
|
|
220
316
|
const apiKey = await getApiKey();
|
|
@@ -227,7 +323,8 @@ async function call(
|
|
|
227
323
|
};
|
|
228
324
|
}
|
|
229
325
|
|
|
230
|
-
const
|
|
326
|
+
const window = resolveSearchWindow(input, now());
|
|
327
|
+
const baseBody = {
|
|
231
328
|
api_key: apiKey,
|
|
232
329
|
// Preserve the exact research query. The prompt layer adds a date only
|
|
233
330
|
// when recency matters; unconditional mutation hurts exact names,
|
|
@@ -240,22 +337,54 @@ async function call(
|
|
|
240
337
|
include_answer: input.search_depth === 'advanced',
|
|
241
338
|
};
|
|
242
339
|
|
|
340
|
+
const buildBody = (selected: SearchWindow): Record<string, unknown> => ({
|
|
341
|
+
...baseBody,
|
|
342
|
+
...(selected.timeRange ? { time_range: selected.timeRange } : {}),
|
|
343
|
+
...(selected.startDate ? { start_date: selected.startDate } : {}),
|
|
344
|
+
...(selected.endDate ? { end_date: selected.endDate } : {}),
|
|
345
|
+
});
|
|
346
|
+
|
|
243
347
|
// 5c. 发请求(带退避重试,吸收 dev/免费 key 在并发突发下的 socket 切断 + 429/5xx)
|
|
244
|
-
const fetched = await fetchTavilyWithRetry(
|
|
348
|
+
const fetched = await fetchTavilyWithRetry(buildBody(window), signal);
|
|
245
349
|
if (!fetched.ok) return { ok: false, error: fetched.error };
|
|
246
|
-
|
|
350
|
+
let data = fetched.data;
|
|
351
|
+
let effectiveWindow = window;
|
|
352
|
+
let fallbackNote = '';
|
|
353
|
+
|
|
354
|
+
const fallback = window.currentYearFallback;
|
|
355
|
+
const minimumResults = Math.min(fallback?.minimumResults ?? 0, input.max_results ?? 5);
|
|
356
|
+
if (fallback && (data.results?.length ?? 0) < minimumResults) {
|
|
357
|
+
const expanded: SearchWindow = {
|
|
358
|
+
...window,
|
|
359
|
+
startDate: fallback.expandedStartDate,
|
|
360
|
+
label: `${fallback.expandedStartDate} 至 ${window.endDate}`,
|
|
361
|
+
};
|
|
362
|
+
const wider = await fetchTavilyWithRetry(buildBody(expanded), signal);
|
|
363
|
+
if (wider.ok) {
|
|
364
|
+
data = wider.data;
|
|
365
|
+
effectiveWindow = expanded;
|
|
366
|
+
fallbackNote = `今年结果不足 ${minimumResults} 条,已自动扩展到上一年。`;
|
|
367
|
+
} else if ((data.results?.length ?? 0) === 0) {
|
|
368
|
+
return { ok: false, error: wider.error };
|
|
369
|
+
} else {
|
|
370
|
+
fallbackNote = `今年结果不足 ${minimumResults} 条;扩展到上一年的检索失败,以下保留今年结果。`;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
247
373
|
|
|
248
374
|
// 5d. 取结果
|
|
249
375
|
const results = data.results ?? [];
|
|
250
376
|
if (results.length === 0) {
|
|
251
377
|
return {
|
|
252
378
|
ok: true,
|
|
253
|
-
content: `(no results for "${input.query}")`,
|
|
379
|
+
content: `${effectiveWindow.label ? `【检索时间范围】${effectiveWindow.label}\n` : ''}(no results for "${input.query}")`,
|
|
254
380
|
};
|
|
255
381
|
}
|
|
256
382
|
|
|
257
383
|
// 5e. 拼输出
|
|
258
384
|
const parts: string[] = [];
|
|
385
|
+
if (effectiveWindow.label) {
|
|
386
|
+
parts.push(`【检索时间范围】${effectiveWindow.label}${fallbackNote ? `;${fallbackNote}` : ''}`);
|
|
387
|
+
}
|
|
259
388
|
if (data.answer) {
|
|
260
389
|
parts.push(`【综合回答】\n${data.answer}\n`);
|
|
261
390
|
}
|
|
@@ -280,13 +409,16 @@ async function call(
|
|
|
280
409
|
// ---------------- 6. 导出 ----------------
|
|
281
410
|
export function createWebSearchTool(
|
|
282
411
|
getApiKey: () => Promise<string | undefined> = async () => (await configService.tool('webSearch'))?.apiKey,
|
|
412
|
+
now: () => Date = () => new Date(),
|
|
283
413
|
): Tool<WebSearchInput> {
|
|
284
414
|
return {
|
|
285
415
|
name: 'WebSearch', description, inputSchema, parameters, isReadOnly: true,
|
|
286
416
|
isConcurrencySafe: true, maxResultSizeChars: DEFAULT_MAX_RESULT_SIZE_CHARS,
|
|
287
417
|
interruptBehavior: () => 'cancel',
|
|
288
|
-
call: (input, signal) => call(input, signal, getApiKey),
|
|
418
|
+
call: (input, signal) => call(input, signal, getApiKey, now),
|
|
289
419
|
};
|
|
290
420
|
}
|
|
291
421
|
|
|
292
422
|
export const webSearchTool = createWebSearchTool();
|
|
423
|
+
|
|
424
|
+
export { resolveSearchWindow as _resolveSearchWindow };
|