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,167 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """Local ODF promotion diagnostics.
3
+
4
+ ODF is promoted for bounded odfdo-backed write/render/save operations. This
5
+ module keeps the separate LibreOffice layout-oracle bridge visible so evidence
6
+ does not confuse structural SVG rendering with original-page fidelity.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import os
12
+ from collections.abc import Mapping, Sequence
13
+ from importlib.util import find_spec
14
+ from pathlib import Path
15
+ from shutil import which
16
+ from typing import Literal
17
+
18
+ from pydantic import BaseModel, ConfigDict, Field
19
+
20
+ from ummaya.tools.documents.adapter_registry import build_default_document_adapter_registry
21
+ from ummaya.tools.documents.models import DocumentFormat, DocumentFormatFamily, KnownDocumentFormat
22
+
23
+ ODF_WRITER_PACKAGE = "odfdo"
24
+ ODF_WRITER_CANDIDATE_ID = "odfdo-odf-package-writer"
25
+ ODF_RENDER_ORACLE_ID = "libreoffice-headless-pdf-export"
26
+ ODF_READ_ADAPTER_ID = "odfdo-document-adapter"
27
+ ODF_SOURCE_REFS = (
28
+ "upstream:oasis-open-document-v1.4",
29
+ "upstream:odfdo-v3.22.8",
30
+ "upstream:libreoffice-26.2-headless-pdf-export",
31
+ )
32
+ ODF_PROMOTION_FORMATS = (
33
+ KnownDocumentFormat.odt,
34
+ KnownDocumentFormat.ods,
35
+ KnownDocumentFormat.odp,
36
+ )
37
+
38
+ OdfPromotionProbeStatus = Literal["blocked", "promoted_bounded"]
39
+
40
+
41
+ class OdfPromotionProbeReport(BaseModel):
42
+ """Current local availability of ODF writer/render promotion candidates."""
43
+
44
+ model_config = ConfigDict(frozen=True, extra="forbid")
45
+
46
+ candidate_id: str = Field(min_length=1)
47
+ known_format: KnownDocumentFormat
48
+ family: DocumentFormatFamily
49
+ status: OdfPromotionProbeStatus
50
+ read_adapter_id: str = Field(min_length=1)
51
+ writer_package: str = Field(min_length=1)
52
+ writer_available: bool
53
+ render_oracle_id: str = Field(min_length=1)
54
+ render_oracle_available: bool
55
+ render_oracle_executable: Path | None
56
+ reasons: tuple[str, ...]
57
+ required_gates: tuple[str, ...]
58
+ evidence_refs: tuple[str, ...]
59
+
60
+
61
+ def probe_odf_promotion(
62
+ *,
63
+ env: Mapping[str, str] | None = None,
64
+ search_path: Sequence[str] | None = None,
65
+ importable_modules: frozenset[str] | None = None,
66
+ ) -> tuple[OdfPromotionProbeReport, ...]:
67
+ """Report ODF promotion readiness without mutating adapter registries."""
68
+ active_env = os.environ if env is None else env
69
+ writer_available = _is_importable(ODF_WRITER_PACKAGE, importable_modules=importable_modules)
70
+ runtime_promoted = _is_runtime_promoted()
71
+ render_oracle_executable = _find_libreoffice_cli(active_env=active_env, search_path=search_path)
72
+ render_oracle_available = render_oracle_executable is not None
73
+ status: OdfPromotionProbeStatus = (
74
+ "promoted_bounded" if writer_available and runtime_promoted else "blocked"
75
+ )
76
+ reasons = _reasons(
77
+ writer_available=writer_available,
78
+ runtime_promoted=runtime_promoted,
79
+ render_oracle_available=render_oracle_available,
80
+ )
81
+ return tuple(
82
+ OdfPromotionProbeReport(
83
+ candidate_id=ODF_WRITER_CANDIDATE_ID,
84
+ known_format=known_format,
85
+ family=DocumentFormatFamily.odf,
86
+ status=status,
87
+ read_adapter_id=ODF_READ_ADAPTER_ID,
88
+ writer_package=ODF_WRITER_PACKAGE,
89
+ writer_available=writer_available,
90
+ render_oracle_id=ODF_RENDER_ORACLE_ID,
91
+ render_oracle_available=render_oracle_available,
92
+ render_oracle_executable=render_oracle_executable,
93
+ reasons=reasons,
94
+ required_gates=(
95
+ "odf_writer_package_available",
96
+ "odf_save_reread_fixture_gate",
97
+ "odf_runtime_document_format_promotion",
98
+ "odf_structural_svg_render_gate",
99
+ "odf_layout_oracle_bridge_deferred",
100
+ ),
101
+ evidence_refs=ODF_SOURCE_REFS,
102
+ )
103
+ for known_format in ODF_PROMOTION_FORMATS
104
+ )
105
+
106
+
107
+ def _is_importable(name: str, *, importable_modules: frozenset[str] | None) -> bool:
108
+ if importable_modules is not None:
109
+ return name in importable_modules
110
+ return find_spec(name) is not None
111
+
112
+
113
+ def _is_runtime_promoted() -> bool:
114
+ registry = build_default_document_adapter_registry()
115
+ return all(
116
+ document_format in registry.require_known(known_format).promoted_formats
117
+ for known_format, document_format in (
118
+ (KnownDocumentFormat.odt, DocumentFormat.odt),
119
+ (KnownDocumentFormat.ods, DocumentFormat.ods),
120
+ (KnownDocumentFormat.odp, DocumentFormat.odp),
121
+ )
122
+ )
123
+
124
+
125
+ def _find_libreoffice_cli(
126
+ *,
127
+ active_env: Mapping[str, str],
128
+ search_path: Sequence[str] | None,
129
+ ) -> Path | None:
130
+ path_env = os.pathsep.join(search_path) if search_path is not None else active_env.get("PATH")
131
+ if not path_env:
132
+ return None
133
+ for executable_name in ("soffice", "libreoffice"):
134
+ found = which(executable_name, path=path_env)
135
+ if found is None:
136
+ continue
137
+ executable = Path(found).expanduser().resolve(strict=False)
138
+ if _is_executable_file(executable):
139
+ return executable
140
+ return None
141
+
142
+
143
+ def _is_executable_file(path: Path) -> bool:
144
+ return path.exists() and path.is_file() and os.access(path, os.X_OK)
145
+
146
+
147
+ def _reasons(
148
+ *,
149
+ writer_available: bool,
150
+ runtime_promoted: bool,
151
+ render_oracle_available: bool,
152
+ ) -> tuple[str, ...]:
153
+ reasons: list[str] = []
154
+ if runtime_promoted:
155
+ reasons.append("odf_runtime_promoted_bounded")
156
+ else:
157
+ reasons.append("odf_runtime_not_promoted")
158
+ if writer_available:
159
+ reasons.append("odfdo_package_registered")
160
+ else:
161
+ reasons.append("odfdo_package_not_found")
162
+ if render_oracle_available:
163
+ reasons.append("libreoffice_cli_found_layout_oracle_candidate")
164
+ else:
165
+ reasons.append("libreoffice_cli_not_found")
166
+ reasons.append("libreoffice_layout_oracle_deferred")
167
+ return tuple(reasons)
@@ -0,0 +1,96 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """Internal orchestration boundary for the model-facing document primitive."""
3
+
4
+ from __future__ import annotations
5
+
6
+ from pathlib import Path
7
+ from typing import Protocol
8
+
9
+ from ummaya.tools.documents.adapter_registry import (
10
+ DocumentAdapterRegistry,
11
+ build_document_adapter_registry_from_engine_registry,
12
+ )
13
+ from ummaya.tools.documents.engines import DocumentEngineRegistry
14
+ from ummaya.tools.documents.inspection import inspect_document
15
+ from ummaya.tools.documents.models import (
16
+ DocumentExtraction,
17
+ DocumentFormat,
18
+ DocumentIR,
19
+ DocumentToolResult,
20
+ )
21
+
22
+
23
+ class DocumentInspectionOrchestrator(Protocol):
24
+ """Minimal inspection boundary consumed by the document runtime."""
25
+
26
+ def inspect_local_path(
27
+ self,
28
+ source_path: Path,
29
+ *,
30
+ expected_format: DocumentFormat | None,
31
+ correlation_id: str,
32
+ ) -> DocumentToolResult:
33
+ """Inspect one local document path through adapter selection."""
34
+
35
+ def build_document_ir(
36
+ self,
37
+ *,
38
+ artifact_id: str,
39
+ document_format: DocumentFormat,
40
+ extraction: DocumentExtraction,
41
+ ) -> DocumentIR:
42
+ """Normalize inspected document content into planner-facing IR."""
43
+
44
+
45
+ class DocumentOrchestrator:
46
+ """Coordinate intake, format selection, and adapter-backed inspection."""
47
+
48
+ def __init__(
49
+ self,
50
+ *,
51
+ adapter_registry: DocumentAdapterRegistry | None = None,
52
+ engine_registry: DocumentEngineRegistry | None = None,
53
+ ) -> None:
54
+ self.engine_registry = engine_registry or DocumentEngineRegistry()
55
+ self.adapter_registry = (
56
+ adapter_registry
57
+ or build_document_adapter_registry_from_engine_registry(self.engine_registry)
58
+ )
59
+
60
+ def inspect_local_path(
61
+ self,
62
+ source_path: Path,
63
+ *,
64
+ expected_format: DocumentFormat | None,
65
+ correlation_id: str,
66
+ ) -> DocumentToolResult:
67
+ """Inspect a local source document without mutating it."""
68
+ return inspect_document(
69
+ source_path,
70
+ expected_format=expected_format,
71
+ engine_registry=self.engine_registry,
72
+ adapter_registry=self.adapter_registry,
73
+ )
74
+
75
+ def build_document_ir(
76
+ self,
77
+ *,
78
+ artifact_id: str,
79
+ document_format: DocumentFormat,
80
+ extraction: DocumentExtraction,
81
+ ) -> DocumentIR:
82
+ """Normalize inspected document content into planner-facing IR."""
83
+ return DocumentIR.from_extraction(
84
+ artifact_id=artifact_id,
85
+ document_format=document_format,
86
+ extraction=extraction,
87
+ engine_id=_engine_id_for_extraction(extraction),
88
+ )
89
+
90
+
91
+ def _engine_id_for_extraction(extraction: DocumentExtraction) -> str:
92
+ for key in ("engine_id", "adapter_id", "format_adapter_id"):
93
+ value = extraction.metadata.get(key)
94
+ if isinstance(value, str) and value:
95
+ return value
96
+ return "document-orchestrator"
@@ -0,0 +1,251 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """Local passive attachment capability diagnostics."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import os
7
+ from collections.abc import Mapping, Sequence
8
+ from importlib.util import find_spec
9
+ from pathlib import Path
10
+ from shutil import which
11
+ from typing import Literal
12
+
13
+ from pydantic import BaseModel, ConfigDict, Field
14
+
15
+ from ummaya.tools.documents.models import DocumentFormatFamily, KnownDocumentFormat
16
+
17
+ PASSIVE_CAPABILITY_CANDIDATE_ID = "passive-attachment-extraction-boundary"
18
+ PASSIVE_CAPABILITY_SOURCE_REFS = (
19
+ "upstream:tesseract-ocr-cli",
20
+ "upstream:ffmpeg-ffprobe",
21
+ "upstream:gdal-ogrinfo",
22
+ "upstream:pyshp",
23
+ "upstream:trimesh",
24
+ "upstream:owasp-file-upload-attachment-limits",
25
+ )
26
+
27
+ PassiveCapabilityProbeStatus = Literal["blocked", "candidate_available"]
28
+
29
+ _IMAGE_FORMATS = (
30
+ KnownDocumentFormat.png,
31
+ KnownDocumentFormat.jpg,
32
+ KnownDocumentFormat.jpeg,
33
+ KnownDocumentFormat.gif,
34
+ KnownDocumentFormat.tif,
35
+ KnownDocumentFormat.tiff,
36
+ KnownDocumentFormat.bmp,
37
+ KnownDocumentFormat.webp,
38
+ )
39
+ _GEOSPATIAL_FORMATS = (
40
+ KnownDocumentFormat.shp,
41
+ KnownDocumentFormat.shx,
42
+ KnownDocumentFormat.dbf,
43
+ KnownDocumentFormat.prj,
44
+ KnownDocumentFormat.stl,
45
+ )
46
+ _MEDIA_FORMATS = (
47
+ KnownDocumentFormat.wav,
48
+ KnownDocumentFormat.mp3,
49
+ KnownDocumentFormat.mp4,
50
+ )
51
+
52
+
53
+ class PassiveCapabilityProbeReport(BaseModel):
54
+ """Current local availability of passive attachment extraction candidates."""
55
+
56
+ model_config = ConfigDict(frozen=True, extra="forbid")
57
+
58
+ candidate_id: str = Field(min_length=1)
59
+ known_format: KnownDocumentFormat
60
+ family: DocumentFormatFamily
61
+ status: PassiveCapabilityProbeStatus
62
+ read_adapter_id: str = Field(min_length=1)
63
+ runtime_id: str = Field(min_length=1)
64
+ runtime_available: bool
65
+ runtime_executable: Path | None
66
+ extraction_available: bool
67
+ direct_mutation_promoted: bool
68
+ reasons: tuple[str, ...]
69
+ required_gates: tuple[str, ...]
70
+ evidence_refs: tuple[str, ...]
71
+
72
+
73
+ def probe_passive_capabilities(
74
+ *,
75
+ env: Mapping[str, str] | None = None,
76
+ search_path: Sequence[str] | None = None,
77
+ importable_modules: frozenset[str] | None = None,
78
+ ) -> tuple[PassiveCapabilityProbeReport, ...]:
79
+ """Report passive attachment readiness without promoting document writes."""
80
+ active_env = os.environ if env is None else env
81
+ tesseract = _find_executable("tesseract", active_env=active_env, search_path=search_path)
82
+ ffprobe = _find_executable("ffprobe", active_env=active_env, search_path=search_path)
83
+ geospatial_available = _geospatial_runtime_available(
84
+ active_env=active_env,
85
+ search_path=search_path,
86
+ importable_modules=importable_modules,
87
+ )
88
+ reports: list[PassiveCapabilityProbeReport] = []
89
+ reports.extend(_image_reports(tesseract=tesseract))
90
+ reports.extend(_geospatial_reports(runtime_available=geospatial_available))
91
+ reports.extend(_media_reports(ffprobe=ffprobe))
92
+ return tuple(reports)
93
+
94
+
95
+ def _image_reports(*, tesseract: Path | None) -> tuple[PassiveCapabilityProbeReport, ...]:
96
+ runtime_available = tesseract is not None
97
+ reasons = (
98
+ "image_ocr_candidate_available" if runtime_available else "tesseract_cli_not_found",
99
+ "image_document_write_not_promoted",
100
+ "no_in_place_raster_mutation",
101
+ )
102
+ return tuple(
103
+ _report(
104
+ known_format=known_format,
105
+ family=DocumentFormatFamily.image_scan,
106
+ read_adapter_id="image-scan-extraction-only-adapter",
107
+ runtime_id="tesseract-ocr-cli",
108
+ runtime_available=runtime_available,
109
+ runtime_executable=tesseract,
110
+ extraction_available=runtime_available,
111
+ reasons=reasons,
112
+ required_gates=(
113
+ "image_ocr_runtime_available",
114
+ "image_text_extraction_gate",
115
+ "document_derivative_write_gate",
116
+ "image_original_preservation_gate",
117
+ ),
118
+ )
119
+ for known_format in _IMAGE_FORMATS
120
+ )
121
+
122
+
123
+ def _geospatial_reports(
124
+ *,
125
+ runtime_available: bool,
126
+ ) -> tuple[PassiveCapabilityProbeReport, ...]:
127
+ reasons = (
128
+ "geospatial_runtime_candidate_available"
129
+ if runtime_available
130
+ else "geospatial_runtime_not_found",
131
+ "geospatial_document_write_not_promoted",
132
+ "geospatial_sidecar_lineage_required",
133
+ )
134
+ return tuple(
135
+ _report(
136
+ known_format=known_format,
137
+ family=DocumentFormatFamily.geospatial_data,
138
+ read_adapter_id="geospatial-metadata-only-adapter",
139
+ runtime_id="gdal-or-pyshp-geospatial-reader",
140
+ runtime_available=runtime_available,
141
+ runtime_executable=None,
142
+ extraction_available=runtime_available,
143
+ reasons=reasons,
144
+ required_gates=(
145
+ "geospatial_runtime_available",
146
+ "sidecar_set_integrity_gate",
147
+ "geometry_metadata_extraction_gate",
148
+ "document_derivative_write_gate",
149
+ ),
150
+ )
151
+ for known_format in _GEOSPATIAL_FORMATS
152
+ )
153
+
154
+
155
+ def _media_reports(*, ffprobe: Path | None) -> tuple[PassiveCapabilityProbeReport, ...]:
156
+ runtime_available = ffprobe is not None
157
+ reasons = (
158
+ "media_metadata_candidate_available" if runtime_available else "ffprobe_cli_not_found",
159
+ "media_transcription_not_promoted",
160
+ "media_document_write_not_promoted",
161
+ )
162
+ return tuple(
163
+ _report(
164
+ known_format=known_format,
165
+ family=DocumentFormatFamily.media_asset,
166
+ read_adapter_id="media-metadata-only-adapter",
167
+ runtime_id="ffprobe-media-metadata",
168
+ runtime_available=runtime_available,
169
+ runtime_executable=ffprobe,
170
+ extraction_available=runtime_available,
171
+ reasons=reasons,
172
+ required_gates=(
173
+ "media_metadata_runtime_available",
174
+ "transcription_or_metadata_extraction_gate",
175
+ "document_derivative_write_gate",
176
+ "media_original_preservation_gate",
177
+ ),
178
+ )
179
+ for known_format in _MEDIA_FORMATS
180
+ )
181
+
182
+
183
+ def _report(
184
+ *,
185
+ known_format: KnownDocumentFormat,
186
+ family: DocumentFormatFamily,
187
+ read_adapter_id: str,
188
+ runtime_id: str,
189
+ runtime_available: bool,
190
+ runtime_executable: Path | None,
191
+ extraction_available: bool,
192
+ reasons: tuple[str, ...],
193
+ required_gates: tuple[str, ...],
194
+ ) -> PassiveCapabilityProbeReport:
195
+ return PassiveCapabilityProbeReport(
196
+ candidate_id=PASSIVE_CAPABILITY_CANDIDATE_ID,
197
+ known_format=known_format,
198
+ family=family,
199
+ status="candidate_available" if extraction_available else "blocked",
200
+ read_adapter_id=read_adapter_id,
201
+ runtime_id=runtime_id,
202
+ runtime_available=runtime_available,
203
+ runtime_executable=runtime_executable,
204
+ extraction_available=extraction_available,
205
+ direct_mutation_promoted=False,
206
+ reasons=reasons,
207
+ required_gates=required_gates,
208
+ evidence_refs=PASSIVE_CAPABILITY_SOURCE_REFS,
209
+ )
210
+
211
+
212
+ def _geospatial_runtime_available(
213
+ *,
214
+ active_env: Mapping[str, str],
215
+ search_path: Sequence[str] | None,
216
+ importable_modules: frozenset[str] | None,
217
+ ) -> bool:
218
+ return (
219
+ _find_executable("ogrinfo", active_env=active_env, search_path=search_path) is not None
220
+ or _find_executable("gdalinfo", active_env=active_env, search_path=search_path) is not None
221
+ or _is_importable("shapefile", importable_modules=importable_modules)
222
+ or _is_importable("trimesh", importable_modules=importable_modules)
223
+ )
224
+
225
+
226
+ def _find_executable(
227
+ name: str,
228
+ *,
229
+ active_env: Mapping[str, str],
230
+ search_path: Sequence[str] | None,
231
+ ) -> Path | None:
232
+ path_env = os.pathsep.join(search_path) if search_path is not None else active_env.get("PATH")
233
+ if not path_env:
234
+ return None
235
+ found = which(name, path=path_env)
236
+ if found is None:
237
+ return None
238
+ executable = Path(found).expanduser().resolve(strict=False)
239
+ if not _is_executable_file(executable):
240
+ return None
241
+ return executable
242
+
243
+
244
+ def _is_importable(name: str, *, importable_modules: frozenset[str] | None) -> bool:
245
+ if importable_modules is not None:
246
+ return name in importable_modules
247
+ return find_spec(name) is not None
248
+
249
+
250
+ def _is_executable_file(path: Path) -> bool:
251
+ return path.exists() and path.is_file() and os.access(path, os.X_OK)
@@ -0,0 +1,170 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """Engine-backed document patch harness."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import logging
7
+ from pathlib import Path
8
+
9
+ from pydantic import BaseModel, ConfigDict
10
+
11
+ from ummaya.tools.documents.artifact_store import DocumentArtifactStore
12
+ from ummaya.tools.documents.diff import DocumentDiff, diff_from_patch
13
+ from ummaya.tools.documents.engines import (
14
+ DocumentEngineRegistry,
15
+ DocumentMutationBlockedError,
16
+ DocumentMutationEngine,
17
+ UnsupportedDocumentEngineError,
18
+ )
19
+ from ummaya.tools.documents.models import (
20
+ ArtifactLineage,
21
+ BlockedReason,
22
+ DocumentArtifact,
23
+ DocumentExtraction,
24
+ DocumentPatch,
25
+ ToolResultStatus,
26
+ )
27
+ from ummaya.tools.documents.style import DocumentPatchValidationError, validate_document_patch
28
+
29
+ logger = logging.getLogger(__name__)
30
+
31
+
32
+ class DocumentPatchResult(BaseModel):
33
+ """Result of a copy or patch operation."""
34
+
35
+ model_config = ConfigDict(frozen=True, extra="forbid")
36
+
37
+ status: ToolResultStatus
38
+ source_artifact: DocumentArtifact
39
+ derivative_artifact: DocumentArtifact | None = None
40
+ diff: DocumentDiff | None = None
41
+ blocked_reason: BlockedReason | None = None
42
+ text_summary: str
43
+
44
+
45
+ def copy_for_edit(
46
+ store: DocumentArtifactStore,
47
+ source: DocumentArtifact,
48
+ *,
49
+ artifact_id: str,
50
+ destination_name: str,
51
+ ) -> DocumentArtifact:
52
+ """Create a working copy without mutating the source artifact."""
53
+ payload = Path(source.source_path).read_bytes()
54
+ return store.write_derivative(
55
+ source,
56
+ artifact_id=artifact_id,
57
+ lineage=ArtifactLineage.working_copy,
58
+ destination_name=destination_name,
59
+ payload=payload,
60
+ )
61
+
62
+
63
+ def apply_document_patch(
64
+ store: DocumentArtifactStore,
65
+ working_artifact: DocumentArtifact,
66
+ patch: DocumentPatch,
67
+ *,
68
+ engine_registry: DocumentEngineRegistry,
69
+ artifact_id: str,
70
+ destination_name: str,
71
+ ) -> DocumentPatchResult:
72
+ """Apply an ordered patch through a promoted mutation engine."""
73
+ if patch.target_artifact_id != working_artifact.artifact_id:
74
+ return _blocked(
75
+ working_artifact,
76
+ BlockedReason.validation_failed,
77
+ "Document patch target does not match the working artifact.",
78
+ )
79
+ if patch.expected_format is not working_artifact.format:
80
+ return _blocked(
81
+ working_artifact,
82
+ BlockedReason.validation_failed,
83
+ "Document patch expected_format does not match the working artifact.",
84
+ )
85
+
86
+ try:
87
+ validate_document_patch(patch)
88
+ engine = engine_registry.require_mutation(working_artifact.format)
89
+ except DocumentPatchValidationError as exc:
90
+ return _blocked(working_artifact, BlockedReason.validation_failed, str(exc))
91
+ except UnsupportedDocumentEngineError:
92
+ return _blocked(
93
+ working_artifact,
94
+ BlockedReason.unsupported_operation,
95
+ f"No mutation-capable engine is registered for {working_artifact.format.value}.",
96
+ )
97
+
98
+ before_extraction = _safe_inspect_for_diff(
99
+ engine,
100
+ Path(working_artifact.source_path),
101
+ artifact_id=working_artifact.artifact_id,
102
+ phase="before",
103
+ )
104
+ try:
105
+ payload = engine.apply_patch(Path(working_artifact.source_path), patch)
106
+ except DocumentMutationBlockedError as exc:
107
+ return _blocked(working_artifact, exc.reason, str(exc))
108
+ except ValueError as exc:
109
+ return _blocked(working_artifact, BlockedReason.validation_failed, str(exc))
110
+ derivative = store.write_derivative(
111
+ working_artifact,
112
+ artifact_id=artifact_id,
113
+ lineage=ArtifactLineage.working_copy,
114
+ destination_name=destination_name,
115
+ payload=payload,
116
+ )
117
+ after_extraction = _safe_inspect_for_diff(
118
+ engine,
119
+ Path(derivative.source_path),
120
+ artifact_id=derivative.artifact_id,
121
+ phase="after",
122
+ )
123
+ return DocumentPatchResult(
124
+ status=ToolResultStatus.ok,
125
+ source_artifact=working_artifact,
126
+ derivative_artifact=derivative,
127
+ diff=diff_from_patch(
128
+ patch,
129
+ source_artifact_id=working_artifact.artifact_id,
130
+ derivative_artifact_id=derivative.artifact_id,
131
+ before_extraction=before_extraction,
132
+ after_extraction=after_extraction,
133
+ ),
134
+ text_summary=(
135
+ f"Applied {len(patch.operations)} document patch operation(s) "
136
+ f"through {engine.engine_id}."
137
+ ),
138
+ )
139
+
140
+
141
+ def _blocked(
142
+ source: DocumentArtifact,
143
+ reason: BlockedReason,
144
+ message: str,
145
+ ) -> DocumentPatchResult:
146
+ return DocumentPatchResult(
147
+ status=ToolResultStatus.blocked,
148
+ source_artifact=source,
149
+ blocked_reason=reason,
150
+ text_summary=message,
151
+ )
152
+
153
+
154
+ def _safe_inspect_for_diff(
155
+ engine: DocumentMutationEngine,
156
+ path: Path,
157
+ *,
158
+ artifact_id: str,
159
+ phase: str,
160
+ ) -> DocumentExtraction | None:
161
+ try:
162
+ return engine.inspect(path, artifact_id=artifact_id)
163
+ except Exception as exc: # pragma: no cover - defensive evidence enrichment path.
164
+ logger.warning(
165
+ "Document patch diff %s-inspection failed for %s: %s",
166
+ phase,
167
+ artifact_id,
168
+ exc,
169
+ )
170
+ return None