ummaya 0.2.4 → 0.2.5
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/npm-shrinkwrap.json +253 -2
- package/package.json +5 -1
- package/prompts/manifest.yaml +1 -1
- package/prompts/system_v1.md +1 -0
- package/pyproject.toml +26 -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/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 +114 -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/package.json +1 -1
- 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/print.ts +7 -7
- 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 +29 -11
- 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/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 +400 -14
- 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
|
@@ -28,11 +28,11 @@ import {
|
|
|
28
28
|
} from '../../services/api/adapterManifest.js'
|
|
29
29
|
import { FIND_TOOL_NAME, DESCRIPTION, FIND_TOOL_PROMPT } from './prompt.js'
|
|
30
30
|
import { dispatchPrimitive } from '../_shared/dispatchPrimitive.js'
|
|
31
|
-
import {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
import {
|
|
32
|
+
applyDocumentVisualRenderGateToOutput,
|
|
33
|
+
isDocumentVisualRenderFailedOutput,
|
|
34
|
+
renderDocumentToolResultIfPresent,
|
|
35
|
+
} from '../_shared/documentToolResultRender.js'
|
|
36
36
|
import {
|
|
37
37
|
renderVerboseInputJson,
|
|
38
38
|
renderVerboseOutputJson,
|
|
@@ -631,26 +631,27 @@ export const LookupPrimitive = buildTool({
|
|
|
631
631
|
},
|
|
632
632
|
|
|
633
633
|
mapToolResultToToolResultBlockParam(output, toolUseID) {
|
|
634
|
+
const gatedOutput = applyDocumentVisualRenderGateToOutput(output)
|
|
634
635
|
// Spec 2521 (2026-05-02) — strip ``outbound_traces`` from the
|
|
635
636
|
// LLM-facing content. The trace is UI-only (verbose render);
|
|
636
637
|
// shipping raw HTTP bodies back into the next turn would bloat
|
|
637
638
|
// K-EXAONE's context with KMA/data.go.kr response payloads.
|
|
638
639
|
const llmContent =
|
|
639
|
-
typeof
|
|
640
|
+
typeof gatedOutput === 'object' && gatedOutput !== null
|
|
640
641
|
? Object.fromEntries(
|
|
641
|
-
Object.entries(
|
|
642
|
+
Object.entries(gatedOutput as Record<string, unknown>).filter(
|
|
642
643
|
([k]) => k !== 'outbound_traces',
|
|
643
644
|
),
|
|
644
645
|
)
|
|
645
|
-
:
|
|
646
|
+
: gatedOutput
|
|
646
647
|
return {
|
|
647
648
|
tool_use_id: toolUseID,
|
|
648
649
|
type: 'tool_result',
|
|
649
650
|
content: JSON.stringify(llmContent),
|
|
651
|
+
...(isDocumentVisualRenderFailedOutput(gatedOutput) ? { is_error: true } : {}),
|
|
650
652
|
}
|
|
651
653
|
},
|
|
652
654
|
|
|
653
|
-
// UMMAYA hotfix #2518 follow-up — CC pattern (tools/BashTool/UI.tsx:renderToolUseMessage).
|
|
654
655
|
// Return an args preview so the citizen can see which tool was dispatched.
|
|
655
656
|
// Spec 2521 (2026-05-01) — fetch-only surface; legacy mode='search'
|
|
656
657
|
// payloads from older sessions surface as the bare tool_id.
|
|
@@ -697,21 +698,6 @@ export const LookupPrimitive = buildTool({
|
|
|
697
698
|
}
|
|
698
699
|
}
|
|
699
700
|
|
|
700
|
-
const protectedChoice = validateProtectedCheckToolChoice(input.tool_id, context)
|
|
701
|
-
if (protectedChoice) return protectedChoice
|
|
702
|
-
const directPublicDataChoice = validateDirectPublicDataToolChoice(
|
|
703
|
-
input.tool_id,
|
|
704
|
-
context,
|
|
705
|
-
input.params,
|
|
706
|
-
)
|
|
707
|
-
if (directPublicDataChoice) return directPublicDataChoice
|
|
708
|
-
const kmaAviationChoice = validateKmaAviationToolChoice(input.tool_id, context)
|
|
709
|
-
if (kmaAviationChoice) return kmaAviationChoice
|
|
710
|
-
const kmaAnalysisChoice = validateKmaAnalysisToolChoice(input.tool_id, context)
|
|
711
|
-
if (kmaAnalysisChoice) return kmaAnalysisChoice
|
|
712
|
-
const nmcAedChoice = validateNmcAedToolChoice(input.tool_id, context)
|
|
713
|
-
if (nmcAedChoice) return nmcAedChoice
|
|
714
|
-
|
|
715
701
|
// Tier 1 — synced backend manifest (FR-017).
|
|
716
702
|
if (isManifestSynced()) {
|
|
717
703
|
const backendEntry = resolveAdapter(input.tool_id)
|
|
@@ -787,14 +773,17 @@ export const LookupPrimitive = buildTool({
|
|
|
787
773
|
_progress: unknown,
|
|
788
774
|
options: { verbose: boolean; isTranscriptMode?: boolean } = { verbose: false },
|
|
789
775
|
): React.ReactNode {
|
|
776
|
+
const gatedOutput = applyDocumentVisualRenderGateToOutput(output) as Output
|
|
777
|
+
const documentResult = renderDocumentToolResultIfPresent(gatedOutput, options)
|
|
778
|
+
if (documentResult !== null) {
|
|
779
|
+
return documentResult
|
|
780
|
+
}
|
|
790
781
|
// Spec 2521 (2026-05-01 evening) — Ctrl+O expand / transcript mode
|
|
791
782
|
// surfaces the full envelope JSON the backend returned. Mirrors
|
|
792
783
|
// CC BashTool/UI.tsx:renderToolResultMessage(verbose).
|
|
793
784
|
if (options.verbose || options.isTranscriptMode) {
|
|
794
|
-
return renderVerboseOutputJson(
|
|
785
|
+
return renderVerboseOutputJson(gatedOutput)
|
|
795
786
|
}
|
|
796
|
-
// UMMAYA hotfix #2519 (CC-original migration, 2026-04-30):
|
|
797
|
-
//
|
|
798
787
|
// After the dispatchPrimitive register-and-await rewrite, output.result
|
|
799
788
|
// is the actual primitive output (the inner of the backend envelope:
|
|
800
789
|
// src/ummaya/tools/find.py LookupSearchResult / LookupRecord /
|
|
@@ -802,8 +791,8 @@ export const LookupPrimitive = buildTool({
|
|
|
802
791
|
// its own `kind` field. The CC pattern wraps each branch in
|
|
803
792
|
// <MessageResponse> so the " ⎿ " gutter glyph prefixes every row
|
|
804
793
|
// (tui/src/components/MessageResponse.tsx:22).
|
|
805
|
-
if (!
|
|
806
|
-
const message = extractErrorMessage(
|
|
794
|
+
if (!gatedOutput.ok) {
|
|
795
|
+
const message = extractErrorMessage(gatedOutput.error.message)
|
|
807
796
|
return React.createElement(
|
|
808
797
|
MessageResponse,
|
|
809
798
|
null,
|
|
@@ -815,7 +804,7 @@ export const LookupPrimitive = buildTool({
|
|
|
815
804
|
)
|
|
816
805
|
}
|
|
817
806
|
|
|
818
|
-
const result =
|
|
807
|
+
const result = gatedOutput.result as Record<string, unknown>
|
|
819
808
|
|
|
820
809
|
// search mode (LookupSearchResult, models.py:820):
|
|
821
810
|
// { kind: "search", candidates: [AdapterCandidate], total_registry_size, effective_top_k, reason }
|
|
@@ -872,12 +861,16 @@ export const LookupPrimitive = buildTool({
|
|
|
872
861
|
* validateInput has already resolved the adapter and populated ummayaCitations on the context.
|
|
873
862
|
*/
|
|
874
863
|
async call(input, context) {
|
|
875
|
-
|
|
864
|
+
const result = await dispatchPrimitive<Output>({
|
|
876
865
|
primitive: 'find',
|
|
877
|
-
args: input
|
|
866
|
+
args: input,
|
|
878
867
|
context,
|
|
879
868
|
registry: getOrCreatePendingCallRegistry(),
|
|
880
869
|
bridge: getOrCreateUmmayaBridge(),
|
|
881
870
|
})
|
|
871
|
+
return {
|
|
872
|
+
...result,
|
|
873
|
+
data: applyDocumentVisualRenderGateToOutput(result.data) as Output,
|
|
874
|
+
}
|
|
882
875
|
},
|
|
883
876
|
} satisfies ToolDef<InputSchema, Output>)
|
|
@@ -17,7 +17,6 @@ export const FIND_TOOL_PROMPT = `Discover Korean public-service lookup adapters
|
|
|
17
17
|
|
|
18
18
|
Preferred path:
|
|
19
19
|
- Call concrete adapter functions directly after their schemas are loaded.
|
|
20
|
-
- Example: kma_current_observation({ base_date: "YYYYMMDD", base_time: "HH00", nx: 97, ny: 74 })
|
|
21
20
|
- Adapter ids and schemas are progressively disclosed by ToolSearch, adapter_manifest, or backend top-K retrieval for the current citizen request.
|
|
22
21
|
- Only top candidates should be loaded; do not expect every adapter schema in the prompt.
|
|
23
22
|
- A concrete adapter id may be valid even when it is not listed in <available-deferred-tools>; if it appears in <available_adapters> or adapter_manifest and its function is loaded, call that function directly with its schema fields.
|
|
@@ -26,7 +25,6 @@ Legacy root wrapper:
|
|
|
26
25
|
- If a concrete adapter function is not loaded and only the root primitive is available, find accepts { tool_id, params } for old transcripts and compatibility paths.
|
|
27
26
|
- tool_id must be a concrete adapter id from <available_adapters>, never "find", "locate", "check", or "send".
|
|
28
27
|
- Invalid: find({ tool_id: "find", params: {...} })
|
|
29
|
-
- Compatibility-only: find({ tool_id: "kma_apihub_url_air_metar_decoded", params: { org: "K", help: 1 } })
|
|
30
28
|
|
|
31
29
|
Rules:
|
|
32
30
|
- Do not call find with mode='search' or query; discovery is handled outside the primitive call.
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { mcpInfoFromString } from '../../services/mcp/mcpStringUtils.js'
|
|
2
|
+
import type { ToolPermissionContext, ToolUseContext } from '../../Tool.js'
|
|
3
|
+
import type { PermissionResult } from '../../utils/permissions/PermissionResult.js'
|
|
4
|
+
import {
|
|
5
|
+
getAllowRules,
|
|
6
|
+
getDenyRuleForTool,
|
|
7
|
+
} from '../../utils/permissions/permissions.js'
|
|
8
|
+
|
|
9
|
+
const TRUSTED_BUILTIN_MCP_SERVERS = ['ummaya'] as const
|
|
10
|
+
|
|
11
|
+
type McpTrustInput = { readonly [key: string]: unknown }
|
|
12
|
+
|
|
13
|
+
function mcpServerRuleName(serverName: string): string {
|
|
14
|
+
return `mcp__${serverName}`
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function hasExactServerAllowRule(
|
|
18
|
+
permissionContext: ToolPermissionContext,
|
|
19
|
+
serverName: string,
|
|
20
|
+
): boolean {
|
|
21
|
+
return getAllowRules(permissionContext).some(rule => {
|
|
22
|
+
if (rule.ruleValue.ruleContent !== undefined) return false
|
|
23
|
+
const ruleInfo = mcpInfoFromString(rule.ruleValue.toolName)
|
|
24
|
+
if (ruleInfo === null) return false
|
|
25
|
+
return (
|
|
26
|
+
ruleInfo.serverName === serverName &&
|
|
27
|
+
(ruleInfo.toolName === undefined || ruleInfo.toolName === '*')
|
|
28
|
+
)
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function hasServerDenyRule(
|
|
33
|
+
permissionContext: ToolPermissionContext,
|
|
34
|
+
serverName: string,
|
|
35
|
+
): boolean {
|
|
36
|
+
return (
|
|
37
|
+
getDenyRuleForTool(permissionContext, {
|
|
38
|
+
name: mcpServerRuleName(serverName),
|
|
39
|
+
mcpInfo: { serverName, toolName: '*' },
|
|
40
|
+
}) !== null
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function isTrustedMcpServer(
|
|
45
|
+
permissionContext: ToolPermissionContext,
|
|
46
|
+
serverName: string,
|
|
47
|
+
): boolean {
|
|
48
|
+
if (hasServerDenyRule(permissionContext, serverName)) return false
|
|
49
|
+
if (TRUSTED_BUILTIN_MCP_SERVERS.some(name => name === serverName)) return true
|
|
50
|
+
return hasExactServerAllowRule(permissionContext, serverName)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function assertNonEmptyMcpServerName(serverName: string): void {
|
|
54
|
+
if (serverName.trim().length === 0) {
|
|
55
|
+
throw new Error('MCP server name cannot be empty')
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function assertNonEmptyMcpResourceUri(uri: string): void {
|
|
60
|
+
if (uri.trim().length === 0) {
|
|
61
|
+
throw new Error('MCP resource URI cannot be empty')
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function assertTrustedMcpServerForResourceAccess(
|
|
66
|
+
permissionContext: ToolPermissionContext,
|
|
67
|
+
serverName: string,
|
|
68
|
+
): void {
|
|
69
|
+
assertTrustedMcpServer(
|
|
70
|
+
permissionContext,
|
|
71
|
+
serverName,
|
|
72
|
+
`Server "${serverName}" is not trusted for MCP resource access`,
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function assertTrustedMcpServer(
|
|
77
|
+
permissionContext: ToolPermissionContext,
|
|
78
|
+
serverName: string,
|
|
79
|
+
message: string,
|
|
80
|
+
): void {
|
|
81
|
+
assertNonEmptyMcpServerName(serverName)
|
|
82
|
+
if (!isTrustedMcpServer(permissionContext, serverName)) {
|
|
83
|
+
throw new Error(message)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function createMcpServerTrustSuggestion(serverName: string) {
|
|
88
|
+
return {
|
|
89
|
+
type: 'addRules' as const,
|
|
90
|
+
rules: [
|
|
91
|
+
{
|
|
92
|
+
toolName: mcpServerRuleName(serverName),
|
|
93
|
+
ruleContent: undefined,
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
behavior: 'allow' as const,
|
|
97
|
+
destination: 'localSettings' as const,
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function checkMcpServerTrustPermission<Input extends McpTrustInput>(
|
|
102
|
+
serverName: string,
|
|
103
|
+
input: Input,
|
|
104
|
+
context: ToolUseContext,
|
|
105
|
+
message: string,
|
|
106
|
+
): PermissionResult<Input> {
|
|
107
|
+
assertNonEmptyMcpServerName(serverName)
|
|
108
|
+
if (
|
|
109
|
+
isTrustedMcpServer(context.getAppState().toolPermissionContext, serverName)
|
|
110
|
+
) {
|
|
111
|
+
return { behavior: 'allow', updatedInput: input }
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
behavior: 'passthrough',
|
|
115
|
+
message,
|
|
116
|
+
suggestions: [createMcpServerTrustSuggestion(serverName)],
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -18,7 +18,11 @@ import type { Tool } from '../../Tool.js'
|
|
|
18
18
|
import { errorMessage } from '../../utils/errors.js'
|
|
19
19
|
import { lazySchema } from '../../utils/lazySchema.js'
|
|
20
20
|
import { logMCPDebug, logMCPError } from '../../utils/log.js'
|
|
21
|
-
import type {
|
|
21
|
+
import type { PermissionResult } from '../../utils/permissions/PermissionResult.js'
|
|
22
|
+
import {
|
|
23
|
+
assertTrustedMcpServer,
|
|
24
|
+
checkMcpServerTrustPermission,
|
|
25
|
+
} from '../MCPTool/trustPolicy.js'
|
|
22
26
|
|
|
23
27
|
const inputSchema = lazySchema(() => z.object({}))
|
|
24
28
|
type InputSchema = ReturnType<typeof inputSchema>
|
|
@@ -79,10 +83,21 @@ export function createMcpAuthTool(
|
|
|
79
83
|
get inputSchema(): InputSchema {
|
|
80
84
|
return inputSchema()
|
|
81
85
|
},
|
|
82
|
-
async checkPermissions(input): Promise<
|
|
83
|
-
return
|
|
86
|
+
async checkPermissions(input, context): Promise<PermissionResult> {
|
|
87
|
+
return checkMcpServerTrustPermission(
|
|
88
|
+
serverName,
|
|
89
|
+
input,
|
|
90
|
+
context,
|
|
91
|
+
`MCP server "${serverName}" requires trust before authentication can run.`,
|
|
92
|
+
)
|
|
84
93
|
},
|
|
85
94
|
async call(_input, context) {
|
|
95
|
+
assertTrustedMcpServer(
|
|
96
|
+
context.getAppState().toolPermissionContext,
|
|
97
|
+
serverName,
|
|
98
|
+
`MCP server "${serverName}" requires trust before authentication can run.`,
|
|
99
|
+
)
|
|
100
|
+
|
|
86
101
|
// claude.ai connectors use a separate auth flow (handleClaudeAIAuth in
|
|
87
102
|
// MCPRemoteServerMenu) that we don't invoke programmatically here —
|
|
88
103
|
// just point the user at /mcp.
|
|
@@ -196,6 +211,9 @@ export function createMcpAuthTool(
|
|
|
196
211
|
},
|
|
197
212
|
}
|
|
198
213
|
} catch (err) {
|
|
214
|
+
if (!(err instanceof Error)) {
|
|
215
|
+
throw err
|
|
216
|
+
}
|
|
199
217
|
return {
|
|
200
218
|
data: {
|
|
201
219
|
status: 'error' as const,
|
|
@@ -1,22 +1,10 @@
|
|
|
1
1
|
import { feature } from 'bun:bundle'
|
|
2
|
-
import { extname, isAbsolute, resolve } from 'path'
|
|
3
|
-
import {
|
|
4
|
-
fileHistoryEnabled,
|
|
5
|
-
fileHistoryTrackEdit,
|
|
6
|
-
} from 'src/utils/fileHistory.js'
|
|
7
2
|
import { z } from 'zod/v4'
|
|
8
|
-
import { buildTool, type ToolDef
|
|
9
|
-
import type { NotebookCell, NotebookContent } from '../../types/notebook.js'
|
|
10
|
-
import { getCwd } from '../../utils/cwd.js'
|
|
11
|
-
import { isENOENT } from '../../utils/errors.js'
|
|
12
|
-
import { getFileModificationTime, writeTextContent } from '../../utils/file.js'
|
|
13
|
-
import { readFileSyncWithMetadata } from '../../utils/fileRead.js'
|
|
14
|
-
import { safeParseJSON } from '../../utils/json.js'
|
|
3
|
+
import { buildTool, type ToolDef } from '../../Tool.js'
|
|
15
4
|
import { lazySchema } from '../../utils/lazySchema.js'
|
|
16
|
-
import { parseCellId } from '../../utils/notebook.js'
|
|
17
5
|
import { checkWritePermissionForTool } from '../../utils/permissions/filesystem.js'
|
|
18
6
|
import type { PermissionDecision } from '../../utils/permissions/PermissionResult.js'
|
|
19
|
-
import {
|
|
7
|
+
import { callNotebookEditTool } from './call.js'
|
|
20
8
|
import { NOTEBOOK_EDIT_TOOL_NAME } from './constants.js'
|
|
21
9
|
import { DESCRIPTION, PROMPT } from './prompt.js'
|
|
22
10
|
import {
|
|
@@ -26,6 +14,7 @@ import {
|
|
|
26
14
|
renderToolUseMessage,
|
|
27
15
|
renderToolUseRejectedMessage,
|
|
28
16
|
} from './UI.js'
|
|
17
|
+
import { validateNotebookEditInput } from './validateInput.js'
|
|
29
18
|
|
|
30
19
|
export const inputSchema = lazySchema(() =>
|
|
31
20
|
z.strictObject({
|
|
@@ -173,318 +162,10 @@ export const NotebookEditTool = buildTool({
|
|
|
173
162
|
renderToolUseRejectedMessage,
|
|
174
163
|
renderToolUseErrorMessage,
|
|
175
164
|
renderToolResultMessage,
|
|
176
|
-
async validateInput(
|
|
177
|
-
|
|
178
|
-
toolUseContext: ToolUseContext,
|
|
179
|
-
) {
|
|
180
|
-
const fullPath = isAbsolute(notebook_path)
|
|
181
|
-
? notebook_path
|
|
182
|
-
: resolve(getCwd(), notebook_path)
|
|
183
|
-
|
|
184
|
-
// SECURITY: Skip filesystem operations for UNC paths to prevent NTLM credential leaks.
|
|
185
|
-
if (fullPath.startsWith('\\\\') || fullPath.startsWith('//')) {
|
|
186
|
-
return { result: true }
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
if (extname(fullPath) !== '.ipynb') {
|
|
190
|
-
return {
|
|
191
|
-
result: false,
|
|
192
|
-
message:
|
|
193
|
-
'File must be a Jupyter notebook (.ipynb file). For editing other file types, use the FileEdit tool.',
|
|
194
|
-
errorCode: 2,
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
if (
|
|
199
|
-
edit_mode !== 'replace' &&
|
|
200
|
-
edit_mode !== 'insert' &&
|
|
201
|
-
edit_mode !== 'delete'
|
|
202
|
-
) {
|
|
203
|
-
return {
|
|
204
|
-
result: false,
|
|
205
|
-
message: 'Edit mode must be replace, insert, or delete.',
|
|
206
|
-
errorCode: 4,
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
if (edit_mode === 'insert' && !cell_type) {
|
|
211
|
-
return {
|
|
212
|
-
result: false,
|
|
213
|
-
message: 'Cell type is required when using edit_mode=insert.',
|
|
214
|
-
errorCode: 5,
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// Require Read-before-Edit (matches FileEditTool/FileWriteTool). Without
|
|
219
|
-
// this, the model could edit a notebook it never saw, or edit against a
|
|
220
|
-
// stale view after an external change — silent data loss.
|
|
221
|
-
const readTimestamp = toolUseContext.readFileState.get(fullPath)
|
|
222
|
-
if (!readTimestamp) {
|
|
223
|
-
return {
|
|
224
|
-
result: false,
|
|
225
|
-
message:
|
|
226
|
-
'File has not been read yet. Read it first before writing to it.',
|
|
227
|
-
errorCode: 9,
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
if (getFileModificationTime(fullPath) > readTimestamp.timestamp) {
|
|
231
|
-
return {
|
|
232
|
-
result: false,
|
|
233
|
-
message:
|
|
234
|
-
'File has been modified since read, either by the user or by a linter. Read it again before attempting to write it.',
|
|
235
|
-
errorCode: 10,
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
let content: string
|
|
240
|
-
try {
|
|
241
|
-
content = readFileSyncWithMetadata(fullPath).content
|
|
242
|
-
} catch (e) {
|
|
243
|
-
if (isENOENT(e)) {
|
|
244
|
-
return {
|
|
245
|
-
result: false,
|
|
246
|
-
message: 'Notebook file does not exist.',
|
|
247
|
-
errorCode: 1,
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
throw e
|
|
251
|
-
}
|
|
252
|
-
const notebook = safeParseJSON(content) as NotebookContent | null
|
|
253
|
-
if (!notebook) {
|
|
254
|
-
return {
|
|
255
|
-
result: false,
|
|
256
|
-
message: 'Notebook is not valid JSON.',
|
|
257
|
-
errorCode: 6,
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
if (!cell_id) {
|
|
261
|
-
if (edit_mode !== 'insert') {
|
|
262
|
-
return {
|
|
263
|
-
result: false,
|
|
264
|
-
message: 'Cell ID must be specified when not inserting a new cell.',
|
|
265
|
-
errorCode: 7,
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
} else {
|
|
269
|
-
// First try to find the cell by its actual ID
|
|
270
|
-
const cellIndex = notebook.cells.findIndex(cell => cell.id === cell_id)
|
|
271
|
-
|
|
272
|
-
if (cellIndex === -1) {
|
|
273
|
-
// If not found, try to parse as a numeric index (cell-N format)
|
|
274
|
-
const parsedCellIndex = parseCellId(cell_id)
|
|
275
|
-
if (parsedCellIndex !== undefined) {
|
|
276
|
-
if (!notebook.cells[parsedCellIndex]) {
|
|
277
|
-
return {
|
|
278
|
-
result: false,
|
|
279
|
-
message: `Cell with index ${parsedCellIndex} does not exist in notebook.`,
|
|
280
|
-
errorCode: 7,
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
} else {
|
|
284
|
-
return {
|
|
285
|
-
result: false,
|
|
286
|
-
message: `Cell with ID "${cell_id}" not found in notebook.`,
|
|
287
|
-
errorCode: 8,
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
return { result: true }
|
|
165
|
+
async validateInput(input, toolUseContext) {
|
|
166
|
+
return validateNotebookEditInput(input, toolUseContext)
|
|
294
167
|
},
|
|
295
|
-
async call(
|
|
296
|
-
|
|
297
|
-
notebook_path,
|
|
298
|
-
new_source,
|
|
299
|
-
cell_id,
|
|
300
|
-
cell_type,
|
|
301
|
-
edit_mode: originalEditMode,
|
|
302
|
-
},
|
|
303
|
-
{ readFileState, updateFileHistoryState },
|
|
304
|
-
_,
|
|
305
|
-
parentMessage,
|
|
306
|
-
) {
|
|
307
|
-
const fullPath = isAbsolute(notebook_path)
|
|
308
|
-
? notebook_path
|
|
309
|
-
: resolve(getCwd(), notebook_path)
|
|
310
|
-
|
|
311
|
-
if (fileHistoryEnabled()) {
|
|
312
|
-
await fileHistoryTrackEdit(
|
|
313
|
-
updateFileHistoryState,
|
|
314
|
-
fullPath,
|
|
315
|
-
parentMessage.uuid,
|
|
316
|
-
)
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
try {
|
|
320
|
-
// readFileSyncWithMetadata gives content + encoding + line endings in
|
|
321
|
-
// one safeResolvePath + readFileSync pass, replacing the previous
|
|
322
|
-
// detectFileEncoding + readFile + detectLineEndings chain (each of
|
|
323
|
-
// which redid safeResolvePath and/or a 4KB readSync).
|
|
324
|
-
const { content, encoding, lineEndings } =
|
|
325
|
-
readFileSyncWithMetadata(fullPath)
|
|
326
|
-
// Must use non-memoized jsonParse here: safeParseJSON caches by content
|
|
327
|
-
// string and returns a shared object reference, but we mutate the
|
|
328
|
-
// notebook in place below (cells.splice, targetCell.source = ...).
|
|
329
|
-
// Using the memoized version poisons the cache for validateInput() and
|
|
330
|
-
// any subsequent call() with the same file content.
|
|
331
|
-
let notebook: NotebookContent
|
|
332
|
-
try {
|
|
333
|
-
notebook = jsonParse(content) as NotebookContent
|
|
334
|
-
} catch {
|
|
335
|
-
return {
|
|
336
|
-
data: {
|
|
337
|
-
new_source,
|
|
338
|
-
cell_type: cell_type ?? 'code',
|
|
339
|
-
language: 'python',
|
|
340
|
-
edit_mode: 'replace',
|
|
341
|
-
error: 'Notebook is not valid JSON.',
|
|
342
|
-
cell_id,
|
|
343
|
-
notebook_path: fullPath,
|
|
344
|
-
original_file: '',
|
|
345
|
-
updated_file: '',
|
|
346
|
-
},
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
let cellIndex
|
|
351
|
-
if (!cell_id) {
|
|
352
|
-
cellIndex = 0 // Default to inserting at the beginning if no cell_id is provided
|
|
353
|
-
} else {
|
|
354
|
-
// First try to find the cell by its actual ID
|
|
355
|
-
cellIndex = notebook.cells.findIndex(cell => cell.id === cell_id)
|
|
356
|
-
|
|
357
|
-
// If not found, try to parse as a numeric index (cell-N format)
|
|
358
|
-
if (cellIndex === -1) {
|
|
359
|
-
const parsedCellIndex = parseCellId(cell_id)
|
|
360
|
-
if (parsedCellIndex !== undefined) {
|
|
361
|
-
cellIndex = parsedCellIndex
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
if (originalEditMode === 'insert') {
|
|
366
|
-
cellIndex += 1 // Insert after the cell with this ID
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
// Convert replace to insert if trying to replace one past the end
|
|
371
|
-
let edit_mode = originalEditMode
|
|
372
|
-
if (edit_mode === 'replace' && cellIndex === notebook.cells.length) {
|
|
373
|
-
edit_mode = 'insert'
|
|
374
|
-
if (!cell_type) {
|
|
375
|
-
cell_type = 'code' // Default to code if no cell_type specified
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
const language = notebook.metadata.language_info?.name ?? 'python'
|
|
380
|
-
let new_cell_id = undefined
|
|
381
|
-
if (
|
|
382
|
-
notebook.nbformat > 4 ||
|
|
383
|
-
(notebook.nbformat === 4 && notebook.nbformat_minor >= 5)
|
|
384
|
-
) {
|
|
385
|
-
if (edit_mode === 'insert') {
|
|
386
|
-
new_cell_id = Math.random().toString(36).substring(2, 15)
|
|
387
|
-
} else if (cell_id !== null) {
|
|
388
|
-
new_cell_id = cell_id
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
if (edit_mode === 'delete') {
|
|
393
|
-
// Delete the specified cell
|
|
394
|
-
notebook.cells.splice(cellIndex, 1)
|
|
395
|
-
} else if (edit_mode === 'insert') {
|
|
396
|
-
let new_cell: NotebookCell
|
|
397
|
-
if (cell_type === 'markdown') {
|
|
398
|
-
new_cell = {
|
|
399
|
-
cell_type: 'markdown',
|
|
400
|
-
id: new_cell_id,
|
|
401
|
-
source: new_source,
|
|
402
|
-
metadata: {},
|
|
403
|
-
}
|
|
404
|
-
} else {
|
|
405
|
-
new_cell = {
|
|
406
|
-
cell_type: 'code',
|
|
407
|
-
id: new_cell_id,
|
|
408
|
-
source: new_source,
|
|
409
|
-
metadata: {},
|
|
410
|
-
execution_count: null,
|
|
411
|
-
outputs: [],
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
// Insert the new cell
|
|
415
|
-
notebook.cells.splice(cellIndex, 0, new_cell)
|
|
416
|
-
} else {
|
|
417
|
-
// Find the specified cell
|
|
418
|
-
const targetCell = notebook.cells[cellIndex]! // validateInput ensures cell_number is in bounds
|
|
419
|
-
targetCell.source = new_source
|
|
420
|
-
if (targetCell.cell_type === 'code') {
|
|
421
|
-
// Reset execution count and clear outputs since cell was modified
|
|
422
|
-
targetCell.execution_count = null
|
|
423
|
-
targetCell.outputs = []
|
|
424
|
-
}
|
|
425
|
-
if (cell_type && cell_type !== targetCell.cell_type) {
|
|
426
|
-
targetCell.cell_type = cell_type
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
// Write back to file
|
|
430
|
-
const IPYNB_INDENT = 1
|
|
431
|
-
const updatedContent = jsonStringify(notebook, null, IPYNB_INDENT)
|
|
432
|
-
writeTextContent(fullPath, updatedContent, encoding, lineEndings)
|
|
433
|
-
// Update readFileState with post-write mtime (matches FileEditTool/
|
|
434
|
-
// FileWriteTool). offset:undefined breaks FileReadTool's dedup match —
|
|
435
|
-
// without this, Read→NotebookEdit→Read in the same millisecond would
|
|
436
|
-
// return the file_unchanged stub against stale in-context content.
|
|
437
|
-
readFileState.set(fullPath, {
|
|
438
|
-
content: updatedContent,
|
|
439
|
-
timestamp: getFileModificationTime(fullPath),
|
|
440
|
-
offset: undefined,
|
|
441
|
-
limit: undefined,
|
|
442
|
-
})
|
|
443
|
-
const data = {
|
|
444
|
-
new_source,
|
|
445
|
-
cell_type: cell_type ?? 'code',
|
|
446
|
-
language,
|
|
447
|
-
edit_mode: edit_mode ?? 'replace',
|
|
448
|
-
cell_id: new_cell_id || undefined,
|
|
449
|
-
error: '',
|
|
450
|
-
notebook_path: fullPath,
|
|
451
|
-
original_file: content,
|
|
452
|
-
updated_file: updatedContent,
|
|
453
|
-
}
|
|
454
|
-
return {
|
|
455
|
-
data,
|
|
456
|
-
}
|
|
457
|
-
} catch (error) {
|
|
458
|
-
if (error instanceof Error) {
|
|
459
|
-
const data = {
|
|
460
|
-
new_source,
|
|
461
|
-
cell_type: cell_type ?? 'code',
|
|
462
|
-
language: 'python',
|
|
463
|
-
edit_mode: 'replace',
|
|
464
|
-
error: error.message,
|
|
465
|
-
cell_id,
|
|
466
|
-
notebook_path: fullPath,
|
|
467
|
-
original_file: '',
|
|
468
|
-
updated_file: '',
|
|
469
|
-
}
|
|
470
|
-
return {
|
|
471
|
-
data,
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
const data = {
|
|
475
|
-
new_source,
|
|
476
|
-
cell_type: cell_type ?? 'code',
|
|
477
|
-
language: 'python',
|
|
478
|
-
edit_mode: 'replace',
|
|
479
|
-
error: 'Unknown error occurred while editing notebook',
|
|
480
|
-
cell_id,
|
|
481
|
-
notebook_path: fullPath,
|
|
482
|
-
original_file: '',
|
|
483
|
-
updated_file: '',
|
|
484
|
-
}
|
|
485
|
-
return {
|
|
486
|
-
data,
|
|
487
|
-
}
|
|
488
|
-
}
|
|
168
|
+
async call(input, context, _, parentMessage) {
|
|
169
|
+
return callNotebookEditTool(input, context, parentMessage)
|
|
489
170
|
},
|
|
490
171
|
} satisfies ToolDef<InputSchema, Output>)
|