ummaya 0.2.3 → 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 +17 -3
- package/bin/ummaya +10 -1
- package/npm-shrinkwrap.json +253 -2
- package/package.json +5 -1
- package/prompts/manifest.yaml +2 -2
- package/prompts/session_guidance_v1.md +3 -1
- package/prompts/system_v1.md +9 -7
- package/pyproject.toml +26 -7
- package/specs/2803-document-production-hardening/contracts/document-tools.schema.json +1043 -0
- package/src/ummaya/_canonical/__init__.py +2 -0
- package/src/ummaya/context/builder.py +17 -11
- package/src/ummaya/engine/engine.py +30 -113
- package/src/ummaya/engine/query.py +20 -0
- package/src/ummaya/evidence/__init__.py +44 -0
- package/src/ummaya/evidence/__main__.py +7 -0
- 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 +145 -0
- 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 +177 -0
- package/src/ummaya/evidence/source_provenance.py +246 -0
- package/src/ummaya/evidence/source_provenance_redaction.py +176 -0
- package/src/ummaya/evidence/task_registry.py +264 -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 +52 -5
- package/src/ummaya/ipc/route_diagnostics.py +73 -0
- package/src/ummaya/ipc/stdio.py +2282 -417
- package/src/ummaya/llm/client.py +234 -59
- package/src/ummaya/llm/config.py +8 -3
- package/src/ummaya/llm/reasoning.py +84 -0
- 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 +34 -2
- 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 +61 -12
- package/src/ummaya/tools/geocoding/kakao_client.py +1 -2
- package/src/ummaya/tools/kma/apihub_catalog.py +984 -1
- package/src/ummaya/tools/kma/apihub_structured_adapter.py +86 -6
- package/src/ummaya/tools/kma/apihub_url_adapter.py +593 -0
- package/src/ummaya/tools/kma/apihub_url_catalog.py +296 -0
- package/src/ummaya/tools/live_proxy.py +0 -3
- package/src/ummaya/tools/location_adapters.py +8 -6
- package/src/ummaya/tools/manifest_metadata.py +16 -3
- package/src/ummaya/tools/models.py +5 -1
- package/src/ummaya/tools/mvp_surface.py +2 -2
- package/src/ummaya/tools/nmc/emergency_search.py +8 -6
- package/src/ummaya/tools/register_all.py +17 -0
- package/src/ummaya/tools/registry.py +10 -1
- package/src/ummaya/tools/resolve_location.py +4 -4
- 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 +40 -106
- package/src/ummaya/tools/verified_data_go_kr/_manifest.py +115 -25
- package/src/ummaya/tools/verified_data_go_kr/airkorea_air_quality.py +109 -4
- package/src/ummaya/tools/verified_data_go_kr/nmc_aed_site.py +108 -2
- package/src/ummaya/tools/verified_data_go_kr/pps_bid_public_info.py +174 -9
- package/src/ummaya/tools/verified_data_go_kr/tago_bus_arrival.py +66 -3
- package/src/ummaya/tools/verified_data_go_kr/tago_bus_location.py +12 -2
- package/src/ummaya/tools/verified_data_go_kr/tago_bus_route.py +8 -2
- package/src/ummaya/tools/verified_data_go_kr/tago_bus_route_station.py +114 -0
- package/src/ummaya/tools/verified_data_go_kr/tago_bus_station.py +14 -3
- package/src/ummaya/tools/verify_canonical_map.py +21 -0
- package/tests/fixtures/documents/public_forms/baselines.yaml +113 -0
- package/tui/package.json +1 -2
- package/tui/src/.cc-byte-identical-whitelist.yaml +266 -0
- package/tui/src/QueryEngine.ts +12 -4
- package/tui/src/bridge/inboundAttachments.ts +3 -3
- package/tui/src/cli/handlers/auth.ts +4 -13
- package/tui/src/cli/handlers/mcp.tsx +3 -3
- package/tui/src/cli/print.ts +69 -18
- package/tui/src/cli/update.ts +13 -13
- package/tui/src/commands/copy/index.ts +1 -1
- package/tui/src/commands/cost/cost.ts +2 -2
- package/tui/src/commands/init-verifiers.ts +5 -5
- package/tui/src/commands/init.ts +30 -30
- package/tui/src/commands/insights.ts +44 -44
- package/tui/src/commands/install-github-app/install-github-app.tsx +2 -2
- package/tui/src/commands/install-github-app/setupGitHubActions.ts +3 -3
- package/tui/src/commands/install-github-app/types.ts +8 -30
- package/tui/src/commands/install.tsx +5 -5
- package/tui/src/commands/mcp/addCommand.ts +5 -5
- package/tui/src/commands/mcp/xaaIdpCommand.ts +2 -2
- package/tui/src/commands/plugin/ManageMarketplaces.tsx +2 -2
- package/tui/src/commands/plugin/types.ts +6 -28
- package/tui/src/commands/plugin/unifiedTypes.ts +4 -26
- package/tui/src/commands/reasoning/index.ts +13 -0
- package/tui/src/commands/reasoning/reasoning.tsx +177 -0
- package/tui/src/commands/rename/generateSessionName.ts +1 -1
- package/tui/src/commands/thinkback/thinkback.tsx +3 -3
- package/tui/src/commands.ts +2 -0
- 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/Messages.tsx +2 -1
- package/tui/src/components/ScrollKeybindingHandler.tsx +6 -6
- package/tui/src/components/Spinner/types.ts +6 -28
- package/tui/src/components/Spinner.tsx +2 -2
- 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/design-system/LoadingState.tsx +2 -2
- 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 +29 -3
- package/tui/src/ipc/frames.generated.ts +407 -312
- package/tui/src/ipc/llmClient.ts +279 -76
- package/tui/src/ipc/llmTypes.ts +16 -1
- package/tui/src/ipc/schema/frame.schema.json +1 -3475
- package/tui/src/keybindings/defaultBindings.ts +4 -0
- package/tui/src/main.tsx +32 -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 -1721
- package/tui/src/screens/REPL.tsx +42 -31
- 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 +98 -14
- 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 -364
- 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/skills/bundled/stuck.ts +12 -12
- package/tui/src/state/AppStateStore.ts +7 -0
- 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 +1239 -163
- 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 +48 -29
- package/tui/src/tools/LookupPrimitive/prompt.ts +6 -7
- 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 +30 -19
- 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 +51 -18
- 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 +27 -10
- 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/citizenUserText.ts +49 -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/locationInputRepair.ts +112 -0
- package/tui/src/tools/_shared/pendingCallRegistry.ts +1 -6
- package/tui/src/tools/_shared/rootPrimitiveInput.ts +68 -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 +61 -0
- 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/attachments.ts +1 -1
- 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/kExaoneReasoning.ts +138 -0
- package/tui/src/utils/mcp/dateTimeParser.ts +1 -1
- package/tui/src/utils/messages.ts +19 -0
- package/tui/src/utils/migrateSessions.ts +3 -3
- package/tui/src/utils/model/model.ts +6 -6
- package/tui/src/utils/multiToolLayout.ts +13 -0
- 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/processUserInput/processSlashCommand.tsx +2 -2
- package/tui/src/utils/processUserInput/processUserInput.ts +26 -0
- 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/applySettingsChange.ts +4 -0
- package/tui/src/utils/settings/permissionValidation.ts +14 -2
- package/tui/src/utils/settings/types.ts +9 -3
- package/tui/src/utils/shell/prefix.ts +1 -1
- package/tui/src/utils/sideQuery.ts +1 -1
- package/tui/src/utils/stats.ts +1 -1
- package/tui/src/utils/systemThemeWatcher.ts +13 -3
- package/tui/src/utils/teleport.tsx +1 -1
- package/uv.lock +394 -22
- package/assets/copilot-gate-logo.svg +0 -58
- package/assets/govon-logo.svg +0 -40
- package/src/ummaya/eval/__init__.py +0 -5
- package/src/ummaya/eval/retrieval.py +0 -713
- package/tui/src/services/api/claude.ts +0 -3510
- package/tui/src/utils/messageStream.ts +0 -186
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// UMMAYA-original — DocumentPrimitive prompt strings.
|
|
3
|
+
|
|
4
|
+
export const DOCUMENT_TOOL_NAME = 'document'
|
|
5
|
+
|
|
6
|
+
export const DESCRIPTION =
|
|
7
|
+
'Read, fill, validate, render, and save local public-document files through the document harness primitive.'
|
|
8
|
+
|
|
9
|
+
export const DOCUMENT_TOOL_PROMPT = `Operate on local public-document files through UMMAYA's document harness.
|
|
10
|
+
|
|
11
|
+
Use this primitive for HWPX, HWP, DOCX, PDF, XLSX, and PPTX document work when the user asks to understand, write, revise, validate, render, diff, or save a document.
|
|
12
|
+
|
|
13
|
+
Input:
|
|
14
|
+
- correlation_id: stable request id for evidence join.
|
|
15
|
+
- document: { path?: string, artifact_id?: string, expected_format?: "hwpx" | "hwp" | "docx" | "pdf" | "xlsx" | "pptx" }.
|
|
16
|
+
- operation: "inspect", "extract", "fill", "style", "validate", or "save".
|
|
17
|
+
- instruction: natural-language instruction for the document harness.
|
|
18
|
+
- destination_path: optional explicit local output path.
|
|
19
|
+
- approved_draft_id and approved_draft_sha256: include both only after the user has approved a draft preview for narrative insertion.
|
|
20
|
+
- requires_source_verification/source_support: for externally researched factual patches, include source_support with state "source_supported", citation_handle, source_sha256 matching the patch value, observed_at, and prompt_injection "not_detected".
|
|
21
|
+
|
|
22
|
+
Rules:
|
|
23
|
+
- For "read only" requests use inspect or extract.
|
|
24
|
+
- If the user says not to write, save, or apply changes yet, do not call fill or save.
|
|
25
|
+
- For "understand and write/fill/save" requests use fill or save; do not split into separate inspect/fill/render tool calls.
|
|
26
|
+
- For question-first authoring requests, inspect the document structure first, ask the user for missing evidence, then make one fill/save call after approval.
|
|
27
|
+
- Use either document.path or document.artifact_id, never both.
|
|
28
|
+
- After a document result returns artifact_refs for an existing local artifact, use document.artifact_id only on follow-up document calls and omit document.path.
|
|
29
|
+
- When a result needs more information, ask the user for missing evidence before another write attempt.
|
|
30
|
+
- For self-introductions, business plans, essays, and narrative fields, collect user evidence, show a draft preview in assistant text, wait for user approval, then write only the approved draft with patches plus approved_draft_id and approved_draft_sha256.
|
|
31
|
+
- Externally researched facts are never enough by themselves: write them only when the patch is source-supported and the user has separately approved the exact draft; if source support is missing, blocked, prompt-injected, stale, or unapproved, leave the field blank/question-waiting.
|
|
32
|
+
- Approved narrative writes must include patches whose target_path comes from the inspected document field path; if you do not know the target path, ask the user instead of calling save.
|
|
33
|
+
- Prefer explicit local paths supplied by the user.
|
|
34
|
+
- Do not use workspace file tools for document-format editing; this primitive owns document edits, save evidence, and inline diff rendering.
|
|
35
|
+
- The tool result is already rendered inline in the TUI; final answers should only summarize the visible outcome.`
|
|
@@ -1,59 +1,10 @@
|
|
|
1
|
-
import { dirname, isAbsolute, sep } from 'path'
|
|
2
|
-
import { logEvent } from 'src/services/analytics/index.js'
|
|
3
|
-
import { getFeatureValue_CACHED_MAY_BE_STALE } from '../../services/analytics/growthbook.js'
|
|
4
|
-
import { diagnosticTracker } from '../../services/diagnosticTracking.js'
|
|
5
|
-
import { clearDeliveredDiagnosticsForFile } from '../../services/lsp/LSPDiagnosticRegistry.js'
|
|
6
|
-
import { getLspServerManager } from '../../services/lsp/manager.js'
|
|
7
|
-
import { notifyVscodeFileUpdated } from '../../services/mcp/vscodeSdkMcp.js'
|
|
8
|
-
import { checkTeamMemSecrets } from '../../services/teamMemorySync/teamMemSecretGuard.js'
|
|
9
|
-
import {
|
|
10
|
-
activateConditionalSkillsForPaths,
|
|
11
|
-
addSkillDirectories,
|
|
12
|
-
discoverSkillDirsForPaths,
|
|
13
|
-
} from '../../skills/loadSkillsDir.js'
|
|
14
|
-
import type { ToolUseContext } from '../../Tool.js'
|
|
15
1
|
import { buildTool, type ToolDef } from '../../Tool.js'
|
|
16
|
-
import { getCwd } from '../../utils/cwd.js'
|
|
17
|
-
import { logForDebugging } from '../../utils/debug.js'
|
|
18
|
-
import { countLinesChanged } from '../../utils/diff.js'
|
|
19
|
-
import { isEnvTruthy } from '../../utils/envUtils.js'
|
|
20
|
-
import { isENOENT } from '../../utils/errors.js'
|
|
21
|
-
import {
|
|
22
|
-
FILE_NOT_FOUND_CWD_NOTE,
|
|
23
|
-
findSimilarFile,
|
|
24
|
-
getFileModificationTime,
|
|
25
|
-
suggestPathUnderCwd,
|
|
26
|
-
writeTextContent,
|
|
27
|
-
} from '../../utils/file.js'
|
|
28
|
-
import {
|
|
29
|
-
fileHistoryEnabled,
|
|
30
|
-
fileHistoryTrackEdit,
|
|
31
|
-
} from '../../utils/fileHistory.js'
|
|
32
|
-
import { logFileOperation } from '../../utils/fileOperationAnalytics.js'
|
|
33
|
-
import {
|
|
34
|
-
type LineEndingType,
|
|
35
|
-
readFileSyncWithMetadata,
|
|
36
|
-
} from '../../utils/fileRead.js'
|
|
37
|
-
import { formatFileSize } from '../../utils/format.js'
|
|
38
|
-
import { getFsImplementation } from '../../utils/fsOperations.js'
|
|
39
|
-
import {
|
|
40
|
-
fetchSingleFileGitDiff,
|
|
41
|
-
type ToolUseDiff,
|
|
42
|
-
} from '../../utils/gitDiff.js'
|
|
43
|
-
import { logError } from '../../utils/log.js'
|
|
44
2
|
import { expandPath } from '../../utils/path.js'
|
|
45
|
-
import {
|
|
46
|
-
checkWritePermissionForTool,
|
|
47
|
-
matchingRuleForInput,
|
|
48
|
-
} from '../../utils/permissions/filesystem.js'
|
|
3
|
+
import { checkWritePermissionForTool } from '../../utils/permissions/filesystem.js'
|
|
49
4
|
import type { PermissionDecision } from '../../utils/permissions/PermissionResult.js'
|
|
50
5
|
import { matchWildcardPattern } from '../../utils/permissions/shellRuleMatching.js'
|
|
51
|
-
import {
|
|
52
|
-
import {
|
|
53
|
-
import {
|
|
54
|
-
FILE_EDIT_TOOL_NAME,
|
|
55
|
-
FILE_UNEXPECTEDLY_MODIFIED_ERROR,
|
|
56
|
-
} from './constants.js'
|
|
6
|
+
import { callFileEditTool } from './call.js'
|
|
7
|
+
import { FILE_EDIT_TOOL_NAME } from './constants.js'
|
|
57
8
|
import { getEditToolDescription } from './prompt.js'
|
|
58
9
|
import {
|
|
59
10
|
type FileEditInput,
|
|
@@ -69,19 +20,8 @@ import {
|
|
|
69
20
|
renderToolUseRejectedMessage,
|
|
70
21
|
userFacingName,
|
|
71
22
|
} from './UI.js'
|
|
72
|
-
import {
|
|
73
|
-
|
|
74
|
-
findActualString,
|
|
75
|
-
getPatchForEdit,
|
|
76
|
-
preserveQuoteStyle,
|
|
77
|
-
} from './utils.js'
|
|
78
|
-
|
|
79
|
-
// V8/Bun string length limit is ~2^30 characters (~1 billion). For typical
|
|
80
|
-
// ASCII/Latin-1 files, 1 byte on disk = 1 character, so 1 GiB in stat bytes
|
|
81
|
-
// ≈ 1 billion characters ≈ the runtime string limit. Multi-byte UTF-8 files
|
|
82
|
-
// can be larger on disk per character, but 1 GiB is a safe byte-level guard
|
|
83
|
-
// that prevents OOM without being unnecessarily restrictive.
|
|
84
|
-
const MAX_EDIT_FILE_SIZE = 1024 * 1024 * 1024 // 1 GiB (stat bytes)
|
|
23
|
+
import { areFileEditsInputsEquivalent } from './utils.js'
|
|
24
|
+
import { validateFileEditInput } from './validateInput.js'
|
|
85
25
|
|
|
86
26
|
export const FileEditTool = buildTool({
|
|
87
27
|
name: FILE_EDIT_TOOL_NAME,
|
|
@@ -134,231 +74,8 @@ export const FileEditTool = buildTool({
|
|
|
134
74
|
renderToolResultMessage,
|
|
135
75
|
renderToolUseRejectedMessage,
|
|
136
76
|
renderToolUseErrorMessage,
|
|
137
|
-
async validateInput(input: FileEditInput, toolUseContext
|
|
138
|
-
|
|
139
|
-
// Use expandPath for consistent path normalization (especially on Windows
|
|
140
|
-
// where "/" vs "\" can cause readFileState lookup mismatches)
|
|
141
|
-
const fullFilePath = expandPath(file_path)
|
|
142
|
-
|
|
143
|
-
// Reject edits to team memory files that introduce secrets
|
|
144
|
-
const secretError = checkTeamMemSecrets(fullFilePath, new_string)
|
|
145
|
-
if (secretError) {
|
|
146
|
-
return { result: false, message: secretError, errorCode: 0 }
|
|
147
|
-
}
|
|
148
|
-
if (old_string === new_string) {
|
|
149
|
-
return {
|
|
150
|
-
result: false,
|
|
151
|
-
behavior: 'ask',
|
|
152
|
-
message:
|
|
153
|
-
'No changes to make: old_string and new_string are exactly the same.',
|
|
154
|
-
errorCode: 1,
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Check if path should be ignored based on permission settings
|
|
159
|
-
const appState = toolUseContext.getAppState()
|
|
160
|
-
const denyRule = matchingRuleForInput(
|
|
161
|
-
fullFilePath,
|
|
162
|
-
appState.toolPermissionContext,
|
|
163
|
-
'edit',
|
|
164
|
-
'deny',
|
|
165
|
-
)
|
|
166
|
-
if (denyRule !== null) {
|
|
167
|
-
return {
|
|
168
|
-
result: false,
|
|
169
|
-
behavior: 'ask',
|
|
170
|
-
message:
|
|
171
|
-
'File is in a directory that is denied by your permission settings.',
|
|
172
|
-
errorCode: 2,
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// SECURITY: Skip filesystem operations for UNC paths to prevent NTLM credential leaks.
|
|
177
|
-
// On Windows, fs.existsSync() on UNC paths triggers SMB authentication which could
|
|
178
|
-
// leak credentials to malicious servers. Let the permission check handle UNC paths.
|
|
179
|
-
if (fullFilePath.startsWith('\\\\') || fullFilePath.startsWith('//')) {
|
|
180
|
-
return { result: true }
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
const fs = getFsImplementation()
|
|
184
|
-
|
|
185
|
-
// Prevent OOM on multi-GB files.
|
|
186
|
-
try {
|
|
187
|
-
const { size } = await fs.stat(fullFilePath)
|
|
188
|
-
if (size > MAX_EDIT_FILE_SIZE) {
|
|
189
|
-
return {
|
|
190
|
-
result: false,
|
|
191
|
-
behavior: 'ask',
|
|
192
|
-
message: `File is too large to edit (${formatFileSize(size)}). Maximum editable file size is ${formatFileSize(MAX_EDIT_FILE_SIZE)}.`,
|
|
193
|
-
errorCode: 10,
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
} catch (e) {
|
|
197
|
-
if (!isENOENT(e)) {
|
|
198
|
-
throw e
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// Read the file as bytes first so we can detect encoding from the buffer
|
|
203
|
-
// instead of calling detectFileEncoding (which does its own sync readSync
|
|
204
|
-
// and would fail with a wasted ENOENT when the file doesn't exist).
|
|
205
|
-
let fileContent: string | null
|
|
206
|
-
try {
|
|
207
|
-
const fileBuffer = await fs.readFileBytes(fullFilePath)
|
|
208
|
-
const encoding: BufferEncoding =
|
|
209
|
-
fileBuffer.length >= 2 &&
|
|
210
|
-
fileBuffer[0] === 0xff &&
|
|
211
|
-
fileBuffer[1] === 0xfe
|
|
212
|
-
? 'utf16le'
|
|
213
|
-
: 'utf8'
|
|
214
|
-
fileContent = fileBuffer.toString(encoding).replaceAll('\r\n', '\n')
|
|
215
|
-
} catch (e) {
|
|
216
|
-
if (isENOENT(e)) {
|
|
217
|
-
fileContent = null
|
|
218
|
-
} else {
|
|
219
|
-
throw e
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// File doesn't exist
|
|
224
|
-
if (fileContent === null) {
|
|
225
|
-
// Empty old_string on nonexistent file means new file creation — valid
|
|
226
|
-
if (old_string === '') {
|
|
227
|
-
return { result: true }
|
|
228
|
-
}
|
|
229
|
-
// Try to find a similar file with a different extension
|
|
230
|
-
const similarFilename = findSimilarFile(fullFilePath)
|
|
231
|
-
const cwdSuggestion = await suggestPathUnderCwd(fullFilePath)
|
|
232
|
-
let message = `File does not exist. ${FILE_NOT_FOUND_CWD_NOTE} ${getCwd()}.`
|
|
233
|
-
|
|
234
|
-
if (cwdSuggestion) {
|
|
235
|
-
message += ` Did you mean ${cwdSuggestion}?`
|
|
236
|
-
} else if (similarFilename) {
|
|
237
|
-
message += ` Did you mean ${similarFilename}?`
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
return {
|
|
241
|
-
result: false,
|
|
242
|
-
behavior: 'ask',
|
|
243
|
-
message,
|
|
244
|
-
errorCode: 4,
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
// File exists with empty old_string — only valid if file is empty
|
|
249
|
-
if (old_string === '') {
|
|
250
|
-
// Only reject if the file has content (for file creation attempt)
|
|
251
|
-
if (fileContent.trim() !== '') {
|
|
252
|
-
return {
|
|
253
|
-
result: false,
|
|
254
|
-
behavior: 'ask',
|
|
255
|
-
message: 'Cannot create new file - file already exists.',
|
|
256
|
-
errorCode: 3,
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// Empty file with empty old_string is valid - we're replacing empty with content
|
|
261
|
-
return {
|
|
262
|
-
result: true,
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
if (fullFilePath.endsWith('.ipynb')) {
|
|
267
|
-
return {
|
|
268
|
-
result: false,
|
|
269
|
-
behavior: 'ask',
|
|
270
|
-
message: `File is a Jupyter Notebook. Use the ${NOTEBOOK_EDIT_TOOL_NAME} to edit this file.`,
|
|
271
|
-
errorCode: 5,
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
const readTimestamp = toolUseContext.readFileState.get(fullFilePath)
|
|
276
|
-
if (!readTimestamp || readTimestamp.isPartialView) {
|
|
277
|
-
return {
|
|
278
|
-
result: false,
|
|
279
|
-
behavior: 'ask',
|
|
280
|
-
message:
|
|
281
|
-
'File has not been read yet. Read it first before writing to it.',
|
|
282
|
-
meta: {
|
|
283
|
-
isFilePathAbsolute: String(isAbsolute(file_path)),
|
|
284
|
-
},
|
|
285
|
-
errorCode: 6,
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// Check if file exists and get its last modified time
|
|
290
|
-
if (readTimestamp) {
|
|
291
|
-
const lastWriteTime = getFileModificationTime(fullFilePath)
|
|
292
|
-
if (lastWriteTime > readTimestamp.timestamp) {
|
|
293
|
-
// Timestamp indicates modification, but on Windows timestamps can change
|
|
294
|
-
// without content changes (cloud sync, antivirus, etc.). For full reads,
|
|
295
|
-
// compare content as a fallback to avoid false positives.
|
|
296
|
-
const isFullRead =
|
|
297
|
-
readTimestamp.offset === undefined &&
|
|
298
|
-
readTimestamp.limit === undefined
|
|
299
|
-
if (isFullRead && fileContent === readTimestamp.content) {
|
|
300
|
-
// Content unchanged, safe to proceed
|
|
301
|
-
} else {
|
|
302
|
-
return {
|
|
303
|
-
result: false,
|
|
304
|
-
behavior: 'ask',
|
|
305
|
-
message:
|
|
306
|
-
'File has been modified since read, either by the user or by a linter. Read it again before attempting to write it.',
|
|
307
|
-
errorCode: 7,
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
const file = fileContent
|
|
314
|
-
|
|
315
|
-
// Use findActualString to handle quote normalization
|
|
316
|
-
const actualOldString = findActualString(file, old_string)
|
|
317
|
-
if (!actualOldString) {
|
|
318
|
-
return {
|
|
319
|
-
result: false,
|
|
320
|
-
behavior: 'ask',
|
|
321
|
-
message: `String to replace not found in file.\nString: ${old_string}`,
|
|
322
|
-
meta: {
|
|
323
|
-
isFilePathAbsolute: String(isAbsolute(file_path)),
|
|
324
|
-
},
|
|
325
|
-
errorCode: 8,
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
const matches = file.split(actualOldString).length - 1
|
|
330
|
-
|
|
331
|
-
// Check if we have multiple matches but replace_all is false
|
|
332
|
-
if (matches > 1 && !replace_all) {
|
|
333
|
-
return {
|
|
334
|
-
result: false,
|
|
335
|
-
behavior: 'ask',
|
|
336
|
-
message: `Found ${matches} matches of the string to replace, but replace_all is false. To replace all occurrences, set replace_all to true. To replace only one occurrence, please provide more context to uniquely identify the instance.\nString: ${old_string}`,
|
|
337
|
-
meta: {
|
|
338
|
-
isFilePathAbsolute: String(isAbsolute(file_path)),
|
|
339
|
-
actualOldString,
|
|
340
|
-
},
|
|
341
|
-
errorCode: 9,
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
// Additional validation for Claude settings files
|
|
346
|
-
const settingsValidationResult = validateInputForSettingsFileEdit(
|
|
347
|
-
fullFilePath,
|
|
348
|
-
file,
|
|
349
|
-
() => {
|
|
350
|
-
// Simulate the edit to get the final content using the exact same logic as the tool
|
|
351
|
-
return replace_all
|
|
352
|
-
? file.replaceAll(actualOldString, new_string)
|
|
353
|
-
: file.replace(actualOldString, new_string)
|
|
354
|
-
},
|
|
355
|
-
)
|
|
356
|
-
|
|
357
|
-
if (settingsValidationResult !== null) {
|
|
358
|
-
return settingsValidationResult
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
return { result: true, meta: { actualOldString } }
|
|
77
|
+
async validateInput(input: FileEditInput, toolUseContext) {
|
|
78
|
+
return validateFileEditInput(input, toolUseContext)
|
|
362
79
|
},
|
|
363
80
|
inputsEquivalent(input1, input2) {
|
|
364
81
|
return areFileEditsInputsEquivalent(
|
|
@@ -384,193 +101,8 @@ export const FileEditTool = buildTool({
|
|
|
384
101
|
},
|
|
385
102
|
)
|
|
386
103
|
},
|
|
387
|
-
async call(
|
|
388
|
-
input
|
|
389
|
-
{
|
|
390
|
-
readFileState,
|
|
391
|
-
userModified,
|
|
392
|
-
updateFileHistoryState,
|
|
393
|
-
dynamicSkillDirTriggers,
|
|
394
|
-
},
|
|
395
|
-
_,
|
|
396
|
-
parentMessage,
|
|
397
|
-
) {
|
|
398
|
-
const { file_path, old_string, new_string, replace_all = false } = input
|
|
399
|
-
|
|
400
|
-
// 1. Get current state
|
|
401
|
-
const fs = getFsImplementation()
|
|
402
|
-
const absoluteFilePath = expandPath(file_path)
|
|
403
|
-
|
|
404
|
-
// Discover skills from this file's path (fire-and-forget, non-blocking)
|
|
405
|
-
// Skip in simple mode - no skills available
|
|
406
|
-
const cwd = getCwd()
|
|
407
|
-
if (!isEnvTruthy(process.env.CLAUDE_CODE_SIMPLE)) {
|
|
408
|
-
const newSkillDirs = await discoverSkillDirsForPaths(
|
|
409
|
-
[absoluteFilePath],
|
|
410
|
-
cwd,
|
|
411
|
-
)
|
|
412
|
-
if (newSkillDirs.length > 0) {
|
|
413
|
-
// Store discovered dirs for attachment display
|
|
414
|
-
for (const dir of newSkillDirs) {
|
|
415
|
-
dynamicSkillDirTriggers?.add(dir)
|
|
416
|
-
}
|
|
417
|
-
// Don't await - let skill loading happen in the background
|
|
418
|
-
addSkillDirectories(newSkillDirs).catch(() => {})
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
// Activate conditional skills whose path patterns match this file
|
|
422
|
-
activateConditionalSkillsForPaths([absoluteFilePath], cwd)
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
await diagnosticTracker.beforeFileEdited(absoluteFilePath)
|
|
426
|
-
|
|
427
|
-
// Ensure parent directory exists before the atomic read-modify-write section.
|
|
428
|
-
// These awaits must stay OUTSIDE the critical section below — a yield between
|
|
429
|
-
// the staleness check and writeTextContent lets concurrent edits interleave.
|
|
430
|
-
await fs.mkdir(dirname(absoluteFilePath))
|
|
431
|
-
if (fileHistoryEnabled()) {
|
|
432
|
-
// Backup captures pre-edit content — safe to call before the staleness
|
|
433
|
-
// check (idempotent v1 backup keyed on content hash; if staleness fails
|
|
434
|
-
// later we just have an unused backup, not corrupt state).
|
|
435
|
-
await fileHistoryTrackEdit(
|
|
436
|
-
updateFileHistoryState,
|
|
437
|
-
absoluteFilePath,
|
|
438
|
-
parentMessage.uuid,
|
|
439
|
-
)
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
// 2. Load current state and confirm no changes since last read
|
|
443
|
-
// Please avoid async operations between here and writing to disk to preserve atomicity
|
|
444
|
-
const {
|
|
445
|
-
content: originalFileContents,
|
|
446
|
-
fileExists,
|
|
447
|
-
encoding,
|
|
448
|
-
lineEndings: endings,
|
|
449
|
-
} = readFileForEdit(absoluteFilePath)
|
|
450
|
-
|
|
451
|
-
if (fileExists) {
|
|
452
|
-
const lastWriteTime = getFileModificationTime(absoluteFilePath)
|
|
453
|
-
const lastRead = readFileState.get(absoluteFilePath)
|
|
454
|
-
if (!lastRead || lastWriteTime > lastRead.timestamp) {
|
|
455
|
-
// Timestamp indicates modification, but on Windows timestamps can change
|
|
456
|
-
// without content changes (cloud sync, antivirus, etc.). For full reads,
|
|
457
|
-
// compare content as a fallback to avoid false positives.
|
|
458
|
-
const isFullRead =
|
|
459
|
-
lastRead &&
|
|
460
|
-
lastRead.offset === undefined &&
|
|
461
|
-
lastRead.limit === undefined
|
|
462
|
-
const contentUnchanged =
|
|
463
|
-
isFullRead && originalFileContents === lastRead.content
|
|
464
|
-
if (!contentUnchanged) {
|
|
465
|
-
throw new Error(FILE_UNEXPECTEDLY_MODIFIED_ERROR)
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
// 3. Use findActualString to handle quote normalization
|
|
471
|
-
const actualOldString =
|
|
472
|
-
findActualString(originalFileContents, old_string) || old_string
|
|
473
|
-
|
|
474
|
-
// Preserve curly quotes in new_string when the file uses them
|
|
475
|
-
const actualNewString = preserveQuoteStyle(
|
|
476
|
-
old_string,
|
|
477
|
-
actualOldString,
|
|
478
|
-
new_string,
|
|
479
|
-
)
|
|
480
|
-
|
|
481
|
-
// 4. Generate patch
|
|
482
|
-
const { patch, updatedFile } = getPatchForEdit({
|
|
483
|
-
filePath: absoluteFilePath,
|
|
484
|
-
fileContents: originalFileContents,
|
|
485
|
-
oldString: actualOldString,
|
|
486
|
-
newString: actualNewString,
|
|
487
|
-
replaceAll: replace_all,
|
|
488
|
-
})
|
|
489
|
-
|
|
490
|
-
// 5. Write to disk
|
|
491
|
-
writeTextContent(absoluteFilePath, updatedFile, encoding, endings)
|
|
492
|
-
|
|
493
|
-
// Notify LSP servers about file modification (didChange) and save (didSave)
|
|
494
|
-
const lspManager = getLspServerManager()
|
|
495
|
-
if (lspManager) {
|
|
496
|
-
// Clear previously delivered diagnostics so new ones will be shown
|
|
497
|
-
clearDeliveredDiagnosticsForFile(`file://${absoluteFilePath}`)
|
|
498
|
-
// didChange: Content has been modified
|
|
499
|
-
lspManager
|
|
500
|
-
.changeFile(absoluteFilePath, updatedFile)
|
|
501
|
-
.catch((err: Error) => {
|
|
502
|
-
logForDebugging(
|
|
503
|
-
`LSP: Failed to notify server of file change for ${absoluteFilePath}: ${err.message}`,
|
|
504
|
-
)
|
|
505
|
-
logError(err)
|
|
506
|
-
})
|
|
507
|
-
// didSave: File has been saved to disk (triggers diagnostics in TypeScript server)
|
|
508
|
-
lspManager.saveFile(absoluteFilePath).catch((err: Error) => {
|
|
509
|
-
logForDebugging(
|
|
510
|
-
`LSP: Failed to notify server of file save for ${absoluteFilePath}: ${err.message}`,
|
|
511
|
-
)
|
|
512
|
-
logError(err)
|
|
513
|
-
})
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
// Notify VSCode about the file change for diff view
|
|
517
|
-
notifyVscodeFileUpdated(absoluteFilePath, originalFileContents, updatedFile)
|
|
518
|
-
|
|
519
|
-
// 6. Update read timestamp, to invalidate stale writes
|
|
520
|
-
readFileState.set(absoluteFilePath, {
|
|
521
|
-
content: updatedFile,
|
|
522
|
-
timestamp: getFileModificationTime(absoluteFilePath),
|
|
523
|
-
offset: undefined,
|
|
524
|
-
limit: undefined,
|
|
525
|
-
})
|
|
526
|
-
|
|
527
|
-
// 7. Log events
|
|
528
|
-
if (absoluteFilePath.endsWith(`${sep}CLAUDE.md`)) {
|
|
529
|
-
logEvent('tengu_write_claudemd', {})
|
|
530
|
-
}
|
|
531
|
-
countLinesChanged(patch)
|
|
532
|
-
|
|
533
|
-
logFileOperation({
|
|
534
|
-
operation: 'edit',
|
|
535
|
-
tool: 'FileEditTool',
|
|
536
|
-
filePath: absoluteFilePath,
|
|
537
|
-
})
|
|
538
|
-
|
|
539
|
-
logEvent('tengu_edit_string_lengths', {
|
|
540
|
-
oldStringBytes: Buffer.byteLength(old_string, 'utf8'),
|
|
541
|
-
newStringBytes: Buffer.byteLength(new_string, 'utf8'),
|
|
542
|
-
replaceAll: replace_all,
|
|
543
|
-
})
|
|
544
|
-
|
|
545
|
-
let gitDiff: ToolUseDiff | undefined
|
|
546
|
-
if (
|
|
547
|
-
isEnvTruthy(process.env.CLAUDE_CODE_REMOTE) &&
|
|
548
|
-
getFeatureValue_CACHED_MAY_BE_STALE('tengu_quartz_lantern', false)
|
|
549
|
-
) {
|
|
550
|
-
const startTime = Date.now()
|
|
551
|
-
const diff = await fetchSingleFileGitDiff(absoluteFilePath)
|
|
552
|
-
if (diff) gitDiff = diff
|
|
553
|
-
logEvent('tengu_tool_use_diff_computed', {
|
|
554
|
-
isEditTool: true,
|
|
555
|
-
durationMs: Date.now() - startTime,
|
|
556
|
-
hasDiff: !!diff,
|
|
557
|
-
})
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
// 8. Yield result
|
|
561
|
-
const data = {
|
|
562
|
-
filePath: file_path,
|
|
563
|
-
oldString: actualOldString,
|
|
564
|
-
newString: new_string,
|
|
565
|
-
originalFile: originalFileContents,
|
|
566
|
-
structuredPatch: patch,
|
|
567
|
-
userModified: userModified ?? false,
|
|
568
|
-
replaceAll: replace_all,
|
|
569
|
-
...(gitDiff && { gitDiff }),
|
|
570
|
-
}
|
|
571
|
-
return {
|
|
572
|
-
data,
|
|
573
|
-
}
|
|
104
|
+
async call(input: FileEditInput, context, _, parentMessage) {
|
|
105
|
+
return callFileEditTool(input, context, parentMessage)
|
|
574
106
|
},
|
|
575
107
|
mapToolResultToToolResultBlockParam(data: FileEditOutput, toolUseID) {
|
|
576
108
|
const { filePath, userModified, replaceAll } = data
|
|
@@ -593,33 +125,3 @@ export const FileEditTool = buildTool({
|
|
|
593
125
|
}
|
|
594
126
|
},
|
|
595
127
|
} satisfies ToolDef<ReturnType<typeof inputSchema>, FileEditOutput>)
|
|
596
|
-
|
|
597
|
-
// --
|
|
598
|
-
|
|
599
|
-
function readFileForEdit(absoluteFilePath: string): {
|
|
600
|
-
content: string
|
|
601
|
-
fileExists: boolean
|
|
602
|
-
encoding: BufferEncoding
|
|
603
|
-
lineEndings: LineEndingType
|
|
604
|
-
} {
|
|
605
|
-
try {
|
|
606
|
-
// eslint-disable-next-line custom-rules/no-sync-fs
|
|
607
|
-
const meta = readFileSyncWithMetadata(absoluteFilePath)
|
|
608
|
-
return {
|
|
609
|
-
content: meta.content,
|
|
610
|
-
fileExists: true,
|
|
611
|
-
encoding: meta.encoding,
|
|
612
|
-
lineEndings: meta.lineEndings,
|
|
613
|
-
}
|
|
614
|
-
} catch (e) {
|
|
615
|
-
if (isENOENT(e)) {
|
|
616
|
-
return {
|
|
617
|
-
content: '',
|
|
618
|
-
fileExists: false,
|
|
619
|
-
encoding: 'utf8',
|
|
620
|
-
lineEndings: 'LF',
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
throw e
|
|
624
|
-
}
|
|
625
|
-
}
|