ummaya 0.2.4 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -2
- package/bin/ummaya +10 -1
- package/bun.lock +180 -244
- package/npm-shrinkwrap.json +760 -1760
- package/package.json +39 -22
- package/prompts/manifest.yaml +1 -1
- package/prompts/system_v1.md +1 -0
- package/pyproject.toml +27 -2
- package/specs/2803-document-production-hardening/contracts/document-tools.schema.json +1043 -0
- package/src/ummaya/_canonical/__init__.py +2 -0
- package/src/ummaya/_canonical/baselines.yaml +113 -0
- package/src/ummaya/engine/engine.py +29 -132
- package/src/ummaya/evidence/__init__.py +21 -2
- package/src/ummaya/evidence/dataset_contract.py +193 -0
- package/src/ummaya/evidence/document_authoring_cases.py +33 -0
- package/src/ummaya/evidence/document_harness.py +313 -0
- package/src/ummaya/evidence/document_viewer_ux.py +391 -0
- package/src/ummaya/evidence/gates.py +70 -0
- package/src/ummaya/evidence/json_types.py +20 -0
- package/src/ummaya/evidence/models.py +88 -1
- package/src/ummaya/evidence/output_payload.py +89 -0
- package/src/ummaya/evidence/payload_documents.py +233 -0
- package/src/ummaya/evidence/route_contracts.py +224 -0
- package/src/ummaya/evidence/route_helpers.py +150 -0
- package/src/ummaya/evidence/runner.py +81 -212
- package/src/ummaya/evidence/source_provenance.py +246 -0
- package/src/ummaya/evidence/source_provenance_redaction.py +176 -0
- package/src/ummaya/evidence/tool_layer.py +39 -0
- package/src/ummaya/evidence/tool_layer_models.py +151 -0
- package/src/ummaya/ipc/adapter_manifest_emitter.py +26 -10
- package/src/ummaya/ipc/document_intent_normalization.py +185 -0
- package/src/ummaya/ipc/frame_schema.py +5 -5
- package/src/ummaya/ipc/route_diagnostics.py +73 -0
- package/src/ummaya/ipc/stdio.py +1109 -477
- package/src/ummaya/llm/client.py +102 -3
- package/src/ummaya/llm/config.py +8 -3
- package/src/ummaya/primitives/__init__.py +6 -2
- package/src/ummaya/primitives/delegation.py +1 -1
- package/src/ummaya/primitives/document.py +28 -0
- package/src/ummaya/settings.py +0 -3
- package/src/ummaya/tools/discovery_bridge.py +17 -1
- package/src/ummaya/tools/documents/__init__.py +297 -0
- package/src/ummaya/tools/documents/adapter_registry.py +487 -0
- package/src/ummaya/tools/documents/archive_container_probe.py +167 -0
- package/src/ummaya/tools/documents/artifact_store.py +454 -0
- package/src/ummaya/tools/documents/authoring.py +283 -0
- package/src/ummaya/tools/documents/baselines.py +132 -0
- package/src/ummaya/tools/documents/capability.py +331 -0
- package/src/ummaya/tools/documents/contracts.py +112 -0
- package/src/ummaya/tools/documents/conversion.py +521 -0
- package/src/ummaya/tools/documents/diff.py +275 -0
- package/src/ummaya/tools/documents/engines.py +163 -0
- package/src/ummaya/tools/documents/evaluation.py +291 -0
- package/src/ummaya/tools/documents/explicit_values.py +108 -0
- package/src/ummaya/tools/documents/fixtures.py +174 -0
- package/src/ummaya/tools/documents/format_completion_audit.py +471 -0
- package/src/ummaya/tools/documents/formats/__init__.py +2 -0
- package/src/ummaya/tools/documents/formats/archive.py +528 -0
- package/src/ummaya/tools/documents/formats/base.py +41 -0
- package/src/ummaya/tools/documents/formats/code_file.py +211 -0
- package/src/ummaya/tools/documents/formats/data_file.py +272 -0
- package/src/ummaya/tools/documents/formats/hwp.py +284 -0
- package/src/ummaya/tools/documents/formats/hwpx.py +1837 -0
- package/src/ummaya/tools/documents/formats/odf.py +435 -0
- package/src/ummaya/tools/documents/formats/ooxml.py +1030 -0
- package/src/ummaya/tools/documents/formats/passive.py +766 -0
- package/src/ummaya/tools/documents/formats/pdf.py +702 -0
- package/src/ummaya/tools/documents/formats/text_web.py +268 -0
- package/src/ummaya/tools/documents/hwp_conversion_probe.py +178 -0
- package/src/ummaya/tools/documents/hwp_direct_candidate.py +141 -0
- package/src/ummaya/tools/documents/inspection.py +289 -0
- package/src/ummaya/tools/documents/intake.py +1079 -0
- package/src/ummaya/tools/documents/legacy_office_promotion_probe.py +366 -0
- package/src/ummaya/tools/documents/models.py +1598 -0
- package/src/ummaya/tools/documents/odf_promotion_probe.py +167 -0
- package/src/ummaya/tools/documents/orchestrator.py +96 -0
- package/src/ummaya/tools/documents/passive_capability_probe.py +251 -0
- package/src/ummaya/tools/documents/patch.py +170 -0
- package/src/ummaya/tools/documents/pdfa_conformance.py +284 -0
- package/src/ummaya/tools/documents/pdfa_promotion_probe.py +198 -0
- package/src/ummaya/tools/documents/permissions.py +110 -0
- package/src/ummaya/tools/documents/planner.py +616 -0
- package/src/ummaya/tools/documents/registry.py +2733 -0
- package/src/ummaya/tools/documents/render.py +978 -0
- package/src/ummaya/tools/documents/render_comparison.py +113 -0
- package/src/ummaya/tools/documents/render_comparison_models.py +74 -0
- package/src/ummaya/tools/documents/render_comparison_regions.py +73 -0
- package/src/ummaya/tools/documents/render_comparison_style.py +161 -0
- package/src/ummaya/tools/documents/reread.py +157 -0
- package/src/ummaya/tools/documents/runtime_authoring.py +244 -0
- package/src/ummaya/tools/documents/runtime_authoring_bundle.py +76 -0
- package/src/ummaya/tools/documents/scorecard.py +184 -0
- package/src/ummaya/tools/documents/socratic_planner.py +193 -0
- package/src/ummaya/tools/documents/style.py +48 -0
- package/src/ummaya/tools/documents/tool_defs.py +523 -0
- package/src/ummaya/tools/documents/validate.py +347 -0
- package/src/ummaya/tools/executor.py +29 -0
- package/src/ummaya/tools/live_proxy.py +0 -3
- package/src/ummaya/tools/models.py +5 -1
- package/src/ummaya/tools/register_all.py +8 -0
- package/src/ummaya/tools/registry.py +10 -1
- package/src/ummaya/tools/routing/__init__.py +59 -0
- package/src/ummaya/tools/routing/builder.py +105 -0
- package/src/ummaya/tools/routing/cards.py +29 -0
- package/src/ummaya/tools/routing/decision_service.py +534 -0
- package/src/ummaya/tools/routing/decision_types.py +74 -0
- package/src/ummaya/tools/routing/feasibility.py +122 -0
- package/src/ummaya/tools/routing/intent.py +17 -0
- package/src/ummaya/tools/routing/intent_extractor.py +207 -0
- package/src/ummaya/tools/routing/intent_patterns.py +160 -0
- package/src/ummaya/tools/routing/intent_public_data.py +150 -0
- package/src/ummaya/tools/routing/intent_types.py +48 -0
- package/src/ummaya/tools/routing/lint.py +78 -0
- package/src/ummaya/tools/routing/metadata.py +174 -0
- package/src/ummaya/tools/routing/projection.py +340 -0
- package/src/ummaya/tools/routing/retrieval_policy.py +629 -0
- package/src/ummaya/tools/routing/schema.py +81 -0
- package/src/ummaya/tools/routing/types.py +96 -0
- package/src/ummaya/tools/routing_index.py +2 -2
- package/src/ummaya/tools/search.py +34 -746
- package/tests/fixtures/documents/public_forms/baselines.yaml +113 -0
- package/tui/bun.lock +126 -305
- package/tui/package.json +35 -22
- package/tui/src/.cc-byte-identical-whitelist.yaml +266 -0
- package/tui/src/QueryEngine.ts +12 -8
- package/tui/src/bridge/inboundAttachments.ts +3 -3
- package/tui/src/cli/handlers/auth.ts +3 -12
- package/tui/src/cli/handlers/mcp.tsx +0 -1
- package/tui/src/cli/print.ts +8 -9
- package/tui/src/commands/insights.ts +1 -1
- package/tui/src/commands/install-github-app/types.ts +8 -30
- package/tui/src/commands/plugin/types.ts +6 -28
- package/tui/src/commands/plugin/unifiedTypes.ts +4 -26
- package/tui/src/commands/rename/generateSessionName.ts +1 -1
- package/tui/src/components/Feedback.tsx +1 -1
- package/tui/src/components/LogoV2/EmergencyTip.tsx +11 -2
- package/tui/src/components/LogoV2/WelcomeV2.tsx +1 -3
- package/tui/src/components/ScrollKeybindingHandler.tsx +6 -6
- package/tui/src/components/Spinner/types.ts +6 -28
- package/tui/src/components/agents/generateAgent.ts +1 -1
- package/tui/src/components/agents/new-agent-creation/types.ts +4 -26
- package/tui/src/components/config/EnvSecretIsolatedEditor.tsx +1 -1
- package/tui/src/components/mcp/types.ts +16 -38
- package/tui/src/components/messages/AssistantToolUseMessage.tsx +3 -2
- package/tui/src/components/messages/UserCrossSessionMessage.ts +16 -4
- package/tui/src/components/messages/UserForkBoilerplateMessage.ts +16 -4
- package/tui/src/components/messages/UserGitHubWebhookMessage.ts +16 -4
- package/tui/src/components/messages/UserToolResultMessage/utils.tsx +3 -2
- package/tui/src/components/permissions/MonitorPermissionRequest/MonitorPermissionRequest.ts +9 -4
- package/tui/src/components/permissions/ReviewArtifactPermissionRequest/ReviewArtifactPermissionRequest.ts +9 -4
- package/tui/src/components/primitive/DocumentSocraticReviewBlock.tsx +129 -0
- package/tui/src/components/primitive/DocumentToolResultCard.tsx +224 -0
- package/tui/src/components/primitive/documentSocraticReview.ts +215 -0
- package/tui/src/components/primitive/index.tsx +43 -1
- package/tui/src/components/primitive/types.ts +137 -0
- package/tui/src/components/ui/option.ts +4 -26
- package/tui/src/constants/common.ts +0 -2
- package/tui/src/constants/prompts.ts +4 -3
- package/tui/src/constants/querySource.ts +4 -26
- package/tui/src/entrypoints/sdk/controlTypes.ts +26 -48
- package/tui/src/entrypoints/sdk/coreTypes.generated.ts +3 -25
- package/tui/src/entrypoints/sdk/runtimeTypes.ts +38 -60
- package/tui/src/entrypoints/sdk/sdkUtilityTypes.ts +4 -26
- package/tui/src/entrypoints/sdk/settingsTypes.generated.ts +3 -25
- package/tui/src/entrypoints/sdk/toolTypes.ts +3 -25
- package/tui/src/hooks/toolPermission/handlers/interactiveHandler.ts +10 -0
- package/tui/src/hooks/useApiKeyVerification.ts +1 -1
- package/tui/src/hooks/useVirtualScroll.ts +1 -1
- package/tui/src/ink/ink.tsx +33 -14
- package/tui/src/ink/reconciler.ts +2 -3
- package/tui/src/ink/render-to-screen.ts +30 -10
- package/tui/src/ipc/bridge.ts +62 -15
- package/tui/src/ipc/bridgeSingleton.ts +5 -1
- package/tui/src/ipc/codec.ts +3 -3
- package/tui/src/ipc/frames.generated.ts +12 -12
- package/tui/src/ipc/llmClient.ts +151 -27
- package/tui/src/ipc/schema/frame.schema.json +1 -1
- package/tui/src/keybindings/defaultBindings.ts +4 -0
- package/tui/src/main.tsx +32 -15
- package/tui/src/native-ts/file-index/index.ts +33 -3
- package/tui/src/observability/surface.ts +2 -2
- package/tui/src/probes/toolRegistryProbe.tsx +3 -1
- package/tui/src/projectOnboardingState.ts +7 -6
- package/tui/src/query/chatMessageTypes.ts +18 -0
- package/tui/src/query/chatMessagesBuilder.ts +1 -1
- package/tui/src/query/deps.ts +1 -1
- package/tui/src/query/messageGuards.ts +106 -0
- package/tui/src/query/publicDataTerminalRepair.ts +384 -0
- package/tui/src/query/run.ts +1075 -0
- package/tui/src/query/supportBoundary.ts +168 -0
- package/tui/src/query/toolResultErrors.ts +103 -0
- package/tui/src/query/toolRunner.ts +687 -0
- package/tui/src/query/unavailableToolRepair.ts +118 -0
- package/tui/src/query.ts +9 -2186
- package/tui/src/screens/REPL.tsx +40 -29
- package/tui/src/services/api/adapterManifest.ts +4 -0
- package/tui/src/services/api/backendChat/events.ts +117 -0
- package/tui/src/services/api/backendChat/finalMessage.ts +40 -0
- package/tui/src/services/api/backendChat/frame.ts +9 -0
- package/tui/src/services/api/backendChat/streaming.ts +430 -0
- package/tui/src/services/api/backendChat/types.ts +62 -0
- package/tui/src/services/api/backendChat.ts +1 -0
- package/tui/src/services/api/client.ts +65 -2
- package/tui/src/services/api/errorUtils.ts +5 -5
- package/tui/src/services/api/errors.ts +1 -1
- package/tui/src/services/api/logging.ts +1 -1
- package/tui/src/services/api/ummaya/evidence.ts +194 -0
- package/tui/src/services/api/ummaya/messages.ts +255 -0
- package/tui/src/services/api/ummaya/nonStreaming.ts +66 -0
- package/tui/src/services/api/ummaya/provider.ts +200 -0
- package/tui/src/services/api/ummaya/reasoning.ts +24 -0
- package/tui/src/services/api/ummaya/request.ts +200 -0
- package/tui/src/services/api/ummaya/selectionContext.ts +240 -0
- package/tui/src/services/api/ummaya/streaming.ts +365 -0
- package/tui/src/services/api/ummaya/streamingPayload.ts +129 -0
- package/tui/src/services/api/ummaya/streamingReader.ts +40 -0
- package/tui/src/services/api/ummaya/toolSelection.ts +217 -0
- package/tui/src/services/api/ummaya/types.ts +110 -0
- package/tui/src/services/api/ummaya/usage.ts +30 -0
- package/tui/src/services/api/ummaya.ts +26 -418
- package/tui/src/services/api/withRetry.ts +1 -1
- package/tui/src/services/awaySummary.ts +2 -2
- package/tui/src/services/claudeAiLimits.ts +1 -1
- package/tui/src/services/compact/autoCompact.ts +1 -1
- package/tui/src/services/compact/compact.ts +1 -1
- package/tui/src/services/lsp/types.ts +8 -30
- package/tui/src/services/tips/types.ts +6 -28
- package/tui/src/services/tokenEstimation.ts +1 -1
- package/tui/src/services/toolRegistry/bootGuard.ts +5 -5
- package/tui/src/services/toolUseSummary/toolUseSummaryGenerator.ts +1 -1
- package/tui/src/services/tools/toolExecution.ts +94 -1
- package/tui/src/store/pendingPermissionSlot.ts +1 -1
- package/tui/src/store/session-store.ts +10 -36
- package/tui/src/stubs/any-stub.ts +15 -10
- package/tui/src/stubs/color-diff-napi.ts +37 -23
- package/tui/src/stubs/globals.d.ts +3 -3
- package/tui/src/stubs/macro-preload.ts +23 -12
- package/tui/src/tools/AdapterTool/AdapterTool.ts +1207 -714
- package/tui/src/tools/AdapterTool/routeDiagnostics.ts +75 -0
- package/tui/src/tools/AgentTool/AgentTool.tsx +84 -1371
- package/tui/src/tools/AgentTool/agentToolHandoff.ts +114 -0
- package/tui/src/tools/AgentTool/agentToolPartialResult.ts +16 -0
- package/tui/src/tools/AgentTool/agentToolProgress.ts +32 -0
- package/tui/src/tools/AgentTool/agentToolResolver.ts +161 -0
- package/tui/src/tools/AgentTool/agentToolResult.ts +163 -0
- package/tui/src/tools/AgentTool/agentToolUtils.ts +14 -686
- package/tui/src/tools/AgentTool/asyncAgentLifecycle.ts +208 -0
- package/tui/src/tools/AgentTool/asyncLifecycle.ts +153 -0
- package/tui/src/tools/AgentTool/backgroundedCompletion.ts +126 -0
- package/tui/src/tools/AgentTool/backgroundedLifecycle.ts +174 -0
- package/tui/src/tools/AgentTool/foregroundBackground.ts +83 -0
- package/tui/src/tools/AgentTool/foregroundDrain.tsx +133 -0
- package/tui/src/tools/AgentTool/foregroundFinalize.ts +98 -0
- package/tui/src/tools/AgentTool/foregroundLifecycle.tsx +237 -0
- package/tui/src/tools/AgentTool/foregroundProgress.tsx +169 -0
- package/tui/src/tools/AgentTool/foregroundTask.ts +89 -0
- package/tui/src/tools/AgentTool/forkSubagent.ts +1 -12
- package/tui/src/tools/AgentTool/forkSubagentGate.ts +34 -0
- package/tui/src/tools/AgentTool/launchRouting.ts +203 -0
- package/tui/src/tools/AgentTool/lifecycle.ts +244 -0
- package/tui/src/tools/AgentTool/mcpRouting.ts +73 -0
- package/tui/src/tools/AgentTool/orchestrationSupport.ts +70 -0
- package/tui/src/tools/AgentTool/permissions.ts +39 -0
- package/tui/src/tools/AgentTool/promptSetup.ts +181 -0
- package/tui/src/tools/AgentTool/remoteRouting.ts +62 -0
- package/tui/src/tools/AgentTool/resultMapping.ts +116 -0
- package/tui/src/tools/AgentTool/resumeAgent.ts +39 -107
- package/tui/src/tools/AgentTool/resumeAgentHelpers.ts +140 -0
- package/tui/src/tools/AgentTool/runAgent.ts +1 -1
- package/tui/src/tools/AgentTool/runtimeConfig.ts +57 -0
- package/tui/src/tools/AgentTool/schemas.ts +196 -0
- package/tui/src/tools/AgentTool/sourceVerificationPropagation.ts +263 -0
- package/tui/src/tools/AgentTool/worktreeLifecycle.ts +105 -0
- package/tui/src/tools/AskUserQuestionTool/AskUserQuestionTool.tsx +174 -202
- package/tui/src/tools/BashTool/BashTool.tsx +71 -1072
- package/tui/src/tools/BashTool/bashCommandHelpers.ts +12 -12
- package/tui/src/tools/BashTool/bashPermissions/astPreflight.ts +173 -0
- package/tui/src/tools/BashTool/bashPermissions/classifierChecks.ts +199 -0
- package/tui/src/tools/BashTool/bashPermissions/compoundGuards.ts +53 -0
- package/tui/src/tools/BashTool/bashPermissions/constants.ts +99 -0
- package/tui/src/tools/BashTool/bashPermissions/index.ts +38 -0
- package/tui/src/tools/BashTool/bashPermissions/legacyMisparsing.ts +62 -0
- package/tui/src/tools/BashTool/bashPermissions/main.ts +135 -0
- package/tui/src/tools/BashTool/bashPermissions/normalizedCommands.ts +33 -0
- package/tui/src/tools/BashTool/bashPermissions/operatorFlow.ts +98 -0
- package/tui/src/tools/BashTool/bashPermissions/permissionChecks.ts +200 -0
- package/tui/src/tools/BashTool/bashPermissions/prefixSuggestions.ts +88 -0
- package/tui/src/tools/BashTool/bashPermissions/promptClassifierRules.ts +125 -0
- package/tui/src/tools/BashTool/bashPermissions/ruleDelegates.ts +19 -0
- package/tui/src/tools/BashTool/bashPermissions/ruleMatching.ts +145 -0
- package/tui/src/tools/BashTool/bashPermissions/sandboxAutoAllow.ts +75 -0
- package/tui/src/tools/BashTool/bashPermissions/subcommandFlow.ts +205 -0
- package/tui/src/tools/BashTool/bashPermissions/subcommandGuards.ts +73 -0
- package/tui/src/tools/BashTool/bashPermissions/subcommandResultHelpers.ts +116 -0
- package/tui/src/tools/BashTool/bashPermissions/types.ts +26 -0
- package/tui/src/tools/BashTool/bashPermissions/wrapperStripping.ts +139 -0
- package/tui/src/tools/BashTool/bashPermissions.ts +26 -2621
- package/tui/src/tools/BashTool/call.ts +202 -0
- package/tui/src/tools/BashTool/callLoader.ts +35 -0
- package/tui/src/tools/BashTool/commandClassification.ts +151 -0
- package/tui/src/tools/BashTool/commandClassificationLoader.ts +40 -0
- package/tui/src/tools/BashTool/cwdReset.ts +33 -0
- package/tui/src/tools/BashTool/lineTruncation.ts +11 -0
- package/tui/src/tools/BashTool/modeValidation.ts +13 -1
- package/tui/src/tools/BashTool/outputPersistence.ts +42 -0
- package/tui/src/tools/BashTool/permissionClassification.ts +66 -0
- package/tui/src/tools/BashTool/permissionLoader.ts +44 -0
- package/tui/src/tools/BashTool/resultLoader.ts +29 -0
- package/tui/src/tools/BashTool/resultMapping.ts +83 -0
- package/tui/src/tools/BashTool/sandboxPolicy.ts +79 -0
- package/tui/src/tools/BashTool/schemas.ts +65 -0
- package/tui/src/tools/BashTool/sedEditExecution.ts +59 -0
- package/tui/src/tools/BashTool/shellExecution.tsx +245 -0
- package/tui/src/tools/BashTool/shellOutputUtils.ts +85 -0
- package/tui/src/tools/BashTool/shellPermissionGauntlet.ts +97 -0
- package/tui/src/tools/BashTool/uiLoader.ts +37 -0
- package/tui/src/tools/BriefTool/upload.ts +1 -1
- package/tui/src/tools/CalculatorTool/parser.ts +2 -2
- package/tui/src/tools/DocumentPrimitive/DocumentPrimitive.ts +262 -0
- package/tui/src/tools/DocumentPrimitive/dispatchNormalization.ts +270 -0
- package/tui/src/tools/DocumentPrimitive/documentDestinationPath.ts +18 -0
- package/tui/src/tools/DocumentPrimitive/documentMutationGuard.ts +22 -0
- package/tui/src/tools/DocumentPrimitive/documentPatchNormalization.ts +248 -0
- package/tui/src/tools/DocumentPrimitive/documentSourceVerification.ts +245 -0
- package/tui/src/tools/DocumentPrimitive/documentSourceVerificationFields.ts +103 -0
- package/tui/src/tools/DocumentPrimitive/modelVisibleOutput.ts +40 -0
- package/tui/src/tools/DocumentPrimitive/prompt.ts +35 -0
- package/tui/src/tools/FileEditTool/FileEditTool.ts +9 -507
- package/tui/src/tools/FileEditTool/call.ts +228 -0
- package/tui/src/tools/FileEditTool/validateInput.ts +196 -0
- package/tui/src/tools/FileReadTool/imageProcessor.ts +13 -0
- package/tui/src/tools/FileWriteTool/FileWriteTool.ts +7 -300
- package/tui/src/tools/FileWriteTool/call.ts +223 -0
- package/tui/src/tools/FileWriteTool/validateInput.ts +80 -0
- package/tui/src/tools/ListMcpResourcesTool/ListMcpResourcesTool.ts +19 -3
- package/tui/src/tools/LookupPrimitive/LookupPrimitive.ts +25 -32
- package/tui/src/tools/LookupPrimitive/prompt.ts +0 -2
- package/tui/src/tools/MCPTool/trustPolicy.ts +118 -0
- package/tui/src/tools/McpAuthTool/McpAuthTool.ts +21 -3
- package/tui/src/tools/NotebookEditTool/NotebookEditTool.ts +7 -326
- package/tui/src/tools/NotebookEditTool/call.ts +254 -0
- package/tui/src/tools/NotebookEditTool/notebookModel.ts +51 -0
- package/tui/src/tools/NotebookEditTool/validateInput.ts +142 -0
- package/tui/src/tools/PowerShellTool/PowerShellTool.tsx +46 -937
- package/tui/src/tools/PowerShellTool/acceptEditsCommandValidation.ts +162 -0
- package/tui/src/tools/PowerShellTool/call.ts +179 -0
- package/tui/src/tools/PowerShellTool/callLoader.ts +37 -0
- package/tui/src/tools/PowerShellTool/commandClassification.ts +86 -0
- package/tui/src/tools/PowerShellTool/modeValidation.ts +25 -332
- package/tui/src/tools/PowerShellTool/outputPersistence.ts +42 -0
- package/tui/src/tools/PowerShellTool/permissionClassification.ts +28 -0
- package/tui/src/tools/PowerShellTool/resultLoader.ts +31 -0
- package/tui/src/tools/PowerShellTool/resultMapping.ts +75 -0
- package/tui/src/tools/PowerShellTool/schemas.ts +40 -0
- package/tui/src/tools/PowerShellTool/shellExecution.tsx +258 -0
- package/tui/src/tools/PowerShellTool/symlinkModeValidation.ts +44 -0
- package/tui/src/tools/PowerShellTool/uiLoader.ts +37 -0
- package/tui/src/tools/PowerShellTool/validation.ts +39 -0
- package/tui/src/tools/ReadMcpResourceTool/ReadMcpResourceTool.ts +19 -3
- package/tui/src/tools/ResolveLocationPrimitive/ResolveLocationPrimitive.ts +1 -11
- package/tui/src/tools/ResolveLocationPrimitive/prompt.ts +2 -6
- package/tui/src/tools/SkillTool/SkillTool.ts +2 -2
- package/tui/src/tools/SubmitPrimitive/SubmitPrimitive.ts +27 -10
- package/tui/src/tools/TaskCreateTool/TaskCreateTool.ts +16 -2
- package/tui/src/tools/TaskGetTool/TaskGetTool.ts +23 -3
- package/tui/src/tools/TaskListTool/TaskListTool.ts +22 -4
- package/tui/src/tools/TaskOutputTool/TaskOutputTool.tsx +46 -547
- package/tui/src/tools/TaskOutputTool/lookup.ts +216 -0
- package/tui/src/tools/TaskOutputTool/render.tsx +257 -0
- package/tui/src/tools/TaskOutputTool/schemas.ts +55 -0
- package/tui/src/tools/TaskOutputTool/serialization.ts +36 -0
- package/tui/src/tools/TaskStopTool/TaskStopTool.ts +10 -0
- package/tui/src/tools/TaskUpdateTool/TaskUpdateTool.ts +14 -364
- package/tui/src/tools/TaskUpdateTool/completion.ts +62 -0
- package/tui/src/tools/TaskUpdateTool/schemas.ts +62 -0
- package/tui/src/tools/TaskUpdateTool/serialization.ts +46 -0
- package/tui/src/tools/TaskUpdateTool/statusUpdate.ts +247 -0
- package/tui/src/tools/TodoWriteTool/TodoWriteTool.ts +21 -2
- package/tui/src/tools/ToolSearchTool/ToolSearchTool.ts +21 -302
- package/tui/src/tools/ToolSearchTool/ccSupportTools.ts +223 -0
- package/tui/src/tools/ToolSearchTool/descriptionCache.ts +50 -0
- package/tui/src/tools/ToolSearchTool/keywordSearch.ts +216 -0
- package/tui/src/tools/ToolSearchTool/prompt.ts +10 -4
- package/tui/src/tools/ToolSearchTool/resultMapping.ts +30 -0
- package/tui/src/tools/ToolSearchTool/schemas.ts +30 -0
- package/tui/src/tools/ToolSearchTool/searchPool.ts +47 -0
- package/tui/src/tools/ToolSearchTool/supportIntentHints.ts +140 -0
- package/tui/src/tools/TranslateTool/TranslateTool.ts +1 -1
- package/tui/src/tools/VerifyPrimitive/VerifyPrimitive.ts +2 -1
- package/tui/src/tools/WebFetchTool/WebFetchTool.ts +43 -138
- package/tui/src/tools/WebFetchTool/call.ts +227 -0
- package/tui/src/tools/WebFetchTool/resolvedAddressSafety.ts +78 -0
- package/tui/src/tools/WebFetchTool/sourceVerification.ts +204 -0
- package/tui/src/tools/WebFetchTool/types.ts +23 -0
- package/tui/src/tools/WebFetchTool/urlSafety.ts +181 -0
- package/tui/src/tools/WebFetchTool/utils.ts +1 -1
- package/tui/src/tools/WebSearchTool/UI.tsx +0 -1
- package/tui/src/tools/WebSearchTool/WebSearchTool.ts +9 -313
- package/tui/src/tools/WebSearchTool/call.ts +33 -0
- package/tui/src/tools/WebSearchTool/responseMapping.ts +190 -0
- package/tui/src/tools/WebSearchTool/resultBlock.ts +47 -0
- package/tui/src/tools/WebSearchTool/schemas.ts +47 -0
- package/tui/src/tools/WebSearchTool/toolSchema.ts +12 -0
- package/tui/src/tools/WorkspaceToolAdapter/WorkspaceToolAdapter.ts +79 -0
- package/tui/src/tools/WorkspaceToolAdapter/allowedRootPolicy.ts +85 -0
- package/tui/src/tools/WorkspaceToolAdapter/documentFormatGuards.ts +73 -0
- package/tui/src/tools/WorkspaceToolAdapter/inputNormalization.ts +105 -0
- package/tui/src/tools/WorkspaceToolAdapter/mcpExposurePolicy.ts +64 -0
- package/tui/src/tools/WorkspaceToolAdapter/toolDefFactory.ts +215 -0
- package/tui/src/tools/WorkspaceToolAdapter/toolNames.ts +6 -0
- package/tui/src/tools/WorkspaceToolAdapter/workspacePolicy.ts +15 -0
- package/tui/src/tools/_shared/dispatchPrimitive.ts +6 -6
- package/tui/src/tools/_shared/documentChangeToPatch.ts +125 -0
- package/tui/src/tools/_shared/documentDispatchArguments.ts +87 -0
- package/tui/src/tools/_shared/documentPrimitiveTimeout.ts +13 -0
- package/tui/src/tools/_shared/documentToolResultRender.ts +98 -0
- package/tui/src/tools/_shared/pendingCallRegistry.ts +1 -6
- package/tui/src/tools/_shared/rootPrimitiveInput.ts +1 -0
- package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPatterns.ts +58 -0
- package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPrompt.ts +271 -0
- package/tui/src/tools/_shared/toolChoiceRepair/documentRepair.ts +452 -0
- package/tui/src/tools/_shared/toolChoiceRepair/messageAccess.ts +80 -0
- package/tui/src/tools/_shared/toolChoiceRepair/publicDataRepair.ts +92 -0
- package/tui/src/tools/_shared/toolChoiceRepair/supportRepair.ts +135 -0
- package/tui/src/tools/_shared/toolChoiceRepair.ts +55 -860
- package/tui/src/tools/shared/mockDisclaimer.ts +1 -1
- package/tui/src/tools.ts +39 -190
- package/tui/src/types/fileSuggestion.ts +4 -26
- package/tui/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +186 -148
- package/tui/src/types/generated/events_mono/common/v1/auth.ts +25 -11
- package/tui/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +47 -30
- package/tui/src/types/generated/google/protobuf/timestamp.ts +21 -7
- package/tui/src/types/message.ts +80 -102
- package/tui/src/types/messageQueueTypes.ts +6 -28
- package/tui/src/types/notebook.ts +16 -38
- package/tui/src/types/statusLine.ts +4 -26
- package/tui/src/types/tools.ts +24 -46
- package/tui/src/types/utils.ts +6 -28
- package/tui/src/upstreamproxy/relay.ts +7 -3
- package/tui/src/upstreamproxy/upstreamproxy.ts +1 -1
- package/tui/src/utils/assistantMessageFactories.ts +9 -3
- package/tui/src/utils/auth.ts +129 -139
- package/tui/src/utils/bash/ast.ts +23 -23
- package/tui/src/utils/bash/bashParser.ts +5 -5
- package/tui/src/utils/billing.ts +1 -1
- package/tui/src/utils/claudeDesktop.ts +4 -4
- package/tui/src/utils/collapseReadSearch.ts +3 -3
- package/tui/src/utils/cronTasks.ts +1 -1
- package/tui/src/utils/execFileNoThrow.ts +1 -1
- package/tui/src/utils/filePersistence/types.ts +16 -38
- package/tui/src/utils/forkedAgent.ts +1 -1
- package/tui/src/utils/gracefulShutdown.ts +4 -4
- package/tui/src/utils/heapDumpService.ts +12 -8
- package/tui/src/utils/hooks/apiQueryHookHelper.ts +1 -1
- package/tui/src/utils/hooks/execPromptHook.ts +1 -1
- package/tui/src/utils/hooks/skillImprovement.ts +1 -1
- package/tui/src/utils/mcp/dateTimeParser.ts +1 -1
- package/tui/src/utils/messages.ts +18 -0
- package/tui/src/utils/migrateSessions.ts +3 -3
- package/tui/src/utils/model/model.ts +6 -6
- package/tui/src/utils/permissions/yoloClassifier.ts +1 -1
- package/tui/src/utils/plugins/headlessPluginInstall.ts +1 -1
- package/tui/src/utils/plugins/mcpPluginIntegration.ts +1 -1
- package/tui/src/utils/plugins/mcpbHandler.ts +1 -1
- package/tui/src/utils/plugins/pluginLoader.ts +8 -8
- package/tui/src/utils/protectedNamespace.ts +5 -3
- package/tui/src/utils/rawJsonToolCall.ts +242 -0
- package/tui/src/utils/ripgrep.ts +16 -7
- package/tui/src/utils/sessionTitle.ts +1 -1
- package/tui/src/utils/settings/permissionValidation.ts +14 -2
- package/tui/src/utils/shell/prefix.ts +1 -1
- package/tui/src/utils/sideQuery.ts +1 -1
- package/tui/src/utils/systemThemeWatcher.ts +13 -3
- package/tui/src/utils/teleport.tsx +1 -1
- package/uv.lock +426 -45
- package/tui/src/services/api/claude.ts +0 -3540
- package/tui/src/tools/_shared/directPublicDataGuard.ts +0 -362
- package/tui/src/tools/_shared/kmaAnalysisGuard.ts +0 -197
- package/tui/src/tools/_shared/kmaAviationGuard.ts +0 -70
- package/tui/src/tools/_shared/nmcAedGuard.ts +0 -234
- package/tui/src/tools/_shared/protectedCheckGuard.ts +0 -207
- package/tui/src/tools/_shared/textToolCallGuard.ts +0 -91
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto'
|
|
2
|
+
import type { Tools } from '../../../Tool.js'
|
|
3
|
+
import type { Message } from '../../../types/message.js'
|
|
4
|
+
import type {
|
|
5
|
+
ForcedUmmayaToolUse,
|
|
6
|
+
UmmayaBackendRepairReceipt,
|
|
7
|
+
} from '../toolChoiceRepair.js'
|
|
8
|
+
import {
|
|
9
|
+
buildDocumentCompletionPrompt,
|
|
10
|
+
hasTerminalDocumentCompletion,
|
|
11
|
+
mentionsDocumentWork,
|
|
12
|
+
} from './documentCompletionPrompt.js'
|
|
13
|
+
import {
|
|
14
|
+
DOCUMENT_INTENT_RE,
|
|
15
|
+
DOCUMENT_READ_ONLY_RE,
|
|
16
|
+
DOCUMENT_RENDER_TOOL_NAME,
|
|
17
|
+
DOCUMENT_TOOL_NAME,
|
|
18
|
+
DOCUMENT_WRITE_RE,
|
|
19
|
+
documentExpectedFormatFromPath,
|
|
20
|
+
isExactLocalReadOnlyDocumentPrompt,
|
|
21
|
+
localDocumentPathFromText,
|
|
22
|
+
type DocumentExpectedFormat,
|
|
23
|
+
} from './documentCompletionPatterns.js'
|
|
24
|
+
import {
|
|
25
|
+
isRecord,
|
|
26
|
+
latestUserMessageIndex,
|
|
27
|
+
latestUserText,
|
|
28
|
+
messageContent,
|
|
29
|
+
textFromContent,
|
|
30
|
+
} from './messageAccess.js'
|
|
31
|
+
|
|
32
|
+
const DOCUMENT_EXPLICIT_PATH_SCAN_RE =
|
|
33
|
+
/(?:^|[\s:'"(])((?:~|\/|[A-Za-z]:\\|\.{1,2}\/)[^\s:'"]+\.(hwpx|hwp|docx|pdf|xlsx|pptx))\b/giu
|
|
34
|
+
const DOCUMENT_ARTIFACT_ID_RE =
|
|
35
|
+
/(?:^|[\s"'`(])(?:artifact_id|artifact\s*id|artifact|아티팩트)?\s*((?:source|working|derivative|render|export|viewport)-[A-Za-z0-9][A-Za-z0-9_.-]{0,127})(?=$|[^A-Za-z0-9_.-])/iu
|
|
36
|
+
const DOCUMENT_FORMAT_RE = /\b(?:hwpx|hwp|docx|pdf|xlsx|pptx)\b/iu
|
|
37
|
+
const DOCUMENT_REVIEW_RE =
|
|
38
|
+
/(diff|compact|변경사항|렌더|미리보기|render|viewport|page)/iu
|
|
39
|
+
const DOCUMENT_LOCAL_HINT_RE =
|
|
40
|
+
/(다운로드|downloads?|폴더|파일|양식|서식|활동일지|신청서|등본|증명서)/iu
|
|
41
|
+
|
|
42
|
+
function toolAvailable(tools: Tools, toolName: string): boolean {
|
|
43
|
+
return tools.some(tool => tool.name === toolName)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function documentCandidateText(candidate: unknown): string {
|
|
47
|
+
if (typeof candidate === 'string') return candidate
|
|
48
|
+
if (!isRecord(candidate)) return ''
|
|
49
|
+
const message = isRecord(candidate.message) ? candidate.message : candidate
|
|
50
|
+
return textFromContent(messageContent(message))
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
type DocumentDispatchRepair =
|
|
54
|
+
| {
|
|
55
|
+
readonly kind: 'ready'
|
|
56
|
+
readonly input: Record<string, unknown>
|
|
57
|
+
}
|
|
58
|
+
| {
|
|
59
|
+
readonly kind: 'blocked'
|
|
60
|
+
readonly message: string
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
type DocumentPathRef = {
|
|
64
|
+
readonly path: string
|
|
65
|
+
readonly expectedFormat: DocumentExpectedFormat
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function repairUmmayaDocumentToolInputForDispatch({
|
|
69
|
+
toolName,
|
|
70
|
+
input,
|
|
71
|
+
messages,
|
|
72
|
+
}: {
|
|
73
|
+
readonly toolName: string
|
|
74
|
+
readonly input: Record<string, unknown>
|
|
75
|
+
readonly messages: readonly Message[]
|
|
76
|
+
}): DocumentDispatchRepair {
|
|
77
|
+
if (toolName !== DOCUMENT_TOOL_NAME) {
|
|
78
|
+
return { kind: 'ready', input }
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const userText = latestUserText(messages)
|
|
82
|
+
const exactReadOnlyInspect = isExactLocalReadOnlyDocumentPrompt(userText)
|
|
83
|
+
if (hasDocumentDispatchContract(input) && !exactReadOnlyInspect) {
|
|
84
|
+
return { kind: 'ready', input }
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (!exactReadOnlyInspect) {
|
|
88
|
+
return {
|
|
89
|
+
kind: 'blocked',
|
|
90
|
+
message:
|
|
91
|
+
'Document boundary blocked: provider emitted malformed document input, and the latest user request was not an exact local read-only inspect prompt. The document tool was not dispatched.',
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const path = localDocumentPathFromText(userText)
|
|
96
|
+
if (path === undefined) {
|
|
97
|
+
return {
|
|
98
|
+
kind: 'blocked',
|
|
99
|
+
message:
|
|
100
|
+
'Document boundary blocked: provider emitted malformed document input, and no exact local document path could be recovered from the latest user request. Provide an exact existing file path.',
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const expectedFormat = documentExpectedFormatFromPath(path)
|
|
105
|
+
return {
|
|
106
|
+
kind: 'ready',
|
|
107
|
+
input: {
|
|
108
|
+
correlation_id:
|
|
109
|
+
nonEmptyString(input.correlation_id) ??
|
|
110
|
+
`client-repaired-document-${shortHash(`${path}\n${userText}`)}`,
|
|
111
|
+
document: {
|
|
112
|
+
path,
|
|
113
|
+
...(expectedFormat === undefined ? {} : { expected_format: expectedFormat }),
|
|
114
|
+
},
|
|
115
|
+
operation: 'inspect',
|
|
116
|
+
instruction: documentInstruction(input, userText),
|
|
117
|
+
__ummaya_user_query: userText,
|
|
118
|
+
},
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function hasDocumentDispatchContract(input: Record<string, unknown>): boolean {
|
|
123
|
+
const document = isRecord(input.document) ? input.document : undefined
|
|
124
|
+
return nonEmptyString(input.correlation_id) !== undefined &&
|
|
125
|
+
document !== undefined &&
|
|
126
|
+
(nonEmptyString(document.path) !== undefined ||
|
|
127
|
+
nonEmptyString(document.artifact_id) !== undefined) &&
|
|
128
|
+
nonEmptyString(input.instruction) !== undefined
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function documentInstruction(
|
|
132
|
+
input: Record<string, unknown>,
|
|
133
|
+
userText: string,
|
|
134
|
+
): string {
|
|
135
|
+
const instruction = nonEmptyString(input.instruction)
|
|
136
|
+
if (instruction === undefined) return userText
|
|
137
|
+
if (instruction.includes(userText)) return instruction
|
|
138
|
+
return `${instruction}\n\nOriginal user request:\n${userText}`
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function nonEmptyString(value: unknown): string | undefined {
|
|
142
|
+
return typeof value === 'string' && value.trim().length > 0
|
|
143
|
+
? value
|
|
144
|
+
: undefined
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function shortHash(text: string): string {
|
|
148
|
+
return createHash('sha256').update(text).digest('hex').slice(0, 8)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function hasBackendRepairReceipt(
|
|
152
|
+
receipt: UmmayaBackendRepairReceipt | undefined,
|
|
153
|
+
): boolean {
|
|
154
|
+
return receipt !== undefined &&
|
|
155
|
+
(receipt.source === 'backend_route_decision' ||
|
|
156
|
+
receipt.source === 'backend_validation') &&
|
|
157
|
+
receipt.reason.trim() !== '' &&
|
|
158
|
+
receipt.evidenceEvent.startsWith('ummaya.')
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function isDocumentHarnessQuery(text: string): boolean {
|
|
162
|
+
return localDocumentPathFromText(text) !== undefined ||
|
|
163
|
+
DOCUMENT_ARTIFACT_ID_RE.test(text) ||
|
|
164
|
+
((DOCUMENT_FORMAT_RE.test(text) || DOCUMENT_ARTIFACT_ID_RE.test(text)) &&
|
|
165
|
+
DOCUMENT_INTENT_RE.test(text)) ||
|
|
166
|
+
(DOCUMENT_INTENT_RE.test(text) &&
|
|
167
|
+
DOCUMENT_WRITE_RE.test(text) &&
|
|
168
|
+
DOCUMENT_LOCAL_HINT_RE.test(text))
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function hasExplicitDocumentLocator(text: string): boolean {
|
|
172
|
+
return localDocumentPathFromText(text) !== undefined ||
|
|
173
|
+
DOCUMENT_ARTIFACT_ID_RE.test(text)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function explicitDocumentPathRefs(userText: string): readonly DocumentPathRef[] {
|
|
177
|
+
return [...userText.matchAll(DOCUMENT_EXPLICIT_PATH_SCAN_RE)].map(match => ({
|
|
178
|
+
path: match[1]!,
|
|
179
|
+
expectedFormat: match[2]!.toLowerCase() as DocumentExpectedFormat,
|
|
180
|
+
}))
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function stableDocumentCorrelationId(userText: string): string {
|
|
184
|
+
return `client-forced-document-${shortHash(userText)}`
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function forcedDocumentInputFromExplicitPath(
|
|
188
|
+
userText: string,
|
|
189
|
+
): Record<string, unknown> | undefined {
|
|
190
|
+
if (!isDocumentHarnessQuery(userText)) return undefined
|
|
191
|
+
const wantsWrite =
|
|
192
|
+
DOCUMENT_WRITE_RE.test(userText) && !DOCUMENT_READ_ONLY_RE.test(userText)
|
|
193
|
+
const wantsReview = DOCUMENT_REVIEW_RE.test(userText)
|
|
194
|
+
const wantsReadOnly = DOCUMENT_READ_ONLY_RE.test(userText)
|
|
195
|
+
if (!wantsWrite && !wantsReview && !wantsReadOnly) return undefined
|
|
196
|
+
|
|
197
|
+
const paths = explicitDocumentPathRefs(userText)
|
|
198
|
+
const source = paths[0]
|
|
199
|
+
if (!source) return undefined
|
|
200
|
+
|
|
201
|
+
const input: Record<string, unknown> = {
|
|
202
|
+
correlation_id: stableDocumentCorrelationId(userText),
|
|
203
|
+
document: {
|
|
204
|
+
path: source.path,
|
|
205
|
+
expected_format: source.expectedFormat,
|
|
206
|
+
},
|
|
207
|
+
operation: wantsWrite ? 'fill' : 'inspect',
|
|
208
|
+
instruction: userText,
|
|
209
|
+
}
|
|
210
|
+
const destination = paths.find(candidate => candidate.path !== source.path)
|
|
211
|
+
if (destination !== undefined && wantsWrite) {
|
|
212
|
+
input.destination_path = destination.path
|
|
213
|
+
}
|
|
214
|
+
return input
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function toolAvailableOrSynced(tools: Tools, toolName: string): boolean {
|
|
218
|
+
return toolAvailable(tools, toolName)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function hasExplicitMutationPayload(input: Record<string, unknown>): boolean {
|
|
222
|
+
return Array.isArray(input.patches) ||
|
|
223
|
+
Array.isArray(input.styles) ||
|
|
224
|
+
typeof input.destination_path === 'string'
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function parseJsonRecord(value: string): Record<string, unknown> | undefined {
|
|
228
|
+
try {
|
|
229
|
+
const parsed: unknown = JSON.parse(value)
|
|
230
|
+
return isRecord(parsed) ? parsed : undefined
|
|
231
|
+
} catch {
|
|
232
|
+
return undefined
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function documentResultPayload(value: unknown): Record<string, unknown> | undefined {
|
|
237
|
+
if (Array.isArray(value)) {
|
|
238
|
+
for (let index = value.length - 1; index >= 0; index -= 1) {
|
|
239
|
+
const nested = documentResultPayload(value[index])
|
|
240
|
+
if (nested !== undefined) return nested
|
|
241
|
+
}
|
|
242
|
+
return undefined
|
|
243
|
+
}
|
|
244
|
+
if (!isRecord(value)) return undefined
|
|
245
|
+
const toolId = typeof value.tool_id === 'string' ? value.tool_id : undefined
|
|
246
|
+
if (toolId === DOCUMENT_TOOL_NAME || toolId === DOCUMENT_RENDER_TOOL_NAME) {
|
|
247
|
+
return value
|
|
248
|
+
}
|
|
249
|
+
return documentResultPayload(value.result)
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function isSuccessfulDocumentPayload(
|
|
253
|
+
payload: Record<string, unknown>,
|
|
254
|
+
acceptedToolNames: ReadonlySet<string>,
|
|
255
|
+
): boolean {
|
|
256
|
+
const toolId = typeof payload.tool_id === 'string' ? payload.tool_id : undefined
|
|
257
|
+
if (toolId === undefined || !acceptedToolNames.has(toolId)) return false
|
|
258
|
+
const status = typeof payload.status === 'string'
|
|
259
|
+
? payload.status.toLowerCase()
|
|
260
|
+
: 'ok'
|
|
261
|
+
const okFlag = typeof payload.ok === 'boolean' ? payload.ok : true
|
|
262
|
+
const hasError =
|
|
263
|
+
payload.kind === 'error' ||
|
|
264
|
+
typeof payload.error === 'string' ||
|
|
265
|
+
isRecord(payload.error)
|
|
266
|
+
return okFlag && !hasError &&
|
|
267
|
+
['ok', 'succeeded', 'completed', 'ready'].includes(status)
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function hasSuccessfulDocumentResultAfter(
|
|
271
|
+
messages: readonly Message[],
|
|
272
|
+
afterIndex: number,
|
|
273
|
+
acceptedToolNames: ReadonlySet<string>,
|
|
274
|
+
): boolean {
|
|
275
|
+
for (let index = Math.max(0, afterIndex + 1); index < messages.length; index += 1) {
|
|
276
|
+
const content = messageContent(messages[index])
|
|
277
|
+
if (!Array.isArray(content)) continue
|
|
278
|
+
for (const block of content) {
|
|
279
|
+
if (!isRecord(block) || block.type !== 'tool_result') continue
|
|
280
|
+
if (block.is_error === true || typeof block.content !== 'string') continue
|
|
281
|
+
const payload = documentResultPayload(parseJsonRecord(block.content))
|
|
282
|
+
if (
|
|
283
|
+
payload !== undefined &&
|
|
284
|
+
isSuccessfulDocumentPayload(payload, acceptedToolNames)
|
|
285
|
+
) {
|
|
286
|
+
return true
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return false
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export function repairUmmayaExplicitDocumentToolUseFromUserQuery({
|
|
294
|
+
input,
|
|
295
|
+
toolName,
|
|
296
|
+
messages,
|
|
297
|
+
tools,
|
|
298
|
+
backendRepairReceipt,
|
|
299
|
+
}: {
|
|
300
|
+
readonly toolName: string
|
|
301
|
+
readonly input: Record<string, unknown>
|
|
302
|
+
readonly messages: readonly Message[]
|
|
303
|
+
readonly tools: Tools
|
|
304
|
+
readonly backendRepairReceipt?: UmmayaBackendRepairReceipt
|
|
305
|
+
}): ForcedUmmayaToolUse | undefined {
|
|
306
|
+
if (!hasBackendRepairReceipt(backendRepairReceipt)) return undefined
|
|
307
|
+
if (!toolAvailableOrSynced(tools, DOCUMENT_TOOL_NAME)) return undefined
|
|
308
|
+
|
|
309
|
+
const userText = latestUserText(messages)
|
|
310
|
+
if (!hasExplicitDocumentLocator(userText)) return undefined
|
|
311
|
+
const forced = forcedDocumentInputFromExplicitPath(userText)
|
|
312
|
+
if (forced === undefined) return undefined
|
|
313
|
+
|
|
314
|
+
if (toolName === DOCUMENT_TOOL_NAME) {
|
|
315
|
+
const forcedOperation = typeof forced.operation === 'string'
|
|
316
|
+
? forced.operation
|
|
317
|
+
: undefined
|
|
318
|
+
const currentOperation = typeof input.operation === 'string'
|
|
319
|
+
? input.operation
|
|
320
|
+
: undefined
|
|
321
|
+
if (
|
|
322
|
+
forcedOperation === currentOperation ||
|
|
323
|
+
(forcedOperation !== 'inspect' && hasExplicitMutationPayload(input))
|
|
324
|
+
) {
|
|
325
|
+
return undefined
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return {
|
|
330
|
+
name: DOCUMENT_TOOL_NAME,
|
|
331
|
+
input: forced,
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export function backfillUmmayaObservableToolInputFromUserQuery(_params: {
|
|
336
|
+
readonly toolName: string
|
|
337
|
+
readonly input: Record<string, unknown>
|
|
338
|
+
readonly messages: readonly Message[]
|
|
339
|
+
}): void {
|
|
340
|
+
if (_params.toolName !== DOCUMENT_TOOL_NAME) return
|
|
341
|
+
const operation = typeof _params.input.operation === 'string'
|
|
342
|
+
? _params.input.operation
|
|
343
|
+
: undefined
|
|
344
|
+
if (operation !== 'inspect' && operation !== 'extract') return
|
|
345
|
+
|
|
346
|
+
const userText = latestUserText(_params.messages)
|
|
347
|
+
if (!isDocumentHarnessQuery(userText)) return
|
|
348
|
+
if (!DOCUMENT_WRITE_RE.test(userText) || DOCUMENT_READ_ONLY_RE.test(userText)) {
|
|
349
|
+
return
|
|
350
|
+
}
|
|
351
|
+
if (!hasExplicitDocumentLocator(userText)) return
|
|
352
|
+
|
|
353
|
+
_params.input.__ummaya_display_operation = 'fill'
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
export function selectUmmayaClientForcedToolUse({
|
|
357
|
+
messages,
|
|
358
|
+
tools,
|
|
359
|
+
backendRepairReceipt,
|
|
360
|
+
}: {
|
|
361
|
+
readonly messages: readonly Message[]
|
|
362
|
+
readonly tools: Tools
|
|
363
|
+
readonly backendRepairReceipt?: UmmayaBackendRepairReceipt
|
|
364
|
+
}): ForcedUmmayaToolUse | undefined {
|
|
365
|
+
if (!hasBackendRepairReceipt(backendRepairReceipt)) return undefined
|
|
366
|
+
if (!toolAvailableOrSynced(tools, DOCUMENT_TOOL_NAME)) return undefined
|
|
367
|
+
const input = forcedDocumentInputFromExplicitPath(latestUserText(messages))
|
|
368
|
+
if (input === undefined) return undefined
|
|
369
|
+
return {
|
|
370
|
+
name: DOCUMENT_TOOL_NAME,
|
|
371
|
+
input,
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export function selectRecoveredDocumentToolChoiceNameForMessages({
|
|
376
|
+
messages,
|
|
377
|
+
tools,
|
|
378
|
+
}: {
|
|
379
|
+
readonly messages: readonly Message[]
|
|
380
|
+
readonly tools: Tools
|
|
381
|
+
}): string | undefined {
|
|
382
|
+
if (!isExactLocalReadOnlyDocumentPrompt(latestUserText(messages))) {
|
|
383
|
+
return undefined
|
|
384
|
+
}
|
|
385
|
+
return toolAvailable(tools, DOCUMENT_TOOL_NAME) ? DOCUMENT_TOOL_NAME : undefined
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
export function shouldWithholdIgnoredDocumentToolChoiceText({
|
|
389
|
+
toolChoiceName,
|
|
390
|
+
candidate,
|
|
391
|
+
}: {
|
|
392
|
+
readonly toolChoiceName: string
|
|
393
|
+
readonly candidate: unknown
|
|
394
|
+
}): boolean {
|
|
395
|
+
return toolChoiceName === DOCUMENT_TOOL_NAME &&
|
|
396
|
+
documentCandidateText(candidate).trim().length > 0
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
export function buildIgnoredDocumentToolChoiceBlockedText(
|
|
400
|
+
toolChoiceAvailable = true,
|
|
401
|
+
): string {
|
|
402
|
+
const reason = toolChoiceAvailable
|
|
403
|
+
? 'provider ignored forced document tool_choice.'
|
|
404
|
+
: 'document 도구가 현재 TUI 도구 풀에 없어 로컬 문서 검사를 실행할 수 없습니다.'
|
|
405
|
+
return [
|
|
406
|
+
'문서 도구 호출 차단: document tool_choice를 강제했지만 모델 응답에 document 도구 경계가 포함되지 않았습니다.',
|
|
407
|
+
`이유: ${reason}`,
|
|
408
|
+
'로컬 문서는 검색 또는 추측 답변으로 처리하지 않습니다.',
|
|
409
|
+
].join(' ')
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
export function shouldCompleteAfterSuccessfulDocumentRender(_params: {
|
|
413
|
+
readonly messages: readonly Message[]
|
|
414
|
+
}): boolean {
|
|
415
|
+
const userText = latestUserText(_params.messages)
|
|
416
|
+
if (!isDocumentHarnessQuery(userText)) return false
|
|
417
|
+
if (!DOCUMENT_REVIEW_RE.test(userText)) return false
|
|
418
|
+
if (!DOCUMENT_ARTIFACT_ID_RE.test(userText)) return false
|
|
419
|
+
return hasSuccessfulDocumentResultAfter(
|
|
420
|
+
_params.messages,
|
|
421
|
+
latestUserMessageIndex(_params.messages),
|
|
422
|
+
new Set([DOCUMENT_TOOL_NAME, DOCUMENT_RENDER_TOOL_NAME]),
|
|
423
|
+
)
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
export function shouldCompleteAfterTerminalDocumentToolResult(_params: {
|
|
427
|
+
readonly messages: readonly Message[]
|
|
428
|
+
}): boolean {
|
|
429
|
+
const userText = latestUserText(_params.messages)
|
|
430
|
+
if (!mentionsDocumentWork(userText)) return false
|
|
431
|
+
return hasTerminalDocumentCompletion({
|
|
432
|
+
messages: _params.messages,
|
|
433
|
+
userText,
|
|
434
|
+
})
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
export function shouldSuppressDocumentToolCallsForAnswerSynthesis(params: {
|
|
438
|
+
readonly messages: readonly Message[]
|
|
439
|
+
}): boolean {
|
|
440
|
+
return shouldCompleteAfterSuccessfulDocumentRender(params) ||
|
|
441
|
+
shouldCompleteAfterTerminalDocumentToolResult(params)
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
export function buildDocumentCompletionPromptIfNeeded({
|
|
445
|
+
messages,
|
|
446
|
+
}: {
|
|
447
|
+
readonly messages: readonly Message[]
|
|
448
|
+
}): string | undefined {
|
|
449
|
+
const userText = latestUserText(messages)
|
|
450
|
+
if (!mentionsDocumentWork(userText)) return undefined
|
|
451
|
+
return buildDocumentCompletionPrompt({ messages, userText })
|
|
452
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { Message } from '../../../types/message.js'
|
|
2
|
+
|
|
3
|
+
export function isRecord(value: unknown): value is Record<string, unknown> {
|
|
4
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function messageRecord(
|
|
8
|
+
message: unknown,
|
|
9
|
+
): Record<string, unknown> | undefined {
|
|
10
|
+
if (!isRecord(message)) return undefined
|
|
11
|
+
return isRecord(message.message) ? message.message : undefined
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function messageRole(message: unknown): string | undefined {
|
|
15
|
+
const outer = isRecord(message) ? message : undefined
|
|
16
|
+
const inner = messageRecord(message)
|
|
17
|
+
if (typeof inner?.role === 'string') return inner.role
|
|
18
|
+
if (typeof outer?.role === 'string') return outer.role
|
|
19
|
+
return typeof outer?.type === 'string' ? outer.type : undefined
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function messageContent(message: unknown): unknown {
|
|
23
|
+
return messageRecord(message)?.content ?? (isRecord(message) ? message.content : undefined)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function textFromContent(content: unknown): string {
|
|
27
|
+
if (typeof content === 'string') return content
|
|
28
|
+
if (!Array.isArray(content)) return ''
|
|
29
|
+
return content
|
|
30
|
+
.map(block => {
|
|
31
|
+
if (typeof block === 'string') return block
|
|
32
|
+
if (!isRecord(block)) return ''
|
|
33
|
+
if (block.type !== 'text') return ''
|
|
34
|
+
return typeof block.text === 'string' ? block.text : ''
|
|
35
|
+
})
|
|
36
|
+
.filter(text => text.length > 0)
|
|
37
|
+
.join('\n')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function latestUserText(messages: readonly unknown[]): string {
|
|
41
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
42
|
+
if (messageRole(messages[index]) !== 'user') continue
|
|
43
|
+
const text = textFromContent(messageContent(messages[index])).trim()
|
|
44
|
+
if (text.length > 0) return text
|
|
45
|
+
}
|
|
46
|
+
return ''
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function latestUserMessageIndex(messages: readonly unknown[]): number {
|
|
50
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
51
|
+
if (messageRole(messages[index]) !== 'user') continue
|
|
52
|
+
const text = textFromContent(messageContent(messages[index])).trim()
|
|
53
|
+
if (text.length > 0) return index
|
|
54
|
+
}
|
|
55
|
+
return -1
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function toolUseNames(messages: readonly unknown[]): ReadonlySet<string> {
|
|
59
|
+
const names = new Set<string>()
|
|
60
|
+
for (const candidate of messages) {
|
|
61
|
+
const content = messageContent(candidate)
|
|
62
|
+
if (!Array.isArray(content)) continue
|
|
63
|
+
for (const block of content) {
|
|
64
|
+
if (isRecord(block) && block.type === 'tool_use' && typeof block.name === 'string') {
|
|
65
|
+
const input = isRecord(block.input) ? block.input : undefined
|
|
66
|
+
names.add(typeof input?.tool_id === 'string' ? input.tool_id : block.name)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return names
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function latestAssistantText(messages: readonly Message[]): string {
|
|
74
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
75
|
+
if (messageRole(messages[index]) !== 'assistant') continue
|
|
76
|
+
const text = textFromContent(messageContent(messages[index]))
|
|
77
|
+
if (text.trim().length > 0) return text
|
|
78
|
+
}
|
|
79
|
+
return ''
|
|
80
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { Tools } from '../../../Tool.js'
|
|
2
|
+
import type { Message } from '../../../types/message.js'
|
|
3
|
+
import { isNonSyntheticUserMessageText } from '../citizenUserText.js'
|
|
4
|
+
import {
|
|
5
|
+
isRecord,
|
|
6
|
+
latestAssistantText,
|
|
7
|
+
messageContent,
|
|
8
|
+
messageRole,
|
|
9
|
+
textFromContent,
|
|
10
|
+
} from './messageAccess.js'
|
|
11
|
+
|
|
12
|
+
type PromptParams = { readonly messages: readonly Message[] }
|
|
13
|
+
type CandidateWithholdParams = PromptParams & { readonly candidate: Message }
|
|
14
|
+
|
|
15
|
+
const GENERIC_PENDING_FINAL_RE =
|
|
16
|
+
/(답변을?\s*제공하겠습니다|제공하겠습니다|확인해\s*보겠습니다|확인하겠습니다|조회하겠습니다|찾아보겠습니다|검색해\s*보겠습니다|검색하겠습니다|최종\s*답변은|final answer should|will\s+(?:answer|provide|check|search|look\s+up))/iu
|
|
17
|
+
const GENERIC_PENDING_FINAL_REPAIR_PROMPT =
|
|
18
|
+
'Final answer repair: successful tool_result evidence already exists, but the previous assistant message was still a plan or promise to answer later. Write the final Korean answer now from the actual tool_result values only. Do not say 제공하겠습니다, 확인하겠습니다, 조회하겠습니다, 찾아보겠습니다, 검색해 보겠습니다, or describe what you will answer next.'
|
|
19
|
+
const GENERIC_PENDING_FINAL_TOOL_USE_BLOCKED_TEXT =
|
|
20
|
+
'이미 도구 결과가 반환되어 최종 답변 보정이 요청되었습니다. 이 단계에서는 추가 도구를 실행하지 않습니다. 현재 확인된 도구 결과만 근거로 답변을 마무리하고, 연결되지 않은 업무는 공식 채널 확인 또는 필요한 adapter/credential 준비로 넘겨야 합니다.'
|
|
21
|
+
|
|
22
|
+
export function buildGenericPendingFinalAnswerRepairPromptIfNeeded(
|
|
23
|
+
params: PromptParams,
|
|
24
|
+
): string | undefined {
|
|
25
|
+
if (!hasToolResultAfterLatestUser(params.messages)) return undefined
|
|
26
|
+
if (hasGenericPendingFinalRepairPrompt(params.messages)) return undefined
|
|
27
|
+
if (!GENERIC_PENDING_FINAL_RE.test(latestAssistantText(params.messages))) {
|
|
28
|
+
return undefined
|
|
29
|
+
}
|
|
30
|
+
return GENERIC_PENDING_FINAL_REPAIR_PROMPT
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function shouldWithholdGenericPendingFinalAnswer(
|
|
34
|
+
params: CandidateWithholdParams,
|
|
35
|
+
): boolean {
|
|
36
|
+
if (hasGenericPendingFinalRepairPrompt(params.messages)) return false
|
|
37
|
+
if (candidateHasToolUse(params.candidate)) return false
|
|
38
|
+
return buildGenericPendingFinalAnswerRepairPromptIfNeeded({
|
|
39
|
+
messages: [...params.messages, params.candidate],
|
|
40
|
+
}) !== undefined
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function shouldBlockToolUseAfterGenericPendingFinalAnswerRepair(
|
|
44
|
+
params: CandidateWithholdParams,
|
|
45
|
+
): boolean {
|
|
46
|
+
return hasGenericPendingFinalRepairPrompt(params.messages) &&
|
|
47
|
+
candidateHasToolUse(params.candidate)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function buildGenericPendingFinalAnswerToolUseBlockedText(): string {
|
|
51
|
+
return GENERIC_PENDING_FINAL_TOOL_USE_BLOCKED_TEXT
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function selectUmmayaClientForcedToolUseForPublicData(_params: {
|
|
55
|
+
readonly messages: readonly Message[]
|
|
56
|
+
readonly tools: Tools
|
|
57
|
+
}): undefined {
|
|
58
|
+
return undefined
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function hasGenericPendingFinalRepairPrompt(messages: readonly Message[]): boolean {
|
|
62
|
+
return messages.some(message =>
|
|
63
|
+
textFromContent(messageContent(message)).includes(
|
|
64
|
+
'Final answer repair: successful tool_result',
|
|
65
|
+
),
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function candidateHasToolUse(candidate: Message): boolean {
|
|
70
|
+
const content = messageContent(candidate)
|
|
71
|
+
return Array.isArray(content) &&
|
|
72
|
+
content.some(block => isRecord(block) && block.type === 'tool_use')
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function hasToolResultAfterLatestUser(messages: readonly Message[]): boolean {
|
|
76
|
+
let latestUserIndex = -1
|
|
77
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
78
|
+
const message = messages[index]
|
|
79
|
+
if (messageRole(message) !== 'user') continue
|
|
80
|
+
const text = textFromContent(messageContent(message))
|
|
81
|
+
if (isNonSyntheticUserMessageText(message, text)) {
|
|
82
|
+
latestUserIndex = index
|
|
83
|
+
break
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (latestUserIndex < 0) return false
|
|
87
|
+
return messages.slice(latestUserIndex + 1).some(message => {
|
|
88
|
+
const content = messageContent(message)
|
|
89
|
+
return Array.isArray(content) &&
|
|
90
|
+
content.some(block => isRecord(block) && block.type === 'tool_result')
|
|
91
|
+
})
|
|
92
|
+
}
|