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,176 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import re
|
|
5
|
+
from collections.abc import Iterable
|
|
6
|
+
from typing import Literal
|
|
7
|
+
from urllib.parse import parse_qsl, urlencode, urlsplit, urlunsplit
|
|
8
|
+
|
|
9
|
+
RedactionCategory = Literal[
|
|
10
|
+
"auth_header",
|
|
11
|
+
"cookie",
|
|
12
|
+
"service_key",
|
|
13
|
+
"token",
|
|
14
|
+
"pii",
|
|
15
|
+
"private_document",
|
|
16
|
+
]
|
|
17
|
+
PromptInjectionState = Literal["detected", "not_detected"]
|
|
18
|
+
|
|
19
|
+
_AUTH_HEADER_PATTERN = re.compile(r"\bAuthorization\s*:\s*[^\n\r;]+", re.IGNORECASE)
|
|
20
|
+
_AUTH_ASSIGNMENT_PATTERN = re.compile(
|
|
21
|
+
r"\bauthorization\s*=\s*[^\s&;\n\r]+",
|
|
22
|
+
re.IGNORECASE,
|
|
23
|
+
)
|
|
24
|
+
_COOKIE_PATTERN = re.compile(r"\bCookie\s*:\s*[^;\n\r]+;?\s*", re.IGNORECASE)
|
|
25
|
+
_COOKIE_ASSIGNMENT_PATTERN = re.compile(
|
|
26
|
+
r"\bcookie\s*=\s*[^\s&;\n\r]+",
|
|
27
|
+
re.IGNORECASE,
|
|
28
|
+
)
|
|
29
|
+
_SERVICE_KEY_PATTERN = re.compile(
|
|
30
|
+
r"\b(?:serviceKey|authKey)\s*=\s*[^\s&]+",
|
|
31
|
+
re.IGNORECASE,
|
|
32
|
+
)
|
|
33
|
+
_TOKEN_PATTERN = re.compile(
|
|
34
|
+
r"\b(?:UMMAYA_[A-Z0-9_]*TOKEN|"
|
|
35
|
+
r"[A-Z0-9_]*(?:API|AUTH|ACCESS|REFRESH|SESSION)[_-]?KEY|"
|
|
36
|
+
r"(?:session|access|refresh|id)[_-]?token)\s*=\s*[^\s&]+|"
|
|
37
|
+
r"\bBearer\s+[A-Za-z0-9._~+/=-]+",
|
|
38
|
+
re.IGNORECASE,
|
|
39
|
+
)
|
|
40
|
+
_GENERIC_TOKEN_ASSIGNMENT_PATTERN = re.compile(
|
|
41
|
+
r"\b(?:token|secret|api[_-]?key|access[_-]?token|session[_-]?token|"
|
|
42
|
+
r"refresh[_-]?token|id[_-]?token|client[_-]?secret)\s*=\s*[^\s&;\n\r]+",
|
|
43
|
+
re.IGNORECASE,
|
|
44
|
+
)
|
|
45
|
+
_EMAIL_PATTERN = re.compile(r"\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b", re.IGNORECASE)
|
|
46
|
+
_KOREAN_RRN_PATTERN = re.compile(r"\b\d{6}-[1-4]\d{6}\b")
|
|
47
|
+
_PHONE_PATTERN = re.compile(r"\b01[016789]-?\d{3,4}-?\d{4}\b")
|
|
48
|
+
_PRIVATE_DOCUMENT_PATTERN = re.compile(
|
|
49
|
+
r"-----BEGIN [A-Z ]*PRIVATE KEY-----|raw private document|private document bytes",
|
|
50
|
+
re.IGNORECASE,
|
|
51
|
+
)
|
|
52
|
+
_PROMPT_INJECTION_PATTERNS: tuple[re.Pattern[str], ...] = (
|
|
53
|
+
re.compile(r"ignore\s+(?:all\s+)?previous\s+instructions", re.IGNORECASE),
|
|
54
|
+
re.compile(r"change\s+(?:the\s+)?permission\s+policy", re.IGNORECASE),
|
|
55
|
+
re.compile(r"bypass\s+(?:permissions?|approval|policy)", re.IGNORECASE),
|
|
56
|
+
re.compile(r"treat\s+this\s+as\s+(?:a\s+)?system\s+instruction", re.IGNORECASE),
|
|
57
|
+
)
|
|
58
|
+
_SECRET_QUERY_KEYS = frozenset(
|
|
59
|
+
{
|
|
60
|
+
"access_token",
|
|
61
|
+
"api_key",
|
|
62
|
+
"apikey",
|
|
63
|
+
"auth",
|
|
64
|
+
"authkey",
|
|
65
|
+
"authorization",
|
|
66
|
+
"cookie",
|
|
67
|
+
"id_token",
|
|
68
|
+
"key",
|
|
69
|
+
"refresh_token",
|
|
70
|
+
"servicekey",
|
|
71
|
+
"session",
|
|
72
|
+
"session_token",
|
|
73
|
+
"token",
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def redact_source_url(value: str | None) -> tuple[str | None, tuple[RedactionCategory, ...]]:
|
|
79
|
+
if value is None:
|
|
80
|
+
return None, ()
|
|
81
|
+
categories: list[RedactionCategory] = []
|
|
82
|
+
try:
|
|
83
|
+
parsed = urlsplit(value)
|
|
84
|
+
except ValueError:
|
|
85
|
+
return redact_source_text(value)
|
|
86
|
+
query_items: list[tuple[str, str]] = []
|
|
87
|
+
for key, item_value in parse_qsl(parsed.query, keep_blank_values=True):
|
|
88
|
+
lowered_key = key.lower()
|
|
89
|
+
if lowered_key in _SECRET_QUERY_KEYS:
|
|
90
|
+
categories.append(
|
|
91
|
+
"service_key" if lowered_key in {"authkey", "servicekey"} else "token"
|
|
92
|
+
)
|
|
93
|
+
continue
|
|
94
|
+
redacted_value, item_categories = redact_source_text(item_value)
|
|
95
|
+
categories.extend(item_categories)
|
|
96
|
+
query_items.append((key, redacted_value or ""))
|
|
97
|
+
rebuilt = urlunsplit(
|
|
98
|
+
(
|
|
99
|
+
parsed.scheme,
|
|
100
|
+
parsed.netloc,
|
|
101
|
+
parsed.path,
|
|
102
|
+
urlencode(query_items),
|
|
103
|
+
parsed.fragment,
|
|
104
|
+
)
|
|
105
|
+
)
|
|
106
|
+
redacted_text, text_categories = redact_source_text(rebuilt)
|
|
107
|
+
categories.extend(text_categories)
|
|
108
|
+
return redacted_text, ordered_redaction_categories(categories)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def redact_source_text(value: str | None) -> tuple[str | None, tuple[RedactionCategory, ...]]:
|
|
112
|
+
if value is None:
|
|
113
|
+
return None, ()
|
|
114
|
+
categories = list(redaction_categories_for_text(value))
|
|
115
|
+
redacted = _AUTH_HEADER_PATTERN.sub("[REDACTED_AUTH_HEADER]", value)
|
|
116
|
+
redacted = _AUTH_ASSIGNMENT_PATTERN.sub("[REDACTED_AUTH_HEADER]", redacted)
|
|
117
|
+
redacted = _COOKIE_PATTERN.sub("[REDACTED_COOKIE] ", redacted)
|
|
118
|
+
redacted = _COOKIE_ASSIGNMENT_PATTERN.sub("[REDACTED_COOKIE]", redacted)
|
|
119
|
+
redacted = _SERVICE_KEY_PATTERN.sub("[REDACTED_SERVICE_KEY]", redacted)
|
|
120
|
+
redacted = _TOKEN_PATTERN.sub("[REDACTED_TOKEN]", redacted)
|
|
121
|
+
redacted = _GENERIC_TOKEN_ASSIGNMENT_PATTERN.sub("[REDACTED_TOKEN]", redacted)
|
|
122
|
+
redacted = _EMAIL_PATTERN.sub("[REDACTED_PII]", redacted)
|
|
123
|
+
redacted = _KOREAN_RRN_PATTERN.sub("[REDACTED_PII]", redacted)
|
|
124
|
+
redacted = _PHONE_PATTERN.sub("[REDACTED_PII]", redacted)
|
|
125
|
+
redacted = _PRIVATE_DOCUMENT_PATTERN.sub("[REDACTED_PRIVATE_DOCUMENT]", redacted)
|
|
126
|
+
return re.sub(r"[ \t]{2,}", " ", redacted).strip(), ordered_redaction_categories(categories)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def detect_prompt_injection(value: str) -> PromptInjectionState:
|
|
130
|
+
return (
|
|
131
|
+
"detected"
|
|
132
|
+
if any(pattern.search(value) for pattern in _PROMPT_INJECTION_PATTERNS)
|
|
133
|
+
else "not_detected"
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def redaction_categories_for_text(value: str) -> tuple[RedactionCategory, ...]:
|
|
138
|
+
categories: list[RedactionCategory] = []
|
|
139
|
+
if _AUTH_HEADER_PATTERN.search(value):
|
|
140
|
+
categories.append("auth_header")
|
|
141
|
+
if _AUTH_ASSIGNMENT_PATTERN.search(value):
|
|
142
|
+
categories.append("auth_header")
|
|
143
|
+
if _COOKIE_PATTERN.search(value):
|
|
144
|
+
categories.append("cookie")
|
|
145
|
+
if _COOKIE_ASSIGNMENT_PATTERN.search(value):
|
|
146
|
+
categories.append("cookie")
|
|
147
|
+
if _SERVICE_KEY_PATTERN.search(value):
|
|
148
|
+
categories.append("service_key")
|
|
149
|
+
if _TOKEN_PATTERN.search(value):
|
|
150
|
+
categories.append("token")
|
|
151
|
+
if _GENERIC_TOKEN_ASSIGNMENT_PATTERN.search(value):
|
|
152
|
+
categories.append("token")
|
|
153
|
+
if (
|
|
154
|
+
_EMAIL_PATTERN.search(value)
|
|
155
|
+
or _KOREAN_RRN_PATTERN.search(value)
|
|
156
|
+
or _PHONE_PATTERN.search(value)
|
|
157
|
+
):
|
|
158
|
+
categories.append("pii")
|
|
159
|
+
if _PRIVATE_DOCUMENT_PATTERN.search(value):
|
|
160
|
+
categories.append("private_document")
|
|
161
|
+
return ordered_redaction_categories(categories)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def ordered_redaction_categories(
|
|
165
|
+
categories: Iterable[RedactionCategory],
|
|
166
|
+
) -> tuple[RedactionCategory, ...]:
|
|
167
|
+
order: tuple[RedactionCategory, ...] = (
|
|
168
|
+
"auth_header",
|
|
169
|
+
"cookie",
|
|
170
|
+
"service_key",
|
|
171
|
+
"token",
|
|
172
|
+
"pii",
|
|
173
|
+
"private_document",
|
|
174
|
+
)
|
|
175
|
+
present = set(categories)
|
|
176
|
+
return tuple(category for category in order if category in present)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
|
|
6
|
+
from ummaya.evidence.models import RouteTraceRecord
|
|
7
|
+
from ummaya.evidence.tool_layer_models import ToolLayerEvidenceEvent
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass(frozen=True, slots=True)
|
|
11
|
+
class ToolLayerEvidenceJoinError(ValueError):
|
|
12
|
+
"""Raised when a tool-layer artifact cannot be joined to route evidence."""
|
|
13
|
+
|
|
14
|
+
event_id: str
|
|
15
|
+
|
|
16
|
+
def __str__(self) -> str:
|
|
17
|
+
return f"tool-layer event does not join to route evidence: {self.event_id}"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def build_tool_layer_events(
|
|
21
|
+
route_trace_records: tuple[RouteTraceRecord, ...],
|
|
22
|
+
*,
|
|
23
|
+
observed_events: tuple[ToolLayerEvidenceEvent, ...] = (),
|
|
24
|
+
) -> tuple[ToolLayerEvidenceEvent, ...]:
|
|
25
|
+
"""Return validated tool-layer artifacts without synthesizing sample events."""
|
|
26
|
+
|
|
27
|
+
if not observed_events:
|
|
28
|
+
return ()
|
|
29
|
+
|
|
30
|
+
route_keys = {
|
|
31
|
+
(record.scenario_id, record.trace_id, record.correlation_id)
|
|
32
|
+
for record in route_trace_records
|
|
33
|
+
if record.trace_kind == "scenario_route"
|
|
34
|
+
}
|
|
35
|
+
for event in observed_events:
|
|
36
|
+
event_key = (event.scenario_id, event.trace_id, event.correlation_id)
|
|
37
|
+
if event_key not in route_keys:
|
|
38
|
+
raise ToolLayerEvidenceJoinError(event_id=event.event_id)
|
|
39
|
+
return observed_events
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""Tool-layer Evidence Fabric event models."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
from typing import Literal, Self, assert_never
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
|
9
|
+
from pydantic_core import PydanticCustomError
|
|
10
|
+
|
|
11
|
+
ToolLayerExposureState = Literal[
|
|
12
|
+
"always-loaded",
|
|
13
|
+
"deferred-searchable",
|
|
14
|
+
"permission-gated-callable",
|
|
15
|
+
"hidden",
|
|
16
|
+
"unsupported",
|
|
17
|
+
]
|
|
18
|
+
ToolLayerTrustTier = Literal[0, 1, 2, 3, 4, 5]
|
|
19
|
+
ToolLayerPermissionDecision = Literal[
|
|
20
|
+
"not_required",
|
|
21
|
+
"approved",
|
|
22
|
+
"denied",
|
|
23
|
+
"blocked_pending_approval",
|
|
24
|
+
"policy_preapproved",
|
|
25
|
+
]
|
|
26
|
+
ToolLayerResultStatus = Literal["succeeded", "failed", "blocked"]
|
|
27
|
+
ToolLayerBlockedState = Literal[
|
|
28
|
+
"not_blocked",
|
|
29
|
+
"blocked_by_permission",
|
|
30
|
+
"blocked_by_policy",
|
|
31
|
+
"blocked_by_missing_source",
|
|
32
|
+
"blocked_by_unsupported",
|
|
33
|
+
]
|
|
34
|
+
ToolLayerRenderFrame = Literal[
|
|
35
|
+
"permission_prompt",
|
|
36
|
+
"tool_call",
|
|
37
|
+
"tool_result",
|
|
38
|
+
"blocked_state",
|
|
39
|
+
]
|
|
40
|
+
ToolLayerPromptInjectionState = Literal["detected", "not_detected"]
|
|
41
|
+
ToolLayerSourceTrust = Literal["trusted", "untrusted"]
|
|
42
|
+
ToolLayerSourceInstructionVisibility = Literal["evidence_only"]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _validation_error(code: str, message: str) -> PydanticCustomError:
|
|
46
|
+
return PydanticCustomError(code, message)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class ToolLayerEvidenceEvent(BaseModel):
|
|
50
|
+
"""One recovered Claude Code support-tool exposure and provenance event."""
|
|
51
|
+
|
|
52
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
53
|
+
|
|
54
|
+
event_id: str = Field(min_length=1)
|
|
55
|
+
scenario_id: str = Field(min_length=1)
|
|
56
|
+
trace_id: str = Field(min_length=1)
|
|
57
|
+
correlation_id: str = Field(min_length=1)
|
|
58
|
+
frame_hash: str = Field(min_length=64, max_length=64)
|
|
59
|
+
render_frame: ToolLayerRenderFrame
|
|
60
|
+
selected_tool: str = Field(min_length=1)
|
|
61
|
+
exposure_state: ToolLayerExposureState
|
|
62
|
+
trust_tier: ToolLayerTrustTier
|
|
63
|
+
permission_decision: ToolLayerPermissionDecision
|
|
64
|
+
source_url: str | None
|
|
65
|
+
source_local_handle: str | None
|
|
66
|
+
source_citation_id: str = Field(min_length=1)
|
|
67
|
+
provenance_id: str = Field(min_length=1)
|
|
68
|
+
source_trust: ToolLayerSourceTrust
|
|
69
|
+
source_prompt_injection: ToolLayerPromptInjectionState
|
|
70
|
+
source_instruction_visibility: ToolLayerSourceInstructionVisibility = "evidence_only"
|
|
71
|
+
result_status: ToolLayerResultStatus
|
|
72
|
+
result_summary: str | None
|
|
73
|
+
error_summary: str | None
|
|
74
|
+
blocked_state: ToolLayerBlockedState
|
|
75
|
+
|
|
76
|
+
@field_validator("frame_hash")
|
|
77
|
+
@classmethod
|
|
78
|
+
def _validate_frame_hash(cls, value: str) -> str:
|
|
79
|
+
if len(value) != 64 or any(ch not in "0123456789abcdef" for ch in value):
|
|
80
|
+
raise _validation_error(
|
|
81
|
+
"tool_layer_frame_hash", "frame_hash must be lowercase SHA-256 hex"
|
|
82
|
+
)
|
|
83
|
+
return value
|
|
84
|
+
|
|
85
|
+
@field_validator("source_url", "source_local_handle", "source_citation_id", "provenance_id")
|
|
86
|
+
@classmethod
|
|
87
|
+
def _reject_model_visible_leakage_keys(cls, value: str | None) -> str | None:
|
|
88
|
+
if value is not None and ("adapter_id" in value or "expected_tool" in value):
|
|
89
|
+
raise _validation_error(
|
|
90
|
+
"tool_layer_model_visible_leakage",
|
|
91
|
+
"tool-layer evidence cannot carry model-visible leakage keys",
|
|
92
|
+
)
|
|
93
|
+
return value
|
|
94
|
+
|
|
95
|
+
@field_validator("result_summary", "error_summary")
|
|
96
|
+
@classmethod
|
|
97
|
+
def _reject_empty_summary(cls, value: str | None) -> str | None:
|
|
98
|
+
if value is not None and not value.strip():
|
|
99
|
+
raise _validation_error(
|
|
100
|
+
"tool_layer_blank_summary", "tool-layer summaries cannot be blank"
|
|
101
|
+
)
|
|
102
|
+
return value
|
|
103
|
+
|
|
104
|
+
@model_validator(mode="after")
|
|
105
|
+
def _requires_source_reference(self) -> Self:
|
|
106
|
+
if self.source_url is None and self.source_local_handle is None:
|
|
107
|
+
raise _validation_error(
|
|
108
|
+
"tool_layer_missing_source",
|
|
109
|
+
"tool-layer evidence requires source_url or source_local_handle",
|
|
110
|
+
)
|
|
111
|
+
return self
|
|
112
|
+
|
|
113
|
+
@model_validator(mode="after")
|
|
114
|
+
def _requires_status_payload(self) -> Self:
|
|
115
|
+
match self.result_status:
|
|
116
|
+
case "succeeded":
|
|
117
|
+
if self.result_summary is None:
|
|
118
|
+
raise _validation_error(
|
|
119
|
+
"tool_layer_missing_result_summary",
|
|
120
|
+
"succeeded tool-layer event requires result_summary",
|
|
121
|
+
)
|
|
122
|
+
if self.error_summary is not None:
|
|
123
|
+
raise _validation_error(
|
|
124
|
+
"tool_layer_unexpected_error_summary",
|
|
125
|
+
"succeeded tool-layer event cannot carry error_summary",
|
|
126
|
+
)
|
|
127
|
+
if self.blocked_state != "not_blocked":
|
|
128
|
+
raise _validation_error(
|
|
129
|
+
"tool_layer_unexpected_blocked_state",
|
|
130
|
+
"succeeded tool-layer event must not be blocked",
|
|
131
|
+
)
|
|
132
|
+
case "failed":
|
|
133
|
+
if self.error_summary is None:
|
|
134
|
+
raise _validation_error(
|
|
135
|
+
"tool_layer_failed_without_error",
|
|
136
|
+
"failed tool-layer event requires error_summary",
|
|
137
|
+
)
|
|
138
|
+
case "blocked":
|
|
139
|
+
if self.error_summary is None:
|
|
140
|
+
raise _validation_error(
|
|
141
|
+
"tool_layer_blocked_without_error",
|
|
142
|
+
"blocked tool-layer event requires error_summary",
|
|
143
|
+
)
|
|
144
|
+
if self.blocked_state == "not_blocked":
|
|
145
|
+
raise _validation_error(
|
|
146
|
+
"tool_layer_blocked_without_state",
|
|
147
|
+
"blocked tool-layer event requires a blocked_state",
|
|
148
|
+
)
|
|
149
|
+
case unreachable:
|
|
150
|
+
assert_never(unreachable)
|
|
151
|
+
return self
|
|
@@ -47,6 +47,7 @@ import importlib
|
|
|
47
47
|
import json
|
|
48
48
|
import logging
|
|
49
49
|
import os
|
|
50
|
+
import re
|
|
50
51
|
from datetime import UTC, datetime
|
|
51
52
|
from typing import IO, Any, Literal
|
|
52
53
|
|
|
@@ -255,7 +256,7 @@ def _build_entries( # noqa: C901, ANN401 — three-source walker, refactor defe
|
|
|
255
256
|
except Exception:
|
|
256
257
|
tools_list = []
|
|
257
258
|
|
|
258
|
-
root_primitive_tool_ids = frozenset({"locate", "find", "check", "send"})
|
|
259
|
+
root_primitive_tool_ids = frozenset({"locate", "find", "check", "send", "document"})
|
|
259
260
|
|
|
260
261
|
for tool in tools_list:
|
|
261
262
|
tool_id_opt: str | None = tool.id if hasattr(tool, "id") else getattr(tool, "tool_id", None)
|
|
@@ -371,24 +372,39 @@ def _verify_family_llm_description(
|
|
|
371
372
|
"""Build model-facing prose for a verify-family manifest entry."""
|
|
372
373
|
|
|
373
374
|
metadata = metadata or {}
|
|
374
|
-
tool_id = str(metadata.get("tool_id") or family).strip()
|
|
375
375
|
name = str(metadata.get("name_ko") or family).strip()
|
|
376
|
-
scope_rules = str(metadata.get("scope_rules") or "").strip()
|
|
376
|
+
scope_rules = _safe_verify_scope_rules(str(metadata.get("scope_rules") or "").strip())
|
|
377
377
|
scope_clause = f" {scope_rules}" if scope_rules else ""
|
|
378
378
|
return (
|
|
379
|
-
f"Internal check-family surface for {name} (family_hint='{family}'
|
|
380
|
-
|
|
381
|
-
"
|
|
382
|
-
"
|
|
383
|
-
"
|
|
384
|
-
"
|
|
379
|
+
f"Internal check-family surface for {name} (family_hint='{family}'). "
|
|
380
|
+
"Use this only through the core check primitive before a downstream "
|
|
381
|
+
"protected find/send action needs delegated authorization. Params must "
|
|
382
|
+
"follow input_schema_json exactly: scope_list contains "
|
|
383
|
+
"'<verb>:<adapter_family>.<action>' scope strings, purpose_ko is the "
|
|
384
|
+
"Korean citizen-facing consent purpose, and purpose_en is the audit-log "
|
|
385
385
|
"English purpose. The manifest entry stays source_mode='internal' because "
|
|
386
386
|
"the agency citation is emitted by the verify response transparency stamp, "
|
|
387
|
-
"while the pre-call tool schema remains stable for the TUI and LLM loop."
|
|
387
|
+
"while the pre-call tool schema remains stable for the TUI and LLM loop. "
|
|
388
|
+
"Do not mention internal mock bridge identifiers in citizen-facing prose."
|
|
388
389
|
f"{scope_clause}"
|
|
389
390
|
)
|
|
390
391
|
|
|
391
392
|
|
|
393
|
+
def _safe_verify_scope_rules(scope_rules: str) -> str:
|
|
394
|
+
if not scope_rules:
|
|
395
|
+
return ""
|
|
396
|
+
safe_sentences: list[str] = []
|
|
397
|
+
for sentence in re.split(r"(?<=[.!?])\s+", scope_rules):
|
|
398
|
+
candidate = sentence.strip()
|
|
399
|
+
if not candidate:
|
|
400
|
+
continue
|
|
401
|
+
lowered = candidate.lower()
|
|
402
|
+
if "mock_verify" in lowered or "tool_id" in lowered:
|
|
403
|
+
continue
|
|
404
|
+
safe_sentences.append(candidate)
|
|
405
|
+
return " ".join(safe_sentences)
|
|
406
|
+
|
|
407
|
+
|
|
392
408
|
def _string_list(value: object) -> list[str]:
|
|
393
409
|
"""Return non-empty strings from a loosely typed metadata list."""
|
|
394
410
|
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
import uuid
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Final
|
|
9
|
+
|
|
10
|
+
_DOCUMENT_WRITE_REQUEST_RE: Final = re.compile(
|
|
11
|
+
r"(작성|수정|편집|채우|채워|입력|변경|저장|write|edit|fill|apply|save)",
|
|
12
|
+
re.IGNORECASE,
|
|
13
|
+
)
|
|
14
|
+
_DOCUMENT_SAVE_REQUEST_RE: Final = re.compile(
|
|
15
|
+
r"(저장|내보내|export|save)",
|
|
16
|
+
re.IGNORECASE,
|
|
17
|
+
)
|
|
18
|
+
_DOCUMENT_READ_ONLY_INSPECT_RE: Final = re.compile(
|
|
19
|
+
r"(구조.{0,30}빈칸.{0,30}확인|빈칸.{0,30}확인|구조.{0,30}확인|"
|
|
20
|
+
r"확인해\s*줘|검토만|inspect|read[- ]?only)",
|
|
21
|
+
re.IGNORECASE,
|
|
22
|
+
)
|
|
23
|
+
_DOCUMENT_MUTATION_PROHIBITION_RE: Final = re.compile(
|
|
24
|
+
r"(절대.{0,40}(?:수정|저장|작성|채우|입력|변경).{0,40}"
|
|
25
|
+
r"(?:하지\s*마|하지\s*말|금지)|"
|
|
26
|
+
r"(?:수정|저장|작성|채우|입력|변경).{0,30}(?:하지\s*마|하지\s*말)|"
|
|
27
|
+
r"(?:do not|don't).{0,40}(?:modify|save|write|edit|fill))",
|
|
28
|
+
re.IGNORECASE,
|
|
29
|
+
)
|
|
30
|
+
_QUESTION_FIRST_AUTHORING_RE: Final = re.compile(
|
|
31
|
+
r"(근거가\s*부족하면\s*먼저\s*질문|먼저\s*(?:확인|파악|검토|질문|물어)|"
|
|
32
|
+
r"초안을?\s*먼저|아직.{0,40}(?:쓰지\s*마|작성하지\s*마|저장하지\s*마|"
|
|
33
|
+
r"반영하지\s*마)|문서에는\s*쓰지\s*마)",
|
|
34
|
+
re.IGNORECASE,
|
|
35
|
+
)
|
|
36
|
+
_DOCUMENT_MUTATION_PARAM_KEYS: Final[frozenset[str]] = frozenset(
|
|
37
|
+
{
|
|
38
|
+
"approved_draft_id",
|
|
39
|
+
"destination_display_name",
|
|
40
|
+
"destination_path",
|
|
41
|
+
"dry_run",
|
|
42
|
+
"patches",
|
|
43
|
+
"styles",
|
|
44
|
+
"template_id",
|
|
45
|
+
}
|
|
46
|
+
)
|
|
47
|
+
_DOCUMENT_INTERNAL_USER_QUERY_KEY: Final = "__ummaya_user_query"
|
|
48
|
+
_DOCUMENT_ROOT_SYNTHESIS_KEYS: Final[frozenset[str]] = frozenset(
|
|
49
|
+
{_DOCUMENT_INTERNAL_USER_QUERY_KEY}
|
|
50
|
+
)
|
|
51
|
+
_DOCUMENT_EXPLICIT_LOCAL_PATH_RE: Final = re.compile(
|
|
52
|
+
r"(?P<path>(?:~|/)[^\s\"'<>]+?\."
|
|
53
|
+
r"(?:hwpx|hwp|docx|pdf|xlsx|pptx|odt|ods|odp|doc|xls|ppt|csv|txt|md|json|xml|html))",
|
|
54
|
+
re.IGNORECASE,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _normalize_document_root_call_for_user_intent(
|
|
59
|
+
fname: str,
|
|
60
|
+
args_obj: dict[str, object],
|
|
61
|
+
latest_user_utt: str,
|
|
62
|
+
) -> dict[str, object]:
|
|
63
|
+
if fname != "document" or args_obj.get("tool_id") != "document":
|
|
64
|
+
return args_obj
|
|
65
|
+
params_obj = args_obj.get("params")
|
|
66
|
+
if not isinstance(params_obj, dict):
|
|
67
|
+
return args_obj
|
|
68
|
+
|
|
69
|
+
intent_text = _document_intent_text(params_obj, latest_user_utt)
|
|
70
|
+
synthesized_params = _synthesize_document_read_params(params_obj, intent_text)
|
|
71
|
+
if synthesized_params is not None:
|
|
72
|
+
return {**args_obj, "params": synthesized_params}
|
|
73
|
+
|
|
74
|
+
normalized_params = dict(params_obj)
|
|
75
|
+
normalized_params.pop(_DOCUMENT_INTERNAL_USER_QUERY_KEY, None)
|
|
76
|
+
_normalize_document_path_from_user_query(normalized_params, intent_text)
|
|
77
|
+
if _is_explicit_read_only_inspect_intent(intent_text):
|
|
78
|
+
read_only_params = _strip_mutation_params(normalized_params)
|
|
79
|
+
read_only_params["operation"] = "inspect"
|
|
80
|
+
read_only_params["instruction"] = intent_text
|
|
81
|
+
return {**args_obj, "params": read_only_params}
|
|
82
|
+
|
|
83
|
+
operation = str(params_obj.get("operation") or "").casefold()
|
|
84
|
+
changed = normalized_params != params_obj
|
|
85
|
+
if (
|
|
86
|
+
operation in {"fill", "save"}
|
|
87
|
+
and intent_text
|
|
88
|
+
and _DOCUMENT_WRITE_REQUEST_RE.search(intent_text)
|
|
89
|
+
):
|
|
90
|
+
if _DOCUMENT_SAVE_REQUEST_RE.search(intent_text):
|
|
91
|
+
normalized_params["operation"] = "save"
|
|
92
|
+
normalized_params["instruction"] = intent_text
|
|
93
|
+
return {**args_obj, "params": normalized_params}
|
|
94
|
+
if operation not in {"inspect", "extract"}:
|
|
95
|
+
return {**args_obj, "params": normalized_params} if changed else args_obj
|
|
96
|
+
if _should_keep_read_only_for_question_first_authoring(intent_text):
|
|
97
|
+
return {**args_obj, "params": normalized_params} if changed else args_obj
|
|
98
|
+
if not intent_text or not _DOCUMENT_WRITE_REQUEST_RE.search(intent_text):
|
|
99
|
+
return {**args_obj, "params": normalized_params} if changed else args_obj
|
|
100
|
+
|
|
101
|
+
normalized_params["operation"] = (
|
|
102
|
+
"save" if _DOCUMENT_SAVE_REQUEST_RE.search(intent_text) else "fill"
|
|
103
|
+
)
|
|
104
|
+
normalized_params["instruction"] = intent_text
|
|
105
|
+
return {**args_obj, "params": normalized_params}
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _document_intent_text(params_obj: dict[str, object], latest_user_utt: str) -> str:
|
|
109
|
+
internal_user_query = params_obj.get(_DOCUMENT_INTERNAL_USER_QUERY_KEY)
|
|
110
|
+
if isinstance(internal_user_query, str) and internal_user_query.strip():
|
|
111
|
+
return internal_user_query.strip()
|
|
112
|
+
return latest_user_utt
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _synthesize_document_read_params(
|
|
116
|
+
params_obj: dict[str, object],
|
|
117
|
+
intent_text: str,
|
|
118
|
+
) -> dict[str, object] | None:
|
|
119
|
+
if (
|
|
120
|
+
not intent_text
|
|
121
|
+
or isinstance(params_obj.get("document"), dict)
|
|
122
|
+
or set(params_obj) - _DOCUMENT_ROOT_SYNTHESIS_KEYS
|
|
123
|
+
):
|
|
124
|
+
return None
|
|
125
|
+
local_path = _first_existing_document_path(intent_text, None)
|
|
126
|
+
if local_path is None:
|
|
127
|
+
return None
|
|
128
|
+
document_format = local_path.suffix.removeprefix(".").lower()
|
|
129
|
+
return {
|
|
130
|
+
"correlation_id": f"document-intent-{uuid.uuid4().hex}",
|
|
131
|
+
"document": {"path": str(local_path), "expected_format": document_format},
|
|
132
|
+
"operation": "inspect",
|
|
133
|
+
"instruction": intent_text,
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def _normalize_document_path_from_user_query(
|
|
138
|
+
normalized_params: dict[str, object],
|
|
139
|
+
intent_text: str,
|
|
140
|
+
) -> None:
|
|
141
|
+
if not intent_text:
|
|
142
|
+
return
|
|
143
|
+
document_obj = normalized_params.get("document")
|
|
144
|
+
if not isinstance(document_obj, dict):
|
|
145
|
+
return
|
|
146
|
+
current_path = document_obj.get("path")
|
|
147
|
+
if isinstance(current_path, str) and Path(current_path).expanduser().exists():
|
|
148
|
+
return
|
|
149
|
+
expected_format = document_obj.get("expected_format")
|
|
150
|
+
expected_suffix = f".{expected_format}".lower() if isinstance(expected_format, str) else None
|
|
151
|
+
explicit_path = _first_existing_document_path(intent_text, expected_suffix)
|
|
152
|
+
if explicit_path is None:
|
|
153
|
+
return
|
|
154
|
+
normalized_params["document"] = {
|
|
155
|
+
**document_obj,
|
|
156
|
+
"path": str(explicit_path),
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _first_existing_document_path(intent_text: str, expected_suffix: str | None) -> Path | None:
|
|
161
|
+
for match in _DOCUMENT_EXPLICIT_LOCAL_PATH_RE.finditer(intent_text):
|
|
162
|
+
candidate = Path(match.group("path").rstrip(".,;:)]})")).expanduser()
|
|
163
|
+
if expected_suffix is not None and candidate.suffix.lower() != expected_suffix:
|
|
164
|
+
continue
|
|
165
|
+
if candidate.exists():
|
|
166
|
+
return candidate.resolve()
|
|
167
|
+
return None
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def _should_keep_read_only_for_question_first_authoring(intent_text: str) -> bool:
|
|
171
|
+
return bool(intent_text and _QUESTION_FIRST_AUTHORING_RE.search(intent_text))
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def _is_explicit_read_only_inspect_intent(intent_text: str) -> bool:
|
|
175
|
+
return bool(
|
|
176
|
+
intent_text
|
|
177
|
+
and _DOCUMENT_READ_ONLY_INSPECT_RE.search(intent_text)
|
|
178
|
+
and _DOCUMENT_MUTATION_PROHIBITION_RE.search(intent_text)
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def _strip_mutation_params(params_obj: dict[str, object]) -> dict[str, object]:
|
|
183
|
+
return {
|
|
184
|
+
key: value for key, value in params_obj.items() if key not in _DOCUMENT_MUTATION_PARAM_KEYS
|
|
185
|
+
}
|
|
@@ -528,7 +528,7 @@ class ToolResultEnvelope(BaseModel):
|
|
|
528
528
|
|
|
529
529
|
model_config = ConfigDict(frozen=True, extra="allow", populate_by_name=True)
|
|
530
530
|
|
|
531
|
-
kind: Literal["find", "locate", "send", "check"] = Field(
|
|
531
|
+
kind: Literal["find", "locate", "send", "check", "document"] = Field(
|
|
532
532
|
description="Primitive kind discriminator per Spec 031."
|
|
533
533
|
)
|
|
534
534
|
|
|
@@ -576,7 +576,7 @@ class WorkerStatusFrame(_BaseFrame):
|
|
|
576
576
|
role_id: str = Field(
|
|
577
577
|
description="Specialist label (e.g., transport-specialist, health-specialist)."
|
|
578
578
|
)
|
|
579
|
-
current_primitive: Literal["find", "locate", "send", "check"] = Field(
|
|
579
|
+
current_primitive: Literal["find", "locate", "send", "check", "document"] = Field(
|
|
580
580
|
description="Primitive currently being invoked by this worker."
|
|
581
581
|
)
|
|
582
582
|
status: Literal["idle", "running", "waiting_permission", "error"] = Field(
|
|
@@ -599,7 +599,7 @@ class PermissionRequestFrame(_BaseFrame):
|
|
|
599
599
|
description="ULID; round-trips in the matching permission_response frame."
|
|
600
600
|
)
|
|
601
601
|
worker_id: str = Field(description="Worker requesting permission.")
|
|
602
|
-
primitive_kind: Literal["find", "locate", "send", "check"] = Field(
|
|
602
|
+
primitive_kind: Literal["find", "locate", "send", "check", "document"] = Field(
|
|
603
603
|
description="The primitive the worker wants to invoke."
|
|
604
604
|
)
|
|
605
605
|
description_ko: str = Field(description="Korean-language description shown to the citizen.")
|
|
@@ -669,7 +669,7 @@ class PermissionResponseFrame(_BaseFrame):
|
|
|
669
669
|
# `layer: 1, tool_name: 'unknown'` (UI-C-1 spec violation: Layer 2/3
|
|
670
670
|
# submits were colour-coded green like a Layer 1 verify).
|
|
671
671
|
# Both fields are optional so legacy backends remain wire-compatible.
|
|
672
|
-
primitive_kind: Literal["find", "locate", "send", "check"] | None = Field(
|
|
672
|
+
primitive_kind: Literal["find", "locate", "send", "check", "document"] | None = Field(
|
|
673
673
|
default=None,
|
|
674
674
|
description=(
|
|
675
675
|
"The primitive that was authorised. The TUI feeds this into "
|
|
@@ -1220,7 +1220,7 @@ class AdapterManifestEntry(BaseModel):
|
|
|
1220
1220
|
max_length=80,
|
|
1221
1221
|
description="Human-readable display name; bilingual permitted.",
|
|
1222
1222
|
)
|
|
1223
|
-
primitive: Literal["find", "send", "check", "locate"] = Field(
|
|
1223
|
+
primitive: Literal["find", "send", "check", "locate", "document"] = Field(
|
|
1224
1224
|
description="Primitive verb the adapter is registered under (I6).",
|
|
1225
1225
|
)
|
|
1226
1226
|
policy_authority_url: str | None = Field(
|