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.
Files changed (534) hide show
  1. package/README.md +17 -3
  2. package/bin/ummaya +10 -1
  3. package/npm-shrinkwrap.json +253 -2
  4. package/package.json +5 -1
  5. package/prompts/manifest.yaml +2 -2
  6. package/prompts/session_guidance_v1.md +3 -1
  7. package/prompts/system_v1.md +9 -7
  8. package/pyproject.toml +26 -7
  9. package/specs/2803-document-production-hardening/contracts/document-tools.schema.json +1043 -0
  10. package/src/ummaya/_canonical/__init__.py +2 -0
  11. package/src/ummaya/context/builder.py +17 -11
  12. package/src/ummaya/engine/engine.py +30 -113
  13. package/src/ummaya/engine/query.py +20 -0
  14. package/src/ummaya/evidence/__init__.py +44 -0
  15. package/src/ummaya/evidence/__main__.py +7 -0
  16. package/src/ummaya/evidence/dataset_contract.py +193 -0
  17. package/src/ummaya/evidence/document_authoring_cases.py +33 -0
  18. package/src/ummaya/evidence/document_harness.py +313 -0
  19. package/src/ummaya/evidence/document_viewer_ux.py +391 -0
  20. package/src/ummaya/evidence/gates.py +70 -0
  21. package/src/ummaya/evidence/json_types.py +20 -0
  22. package/src/ummaya/evidence/models.py +145 -0
  23. package/src/ummaya/evidence/output_payload.py +89 -0
  24. package/src/ummaya/evidence/payload_documents.py +233 -0
  25. package/src/ummaya/evidence/route_contracts.py +224 -0
  26. package/src/ummaya/evidence/route_helpers.py +150 -0
  27. package/src/ummaya/evidence/runner.py +177 -0
  28. package/src/ummaya/evidence/source_provenance.py +246 -0
  29. package/src/ummaya/evidence/source_provenance_redaction.py +176 -0
  30. package/src/ummaya/evidence/task_registry.py +264 -0
  31. package/src/ummaya/evidence/tool_layer.py +39 -0
  32. package/src/ummaya/evidence/tool_layer_models.py +151 -0
  33. package/src/ummaya/ipc/adapter_manifest_emitter.py +26 -10
  34. package/src/ummaya/ipc/document_intent_normalization.py +185 -0
  35. package/src/ummaya/ipc/frame_schema.py +52 -5
  36. package/src/ummaya/ipc/route_diagnostics.py +73 -0
  37. package/src/ummaya/ipc/stdio.py +2282 -417
  38. package/src/ummaya/llm/client.py +234 -59
  39. package/src/ummaya/llm/config.py +8 -3
  40. package/src/ummaya/llm/reasoning.py +84 -0
  41. package/src/ummaya/primitives/__init__.py +6 -2
  42. package/src/ummaya/primitives/delegation.py +1 -1
  43. package/src/ummaya/primitives/document.py +28 -0
  44. package/src/ummaya/settings.py +0 -3
  45. package/src/ummaya/tools/discovery_bridge.py +34 -2
  46. package/src/ummaya/tools/documents/__init__.py +297 -0
  47. package/src/ummaya/tools/documents/adapter_registry.py +487 -0
  48. package/src/ummaya/tools/documents/archive_container_probe.py +167 -0
  49. package/src/ummaya/tools/documents/artifact_store.py +454 -0
  50. package/src/ummaya/tools/documents/authoring.py +283 -0
  51. package/src/ummaya/tools/documents/baselines.py +114 -0
  52. package/src/ummaya/tools/documents/capability.py +331 -0
  53. package/src/ummaya/tools/documents/contracts.py +112 -0
  54. package/src/ummaya/tools/documents/conversion.py +521 -0
  55. package/src/ummaya/tools/documents/diff.py +275 -0
  56. package/src/ummaya/tools/documents/engines.py +163 -0
  57. package/src/ummaya/tools/documents/evaluation.py +291 -0
  58. package/src/ummaya/tools/documents/explicit_values.py +108 -0
  59. package/src/ummaya/tools/documents/fixtures.py +174 -0
  60. package/src/ummaya/tools/documents/format_completion_audit.py +471 -0
  61. package/src/ummaya/tools/documents/formats/__init__.py +2 -0
  62. package/src/ummaya/tools/documents/formats/archive.py +528 -0
  63. package/src/ummaya/tools/documents/formats/base.py +41 -0
  64. package/src/ummaya/tools/documents/formats/code_file.py +211 -0
  65. package/src/ummaya/tools/documents/formats/data_file.py +272 -0
  66. package/src/ummaya/tools/documents/formats/hwp.py +284 -0
  67. package/src/ummaya/tools/documents/formats/hwpx.py +1837 -0
  68. package/src/ummaya/tools/documents/formats/odf.py +435 -0
  69. package/src/ummaya/tools/documents/formats/ooxml.py +1030 -0
  70. package/src/ummaya/tools/documents/formats/passive.py +766 -0
  71. package/src/ummaya/tools/documents/formats/pdf.py +702 -0
  72. package/src/ummaya/tools/documents/formats/text_web.py +268 -0
  73. package/src/ummaya/tools/documents/hwp_conversion_probe.py +178 -0
  74. package/src/ummaya/tools/documents/hwp_direct_candidate.py +141 -0
  75. package/src/ummaya/tools/documents/inspection.py +289 -0
  76. package/src/ummaya/tools/documents/intake.py +1079 -0
  77. package/src/ummaya/tools/documents/legacy_office_promotion_probe.py +366 -0
  78. package/src/ummaya/tools/documents/models.py +1598 -0
  79. package/src/ummaya/tools/documents/odf_promotion_probe.py +167 -0
  80. package/src/ummaya/tools/documents/orchestrator.py +96 -0
  81. package/src/ummaya/tools/documents/passive_capability_probe.py +251 -0
  82. package/src/ummaya/tools/documents/patch.py +170 -0
  83. package/src/ummaya/tools/documents/pdfa_conformance.py +284 -0
  84. package/src/ummaya/tools/documents/pdfa_promotion_probe.py +198 -0
  85. package/src/ummaya/tools/documents/permissions.py +110 -0
  86. package/src/ummaya/tools/documents/planner.py +616 -0
  87. package/src/ummaya/tools/documents/registry.py +2733 -0
  88. package/src/ummaya/tools/documents/render.py +978 -0
  89. package/src/ummaya/tools/documents/render_comparison.py +113 -0
  90. package/src/ummaya/tools/documents/render_comparison_models.py +74 -0
  91. package/src/ummaya/tools/documents/render_comparison_regions.py +73 -0
  92. package/src/ummaya/tools/documents/render_comparison_style.py +161 -0
  93. package/src/ummaya/tools/documents/reread.py +157 -0
  94. package/src/ummaya/tools/documents/runtime_authoring.py +244 -0
  95. package/src/ummaya/tools/documents/runtime_authoring_bundle.py +76 -0
  96. package/src/ummaya/tools/documents/scorecard.py +184 -0
  97. package/src/ummaya/tools/documents/socratic_planner.py +193 -0
  98. package/src/ummaya/tools/documents/style.py +48 -0
  99. package/src/ummaya/tools/documents/tool_defs.py +523 -0
  100. package/src/ummaya/tools/documents/validate.py +347 -0
  101. package/src/ummaya/tools/executor.py +61 -12
  102. package/src/ummaya/tools/geocoding/kakao_client.py +1 -2
  103. package/src/ummaya/tools/kma/apihub_catalog.py +984 -1
  104. package/src/ummaya/tools/kma/apihub_structured_adapter.py +86 -6
  105. package/src/ummaya/tools/kma/apihub_url_adapter.py +593 -0
  106. package/src/ummaya/tools/kma/apihub_url_catalog.py +296 -0
  107. package/src/ummaya/tools/live_proxy.py +0 -3
  108. package/src/ummaya/tools/location_adapters.py +8 -6
  109. package/src/ummaya/tools/manifest_metadata.py +16 -3
  110. package/src/ummaya/tools/models.py +5 -1
  111. package/src/ummaya/tools/mvp_surface.py +2 -2
  112. package/src/ummaya/tools/nmc/emergency_search.py +8 -6
  113. package/src/ummaya/tools/register_all.py +17 -0
  114. package/src/ummaya/tools/registry.py +10 -1
  115. package/src/ummaya/tools/resolve_location.py +4 -4
  116. package/src/ummaya/tools/routing/__init__.py +59 -0
  117. package/src/ummaya/tools/routing/builder.py +105 -0
  118. package/src/ummaya/tools/routing/cards.py +29 -0
  119. package/src/ummaya/tools/routing/decision_service.py +534 -0
  120. package/src/ummaya/tools/routing/decision_types.py +74 -0
  121. package/src/ummaya/tools/routing/feasibility.py +122 -0
  122. package/src/ummaya/tools/routing/intent.py +17 -0
  123. package/src/ummaya/tools/routing/intent_extractor.py +207 -0
  124. package/src/ummaya/tools/routing/intent_patterns.py +160 -0
  125. package/src/ummaya/tools/routing/intent_public_data.py +150 -0
  126. package/src/ummaya/tools/routing/intent_types.py +48 -0
  127. package/src/ummaya/tools/routing/lint.py +78 -0
  128. package/src/ummaya/tools/routing/metadata.py +174 -0
  129. package/src/ummaya/tools/routing/projection.py +340 -0
  130. package/src/ummaya/tools/routing/retrieval_policy.py +629 -0
  131. package/src/ummaya/tools/routing/schema.py +81 -0
  132. package/src/ummaya/tools/routing/types.py +96 -0
  133. package/src/ummaya/tools/routing_index.py +2 -2
  134. package/src/ummaya/tools/search.py +40 -106
  135. package/src/ummaya/tools/verified_data_go_kr/_manifest.py +115 -25
  136. package/src/ummaya/tools/verified_data_go_kr/airkorea_air_quality.py +109 -4
  137. package/src/ummaya/tools/verified_data_go_kr/nmc_aed_site.py +108 -2
  138. package/src/ummaya/tools/verified_data_go_kr/pps_bid_public_info.py +174 -9
  139. package/src/ummaya/tools/verified_data_go_kr/tago_bus_arrival.py +66 -3
  140. package/src/ummaya/tools/verified_data_go_kr/tago_bus_location.py +12 -2
  141. package/src/ummaya/tools/verified_data_go_kr/tago_bus_route.py +8 -2
  142. package/src/ummaya/tools/verified_data_go_kr/tago_bus_route_station.py +114 -0
  143. package/src/ummaya/tools/verified_data_go_kr/tago_bus_station.py +14 -3
  144. package/src/ummaya/tools/verify_canonical_map.py +21 -0
  145. package/tests/fixtures/documents/public_forms/baselines.yaml +113 -0
  146. package/tui/package.json +1 -2
  147. package/tui/src/.cc-byte-identical-whitelist.yaml +266 -0
  148. package/tui/src/QueryEngine.ts +12 -4
  149. package/tui/src/bridge/inboundAttachments.ts +3 -3
  150. package/tui/src/cli/handlers/auth.ts +4 -13
  151. package/tui/src/cli/handlers/mcp.tsx +3 -3
  152. package/tui/src/cli/print.ts +69 -18
  153. package/tui/src/cli/update.ts +13 -13
  154. package/tui/src/commands/copy/index.ts +1 -1
  155. package/tui/src/commands/cost/cost.ts +2 -2
  156. package/tui/src/commands/init-verifiers.ts +5 -5
  157. package/tui/src/commands/init.ts +30 -30
  158. package/tui/src/commands/insights.ts +44 -44
  159. package/tui/src/commands/install-github-app/install-github-app.tsx +2 -2
  160. package/tui/src/commands/install-github-app/setupGitHubActions.ts +3 -3
  161. package/tui/src/commands/install-github-app/types.ts +8 -30
  162. package/tui/src/commands/install.tsx +5 -5
  163. package/tui/src/commands/mcp/addCommand.ts +5 -5
  164. package/tui/src/commands/mcp/xaaIdpCommand.ts +2 -2
  165. package/tui/src/commands/plugin/ManageMarketplaces.tsx +2 -2
  166. package/tui/src/commands/plugin/types.ts +6 -28
  167. package/tui/src/commands/plugin/unifiedTypes.ts +4 -26
  168. package/tui/src/commands/reasoning/index.ts +13 -0
  169. package/tui/src/commands/reasoning/reasoning.tsx +177 -0
  170. package/tui/src/commands/rename/generateSessionName.ts +1 -1
  171. package/tui/src/commands/thinkback/thinkback.tsx +3 -3
  172. package/tui/src/commands.ts +2 -0
  173. package/tui/src/components/Feedback.tsx +1 -1
  174. package/tui/src/components/LogoV2/EmergencyTip.tsx +11 -2
  175. package/tui/src/components/LogoV2/WelcomeV2.tsx +1 -3
  176. package/tui/src/components/Messages.tsx +2 -1
  177. package/tui/src/components/ScrollKeybindingHandler.tsx +6 -6
  178. package/tui/src/components/Spinner/types.ts +6 -28
  179. package/tui/src/components/Spinner.tsx +2 -2
  180. package/tui/src/components/agents/generateAgent.ts +1 -1
  181. package/tui/src/components/agents/new-agent-creation/types.ts +4 -26
  182. package/tui/src/components/config/EnvSecretIsolatedEditor.tsx +1 -1
  183. package/tui/src/components/design-system/LoadingState.tsx +2 -2
  184. package/tui/src/components/mcp/types.ts +16 -38
  185. package/tui/src/components/messages/AssistantToolUseMessage.tsx +3 -2
  186. package/tui/src/components/messages/UserCrossSessionMessage.ts +16 -4
  187. package/tui/src/components/messages/UserForkBoilerplateMessage.ts +16 -4
  188. package/tui/src/components/messages/UserGitHubWebhookMessage.ts +16 -4
  189. package/tui/src/components/messages/UserToolResultMessage/utils.tsx +3 -2
  190. package/tui/src/components/permissions/MonitorPermissionRequest/MonitorPermissionRequest.ts +9 -4
  191. package/tui/src/components/permissions/ReviewArtifactPermissionRequest/ReviewArtifactPermissionRequest.ts +9 -4
  192. package/tui/src/components/primitive/DocumentSocraticReviewBlock.tsx +129 -0
  193. package/tui/src/components/primitive/DocumentToolResultCard.tsx +224 -0
  194. package/tui/src/components/primitive/documentSocraticReview.ts +215 -0
  195. package/tui/src/components/primitive/index.tsx +43 -1
  196. package/tui/src/components/primitive/types.ts +137 -0
  197. package/tui/src/components/ui/option.ts +4 -26
  198. package/tui/src/constants/common.ts +0 -2
  199. package/tui/src/constants/prompts.ts +4 -3
  200. package/tui/src/constants/querySource.ts +4 -26
  201. package/tui/src/entrypoints/sdk/controlTypes.ts +26 -48
  202. package/tui/src/entrypoints/sdk/coreTypes.generated.ts +3 -25
  203. package/tui/src/entrypoints/sdk/runtimeTypes.ts +38 -60
  204. package/tui/src/entrypoints/sdk/sdkUtilityTypes.ts +4 -26
  205. package/tui/src/entrypoints/sdk/settingsTypes.generated.ts +3 -25
  206. package/tui/src/entrypoints/sdk/toolTypes.ts +3 -25
  207. package/tui/src/hooks/toolPermission/handlers/interactiveHandler.ts +10 -0
  208. package/tui/src/hooks/useApiKeyVerification.ts +1 -1
  209. package/tui/src/hooks/useVirtualScroll.ts +1 -1
  210. package/tui/src/ink/ink.tsx +33 -14
  211. package/tui/src/ink/reconciler.ts +2 -3
  212. package/tui/src/ink/render-to-screen.ts +30 -10
  213. package/tui/src/ipc/bridge.ts +62 -15
  214. package/tui/src/ipc/bridgeSingleton.ts +5 -1
  215. package/tui/src/ipc/codec.ts +29 -3
  216. package/tui/src/ipc/frames.generated.ts +407 -312
  217. package/tui/src/ipc/llmClient.ts +279 -76
  218. package/tui/src/ipc/llmTypes.ts +16 -1
  219. package/tui/src/ipc/schema/frame.schema.json +1 -3475
  220. package/tui/src/keybindings/defaultBindings.ts +4 -0
  221. package/tui/src/main.tsx +32 -11
  222. package/tui/src/native-ts/file-index/index.ts +33 -3
  223. package/tui/src/observability/surface.ts +2 -2
  224. package/tui/src/probes/toolRegistryProbe.tsx +3 -1
  225. package/tui/src/projectOnboardingState.ts +7 -6
  226. package/tui/src/query/chatMessageTypes.ts +18 -0
  227. package/tui/src/query/chatMessagesBuilder.ts +1 -1
  228. package/tui/src/query/deps.ts +1 -1
  229. package/tui/src/query/messageGuards.ts +106 -0
  230. package/tui/src/query/publicDataTerminalRepair.ts +384 -0
  231. package/tui/src/query/run.ts +1075 -0
  232. package/tui/src/query/supportBoundary.ts +168 -0
  233. package/tui/src/query/toolResultErrors.ts +103 -0
  234. package/tui/src/query/toolRunner.ts +687 -0
  235. package/tui/src/query/unavailableToolRepair.ts +118 -0
  236. package/tui/src/query.ts +9 -1721
  237. package/tui/src/screens/REPL.tsx +42 -31
  238. package/tui/src/services/api/adapterManifest.ts +4 -0
  239. package/tui/src/services/api/backendChat/events.ts +117 -0
  240. package/tui/src/services/api/backendChat/finalMessage.ts +40 -0
  241. package/tui/src/services/api/backendChat/frame.ts +9 -0
  242. package/tui/src/services/api/backendChat/streaming.ts +430 -0
  243. package/tui/src/services/api/backendChat/types.ts +62 -0
  244. package/tui/src/services/api/backendChat.ts +1 -0
  245. package/tui/src/services/api/client.ts +98 -14
  246. package/tui/src/services/api/errorUtils.ts +5 -5
  247. package/tui/src/services/api/errors.ts +1 -1
  248. package/tui/src/services/api/logging.ts +1 -1
  249. package/tui/src/services/api/ummaya/evidence.ts +194 -0
  250. package/tui/src/services/api/ummaya/messages.ts +255 -0
  251. package/tui/src/services/api/ummaya/nonStreaming.ts +66 -0
  252. package/tui/src/services/api/ummaya/provider.ts +200 -0
  253. package/tui/src/services/api/ummaya/reasoning.ts +24 -0
  254. package/tui/src/services/api/ummaya/request.ts +200 -0
  255. package/tui/src/services/api/ummaya/selectionContext.ts +240 -0
  256. package/tui/src/services/api/ummaya/streaming.ts +365 -0
  257. package/tui/src/services/api/ummaya/streamingPayload.ts +129 -0
  258. package/tui/src/services/api/ummaya/streamingReader.ts +40 -0
  259. package/tui/src/services/api/ummaya/toolSelection.ts +217 -0
  260. package/tui/src/services/api/ummaya/types.ts +110 -0
  261. package/tui/src/services/api/ummaya/usage.ts +30 -0
  262. package/tui/src/services/api/ummaya.ts +26 -364
  263. package/tui/src/services/api/withRetry.ts +1 -1
  264. package/tui/src/services/awaySummary.ts +2 -2
  265. package/tui/src/services/claudeAiLimits.ts +1 -1
  266. package/tui/src/services/compact/autoCompact.ts +1 -1
  267. package/tui/src/services/compact/compact.ts +1 -1
  268. package/tui/src/services/lsp/types.ts +8 -30
  269. package/tui/src/services/tips/types.ts +6 -28
  270. package/tui/src/services/tokenEstimation.ts +1 -1
  271. package/tui/src/services/toolRegistry/bootGuard.ts +5 -5
  272. package/tui/src/services/toolUseSummary/toolUseSummaryGenerator.ts +1 -1
  273. package/tui/src/services/tools/toolExecution.ts +94 -1
  274. package/tui/src/skills/bundled/stuck.ts +12 -12
  275. package/tui/src/state/AppStateStore.ts +7 -0
  276. package/tui/src/store/pendingPermissionSlot.ts +1 -1
  277. package/tui/src/store/session-store.ts +10 -36
  278. package/tui/src/stubs/any-stub.ts +15 -10
  279. package/tui/src/stubs/color-diff-napi.ts +37 -23
  280. package/tui/src/stubs/globals.d.ts +3 -3
  281. package/tui/src/stubs/macro-preload.ts +23 -12
  282. package/tui/src/tools/AdapterTool/AdapterTool.ts +1239 -163
  283. package/tui/src/tools/AdapterTool/routeDiagnostics.ts +75 -0
  284. package/tui/src/tools/AgentTool/AgentTool.tsx +84 -1371
  285. package/tui/src/tools/AgentTool/agentToolHandoff.ts +114 -0
  286. package/tui/src/tools/AgentTool/agentToolPartialResult.ts +16 -0
  287. package/tui/src/tools/AgentTool/agentToolProgress.ts +32 -0
  288. package/tui/src/tools/AgentTool/agentToolResolver.ts +161 -0
  289. package/tui/src/tools/AgentTool/agentToolResult.ts +163 -0
  290. package/tui/src/tools/AgentTool/agentToolUtils.ts +14 -686
  291. package/tui/src/tools/AgentTool/asyncAgentLifecycle.ts +208 -0
  292. package/tui/src/tools/AgentTool/asyncLifecycle.ts +153 -0
  293. package/tui/src/tools/AgentTool/backgroundedCompletion.ts +126 -0
  294. package/tui/src/tools/AgentTool/backgroundedLifecycle.ts +174 -0
  295. package/tui/src/tools/AgentTool/foregroundBackground.ts +83 -0
  296. package/tui/src/tools/AgentTool/foregroundDrain.tsx +133 -0
  297. package/tui/src/tools/AgentTool/foregroundFinalize.ts +98 -0
  298. package/tui/src/tools/AgentTool/foregroundLifecycle.tsx +237 -0
  299. package/tui/src/tools/AgentTool/foregroundProgress.tsx +169 -0
  300. package/tui/src/tools/AgentTool/foregroundTask.ts +89 -0
  301. package/tui/src/tools/AgentTool/forkSubagent.ts +1 -12
  302. package/tui/src/tools/AgentTool/forkSubagentGate.ts +34 -0
  303. package/tui/src/tools/AgentTool/launchRouting.ts +203 -0
  304. package/tui/src/tools/AgentTool/lifecycle.ts +244 -0
  305. package/tui/src/tools/AgentTool/mcpRouting.ts +73 -0
  306. package/tui/src/tools/AgentTool/orchestrationSupport.ts +70 -0
  307. package/tui/src/tools/AgentTool/permissions.ts +39 -0
  308. package/tui/src/tools/AgentTool/promptSetup.ts +181 -0
  309. package/tui/src/tools/AgentTool/remoteRouting.ts +62 -0
  310. package/tui/src/tools/AgentTool/resultMapping.ts +116 -0
  311. package/tui/src/tools/AgentTool/resumeAgent.ts +39 -107
  312. package/tui/src/tools/AgentTool/resumeAgentHelpers.ts +140 -0
  313. package/tui/src/tools/AgentTool/runAgent.ts +1 -1
  314. package/tui/src/tools/AgentTool/runtimeConfig.ts +57 -0
  315. package/tui/src/tools/AgentTool/schemas.ts +196 -0
  316. package/tui/src/tools/AgentTool/sourceVerificationPropagation.ts +263 -0
  317. package/tui/src/tools/AgentTool/worktreeLifecycle.ts +105 -0
  318. package/tui/src/tools/AskUserQuestionTool/AskUserQuestionTool.tsx +174 -202
  319. package/tui/src/tools/BashTool/BashTool.tsx +71 -1072
  320. package/tui/src/tools/BashTool/bashCommandHelpers.ts +12 -12
  321. package/tui/src/tools/BashTool/bashPermissions/astPreflight.ts +173 -0
  322. package/tui/src/tools/BashTool/bashPermissions/classifierChecks.ts +199 -0
  323. package/tui/src/tools/BashTool/bashPermissions/compoundGuards.ts +53 -0
  324. package/tui/src/tools/BashTool/bashPermissions/constants.ts +99 -0
  325. package/tui/src/tools/BashTool/bashPermissions/index.ts +38 -0
  326. package/tui/src/tools/BashTool/bashPermissions/legacyMisparsing.ts +62 -0
  327. package/tui/src/tools/BashTool/bashPermissions/main.ts +135 -0
  328. package/tui/src/tools/BashTool/bashPermissions/normalizedCommands.ts +33 -0
  329. package/tui/src/tools/BashTool/bashPermissions/operatorFlow.ts +98 -0
  330. package/tui/src/tools/BashTool/bashPermissions/permissionChecks.ts +200 -0
  331. package/tui/src/tools/BashTool/bashPermissions/prefixSuggestions.ts +88 -0
  332. package/tui/src/tools/BashTool/bashPermissions/promptClassifierRules.ts +125 -0
  333. package/tui/src/tools/BashTool/bashPermissions/ruleDelegates.ts +19 -0
  334. package/tui/src/tools/BashTool/bashPermissions/ruleMatching.ts +145 -0
  335. package/tui/src/tools/BashTool/bashPermissions/sandboxAutoAllow.ts +75 -0
  336. package/tui/src/tools/BashTool/bashPermissions/subcommandFlow.ts +205 -0
  337. package/tui/src/tools/BashTool/bashPermissions/subcommandGuards.ts +73 -0
  338. package/tui/src/tools/BashTool/bashPermissions/subcommandResultHelpers.ts +116 -0
  339. package/tui/src/tools/BashTool/bashPermissions/types.ts +26 -0
  340. package/tui/src/tools/BashTool/bashPermissions/wrapperStripping.ts +139 -0
  341. package/tui/src/tools/BashTool/bashPermissions.ts +26 -2621
  342. package/tui/src/tools/BashTool/call.ts +202 -0
  343. package/tui/src/tools/BashTool/callLoader.ts +35 -0
  344. package/tui/src/tools/BashTool/commandClassification.ts +151 -0
  345. package/tui/src/tools/BashTool/commandClassificationLoader.ts +40 -0
  346. package/tui/src/tools/BashTool/cwdReset.ts +33 -0
  347. package/tui/src/tools/BashTool/lineTruncation.ts +11 -0
  348. package/tui/src/tools/BashTool/modeValidation.ts +13 -1
  349. package/tui/src/tools/BashTool/outputPersistence.ts +42 -0
  350. package/tui/src/tools/BashTool/permissionClassification.ts +66 -0
  351. package/tui/src/tools/BashTool/permissionLoader.ts +44 -0
  352. package/tui/src/tools/BashTool/resultLoader.ts +29 -0
  353. package/tui/src/tools/BashTool/resultMapping.ts +83 -0
  354. package/tui/src/tools/BashTool/sandboxPolicy.ts +79 -0
  355. package/tui/src/tools/BashTool/schemas.ts +65 -0
  356. package/tui/src/tools/BashTool/sedEditExecution.ts +59 -0
  357. package/tui/src/tools/BashTool/shellExecution.tsx +245 -0
  358. package/tui/src/tools/BashTool/shellOutputUtils.ts +85 -0
  359. package/tui/src/tools/BashTool/shellPermissionGauntlet.ts +97 -0
  360. package/tui/src/tools/BashTool/uiLoader.ts +37 -0
  361. package/tui/src/tools/BriefTool/upload.ts +1 -1
  362. package/tui/src/tools/CalculatorTool/parser.ts +2 -2
  363. package/tui/src/tools/DocumentPrimitive/DocumentPrimitive.ts +262 -0
  364. package/tui/src/tools/DocumentPrimitive/dispatchNormalization.ts +270 -0
  365. package/tui/src/tools/DocumentPrimitive/documentDestinationPath.ts +18 -0
  366. package/tui/src/tools/DocumentPrimitive/documentMutationGuard.ts +22 -0
  367. package/tui/src/tools/DocumentPrimitive/documentPatchNormalization.ts +248 -0
  368. package/tui/src/tools/DocumentPrimitive/documentSourceVerification.ts +245 -0
  369. package/tui/src/tools/DocumentPrimitive/documentSourceVerificationFields.ts +103 -0
  370. package/tui/src/tools/DocumentPrimitive/modelVisibleOutput.ts +40 -0
  371. package/tui/src/tools/DocumentPrimitive/prompt.ts +35 -0
  372. package/tui/src/tools/FileEditTool/FileEditTool.ts +9 -507
  373. package/tui/src/tools/FileEditTool/call.ts +228 -0
  374. package/tui/src/tools/FileEditTool/validateInput.ts +196 -0
  375. package/tui/src/tools/FileReadTool/imageProcessor.ts +13 -0
  376. package/tui/src/tools/FileWriteTool/FileWriteTool.ts +7 -300
  377. package/tui/src/tools/FileWriteTool/call.ts +223 -0
  378. package/tui/src/tools/FileWriteTool/validateInput.ts +80 -0
  379. package/tui/src/tools/ListMcpResourcesTool/ListMcpResourcesTool.ts +19 -3
  380. package/tui/src/tools/LookupPrimitive/LookupPrimitive.ts +48 -29
  381. package/tui/src/tools/LookupPrimitive/prompt.ts +6 -7
  382. package/tui/src/tools/MCPTool/trustPolicy.ts +118 -0
  383. package/tui/src/tools/McpAuthTool/McpAuthTool.ts +21 -3
  384. package/tui/src/tools/NotebookEditTool/NotebookEditTool.ts +7 -326
  385. package/tui/src/tools/NotebookEditTool/call.ts +254 -0
  386. package/tui/src/tools/NotebookEditTool/notebookModel.ts +51 -0
  387. package/tui/src/tools/NotebookEditTool/validateInput.ts +142 -0
  388. package/tui/src/tools/PowerShellTool/PowerShellTool.tsx +46 -937
  389. package/tui/src/tools/PowerShellTool/acceptEditsCommandValidation.ts +162 -0
  390. package/tui/src/tools/PowerShellTool/call.ts +179 -0
  391. package/tui/src/tools/PowerShellTool/callLoader.ts +37 -0
  392. package/tui/src/tools/PowerShellTool/commandClassification.ts +86 -0
  393. package/tui/src/tools/PowerShellTool/modeValidation.ts +25 -332
  394. package/tui/src/tools/PowerShellTool/outputPersistence.ts +42 -0
  395. package/tui/src/tools/PowerShellTool/permissionClassification.ts +28 -0
  396. package/tui/src/tools/PowerShellTool/resultLoader.ts +31 -0
  397. package/tui/src/tools/PowerShellTool/resultMapping.ts +75 -0
  398. package/tui/src/tools/PowerShellTool/schemas.ts +40 -0
  399. package/tui/src/tools/PowerShellTool/shellExecution.tsx +258 -0
  400. package/tui/src/tools/PowerShellTool/symlinkModeValidation.ts +44 -0
  401. package/tui/src/tools/PowerShellTool/uiLoader.ts +37 -0
  402. package/tui/src/tools/PowerShellTool/validation.ts +39 -0
  403. package/tui/src/tools/ReadMcpResourceTool/ReadMcpResourceTool.ts +19 -3
  404. package/tui/src/tools/ResolveLocationPrimitive/ResolveLocationPrimitive.ts +30 -19
  405. package/tui/src/tools/ResolveLocationPrimitive/prompt.ts +2 -6
  406. package/tui/src/tools/SkillTool/SkillTool.ts +2 -2
  407. package/tui/src/tools/SubmitPrimitive/SubmitPrimitive.ts +51 -18
  408. package/tui/src/tools/TaskCreateTool/TaskCreateTool.ts +16 -2
  409. package/tui/src/tools/TaskGetTool/TaskGetTool.ts +23 -3
  410. package/tui/src/tools/TaskListTool/TaskListTool.ts +22 -4
  411. package/tui/src/tools/TaskOutputTool/TaskOutputTool.tsx +46 -547
  412. package/tui/src/tools/TaskOutputTool/lookup.ts +216 -0
  413. package/tui/src/tools/TaskOutputTool/render.tsx +257 -0
  414. package/tui/src/tools/TaskOutputTool/schemas.ts +55 -0
  415. package/tui/src/tools/TaskOutputTool/serialization.ts +36 -0
  416. package/tui/src/tools/TaskStopTool/TaskStopTool.ts +10 -0
  417. package/tui/src/tools/TaskUpdateTool/TaskUpdateTool.ts +14 -364
  418. package/tui/src/tools/TaskUpdateTool/completion.ts +62 -0
  419. package/tui/src/tools/TaskUpdateTool/schemas.ts +62 -0
  420. package/tui/src/tools/TaskUpdateTool/serialization.ts +46 -0
  421. package/tui/src/tools/TaskUpdateTool/statusUpdate.ts +247 -0
  422. package/tui/src/tools/TodoWriteTool/TodoWriteTool.ts +21 -2
  423. package/tui/src/tools/ToolSearchTool/ToolSearchTool.ts +21 -302
  424. package/tui/src/tools/ToolSearchTool/ccSupportTools.ts +223 -0
  425. package/tui/src/tools/ToolSearchTool/descriptionCache.ts +50 -0
  426. package/tui/src/tools/ToolSearchTool/keywordSearch.ts +216 -0
  427. package/tui/src/tools/ToolSearchTool/prompt.ts +10 -4
  428. package/tui/src/tools/ToolSearchTool/resultMapping.ts +30 -0
  429. package/tui/src/tools/ToolSearchTool/schemas.ts +30 -0
  430. package/tui/src/tools/ToolSearchTool/searchPool.ts +47 -0
  431. package/tui/src/tools/ToolSearchTool/supportIntentHints.ts +140 -0
  432. package/tui/src/tools/TranslateTool/TranslateTool.ts +1 -1
  433. package/tui/src/tools/VerifyPrimitive/VerifyPrimitive.ts +27 -10
  434. package/tui/src/tools/WebFetchTool/WebFetchTool.ts +43 -138
  435. package/tui/src/tools/WebFetchTool/call.ts +227 -0
  436. package/tui/src/tools/WebFetchTool/resolvedAddressSafety.ts +78 -0
  437. package/tui/src/tools/WebFetchTool/sourceVerification.ts +204 -0
  438. package/tui/src/tools/WebFetchTool/types.ts +23 -0
  439. package/tui/src/tools/WebFetchTool/urlSafety.ts +181 -0
  440. package/tui/src/tools/WebFetchTool/utils.ts +1 -1
  441. package/tui/src/tools/WebSearchTool/UI.tsx +0 -1
  442. package/tui/src/tools/WebSearchTool/WebSearchTool.ts +9 -313
  443. package/tui/src/tools/WebSearchTool/call.ts +33 -0
  444. package/tui/src/tools/WebSearchTool/responseMapping.ts +190 -0
  445. package/tui/src/tools/WebSearchTool/resultBlock.ts +47 -0
  446. package/tui/src/tools/WebSearchTool/schemas.ts +47 -0
  447. package/tui/src/tools/WebSearchTool/toolSchema.ts +12 -0
  448. package/tui/src/tools/WorkspaceToolAdapter/WorkspaceToolAdapter.ts +79 -0
  449. package/tui/src/tools/WorkspaceToolAdapter/allowedRootPolicy.ts +85 -0
  450. package/tui/src/tools/WorkspaceToolAdapter/documentFormatGuards.ts +73 -0
  451. package/tui/src/tools/WorkspaceToolAdapter/inputNormalization.ts +105 -0
  452. package/tui/src/tools/WorkspaceToolAdapter/mcpExposurePolicy.ts +64 -0
  453. package/tui/src/tools/WorkspaceToolAdapter/toolDefFactory.ts +215 -0
  454. package/tui/src/tools/WorkspaceToolAdapter/toolNames.ts +6 -0
  455. package/tui/src/tools/WorkspaceToolAdapter/workspacePolicy.ts +15 -0
  456. package/tui/src/tools/_shared/citizenUserText.ts +49 -0
  457. package/tui/src/tools/_shared/dispatchPrimitive.ts +6 -6
  458. package/tui/src/tools/_shared/documentChangeToPatch.ts +125 -0
  459. package/tui/src/tools/_shared/documentDispatchArguments.ts +87 -0
  460. package/tui/src/tools/_shared/documentPrimitiveTimeout.ts +13 -0
  461. package/tui/src/tools/_shared/documentToolResultRender.ts +98 -0
  462. package/tui/src/tools/_shared/locationInputRepair.ts +112 -0
  463. package/tui/src/tools/_shared/pendingCallRegistry.ts +1 -6
  464. package/tui/src/tools/_shared/rootPrimitiveInput.ts +68 -0
  465. package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPatterns.ts +58 -0
  466. package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPrompt.ts +271 -0
  467. package/tui/src/tools/_shared/toolChoiceRepair/documentRepair.ts +452 -0
  468. package/tui/src/tools/_shared/toolChoiceRepair/messageAccess.ts +80 -0
  469. package/tui/src/tools/_shared/toolChoiceRepair/publicDataRepair.ts +92 -0
  470. package/tui/src/tools/_shared/toolChoiceRepair/supportRepair.ts +135 -0
  471. package/tui/src/tools/_shared/toolChoiceRepair.ts +61 -0
  472. package/tui/src/tools/shared/mockDisclaimer.ts +1 -1
  473. package/tui/src/tools.ts +39 -190
  474. package/tui/src/types/fileSuggestion.ts +4 -26
  475. package/tui/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +186 -148
  476. package/tui/src/types/generated/events_mono/common/v1/auth.ts +25 -11
  477. package/tui/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +47 -30
  478. package/tui/src/types/generated/google/protobuf/timestamp.ts +21 -7
  479. package/tui/src/types/message.ts +80 -102
  480. package/tui/src/types/messageQueueTypes.ts +6 -28
  481. package/tui/src/types/notebook.ts +16 -38
  482. package/tui/src/types/statusLine.ts +4 -26
  483. package/tui/src/types/tools.ts +24 -46
  484. package/tui/src/types/utils.ts +6 -28
  485. package/tui/src/upstreamproxy/relay.ts +7 -3
  486. package/tui/src/upstreamproxy/upstreamproxy.ts +1 -1
  487. package/tui/src/utils/assistantMessageFactories.ts +9 -3
  488. package/tui/src/utils/attachments.ts +1 -1
  489. package/tui/src/utils/auth.ts +129 -139
  490. package/tui/src/utils/bash/ast.ts +23 -23
  491. package/tui/src/utils/bash/bashParser.ts +5 -5
  492. package/tui/src/utils/billing.ts +1 -1
  493. package/tui/src/utils/collapseReadSearch.ts +3 -3
  494. package/tui/src/utils/cronTasks.ts +1 -1
  495. package/tui/src/utils/execFileNoThrow.ts +1 -1
  496. package/tui/src/utils/filePersistence/types.ts +16 -38
  497. package/tui/src/utils/forkedAgent.ts +1 -1
  498. package/tui/src/utils/gracefulShutdown.ts +4 -4
  499. package/tui/src/utils/heapDumpService.ts +12 -8
  500. package/tui/src/utils/hooks/apiQueryHookHelper.ts +1 -1
  501. package/tui/src/utils/hooks/execPromptHook.ts +1 -1
  502. package/tui/src/utils/hooks/skillImprovement.ts +1 -1
  503. package/tui/src/utils/kExaoneReasoning.ts +138 -0
  504. package/tui/src/utils/mcp/dateTimeParser.ts +1 -1
  505. package/tui/src/utils/messages.ts +19 -0
  506. package/tui/src/utils/migrateSessions.ts +3 -3
  507. package/tui/src/utils/model/model.ts +6 -6
  508. package/tui/src/utils/multiToolLayout.ts +13 -0
  509. package/tui/src/utils/permissions/yoloClassifier.ts +1 -1
  510. package/tui/src/utils/plugins/headlessPluginInstall.ts +1 -1
  511. package/tui/src/utils/plugins/mcpPluginIntegration.ts +1 -1
  512. package/tui/src/utils/plugins/mcpbHandler.ts +1 -1
  513. package/tui/src/utils/plugins/pluginLoader.ts +8 -8
  514. package/tui/src/utils/processUserInput/processSlashCommand.tsx +2 -2
  515. package/tui/src/utils/processUserInput/processUserInput.ts +26 -0
  516. package/tui/src/utils/protectedNamespace.ts +5 -3
  517. package/tui/src/utils/rawJsonToolCall.ts +242 -0
  518. package/tui/src/utils/ripgrep.ts +16 -7
  519. package/tui/src/utils/sessionTitle.ts +1 -1
  520. package/tui/src/utils/settings/applySettingsChange.ts +4 -0
  521. package/tui/src/utils/settings/permissionValidation.ts +14 -2
  522. package/tui/src/utils/settings/types.ts +9 -3
  523. package/tui/src/utils/shell/prefix.ts +1 -1
  524. package/tui/src/utils/sideQuery.ts +1 -1
  525. package/tui/src/utils/stats.ts +1 -1
  526. package/tui/src/utils/systemThemeWatcher.ts +13 -3
  527. package/tui/src/utils/teleport.tsx +1 -1
  528. package/uv.lock +394 -22
  529. package/assets/copilot-gate-logo.svg +0 -58
  530. package/assets/govon-logo.svg +0 -40
  531. package/src/ummaya/eval/__init__.py +0 -5
  532. package/src/ummaya/eval/retrieval.py +0 -713
  533. package/tui/src/services/api/claude.ts +0 -3510
  534. 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
+ ]