ummaya 0.2.4 → 0.2.6
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 +15 -2
- package/bin/ummaya +10 -1
- package/bun.lock +180 -244
- package/npm-shrinkwrap.json +760 -1760
- package/package.json +39 -22
- package/prompts/manifest.yaml +1 -1
- package/prompts/system_v1.md +1 -0
- package/pyproject.toml +27 -2
- package/specs/2803-document-production-hardening/contracts/document-tools.schema.json +1043 -0
- package/src/ummaya/_canonical/__init__.py +2 -0
- package/src/ummaya/_canonical/baselines.yaml +113 -0
- package/src/ummaya/engine/engine.py +29 -132
- package/src/ummaya/evidence/__init__.py +21 -2
- package/src/ummaya/evidence/dataset_contract.py +193 -0
- package/src/ummaya/evidence/document_authoring_cases.py +33 -0
- package/src/ummaya/evidence/document_harness.py +313 -0
- package/src/ummaya/evidence/document_viewer_ux.py +391 -0
- package/src/ummaya/evidence/gates.py +70 -0
- package/src/ummaya/evidence/json_types.py +20 -0
- package/src/ummaya/evidence/models.py +88 -1
- package/src/ummaya/evidence/output_payload.py +89 -0
- package/src/ummaya/evidence/payload_documents.py +233 -0
- package/src/ummaya/evidence/route_contracts.py +224 -0
- package/src/ummaya/evidence/route_helpers.py +150 -0
- package/src/ummaya/evidence/runner.py +81 -212
- package/src/ummaya/evidence/source_provenance.py +246 -0
- package/src/ummaya/evidence/source_provenance_redaction.py +176 -0
- package/src/ummaya/evidence/tool_layer.py +39 -0
- package/src/ummaya/evidence/tool_layer_models.py +151 -0
- package/src/ummaya/ipc/adapter_manifest_emitter.py +26 -10
- package/src/ummaya/ipc/document_intent_normalization.py +185 -0
- package/src/ummaya/ipc/frame_schema.py +5 -5
- package/src/ummaya/ipc/route_diagnostics.py +73 -0
- package/src/ummaya/ipc/stdio.py +1109 -477
- package/src/ummaya/llm/client.py +102 -3
- package/src/ummaya/llm/config.py +8 -3
- package/src/ummaya/primitives/__init__.py +6 -2
- package/src/ummaya/primitives/delegation.py +1 -1
- package/src/ummaya/primitives/document.py +28 -0
- package/src/ummaya/settings.py +0 -3
- package/src/ummaya/tools/discovery_bridge.py +17 -1
- package/src/ummaya/tools/documents/__init__.py +297 -0
- package/src/ummaya/tools/documents/adapter_registry.py +487 -0
- package/src/ummaya/tools/documents/archive_container_probe.py +167 -0
- package/src/ummaya/tools/documents/artifact_store.py +454 -0
- package/src/ummaya/tools/documents/authoring.py +283 -0
- package/src/ummaya/tools/documents/baselines.py +132 -0
- package/src/ummaya/tools/documents/capability.py +331 -0
- package/src/ummaya/tools/documents/contracts.py +112 -0
- package/src/ummaya/tools/documents/conversion.py +521 -0
- package/src/ummaya/tools/documents/diff.py +275 -0
- package/src/ummaya/tools/documents/engines.py +163 -0
- package/src/ummaya/tools/documents/evaluation.py +291 -0
- package/src/ummaya/tools/documents/explicit_values.py +108 -0
- package/src/ummaya/tools/documents/fixtures.py +174 -0
- package/src/ummaya/tools/documents/format_completion_audit.py +471 -0
- package/src/ummaya/tools/documents/formats/__init__.py +2 -0
- package/src/ummaya/tools/documents/formats/archive.py +528 -0
- package/src/ummaya/tools/documents/formats/base.py +41 -0
- package/src/ummaya/tools/documents/formats/code_file.py +211 -0
- package/src/ummaya/tools/documents/formats/data_file.py +272 -0
- package/src/ummaya/tools/documents/formats/hwp.py +284 -0
- package/src/ummaya/tools/documents/formats/hwpx.py +1837 -0
- package/src/ummaya/tools/documents/formats/odf.py +435 -0
- package/src/ummaya/tools/documents/formats/ooxml.py +1030 -0
- package/src/ummaya/tools/documents/formats/passive.py +766 -0
- package/src/ummaya/tools/documents/formats/pdf.py +702 -0
- package/src/ummaya/tools/documents/formats/text_web.py +268 -0
- package/src/ummaya/tools/documents/hwp_conversion_probe.py +178 -0
- package/src/ummaya/tools/documents/hwp_direct_candidate.py +141 -0
- package/src/ummaya/tools/documents/inspection.py +289 -0
- package/src/ummaya/tools/documents/intake.py +1079 -0
- package/src/ummaya/tools/documents/legacy_office_promotion_probe.py +366 -0
- package/src/ummaya/tools/documents/models.py +1598 -0
- package/src/ummaya/tools/documents/odf_promotion_probe.py +167 -0
- package/src/ummaya/tools/documents/orchestrator.py +96 -0
- package/src/ummaya/tools/documents/passive_capability_probe.py +251 -0
- package/src/ummaya/tools/documents/patch.py +170 -0
- package/src/ummaya/tools/documents/pdfa_conformance.py +284 -0
- package/src/ummaya/tools/documents/pdfa_promotion_probe.py +198 -0
- package/src/ummaya/tools/documents/permissions.py +110 -0
- package/src/ummaya/tools/documents/planner.py +616 -0
- package/src/ummaya/tools/documents/registry.py +2733 -0
- package/src/ummaya/tools/documents/render.py +978 -0
- package/src/ummaya/tools/documents/render_comparison.py +113 -0
- package/src/ummaya/tools/documents/render_comparison_models.py +74 -0
- package/src/ummaya/tools/documents/render_comparison_regions.py +73 -0
- package/src/ummaya/tools/documents/render_comparison_style.py +161 -0
- package/src/ummaya/tools/documents/reread.py +157 -0
- package/src/ummaya/tools/documents/runtime_authoring.py +244 -0
- package/src/ummaya/tools/documents/runtime_authoring_bundle.py +76 -0
- package/src/ummaya/tools/documents/scorecard.py +184 -0
- package/src/ummaya/tools/documents/socratic_planner.py +193 -0
- package/src/ummaya/tools/documents/style.py +48 -0
- package/src/ummaya/tools/documents/tool_defs.py +523 -0
- package/src/ummaya/tools/documents/validate.py +347 -0
- package/src/ummaya/tools/executor.py +29 -0
- package/src/ummaya/tools/live_proxy.py +0 -3
- package/src/ummaya/tools/models.py +5 -1
- package/src/ummaya/tools/register_all.py +8 -0
- package/src/ummaya/tools/registry.py +10 -1
- package/src/ummaya/tools/routing/__init__.py +59 -0
- package/src/ummaya/tools/routing/builder.py +105 -0
- package/src/ummaya/tools/routing/cards.py +29 -0
- package/src/ummaya/tools/routing/decision_service.py +534 -0
- package/src/ummaya/tools/routing/decision_types.py +74 -0
- package/src/ummaya/tools/routing/feasibility.py +122 -0
- package/src/ummaya/tools/routing/intent.py +17 -0
- package/src/ummaya/tools/routing/intent_extractor.py +207 -0
- package/src/ummaya/tools/routing/intent_patterns.py +160 -0
- package/src/ummaya/tools/routing/intent_public_data.py +150 -0
- package/src/ummaya/tools/routing/intent_types.py +48 -0
- package/src/ummaya/tools/routing/lint.py +78 -0
- package/src/ummaya/tools/routing/metadata.py +174 -0
- package/src/ummaya/tools/routing/projection.py +340 -0
- package/src/ummaya/tools/routing/retrieval_policy.py +629 -0
- package/src/ummaya/tools/routing/schema.py +81 -0
- package/src/ummaya/tools/routing/types.py +96 -0
- package/src/ummaya/tools/routing_index.py +2 -2
- package/src/ummaya/tools/search.py +34 -746
- package/tests/fixtures/documents/public_forms/baselines.yaml +113 -0
- package/tui/bun.lock +126 -305
- package/tui/package.json +35 -22
- package/tui/src/.cc-byte-identical-whitelist.yaml +266 -0
- package/tui/src/QueryEngine.ts +12 -8
- package/tui/src/bridge/inboundAttachments.ts +3 -3
- package/tui/src/cli/handlers/auth.ts +3 -12
- package/tui/src/cli/handlers/mcp.tsx +0 -1
- package/tui/src/cli/print.ts +8 -9
- package/tui/src/commands/insights.ts +1 -1
- package/tui/src/commands/install-github-app/types.ts +8 -30
- package/tui/src/commands/plugin/types.ts +6 -28
- package/tui/src/commands/plugin/unifiedTypes.ts +4 -26
- package/tui/src/commands/rename/generateSessionName.ts +1 -1
- package/tui/src/components/Feedback.tsx +1 -1
- package/tui/src/components/LogoV2/EmergencyTip.tsx +11 -2
- package/tui/src/components/LogoV2/WelcomeV2.tsx +1 -3
- package/tui/src/components/ScrollKeybindingHandler.tsx +6 -6
- package/tui/src/components/Spinner/types.ts +6 -28
- package/tui/src/components/agents/generateAgent.ts +1 -1
- package/tui/src/components/agents/new-agent-creation/types.ts +4 -26
- package/tui/src/components/config/EnvSecretIsolatedEditor.tsx +1 -1
- package/tui/src/components/mcp/types.ts +16 -38
- package/tui/src/components/messages/AssistantToolUseMessage.tsx +3 -2
- package/tui/src/components/messages/UserCrossSessionMessage.ts +16 -4
- package/tui/src/components/messages/UserForkBoilerplateMessage.ts +16 -4
- package/tui/src/components/messages/UserGitHubWebhookMessage.ts +16 -4
- package/tui/src/components/messages/UserToolResultMessage/utils.tsx +3 -2
- package/tui/src/components/permissions/MonitorPermissionRequest/MonitorPermissionRequest.ts +9 -4
- package/tui/src/components/permissions/ReviewArtifactPermissionRequest/ReviewArtifactPermissionRequest.ts +9 -4
- package/tui/src/components/primitive/DocumentSocraticReviewBlock.tsx +129 -0
- package/tui/src/components/primitive/DocumentToolResultCard.tsx +224 -0
- package/tui/src/components/primitive/documentSocraticReview.ts +215 -0
- package/tui/src/components/primitive/index.tsx +43 -1
- package/tui/src/components/primitive/types.ts +137 -0
- package/tui/src/components/ui/option.ts +4 -26
- package/tui/src/constants/common.ts +0 -2
- package/tui/src/constants/prompts.ts +4 -3
- package/tui/src/constants/querySource.ts +4 -26
- package/tui/src/entrypoints/sdk/controlTypes.ts +26 -48
- package/tui/src/entrypoints/sdk/coreTypes.generated.ts +3 -25
- package/tui/src/entrypoints/sdk/runtimeTypes.ts +38 -60
- package/tui/src/entrypoints/sdk/sdkUtilityTypes.ts +4 -26
- package/tui/src/entrypoints/sdk/settingsTypes.generated.ts +3 -25
- package/tui/src/entrypoints/sdk/toolTypes.ts +3 -25
- package/tui/src/hooks/toolPermission/handlers/interactiveHandler.ts +10 -0
- package/tui/src/hooks/useApiKeyVerification.ts +1 -1
- package/tui/src/hooks/useVirtualScroll.ts +1 -1
- package/tui/src/ink/ink.tsx +33 -14
- package/tui/src/ink/reconciler.ts +2 -3
- package/tui/src/ink/render-to-screen.ts +30 -10
- package/tui/src/ipc/bridge.ts +62 -15
- package/tui/src/ipc/bridgeSingleton.ts +5 -1
- package/tui/src/ipc/codec.ts +3 -3
- package/tui/src/ipc/frames.generated.ts +12 -12
- package/tui/src/ipc/llmClient.ts +151 -27
- package/tui/src/ipc/schema/frame.schema.json +1 -1
- package/tui/src/keybindings/defaultBindings.ts +4 -0
- package/tui/src/main.tsx +32 -15
- package/tui/src/native-ts/file-index/index.ts +33 -3
- package/tui/src/observability/surface.ts +2 -2
- package/tui/src/probes/toolRegistryProbe.tsx +3 -1
- package/tui/src/projectOnboardingState.ts +7 -6
- package/tui/src/query/chatMessageTypes.ts +18 -0
- package/tui/src/query/chatMessagesBuilder.ts +1 -1
- package/tui/src/query/deps.ts +1 -1
- package/tui/src/query/messageGuards.ts +106 -0
- package/tui/src/query/publicDataTerminalRepair.ts +384 -0
- package/tui/src/query/run.ts +1075 -0
- package/tui/src/query/supportBoundary.ts +168 -0
- package/tui/src/query/toolResultErrors.ts +103 -0
- package/tui/src/query/toolRunner.ts +687 -0
- package/tui/src/query/unavailableToolRepair.ts +118 -0
- package/tui/src/query.ts +9 -2186
- package/tui/src/screens/REPL.tsx +40 -29
- package/tui/src/services/api/adapterManifest.ts +4 -0
- package/tui/src/services/api/backendChat/events.ts +117 -0
- package/tui/src/services/api/backendChat/finalMessage.ts +40 -0
- package/tui/src/services/api/backendChat/frame.ts +9 -0
- package/tui/src/services/api/backendChat/streaming.ts +430 -0
- package/tui/src/services/api/backendChat/types.ts +62 -0
- package/tui/src/services/api/backendChat.ts +1 -0
- package/tui/src/services/api/client.ts +65 -2
- package/tui/src/services/api/errorUtils.ts +5 -5
- package/tui/src/services/api/errors.ts +1 -1
- package/tui/src/services/api/logging.ts +1 -1
- package/tui/src/services/api/ummaya/evidence.ts +194 -0
- package/tui/src/services/api/ummaya/messages.ts +255 -0
- package/tui/src/services/api/ummaya/nonStreaming.ts +66 -0
- package/tui/src/services/api/ummaya/provider.ts +200 -0
- package/tui/src/services/api/ummaya/reasoning.ts +24 -0
- package/tui/src/services/api/ummaya/request.ts +200 -0
- package/tui/src/services/api/ummaya/selectionContext.ts +240 -0
- package/tui/src/services/api/ummaya/streaming.ts +365 -0
- package/tui/src/services/api/ummaya/streamingPayload.ts +129 -0
- package/tui/src/services/api/ummaya/streamingReader.ts +40 -0
- package/tui/src/services/api/ummaya/toolSelection.ts +217 -0
- package/tui/src/services/api/ummaya/types.ts +110 -0
- package/tui/src/services/api/ummaya/usage.ts +30 -0
- package/tui/src/services/api/ummaya.ts +26 -418
- package/tui/src/services/api/withRetry.ts +1 -1
- package/tui/src/services/awaySummary.ts +2 -2
- package/tui/src/services/claudeAiLimits.ts +1 -1
- package/tui/src/services/compact/autoCompact.ts +1 -1
- package/tui/src/services/compact/compact.ts +1 -1
- package/tui/src/services/lsp/types.ts +8 -30
- package/tui/src/services/tips/types.ts +6 -28
- package/tui/src/services/tokenEstimation.ts +1 -1
- package/tui/src/services/toolRegistry/bootGuard.ts +5 -5
- package/tui/src/services/toolUseSummary/toolUseSummaryGenerator.ts +1 -1
- package/tui/src/services/tools/toolExecution.ts +94 -1
- package/tui/src/store/pendingPermissionSlot.ts +1 -1
- package/tui/src/store/session-store.ts +10 -36
- package/tui/src/stubs/any-stub.ts +15 -10
- package/tui/src/stubs/color-diff-napi.ts +37 -23
- package/tui/src/stubs/globals.d.ts +3 -3
- package/tui/src/stubs/macro-preload.ts +23 -12
- package/tui/src/tools/AdapterTool/AdapterTool.ts +1207 -714
- package/tui/src/tools/AdapterTool/routeDiagnostics.ts +75 -0
- package/tui/src/tools/AgentTool/AgentTool.tsx +84 -1371
- package/tui/src/tools/AgentTool/agentToolHandoff.ts +114 -0
- package/tui/src/tools/AgentTool/agentToolPartialResult.ts +16 -0
- package/tui/src/tools/AgentTool/agentToolProgress.ts +32 -0
- package/tui/src/tools/AgentTool/agentToolResolver.ts +161 -0
- package/tui/src/tools/AgentTool/agentToolResult.ts +163 -0
- package/tui/src/tools/AgentTool/agentToolUtils.ts +14 -686
- package/tui/src/tools/AgentTool/asyncAgentLifecycle.ts +208 -0
- package/tui/src/tools/AgentTool/asyncLifecycle.ts +153 -0
- package/tui/src/tools/AgentTool/backgroundedCompletion.ts +126 -0
- package/tui/src/tools/AgentTool/backgroundedLifecycle.ts +174 -0
- package/tui/src/tools/AgentTool/foregroundBackground.ts +83 -0
- package/tui/src/tools/AgentTool/foregroundDrain.tsx +133 -0
- package/tui/src/tools/AgentTool/foregroundFinalize.ts +98 -0
- package/tui/src/tools/AgentTool/foregroundLifecycle.tsx +237 -0
- package/tui/src/tools/AgentTool/foregroundProgress.tsx +169 -0
- package/tui/src/tools/AgentTool/foregroundTask.ts +89 -0
- package/tui/src/tools/AgentTool/forkSubagent.ts +1 -12
- package/tui/src/tools/AgentTool/forkSubagentGate.ts +34 -0
- package/tui/src/tools/AgentTool/launchRouting.ts +203 -0
- package/tui/src/tools/AgentTool/lifecycle.ts +244 -0
- package/tui/src/tools/AgentTool/mcpRouting.ts +73 -0
- package/tui/src/tools/AgentTool/orchestrationSupport.ts +70 -0
- package/tui/src/tools/AgentTool/permissions.ts +39 -0
- package/tui/src/tools/AgentTool/promptSetup.ts +181 -0
- package/tui/src/tools/AgentTool/remoteRouting.ts +62 -0
- package/tui/src/tools/AgentTool/resultMapping.ts +116 -0
- package/tui/src/tools/AgentTool/resumeAgent.ts +39 -107
- package/tui/src/tools/AgentTool/resumeAgentHelpers.ts +140 -0
- package/tui/src/tools/AgentTool/runAgent.ts +1 -1
- package/tui/src/tools/AgentTool/runtimeConfig.ts +57 -0
- package/tui/src/tools/AgentTool/schemas.ts +196 -0
- package/tui/src/tools/AgentTool/sourceVerificationPropagation.ts +263 -0
- package/tui/src/tools/AgentTool/worktreeLifecycle.ts +105 -0
- package/tui/src/tools/AskUserQuestionTool/AskUserQuestionTool.tsx +174 -202
- package/tui/src/tools/BashTool/BashTool.tsx +71 -1072
- package/tui/src/tools/BashTool/bashCommandHelpers.ts +12 -12
- package/tui/src/tools/BashTool/bashPermissions/astPreflight.ts +173 -0
- package/tui/src/tools/BashTool/bashPermissions/classifierChecks.ts +199 -0
- package/tui/src/tools/BashTool/bashPermissions/compoundGuards.ts +53 -0
- package/tui/src/tools/BashTool/bashPermissions/constants.ts +99 -0
- package/tui/src/tools/BashTool/bashPermissions/index.ts +38 -0
- package/tui/src/tools/BashTool/bashPermissions/legacyMisparsing.ts +62 -0
- package/tui/src/tools/BashTool/bashPermissions/main.ts +135 -0
- package/tui/src/tools/BashTool/bashPermissions/normalizedCommands.ts +33 -0
- package/tui/src/tools/BashTool/bashPermissions/operatorFlow.ts +98 -0
- package/tui/src/tools/BashTool/bashPermissions/permissionChecks.ts +200 -0
- package/tui/src/tools/BashTool/bashPermissions/prefixSuggestions.ts +88 -0
- package/tui/src/tools/BashTool/bashPermissions/promptClassifierRules.ts +125 -0
- package/tui/src/tools/BashTool/bashPermissions/ruleDelegates.ts +19 -0
- package/tui/src/tools/BashTool/bashPermissions/ruleMatching.ts +145 -0
- package/tui/src/tools/BashTool/bashPermissions/sandboxAutoAllow.ts +75 -0
- package/tui/src/tools/BashTool/bashPermissions/subcommandFlow.ts +205 -0
- package/tui/src/tools/BashTool/bashPermissions/subcommandGuards.ts +73 -0
- package/tui/src/tools/BashTool/bashPermissions/subcommandResultHelpers.ts +116 -0
- package/tui/src/tools/BashTool/bashPermissions/types.ts +26 -0
- package/tui/src/tools/BashTool/bashPermissions/wrapperStripping.ts +139 -0
- package/tui/src/tools/BashTool/bashPermissions.ts +26 -2621
- package/tui/src/tools/BashTool/call.ts +202 -0
- package/tui/src/tools/BashTool/callLoader.ts +35 -0
- package/tui/src/tools/BashTool/commandClassification.ts +151 -0
- package/tui/src/tools/BashTool/commandClassificationLoader.ts +40 -0
- package/tui/src/tools/BashTool/cwdReset.ts +33 -0
- package/tui/src/tools/BashTool/lineTruncation.ts +11 -0
- package/tui/src/tools/BashTool/modeValidation.ts +13 -1
- package/tui/src/tools/BashTool/outputPersistence.ts +42 -0
- package/tui/src/tools/BashTool/permissionClassification.ts +66 -0
- package/tui/src/tools/BashTool/permissionLoader.ts +44 -0
- package/tui/src/tools/BashTool/resultLoader.ts +29 -0
- package/tui/src/tools/BashTool/resultMapping.ts +83 -0
- package/tui/src/tools/BashTool/sandboxPolicy.ts +79 -0
- package/tui/src/tools/BashTool/schemas.ts +65 -0
- package/tui/src/tools/BashTool/sedEditExecution.ts +59 -0
- package/tui/src/tools/BashTool/shellExecution.tsx +245 -0
- package/tui/src/tools/BashTool/shellOutputUtils.ts +85 -0
- package/tui/src/tools/BashTool/shellPermissionGauntlet.ts +97 -0
- package/tui/src/tools/BashTool/uiLoader.ts +37 -0
- package/tui/src/tools/BriefTool/upload.ts +1 -1
- package/tui/src/tools/CalculatorTool/parser.ts +2 -2
- package/tui/src/tools/DocumentPrimitive/DocumentPrimitive.ts +262 -0
- package/tui/src/tools/DocumentPrimitive/dispatchNormalization.ts +270 -0
- package/tui/src/tools/DocumentPrimitive/documentDestinationPath.ts +18 -0
- package/tui/src/tools/DocumentPrimitive/documentMutationGuard.ts +22 -0
- package/tui/src/tools/DocumentPrimitive/documentPatchNormalization.ts +248 -0
- package/tui/src/tools/DocumentPrimitive/documentSourceVerification.ts +245 -0
- package/tui/src/tools/DocumentPrimitive/documentSourceVerificationFields.ts +103 -0
- package/tui/src/tools/DocumentPrimitive/modelVisibleOutput.ts +40 -0
- package/tui/src/tools/DocumentPrimitive/prompt.ts +35 -0
- package/tui/src/tools/FileEditTool/FileEditTool.ts +9 -507
- package/tui/src/tools/FileEditTool/call.ts +228 -0
- package/tui/src/tools/FileEditTool/validateInput.ts +196 -0
- package/tui/src/tools/FileReadTool/imageProcessor.ts +13 -0
- package/tui/src/tools/FileWriteTool/FileWriteTool.ts +7 -300
- package/tui/src/tools/FileWriteTool/call.ts +223 -0
- package/tui/src/tools/FileWriteTool/validateInput.ts +80 -0
- package/tui/src/tools/ListMcpResourcesTool/ListMcpResourcesTool.ts +19 -3
- package/tui/src/tools/LookupPrimitive/LookupPrimitive.ts +25 -32
- package/tui/src/tools/LookupPrimitive/prompt.ts +0 -2
- package/tui/src/tools/MCPTool/trustPolicy.ts +118 -0
- package/tui/src/tools/McpAuthTool/McpAuthTool.ts +21 -3
- package/tui/src/tools/NotebookEditTool/NotebookEditTool.ts +7 -326
- package/tui/src/tools/NotebookEditTool/call.ts +254 -0
- package/tui/src/tools/NotebookEditTool/notebookModel.ts +51 -0
- package/tui/src/tools/NotebookEditTool/validateInput.ts +142 -0
- package/tui/src/tools/PowerShellTool/PowerShellTool.tsx +46 -937
- package/tui/src/tools/PowerShellTool/acceptEditsCommandValidation.ts +162 -0
- package/tui/src/tools/PowerShellTool/call.ts +179 -0
- package/tui/src/tools/PowerShellTool/callLoader.ts +37 -0
- package/tui/src/tools/PowerShellTool/commandClassification.ts +86 -0
- package/tui/src/tools/PowerShellTool/modeValidation.ts +25 -332
- package/tui/src/tools/PowerShellTool/outputPersistence.ts +42 -0
- package/tui/src/tools/PowerShellTool/permissionClassification.ts +28 -0
- package/tui/src/tools/PowerShellTool/resultLoader.ts +31 -0
- package/tui/src/tools/PowerShellTool/resultMapping.ts +75 -0
- package/tui/src/tools/PowerShellTool/schemas.ts +40 -0
- package/tui/src/tools/PowerShellTool/shellExecution.tsx +258 -0
- package/tui/src/tools/PowerShellTool/symlinkModeValidation.ts +44 -0
- package/tui/src/tools/PowerShellTool/uiLoader.ts +37 -0
- package/tui/src/tools/PowerShellTool/validation.ts +39 -0
- package/tui/src/tools/ReadMcpResourceTool/ReadMcpResourceTool.ts +19 -3
- package/tui/src/tools/ResolveLocationPrimitive/ResolveLocationPrimitive.ts +1 -11
- package/tui/src/tools/ResolveLocationPrimitive/prompt.ts +2 -6
- package/tui/src/tools/SkillTool/SkillTool.ts +2 -2
- package/tui/src/tools/SubmitPrimitive/SubmitPrimitive.ts +27 -10
- package/tui/src/tools/TaskCreateTool/TaskCreateTool.ts +16 -2
- package/tui/src/tools/TaskGetTool/TaskGetTool.ts +23 -3
- package/tui/src/tools/TaskListTool/TaskListTool.ts +22 -4
- package/tui/src/tools/TaskOutputTool/TaskOutputTool.tsx +46 -547
- package/tui/src/tools/TaskOutputTool/lookup.ts +216 -0
- package/tui/src/tools/TaskOutputTool/render.tsx +257 -0
- package/tui/src/tools/TaskOutputTool/schemas.ts +55 -0
- package/tui/src/tools/TaskOutputTool/serialization.ts +36 -0
- package/tui/src/tools/TaskStopTool/TaskStopTool.ts +10 -0
- package/tui/src/tools/TaskUpdateTool/TaskUpdateTool.ts +14 -364
- package/tui/src/tools/TaskUpdateTool/completion.ts +62 -0
- package/tui/src/tools/TaskUpdateTool/schemas.ts +62 -0
- package/tui/src/tools/TaskUpdateTool/serialization.ts +46 -0
- package/tui/src/tools/TaskUpdateTool/statusUpdate.ts +247 -0
- package/tui/src/tools/TodoWriteTool/TodoWriteTool.ts +21 -2
- package/tui/src/tools/ToolSearchTool/ToolSearchTool.ts +21 -302
- package/tui/src/tools/ToolSearchTool/ccSupportTools.ts +223 -0
- package/tui/src/tools/ToolSearchTool/descriptionCache.ts +50 -0
- package/tui/src/tools/ToolSearchTool/keywordSearch.ts +216 -0
- package/tui/src/tools/ToolSearchTool/prompt.ts +10 -4
- package/tui/src/tools/ToolSearchTool/resultMapping.ts +30 -0
- package/tui/src/tools/ToolSearchTool/schemas.ts +30 -0
- package/tui/src/tools/ToolSearchTool/searchPool.ts +47 -0
- package/tui/src/tools/ToolSearchTool/supportIntentHints.ts +140 -0
- package/tui/src/tools/TranslateTool/TranslateTool.ts +1 -1
- package/tui/src/tools/VerifyPrimitive/VerifyPrimitive.ts +2 -1
- package/tui/src/tools/WebFetchTool/WebFetchTool.ts +43 -138
- package/tui/src/tools/WebFetchTool/call.ts +227 -0
- package/tui/src/tools/WebFetchTool/resolvedAddressSafety.ts +78 -0
- package/tui/src/tools/WebFetchTool/sourceVerification.ts +204 -0
- package/tui/src/tools/WebFetchTool/types.ts +23 -0
- package/tui/src/tools/WebFetchTool/urlSafety.ts +181 -0
- package/tui/src/tools/WebFetchTool/utils.ts +1 -1
- package/tui/src/tools/WebSearchTool/UI.tsx +0 -1
- package/tui/src/tools/WebSearchTool/WebSearchTool.ts +9 -313
- package/tui/src/tools/WebSearchTool/call.ts +33 -0
- package/tui/src/tools/WebSearchTool/responseMapping.ts +190 -0
- package/tui/src/tools/WebSearchTool/resultBlock.ts +47 -0
- package/tui/src/tools/WebSearchTool/schemas.ts +47 -0
- package/tui/src/tools/WebSearchTool/toolSchema.ts +12 -0
- package/tui/src/tools/WorkspaceToolAdapter/WorkspaceToolAdapter.ts +79 -0
- package/tui/src/tools/WorkspaceToolAdapter/allowedRootPolicy.ts +85 -0
- package/tui/src/tools/WorkspaceToolAdapter/documentFormatGuards.ts +73 -0
- package/tui/src/tools/WorkspaceToolAdapter/inputNormalization.ts +105 -0
- package/tui/src/tools/WorkspaceToolAdapter/mcpExposurePolicy.ts +64 -0
- package/tui/src/tools/WorkspaceToolAdapter/toolDefFactory.ts +215 -0
- package/tui/src/tools/WorkspaceToolAdapter/toolNames.ts +6 -0
- package/tui/src/tools/WorkspaceToolAdapter/workspacePolicy.ts +15 -0
- package/tui/src/tools/_shared/dispatchPrimitive.ts +6 -6
- package/tui/src/tools/_shared/documentChangeToPatch.ts +125 -0
- package/tui/src/tools/_shared/documentDispatchArguments.ts +87 -0
- package/tui/src/tools/_shared/documentPrimitiveTimeout.ts +13 -0
- package/tui/src/tools/_shared/documentToolResultRender.ts +98 -0
- package/tui/src/tools/_shared/pendingCallRegistry.ts +1 -6
- package/tui/src/tools/_shared/rootPrimitiveInput.ts +1 -0
- package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPatterns.ts +58 -0
- package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPrompt.ts +271 -0
- package/tui/src/tools/_shared/toolChoiceRepair/documentRepair.ts +452 -0
- package/tui/src/tools/_shared/toolChoiceRepair/messageAccess.ts +80 -0
- package/tui/src/tools/_shared/toolChoiceRepair/publicDataRepair.ts +92 -0
- package/tui/src/tools/_shared/toolChoiceRepair/supportRepair.ts +135 -0
- package/tui/src/tools/_shared/toolChoiceRepair.ts +55 -860
- package/tui/src/tools/shared/mockDisclaimer.ts +1 -1
- package/tui/src/tools.ts +39 -190
- package/tui/src/types/fileSuggestion.ts +4 -26
- package/tui/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +186 -148
- package/tui/src/types/generated/events_mono/common/v1/auth.ts +25 -11
- package/tui/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +47 -30
- package/tui/src/types/generated/google/protobuf/timestamp.ts +21 -7
- package/tui/src/types/message.ts +80 -102
- package/tui/src/types/messageQueueTypes.ts +6 -28
- package/tui/src/types/notebook.ts +16 -38
- package/tui/src/types/statusLine.ts +4 -26
- package/tui/src/types/tools.ts +24 -46
- package/tui/src/types/utils.ts +6 -28
- package/tui/src/upstreamproxy/relay.ts +7 -3
- package/tui/src/upstreamproxy/upstreamproxy.ts +1 -1
- package/tui/src/utils/assistantMessageFactories.ts +9 -3
- package/tui/src/utils/auth.ts +129 -139
- package/tui/src/utils/bash/ast.ts +23 -23
- package/tui/src/utils/bash/bashParser.ts +5 -5
- package/tui/src/utils/billing.ts +1 -1
- package/tui/src/utils/claudeDesktop.ts +4 -4
- package/tui/src/utils/collapseReadSearch.ts +3 -3
- package/tui/src/utils/cronTasks.ts +1 -1
- package/tui/src/utils/execFileNoThrow.ts +1 -1
- package/tui/src/utils/filePersistence/types.ts +16 -38
- package/tui/src/utils/forkedAgent.ts +1 -1
- package/tui/src/utils/gracefulShutdown.ts +4 -4
- package/tui/src/utils/heapDumpService.ts +12 -8
- package/tui/src/utils/hooks/apiQueryHookHelper.ts +1 -1
- package/tui/src/utils/hooks/execPromptHook.ts +1 -1
- package/tui/src/utils/hooks/skillImprovement.ts +1 -1
- package/tui/src/utils/mcp/dateTimeParser.ts +1 -1
- package/tui/src/utils/messages.ts +18 -0
- package/tui/src/utils/migrateSessions.ts +3 -3
- package/tui/src/utils/model/model.ts +6 -6
- package/tui/src/utils/permissions/yoloClassifier.ts +1 -1
- package/tui/src/utils/plugins/headlessPluginInstall.ts +1 -1
- package/tui/src/utils/plugins/mcpPluginIntegration.ts +1 -1
- package/tui/src/utils/plugins/mcpbHandler.ts +1 -1
- package/tui/src/utils/plugins/pluginLoader.ts +8 -8
- package/tui/src/utils/protectedNamespace.ts +5 -3
- package/tui/src/utils/rawJsonToolCall.ts +242 -0
- package/tui/src/utils/ripgrep.ts +16 -7
- package/tui/src/utils/sessionTitle.ts +1 -1
- package/tui/src/utils/settings/permissionValidation.ts +14 -2
- package/tui/src/utils/shell/prefix.ts +1 -1
- package/tui/src/utils/sideQuery.ts +1 -1
- package/tui/src/utils/systemThemeWatcher.ts +13 -3
- package/tui/src/utils/teleport.tsx +1 -1
- package/uv.lock +426 -45
- package/tui/src/services/api/claude.ts +0 -3540
- package/tui/src/tools/_shared/directPublicDataGuard.ts +0 -362
- package/tui/src/tools/_shared/kmaAnalysisGuard.ts +0 -197
- package/tui/src/tools/_shared/kmaAviationGuard.ts +0 -70
- package/tui/src/tools/_shared/nmcAedGuard.ts +0 -234
- package/tui/src/tools/_shared/protectedCheckGuard.ts +0 -207
- package/tui/src/tools/_shared/textToolCallGuard.ts +0 -91
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import type { Tool } from '../../Tool.js'
|
|
2
|
+
|
|
3
|
+
const SOURCE_SUPPORT_INTENT_PATTERN =
|
|
4
|
+
/출처|근거|인용|참고\s*문헌|레퍼런스|출전|증빙|증거|자료\s*(?:출처|근거|조사|검색)|최신|현재\s*(?:정보|자료)|웹\s*검색|source|citation|evidence|provenance|reference|bibliography|current\s+(?:information|source|research)|latest|web\s*search|search\s+the\s+web|https?:\/\//iu
|
|
5
|
+
|
|
6
|
+
const MCP_SUPPORT_INTENT_PATTERN =
|
|
7
|
+
/(?:\bmcp\b|mcp__|(?=.*(?:리소스|자원|resources?))(?=.*(?:신뢰\s*경계|신뢰|경계|trust|boundary|connected\s+servers?|서버\s*(?:리소스|자원)|servers?\s+resources?)))/iu
|
|
8
|
+
|
|
9
|
+
const AGENT_SUPPORT_INTENT_PATTERN =
|
|
10
|
+
/에이전트|sub-?agent|agent|별도\s*작업|하위\s*작업|작업자|작업\s*도구|진행\s*상황|취소\s*가능|cancel(?:lable)?\s+task|delegat(?:e|ion)|background\s+task/iu
|
|
11
|
+
|
|
12
|
+
const KOREAN_QUERY_EXPANSIONS: readonly {
|
|
13
|
+
readonly pattern: RegExp
|
|
14
|
+
readonly terms: readonly string[]
|
|
15
|
+
}[] = [
|
|
16
|
+
{
|
|
17
|
+
pattern:
|
|
18
|
+
/(?=.*(?:저장소|작업\s*공간|워크\s*스페이스|로컬|프로젝트|코드\s*베이스|repository|repo|workspace|codebase))(?=.*(?:파일|경로|첫\s*줄|읽|검색|찾|grep|read))/iu,
|
|
19
|
+
terms: ['+workspace', 'local', 'file', 'read', 'grep', 'search'],
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
pattern: SOURCE_SUPPORT_INTENT_PATTERN,
|
|
23
|
+
terms: [
|
|
24
|
+
'web',
|
|
25
|
+
'search',
|
|
26
|
+
'current',
|
|
27
|
+
'information',
|
|
28
|
+
'fetch',
|
|
29
|
+
'url',
|
|
30
|
+
'source',
|
|
31
|
+
'verification',
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
pattern: MCP_SUPPORT_INTENT_PATTERN,
|
|
36
|
+
terms: ['mcp', 'resources', 'list', 'connected', 'servers'],
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
pattern: AGENT_SUPPORT_INTENT_PATTERN,
|
|
40
|
+
terms: ['+agent', 'delegate', 'subagent', 'task', 'cancel', 'progress'],
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
pattern: /쉘|셸|명령|터미널|git/iu,
|
|
44
|
+
terms: ['shell', 'bash', 'commands', 'permission', 'blocked'],
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
pattern: /쓰기|작성|저장|파일|메모|승인|작업공간/iu,
|
|
48
|
+
terms: ['create', 'overwrite', 'local', 'text', 'files', 'permission', 'blocked'],
|
|
49
|
+
},
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
const SUPPORT_TOOL_NAMES_BY_PATTERN: readonly {
|
|
53
|
+
readonly pattern: RegExp
|
|
54
|
+
readonly toolNames: readonly string[]
|
|
55
|
+
}[] = [
|
|
56
|
+
{
|
|
57
|
+
pattern:
|
|
58
|
+
/(?=.*(?:저장소|작업\s*공간|워크\s*스페이스|로컬|프로젝트|코드\s*베이스|repository|repo|workspace|codebase))(?=.*(?:파일|경로|첫\s*줄|읽|검색|찾|grep|read))/iu,
|
|
59
|
+
toolNames: ['workspace_grep', 'workspace_read'],
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
pattern: SOURCE_SUPPORT_INTENT_PATTERN,
|
|
63
|
+
toolNames: ['WebSearch', 'WebFetch'],
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
pattern: MCP_SUPPORT_INTENT_PATTERN,
|
|
67
|
+
toolNames: ['ListMcpResourcesTool'],
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
pattern: AGENT_SUPPORT_INTENT_PATTERN,
|
|
71
|
+
toolNames: ['Agent'],
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
pattern: /쉘|셸|명령|터미널|git/iu,
|
|
75
|
+
toolNames: ['workspace_bash'],
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
pattern: /쓰기|작성|저장|파일|메모|승인|작업공간/iu,
|
|
79
|
+
toolNames: ['workspace_write'],
|
|
80
|
+
},
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
export function expandedToolSearchTerms(queryLower: string): string[] {
|
|
84
|
+
const terms = queryLower.split(/\s+/).filter(term => term.length > 0)
|
|
85
|
+
for (const expansion of KOREAN_QUERY_EXPANSIONS) {
|
|
86
|
+
if (expansion.pattern.test(queryLower)) {
|
|
87
|
+
terms.push(...expansion.terms)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return [...new Set(terms)]
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function expandedIntentTermSet(queryLower: string): ReadonlySet<string> {
|
|
94
|
+
const expandedTerms: string[] = []
|
|
95
|
+
for (const expansion of KOREAN_QUERY_EXPANSIONS) {
|
|
96
|
+
if (expansion.pattern.test(queryLower)) {
|
|
97
|
+
expandedTerms.push(
|
|
98
|
+
...expansion.terms.map(term =>
|
|
99
|
+
term.startsWith('+') ? term.slice(1) : term,
|
|
100
|
+
),
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return new Set(expandedTerms)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function selectRecoveredSupportToolNamesForQuery(
|
|
108
|
+
query: string,
|
|
109
|
+
): readonly string[] {
|
|
110
|
+
const queryLower = query.toLowerCase()
|
|
111
|
+
const shellIntent = /쉘|셸|명령|터미널|git/iu.test(queryLower)
|
|
112
|
+
const localWorkspaceFileIntent =
|
|
113
|
+
/(?:저장소|작업\s*공간|워크\s*스페이스|로컬|프로젝트|코드\s*베이스|repository|repo|workspace|codebase)/iu.test(
|
|
114
|
+
queryLower,
|
|
115
|
+
) &&
|
|
116
|
+
/(?:파일|경로|첫\s*줄|읽|검색|찾|grep|read)/iu.test(queryLower)
|
|
117
|
+
if (localWorkspaceFileIntent && !shellIntent) {
|
|
118
|
+
return ['workspace_grep', 'workspace_read']
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const toolNames: string[] = []
|
|
122
|
+
for (const supportClass of SUPPORT_TOOL_NAMES_BY_PATTERN) {
|
|
123
|
+
if (supportClass.pattern.test(queryLower)) {
|
|
124
|
+
toolNames.push(...supportClass.toolNames)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return [...new Set(toolNames)]
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function sanitizeSearchHint(searchHint: string): string {
|
|
131
|
+
return searchHint
|
|
132
|
+
.replace(/[<>]/g, '')
|
|
133
|
+
.replace(/\s+/g, ' ')
|
|
134
|
+
.trim()
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function formatDeferredToolSearchLine(tool: Tool): string {
|
|
138
|
+
const searchHint = tool.searchHint ? sanitizeSearchHint(tool.searchHint) : ''
|
|
139
|
+
return searchHint ? `${tool.name} - ${searchHint}` : tool.name
|
|
140
|
+
}
|
|
@@ -58,7 +58,7 @@ type OutputSchema = ReturnType<typeof outputSchema>
|
|
|
58
58
|
export type Output = z.infer<OutputSchema>
|
|
59
59
|
|
|
60
60
|
// ---------------------------------------------------------------------------
|
|
61
|
-
// The UMMAYA model identifier (matches services/api/
|
|
61
|
+
// The UMMAYA model identifier (matches services/api/ummaya.ts)
|
|
62
62
|
// ---------------------------------------------------------------------------
|
|
63
63
|
|
|
64
64
|
const UMMAYA_MODEL = 'LGAI-EXAONE/K-EXAONE-236B-A23B'
|
|
@@ -388,7 +388,8 @@ export const VerifyPrimitive = buildTool({
|
|
|
388
388
|
async checkPermissions(_input) {
|
|
389
389
|
return {
|
|
390
390
|
behavior: 'ask' as const,
|
|
391
|
-
message:
|
|
391
|
+
message:
|
|
392
|
+
'권한 위임 필요: 인증 제공자에게 신원 정보를 전달합니다. 계속할까요? / Permission delegation required: send identity information to the auth provider.',
|
|
392
393
|
}
|
|
393
394
|
},
|
|
394
395
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { z } from 'zod/v4'
|
|
2
2
|
import { buildTool, type ToolDef } from '../../Tool.js'
|
|
3
3
|
import type { PermissionUpdate } from '../../types/permissions.js'
|
|
4
|
-
import { formatFileSize } from '../../utils/format.js'
|
|
5
4
|
import { lazySchema } from '../../utils/lazySchema.js'
|
|
6
5
|
import type { PermissionDecision } from '../../utils/permissions/PermissionResult.js'
|
|
7
6
|
import { getRuleByContentsForTool } from '../../utils/permissions/permissions.js'
|
|
7
|
+
import { callWebFetch } from './call.js'
|
|
8
8
|
import { isPreapprovedHost } from './preapproved.js'
|
|
9
9
|
import { DESCRIPTION, WEB_FETCH_TOOL_NAME } from './prompt.js'
|
|
10
10
|
import {
|
|
@@ -14,12 +14,12 @@ import {
|
|
|
14
14
|
renderToolUseProgressMessage,
|
|
15
15
|
} from './UI.js'
|
|
16
16
|
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
} from './
|
|
17
|
+
formatSourceVerifiedToolResult,
|
|
18
|
+
sourceVerificationSchema,
|
|
19
|
+
} from './sourceVerification.js'
|
|
20
|
+
import type { WebFetchOutput } from './types.js'
|
|
21
|
+
import { validateResolvedPublicWebFetchUrl } from './resolvedAddressSafety.js'
|
|
22
|
+
import { validatePublicWebFetchUrl } from './urlSafety.js'
|
|
23
23
|
|
|
24
24
|
const inputSchema = lazySchema(() =>
|
|
25
25
|
z.strictObject({
|
|
@@ -41,42 +41,31 @@ const outputSchema = lazySchema(() =>
|
|
|
41
41
|
.number()
|
|
42
42
|
.describe('Time taken to fetch and process the content'),
|
|
43
43
|
url: z.string().describe('The URL that was fetched'),
|
|
44
|
+
sourceVerification: sourceVerificationSchema.optional(),
|
|
44
45
|
}),
|
|
45
46
|
)
|
|
46
47
|
type OutputSchema = ReturnType<typeof outputSchema>
|
|
47
48
|
|
|
48
|
-
export type Output =
|
|
49
|
+
export type Output = WebFetchOutput
|
|
49
50
|
|
|
50
51
|
function webFetchToolInputToPermissionRuleContent(input: {
|
|
51
|
-
|
|
52
|
+
readonly url: string
|
|
52
53
|
}): string {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (!parsedInput.success) {
|
|
56
|
-
return `input:${input.toString()}`
|
|
57
|
-
}
|
|
58
|
-
const { url } = parsedInput.data
|
|
59
|
-
const hostname = new URL(url).hostname
|
|
60
|
-
return `domain:${hostname}`
|
|
61
|
-
} catch {
|
|
62
|
-
return `input:${input.toString()}`
|
|
63
|
-
}
|
|
54
|
+
const validation = validatePublicWebFetchUrl(input.url)
|
|
55
|
+
return validation.ok ? `domain:${validation.hostname}` : `input:${input.url}`
|
|
64
56
|
}
|
|
65
57
|
|
|
66
58
|
export const WebFetchTool = buildTool({
|
|
67
59
|
name: WEB_FETCH_TOOL_NAME,
|
|
68
|
-
searchHint: 'fetch and extract content from a URL',
|
|
60
|
+
searchHint: 'fetch and extract content from a URL for source verification',
|
|
69
61
|
// 100K chars - tool result persistence threshold
|
|
70
62
|
maxResultSizeChars: 100_000,
|
|
71
63
|
shouldDefer: true,
|
|
72
64
|
async description(input) {
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
} catch {
|
|
78
|
-
return `UMMAYA wants to fetch content from this URL`
|
|
79
|
-
}
|
|
65
|
+
const validation = validatePublicWebFetchUrl(input.url)
|
|
66
|
+
return validation.ok
|
|
67
|
+
? `UMMAYA wants to fetch content from ${validation.hostname}`
|
|
68
|
+
: `UMMAYA wants to fetch content from this URL`
|
|
80
69
|
},
|
|
81
70
|
userFacingName() {
|
|
82
71
|
return 'Fetch'
|
|
@@ -104,20 +93,28 @@ export const WebFetchTool = buildTool({
|
|
|
104
93
|
async checkPermissions(input, context): Promise<PermissionDecision> {
|
|
105
94
|
const appState = context.getAppState()
|
|
106
95
|
const permissionContext = appState.toolPermissionContext
|
|
96
|
+
const validation = await validateResolvedPublicWebFetchUrl(input.url)
|
|
97
|
+
|
|
98
|
+
if (!validation.ok) {
|
|
99
|
+
return {
|
|
100
|
+
behavior: 'deny',
|
|
101
|
+
message: `${WebFetchTool.name} rejected unsafe URL: ${validation.message}`,
|
|
102
|
+
decisionReason: { type: 'other', reason: validation.reason },
|
|
103
|
+
}
|
|
104
|
+
}
|
|
107
105
|
|
|
108
106
|
// Check if the hostname is in the preapproved list
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
107
|
+
if (
|
|
108
|
+
isPreapprovedHost(
|
|
109
|
+
validation.parsedUrl.hostname,
|
|
110
|
+
validation.parsedUrl.pathname,
|
|
111
|
+
)
|
|
112
|
+
) {
|
|
113
|
+
return {
|
|
114
|
+
behavior: 'allow',
|
|
115
|
+
updatedInput: input,
|
|
116
|
+
decisionReason: { type: 'other', reason: 'Preapproved host' },
|
|
118
117
|
}
|
|
119
|
-
} catch {
|
|
120
|
-
// If URL parsing fails, continue with normal permission checks
|
|
121
118
|
}
|
|
122
119
|
|
|
123
120
|
// Check for a rule specific to the tool input (matching hostname)
|
|
@@ -190,13 +187,12 @@ ${DESCRIPTION}`
|
|
|
190
187
|
},
|
|
191
188
|
async validateInput(input) {
|
|
192
189
|
const { url } = input
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
} catch {
|
|
190
|
+
const validation = await validateResolvedPublicWebFetchUrl(url)
|
|
191
|
+
if (!validation.ok) {
|
|
196
192
|
return {
|
|
197
193
|
result: false,
|
|
198
|
-
message: `Error:
|
|
199
|
-
meta: { reason:
|
|
194
|
+
message: `Error: ${validation.message}`,
|
|
195
|
+
meta: { reason: validation.reason },
|
|
200
196
|
errorCode: 1,
|
|
201
197
|
}
|
|
202
198
|
}
|
|
@@ -205,103 +201,12 @@ ${DESCRIPTION}`
|
|
|
205
201
|
renderToolUseMessage,
|
|
206
202
|
renderToolUseProgressMessage,
|
|
207
203
|
renderToolResultMessage,
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
{ abortController, options: { isNonInteractiveSession } },
|
|
211
|
-
) {
|
|
212
|
-
const start = Date.now()
|
|
213
|
-
|
|
214
|
-
const response = await getURLMarkdownContent(url, abortController)
|
|
215
|
-
|
|
216
|
-
// Check if we got a redirect to a different host
|
|
217
|
-
if ('type' in response && response.type === 'redirect') {
|
|
218
|
-
const statusText =
|
|
219
|
-
response.statusCode === 301
|
|
220
|
-
? 'Moved Permanently'
|
|
221
|
-
: response.statusCode === 308
|
|
222
|
-
? 'Permanent Redirect'
|
|
223
|
-
: response.statusCode === 307
|
|
224
|
-
? 'Temporary Redirect'
|
|
225
|
-
: 'Found'
|
|
226
|
-
|
|
227
|
-
const message = `REDIRECT DETECTED: The URL redirects to a different host.
|
|
228
|
-
|
|
229
|
-
Original URL: ${response.originalUrl}
|
|
230
|
-
Redirect URL: ${response.redirectUrl}
|
|
231
|
-
Status: ${response.statusCode} ${statusText}
|
|
232
|
-
|
|
233
|
-
To complete your request, I need to fetch content from the redirected URL. Please use WebFetch again with these parameters:
|
|
234
|
-
- url: "${response.redirectUrl}"
|
|
235
|
-
- prompt: "${prompt}"`
|
|
236
|
-
|
|
237
|
-
const output: Output = {
|
|
238
|
-
bytes: Buffer.byteLength(message),
|
|
239
|
-
code: response.statusCode,
|
|
240
|
-
codeText: statusText,
|
|
241
|
-
result: message,
|
|
242
|
-
durationMs: Date.now() - start,
|
|
243
|
-
url,
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
return {
|
|
247
|
-
data: output,
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const {
|
|
252
|
-
content,
|
|
253
|
-
bytes,
|
|
254
|
-
code,
|
|
255
|
-
codeText,
|
|
256
|
-
contentType,
|
|
257
|
-
persistedPath,
|
|
258
|
-
persistedSize,
|
|
259
|
-
} = response as FetchedContent
|
|
260
|
-
|
|
261
|
-
const isPreapproved = isPreapprovedUrl(url)
|
|
262
|
-
|
|
263
|
-
let result: string
|
|
264
|
-
if (
|
|
265
|
-
isPreapproved &&
|
|
266
|
-
contentType.includes('text/markdown') &&
|
|
267
|
-
content.length < MAX_MARKDOWN_LENGTH
|
|
268
|
-
) {
|
|
269
|
-
result = content
|
|
270
|
-
} else {
|
|
271
|
-
result = await applyPromptToMarkdown(
|
|
272
|
-
prompt,
|
|
273
|
-
content,
|
|
274
|
-
abortController.signal,
|
|
275
|
-
isNonInteractiveSession,
|
|
276
|
-
isPreapproved,
|
|
277
|
-
)
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
// Binary content (PDFs, etc.) was additionally saved to disk with a
|
|
281
|
-
// mime-derived extension. Note it so Claude can inspect the raw file
|
|
282
|
-
// if the Haiku summary above isn't enough.
|
|
283
|
-
if (persistedPath) {
|
|
284
|
-
result += `\n\n[Binary content (${contentType}, ${formatFileSize(persistedSize ?? bytes)}) also saved to ${persistedPath}]`
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
const output: Output = {
|
|
288
|
-
bytes,
|
|
289
|
-
code,
|
|
290
|
-
codeText,
|
|
291
|
-
result,
|
|
292
|
-
durationMs: Date.now() - start,
|
|
293
|
-
url,
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
return {
|
|
297
|
-
data: output,
|
|
298
|
-
}
|
|
299
|
-
},
|
|
300
|
-
mapToolResultToToolResultBlockParam({ result }, toolUseID) {
|
|
204
|
+
call: callWebFetch,
|
|
205
|
+
mapToolResultToToolResultBlockParam({ result, sourceVerification }, toolUseID) {
|
|
301
206
|
return {
|
|
302
207
|
tool_use_id: toolUseID,
|
|
303
208
|
type: 'tool_result',
|
|
304
|
-
content: result,
|
|
209
|
+
content: formatSourceVerifiedToolResult({ result, sourceVerification }),
|
|
305
210
|
}
|
|
306
211
|
},
|
|
307
212
|
} satisfies ToolDef<InputSchema, Output>)
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import type { ToolResult } from '../../Tool.js'
|
|
2
|
+
import { errorMessage, isAbortError } from '../../utils/errors.js'
|
|
3
|
+
import { formatFileSize } from '../../utils/format.js'
|
|
4
|
+
import { WEB_FETCH_TOOL_NAME } from './prompt.js'
|
|
5
|
+
import {
|
|
6
|
+
buildSourceEvidence,
|
|
7
|
+
buildSourceVerification,
|
|
8
|
+
redactSourceVerificationText,
|
|
9
|
+
} from './sourceVerification.js'
|
|
10
|
+
import type {
|
|
11
|
+
WebFetchCallContext,
|
|
12
|
+
WebFetchCallInput,
|
|
13
|
+
WebFetchOutput,
|
|
14
|
+
} from './types.js'
|
|
15
|
+
import { validateResolvedPublicWebFetchUrl } from './resolvedAddressSafety.js'
|
|
16
|
+
import {
|
|
17
|
+
applyPromptToMarkdown,
|
|
18
|
+
getURLMarkdownContent,
|
|
19
|
+
isPreapprovedUrl,
|
|
20
|
+
MAX_MARKDOWN_LENGTH,
|
|
21
|
+
} from './utils.js'
|
|
22
|
+
|
|
23
|
+
export async function callWebFetch(
|
|
24
|
+
{ url, prompt }: WebFetchCallInput,
|
|
25
|
+
{ abortController, options: { isNonInteractiveSession } }: WebFetchCallContext,
|
|
26
|
+
): Promise<ToolResult<WebFetchOutput>> {
|
|
27
|
+
const start = Date.now()
|
|
28
|
+
const validation = await validateResolvedPublicWebFetchUrl(url)
|
|
29
|
+
if (!validation.ok) {
|
|
30
|
+
return blockedToolResult({
|
|
31
|
+
url,
|
|
32
|
+
start,
|
|
33
|
+
message: `Source verification blocked: ${validation.message}`,
|
|
34
|
+
sourceUrl: null,
|
|
35
|
+
title: 'Unsafe URL',
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
const response = await getURLMarkdownContent(url, abortController)
|
|
41
|
+
|
|
42
|
+
if ('type' in response && response.type === 'redirect') {
|
|
43
|
+
const redirectValidation = await validateResolvedPublicWebFetchUrl(
|
|
44
|
+
response.redirectUrl,
|
|
45
|
+
)
|
|
46
|
+
if (!redirectValidation.ok) {
|
|
47
|
+
return blockedToolResult({
|
|
48
|
+
url,
|
|
49
|
+
start,
|
|
50
|
+
code: response.statusCode,
|
|
51
|
+
codeText: 'Redirect Target Blocked',
|
|
52
|
+
message: `Source verification blocked: ${redirectValidation.message}`,
|
|
53
|
+
sourceUrl: null,
|
|
54
|
+
title: 'Unsafe redirect target',
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
return redirectedToolResult({
|
|
58
|
+
url,
|
|
59
|
+
prompt,
|
|
60
|
+
start,
|
|
61
|
+
originalUrl: response.originalUrl,
|
|
62
|
+
redirectUrl: response.redirectUrl,
|
|
63
|
+
statusCode: response.statusCode,
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const {
|
|
68
|
+
content,
|
|
69
|
+
bytes,
|
|
70
|
+
code,
|
|
71
|
+
codeText,
|
|
72
|
+
contentType,
|
|
73
|
+
persistedPath,
|
|
74
|
+
persistedSize,
|
|
75
|
+
} = response
|
|
76
|
+
const isPreapproved = isPreapprovedUrl(url)
|
|
77
|
+
let result =
|
|
78
|
+
isPreapproved &&
|
|
79
|
+
contentType.includes('text/markdown') &&
|
|
80
|
+
content.length < MAX_MARKDOWN_LENGTH
|
|
81
|
+
? content
|
|
82
|
+
: await applyPromptToMarkdown(
|
|
83
|
+
prompt,
|
|
84
|
+
content,
|
|
85
|
+
abortController.signal,
|
|
86
|
+
isNonInteractiveSession,
|
|
87
|
+
isPreapproved,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
if (persistedPath) {
|
|
91
|
+
result += `\n\n[Binary content (${contentType}, ${formatFileSize(persistedSize ?? bytes)}) also saved to ${persistedPath}]`
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const sourceVerification = buildSourceVerification([
|
|
95
|
+
buildSourceEvidence({
|
|
96
|
+
toolId: WEB_FETCH_TOOL_NAME,
|
|
97
|
+
sourceUrl: url,
|
|
98
|
+
title: contentType,
|
|
99
|
+
blockedOrUsed: 'needs_input',
|
|
100
|
+
rawText: result,
|
|
101
|
+
}),
|
|
102
|
+
])
|
|
103
|
+
const safeResult = redactSourceVerificationText(result)
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
data: {
|
|
107
|
+
bytes,
|
|
108
|
+
code,
|
|
109
|
+
codeText,
|
|
110
|
+
result: safeResult,
|
|
111
|
+
durationMs: Date.now() - start,
|
|
112
|
+
url,
|
|
113
|
+
sourceVerification,
|
|
114
|
+
},
|
|
115
|
+
}
|
|
116
|
+
} catch (error) {
|
|
117
|
+
if (isAbortError(error)) throw error
|
|
118
|
+
const message = `Source verification blocked: ${errorMessage(error)}`
|
|
119
|
+
return blockedToolResult({
|
|
120
|
+
url,
|
|
121
|
+
start,
|
|
122
|
+
message,
|
|
123
|
+
sourceUrl: url,
|
|
124
|
+
title: 'Provider error',
|
|
125
|
+
})
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function redirectedToolResult({
|
|
130
|
+
url,
|
|
131
|
+
prompt,
|
|
132
|
+
start,
|
|
133
|
+
originalUrl,
|
|
134
|
+
redirectUrl,
|
|
135
|
+
statusCode,
|
|
136
|
+
}: {
|
|
137
|
+
readonly url: string
|
|
138
|
+
readonly prompt: string
|
|
139
|
+
readonly start: number
|
|
140
|
+
readonly originalUrl: string
|
|
141
|
+
readonly redirectUrl: string
|
|
142
|
+
readonly statusCode: number
|
|
143
|
+
}): ToolResult<WebFetchOutput> {
|
|
144
|
+
const statusText = redirectStatusText(statusCode)
|
|
145
|
+
const message = `REDIRECT DETECTED: The URL redirects to a different host.
|
|
146
|
+
|
|
147
|
+
Original URL: ${originalUrl}
|
|
148
|
+
Redirect URL: ${redirectUrl}
|
|
149
|
+
Status: ${statusCode} ${statusText}
|
|
150
|
+
|
|
151
|
+
To complete your request, I need to fetch content from the redirected URL. Please use WebFetch again with these parameters:
|
|
152
|
+
- url: "${redirectUrl}"
|
|
153
|
+
- prompt: "${prompt}"`
|
|
154
|
+
const safeMessage = redactSourceVerificationText(message)
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
data: {
|
|
158
|
+
bytes: Buffer.byteLength(safeMessage),
|
|
159
|
+
code: statusCode,
|
|
160
|
+
codeText: statusText,
|
|
161
|
+
result: safeMessage,
|
|
162
|
+
durationMs: Date.now() - start,
|
|
163
|
+
url,
|
|
164
|
+
sourceVerification: buildSourceVerification([
|
|
165
|
+
buildSourceEvidence({
|
|
166
|
+
toolId: WEB_FETCH_TOOL_NAME,
|
|
167
|
+
sourceUrl: redirectUrl,
|
|
168
|
+
title: 'Redirect target',
|
|
169
|
+
blockedOrUsed: 'needs_input',
|
|
170
|
+
rawText: message,
|
|
171
|
+
}),
|
|
172
|
+
]),
|
|
173
|
+
},
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function blockedToolResult({
|
|
178
|
+
url,
|
|
179
|
+
start,
|
|
180
|
+
message,
|
|
181
|
+
sourceUrl,
|
|
182
|
+
title,
|
|
183
|
+
code = 0,
|
|
184
|
+
codeText = 'Source Verification Blocked',
|
|
185
|
+
}: {
|
|
186
|
+
readonly url: string
|
|
187
|
+
readonly start: number
|
|
188
|
+
readonly message: string
|
|
189
|
+
readonly sourceUrl: string | null
|
|
190
|
+
readonly title: string
|
|
191
|
+
readonly code?: number
|
|
192
|
+
readonly codeText?: string
|
|
193
|
+
}): ToolResult<WebFetchOutput> {
|
|
194
|
+
const safeMessage = redactSourceVerificationText(message)
|
|
195
|
+
return {
|
|
196
|
+
data: {
|
|
197
|
+
bytes: Buffer.byteLength(safeMessage),
|
|
198
|
+
code,
|
|
199
|
+
codeText,
|
|
200
|
+
result: safeMessage,
|
|
201
|
+
durationMs: Date.now() - start,
|
|
202
|
+
url,
|
|
203
|
+
sourceVerification: buildSourceVerification([
|
|
204
|
+
buildSourceEvidence({
|
|
205
|
+
toolId: WEB_FETCH_TOOL_NAME,
|
|
206
|
+
sourceUrl,
|
|
207
|
+
title,
|
|
208
|
+
blockedOrUsed: 'blocked',
|
|
209
|
+
rawText: message,
|
|
210
|
+
}),
|
|
211
|
+
]),
|
|
212
|
+
},
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function redirectStatusText(statusCode: number): string {
|
|
217
|
+
switch (statusCode) {
|
|
218
|
+
case 301:
|
|
219
|
+
return 'Moved Permanently'
|
|
220
|
+
case 307:
|
|
221
|
+
return 'Temporary Redirect'
|
|
222
|
+
case 308:
|
|
223
|
+
return 'Permanent Redirect'
|
|
224
|
+
default:
|
|
225
|
+
return 'Found'
|
|
226
|
+
}
|
|
227
|
+
}
|