minimal-agent 0.10.0 → 0.12.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 +11 -3
- package/package.json +52 -5
- package/plugins/computer_use/.claude-plugin/plugin.json +6 -0
- package/plugins/computer_use/README.md +94 -0
- package/plugins/computer_use/app/_template.md +142 -0
- package/plugins/computer_use/app/chrome.md +165 -0
- package/plugins/computer_use/app/finder.md +76 -0
- package/plugins/computer_use/app/macos-system-settings.md +81 -0
- package/plugins/computer_use/app/microsoft-excel.md +80 -0
- package/plugins/computer_use/app/microsoft-powerpoint.md +80 -0
- package/plugins/computer_use/app/microsoft-word.md +79 -0
- package/plugins/computer_use/app/wechat.md +413 -0
- package/plugins/computer_use/app/weread.md +319 -0
- package/plugins/computer_use/commands/computeruse.md +25 -0
- package/plugins/computer_use/commands/cu.md +9 -0
- package/plugins/computer_use/plugin.js +26 -0
- package/plugins/computer_use/plugin.ts +30 -0
- package/plugins/computer_use/src/capture.js +90 -0
- package/plugins/computer_use/src/capture.ts +104 -0
- package/plugins/computer_use/src/commands.js +91 -0
- package/plugins/computer_use/src/commands.ts +103 -0
- package/plugins/computer_use/src/daemon.js +134 -0
- package/plugins/computer_use/src/daemon.ts +161 -0
- package/plugins/computer_use/src/manuals.js +135 -0
- package/plugins/computer_use/src/manuals.ts +159 -0
- package/plugins/computer_use/src/verify.js +168 -0
- package/plugins/computer_use/src/verify.ts +219 -0
- package/plugins/computer_use/test/commands.test.ts +73 -0
- package/plugins/cron-runner/plugin.ts +38 -0
- package/plugins/cron-runner/src/commands.ts +373 -0
- package/plugins/cron-runner/src/cronTime.ts +155 -0
- package/plugins/cron-runner/src/lock.ts +79 -0
- package/plugins/cron-runner/src/runs.ts +99 -0
- package/plugins/cron-runner/src/scheduleEngine.ts +76 -0
- package/plugins/cron-runner/src/scheduler.ts +376 -0
- package/plugins/cron-runner/src/schema.ts +139 -0
- package/plugins/cron-runner/src/service.ts +193 -0
- package/plugins/cron-runner/src/store.ts +333 -0
- package/plugins/cron-runner/src/types.ts +141 -0
- package/plugins/cron-runner/test/cronTime.test.ts +41 -0
- package/plugins/cron-runner/test/plugin-integration.test.ts +47 -0
- package/plugins/cron-runner/test/scheduleEngine.test.ts +41 -0
- package/plugins/cron-runner/test/service.test.ts +76 -0
- package/plugins/cron-runner/test/store-and-scheduler.test.ts +501 -0
- package/plugins/workflow-runner/plugin.js +56 -2
- package/plugins/workflow-runner/plugin.ts +113 -0
- package/plugins/workflow-runner/src/agentCommon.js +43 -4
- package/plugins/workflow-runner/src/agentCommon.ts +435 -0
- package/plugins/workflow-runner/src/controlFlow/branch.js +40 -0
- package/plugins/workflow-runner/src/controlFlow/branch.ts +46 -0
- package/plugins/workflow-runner/src/controlFlow/loop.js +211 -0
- package/plugins/workflow-runner/src/controlFlow/loop.ts +248 -0
- package/plugins/workflow-runner/src/controlFlow/pause.js +129 -0
- package/plugins/workflow-runner/src/controlFlow/pause.ts +141 -0
- package/plugins/workflow-runner/src/controlFlow/signal.js +21 -0
- package/plugins/workflow-runner/src/controlFlow/signal.ts +29 -0
- package/plugins/workflow-runner/src/controlFlow/types.js +18 -0
- package/plugins/workflow-runner/src/controlFlow/types.ts +63 -0
- package/plugins/workflow-runner/src/dslManifest.ts +127 -0
- package/plugins/workflow-runner/src/expressions.ts +622 -0
- package/plugins/workflow-runner/src/index.js +13 -4
- package/plugins/workflow-runner/src/index.ts +338 -0
- package/plugins/workflow-runner/src/jsonPayload.ts +84 -0
- package/plugins/workflow-runner/src/loader.js +23 -0
- package/plugins/workflow-runner/src/loader.ts +721 -0
- package/plugins/workflow-runner/src/multimodal.js +2 -1
- package/plugins/workflow-runner/src/multimodal.ts +64 -0
- package/plugins/workflow-runner/src/recovery.ts +149 -0
- package/plugins/workflow-runner/src/runner.js +75 -659
- package/plugins/workflow-runner/src/runner.ts +604 -0
- package/plugins/workflow-runner/src/stepExecutors/agent.ts +234 -0
- package/plugins/workflow-runner/src/stepExecutors/assert.ts +50 -0
- package/plugins/workflow-runner/src/stepExecutors/echo.js +31 -0
- package/plugins/workflow-runner/src/stepExecutors/echo.ts +38 -0
- package/plugins/workflow-runner/src/stepExecutors/llm.ts +133 -0
- package/plugins/workflow-runner/src/stepExecutors/set.js +49 -0
- package/plugins/workflow-runner/src/stepExecutors/set.ts +56 -0
- package/plugins/workflow-runner/src/stepExecutors/skill.js +5 -6
- package/plugins/workflow-runner/src/stepExecutors/skill.ts +140 -0
- package/plugins/workflow-runner/src/stepExecutors/tool.js +80 -8
- package/plugins/workflow-runner/src/stepExecutors/tool.ts +256 -0
- package/plugins/workflow-runner/src/stepExecutors/verify.ts +68 -0
- package/plugins/workflow-runner/src/stepPipeline.js +277 -0
- package/plugins/workflow-runner/src/stepPipeline.ts +366 -0
- package/plugins/workflow-runner/src/taskIdentity.ts +405 -0
- package/plugins/workflow-runner/src/toolRuntime.js +48 -0
- package/plugins/workflow-runner/src/toolRuntime.ts +64 -0
- package/plugins/workflow-runner/src/types.js +37 -1
- package/plugins/workflow-runner/src/types.ts +602 -0
- package/plugins/workflow-runner/src/workflowState.ts +733 -0
- package/plugins/workflow-runner/test/agent.test.ts +587 -0
- package/plugins/workflow-runner/test/agentLlmError.test.ts +373 -0
- package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +65 -0
- package/plugins/workflow-runner/test/captureMisbind.test.ts +99 -0
- package/plugins/workflow-runner/test/cli.e2e.test.ts +147 -0
- package/plugins/workflow-runner/test/context-files.test.ts +320 -0
- package/plugins/workflow-runner/test/e2e.test.ts +370 -0
- package/plugins/workflow-runner/test/engineRobustness.test.ts +226 -0
- package/plugins/workflow-runner/test/expressions.test.ts +397 -0
- package/plugins/workflow-runner/test/foundation.test.ts +126 -0
- package/plugins/workflow-runner/test/graceful.test.ts +139 -0
- package/plugins/workflow-runner/test/greedyInputs.load.test.ts +47 -0
- package/plugins/workflow-runner/test/hostCapability.test.ts +108 -0
- package/plugins/workflow-runner/test/illustrate.load.test.ts +183 -0
- package/plugins/workflow-runner/test/jsonPayload.test.ts +83 -0
- package/plugins/workflow-runner/test/loader.test.ts +617 -0
- package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +33 -0
- package/plugins/workflow-runner/test/multimodal.test.ts +342 -0
- package/plugins/workflow-runner/test/output-schema.test.ts +213 -0
- package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +87 -0
- package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +269 -0
- package/plugins/workflow-runner/test/ppt.load.test.ts +1220 -0
- package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +220 -0
- package/plugins/workflow-runner/test/recovery.test.ts +265 -0
- package/plugins/workflow-runner/test/runner.test.ts +911 -0
- package/plugins/workflow-runner/test/runnerPreflight.test.ts +379 -0
- package/plugins/workflow-runner/test/skillTurnDone.test.ts +71 -0
- package/plugins/workflow-runner/test/stateLifecycle.test.ts +150 -0
- package/plugins/workflow-runner/test/stepPipeline.test.ts +114 -0
- package/plugins/workflow-runner/test/taskArbitration.test.ts +338 -0
- package/plugins/workflow-runner/test/taskIdentity.test.ts +237 -0
- package/plugins/workflow-runner/test/taskLifecycle.test.ts +270 -0
- package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +221 -0
- package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +29 -0
- package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +168 -0
- package/plugins/workflow-runner/test/webppt.load.test.ts +250 -0
- package/plugins/workflow-runner/test/word.load.test.ts +208 -0
- package/plugins/workflow-runner/test/workflows.smoke.test.ts +76 -0
- package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +207 -0
- package/skills/browser-automation/SKILL.md +9 -19
- package/skills/web-crawler/SKILL.md +9 -11
- package/src/askBridge.ts +249 -0
- package/src/bootstrap/cwdArg.js +10 -3
- package/src/bootstrap/cwdArg.ts +31 -0
- package/src/bootstrap/workingDir.ts +48 -0
- package/src/cli/args.js +70 -7
- package/src/cli/args.ts +146 -0
- package/src/cli/computerUse.js +185 -0
- package/src/cli/computerUse.ts +221 -0
- package/src/cli/configMenu.js +274 -202
- package/src/cli/configMenu.tsx +521 -0
- package/src/cli/memoryAccess.js +45 -0
- package/src/cli/memoryAccess.ts +53 -0
- package/src/cli/print.js +119 -5
- package/src/cli/print.ts +597 -0
- package/src/cli/quickModelSetup.js +60 -0
- package/src/cli/quickModelSetup.tsx +96 -0
- package/src/cli/streamJson.js +80 -4
- package/src/cli/streamJson.ts +433 -0
- package/src/cli/wizards/advisorWizard.js +1 -0
- package/src/cli/wizards/advisorWizard.tsx +195 -0
- package/src/cli/wizards/agentRuntimeWizard.js +84 -0
- package/src/cli/wizards/agentRuntimeWizard.tsx +134 -0
- package/src/cli/wizards/browserWizard.js +55 -0
- package/src/cli/wizards/browserWizard.tsx +77 -0
- package/src/cli/wizards/contextAdvisorWizard.js +84 -0
- package/src/cli/wizards/contextAdvisorWizard.tsx +124 -0
- package/src/cli/wizards/fieldForm.js +7 -4
- package/src/cli/wizards/fieldForm.tsx +250 -0
- package/src/cli/wizards/imageWizard.js +4 -5
- package/src/cli/wizards/imageWizard.tsx +96 -0
- package/src/cli/wizards/openRouterWizard.tsx +48 -0
- package/src/cli/wizards/providerPresets.js +1 -8
- package/src/cli/wizards/providerPresets.ts +106 -0
- package/src/cli/wizards/providerWizard.js +152 -205
- package/src/cli/wizards/providerWizard.tsx +266 -0
- package/src/cli/wizards/searchWizard.tsx +47 -0
- package/src/cli/wizards/ttsWizard.js +4 -3
- package/src/cli/wizards/ttsWizard.tsx +61 -0
- package/src/config/configDefaults.js +25 -0
- package/src/config/configDefaults.ts +33 -0
- package/src/config/configDiagnostics.js +117 -0
- package/src/config/configDiagnostics.ts +166 -0
- package/src/config/configFile.js +52 -32
- package/src/config/configFile.ts +633 -0
- package/src/config/configManagement.js +126 -0
- package/src/config/configManagement.ts +159 -0
- package/src/config/configService.js +66 -11
- package/src/config/configService.ts +554 -0
- package/src/config/numericLimits.js +61 -0
- package/src/config/numericLimits.ts +80 -0
- package/src/config.ts +109 -0
- package/src/context/agentHome.ts +11 -0
- package/src/context/archive.ts +144 -0
- package/src/context/budgetPlan.js +54 -0
- package/src/context/budgetPlan.ts +88 -0
- package/src/context/compact.js +179 -106
- package/src/context/compact.ts +584 -0
- package/src/context/contextBundle.js +119 -0
- package/src/context/contextBundle.ts +176 -0
- package/src/context/contextLock.ts +84 -0
- package/src/context/microCompactLite.ts +218 -0
- package/src/context/persistContext.ts +177 -0
- package/src/context/reactiveCompact.js +19 -4
- package/src/context/reactiveCompact.ts +240 -0
- package/src/context/recentDirs.ts +42 -0
- package/src/context/sessionPath.ts +206 -0
- package/src/context/sessionRegistry.js +8 -2
- package/src/context/sessionRegistry.ts +414 -0
- package/src/context/snipCompact.ts +163 -0
- package/src/context/tokenCounter.ts +106 -0
- package/src/context/workspaceIndex.js +2 -2
- package/src/context/workspaceIndex.ts +751 -0
- package/src/entry.compiled.tsx +20 -0
- package/src/harness/claimValidation.js +9 -0
- package/src/harness/claimValidation.ts +22 -0
- package/src/harness/evidenceLedger.js +92 -0
- package/src/harness/evidenceLedger.ts +96 -0
- package/src/harness/stallGuard.js +60 -0
- package/src/harness/stallGuard.ts +81 -0
- package/src/humanIntervention.js +129 -0
- package/src/humanIntervention.ts +216 -0
- package/src/infra/verification.ts +295 -0
- package/src/irreversible/rules.js +216 -0
- package/src/irreversible/rules.ts +261 -0
- package/src/llm/client.js +40 -3
- package/src/llm/client.ts +621 -0
- package/src/llm/promptCache.js +27 -0
- package/src/llm/promptCache.ts +41 -0
- package/src/llm/providers/anthropicFormat.js +41 -5
- package/src/llm/providers/anthropicFormat.ts +290 -0
- package/src/llm/providers/openaiFormat.js +186 -8
- package/src/llm/providers/openaiFormat.ts +428 -0
- package/src/loop.js +614 -63
- package/src/loop.ts +1454 -0
- package/src/main.js +67 -10
- package/src/main.tsx +344 -0
- package/src/memory/codec.js +204 -0
- package/src/memory/codec.ts +249 -0
- package/src/memory/constants.js +34 -0
- package/src/memory/constants.ts +50 -0
- package/src/memory/episodicMemory.js +684 -0
- package/src/memory/episodicMemory.ts +815 -0
- package/src/memory/fileStore.js +148 -0
- package/src/memory/fileStore.ts +184 -0
- package/src/memory/memoryService.js +570 -0
- package/src/memory/memoryService.ts +859 -0
- package/src/memory/migration.js +128 -0
- package/src/memory/migration.ts +160 -0
- package/src/memory/repository.js +789 -0
- package/src/memory/repository.ts +893 -0
- package/src/memory/retrieval.js +108 -0
- package/src/memory/retrieval.ts +145 -0
- package/src/memory/searchIndex.js +107 -0
- package/src/memory/searchIndex.ts +153 -0
- package/src/memory/topicView.js +82 -0
- package/src/memory/topicView.ts +95 -0
- package/src/memory/turnJournal.js +95 -0
- package/src/memory/turnJournal.ts +120 -0
- package/src/memory/types.js +2 -0
- package/src/memory/types.ts +186 -0
- package/src/messageQueue.ts +123 -0
- package/src/multimodal.js +128 -46
- package/src/multimodal.ts +349 -0
- package/src/plugin-sdk.js +21 -1
- package/src/plugin-sdk.ts +134 -0
- package/src/plugins/builtinPluginIds.js +47 -0
- package/src/plugins/builtinPluginIds.ts +51 -0
- package/src/plugins/builtinRegistry.ts +43 -0
- package/src/plugins/commandRouter.js +40 -26
- package/src/plugins/commandRouter.ts +261 -0
- package/src/plugins/hookEngine.ts +341 -0
- package/src/plugins/pluginApi.ts +133 -0
- package/src/plugins/pluginLifecycle.ts +34 -0
- package/src/plugins/pluginLoader.ts +147 -0
- package/src/plugins/pluginManifest.js +127 -0
- package/src/plugins/pluginManifest.ts +152 -0
- package/src/plugins/pluginRunner.js +47 -2
- package/src/plugins/pluginRunner.ts +207 -0
- package/src/plugins/transcript.ts +208 -0
- package/src/prompts/lint.js +169 -0
- package/src/prompts/lint.ts +220 -0
- package/src/prompts/pluginList.js +32 -16
- package/src/prompts/pluginList.ts +86 -0
- package/src/prompts/policyRegistry.js +318 -0
- package/src/prompts/policyRegistry.ts +358 -0
- package/src/prompts/projectInstructions.js +24 -0
- package/src/prompts/projectInstructions.ts +81 -0
- package/src/prompts/promptAssembly.js +311 -202
- package/src/prompts/promptAssembly.ts +510 -0
- package/src/prompts/skillList.js +106 -45
- package/src/prompts/skillList.ts +198 -0
- package/src/prompts/system.js +31 -6
- package/src/prompts/system.ts +81 -0
- package/src/runtime/agentRuntimeContext.js +53 -0
- package/src/runtime/agentRuntimeContext.ts +112 -0
- package/src/session/runAgentTurn.js +71 -12
- package/src/session/runAgentTurn.ts +181 -0
- package/src/session/runTurn.js +29 -0
- package/src/session/runTurn.ts +160 -0
- package/src/session/runtimeStore.js +149 -0
- package/src/session/runtimeStore.ts +197 -0
- package/src/session/sessionState.js +79 -3
- package/src/session/sessionState.ts +134 -0
- package/src/toolGate.ts +50 -0
- package/src/tools/advisor/advisor.js +76 -15
- package/src/tools/advisor/advisor.ts +512 -0
- package/src/tools/agent/agent.js +245 -29
- package/src/tools/agent/agent.ts +837 -0
- package/src/tools/agent/agentTaskService.js +60 -0
- package/src/tools/agent/agentTaskService.ts +113 -0
- package/src/tools/agent/agentTypes.js +20 -8
- package/src/tools/agent/agentTypes.ts +94 -0
- package/src/tools/agent/coordinator.ts +111 -0
- package/src/tools/agent/worktree.ts +296 -0
- package/src/tools/ask/ask.js +17 -0
- package/src/tools/ask/ask.ts +122 -0
- package/src/tools/bash/attachImage.js +223 -0
- package/src/tools/bash/attachImage.ts +281 -0
- package/src/tools/bash/bash.js +132 -14
- package/src/tools/bash/bash.ts +642 -0
- package/src/tools/bash/semantics.ts +103 -0
- package/src/tools/bash/warnings.js +17 -11
- package/src/tools/bash/warnings.ts +117 -0
- package/src/tools/capabilities.js +42 -0
- package/src/tools/capabilities.ts +69 -0
- package/src/tools/computeruse/accessibilityPermission.js +261 -0
- package/src/tools/computeruse/accessibilityPermission.ts +294 -0
- package/src/tools/computeruse/axSearch.js +96 -0
- package/src/tools/computeruse/axSearch.ts +120 -0
- package/src/tools/computeruse/axSnap.js +272 -0
- package/src/tools/computeruse/axSnap.ts +349 -0
- package/src/tools/computeruse/capabilityLabels.js +95 -0
- package/src/tools/computeruse/capabilityLabels.ts +115 -0
- package/src/tools/computeruse/computerUseService.js +2235 -0
- package/src/tools/computeruse/computerUseService.ts +2686 -0
- package/src/tools/computeruse/computeruse.js +2742 -0
- package/src/tools/computeruse/computeruse.ts +3265 -0
- package/src/tools/computeruse/diagnosticTrace.js +154 -0
- package/src/tools/computeruse/diagnosticTrace.ts +195 -0
- package/src/tools/computeruse/diagnostics.js +369 -0
- package/src/tools/computeruse/diagnostics.ts +453 -0
- package/src/tools/computeruse/grants.js +53 -0
- package/src/tools/computeruse/grants.ts +70 -0
- package/src/tools/computeruse/humanBoundary.js +159 -0
- package/src/tools/computeruse/humanBoundary.ts +199 -0
- package/src/tools/computeruse/intervention.js +77 -0
- package/src/tools/computeruse/intervention.ts +110 -0
- package/src/tools/computeruse/manualSchema.js +709 -0
- package/src/tools/computeruse/manualSchema.ts +916 -0
- package/src/tools/computeruse/observationImages.js +705 -0
- package/src/tools/computeruse/observationImages.ts +889 -0
- package/src/tools/computeruse/protocol.js +60 -0
- package/src/tools/computeruse/protocol.ts +515 -0
- package/src/tools/computeruse/telemetryLog.js +57 -0
- package/src/tools/computeruse/telemetryLog.ts +67 -0
- package/src/tools/computeruse/vision/appGuide.js +325 -0
- package/src/tools/computeruse/vision/appGuide.ts +482 -0
- package/src/tools/computeruse/vision/focus.js +291 -0
- package/src/tools/computeruse/vision/focus.ts +382 -0
- package/src/tools/computeruse/vision/frames.js +248 -0
- package/src/tools/computeruse/vision/frames.ts +329 -0
- package/src/tools/computeruse/vision/geometry.js +131 -0
- package/src/tools/computeruse/vision/geometry.ts +163 -0
- package/src/tools/computeruse/vision/imaging.js +201 -0
- package/src/tools/computeruse/vision/imaging.ts +281 -0
- package/src/tools/computeruse/vision/png.js +274 -0
- package/src/tools/computeruse/vision/png.ts +317 -0
- package/src/tools/computeruse/vision/raster.js +320 -0
- package/src/tools/computeruse/vision/raster.ts +408 -0
- package/src/tools/computeruse/vision/settle.js +131 -0
- package/src/tools/computeruse/vision/settle.ts +220 -0
- package/src/tools/computeruse/vision/telemetry.js +196 -0
- package/src/tools/computeruse/vision/telemetry.ts +241 -0
- package/src/tools/computeruse/visionOcr.js +115 -0
- package/src/tools/computeruse/visionOcr.ts +128 -0
- package/src/tools/computeruse/waitFor.js +237 -0
- package/src/tools/computeruse/waitFor.ts +291 -0
- package/src/tools/download/download.js +10 -6
- package/src/tools/download/download.ts +187 -0
- package/src/tools/edit/edit.js +30 -18
- package/src/tools/edit/edit.ts +349 -0
- package/src/tools/edit/multi-edit.js +25 -14
- package/src/tools/edit/multi-edit.ts +223 -0
- package/src/tools/effectiveToolSet.js +73 -0
- package/src/tools/effectiveToolSet.ts +91 -0
- package/src/tools/genimage/genimage.ts +257 -0
- package/src/tools/genspeech/genspeech.ts +83 -0
- package/src/tools/glob/glob.js +176 -29
- package/src/tools/glob/glob.ts +283 -0
- package/src/tools/grep/grep.js +61 -19
- package/src/tools/grep/grep.ts +239 -0
- package/src/tools/grep/rgPath.ts +206 -0
- package/src/tools/index.js +99 -5
- package/src/tools/index.ts +293 -0
- package/src/tools/lsp/config.js +113 -0
- package/src/tools/lsp/config.ts +113 -0
- package/src/tools/lsp/lsp.js +256 -0
- package/src/tools/lsp/lsp.ts +274 -0
- package/src/tools/lsp/service.js +303 -0
- package/src/tools/lsp/service.ts +296 -0
- package/src/tools/memory/memory.js +520 -0
- package/src/tools/memory/memory.ts +625 -0
- package/src/tools/memory/policy.js +53 -0
- package/src/tools/memory/policy.ts +72 -0
- package/src/tools/notebook/notebookEdit.js +114 -0
- package/src/tools/notebook/notebookEdit.ts +126 -0
- package/src/tools/powershell/powershell.js +210 -0
- package/src/tools/powershell/powershell.ts +239 -0
- package/src/tools/presentresult/presentresult.js +145 -0
- package/src/tools/presentresult/presentresult.ts +156 -0
- package/src/tools/read/read.js +371 -163
- package/src/tools/read/read.ts +558 -0
- package/src/tools/shared/diffSummary.js +44 -0
- package/src/tools/shared/diffSummary.ts +63 -0
- package/src/tools/shared/fileActivity.js +51 -0
- package/src/tools/shared/fileActivity.ts +66 -0
- package/src/tools/shared/fileMutationBus.js +13 -0
- package/src/tools/shared/fileMutationBus.ts +14 -0
- package/src/tools/shared/fileState.js +73 -65
- package/src/tools/shared/fileState.ts +145 -0
- package/src/tools/shared/fileUtils.js +81 -4
- package/src/tools/shared/fileUtils.ts +504 -0
- package/src/tools/shared/killTree.ts +50 -0
- package/src/tools/shared/permanentDeleteGuard.js +26 -0
- package/src/tools/shared/permanentDeleteGuard.ts +34 -0
- package/src/tools/shared/schemas.ts +20 -0
- package/src/tools/shared/toolOutputStore.js +97 -0
- package/src/tools/shared/toolOutputStore.ts +110 -0
- package/src/tools/skill/skill.js +86 -0
- package/src/tools/skill/skill.ts +94 -0
- package/src/tools/snip/snip.js +67 -0
- package/src/tools/snip/snip.ts +80 -0
- package/src/tools/tasks/backgroundTaskService.js +275 -0
- package/src/tools/tasks/backgroundTaskService.ts +369 -0
- package/src/tools/tasks/processEvidence.js +24 -0
- package/src/tools/tasks/processEvidence.ts +34 -0
- package/src/tools/tasks/taskManagement.js +163 -0
- package/src/tools/tasks/taskManagement.ts +180 -0
- package/src/tools/tasks/taskOutput.js +113 -0
- package/src/tools/tasks/taskOutput.ts +145 -0
- package/src/tools/tasks/taskStop.js +74 -0
- package/src/tools/tasks/taskStop.ts +99 -0
- package/src/tools/tasks/taskStore.js +46 -0
- package/src/tools/tasks/taskStore.ts +77 -0
- package/src/tools/terminal/terminalCapture.js +167 -0
- package/src/tools/terminal/terminalCapture.ts +179 -0
- package/src/tools/trash/trash.js +233 -0
- package/src/tools/trash/trash.ts +283 -0
- package/src/tools/types.js +1 -1
- package/src/tools/types.ts +24 -0
- package/src/tools/webbrowser/agentBrowserPath.ts +286 -0
- package/src/tools/webbrowser/browser.js +214 -11
- package/src/tools/webbrowser/browser.ts +293 -0
- package/src/tools/webbrowser/browserControl.js +153 -48
- package/src/tools/webbrowser/browserControl.ts +262 -0
- package/src/tools/webbrowser/browserDaemon.js +147 -39
- package/src/tools/webbrowser/browserDaemon.ts +270 -0
- package/src/tools/webbrowser/browserOutcome.js +273 -0
- package/src/tools/webbrowser/browserOutcome.ts +306 -0
- package/src/tools/webbrowser/browserRunRegistry.js +150 -0
- package/src/tools/webbrowser/browserRunRegistry.ts +179 -0
- package/src/tools/webbrowser/browserService.js +20 -6
- package/src/tools/webbrowser/browserService.ts +56 -0
- package/src/tools/webbrowser/browserStream.js +30 -1
- package/src/tools/webbrowser/browserStream.ts +216 -0
- package/src/tools/webbrowser/browserTabs.js +143 -0
- package/src/tools/webbrowser/browserTabs.ts +210 -0
- package/src/tools/webbrowser/webbrowser.js +831 -150
- package/src/tools/webbrowser/webbrowser.ts +1537 -0
- package/src/tools/webfetch/preapproved.ts +274 -0
- package/src/tools/webfetch/webfetch.js +24 -23
- package/src/tools/webfetch/webfetch.ts +383 -0
- package/src/tools/websearch/websearch.js +12 -11
- package/src/tools/websearch/websearch.ts +292 -0
- package/src/tools/worktree/sessionWorktree.js +128 -0
- package/src/tools/worktree/sessionWorktree.ts +158 -0
- package/src/tools/write/write.js +27 -44
- package/src/tools/write/write.ts +136 -0
- package/src/types.ts +960 -0
- package/src/ui/App.js +216 -12
- package/src/ui/App.tsx +879 -0
- package/src/ui/AskQuestion.tsx +300 -0
- package/src/ui/InputBox.js +77 -1
- package/src/ui/InputBox.tsx +567 -0
- package/src/ui/LiveArea.tsx +344 -0
- package/src/ui/MessageList.js +27 -6
- package/src/ui/MessageList.tsx +559 -0
- package/src/ui/ModelPicker.tsx +107 -0
- package/src/ui/QueuedMessagesBanner.tsx +51 -0
- package/src/ui/Root.js +6 -8
- package/src/ui/Root.tsx +100 -0
- package/src/ui/SessionPicker.tsx +169 -0
- package/src/ui/StatusLine.js +22 -1
- package/src/ui/StatusLine.tsx +145 -0
- package/src/ui/WorkspacePicker.tsx +84 -0
- package/src/ui/advisorCommand.js +54 -0
- package/src/ui/advisorCommand.ts +63 -0
- package/src/ui/computerCommand.js +19 -0
- package/src/ui/computerCommand.ts +35 -0
- package/src/ui/figures.ts +45 -0
- package/src/ui/hooks/askSlot.ts +112 -0
- package/src/ui/hooks/useChat.js +271 -7
- package/src/ui/hooks/useChat.ts +1578 -0
- package/src/ui/hooks/useInputHistory.ts +235 -0
- package/src/ui/hooks/usePasteHandler.ts +220 -0
- package/src/ui/hooks/useTerminalSize.ts +41 -0
- package/src/ui/hooks/useTextBuffer.ts +108 -0
- package/src/ui/hooks/useTokenUsage.ts +44 -0
- package/src/ui/liveViewport.ts +189 -0
- package/src/ui/markdown.ts +230 -0
- package/src/ui/textBuffer.ts +239 -0
- package/src/ui/theme.ts +35 -0
- package/src/utils/clipboardImage.js +358 -0
- package/src/utils/clipboardImage.ts +420 -0
- package/src/utils/debugLog.ts +50 -0
- package/src/utils/greenRoot.ts +35 -0
- package/src/utils/packageRoot.ts +40 -0
- package/src/utils/pathContains.js +28 -0
- package/src/utils/pathContains.ts +31 -0
- package/src/utils/resourcePaths.ts +71 -0
- package/src/utils/stripThink.ts +49 -0
- package/src/utils/zodToJson.ts +73 -0
- package/src/web/browserBridge.js +365 -66
- package/src/web/browserBridge.ts +672 -0
- package/src/web/protocol.ts +1804 -0
- package/vendor/computer-use/arm64-darwin/cu-helperd +0 -0
- package/workflows/ppt.yaml +13 -2
- package/workflows/wechat-reading-shots.yaml +315 -0
- package/workflows/word.yaml +11 -1
- package/skills/docx/scripts/office/helpers/__pycache__/__init__.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/helpers/__pycache__/merge_runs.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/helpers/__pycache__/simplify_redlines.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/__init__.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/base.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/docx.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/pptx.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/redlining.cpython-314.pyc +0 -0
- package/skills/image-stats/scripts/__pycache__/image_stats.cpython-314.pyc +0 -0
- package/skills/image-stats/scripts/__pycache__/image_stats_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/assemble_material.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/assemble_material_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/chart_sanity_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/check_language_policy.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/check_ui_artifact.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/check_ui_artifact_pptx_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/deck_pages_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/deck_pages_check_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/deck_visual_style_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/deck_visual_style_check_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_budget_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_budget_check_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_repair_hints.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_repair_hints_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_style_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_style_check_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/draft_coverage_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/extract_source_assets.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/extract_source_assets_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/generated_image_review_collect.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/generated_image_review_collect_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/image_plan_lint.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/image_plan_lint_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/image_prompt_rewrite.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/image_prompt_rewrite_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/layout_balance.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/layout_balance_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/normalize_design_json.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/normalize_design_json_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/plan_source_layout.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/plan_source_layout_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/resolve_source_hint.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/resolve_source_hint_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/resolve_source_input.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/resolve_source_input_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/scaffold_ui_artifact.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/source_usage_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/source_usage_check_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/text_readability_pixel.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/visual_quality_gate.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/visual_quality_gate_test.cpython-314.pyc +0 -0
- /package/skills/ai-image/scripts/{generate_test.mjs → generate.selftest.mjs} +0 -0
- /package/skills/ai-image/scripts/{generate_from_plan_test.mjs → generate_from_plan.selftest.mjs} +0 -0
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ============================================================
|
|
3
|
+
* src/tools/webfetch.ts —— WebFetch 工具(获取 URL 内容)
|
|
4
|
+
* ------------------------------------------------------------
|
|
5
|
+
* 获取 URL → HTML 转 Markdown
|
|
6
|
+
*
|
|
7
|
+
* 输入:
|
|
8
|
+
* url 必填,要获取内容的 URL
|
|
9
|
+
* prompt 可选,旧版兼容字段,运行时忽略
|
|
10
|
+
*
|
|
11
|
+
* 输出:
|
|
12
|
+
* { bytes, code, codeText, result, durationMs, url }
|
|
13
|
+
*
|
|
14
|
+
* 流程:
|
|
15
|
+
* 1. URL 验证(合法格式、2000字符以内、无凭据)
|
|
16
|
+
* 2. fetch(自动 http→https,超时 60s)
|
|
17
|
+
* 3. 检测跨 host 重定向,返回提示而非自动跟随
|
|
18
|
+
* 4. HTML → Markdown(turndown);非 HTML 原样返回
|
|
19
|
+
* 5. 输出截断到 30K chars(超长内容直接截断)
|
|
20
|
+
* ============================================================
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { z } from 'zod';
|
|
24
|
+
|
|
25
|
+
import type { Tool, ToolResult } from '../../types.js';
|
|
26
|
+
import { DEFAULT_MAX_RESULT_SIZE_CHARS } from '../types.js';
|
|
27
|
+
import { toToolParameters } from '../../utils/zodToJson.js';
|
|
28
|
+
import { isPreapprovedDomain } from './preapproved.js';
|
|
29
|
+
|
|
30
|
+
// ---------------- 1. 常量 ----------------
|
|
31
|
+
const MAX_URL_LENGTH = 2000;
|
|
32
|
+
const FETCH_TIMEOUT_MS = 60_000;
|
|
33
|
+
const MAX_HTTP_CONTENT_LENGTH = 10 * 1024 * 1024;
|
|
34
|
+
const MAX_REDIRECTS = 10;
|
|
35
|
+
|
|
36
|
+
// ---------------- 2. LRU 缓存 ----------------
|
|
37
|
+
type CacheEntry = {
|
|
38
|
+
bytes: number;
|
|
39
|
+
code: number;
|
|
40
|
+
codeText: string;
|
|
41
|
+
content: string;
|
|
42
|
+
contentType: string;
|
|
43
|
+
fetchedAt: number;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const URL_CACHE = new Map<string, CacheEntry>();
|
|
47
|
+
const CACHE_TTL_MS = 15 * 60 * 1000;
|
|
48
|
+
const MAX_CACHE_SIZE_BYTES = 50 * 1024 * 1024;
|
|
49
|
+
|
|
50
|
+
function cleanCache(): void {
|
|
51
|
+
const now = Date.now();
|
|
52
|
+
let totalSize = 0;
|
|
53
|
+
const entries: Array<{ url: string; entry: CacheEntry; size: number }> = [];
|
|
54
|
+
|
|
55
|
+
for (const [url, entry] of URL_CACHE) {
|
|
56
|
+
if (now - entry.fetchedAt > CACHE_TTL_MS) {
|
|
57
|
+
URL_CACHE.delete(url);
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
const size = entry.bytes;
|
|
61
|
+
totalSize += size;
|
|
62
|
+
entries.push({ url, entry, size });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (totalSize > MAX_CACHE_SIZE_BYTES) {
|
|
66
|
+
entries.sort((a, b) => a.entry.fetchedAt - b.entry.fetchedAt);
|
|
67
|
+
for (const { url, size } of entries) {
|
|
68
|
+
URL_CACHE.delete(url);
|
|
69
|
+
totalSize -= size;
|
|
70
|
+
if (totalSize <= MAX_CACHE_SIZE_BYTES * 0.8) break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ---------------- 3. Zod 输入 schema ----------------
|
|
76
|
+
const inputSchema = z.object({
|
|
77
|
+
url: z.string().describe('要获取内容的 URL'),
|
|
78
|
+
/** @deprecated Accepted for callers compiled against the legacy contract. */
|
|
79
|
+
prompt: z.string().optional(),
|
|
80
|
+
});
|
|
81
|
+
type WebFetchInput = z.infer<typeof inputSchema>;
|
|
82
|
+
|
|
83
|
+
// Model-visible v2 contract. WebFetch returns the page body and does not run a
|
|
84
|
+
// hidden extraction model; the runtime schema still accepts legacy `prompt`.
|
|
85
|
+
const parameters = toToolParameters(z.object({
|
|
86
|
+
url: z.string().describe('要读取正文的已知 URL'),
|
|
87
|
+
}));
|
|
88
|
+
|
|
89
|
+
// ---------------- 4. Description ----------------
|
|
90
|
+
const description = `Reads the full text content of a known URL without opening a browser.
|
|
91
|
+
- Takes a URL, fetches its response body, and converts HTML to Markdown.
|
|
92
|
+
- Returns page content directly; it does not call another model or perform hidden summarization or extraction.
|
|
93
|
+
- Use it to inspect a selected source after search, or to read a known static page.
|
|
94
|
+
- It does not discover sources, authenticate, click, upload, or operate an interactive page.
|
|
95
|
+
- HTTP URLs are automatically upgraded to HTTPS.
|
|
96
|
+
- When a URL redirects to a different host, returns a warning with the redirect URL.
|
|
97
|
+
- This tool is read-only and does not modify any files.
|
|
98
|
+
- Very large results may be truncated with an explicit marker.
|
|
99
|
+
- ⚠️ IMPORTANT: This tool WILL FAIL for authenticated or private URLs.
|
|
100
|
+
Do not claim access to private content when the current tool catalog does not
|
|
101
|
+
contain an authenticated integration for that service.
|
|
102
|
+
- If a research source cannot be fetched, choose another source or continue searching; report the limitation when no readable source remains.
|
|
103
|
+
- 💡 For GitHub URLs (repos, issues, PRs), prefer using the \`gh\` CLI via Bash
|
|
104
|
+
instead (e.g. \`gh pr view <pr-number>\`, \`gh issue view <number>\`, \`gh api <endpoint>\`).
|
|
105
|
+
- The preapproved domain list controls network routing only; it is not an
|
|
106
|
+
endorsement of page accuracy. Judge source quality from the source itself.
|
|
107
|
+
- 📝 This tool includes a self-cleaning 15-minute cache for faster repeated access
|
|
108
|
+
to the same URL.
|
|
109
|
+
- ⚠️ For PDF files, the tool will attempt to extract readable text but results may
|
|
110
|
+
be limited. Binary images cannot be processed.`;
|
|
111
|
+
|
|
112
|
+
// ---------------- 5. 辅助函数 ----------------
|
|
113
|
+
|
|
114
|
+
// ---------------- 6. call() 实现 ----------------
|
|
115
|
+
|
|
116
|
+
/** 验证 URL */
|
|
117
|
+
function validateURL(url: string): { ok: true; parsed: URL } | { ok: false; error: string } {
|
|
118
|
+
if (url.length > MAX_URL_LENGTH) {
|
|
119
|
+
return { ok: false, error: `URL 太长(最大 ${MAX_URL_LENGTH} 字符)` };
|
|
120
|
+
}
|
|
121
|
+
let parsed: URL;
|
|
122
|
+
try {
|
|
123
|
+
parsed = new URL(url);
|
|
124
|
+
} catch {
|
|
125
|
+
return { ok: false, error: `无效的 URL 格式` };
|
|
126
|
+
}
|
|
127
|
+
if (parsed.username || parsed.password) {
|
|
128
|
+
return { ok: false, error: `URL 不能包含用户名或密码` };
|
|
129
|
+
}
|
|
130
|
+
return { ok: true, parsed };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** 获取 URL 内容(返回 HTML 字符串或重定向信息) */
|
|
134
|
+
async function fetchURL(
|
|
135
|
+
url: string,
|
|
136
|
+
signal: AbortSignal,
|
|
137
|
+
depth = 0,
|
|
138
|
+
): Promise<
|
|
139
|
+
| { type: 'success'; content: string; bytes: number; code: number; codeText: string; contentType: string }
|
|
140
|
+
| { type: 'redirect'; originalUrl: string; redirectUrl: string; statusCode: number }
|
|
141
|
+
| { type: 'error'; error: string }
|
|
142
|
+
> {
|
|
143
|
+
const validated = validateURL(url);
|
|
144
|
+
if (!validated.ok) return { type: 'error', error: validated.error };
|
|
145
|
+
|
|
146
|
+
let targetUrl = url;
|
|
147
|
+
const parsed = validated.parsed;
|
|
148
|
+
|
|
149
|
+
if (parsed.protocol === 'http:') {
|
|
150
|
+
parsed.protocol = 'https:';
|
|
151
|
+
targetUrl = parsed.toString();
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
let response: Response;
|
|
155
|
+
try {
|
|
156
|
+
const timeoutSignal = AbortSignal.timeout(FETCH_TIMEOUT_MS);
|
|
157
|
+
const controller = new AbortController();
|
|
158
|
+
const combinedSignal = signal
|
|
159
|
+
? AbortSignal.any([signal, timeoutSignal])
|
|
160
|
+
: timeoutSignal;
|
|
161
|
+
|
|
162
|
+
response = await fetch(targetUrl, {
|
|
163
|
+
signal: combinedSignal,
|
|
164
|
+
headers: {
|
|
165
|
+
Accept: 'text/markdown, text/html, */*',
|
|
166
|
+
'User-Agent': 'minimal-agent/1.0',
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
} catch (e) {
|
|
170
|
+
if (signal?.aborted) return { type: 'error', error: '请求被中断' };
|
|
171
|
+
return { type: 'error', error: `网络请求失败:${(e as Error).message}` };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const code = response.status;
|
|
175
|
+
const codeText = response.statusText;
|
|
176
|
+
const contentType = response.headers.get('content-type') ?? '';
|
|
177
|
+
|
|
178
|
+
const location = response.headers.get('location');
|
|
179
|
+
if (location && [301, 302, 307, 308].includes(code)) {
|
|
180
|
+
const redirectUrl = new URL(location, targetUrl).toString();
|
|
181
|
+
const originalHost = new URL(url).hostname;
|
|
182
|
+
const redirectHost = new URL(redirectUrl).hostname;
|
|
183
|
+
|
|
184
|
+
const stripWww = (h: string) => h.replace(/^www\./, '');
|
|
185
|
+
if (stripWww(originalHost) !== stripWww(redirectHost)) {
|
|
186
|
+
return {
|
|
187
|
+
type: 'redirect',
|
|
188
|
+
originalUrl: url,
|
|
189
|
+
redirectUrl,
|
|
190
|
+
statusCode: code,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (depth >= MAX_REDIRECTS) {
|
|
195
|
+
return { type: 'error', error: `重定向循环超过限制(最多 ${MAX_REDIRECTS} 次)` };
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return fetchURL(redirectUrl, signal, depth + 1);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// 读取内容(限制 10MB)
|
|
202
|
+
let rawBuffer: ArrayBuffer;
|
|
203
|
+
try {
|
|
204
|
+
rawBuffer = await response.arrayBuffer();
|
|
205
|
+
} catch (e) {
|
|
206
|
+
return { type: 'error', error: `读取响应体失败:${(e as Error).message}` };
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (rawBuffer.byteLength > MAX_HTTP_CONTENT_LENGTH) {
|
|
210
|
+
return { type: 'error', error: `内容太大(${rawBuffer.byteLength} bytes,超过 ${MAX_HTTP_CONTENT_LENGTH})` };
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// 解码
|
|
214
|
+
let content: string;
|
|
215
|
+
try {
|
|
216
|
+
const decoder = new TextDecoder('utf-8', { fatal: false });
|
|
217
|
+
content = decoder.decode(rawBuffer);
|
|
218
|
+
} catch (e) {
|
|
219
|
+
return { type: 'error', error: `解码失败:${(e as Error).message}` };
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return { type: 'success', content, bytes: rawBuffer.byteLength, code, codeText, contentType };
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/** HTML 转 Markdown */
|
|
226
|
+
async function htmlToMarkdown(html: string): Promise<string> {
|
|
227
|
+
// 动态 import turndown(~1.4MB,按需加载)
|
|
228
|
+
const TurndownService = (await import('turndown')).default;
|
|
229
|
+
const td = new TurndownService();
|
|
230
|
+
return td.turndown(html);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// ---------------- 6. call() 实现 ----------------
|
|
234
|
+
async function call(
|
|
235
|
+
input: WebFetchInput,
|
|
236
|
+
signal?: AbortSignal,
|
|
237
|
+
): Promise<ToolResult> {
|
|
238
|
+
const { url } = input;
|
|
239
|
+
const start = Date.now();
|
|
240
|
+
const cacheKey = url;
|
|
241
|
+
|
|
242
|
+
let targetHostname: string;
|
|
243
|
+
try {
|
|
244
|
+
targetHostname = new URL(url).hostname;
|
|
245
|
+
} catch {
|
|
246
|
+
targetHostname = '';
|
|
247
|
+
}
|
|
248
|
+
const preapproved = isPreapprovedDomain(targetHostname);
|
|
249
|
+
|
|
250
|
+
// 检查缓存
|
|
251
|
+
const cached = URL_CACHE.get(cacheKey);
|
|
252
|
+
if (cached && Date.now() - cached.fetchedAt <= CACHE_TTL_MS) {
|
|
253
|
+
let content = cached.content;
|
|
254
|
+
const contentType = cached.contentType;
|
|
255
|
+
|
|
256
|
+
if (contentType.includes('text/html')) {
|
|
257
|
+
try {
|
|
258
|
+
content = await htmlToMarkdown(content);
|
|
259
|
+
} catch (e) {
|
|
260
|
+
console.warn(`turndown 失败: ${(e as Error).message}`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const formattedSize = cached.bytes < 1024
|
|
265
|
+
? `${cached.bytes} B`
|
|
266
|
+
: cached.bytes < 1024 * 1024
|
|
267
|
+
? `${(cached.bytes / 1024).toFixed(1)} KB`
|
|
268
|
+
: `${(cached.bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
269
|
+
|
|
270
|
+
const domainNote = preapproved
|
|
271
|
+
? '[网络访问:预批准域名]'
|
|
272
|
+
: '[网络访问:普通域名;请按来源本身评估证据质量]';
|
|
273
|
+
|
|
274
|
+
const output = `【WebFetch 结果】
|
|
275
|
+
URL: ${url}
|
|
276
|
+
状态: ${cached.code} ${cached.codeText}
|
|
277
|
+
大小: ${formattedSize}
|
|
278
|
+
耗时: 0.00s (缓存命中)
|
|
279
|
+
${domainNote}
|
|
280
|
+
[📦 来自缓存(15分钟 TTL)]
|
|
281
|
+
|
|
282
|
+
--- 内容 ---
|
|
283
|
+
${content}`;
|
|
284
|
+
|
|
285
|
+
let final = output;
|
|
286
|
+
if (final.length > DEFAULT_MAX_RESULT_SIZE_CHARS) {
|
|
287
|
+
final = final.slice(0, DEFAULT_MAX_RESULT_SIZE_CHARS) + `\n\n... (输出超过 ${DEFAULT_MAX_RESULT_SIZE_CHARS} 字符,已截断)`;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return { ok: true, content: final };
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// 1. fetch
|
|
294
|
+
const fetched = await fetchURL(url, signal ?? new AbortController().signal);
|
|
295
|
+
const durationMs = Date.now() - start;
|
|
296
|
+
|
|
297
|
+
if (fetched.type === 'redirect') {
|
|
298
|
+
const statusText =
|
|
299
|
+
fetched.statusCode === 301 ? 'Moved Permanently' :
|
|
300
|
+
fetched.statusCode === 308 ? 'Permanent Redirect' :
|
|
301
|
+
fetched.statusCode === 307 ? 'Temporary Redirect' : 'Found';
|
|
302
|
+
|
|
303
|
+
return {
|
|
304
|
+
ok: true,
|
|
305
|
+
content: `【重定向检测】
|
|
306
|
+
|
|
307
|
+
原始 URL: ${fetched.originalUrl}
|
|
308
|
+
重定向到: ${fetched.redirectUrl}
|
|
309
|
+
状态: ${fetched.statusCode} ${statusText}
|
|
310
|
+
|
|
311
|
+
请使用重定向后的 URL 再次调用 WebFetch 工具。`,
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (fetched.type === 'error') {
|
|
316
|
+
return { ok: false, error: fetched.error };
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
let { content, bytes, code, codeText, contentType } = fetched;
|
|
320
|
+
|
|
321
|
+
// 写入缓存
|
|
322
|
+
URL_CACHE.set(cacheKey, {
|
|
323
|
+
bytes,
|
|
324
|
+
code,
|
|
325
|
+
codeText,
|
|
326
|
+
content,
|
|
327
|
+
contentType,
|
|
328
|
+
fetchedAt: Date.now(),
|
|
329
|
+
});
|
|
330
|
+
cleanCache();
|
|
331
|
+
|
|
332
|
+
// 2. HTML → Markdown
|
|
333
|
+
if (contentType.includes('text/html')) {
|
|
334
|
+
try {
|
|
335
|
+
content = await htmlToMarkdown(content);
|
|
336
|
+
} catch (e) {
|
|
337
|
+
console.warn(`turndown 失败: ${(e as Error).message}`);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// 3. 内容直接返回(超长内容在这里直接截断)
|
|
342
|
+
// 4. 追加 metadata
|
|
343
|
+
const formattedSize = bytes < 1024
|
|
344
|
+
? `${bytes} B`
|
|
345
|
+
: bytes < 1024 * 1024
|
|
346
|
+
? `${(bytes / 1024).toFixed(1)} KB`
|
|
347
|
+
: `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
348
|
+
|
|
349
|
+
const domainNote = preapproved
|
|
350
|
+
? '[网络访问:预批准域名]'
|
|
351
|
+
: '[网络访问:普通域名;请按来源本身评估证据质量]';
|
|
352
|
+
|
|
353
|
+
const output = `【WebFetch 结果】
|
|
354
|
+
URL: ${url}
|
|
355
|
+
状态: ${code} ${codeText}
|
|
356
|
+
大小: ${formattedSize}
|
|
357
|
+
耗时: ${(durationMs / 1000).toFixed(2)}s
|
|
358
|
+
${domainNote}
|
|
359
|
+
|
|
360
|
+
--- 内容 ---
|
|
361
|
+
${content}`;
|
|
362
|
+
|
|
363
|
+
// 5. 截断
|
|
364
|
+
let final = output;
|
|
365
|
+
if (final.length > DEFAULT_MAX_RESULT_SIZE_CHARS) {
|
|
366
|
+
final = final.slice(0, DEFAULT_MAX_RESULT_SIZE_CHARS) + `\n\n... (输出超过 ${DEFAULT_MAX_RESULT_SIZE_CHARS} 字符,已截断)`;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return { ok: true, content: final };
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// ---------------- 7. 导出 ----------------
|
|
373
|
+
export const webfetchTool: Tool<WebFetchInput> = {
|
|
374
|
+
name: 'WebFetch',
|
|
375
|
+
description,
|
|
376
|
+
inputSchema,
|
|
377
|
+
parameters,
|
|
378
|
+
isReadOnly: true,
|
|
379
|
+
isConcurrencySafe: true,
|
|
380
|
+
maxResultSizeChars: DEFAULT_MAX_RESULT_SIZE_CHARS,
|
|
381
|
+
interruptBehavior: () => 'cancel',
|
|
382
|
+
call,
|
|
383
|
+
};
|
|
@@ -60,11 +60,14 @@ const inputSchema = z.object({
|
|
|
60
60
|
// ---------------- 2. JSON Schema(由 Zod 自动派生) ----------------
|
|
61
61
|
const parameters = toToolParameters(inputSchema);
|
|
62
62
|
// ---------------- 3. Description(给 LLM 看的工具说明) ----------------
|
|
63
|
-
const description =
|
|
64
|
-
- Use
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
63
|
+
const description = `Searches the public web through Tavily and returns structured source candidates.
|
|
64
|
+
- Use it to discover sources, verify current information, compare multiple sources, or locate current documentation.
|
|
65
|
+
- It does not open or operate a browser. Use returned URLs with WebFetch when full source text is needed.
|
|
66
|
+
- Results contain title, URL and a text snippet. They are discovery evidence, not a substitute for reading a high-value source in full.
|
|
67
|
+
- 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
|
+
- Add an explicit date or year only when recency matters; stable concepts and exact names should remain exact.
|
|
69
|
+
- \`search_depth: "advanced"\` is slower but can return a synthesized answer; \`topic: "news"\` favors news sources.
|
|
70
|
+
- Requires a configured Tavily API key.`;
|
|
68
71
|
// ---------------- 4b. 退避重试 ----------------
|
|
69
72
|
//
|
|
70
73
|
// 为什么需要(与单发 fetch 零重试的旧行为对比):WebSearch 是 isConcurrencySafe 工具,
|
|
@@ -187,14 +190,12 @@ async function call(input, signal, getApiKey = async () => (await configService.
|
|
|
187
190
|
'请在 KakadeAI 设置 → 工具 → 联网搜索中配置,或在 env 模式提供 TAVILY_API_KEY。',
|
|
188
191
|
};
|
|
189
192
|
}
|
|
190
|
-
// 5b. 自动追加当前日期到 query(强制时间限制,防止搜索到过时信息)
|
|
191
|
-
const today = new Date().toISOString().slice(0, 10);
|
|
192
|
-
const queryWithDate = input.query.includes(today)
|
|
193
|
-
? input.query
|
|
194
|
-
: `${input.query} (as of ${today})`;
|
|
195
193
|
const body = {
|
|
196
194
|
api_key: apiKey,
|
|
197
|
-
query
|
|
195
|
+
// Preserve the exact research query. The prompt layer adds a date only
|
|
196
|
+
// when recency matters; unconditional mutation hurts exact names,
|
|
197
|
+
// historical topics, and stable technical documentation.
|
|
198
|
+
query: input.query,
|
|
198
199
|
max_results: input.max_results ?? 5,
|
|
199
200
|
search_depth: input.search_depth ?? 'basic',
|
|
200
201
|
topic: input.topic ?? 'general',
|