ummaya 0.2.3 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -3
- package/bin/ummaya +10 -1
- package/npm-shrinkwrap.json +253 -2
- package/package.json +5 -1
- package/prompts/manifest.yaml +2 -2
- package/prompts/session_guidance_v1.md +3 -1
- package/prompts/system_v1.md +9 -7
- package/pyproject.toml +26 -7
- package/specs/2803-document-production-hardening/contracts/document-tools.schema.json +1043 -0
- package/src/ummaya/_canonical/__init__.py +2 -0
- package/src/ummaya/context/builder.py +17 -11
- package/src/ummaya/engine/engine.py +30 -113
- package/src/ummaya/engine/query.py +20 -0
- package/src/ummaya/evidence/__init__.py +44 -0
- package/src/ummaya/evidence/__main__.py +7 -0
- package/src/ummaya/evidence/dataset_contract.py +193 -0
- package/src/ummaya/evidence/document_authoring_cases.py +33 -0
- package/src/ummaya/evidence/document_harness.py +313 -0
- package/src/ummaya/evidence/document_viewer_ux.py +391 -0
- package/src/ummaya/evidence/gates.py +70 -0
- package/src/ummaya/evidence/json_types.py +20 -0
- package/src/ummaya/evidence/models.py +145 -0
- package/src/ummaya/evidence/output_payload.py +89 -0
- package/src/ummaya/evidence/payload_documents.py +233 -0
- package/src/ummaya/evidence/route_contracts.py +224 -0
- package/src/ummaya/evidence/route_helpers.py +150 -0
- package/src/ummaya/evidence/runner.py +177 -0
- package/src/ummaya/evidence/source_provenance.py +246 -0
- package/src/ummaya/evidence/source_provenance_redaction.py +176 -0
- package/src/ummaya/evidence/task_registry.py +264 -0
- package/src/ummaya/evidence/tool_layer.py +39 -0
- package/src/ummaya/evidence/tool_layer_models.py +151 -0
- package/src/ummaya/ipc/adapter_manifest_emitter.py +26 -10
- package/src/ummaya/ipc/document_intent_normalization.py +185 -0
- package/src/ummaya/ipc/frame_schema.py +52 -5
- package/src/ummaya/ipc/route_diagnostics.py +73 -0
- package/src/ummaya/ipc/stdio.py +2282 -417
- package/src/ummaya/llm/client.py +234 -59
- package/src/ummaya/llm/config.py +8 -3
- package/src/ummaya/llm/reasoning.py +84 -0
- package/src/ummaya/primitives/__init__.py +6 -2
- package/src/ummaya/primitives/delegation.py +1 -1
- package/src/ummaya/primitives/document.py +28 -0
- package/src/ummaya/settings.py +0 -3
- package/src/ummaya/tools/discovery_bridge.py +34 -2
- package/src/ummaya/tools/documents/__init__.py +297 -0
- package/src/ummaya/tools/documents/adapter_registry.py +487 -0
- package/src/ummaya/tools/documents/archive_container_probe.py +167 -0
- package/src/ummaya/tools/documents/artifact_store.py +454 -0
- package/src/ummaya/tools/documents/authoring.py +283 -0
- package/src/ummaya/tools/documents/baselines.py +114 -0
- package/src/ummaya/tools/documents/capability.py +331 -0
- package/src/ummaya/tools/documents/contracts.py +112 -0
- package/src/ummaya/tools/documents/conversion.py +521 -0
- package/src/ummaya/tools/documents/diff.py +275 -0
- package/src/ummaya/tools/documents/engines.py +163 -0
- package/src/ummaya/tools/documents/evaluation.py +291 -0
- package/src/ummaya/tools/documents/explicit_values.py +108 -0
- package/src/ummaya/tools/documents/fixtures.py +174 -0
- package/src/ummaya/tools/documents/format_completion_audit.py +471 -0
- package/src/ummaya/tools/documents/formats/__init__.py +2 -0
- package/src/ummaya/tools/documents/formats/archive.py +528 -0
- package/src/ummaya/tools/documents/formats/base.py +41 -0
- package/src/ummaya/tools/documents/formats/code_file.py +211 -0
- package/src/ummaya/tools/documents/formats/data_file.py +272 -0
- package/src/ummaya/tools/documents/formats/hwp.py +284 -0
- package/src/ummaya/tools/documents/formats/hwpx.py +1837 -0
- package/src/ummaya/tools/documents/formats/odf.py +435 -0
- package/src/ummaya/tools/documents/formats/ooxml.py +1030 -0
- package/src/ummaya/tools/documents/formats/passive.py +766 -0
- package/src/ummaya/tools/documents/formats/pdf.py +702 -0
- package/src/ummaya/tools/documents/formats/text_web.py +268 -0
- package/src/ummaya/tools/documents/hwp_conversion_probe.py +178 -0
- package/src/ummaya/tools/documents/hwp_direct_candidate.py +141 -0
- package/src/ummaya/tools/documents/inspection.py +289 -0
- package/src/ummaya/tools/documents/intake.py +1079 -0
- package/src/ummaya/tools/documents/legacy_office_promotion_probe.py +366 -0
- package/src/ummaya/tools/documents/models.py +1598 -0
- package/src/ummaya/tools/documents/odf_promotion_probe.py +167 -0
- package/src/ummaya/tools/documents/orchestrator.py +96 -0
- package/src/ummaya/tools/documents/passive_capability_probe.py +251 -0
- package/src/ummaya/tools/documents/patch.py +170 -0
- package/src/ummaya/tools/documents/pdfa_conformance.py +284 -0
- package/src/ummaya/tools/documents/pdfa_promotion_probe.py +198 -0
- package/src/ummaya/tools/documents/permissions.py +110 -0
- package/src/ummaya/tools/documents/planner.py +616 -0
- package/src/ummaya/tools/documents/registry.py +2733 -0
- package/src/ummaya/tools/documents/render.py +978 -0
- package/src/ummaya/tools/documents/render_comparison.py +113 -0
- package/src/ummaya/tools/documents/render_comparison_models.py +74 -0
- package/src/ummaya/tools/documents/render_comparison_regions.py +73 -0
- package/src/ummaya/tools/documents/render_comparison_style.py +161 -0
- package/src/ummaya/tools/documents/reread.py +157 -0
- package/src/ummaya/tools/documents/runtime_authoring.py +244 -0
- package/src/ummaya/tools/documents/runtime_authoring_bundle.py +76 -0
- package/src/ummaya/tools/documents/scorecard.py +184 -0
- package/src/ummaya/tools/documents/socratic_planner.py +193 -0
- package/src/ummaya/tools/documents/style.py +48 -0
- package/src/ummaya/tools/documents/tool_defs.py +523 -0
- package/src/ummaya/tools/documents/validate.py +347 -0
- package/src/ummaya/tools/executor.py +61 -12
- package/src/ummaya/tools/geocoding/kakao_client.py +1 -2
- package/src/ummaya/tools/kma/apihub_catalog.py +984 -1
- package/src/ummaya/tools/kma/apihub_structured_adapter.py +86 -6
- package/src/ummaya/tools/kma/apihub_url_adapter.py +593 -0
- package/src/ummaya/tools/kma/apihub_url_catalog.py +296 -0
- package/src/ummaya/tools/live_proxy.py +0 -3
- package/src/ummaya/tools/location_adapters.py +8 -6
- package/src/ummaya/tools/manifest_metadata.py +16 -3
- package/src/ummaya/tools/models.py +5 -1
- package/src/ummaya/tools/mvp_surface.py +2 -2
- package/src/ummaya/tools/nmc/emergency_search.py +8 -6
- package/src/ummaya/tools/register_all.py +17 -0
- package/src/ummaya/tools/registry.py +10 -1
- package/src/ummaya/tools/resolve_location.py +4 -4
- package/src/ummaya/tools/routing/__init__.py +59 -0
- package/src/ummaya/tools/routing/builder.py +105 -0
- package/src/ummaya/tools/routing/cards.py +29 -0
- package/src/ummaya/tools/routing/decision_service.py +534 -0
- package/src/ummaya/tools/routing/decision_types.py +74 -0
- package/src/ummaya/tools/routing/feasibility.py +122 -0
- package/src/ummaya/tools/routing/intent.py +17 -0
- package/src/ummaya/tools/routing/intent_extractor.py +207 -0
- package/src/ummaya/tools/routing/intent_patterns.py +160 -0
- package/src/ummaya/tools/routing/intent_public_data.py +150 -0
- package/src/ummaya/tools/routing/intent_types.py +48 -0
- package/src/ummaya/tools/routing/lint.py +78 -0
- package/src/ummaya/tools/routing/metadata.py +174 -0
- package/src/ummaya/tools/routing/projection.py +340 -0
- package/src/ummaya/tools/routing/retrieval_policy.py +629 -0
- package/src/ummaya/tools/routing/schema.py +81 -0
- package/src/ummaya/tools/routing/types.py +96 -0
- package/src/ummaya/tools/routing_index.py +2 -2
- package/src/ummaya/tools/search.py +40 -106
- package/src/ummaya/tools/verified_data_go_kr/_manifest.py +115 -25
- package/src/ummaya/tools/verified_data_go_kr/airkorea_air_quality.py +109 -4
- package/src/ummaya/tools/verified_data_go_kr/nmc_aed_site.py +108 -2
- package/src/ummaya/tools/verified_data_go_kr/pps_bid_public_info.py +174 -9
- package/src/ummaya/tools/verified_data_go_kr/tago_bus_arrival.py +66 -3
- package/src/ummaya/tools/verified_data_go_kr/tago_bus_location.py +12 -2
- package/src/ummaya/tools/verified_data_go_kr/tago_bus_route.py +8 -2
- package/src/ummaya/tools/verified_data_go_kr/tago_bus_route_station.py +114 -0
- package/src/ummaya/tools/verified_data_go_kr/tago_bus_station.py +14 -3
- package/src/ummaya/tools/verify_canonical_map.py +21 -0
- package/tests/fixtures/documents/public_forms/baselines.yaml +113 -0
- package/tui/package.json +1 -2
- package/tui/src/.cc-byte-identical-whitelist.yaml +266 -0
- package/tui/src/QueryEngine.ts +12 -4
- package/tui/src/bridge/inboundAttachments.ts +3 -3
- package/tui/src/cli/handlers/auth.ts +4 -13
- package/tui/src/cli/handlers/mcp.tsx +3 -3
- package/tui/src/cli/print.ts +69 -18
- package/tui/src/cli/update.ts +13 -13
- package/tui/src/commands/copy/index.ts +1 -1
- package/tui/src/commands/cost/cost.ts +2 -2
- package/tui/src/commands/init-verifiers.ts +5 -5
- package/tui/src/commands/init.ts +30 -30
- package/tui/src/commands/insights.ts +44 -44
- package/tui/src/commands/install-github-app/install-github-app.tsx +2 -2
- package/tui/src/commands/install-github-app/setupGitHubActions.ts +3 -3
- package/tui/src/commands/install-github-app/types.ts +8 -30
- package/tui/src/commands/install.tsx +5 -5
- package/tui/src/commands/mcp/addCommand.ts +5 -5
- package/tui/src/commands/mcp/xaaIdpCommand.ts +2 -2
- package/tui/src/commands/plugin/ManageMarketplaces.tsx +2 -2
- package/tui/src/commands/plugin/types.ts +6 -28
- package/tui/src/commands/plugin/unifiedTypes.ts +4 -26
- package/tui/src/commands/reasoning/index.ts +13 -0
- package/tui/src/commands/reasoning/reasoning.tsx +177 -0
- package/tui/src/commands/rename/generateSessionName.ts +1 -1
- package/tui/src/commands/thinkback/thinkback.tsx +3 -3
- package/tui/src/commands.ts +2 -0
- package/tui/src/components/Feedback.tsx +1 -1
- package/tui/src/components/LogoV2/EmergencyTip.tsx +11 -2
- package/tui/src/components/LogoV2/WelcomeV2.tsx +1 -3
- package/tui/src/components/Messages.tsx +2 -1
- package/tui/src/components/ScrollKeybindingHandler.tsx +6 -6
- package/tui/src/components/Spinner/types.ts +6 -28
- package/tui/src/components/Spinner.tsx +2 -2
- package/tui/src/components/agents/generateAgent.ts +1 -1
- package/tui/src/components/agents/new-agent-creation/types.ts +4 -26
- package/tui/src/components/config/EnvSecretIsolatedEditor.tsx +1 -1
- package/tui/src/components/design-system/LoadingState.tsx +2 -2
- package/tui/src/components/mcp/types.ts +16 -38
- package/tui/src/components/messages/AssistantToolUseMessage.tsx +3 -2
- package/tui/src/components/messages/UserCrossSessionMessage.ts +16 -4
- package/tui/src/components/messages/UserForkBoilerplateMessage.ts +16 -4
- package/tui/src/components/messages/UserGitHubWebhookMessage.ts +16 -4
- package/tui/src/components/messages/UserToolResultMessage/utils.tsx +3 -2
- package/tui/src/components/permissions/MonitorPermissionRequest/MonitorPermissionRequest.ts +9 -4
- package/tui/src/components/permissions/ReviewArtifactPermissionRequest/ReviewArtifactPermissionRequest.ts +9 -4
- package/tui/src/components/primitive/DocumentSocraticReviewBlock.tsx +129 -0
- package/tui/src/components/primitive/DocumentToolResultCard.tsx +224 -0
- package/tui/src/components/primitive/documentSocraticReview.ts +215 -0
- package/tui/src/components/primitive/index.tsx +43 -1
- package/tui/src/components/primitive/types.ts +137 -0
- package/tui/src/components/ui/option.ts +4 -26
- package/tui/src/constants/common.ts +0 -2
- package/tui/src/constants/prompts.ts +4 -3
- package/tui/src/constants/querySource.ts +4 -26
- package/tui/src/entrypoints/sdk/controlTypes.ts +26 -48
- package/tui/src/entrypoints/sdk/coreTypes.generated.ts +3 -25
- package/tui/src/entrypoints/sdk/runtimeTypes.ts +38 -60
- package/tui/src/entrypoints/sdk/sdkUtilityTypes.ts +4 -26
- package/tui/src/entrypoints/sdk/settingsTypes.generated.ts +3 -25
- package/tui/src/entrypoints/sdk/toolTypes.ts +3 -25
- package/tui/src/hooks/toolPermission/handlers/interactiveHandler.ts +10 -0
- package/tui/src/hooks/useApiKeyVerification.ts +1 -1
- package/tui/src/hooks/useVirtualScroll.ts +1 -1
- package/tui/src/ink/ink.tsx +33 -14
- package/tui/src/ink/reconciler.ts +2 -3
- package/tui/src/ink/render-to-screen.ts +30 -10
- package/tui/src/ipc/bridge.ts +62 -15
- package/tui/src/ipc/bridgeSingleton.ts +5 -1
- package/tui/src/ipc/codec.ts +29 -3
- package/tui/src/ipc/frames.generated.ts +407 -312
- package/tui/src/ipc/llmClient.ts +279 -76
- package/tui/src/ipc/llmTypes.ts +16 -1
- package/tui/src/ipc/schema/frame.schema.json +1 -3475
- package/tui/src/keybindings/defaultBindings.ts +4 -0
- package/tui/src/main.tsx +32 -11
- package/tui/src/native-ts/file-index/index.ts +33 -3
- package/tui/src/observability/surface.ts +2 -2
- package/tui/src/probes/toolRegistryProbe.tsx +3 -1
- package/tui/src/projectOnboardingState.ts +7 -6
- package/tui/src/query/chatMessageTypes.ts +18 -0
- package/tui/src/query/chatMessagesBuilder.ts +1 -1
- package/tui/src/query/deps.ts +1 -1
- package/tui/src/query/messageGuards.ts +106 -0
- package/tui/src/query/publicDataTerminalRepair.ts +384 -0
- package/tui/src/query/run.ts +1075 -0
- package/tui/src/query/supportBoundary.ts +168 -0
- package/tui/src/query/toolResultErrors.ts +103 -0
- package/tui/src/query/toolRunner.ts +687 -0
- package/tui/src/query/unavailableToolRepair.ts +118 -0
- package/tui/src/query.ts +9 -1721
- package/tui/src/screens/REPL.tsx +42 -31
- package/tui/src/services/api/adapterManifest.ts +4 -0
- package/tui/src/services/api/backendChat/events.ts +117 -0
- package/tui/src/services/api/backendChat/finalMessage.ts +40 -0
- package/tui/src/services/api/backendChat/frame.ts +9 -0
- package/tui/src/services/api/backendChat/streaming.ts +430 -0
- package/tui/src/services/api/backendChat/types.ts +62 -0
- package/tui/src/services/api/backendChat.ts +1 -0
- package/tui/src/services/api/client.ts +98 -14
- package/tui/src/services/api/errorUtils.ts +5 -5
- package/tui/src/services/api/errors.ts +1 -1
- package/tui/src/services/api/logging.ts +1 -1
- package/tui/src/services/api/ummaya/evidence.ts +194 -0
- package/tui/src/services/api/ummaya/messages.ts +255 -0
- package/tui/src/services/api/ummaya/nonStreaming.ts +66 -0
- package/tui/src/services/api/ummaya/provider.ts +200 -0
- package/tui/src/services/api/ummaya/reasoning.ts +24 -0
- package/tui/src/services/api/ummaya/request.ts +200 -0
- package/tui/src/services/api/ummaya/selectionContext.ts +240 -0
- package/tui/src/services/api/ummaya/streaming.ts +365 -0
- package/tui/src/services/api/ummaya/streamingPayload.ts +129 -0
- package/tui/src/services/api/ummaya/streamingReader.ts +40 -0
- package/tui/src/services/api/ummaya/toolSelection.ts +217 -0
- package/tui/src/services/api/ummaya/types.ts +110 -0
- package/tui/src/services/api/ummaya/usage.ts +30 -0
- package/tui/src/services/api/ummaya.ts +26 -364
- package/tui/src/services/api/withRetry.ts +1 -1
- package/tui/src/services/awaySummary.ts +2 -2
- package/tui/src/services/claudeAiLimits.ts +1 -1
- package/tui/src/services/compact/autoCompact.ts +1 -1
- package/tui/src/services/compact/compact.ts +1 -1
- package/tui/src/services/lsp/types.ts +8 -30
- package/tui/src/services/tips/types.ts +6 -28
- package/tui/src/services/tokenEstimation.ts +1 -1
- package/tui/src/services/toolRegistry/bootGuard.ts +5 -5
- package/tui/src/services/toolUseSummary/toolUseSummaryGenerator.ts +1 -1
- package/tui/src/services/tools/toolExecution.ts +94 -1
- package/tui/src/skills/bundled/stuck.ts +12 -12
- package/tui/src/state/AppStateStore.ts +7 -0
- package/tui/src/store/pendingPermissionSlot.ts +1 -1
- package/tui/src/store/session-store.ts +10 -36
- package/tui/src/stubs/any-stub.ts +15 -10
- package/tui/src/stubs/color-diff-napi.ts +37 -23
- package/tui/src/stubs/globals.d.ts +3 -3
- package/tui/src/stubs/macro-preload.ts +23 -12
- package/tui/src/tools/AdapterTool/AdapterTool.ts +1239 -163
- package/tui/src/tools/AdapterTool/routeDiagnostics.ts +75 -0
- package/tui/src/tools/AgentTool/AgentTool.tsx +84 -1371
- package/tui/src/tools/AgentTool/agentToolHandoff.ts +114 -0
- package/tui/src/tools/AgentTool/agentToolPartialResult.ts +16 -0
- package/tui/src/tools/AgentTool/agentToolProgress.ts +32 -0
- package/tui/src/tools/AgentTool/agentToolResolver.ts +161 -0
- package/tui/src/tools/AgentTool/agentToolResult.ts +163 -0
- package/tui/src/tools/AgentTool/agentToolUtils.ts +14 -686
- package/tui/src/tools/AgentTool/asyncAgentLifecycle.ts +208 -0
- package/tui/src/tools/AgentTool/asyncLifecycle.ts +153 -0
- package/tui/src/tools/AgentTool/backgroundedCompletion.ts +126 -0
- package/tui/src/tools/AgentTool/backgroundedLifecycle.ts +174 -0
- package/tui/src/tools/AgentTool/foregroundBackground.ts +83 -0
- package/tui/src/tools/AgentTool/foregroundDrain.tsx +133 -0
- package/tui/src/tools/AgentTool/foregroundFinalize.ts +98 -0
- package/tui/src/tools/AgentTool/foregroundLifecycle.tsx +237 -0
- package/tui/src/tools/AgentTool/foregroundProgress.tsx +169 -0
- package/tui/src/tools/AgentTool/foregroundTask.ts +89 -0
- package/tui/src/tools/AgentTool/forkSubagent.ts +1 -12
- package/tui/src/tools/AgentTool/forkSubagentGate.ts +34 -0
- package/tui/src/tools/AgentTool/launchRouting.ts +203 -0
- package/tui/src/tools/AgentTool/lifecycle.ts +244 -0
- package/tui/src/tools/AgentTool/mcpRouting.ts +73 -0
- package/tui/src/tools/AgentTool/orchestrationSupport.ts +70 -0
- package/tui/src/tools/AgentTool/permissions.ts +39 -0
- package/tui/src/tools/AgentTool/promptSetup.ts +181 -0
- package/tui/src/tools/AgentTool/remoteRouting.ts +62 -0
- package/tui/src/tools/AgentTool/resultMapping.ts +116 -0
- package/tui/src/tools/AgentTool/resumeAgent.ts +39 -107
- package/tui/src/tools/AgentTool/resumeAgentHelpers.ts +140 -0
- package/tui/src/tools/AgentTool/runAgent.ts +1 -1
- package/tui/src/tools/AgentTool/runtimeConfig.ts +57 -0
- package/tui/src/tools/AgentTool/schemas.ts +196 -0
- package/tui/src/tools/AgentTool/sourceVerificationPropagation.ts +263 -0
- package/tui/src/tools/AgentTool/worktreeLifecycle.ts +105 -0
- package/tui/src/tools/AskUserQuestionTool/AskUserQuestionTool.tsx +174 -202
- package/tui/src/tools/BashTool/BashTool.tsx +71 -1072
- package/tui/src/tools/BashTool/bashCommandHelpers.ts +12 -12
- package/tui/src/tools/BashTool/bashPermissions/astPreflight.ts +173 -0
- package/tui/src/tools/BashTool/bashPermissions/classifierChecks.ts +199 -0
- package/tui/src/tools/BashTool/bashPermissions/compoundGuards.ts +53 -0
- package/tui/src/tools/BashTool/bashPermissions/constants.ts +99 -0
- package/tui/src/tools/BashTool/bashPermissions/index.ts +38 -0
- package/tui/src/tools/BashTool/bashPermissions/legacyMisparsing.ts +62 -0
- package/tui/src/tools/BashTool/bashPermissions/main.ts +135 -0
- package/tui/src/tools/BashTool/bashPermissions/normalizedCommands.ts +33 -0
- package/tui/src/tools/BashTool/bashPermissions/operatorFlow.ts +98 -0
- package/tui/src/tools/BashTool/bashPermissions/permissionChecks.ts +200 -0
- package/tui/src/tools/BashTool/bashPermissions/prefixSuggestions.ts +88 -0
- package/tui/src/tools/BashTool/bashPermissions/promptClassifierRules.ts +125 -0
- package/tui/src/tools/BashTool/bashPermissions/ruleDelegates.ts +19 -0
- package/tui/src/tools/BashTool/bashPermissions/ruleMatching.ts +145 -0
- package/tui/src/tools/BashTool/bashPermissions/sandboxAutoAllow.ts +75 -0
- package/tui/src/tools/BashTool/bashPermissions/subcommandFlow.ts +205 -0
- package/tui/src/tools/BashTool/bashPermissions/subcommandGuards.ts +73 -0
- package/tui/src/tools/BashTool/bashPermissions/subcommandResultHelpers.ts +116 -0
- package/tui/src/tools/BashTool/bashPermissions/types.ts +26 -0
- package/tui/src/tools/BashTool/bashPermissions/wrapperStripping.ts +139 -0
- package/tui/src/tools/BashTool/bashPermissions.ts +26 -2621
- package/tui/src/tools/BashTool/call.ts +202 -0
- package/tui/src/tools/BashTool/callLoader.ts +35 -0
- package/tui/src/tools/BashTool/commandClassification.ts +151 -0
- package/tui/src/tools/BashTool/commandClassificationLoader.ts +40 -0
- package/tui/src/tools/BashTool/cwdReset.ts +33 -0
- package/tui/src/tools/BashTool/lineTruncation.ts +11 -0
- package/tui/src/tools/BashTool/modeValidation.ts +13 -1
- package/tui/src/tools/BashTool/outputPersistence.ts +42 -0
- package/tui/src/tools/BashTool/permissionClassification.ts +66 -0
- package/tui/src/tools/BashTool/permissionLoader.ts +44 -0
- package/tui/src/tools/BashTool/resultLoader.ts +29 -0
- package/tui/src/tools/BashTool/resultMapping.ts +83 -0
- package/tui/src/tools/BashTool/sandboxPolicy.ts +79 -0
- package/tui/src/tools/BashTool/schemas.ts +65 -0
- package/tui/src/tools/BashTool/sedEditExecution.ts +59 -0
- package/tui/src/tools/BashTool/shellExecution.tsx +245 -0
- package/tui/src/tools/BashTool/shellOutputUtils.ts +85 -0
- package/tui/src/tools/BashTool/shellPermissionGauntlet.ts +97 -0
- package/tui/src/tools/BashTool/uiLoader.ts +37 -0
- package/tui/src/tools/BriefTool/upload.ts +1 -1
- package/tui/src/tools/CalculatorTool/parser.ts +2 -2
- package/tui/src/tools/DocumentPrimitive/DocumentPrimitive.ts +262 -0
- package/tui/src/tools/DocumentPrimitive/dispatchNormalization.ts +270 -0
- package/tui/src/tools/DocumentPrimitive/documentDestinationPath.ts +18 -0
- package/tui/src/tools/DocumentPrimitive/documentMutationGuard.ts +22 -0
- package/tui/src/tools/DocumentPrimitive/documentPatchNormalization.ts +248 -0
- package/tui/src/tools/DocumentPrimitive/documentSourceVerification.ts +245 -0
- package/tui/src/tools/DocumentPrimitive/documentSourceVerificationFields.ts +103 -0
- package/tui/src/tools/DocumentPrimitive/modelVisibleOutput.ts +40 -0
- package/tui/src/tools/DocumentPrimitive/prompt.ts +35 -0
- package/tui/src/tools/FileEditTool/FileEditTool.ts +9 -507
- package/tui/src/tools/FileEditTool/call.ts +228 -0
- package/tui/src/tools/FileEditTool/validateInput.ts +196 -0
- package/tui/src/tools/FileReadTool/imageProcessor.ts +13 -0
- package/tui/src/tools/FileWriteTool/FileWriteTool.ts +7 -300
- package/tui/src/tools/FileWriteTool/call.ts +223 -0
- package/tui/src/tools/FileWriteTool/validateInput.ts +80 -0
- package/tui/src/tools/ListMcpResourcesTool/ListMcpResourcesTool.ts +19 -3
- package/tui/src/tools/LookupPrimitive/LookupPrimitive.ts +48 -29
- package/tui/src/tools/LookupPrimitive/prompt.ts +6 -7
- package/tui/src/tools/MCPTool/trustPolicy.ts +118 -0
- package/tui/src/tools/McpAuthTool/McpAuthTool.ts +21 -3
- package/tui/src/tools/NotebookEditTool/NotebookEditTool.ts +7 -326
- package/tui/src/tools/NotebookEditTool/call.ts +254 -0
- package/tui/src/tools/NotebookEditTool/notebookModel.ts +51 -0
- package/tui/src/tools/NotebookEditTool/validateInput.ts +142 -0
- package/tui/src/tools/PowerShellTool/PowerShellTool.tsx +46 -937
- package/tui/src/tools/PowerShellTool/acceptEditsCommandValidation.ts +162 -0
- package/tui/src/tools/PowerShellTool/call.ts +179 -0
- package/tui/src/tools/PowerShellTool/callLoader.ts +37 -0
- package/tui/src/tools/PowerShellTool/commandClassification.ts +86 -0
- package/tui/src/tools/PowerShellTool/modeValidation.ts +25 -332
- package/tui/src/tools/PowerShellTool/outputPersistence.ts +42 -0
- package/tui/src/tools/PowerShellTool/permissionClassification.ts +28 -0
- package/tui/src/tools/PowerShellTool/resultLoader.ts +31 -0
- package/tui/src/tools/PowerShellTool/resultMapping.ts +75 -0
- package/tui/src/tools/PowerShellTool/schemas.ts +40 -0
- package/tui/src/tools/PowerShellTool/shellExecution.tsx +258 -0
- package/tui/src/tools/PowerShellTool/symlinkModeValidation.ts +44 -0
- package/tui/src/tools/PowerShellTool/uiLoader.ts +37 -0
- package/tui/src/tools/PowerShellTool/validation.ts +39 -0
- package/tui/src/tools/ReadMcpResourceTool/ReadMcpResourceTool.ts +19 -3
- package/tui/src/tools/ResolveLocationPrimitive/ResolveLocationPrimitive.ts +30 -19
- package/tui/src/tools/ResolveLocationPrimitive/prompt.ts +2 -6
- package/tui/src/tools/SkillTool/SkillTool.ts +2 -2
- package/tui/src/tools/SubmitPrimitive/SubmitPrimitive.ts +51 -18
- package/tui/src/tools/TaskCreateTool/TaskCreateTool.ts +16 -2
- package/tui/src/tools/TaskGetTool/TaskGetTool.ts +23 -3
- package/tui/src/tools/TaskListTool/TaskListTool.ts +22 -4
- package/tui/src/tools/TaskOutputTool/TaskOutputTool.tsx +46 -547
- package/tui/src/tools/TaskOutputTool/lookup.ts +216 -0
- package/tui/src/tools/TaskOutputTool/render.tsx +257 -0
- package/tui/src/tools/TaskOutputTool/schemas.ts +55 -0
- package/tui/src/tools/TaskOutputTool/serialization.ts +36 -0
- package/tui/src/tools/TaskStopTool/TaskStopTool.ts +10 -0
- package/tui/src/tools/TaskUpdateTool/TaskUpdateTool.ts +14 -364
- package/tui/src/tools/TaskUpdateTool/completion.ts +62 -0
- package/tui/src/tools/TaskUpdateTool/schemas.ts +62 -0
- package/tui/src/tools/TaskUpdateTool/serialization.ts +46 -0
- package/tui/src/tools/TaskUpdateTool/statusUpdate.ts +247 -0
- package/tui/src/tools/TodoWriteTool/TodoWriteTool.ts +21 -2
- package/tui/src/tools/ToolSearchTool/ToolSearchTool.ts +21 -302
- package/tui/src/tools/ToolSearchTool/ccSupportTools.ts +223 -0
- package/tui/src/tools/ToolSearchTool/descriptionCache.ts +50 -0
- package/tui/src/tools/ToolSearchTool/keywordSearch.ts +216 -0
- package/tui/src/tools/ToolSearchTool/prompt.ts +10 -4
- package/tui/src/tools/ToolSearchTool/resultMapping.ts +30 -0
- package/tui/src/tools/ToolSearchTool/schemas.ts +30 -0
- package/tui/src/tools/ToolSearchTool/searchPool.ts +47 -0
- package/tui/src/tools/ToolSearchTool/supportIntentHints.ts +140 -0
- package/tui/src/tools/TranslateTool/TranslateTool.ts +1 -1
- package/tui/src/tools/VerifyPrimitive/VerifyPrimitive.ts +27 -10
- package/tui/src/tools/WebFetchTool/WebFetchTool.ts +43 -138
- package/tui/src/tools/WebFetchTool/call.ts +227 -0
- package/tui/src/tools/WebFetchTool/resolvedAddressSafety.ts +78 -0
- package/tui/src/tools/WebFetchTool/sourceVerification.ts +204 -0
- package/tui/src/tools/WebFetchTool/types.ts +23 -0
- package/tui/src/tools/WebFetchTool/urlSafety.ts +181 -0
- package/tui/src/tools/WebFetchTool/utils.ts +1 -1
- package/tui/src/tools/WebSearchTool/UI.tsx +0 -1
- package/tui/src/tools/WebSearchTool/WebSearchTool.ts +9 -313
- package/tui/src/tools/WebSearchTool/call.ts +33 -0
- package/tui/src/tools/WebSearchTool/responseMapping.ts +190 -0
- package/tui/src/tools/WebSearchTool/resultBlock.ts +47 -0
- package/tui/src/tools/WebSearchTool/schemas.ts +47 -0
- package/tui/src/tools/WebSearchTool/toolSchema.ts +12 -0
- package/tui/src/tools/WorkspaceToolAdapter/WorkspaceToolAdapter.ts +79 -0
- package/tui/src/tools/WorkspaceToolAdapter/allowedRootPolicy.ts +85 -0
- package/tui/src/tools/WorkspaceToolAdapter/documentFormatGuards.ts +73 -0
- package/tui/src/tools/WorkspaceToolAdapter/inputNormalization.ts +105 -0
- package/tui/src/tools/WorkspaceToolAdapter/mcpExposurePolicy.ts +64 -0
- package/tui/src/tools/WorkspaceToolAdapter/toolDefFactory.ts +215 -0
- package/tui/src/tools/WorkspaceToolAdapter/toolNames.ts +6 -0
- package/tui/src/tools/WorkspaceToolAdapter/workspacePolicy.ts +15 -0
- package/tui/src/tools/_shared/citizenUserText.ts +49 -0
- package/tui/src/tools/_shared/dispatchPrimitive.ts +6 -6
- package/tui/src/tools/_shared/documentChangeToPatch.ts +125 -0
- package/tui/src/tools/_shared/documentDispatchArguments.ts +87 -0
- package/tui/src/tools/_shared/documentPrimitiveTimeout.ts +13 -0
- package/tui/src/tools/_shared/documentToolResultRender.ts +98 -0
- package/tui/src/tools/_shared/locationInputRepair.ts +112 -0
- package/tui/src/tools/_shared/pendingCallRegistry.ts +1 -6
- package/tui/src/tools/_shared/rootPrimitiveInput.ts +68 -0
- package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPatterns.ts +58 -0
- package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPrompt.ts +271 -0
- package/tui/src/tools/_shared/toolChoiceRepair/documentRepair.ts +452 -0
- package/tui/src/tools/_shared/toolChoiceRepair/messageAccess.ts +80 -0
- package/tui/src/tools/_shared/toolChoiceRepair/publicDataRepair.ts +92 -0
- package/tui/src/tools/_shared/toolChoiceRepair/supportRepair.ts +135 -0
- package/tui/src/tools/_shared/toolChoiceRepair.ts +61 -0
- package/tui/src/tools/shared/mockDisclaimer.ts +1 -1
- package/tui/src/tools.ts +39 -190
- package/tui/src/types/fileSuggestion.ts +4 -26
- package/tui/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +186 -148
- package/tui/src/types/generated/events_mono/common/v1/auth.ts +25 -11
- package/tui/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +47 -30
- package/tui/src/types/generated/google/protobuf/timestamp.ts +21 -7
- package/tui/src/types/message.ts +80 -102
- package/tui/src/types/messageQueueTypes.ts +6 -28
- package/tui/src/types/notebook.ts +16 -38
- package/tui/src/types/statusLine.ts +4 -26
- package/tui/src/types/tools.ts +24 -46
- package/tui/src/types/utils.ts +6 -28
- package/tui/src/upstreamproxy/relay.ts +7 -3
- package/tui/src/upstreamproxy/upstreamproxy.ts +1 -1
- package/tui/src/utils/assistantMessageFactories.ts +9 -3
- package/tui/src/utils/attachments.ts +1 -1
- package/tui/src/utils/auth.ts +129 -139
- package/tui/src/utils/bash/ast.ts +23 -23
- package/tui/src/utils/bash/bashParser.ts +5 -5
- package/tui/src/utils/billing.ts +1 -1
- package/tui/src/utils/collapseReadSearch.ts +3 -3
- package/tui/src/utils/cronTasks.ts +1 -1
- package/tui/src/utils/execFileNoThrow.ts +1 -1
- package/tui/src/utils/filePersistence/types.ts +16 -38
- package/tui/src/utils/forkedAgent.ts +1 -1
- package/tui/src/utils/gracefulShutdown.ts +4 -4
- package/tui/src/utils/heapDumpService.ts +12 -8
- package/tui/src/utils/hooks/apiQueryHookHelper.ts +1 -1
- package/tui/src/utils/hooks/execPromptHook.ts +1 -1
- package/tui/src/utils/hooks/skillImprovement.ts +1 -1
- package/tui/src/utils/kExaoneReasoning.ts +138 -0
- package/tui/src/utils/mcp/dateTimeParser.ts +1 -1
- package/tui/src/utils/messages.ts +19 -0
- package/tui/src/utils/migrateSessions.ts +3 -3
- package/tui/src/utils/model/model.ts +6 -6
- package/tui/src/utils/multiToolLayout.ts +13 -0
- package/tui/src/utils/permissions/yoloClassifier.ts +1 -1
- package/tui/src/utils/plugins/headlessPluginInstall.ts +1 -1
- package/tui/src/utils/plugins/mcpPluginIntegration.ts +1 -1
- package/tui/src/utils/plugins/mcpbHandler.ts +1 -1
- package/tui/src/utils/plugins/pluginLoader.ts +8 -8
- package/tui/src/utils/processUserInput/processSlashCommand.tsx +2 -2
- package/tui/src/utils/processUserInput/processUserInput.ts +26 -0
- package/tui/src/utils/protectedNamespace.ts +5 -3
- package/tui/src/utils/rawJsonToolCall.ts +242 -0
- package/tui/src/utils/ripgrep.ts +16 -7
- package/tui/src/utils/sessionTitle.ts +1 -1
- package/tui/src/utils/settings/applySettingsChange.ts +4 -0
- package/tui/src/utils/settings/permissionValidation.ts +14 -2
- package/tui/src/utils/settings/types.ts +9 -3
- package/tui/src/utils/shell/prefix.ts +1 -1
- package/tui/src/utils/sideQuery.ts +1 -1
- package/tui/src/utils/stats.ts +1 -1
- package/tui/src/utils/systemThemeWatcher.ts +13 -3
- package/tui/src/utils/teleport.tsx +1 -1
- package/uv.lock +394 -22
- package/assets/copilot-gate-logo.svg +0 -58
- package/assets/govon-logo.svg +0 -40
- package/src/ummaya/eval/__init__.py +0 -5
- package/src/ummaya/eval/retrieval.py +0 -713
- package/tui/src/services/api/claude.ts +0 -3510
- package/tui/src/utils/messageStream.ts +0 -186
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""Optional local PDF/A export and conformance validation bridge."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import hashlib
|
|
7
|
+
import os
|
|
8
|
+
import shutil
|
|
9
|
+
import subprocess
|
|
10
|
+
import tempfile
|
|
11
|
+
from collections.abc import Mapping
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from shutil import which
|
|
15
|
+
from typing import Protocol
|
|
16
|
+
|
|
17
|
+
PDFA_EXPORTER_ID = "ghostscript-pdfa2b-pdfwrite-exporter"
|
|
18
|
+
PDFA_VALIDATOR_ID = "verapdf-pdfa-conformance-validator"
|
|
19
|
+
PDFA_FLAVOUR = "2b"
|
|
20
|
+
PDFA_TIMEOUT_SECONDS = 120
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class PdfaConformanceBridgeError(ValueError):
|
|
24
|
+
"""Raised when PDF/A export or validation fails closed."""
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass(frozen=True)
|
|
28
|
+
class PdfaConformanceReport:
|
|
29
|
+
"""Local post-write PDF/A conformance result."""
|
|
30
|
+
|
|
31
|
+
exporter_id: str
|
|
32
|
+
validator_id: str
|
|
33
|
+
pdfa_flavour: str
|
|
34
|
+
sha256: str
|
|
35
|
+
byte_size: int
|
|
36
|
+
summary: str
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass(frozen=True)
|
|
40
|
+
class PdfaExportResult:
|
|
41
|
+
"""PDF/A payload plus the conformance report that approved it."""
|
|
42
|
+
|
|
43
|
+
payload: bytes
|
|
44
|
+
report: PdfaConformanceReport
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class PdfaConformanceBridge(Protocol):
|
|
48
|
+
"""Bridge that turns a PDF payload into a validated PDF/A payload."""
|
|
49
|
+
|
|
50
|
+
bridge_id: str
|
|
51
|
+
|
|
52
|
+
def export_pdfa(self, payload: bytes) -> PdfaExportResult:
|
|
53
|
+
"""Return validated PDF/A bytes or fail closed."""
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class LocalPdfaConformanceBridge:
|
|
57
|
+
"""Ghostscript PDF/A export plus veraPDF post-write validation."""
|
|
58
|
+
|
|
59
|
+
bridge_id = "ghostscript-verapdf-pdfa2b-bridge"
|
|
60
|
+
|
|
61
|
+
def __init__(
|
|
62
|
+
self,
|
|
63
|
+
*,
|
|
64
|
+
ghostscript_executable: Path,
|
|
65
|
+
verapdf_executable: Path,
|
|
66
|
+
pdfa_def_path: Path,
|
|
67
|
+
srgb_icc_path: Path,
|
|
68
|
+
timeout_seconds: int = PDFA_TIMEOUT_SECONDS,
|
|
69
|
+
) -> None:
|
|
70
|
+
self.ghostscript_executable = _validated_executable(
|
|
71
|
+
ghostscript_executable,
|
|
72
|
+
label="ghostscript_executable",
|
|
73
|
+
)
|
|
74
|
+
self.verapdf_executable = _validated_executable(
|
|
75
|
+
verapdf_executable,
|
|
76
|
+
label="verapdf_executable",
|
|
77
|
+
)
|
|
78
|
+
self.pdfa_def_path = _validated_file(pdfa_def_path, label="pdfa_def_path")
|
|
79
|
+
self.srgb_icc_path = _validated_file(srgb_icc_path, label="srgb_icc_path")
|
|
80
|
+
if timeout_seconds < 1 or timeout_seconds > 300:
|
|
81
|
+
raise ValueError("PDF/A bridge timeout_seconds must be between 1 and 300")
|
|
82
|
+
self.timeout_seconds = timeout_seconds
|
|
83
|
+
|
|
84
|
+
def export_pdfa(self, payload: bytes) -> PdfaExportResult:
|
|
85
|
+
"""Export PDF bytes to PDF/A-2b and validate the output with veraPDF."""
|
|
86
|
+
if not payload.startswith(b"%PDF-"):
|
|
87
|
+
raise PdfaConformanceBridgeError("PDF/A export requires a PDF payload")
|
|
88
|
+
with tempfile.TemporaryDirectory(prefix="ummaya-pdfa-") as temp_root:
|
|
89
|
+
temp_dir = Path(temp_root)
|
|
90
|
+
input_path = temp_dir / "input.pdf"
|
|
91
|
+
output_path = temp_dir / "output.pdf"
|
|
92
|
+
pdfa_def_path = temp_dir / "PDFA_def.ps"
|
|
93
|
+
srgb_icc_path = temp_dir / "srgb.icc"
|
|
94
|
+
input_path.write_bytes(payload)
|
|
95
|
+
shutil.copy2(self.pdfa_def_path, pdfa_def_path)
|
|
96
|
+
shutil.copy2(self.srgb_icc_path, srgb_icc_path)
|
|
97
|
+
self._run_ghostscript(
|
|
98
|
+
input_path=input_path,
|
|
99
|
+
output_path=output_path,
|
|
100
|
+
cwd=temp_dir,
|
|
101
|
+
)
|
|
102
|
+
output_payload = output_path.read_bytes()
|
|
103
|
+
if not output_payload.startswith(b"%PDF-"):
|
|
104
|
+
raise PdfaConformanceBridgeError("PDF/A exporter did not produce a PDF payload")
|
|
105
|
+
report = self._validate_with_verapdf(output_path, output_payload)
|
|
106
|
+
return PdfaExportResult(payload=output_payload, report=report)
|
|
107
|
+
|
|
108
|
+
def _run_ghostscript(
|
|
109
|
+
self,
|
|
110
|
+
*,
|
|
111
|
+
input_path: Path,
|
|
112
|
+
output_path: Path,
|
|
113
|
+
cwd: Path,
|
|
114
|
+
) -> None:
|
|
115
|
+
command = [
|
|
116
|
+
str(self.ghostscript_executable),
|
|
117
|
+
"--permit-file-read=srgb.icc",
|
|
118
|
+
"-dPDFA=2",
|
|
119
|
+
"-dBATCH",
|
|
120
|
+
"-dNOPAUSE",
|
|
121
|
+
"-dNOOUTERSAVE",
|
|
122
|
+
"-sColorConversionStrategy=RGB",
|
|
123
|
+
"-sDEVICE=pdfwrite",
|
|
124
|
+
"-dPDFACompatibilityPolicy=1",
|
|
125
|
+
f"-sOutputFile={output_path}",
|
|
126
|
+
"PDFA_def.ps",
|
|
127
|
+
str(input_path),
|
|
128
|
+
]
|
|
129
|
+
completed = _run_local_command(
|
|
130
|
+
command,
|
|
131
|
+
cwd=cwd,
|
|
132
|
+
timeout_seconds=self.timeout_seconds,
|
|
133
|
+
)
|
|
134
|
+
if completed.returncode != 0:
|
|
135
|
+
raise PdfaConformanceBridgeError(
|
|
136
|
+
"Ghostscript PDF/A export failed: " + _process_output_summary(completed)
|
|
137
|
+
)
|
|
138
|
+
if not output_path.is_file() or output_path.stat().st_size == 0:
|
|
139
|
+
raise PdfaConformanceBridgeError("Ghostscript PDF/A export produced no output")
|
|
140
|
+
|
|
141
|
+
def _validate_with_verapdf(
|
|
142
|
+
self,
|
|
143
|
+
output_path: Path,
|
|
144
|
+
output_payload: bytes,
|
|
145
|
+
) -> PdfaConformanceReport:
|
|
146
|
+
command = [
|
|
147
|
+
str(self.verapdf_executable),
|
|
148
|
+
"--format",
|
|
149
|
+
"text",
|
|
150
|
+
"--flavour",
|
|
151
|
+
PDFA_FLAVOUR,
|
|
152
|
+
str(output_path),
|
|
153
|
+
]
|
|
154
|
+
completed = _run_local_command(
|
|
155
|
+
command,
|
|
156
|
+
cwd=output_path.parent,
|
|
157
|
+
timeout_seconds=self.timeout_seconds,
|
|
158
|
+
)
|
|
159
|
+
summary = _process_output_summary(completed)
|
|
160
|
+
if completed.returncode != 0 or not completed.stdout.decode(
|
|
161
|
+
"utf-8",
|
|
162
|
+
errors="replace",
|
|
163
|
+
).lstrip().startswith("PASS "):
|
|
164
|
+
raise PdfaConformanceBridgeError(
|
|
165
|
+
"veraPDF PDF/A conformance validation failed: " + summary
|
|
166
|
+
)
|
|
167
|
+
return PdfaConformanceReport(
|
|
168
|
+
exporter_id=PDFA_EXPORTER_ID,
|
|
169
|
+
validator_id=PDFA_VALIDATOR_ID,
|
|
170
|
+
pdfa_flavour=PDFA_FLAVOUR,
|
|
171
|
+
sha256=hashlib.sha256(output_payload).hexdigest(),
|
|
172
|
+
byte_size=len(output_payload),
|
|
173
|
+
summary=summary,
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def build_default_pdfa_conformance_bridge(
|
|
178
|
+
*,
|
|
179
|
+
env: Mapping[str, str] | None = None,
|
|
180
|
+
) -> PdfaConformanceBridge | None:
|
|
181
|
+
"""Build the local PDF/A bridge when Ghostscript and veraPDF are available."""
|
|
182
|
+
active_env = os.environ if env is None else env
|
|
183
|
+
ghostscript = _find_executable("gs", active_env=active_env)
|
|
184
|
+
verapdf = _find_executable("verapdf", active_env=active_env)
|
|
185
|
+
if ghostscript is None or verapdf is None:
|
|
186
|
+
return None
|
|
187
|
+
assets = discover_ghostscript_pdfa_assets(ghostscript)
|
|
188
|
+
if assets is None:
|
|
189
|
+
return None
|
|
190
|
+
pdfa_def_path, srgb_icc_path = assets
|
|
191
|
+
return LocalPdfaConformanceBridge(
|
|
192
|
+
ghostscript_executable=ghostscript,
|
|
193
|
+
verapdf_executable=verapdf,
|
|
194
|
+
pdfa_def_path=pdfa_def_path,
|
|
195
|
+
srgb_icc_path=srgb_icc_path,
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def discover_ghostscript_pdfa_assets(
|
|
200
|
+
ghostscript_executable: Path,
|
|
201
|
+
) -> tuple[Path, Path] | None:
|
|
202
|
+
"""Return Ghostscript's PDF/A prefix and sRGB ICC profile paths if present."""
|
|
203
|
+
executable = ghostscript_executable.expanduser().resolve(strict=False)
|
|
204
|
+
for parent in executable.parents:
|
|
205
|
+
pdfa_def_path = parent / "share" / "ghostscript" / "lib" / "PDFA_def.ps"
|
|
206
|
+
srgb_icc_path = parent / "share" / "ghostscript" / "iccprofiles" / "srgb.icc"
|
|
207
|
+
if pdfa_def_path.is_file() and srgb_icc_path.is_file():
|
|
208
|
+
return pdfa_def_path.resolve(strict=False), srgb_icc_path.resolve(strict=False)
|
|
209
|
+
return None
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def _find_executable(
|
|
213
|
+
executable_name: str,
|
|
214
|
+
*,
|
|
215
|
+
active_env: Mapping[str, str],
|
|
216
|
+
) -> Path | None:
|
|
217
|
+
path_env = active_env.get("PATH")
|
|
218
|
+
if not path_env:
|
|
219
|
+
return None
|
|
220
|
+
found = which(executable_name, path=path_env)
|
|
221
|
+
if found is None:
|
|
222
|
+
return None
|
|
223
|
+
candidate = Path(found).expanduser().resolve(strict=False)
|
|
224
|
+
if not candidate.exists() or not candidate.is_file() or not os.access(candidate, os.X_OK):
|
|
225
|
+
return None
|
|
226
|
+
return candidate
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def _validated_executable(path: Path, *, label: str) -> Path:
|
|
230
|
+
resolved = path.expanduser().resolve(strict=False)
|
|
231
|
+
if not resolved.is_absolute():
|
|
232
|
+
raise ValueError(f"{label} must be absolute")
|
|
233
|
+
if not resolved.exists() or not resolved.is_file() or not os.access(resolved, os.X_OK):
|
|
234
|
+
raise ValueError(f"{label} must be an executable file: {resolved}")
|
|
235
|
+
return resolved
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def _validated_file(path: Path, *, label: str) -> Path:
|
|
239
|
+
resolved = path.expanduser().resolve(strict=False)
|
|
240
|
+
if not resolved.is_absolute():
|
|
241
|
+
raise ValueError(f"{label} must be absolute")
|
|
242
|
+
if not resolved.is_file():
|
|
243
|
+
raise ValueError(f"{label} must be an existing file: {resolved}")
|
|
244
|
+
return resolved
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def _run_local_command(
|
|
248
|
+
command: list[str],
|
|
249
|
+
*,
|
|
250
|
+
cwd: Path,
|
|
251
|
+
timeout_seconds: int,
|
|
252
|
+
) -> subprocess.CompletedProcess[bytes]:
|
|
253
|
+
try:
|
|
254
|
+
return subprocess.run( # noqa: S603 - executables are absolute and prevalidated.
|
|
255
|
+
command,
|
|
256
|
+
cwd=cwd,
|
|
257
|
+
stdin=subprocess.DEVNULL,
|
|
258
|
+
capture_output=True,
|
|
259
|
+
timeout=timeout_seconds,
|
|
260
|
+
check=False,
|
|
261
|
+
)
|
|
262
|
+
except subprocess.TimeoutExpired as exc:
|
|
263
|
+
raise PdfaConformanceBridgeError(
|
|
264
|
+
f"PDF/A bridge command timed out after {timeout_seconds}s"
|
|
265
|
+
) from exc
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def _process_output_summary(completed: subprocess.CompletedProcess[bytes]) -> str:
|
|
269
|
+
stdout = _truncate_process_bytes(completed.stdout)
|
|
270
|
+
stderr = _truncate_process_bytes(completed.stderr)
|
|
271
|
+
if stdout and stderr:
|
|
272
|
+
return f"stdout={stdout!r}; stderr={stderr!r}"
|
|
273
|
+
if stdout:
|
|
274
|
+
return f"stdout={stdout!r}"
|
|
275
|
+
if stderr:
|
|
276
|
+
return f"stderr={stderr!r}"
|
|
277
|
+
return "no process output"
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def _truncate_process_bytes(payload: bytes, limit: int = 500) -> str:
|
|
281
|
+
text = payload.decode("utf-8", errors="replace").strip()
|
|
282
|
+
if len(text) <= limit:
|
|
283
|
+
return text
|
|
284
|
+
return f"{text[:limit]}..."
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""Local PDF/A conformance promotion diagnostics.
|
|
3
|
+
|
|
4
|
+
PDF/A artifacts can be parsed, rendered, and AcroForm-filled through the PDF
|
|
5
|
+
runtime boundary, but UMMAYA must not claim PDF/A-conformant output until a
|
|
6
|
+
local conformance validator verifies the post-write artifact.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
from collections.abc import Mapping, Sequence
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from shutil import which
|
|
15
|
+
from typing import Literal
|
|
16
|
+
|
|
17
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
18
|
+
|
|
19
|
+
from ummaya.tools.documents.models import (
|
|
20
|
+
DocumentFormat,
|
|
21
|
+
DocumentFormatFamily,
|
|
22
|
+
KnownDocumentFormat,
|
|
23
|
+
)
|
|
24
|
+
from ummaya.tools.documents.pdfa_conformance import (
|
|
25
|
+
PDFA_EXPORTER_ID,
|
|
26
|
+
PDFA_FLAVOUR,
|
|
27
|
+
PDFA_VALIDATOR_ID,
|
|
28
|
+
discover_ghostscript_pdfa_assets,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
PDFA_CANDIDATE_ID = "verapdf-pdfa-postwrite-gate"
|
|
32
|
+
PDFA_READ_ADAPTER_ID = "pypdf-acroform-adapter"
|
|
33
|
+
PDFA_SOURCE_REFS = (
|
|
34
|
+
"upstream:verapdf-home-pdfa-validation",
|
|
35
|
+
"upstream:verapdf-cli-validation",
|
|
36
|
+
"upstream:ghostscript-pdfa-pdfwrite",
|
|
37
|
+
"upstream:pypdf-pdfa-no-guarantee",
|
|
38
|
+
"upstream:pypdf-acroform-forms",
|
|
39
|
+
)
|
|
40
|
+
PDFA_RECOMMENDED_ARGS = (
|
|
41
|
+
"gs",
|
|
42
|
+
"--permit-file-read=srgb.icc",
|
|
43
|
+
"-dPDFA=2",
|
|
44
|
+
"-dBATCH",
|
|
45
|
+
"-dNOPAUSE",
|
|
46
|
+
"-dNOOUTERSAVE",
|
|
47
|
+
"-sColorConversionStrategy=RGB",
|
|
48
|
+
"-sDEVICE=pdfwrite",
|
|
49
|
+
"-dPDFACompatibilityPolicy=1",
|
|
50
|
+
"-sOutputFile={output}",
|
|
51
|
+
"PDFA_def.ps",
|
|
52
|
+
"{source}",
|
|
53
|
+
"&&",
|
|
54
|
+
"verapdf",
|
|
55
|
+
"--format",
|
|
56
|
+
"text",
|
|
57
|
+
"--flavour",
|
|
58
|
+
PDFA_FLAVOUR,
|
|
59
|
+
"{output}",
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
PdfaPromotionProbeStatus = Literal["blocked", "candidate_available"]
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class PdfaPromotionProbeReport(BaseModel):
|
|
66
|
+
"""Current local availability of PDF/A conformance validation candidates."""
|
|
67
|
+
|
|
68
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
69
|
+
|
|
70
|
+
candidate_id: str = Field(min_length=1)
|
|
71
|
+
known_format: KnownDocumentFormat
|
|
72
|
+
family: DocumentFormatFamily
|
|
73
|
+
status: PdfaPromotionProbeStatus
|
|
74
|
+
runtime_format: DocumentFormat
|
|
75
|
+
read_adapter_id: str = Field(min_length=1)
|
|
76
|
+
exporter_id: str = Field(min_length=1)
|
|
77
|
+
exporter_available: bool
|
|
78
|
+
exporter_executable: Path | None
|
|
79
|
+
pdfa_def_path: Path | None
|
|
80
|
+
srgb_icc_path: Path | None
|
|
81
|
+
validator_id: str = Field(min_length=1)
|
|
82
|
+
validator_available: bool
|
|
83
|
+
validator_executable: Path | None
|
|
84
|
+
recommended_args: tuple[str, ...]
|
|
85
|
+
reasons: tuple[str, ...]
|
|
86
|
+
required_gates: tuple[str, ...]
|
|
87
|
+
evidence_refs: tuple[str, ...]
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def probe_pdfa_promotion(
|
|
91
|
+
*,
|
|
92
|
+
env: Mapping[str, str] | None = None,
|
|
93
|
+
search_path: Sequence[str] | None = None,
|
|
94
|
+
) -> PdfaPromotionProbeReport:
|
|
95
|
+
"""Report PDF/A conformance-gate readiness without promoting output writes."""
|
|
96
|
+
active_env = os.environ if env is None else env
|
|
97
|
+
validator_executable = _find_verapdf_cli(active_env=active_env, search_path=search_path)
|
|
98
|
+
exporter_executable = _find_ghostscript_cli(active_env=active_env, search_path=search_path)
|
|
99
|
+
pdfa_assets = (
|
|
100
|
+
discover_ghostscript_pdfa_assets(exporter_executable)
|
|
101
|
+
if exporter_executable is not None
|
|
102
|
+
else None
|
|
103
|
+
)
|
|
104
|
+
pdfa_def_path = pdfa_assets[0] if pdfa_assets is not None else None
|
|
105
|
+
srgb_icc_path = pdfa_assets[1] if pdfa_assets is not None else None
|
|
106
|
+
validator_available = validator_executable is not None
|
|
107
|
+
exporter_available = exporter_executable is not None and pdfa_assets is not None
|
|
108
|
+
status: PdfaPromotionProbeStatus = (
|
|
109
|
+
"candidate_available" if validator_available and exporter_available else "blocked"
|
|
110
|
+
)
|
|
111
|
+
return PdfaPromotionProbeReport(
|
|
112
|
+
candidate_id=PDFA_CANDIDATE_ID,
|
|
113
|
+
known_format=KnownDocumentFormat.pdfa,
|
|
114
|
+
family=DocumentFormatFamily.pdf,
|
|
115
|
+
status=status,
|
|
116
|
+
runtime_format=DocumentFormat.pdf,
|
|
117
|
+
read_adapter_id=PDFA_READ_ADAPTER_ID,
|
|
118
|
+
exporter_id=PDFA_EXPORTER_ID,
|
|
119
|
+
exporter_available=exporter_available,
|
|
120
|
+
exporter_executable=exporter_executable,
|
|
121
|
+
pdfa_def_path=pdfa_def_path,
|
|
122
|
+
srgb_icc_path=srgb_icc_path,
|
|
123
|
+
validator_id=PDFA_VALIDATOR_ID,
|
|
124
|
+
validator_available=validator_available,
|
|
125
|
+
validator_executable=validator_executable,
|
|
126
|
+
recommended_args=PDFA_RECOMMENDED_ARGS,
|
|
127
|
+
reasons=_reasons(
|
|
128
|
+
validator_available=validator_available,
|
|
129
|
+
exporter_available=exporter_available,
|
|
130
|
+
),
|
|
131
|
+
required_gates=(
|
|
132
|
+
"pdfa_runtime_pdf_alias_intake_gate",
|
|
133
|
+
"pdf_acroform_write_render_save_gate",
|
|
134
|
+
"ghostscript_pdfa2b_export_available",
|
|
135
|
+
"verapdf_cli_available",
|
|
136
|
+
"verapdf_postwrite_conformance_gate",
|
|
137
|
+
"pdfa_runtime_completion_promotion",
|
|
138
|
+
),
|
|
139
|
+
evidence_refs=PDFA_SOURCE_REFS,
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def _find_verapdf_cli(
|
|
144
|
+
*,
|
|
145
|
+
active_env: Mapping[str, str],
|
|
146
|
+
search_path: Sequence[str] | None,
|
|
147
|
+
) -> Path | None:
|
|
148
|
+
path_env = os.pathsep.join(search_path) if search_path is not None else active_env.get("PATH")
|
|
149
|
+
if not path_env:
|
|
150
|
+
return None
|
|
151
|
+
found = which("verapdf", path=path_env)
|
|
152
|
+
if found is None:
|
|
153
|
+
return None
|
|
154
|
+
executable = Path(found).expanduser().resolve(strict=False)
|
|
155
|
+
if not _is_executable_file(executable):
|
|
156
|
+
return None
|
|
157
|
+
return executable
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _find_ghostscript_cli(
|
|
161
|
+
*,
|
|
162
|
+
active_env: Mapping[str, str],
|
|
163
|
+
search_path: Sequence[str] | None,
|
|
164
|
+
) -> Path | None:
|
|
165
|
+
path_env = os.pathsep.join(search_path) if search_path is not None else active_env.get("PATH")
|
|
166
|
+
if not path_env:
|
|
167
|
+
return None
|
|
168
|
+
found = which("gs", path=path_env)
|
|
169
|
+
if found is None:
|
|
170
|
+
return None
|
|
171
|
+
executable = Path(found).expanduser().resolve(strict=False)
|
|
172
|
+
if not _is_executable_file(executable):
|
|
173
|
+
return None
|
|
174
|
+
return executable
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def _is_executable_file(path: Path) -> bool:
|
|
178
|
+
return path.exists() and path.is_file() and os.access(path, os.X_OK)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def _reasons(*, validator_available: bool, exporter_available: bool) -> tuple[str, ...]:
|
|
182
|
+
reasons = [
|
|
183
|
+
"pdfa_runtime_aliases_pdf_adapter",
|
|
184
|
+
"pypdf_pdfa_conformance_not_claimed",
|
|
185
|
+
]
|
|
186
|
+
if validator_available:
|
|
187
|
+
reasons.append("verapdf_cli_found")
|
|
188
|
+
else:
|
|
189
|
+
reasons.append("verapdf_cli_not_found")
|
|
190
|
+
if exporter_available:
|
|
191
|
+
reasons.append("ghostscript_pdfa_exporter_found")
|
|
192
|
+
else:
|
|
193
|
+
reasons.append("ghostscript_pdfa_exporter_not_found")
|
|
194
|
+
if validator_available and exporter_available:
|
|
195
|
+
reasons.append("pdfa_postwrite_conformance_gate_available")
|
|
196
|
+
else:
|
|
197
|
+
reasons.append("pdfa_conformance_write_not_promoted")
|
|
198
|
+
return tuple(reasons)
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""Document artifact permission payloads for local harness operations."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
from enum import StrEnum
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
|
9
|
+
|
|
10
|
+
from ummaya.tools.documents.models import (
|
|
11
|
+
BlockedReason,
|
|
12
|
+
DocumentToolResult,
|
|
13
|
+
ToolResultStatus,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class DocumentArtifactPermissionKind(StrEnum):
|
|
18
|
+
"""Permission boundary for one document harness tool call."""
|
|
19
|
+
|
|
20
|
+
read_local_artifact = "read_local_artifact"
|
|
21
|
+
write_derivative_artifact = "write_derivative_artifact"
|
|
22
|
+
validate_local_artifact = "validate_local_artifact"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class DocumentArtifactPermissionPayload(BaseModel):
|
|
26
|
+
"""Minimal PermissionRequest payload for document artifacts.
|
|
27
|
+
|
|
28
|
+
The payload intentionally carries artifact/report identifiers only. It does
|
|
29
|
+
not expose source paths or inline bytes to the model-facing permission layer.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
33
|
+
|
|
34
|
+
kind: DocumentArtifactPermissionKind
|
|
35
|
+
tool_id: str = Field(min_length=1)
|
|
36
|
+
correlation_id: str = Field(min_length=1)
|
|
37
|
+
artifact_id: str = Field(min_length=1)
|
|
38
|
+
derivative_artifact_id: str | None = Field(default=None, min_length=1)
|
|
39
|
+
validation_report_id: str | None = Field(default=None, min_length=1)
|
|
40
|
+
intended_change_class: str | None = Field(default=None, min_length=1, max_length=80)
|
|
41
|
+
validation_status: str | None = Field(default=None, min_length=1, max_length=80)
|
|
42
|
+
requires_approval: bool
|
|
43
|
+
|
|
44
|
+
@model_validator(mode="after")
|
|
45
|
+
def _enforce_approval_boundary(self) -> DocumentArtifactPermissionPayload:
|
|
46
|
+
if (
|
|
47
|
+
self.kind is DocumentArtifactPermissionKind.write_derivative_artifact
|
|
48
|
+
and not self.requires_approval
|
|
49
|
+
):
|
|
50
|
+
raise ValueError("write_derivative_artifact permission requires approval")
|
|
51
|
+
if (
|
|
52
|
+
self.kind is not DocumentArtifactPermissionKind.write_derivative_artifact
|
|
53
|
+
and self.requires_approval
|
|
54
|
+
):
|
|
55
|
+
raise ValueError("read and validation document permissions do not require approval")
|
|
56
|
+
return self
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def build_document_artifact_permission(
|
|
60
|
+
*,
|
|
61
|
+
kind: DocumentArtifactPermissionKind,
|
|
62
|
+
tool_id: str,
|
|
63
|
+
correlation_id: str,
|
|
64
|
+
artifact_id: str,
|
|
65
|
+
derivative_artifact_id: str | None = None,
|
|
66
|
+
validation_report_id: str | None = None,
|
|
67
|
+
intended_change_class: str | None = None,
|
|
68
|
+
validation_status: str | None = None,
|
|
69
|
+
) -> DocumentArtifactPermissionPayload:
|
|
70
|
+
"""Build the identifier-only permission payload for a document tool call."""
|
|
71
|
+
return DocumentArtifactPermissionPayload(
|
|
72
|
+
kind=kind,
|
|
73
|
+
tool_id=tool_id,
|
|
74
|
+
correlation_id=correlation_id,
|
|
75
|
+
artifact_id=artifact_id,
|
|
76
|
+
derivative_artifact_id=derivative_artifact_id,
|
|
77
|
+
validation_report_id=validation_report_id,
|
|
78
|
+
intended_change_class=intended_change_class,
|
|
79
|
+
validation_status=validation_status,
|
|
80
|
+
requires_approval=kind is DocumentArtifactPermissionKind.write_derivative_artifact,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def document_permission_denied_result(
|
|
85
|
+
*,
|
|
86
|
+
tool_id: str,
|
|
87
|
+
correlation_id: str,
|
|
88
|
+
artifact_id: str,
|
|
89
|
+
derivative_artifact_id: str | None = None,
|
|
90
|
+
) -> DocumentToolResult:
|
|
91
|
+
"""Return a typed blocked result when the user denies a document write."""
|
|
92
|
+
artifact_refs = [artifact_id]
|
|
93
|
+
if derivative_artifact_id is not None:
|
|
94
|
+
artifact_refs.append(derivative_artifact_id)
|
|
95
|
+
return DocumentToolResult(
|
|
96
|
+
tool_id=tool_id,
|
|
97
|
+
correlation_id=correlation_id,
|
|
98
|
+
status=ToolResultStatus.blocked,
|
|
99
|
+
artifact_refs=artifact_refs,
|
|
100
|
+
text_summary="Document write permission was denied by the user.",
|
|
101
|
+
blocked_reason=BlockedReason.permission_denied,
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
__all__ = [
|
|
106
|
+
"DocumentArtifactPermissionKind",
|
|
107
|
+
"DocumentArtifactPermissionPayload",
|
|
108
|
+
"build_document_artifact_permission",
|
|
109
|
+
"document_permission_denied_result",
|
|
110
|
+
]
|