ummaya 0.2.4 → 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 (477) hide show
  1. package/README.md +15 -2
  2. package/bin/ummaya +10 -1
  3. package/npm-shrinkwrap.json +253 -2
  4. package/package.json +5 -1
  5. package/prompts/manifest.yaml +1 -1
  6. package/prompts/system_v1.md +1 -0
  7. package/pyproject.toml +26 -2
  8. package/specs/2803-document-production-hardening/contracts/document-tools.schema.json +1043 -0
  9. package/src/ummaya/_canonical/__init__.py +2 -0
  10. package/src/ummaya/engine/engine.py +29 -132
  11. package/src/ummaya/evidence/__init__.py +21 -2
  12. package/src/ummaya/evidence/dataset_contract.py +193 -0
  13. package/src/ummaya/evidence/document_authoring_cases.py +33 -0
  14. package/src/ummaya/evidence/document_harness.py +313 -0
  15. package/src/ummaya/evidence/document_viewer_ux.py +391 -0
  16. package/src/ummaya/evidence/gates.py +70 -0
  17. package/src/ummaya/evidence/json_types.py +20 -0
  18. package/src/ummaya/evidence/models.py +88 -1
  19. package/src/ummaya/evidence/output_payload.py +89 -0
  20. package/src/ummaya/evidence/payload_documents.py +233 -0
  21. package/src/ummaya/evidence/route_contracts.py +224 -0
  22. package/src/ummaya/evidence/route_helpers.py +150 -0
  23. package/src/ummaya/evidence/runner.py +81 -212
  24. package/src/ummaya/evidence/source_provenance.py +246 -0
  25. package/src/ummaya/evidence/source_provenance_redaction.py +176 -0
  26. package/src/ummaya/evidence/tool_layer.py +39 -0
  27. package/src/ummaya/evidence/tool_layer_models.py +151 -0
  28. package/src/ummaya/ipc/adapter_manifest_emitter.py +26 -10
  29. package/src/ummaya/ipc/document_intent_normalization.py +185 -0
  30. package/src/ummaya/ipc/frame_schema.py +5 -5
  31. package/src/ummaya/ipc/route_diagnostics.py +73 -0
  32. package/src/ummaya/ipc/stdio.py +1109 -477
  33. package/src/ummaya/llm/client.py +102 -3
  34. package/src/ummaya/llm/config.py +8 -3
  35. package/src/ummaya/primitives/__init__.py +6 -2
  36. package/src/ummaya/primitives/delegation.py +1 -1
  37. package/src/ummaya/primitives/document.py +28 -0
  38. package/src/ummaya/settings.py +0 -3
  39. package/src/ummaya/tools/discovery_bridge.py +17 -1
  40. package/src/ummaya/tools/documents/__init__.py +297 -0
  41. package/src/ummaya/tools/documents/adapter_registry.py +487 -0
  42. package/src/ummaya/tools/documents/archive_container_probe.py +167 -0
  43. package/src/ummaya/tools/documents/artifact_store.py +454 -0
  44. package/src/ummaya/tools/documents/authoring.py +283 -0
  45. package/src/ummaya/tools/documents/baselines.py +114 -0
  46. package/src/ummaya/tools/documents/capability.py +331 -0
  47. package/src/ummaya/tools/documents/contracts.py +112 -0
  48. package/src/ummaya/tools/documents/conversion.py +521 -0
  49. package/src/ummaya/tools/documents/diff.py +275 -0
  50. package/src/ummaya/tools/documents/engines.py +163 -0
  51. package/src/ummaya/tools/documents/evaluation.py +291 -0
  52. package/src/ummaya/tools/documents/explicit_values.py +108 -0
  53. package/src/ummaya/tools/documents/fixtures.py +174 -0
  54. package/src/ummaya/tools/documents/format_completion_audit.py +471 -0
  55. package/src/ummaya/tools/documents/formats/__init__.py +2 -0
  56. package/src/ummaya/tools/documents/formats/archive.py +528 -0
  57. package/src/ummaya/tools/documents/formats/base.py +41 -0
  58. package/src/ummaya/tools/documents/formats/code_file.py +211 -0
  59. package/src/ummaya/tools/documents/formats/data_file.py +272 -0
  60. package/src/ummaya/tools/documents/formats/hwp.py +284 -0
  61. package/src/ummaya/tools/documents/formats/hwpx.py +1837 -0
  62. package/src/ummaya/tools/documents/formats/odf.py +435 -0
  63. package/src/ummaya/tools/documents/formats/ooxml.py +1030 -0
  64. package/src/ummaya/tools/documents/formats/passive.py +766 -0
  65. package/src/ummaya/tools/documents/formats/pdf.py +702 -0
  66. package/src/ummaya/tools/documents/formats/text_web.py +268 -0
  67. package/src/ummaya/tools/documents/hwp_conversion_probe.py +178 -0
  68. package/src/ummaya/tools/documents/hwp_direct_candidate.py +141 -0
  69. package/src/ummaya/tools/documents/inspection.py +289 -0
  70. package/src/ummaya/tools/documents/intake.py +1079 -0
  71. package/src/ummaya/tools/documents/legacy_office_promotion_probe.py +366 -0
  72. package/src/ummaya/tools/documents/models.py +1598 -0
  73. package/src/ummaya/tools/documents/odf_promotion_probe.py +167 -0
  74. package/src/ummaya/tools/documents/orchestrator.py +96 -0
  75. package/src/ummaya/tools/documents/passive_capability_probe.py +251 -0
  76. package/src/ummaya/tools/documents/patch.py +170 -0
  77. package/src/ummaya/tools/documents/pdfa_conformance.py +284 -0
  78. package/src/ummaya/tools/documents/pdfa_promotion_probe.py +198 -0
  79. package/src/ummaya/tools/documents/permissions.py +110 -0
  80. package/src/ummaya/tools/documents/planner.py +616 -0
  81. package/src/ummaya/tools/documents/registry.py +2733 -0
  82. package/src/ummaya/tools/documents/render.py +978 -0
  83. package/src/ummaya/tools/documents/render_comparison.py +113 -0
  84. package/src/ummaya/tools/documents/render_comparison_models.py +74 -0
  85. package/src/ummaya/tools/documents/render_comparison_regions.py +73 -0
  86. package/src/ummaya/tools/documents/render_comparison_style.py +161 -0
  87. package/src/ummaya/tools/documents/reread.py +157 -0
  88. package/src/ummaya/tools/documents/runtime_authoring.py +244 -0
  89. package/src/ummaya/tools/documents/runtime_authoring_bundle.py +76 -0
  90. package/src/ummaya/tools/documents/scorecard.py +184 -0
  91. package/src/ummaya/tools/documents/socratic_planner.py +193 -0
  92. package/src/ummaya/tools/documents/style.py +48 -0
  93. package/src/ummaya/tools/documents/tool_defs.py +523 -0
  94. package/src/ummaya/tools/documents/validate.py +347 -0
  95. package/src/ummaya/tools/executor.py +29 -0
  96. package/src/ummaya/tools/live_proxy.py +0 -3
  97. package/src/ummaya/tools/models.py +5 -1
  98. package/src/ummaya/tools/register_all.py +8 -0
  99. package/src/ummaya/tools/registry.py +10 -1
  100. package/src/ummaya/tools/routing/__init__.py +59 -0
  101. package/src/ummaya/tools/routing/builder.py +105 -0
  102. package/src/ummaya/tools/routing/cards.py +29 -0
  103. package/src/ummaya/tools/routing/decision_service.py +534 -0
  104. package/src/ummaya/tools/routing/decision_types.py +74 -0
  105. package/src/ummaya/tools/routing/feasibility.py +122 -0
  106. package/src/ummaya/tools/routing/intent.py +17 -0
  107. package/src/ummaya/tools/routing/intent_extractor.py +207 -0
  108. package/src/ummaya/tools/routing/intent_patterns.py +160 -0
  109. package/src/ummaya/tools/routing/intent_public_data.py +150 -0
  110. package/src/ummaya/tools/routing/intent_types.py +48 -0
  111. package/src/ummaya/tools/routing/lint.py +78 -0
  112. package/src/ummaya/tools/routing/metadata.py +174 -0
  113. package/src/ummaya/tools/routing/projection.py +340 -0
  114. package/src/ummaya/tools/routing/retrieval_policy.py +629 -0
  115. package/src/ummaya/tools/routing/schema.py +81 -0
  116. package/src/ummaya/tools/routing/types.py +96 -0
  117. package/src/ummaya/tools/routing_index.py +2 -2
  118. package/src/ummaya/tools/search.py +34 -746
  119. package/tests/fixtures/documents/public_forms/baselines.yaml +113 -0
  120. package/tui/package.json +1 -1
  121. package/tui/src/.cc-byte-identical-whitelist.yaml +266 -0
  122. package/tui/src/QueryEngine.ts +12 -8
  123. package/tui/src/bridge/inboundAttachments.ts +3 -3
  124. package/tui/src/cli/handlers/auth.ts +3 -12
  125. package/tui/src/cli/print.ts +7 -7
  126. package/tui/src/commands/insights.ts +1 -1
  127. package/tui/src/commands/install-github-app/types.ts +8 -30
  128. package/tui/src/commands/plugin/types.ts +6 -28
  129. package/tui/src/commands/plugin/unifiedTypes.ts +4 -26
  130. package/tui/src/commands/rename/generateSessionName.ts +1 -1
  131. package/tui/src/components/Feedback.tsx +1 -1
  132. package/tui/src/components/LogoV2/EmergencyTip.tsx +11 -2
  133. package/tui/src/components/LogoV2/WelcomeV2.tsx +1 -3
  134. package/tui/src/components/ScrollKeybindingHandler.tsx +6 -6
  135. package/tui/src/components/Spinner/types.ts +6 -28
  136. package/tui/src/components/agents/generateAgent.ts +1 -1
  137. package/tui/src/components/agents/new-agent-creation/types.ts +4 -26
  138. package/tui/src/components/config/EnvSecretIsolatedEditor.tsx +1 -1
  139. package/tui/src/components/mcp/types.ts +16 -38
  140. package/tui/src/components/messages/AssistantToolUseMessage.tsx +3 -2
  141. package/tui/src/components/messages/UserCrossSessionMessage.ts +16 -4
  142. package/tui/src/components/messages/UserForkBoilerplateMessage.ts +16 -4
  143. package/tui/src/components/messages/UserGitHubWebhookMessage.ts +16 -4
  144. package/tui/src/components/messages/UserToolResultMessage/utils.tsx +3 -2
  145. package/tui/src/components/permissions/MonitorPermissionRequest/MonitorPermissionRequest.ts +9 -4
  146. package/tui/src/components/permissions/ReviewArtifactPermissionRequest/ReviewArtifactPermissionRequest.ts +9 -4
  147. package/tui/src/components/primitive/DocumentSocraticReviewBlock.tsx +129 -0
  148. package/tui/src/components/primitive/DocumentToolResultCard.tsx +224 -0
  149. package/tui/src/components/primitive/documentSocraticReview.ts +215 -0
  150. package/tui/src/components/primitive/index.tsx +43 -1
  151. package/tui/src/components/primitive/types.ts +137 -0
  152. package/tui/src/components/ui/option.ts +4 -26
  153. package/tui/src/constants/common.ts +0 -2
  154. package/tui/src/constants/prompts.ts +4 -3
  155. package/tui/src/constants/querySource.ts +4 -26
  156. package/tui/src/entrypoints/sdk/controlTypes.ts +26 -48
  157. package/tui/src/entrypoints/sdk/coreTypes.generated.ts +3 -25
  158. package/tui/src/entrypoints/sdk/runtimeTypes.ts +38 -60
  159. package/tui/src/entrypoints/sdk/sdkUtilityTypes.ts +4 -26
  160. package/tui/src/entrypoints/sdk/settingsTypes.generated.ts +3 -25
  161. package/tui/src/entrypoints/sdk/toolTypes.ts +3 -25
  162. package/tui/src/hooks/toolPermission/handlers/interactiveHandler.ts +10 -0
  163. package/tui/src/hooks/useApiKeyVerification.ts +1 -1
  164. package/tui/src/hooks/useVirtualScroll.ts +1 -1
  165. package/tui/src/ink/ink.tsx +33 -14
  166. package/tui/src/ink/reconciler.ts +2 -3
  167. package/tui/src/ink/render-to-screen.ts +30 -10
  168. package/tui/src/ipc/bridge.ts +62 -15
  169. package/tui/src/ipc/bridgeSingleton.ts +5 -1
  170. package/tui/src/ipc/codec.ts +3 -3
  171. package/tui/src/ipc/frames.generated.ts +12 -12
  172. package/tui/src/ipc/llmClient.ts +151 -27
  173. package/tui/src/ipc/schema/frame.schema.json +1 -1
  174. package/tui/src/keybindings/defaultBindings.ts +4 -0
  175. package/tui/src/main.tsx +29 -11
  176. package/tui/src/native-ts/file-index/index.ts +33 -3
  177. package/tui/src/observability/surface.ts +2 -2
  178. package/tui/src/probes/toolRegistryProbe.tsx +3 -1
  179. package/tui/src/projectOnboardingState.ts +7 -6
  180. package/tui/src/query/chatMessageTypes.ts +18 -0
  181. package/tui/src/query/chatMessagesBuilder.ts +1 -1
  182. package/tui/src/query/deps.ts +1 -1
  183. package/tui/src/query/messageGuards.ts +106 -0
  184. package/tui/src/query/publicDataTerminalRepair.ts +384 -0
  185. package/tui/src/query/run.ts +1075 -0
  186. package/tui/src/query/supportBoundary.ts +168 -0
  187. package/tui/src/query/toolResultErrors.ts +103 -0
  188. package/tui/src/query/toolRunner.ts +687 -0
  189. package/tui/src/query/unavailableToolRepair.ts +118 -0
  190. package/tui/src/query.ts +9 -2186
  191. package/tui/src/screens/REPL.tsx +40 -29
  192. package/tui/src/services/api/adapterManifest.ts +4 -0
  193. package/tui/src/services/api/backendChat/events.ts +117 -0
  194. package/tui/src/services/api/backendChat/finalMessage.ts +40 -0
  195. package/tui/src/services/api/backendChat/frame.ts +9 -0
  196. package/tui/src/services/api/backendChat/streaming.ts +430 -0
  197. package/tui/src/services/api/backendChat/types.ts +62 -0
  198. package/tui/src/services/api/backendChat.ts +1 -0
  199. package/tui/src/services/api/client.ts +65 -2
  200. package/tui/src/services/api/errorUtils.ts +5 -5
  201. package/tui/src/services/api/errors.ts +1 -1
  202. package/tui/src/services/api/logging.ts +1 -1
  203. package/tui/src/services/api/ummaya/evidence.ts +194 -0
  204. package/tui/src/services/api/ummaya/messages.ts +255 -0
  205. package/tui/src/services/api/ummaya/nonStreaming.ts +66 -0
  206. package/tui/src/services/api/ummaya/provider.ts +200 -0
  207. package/tui/src/services/api/ummaya/reasoning.ts +24 -0
  208. package/tui/src/services/api/ummaya/request.ts +200 -0
  209. package/tui/src/services/api/ummaya/selectionContext.ts +240 -0
  210. package/tui/src/services/api/ummaya/streaming.ts +365 -0
  211. package/tui/src/services/api/ummaya/streamingPayload.ts +129 -0
  212. package/tui/src/services/api/ummaya/streamingReader.ts +40 -0
  213. package/tui/src/services/api/ummaya/toolSelection.ts +217 -0
  214. package/tui/src/services/api/ummaya/types.ts +110 -0
  215. package/tui/src/services/api/ummaya/usage.ts +30 -0
  216. package/tui/src/services/api/ummaya.ts +26 -418
  217. package/tui/src/services/api/withRetry.ts +1 -1
  218. package/tui/src/services/awaySummary.ts +2 -2
  219. package/tui/src/services/claudeAiLimits.ts +1 -1
  220. package/tui/src/services/compact/autoCompact.ts +1 -1
  221. package/tui/src/services/compact/compact.ts +1 -1
  222. package/tui/src/services/lsp/types.ts +8 -30
  223. package/tui/src/services/tips/types.ts +6 -28
  224. package/tui/src/services/tokenEstimation.ts +1 -1
  225. package/tui/src/services/toolRegistry/bootGuard.ts +5 -5
  226. package/tui/src/services/toolUseSummary/toolUseSummaryGenerator.ts +1 -1
  227. package/tui/src/services/tools/toolExecution.ts +94 -1
  228. package/tui/src/store/pendingPermissionSlot.ts +1 -1
  229. package/tui/src/store/session-store.ts +10 -36
  230. package/tui/src/stubs/any-stub.ts +15 -10
  231. package/tui/src/stubs/color-diff-napi.ts +37 -23
  232. package/tui/src/stubs/globals.d.ts +3 -3
  233. package/tui/src/stubs/macro-preload.ts +23 -12
  234. package/tui/src/tools/AdapterTool/AdapterTool.ts +1207 -714
  235. package/tui/src/tools/AdapterTool/routeDiagnostics.ts +75 -0
  236. package/tui/src/tools/AgentTool/AgentTool.tsx +84 -1371
  237. package/tui/src/tools/AgentTool/agentToolHandoff.ts +114 -0
  238. package/tui/src/tools/AgentTool/agentToolPartialResult.ts +16 -0
  239. package/tui/src/tools/AgentTool/agentToolProgress.ts +32 -0
  240. package/tui/src/tools/AgentTool/agentToolResolver.ts +161 -0
  241. package/tui/src/tools/AgentTool/agentToolResult.ts +163 -0
  242. package/tui/src/tools/AgentTool/agentToolUtils.ts +14 -686
  243. package/tui/src/tools/AgentTool/asyncAgentLifecycle.ts +208 -0
  244. package/tui/src/tools/AgentTool/asyncLifecycle.ts +153 -0
  245. package/tui/src/tools/AgentTool/backgroundedCompletion.ts +126 -0
  246. package/tui/src/tools/AgentTool/backgroundedLifecycle.ts +174 -0
  247. package/tui/src/tools/AgentTool/foregroundBackground.ts +83 -0
  248. package/tui/src/tools/AgentTool/foregroundDrain.tsx +133 -0
  249. package/tui/src/tools/AgentTool/foregroundFinalize.ts +98 -0
  250. package/tui/src/tools/AgentTool/foregroundLifecycle.tsx +237 -0
  251. package/tui/src/tools/AgentTool/foregroundProgress.tsx +169 -0
  252. package/tui/src/tools/AgentTool/foregroundTask.ts +89 -0
  253. package/tui/src/tools/AgentTool/forkSubagent.ts +1 -12
  254. package/tui/src/tools/AgentTool/forkSubagentGate.ts +34 -0
  255. package/tui/src/tools/AgentTool/launchRouting.ts +203 -0
  256. package/tui/src/tools/AgentTool/lifecycle.ts +244 -0
  257. package/tui/src/tools/AgentTool/mcpRouting.ts +73 -0
  258. package/tui/src/tools/AgentTool/orchestrationSupport.ts +70 -0
  259. package/tui/src/tools/AgentTool/permissions.ts +39 -0
  260. package/tui/src/tools/AgentTool/promptSetup.ts +181 -0
  261. package/tui/src/tools/AgentTool/remoteRouting.ts +62 -0
  262. package/tui/src/tools/AgentTool/resultMapping.ts +116 -0
  263. package/tui/src/tools/AgentTool/resumeAgent.ts +39 -107
  264. package/tui/src/tools/AgentTool/resumeAgentHelpers.ts +140 -0
  265. package/tui/src/tools/AgentTool/runAgent.ts +1 -1
  266. package/tui/src/tools/AgentTool/runtimeConfig.ts +57 -0
  267. package/tui/src/tools/AgentTool/schemas.ts +196 -0
  268. package/tui/src/tools/AgentTool/sourceVerificationPropagation.ts +263 -0
  269. package/tui/src/tools/AgentTool/worktreeLifecycle.ts +105 -0
  270. package/tui/src/tools/AskUserQuestionTool/AskUserQuestionTool.tsx +174 -202
  271. package/tui/src/tools/BashTool/BashTool.tsx +71 -1072
  272. package/tui/src/tools/BashTool/bashCommandHelpers.ts +12 -12
  273. package/tui/src/tools/BashTool/bashPermissions/astPreflight.ts +173 -0
  274. package/tui/src/tools/BashTool/bashPermissions/classifierChecks.ts +199 -0
  275. package/tui/src/tools/BashTool/bashPermissions/compoundGuards.ts +53 -0
  276. package/tui/src/tools/BashTool/bashPermissions/constants.ts +99 -0
  277. package/tui/src/tools/BashTool/bashPermissions/index.ts +38 -0
  278. package/tui/src/tools/BashTool/bashPermissions/legacyMisparsing.ts +62 -0
  279. package/tui/src/tools/BashTool/bashPermissions/main.ts +135 -0
  280. package/tui/src/tools/BashTool/bashPermissions/normalizedCommands.ts +33 -0
  281. package/tui/src/tools/BashTool/bashPermissions/operatorFlow.ts +98 -0
  282. package/tui/src/tools/BashTool/bashPermissions/permissionChecks.ts +200 -0
  283. package/tui/src/tools/BashTool/bashPermissions/prefixSuggestions.ts +88 -0
  284. package/tui/src/tools/BashTool/bashPermissions/promptClassifierRules.ts +125 -0
  285. package/tui/src/tools/BashTool/bashPermissions/ruleDelegates.ts +19 -0
  286. package/tui/src/tools/BashTool/bashPermissions/ruleMatching.ts +145 -0
  287. package/tui/src/tools/BashTool/bashPermissions/sandboxAutoAllow.ts +75 -0
  288. package/tui/src/tools/BashTool/bashPermissions/subcommandFlow.ts +205 -0
  289. package/tui/src/tools/BashTool/bashPermissions/subcommandGuards.ts +73 -0
  290. package/tui/src/tools/BashTool/bashPermissions/subcommandResultHelpers.ts +116 -0
  291. package/tui/src/tools/BashTool/bashPermissions/types.ts +26 -0
  292. package/tui/src/tools/BashTool/bashPermissions/wrapperStripping.ts +139 -0
  293. package/tui/src/tools/BashTool/bashPermissions.ts +26 -2621
  294. package/tui/src/tools/BashTool/call.ts +202 -0
  295. package/tui/src/tools/BashTool/callLoader.ts +35 -0
  296. package/tui/src/tools/BashTool/commandClassification.ts +151 -0
  297. package/tui/src/tools/BashTool/commandClassificationLoader.ts +40 -0
  298. package/tui/src/tools/BashTool/cwdReset.ts +33 -0
  299. package/tui/src/tools/BashTool/lineTruncation.ts +11 -0
  300. package/tui/src/tools/BashTool/modeValidation.ts +13 -1
  301. package/tui/src/tools/BashTool/outputPersistence.ts +42 -0
  302. package/tui/src/tools/BashTool/permissionClassification.ts +66 -0
  303. package/tui/src/tools/BashTool/permissionLoader.ts +44 -0
  304. package/tui/src/tools/BashTool/resultLoader.ts +29 -0
  305. package/tui/src/tools/BashTool/resultMapping.ts +83 -0
  306. package/tui/src/tools/BashTool/sandboxPolicy.ts +79 -0
  307. package/tui/src/tools/BashTool/schemas.ts +65 -0
  308. package/tui/src/tools/BashTool/sedEditExecution.ts +59 -0
  309. package/tui/src/tools/BashTool/shellExecution.tsx +245 -0
  310. package/tui/src/tools/BashTool/shellOutputUtils.ts +85 -0
  311. package/tui/src/tools/BashTool/shellPermissionGauntlet.ts +97 -0
  312. package/tui/src/tools/BashTool/uiLoader.ts +37 -0
  313. package/tui/src/tools/BriefTool/upload.ts +1 -1
  314. package/tui/src/tools/CalculatorTool/parser.ts +2 -2
  315. package/tui/src/tools/DocumentPrimitive/DocumentPrimitive.ts +262 -0
  316. package/tui/src/tools/DocumentPrimitive/dispatchNormalization.ts +270 -0
  317. package/tui/src/tools/DocumentPrimitive/documentDestinationPath.ts +18 -0
  318. package/tui/src/tools/DocumentPrimitive/documentMutationGuard.ts +22 -0
  319. package/tui/src/tools/DocumentPrimitive/documentPatchNormalization.ts +248 -0
  320. package/tui/src/tools/DocumentPrimitive/documentSourceVerification.ts +245 -0
  321. package/tui/src/tools/DocumentPrimitive/documentSourceVerificationFields.ts +103 -0
  322. package/tui/src/tools/DocumentPrimitive/modelVisibleOutput.ts +40 -0
  323. package/tui/src/tools/DocumentPrimitive/prompt.ts +35 -0
  324. package/tui/src/tools/FileEditTool/FileEditTool.ts +9 -507
  325. package/tui/src/tools/FileEditTool/call.ts +228 -0
  326. package/tui/src/tools/FileEditTool/validateInput.ts +196 -0
  327. package/tui/src/tools/FileReadTool/imageProcessor.ts +13 -0
  328. package/tui/src/tools/FileWriteTool/FileWriteTool.ts +7 -300
  329. package/tui/src/tools/FileWriteTool/call.ts +223 -0
  330. package/tui/src/tools/FileWriteTool/validateInput.ts +80 -0
  331. package/tui/src/tools/ListMcpResourcesTool/ListMcpResourcesTool.ts +19 -3
  332. package/tui/src/tools/LookupPrimitive/LookupPrimitive.ts +25 -32
  333. package/tui/src/tools/LookupPrimitive/prompt.ts +0 -2
  334. package/tui/src/tools/MCPTool/trustPolicy.ts +118 -0
  335. package/tui/src/tools/McpAuthTool/McpAuthTool.ts +21 -3
  336. package/tui/src/tools/NotebookEditTool/NotebookEditTool.ts +7 -326
  337. package/tui/src/tools/NotebookEditTool/call.ts +254 -0
  338. package/tui/src/tools/NotebookEditTool/notebookModel.ts +51 -0
  339. package/tui/src/tools/NotebookEditTool/validateInput.ts +142 -0
  340. package/tui/src/tools/PowerShellTool/PowerShellTool.tsx +46 -937
  341. package/tui/src/tools/PowerShellTool/acceptEditsCommandValidation.ts +162 -0
  342. package/tui/src/tools/PowerShellTool/call.ts +179 -0
  343. package/tui/src/tools/PowerShellTool/callLoader.ts +37 -0
  344. package/tui/src/tools/PowerShellTool/commandClassification.ts +86 -0
  345. package/tui/src/tools/PowerShellTool/modeValidation.ts +25 -332
  346. package/tui/src/tools/PowerShellTool/outputPersistence.ts +42 -0
  347. package/tui/src/tools/PowerShellTool/permissionClassification.ts +28 -0
  348. package/tui/src/tools/PowerShellTool/resultLoader.ts +31 -0
  349. package/tui/src/tools/PowerShellTool/resultMapping.ts +75 -0
  350. package/tui/src/tools/PowerShellTool/schemas.ts +40 -0
  351. package/tui/src/tools/PowerShellTool/shellExecution.tsx +258 -0
  352. package/tui/src/tools/PowerShellTool/symlinkModeValidation.ts +44 -0
  353. package/tui/src/tools/PowerShellTool/uiLoader.ts +37 -0
  354. package/tui/src/tools/PowerShellTool/validation.ts +39 -0
  355. package/tui/src/tools/ReadMcpResourceTool/ReadMcpResourceTool.ts +19 -3
  356. package/tui/src/tools/ResolveLocationPrimitive/ResolveLocationPrimitive.ts +1 -11
  357. package/tui/src/tools/ResolveLocationPrimitive/prompt.ts +2 -6
  358. package/tui/src/tools/SkillTool/SkillTool.ts +2 -2
  359. package/tui/src/tools/SubmitPrimitive/SubmitPrimitive.ts +27 -10
  360. package/tui/src/tools/TaskCreateTool/TaskCreateTool.ts +16 -2
  361. package/tui/src/tools/TaskGetTool/TaskGetTool.ts +23 -3
  362. package/tui/src/tools/TaskListTool/TaskListTool.ts +22 -4
  363. package/tui/src/tools/TaskOutputTool/TaskOutputTool.tsx +46 -547
  364. package/tui/src/tools/TaskOutputTool/lookup.ts +216 -0
  365. package/tui/src/tools/TaskOutputTool/render.tsx +257 -0
  366. package/tui/src/tools/TaskOutputTool/schemas.ts +55 -0
  367. package/tui/src/tools/TaskOutputTool/serialization.ts +36 -0
  368. package/tui/src/tools/TaskStopTool/TaskStopTool.ts +10 -0
  369. package/tui/src/tools/TaskUpdateTool/TaskUpdateTool.ts +14 -364
  370. package/tui/src/tools/TaskUpdateTool/completion.ts +62 -0
  371. package/tui/src/tools/TaskUpdateTool/schemas.ts +62 -0
  372. package/tui/src/tools/TaskUpdateTool/serialization.ts +46 -0
  373. package/tui/src/tools/TaskUpdateTool/statusUpdate.ts +247 -0
  374. package/tui/src/tools/TodoWriteTool/TodoWriteTool.ts +21 -2
  375. package/tui/src/tools/ToolSearchTool/ToolSearchTool.ts +21 -302
  376. package/tui/src/tools/ToolSearchTool/ccSupportTools.ts +223 -0
  377. package/tui/src/tools/ToolSearchTool/descriptionCache.ts +50 -0
  378. package/tui/src/tools/ToolSearchTool/keywordSearch.ts +216 -0
  379. package/tui/src/tools/ToolSearchTool/prompt.ts +10 -4
  380. package/tui/src/tools/ToolSearchTool/resultMapping.ts +30 -0
  381. package/tui/src/tools/ToolSearchTool/schemas.ts +30 -0
  382. package/tui/src/tools/ToolSearchTool/searchPool.ts +47 -0
  383. package/tui/src/tools/ToolSearchTool/supportIntentHints.ts +140 -0
  384. package/tui/src/tools/TranslateTool/TranslateTool.ts +1 -1
  385. package/tui/src/tools/VerifyPrimitive/VerifyPrimitive.ts +2 -1
  386. package/tui/src/tools/WebFetchTool/WebFetchTool.ts +43 -138
  387. package/tui/src/tools/WebFetchTool/call.ts +227 -0
  388. package/tui/src/tools/WebFetchTool/resolvedAddressSafety.ts +78 -0
  389. package/tui/src/tools/WebFetchTool/sourceVerification.ts +204 -0
  390. package/tui/src/tools/WebFetchTool/types.ts +23 -0
  391. package/tui/src/tools/WebFetchTool/urlSafety.ts +181 -0
  392. package/tui/src/tools/WebFetchTool/utils.ts +1 -1
  393. package/tui/src/tools/WebSearchTool/UI.tsx +0 -1
  394. package/tui/src/tools/WebSearchTool/WebSearchTool.ts +9 -313
  395. package/tui/src/tools/WebSearchTool/call.ts +33 -0
  396. package/tui/src/tools/WebSearchTool/responseMapping.ts +190 -0
  397. package/tui/src/tools/WebSearchTool/resultBlock.ts +47 -0
  398. package/tui/src/tools/WebSearchTool/schemas.ts +47 -0
  399. package/tui/src/tools/WebSearchTool/toolSchema.ts +12 -0
  400. package/tui/src/tools/WorkspaceToolAdapter/WorkspaceToolAdapter.ts +79 -0
  401. package/tui/src/tools/WorkspaceToolAdapter/allowedRootPolicy.ts +85 -0
  402. package/tui/src/tools/WorkspaceToolAdapter/documentFormatGuards.ts +73 -0
  403. package/tui/src/tools/WorkspaceToolAdapter/inputNormalization.ts +105 -0
  404. package/tui/src/tools/WorkspaceToolAdapter/mcpExposurePolicy.ts +64 -0
  405. package/tui/src/tools/WorkspaceToolAdapter/toolDefFactory.ts +215 -0
  406. package/tui/src/tools/WorkspaceToolAdapter/toolNames.ts +6 -0
  407. package/tui/src/tools/WorkspaceToolAdapter/workspacePolicy.ts +15 -0
  408. package/tui/src/tools/_shared/dispatchPrimitive.ts +6 -6
  409. package/tui/src/tools/_shared/documentChangeToPatch.ts +125 -0
  410. package/tui/src/tools/_shared/documentDispatchArguments.ts +87 -0
  411. package/tui/src/tools/_shared/documentPrimitiveTimeout.ts +13 -0
  412. package/tui/src/tools/_shared/documentToolResultRender.ts +98 -0
  413. package/tui/src/tools/_shared/pendingCallRegistry.ts +1 -6
  414. package/tui/src/tools/_shared/rootPrimitiveInput.ts +1 -0
  415. package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPatterns.ts +58 -0
  416. package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPrompt.ts +271 -0
  417. package/tui/src/tools/_shared/toolChoiceRepair/documentRepair.ts +452 -0
  418. package/tui/src/tools/_shared/toolChoiceRepair/messageAccess.ts +80 -0
  419. package/tui/src/tools/_shared/toolChoiceRepair/publicDataRepair.ts +92 -0
  420. package/tui/src/tools/_shared/toolChoiceRepair/supportRepair.ts +135 -0
  421. package/tui/src/tools/_shared/toolChoiceRepair.ts +55 -860
  422. package/tui/src/tools/shared/mockDisclaimer.ts +1 -1
  423. package/tui/src/tools.ts +39 -190
  424. package/tui/src/types/fileSuggestion.ts +4 -26
  425. package/tui/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +186 -148
  426. package/tui/src/types/generated/events_mono/common/v1/auth.ts +25 -11
  427. package/tui/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +47 -30
  428. package/tui/src/types/generated/google/protobuf/timestamp.ts +21 -7
  429. package/tui/src/types/message.ts +80 -102
  430. package/tui/src/types/messageQueueTypes.ts +6 -28
  431. package/tui/src/types/notebook.ts +16 -38
  432. package/tui/src/types/statusLine.ts +4 -26
  433. package/tui/src/types/tools.ts +24 -46
  434. package/tui/src/types/utils.ts +6 -28
  435. package/tui/src/upstreamproxy/relay.ts +7 -3
  436. package/tui/src/upstreamproxy/upstreamproxy.ts +1 -1
  437. package/tui/src/utils/assistantMessageFactories.ts +9 -3
  438. package/tui/src/utils/auth.ts +129 -139
  439. package/tui/src/utils/bash/ast.ts +23 -23
  440. package/tui/src/utils/bash/bashParser.ts +5 -5
  441. package/tui/src/utils/billing.ts +1 -1
  442. package/tui/src/utils/collapseReadSearch.ts +3 -3
  443. package/tui/src/utils/cronTasks.ts +1 -1
  444. package/tui/src/utils/execFileNoThrow.ts +1 -1
  445. package/tui/src/utils/filePersistence/types.ts +16 -38
  446. package/tui/src/utils/forkedAgent.ts +1 -1
  447. package/tui/src/utils/gracefulShutdown.ts +4 -4
  448. package/tui/src/utils/heapDumpService.ts +12 -8
  449. package/tui/src/utils/hooks/apiQueryHookHelper.ts +1 -1
  450. package/tui/src/utils/hooks/execPromptHook.ts +1 -1
  451. package/tui/src/utils/hooks/skillImprovement.ts +1 -1
  452. package/tui/src/utils/mcp/dateTimeParser.ts +1 -1
  453. package/tui/src/utils/messages.ts +18 -0
  454. package/tui/src/utils/migrateSessions.ts +3 -3
  455. package/tui/src/utils/model/model.ts +6 -6
  456. package/tui/src/utils/permissions/yoloClassifier.ts +1 -1
  457. package/tui/src/utils/plugins/headlessPluginInstall.ts +1 -1
  458. package/tui/src/utils/plugins/mcpPluginIntegration.ts +1 -1
  459. package/tui/src/utils/plugins/mcpbHandler.ts +1 -1
  460. package/tui/src/utils/plugins/pluginLoader.ts +8 -8
  461. package/tui/src/utils/protectedNamespace.ts +5 -3
  462. package/tui/src/utils/rawJsonToolCall.ts +242 -0
  463. package/tui/src/utils/ripgrep.ts +16 -7
  464. package/tui/src/utils/sessionTitle.ts +1 -1
  465. package/tui/src/utils/settings/permissionValidation.ts +14 -2
  466. package/tui/src/utils/shell/prefix.ts +1 -1
  467. package/tui/src/utils/sideQuery.ts +1 -1
  468. package/tui/src/utils/systemThemeWatcher.ts +13 -3
  469. package/tui/src/utils/teleport.tsx +1 -1
  470. package/uv.lock +400 -14
  471. package/tui/src/services/api/claude.ts +0 -3540
  472. package/tui/src/tools/_shared/directPublicDataGuard.ts +0 -362
  473. package/tui/src/tools/_shared/kmaAnalysisGuard.ts +0 -197
  474. package/tui/src/tools/_shared/kmaAviationGuard.ts +0 -70
  475. package/tui/src/tools/_shared/nmcAedGuard.ts +0 -234
  476. package/tui/src/tools/_shared/protectedCheckGuard.ts +0 -207
  477. package/tui/src/tools/_shared/textToolCallGuard.ts +0 -91
@@ -0,0 +1,487 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """Format adapter registry for the single document primitive."""
3
+
4
+ from __future__ import annotations
5
+
6
+ from pathlib import Path
7
+ from typing import TYPE_CHECKING
8
+
9
+ from ummaya.tools.documents.engines import DocumentEngineRegistry, DocumentInspectionEngine
10
+ from ummaya.tools.documents.formats.base import DocumentFormatAdapter
11
+ from ummaya.tools.documents.models import DocumentExtraction, DocumentFormat, KnownDocumentFormat
12
+
13
+ if TYPE_CHECKING:
14
+ from ummaya.tools.documents.tool_defs import DocumentFieldPatch
15
+
16
+
17
+ _ODF_PROMOTED_FORMATS = (DocumentFormat.odt, DocumentFormat.ods, DocumentFormat.odp)
18
+ _TEXT_WEB_PROMOTED_FORMATS = (
19
+ DocumentFormat.html,
20
+ DocumentFormat.htm,
21
+ DocumentFormat.txt,
22
+ DocumentFormat.rtf,
23
+ DocumentFormat.md,
24
+ )
25
+ _DATA_PROMOTED_FORMATS = (
26
+ DocumentFormat.csv,
27
+ DocumentFormat.tsv,
28
+ DocumentFormat.xml,
29
+ DocumentFormat.rdf,
30
+ DocumentFormat.ttl,
31
+ DocumentFormat.lod,
32
+ DocumentFormat.json,
33
+ DocumentFormat.jsonl,
34
+ DocumentFormat.yaml,
35
+ DocumentFormat.yml,
36
+ DocumentFormat.geojson,
37
+ DocumentFormat.gpx,
38
+ DocumentFormat.kml,
39
+ DocumentFormat.fasta,
40
+ DocumentFormat.sgml,
41
+ DocumentFormat.dtd,
42
+ DocumentFormat.hml,
43
+ DocumentFormat.etc,
44
+ )
45
+ _ARCHIVE_PROMOTED_FORMATS = (
46
+ DocumentFormat.epub,
47
+ DocumentFormat.zip,
48
+ DocumentFormat.seven_z,
49
+ DocumentFormat.tar,
50
+ DocumentFormat.gz,
51
+ )
52
+ _CODE_PROMOTED_FORMATS = (DocumentFormat.python,)
53
+
54
+
55
+ class UnsupportedDocumentAdapterError(LookupError):
56
+ """Raised when no document adapter is registered for a format."""
57
+
58
+ def __init__(self, document_format: DocumentFormat | KnownDocumentFormat) -> None:
59
+ super().__init__(f"No document adapter registered for {document_format.value}")
60
+ self.document_format = document_format
61
+
62
+
63
+ class DocumentAdapterRegistry:
64
+ """Session-local registry of format-scoped document adapters."""
65
+
66
+ def __init__(self) -> None:
67
+ self._by_adapter_id: dict[str, DocumentFormatAdapter] = {}
68
+ self._by_known_format: dict[KnownDocumentFormat, DocumentFormatAdapter] = {}
69
+ self._by_promoted_format: dict[DocumentFormat, DocumentFormatAdapter] = {}
70
+
71
+ def register(self, adapter: DocumentFormatAdapter) -> None:
72
+ """Register one adapter for its known and promoted formats."""
73
+ self._validate_registration(adapter)
74
+
75
+ self._by_adapter_id[adapter.adapter_id] = adapter
76
+ for known_format in adapter.known_formats:
77
+ self._by_known_format[known_format] = adapter
78
+ for promoted_format in adapter.promoted_formats:
79
+ self._by_promoted_format[promoted_format] = adapter
80
+
81
+ def _validate_registration(self, adapter: DocumentFormatAdapter) -> None:
82
+ """Validate adapter metadata before mutating registry state."""
83
+ if not adapter.adapter_id:
84
+ raise ValueError("adapter_id is required")
85
+ if adapter.adapter_id in self._by_adapter_id:
86
+ raise ValueError(f"adapter_id already registered: {adapter.adapter_id}")
87
+ if not adapter.known_formats:
88
+ raise ValueError("adapter must declare at least one known format")
89
+
90
+ self._validate_format_sets(adapter)
91
+ self._validate_no_existing_registration(adapter)
92
+
93
+ def _validate_format_sets(self, adapter: DocumentFormatAdapter) -> None:
94
+ """Validate one adapter's own format declarations."""
95
+ if len(set(adapter.known_formats)) != len(adapter.known_formats):
96
+ raise ValueError("adapter known formats must be unique")
97
+ if len(set(adapter.promoted_formats)) != len(adapter.promoted_formats):
98
+ raise ValueError("adapter promoted formats must be unique")
99
+
100
+ known_formats = set(adapter.known_formats)
101
+ for promoted_format in adapter.promoted_formats:
102
+ if KnownDocumentFormat(promoted_format.value) not in known_formats:
103
+ raise ValueError("adapter promoted format must also be declared as a known format")
104
+
105
+ def _validate_no_existing_registration(self, adapter: DocumentFormatAdapter) -> None:
106
+ """Validate that the registry has no conflicting adapter mapping."""
107
+ for known_format in adapter.known_formats:
108
+ if known_format in self._by_known_format:
109
+ raise ValueError(f"known format already registered: {known_format.value}")
110
+
111
+ for promoted_format in adapter.promoted_formats:
112
+ if promoted_format in self._by_promoted_format:
113
+ raise ValueError(f"promoted format already registered: {promoted_format.value}")
114
+
115
+ def get_known(
116
+ self,
117
+ document_format: KnownDocumentFormat,
118
+ ) -> DocumentFormatAdapter | None:
119
+ """Return the adapter for a known format, if registered."""
120
+ return self._by_known_format.get(document_format)
121
+
122
+ def require_known(self, document_format: KnownDocumentFormat) -> DocumentFormatAdapter:
123
+ """Return the adapter for a known format or fail closed."""
124
+ adapter = self.get_known(document_format)
125
+ if adapter is None:
126
+ raise UnsupportedDocumentAdapterError(document_format)
127
+ return adapter
128
+
129
+ def get_promoted(
130
+ self,
131
+ document_format: DocumentFormat,
132
+ ) -> DocumentFormatAdapter | None:
133
+ """Return the adapter for a promoted runtime format, if registered."""
134
+ return self._by_promoted_format.get(document_format)
135
+
136
+ def require_promoted(self, document_format: DocumentFormat) -> DocumentFormatAdapter:
137
+ """Return the adapter for a promoted runtime format or fail closed."""
138
+ adapter = self.get_promoted(document_format)
139
+ if adapter is None:
140
+ raise UnsupportedDocumentAdapterError(document_format)
141
+ return adapter
142
+
143
+
144
+ class EngineBackedDocumentAdapter:
145
+ """Adapter wrapper around one promoted inspection engine."""
146
+
147
+ def __init__(
148
+ self,
149
+ *,
150
+ adapter_id: str,
151
+ known_formats: tuple[KnownDocumentFormat, ...],
152
+ promoted_formats: tuple[DocumentFormat, ...],
153
+ inspection_engine: DocumentInspectionEngine,
154
+ ) -> None:
155
+ self.adapter_id = adapter_id
156
+ self.known_formats = known_formats
157
+ self.promoted_formats = promoted_formats
158
+ self._inspection_engine = inspection_engine
159
+
160
+ @property
161
+ def engine_id(self) -> str:
162
+ """Return the wrapped engine id for diagnostics and result text."""
163
+ return self._inspection_engine.engine_id
164
+
165
+ def inspect(self, path: Path, *, artifact_id: str) -> DocumentExtraction:
166
+ """Delegate inspection to the wrapped promoted engine."""
167
+ return self._inspection_engine.inspect(path, artifact_id=artifact_id)
168
+
169
+ def normalize_fill_patches(
170
+ self,
171
+ patches: tuple[DocumentFieldPatch, ...],
172
+ *,
173
+ extraction: DocumentExtraction | None,
174
+ ) -> tuple[DocumentFieldPatch, ...]:
175
+ """Return fill patches unchanged for adapters without target aliases."""
176
+ _ = extraction
177
+ return patches
178
+
179
+
180
+ def build_default_document_adapter_registry() -> DocumentAdapterRegistry:
181
+ """Build the default adapter registry for currently promoted engines."""
182
+ from ummaya.tools.documents.formats.archive import ( # noqa: PLC0415
183
+ ArchiveContainerDocumentEngine,
184
+ )
185
+ from ummaya.tools.documents.formats.code_file import ( # noqa: PLC0415
186
+ PythonSourceDocumentAdapter,
187
+ )
188
+ from ummaya.tools.documents.formats.data_file import DataFileDocumentAdapter # noqa: PLC0415
189
+ from ummaya.tools.documents.formats.hwp import HwpDocumentAdapter # noqa: PLC0415
190
+ from ummaya.tools.documents.formats.hwpx import HwpXDocumentAdapter # noqa: PLC0415
191
+ from ummaya.tools.documents.formats.odf import OdfdoDocumentAdapter # noqa: PLC0415
192
+ from ummaya.tools.documents.formats.ooxml import ( # noqa: PLC0415
193
+ DocxDocumentAdapter,
194
+ OpenPyxlDocumentEngine,
195
+ PptxDocumentAdapter,
196
+ PythonPptxDocumentEngine,
197
+ XlsxDocumentAdapter,
198
+ )
199
+ from ummaya.tools.documents.formats.pdf import PdfDocumentAdapter # noqa: PLC0415
200
+ from ummaya.tools.documents.formats.text_web import TextWebDocumentAdapter # noqa: PLC0415
201
+
202
+ registry = DocumentAdapterRegistry()
203
+ registry.register(HwpXDocumentAdapter())
204
+ registry.register(HwpDocumentAdapter())
205
+ registry.register(DocxDocumentAdapter())
206
+ registry.register(XlsxDocumentAdapter(OpenPyxlDocumentEngine()))
207
+ registry.register(PptxDocumentAdapter(PythonPptxDocumentEngine()))
208
+ registry.register(PdfDocumentAdapter())
209
+ registry.register(OdfdoDocumentAdapter())
210
+ registry.register(TextWebDocumentAdapter())
211
+ registry.register(DataFileDocumentAdapter())
212
+ registry.register(PythonSourceDocumentAdapter())
213
+ for document_format in _ARCHIVE_PROMOTED_FORMATS:
214
+ _register_engine_backed_adapter(
215
+ registry,
216
+ document_format=document_format,
217
+ engine=ArchiveContainerDocumentEngine(document_format),
218
+ )
219
+ _register_passive_known_only_adapters(registry)
220
+ return registry
221
+
222
+
223
+ def build_document_adapter_registry_from_engine_registry(
224
+ engine_registry: DocumentEngineRegistry,
225
+ ) -> DocumentAdapterRegistry:
226
+ """Wrap currently registered promoted engines in document adapters."""
227
+ from ummaya.tools.documents.formats.hwp import HwpDocumentAdapter # noqa: PLC0415
228
+ from ummaya.tools.documents.formats.ooxml import ( # noqa: PLC0415
229
+ PptxDocumentAdapter,
230
+ XlsxDocumentAdapter,
231
+ )
232
+ from ummaya.tools.documents.formats.pdf import PdfDocumentAdapter # noqa: PLC0415
233
+
234
+ registry = DocumentAdapterRegistry()
235
+ if engine_registry.get(DocumentFormat.hwp) is None:
236
+ registry.register(HwpDocumentAdapter())
237
+ if engine_registry.get(DocumentFormat.xlsx) is None:
238
+ registry.register(XlsxDocumentAdapter())
239
+ if engine_registry.get(DocumentFormat.pptx) is None:
240
+ registry.register(PptxDocumentAdapter())
241
+ if engine_registry.get(DocumentFormat.pdf) is None:
242
+ registry.register(PdfDocumentAdapter(promote_default=False))
243
+ registered_family_formats = _register_promoted_family_adapters(registry, engine_registry)
244
+ _register_passive_known_only_adapters(registry)
245
+ for document_format in DocumentFormat:
246
+ engine = engine_registry.get(document_format)
247
+ if engine is None:
248
+ continue
249
+ if document_format in registered_family_formats:
250
+ continue
251
+ _register_engine_backed_adapter(
252
+ registry,
253
+ document_format=document_format,
254
+ engine=engine,
255
+ )
256
+ return registry
257
+
258
+
259
+ def _register_promoted_family_adapters(
260
+ registry: DocumentAdapterRegistry,
261
+ engine_registry: DocumentEngineRegistry,
262
+ ) -> set[DocumentFormat]:
263
+ """Register multi-format promoted adapters and return their owned formats."""
264
+ registered: set[DocumentFormat] = set()
265
+ if _has_any_engine(engine_registry, _ODF_PROMOTED_FORMATS):
266
+ _register_promoted_odf_adapter(registry, engine_registry)
267
+ registered.update(_ODF_PROMOTED_FORMATS)
268
+ if _has_any_engine(engine_registry, _TEXT_WEB_PROMOTED_FORMATS):
269
+ _register_promoted_text_web_adapter(registry, engine_registry)
270
+ registered.update(_TEXT_WEB_PROMOTED_FORMATS)
271
+ if _has_any_engine(engine_registry, _DATA_PROMOTED_FORMATS):
272
+ _register_promoted_data_adapter(registry, engine_registry)
273
+ registered.update(_DATA_PROMOTED_FORMATS)
274
+ if _has_any_engine(engine_registry, _CODE_PROMOTED_FORMATS):
275
+ _register_promoted_code_adapter(registry, engine_registry)
276
+ registered.update(_CODE_PROMOTED_FORMATS)
277
+ if _has_any_engine(engine_registry, _ARCHIVE_PROMOTED_FORMATS):
278
+ registered.update(_register_promoted_archive_adapters(registry, engine_registry))
279
+ return registered
280
+
281
+
282
+ def _has_any_engine(
283
+ engine_registry: DocumentEngineRegistry,
284
+ document_formats: tuple[DocumentFormat, ...],
285
+ ) -> bool:
286
+ """Return whether any format in a family has a promoted engine."""
287
+ return any(
288
+ engine_registry.get(document_format) is not None for document_format in document_formats
289
+ )
290
+
291
+
292
+ def _register_passive_known_only_adapters(registry: DocumentAdapterRegistry) -> None:
293
+ """Register known-only passive adapters for non-promoted document families."""
294
+ from ummaya.tools.documents.formats.passive import ( # noqa: PLC0415
295
+ ArchiveDocumentSetAdapter,
296
+ CodeFileDocumentAdapter,
297
+ DataFileDocumentAdapter,
298
+ GeospatialDocumentAdapter,
299
+ ImageScanDocumentAdapter,
300
+ LegacyOfficeDocumentAdapter,
301
+ MediaAssetDocumentAdapter,
302
+ OdfDocumentAdapter,
303
+ TextWebExportAdapter,
304
+ )
305
+
306
+ if registry.get_known(KnownDocumentFormat.odt) is None:
307
+ registry.register(OdfDocumentAdapter())
308
+ registry.register(LegacyOfficeDocumentAdapter())
309
+ if registry.get_known(KnownDocumentFormat.csv) is None:
310
+ registry.register(DataFileDocumentAdapter())
311
+ if registry.get_known(KnownDocumentFormat.html) is None:
312
+ registry.register(TextWebExportAdapter())
313
+ if registry.get_known(KnownDocumentFormat.python) is None:
314
+ registry.register(CodeFileDocumentAdapter())
315
+ registry.register(ImageScanDocumentAdapter())
316
+ registry.register(GeospatialDocumentAdapter())
317
+ registry.register(MediaAssetDocumentAdapter())
318
+ remaining_archive_formats = tuple(
319
+ known_format
320
+ for known_format in (
321
+ KnownDocumentFormat.epub,
322
+ KnownDocumentFormat.zip,
323
+ KnownDocumentFormat.seven_z,
324
+ KnownDocumentFormat.tar,
325
+ KnownDocumentFormat.gz,
326
+ )
327
+ if registry.get_known(known_format) is None
328
+ )
329
+ if remaining_archive_formats:
330
+ registry.register(ArchiveDocumentSetAdapter(known_formats=remaining_archive_formats))
331
+
332
+
333
+ def _register_promoted_archive_adapters(
334
+ registry: DocumentAdapterRegistry,
335
+ engine_registry: DocumentEngineRegistry,
336
+ ) -> set[DocumentFormat]:
337
+ """Register promoted archive engines individually."""
338
+ registered: set[DocumentFormat] = set()
339
+ for document_format in _ARCHIVE_PROMOTED_FORMATS:
340
+ engine = engine_registry.get(document_format)
341
+ if engine is None:
342
+ continue
343
+ _register_engine_backed_adapter(
344
+ registry,
345
+ document_format=document_format,
346
+ engine=engine,
347
+ )
348
+ registered.add(document_format)
349
+ return registered
350
+
351
+
352
+ def _register_promoted_odf_adapter(
353
+ registry: DocumentAdapterRegistry,
354
+ engine_registry: DocumentEngineRegistry,
355
+ ) -> None:
356
+ """Register one promoted adapter for ODT, ODS, and ODP engines."""
357
+ from ummaya.tools.documents.formats.odf import ( # noqa: PLC0415
358
+ OdfdoDocumentAdapter,
359
+ OdfdoPresentationDocumentEngine,
360
+ OdfdoSpreadsheetDocumentEngine,
361
+ OdfdoTextDocumentEngine,
362
+ )
363
+
364
+ text_engine = engine_registry.get(DocumentFormat.odt)
365
+ spreadsheet_engine = engine_registry.get(DocumentFormat.ods)
366
+ presentation_engine = engine_registry.get(DocumentFormat.odp)
367
+ registry.register(
368
+ OdfdoDocumentAdapter(
369
+ text_engine=(text_engine if isinstance(text_engine, OdfdoTextDocumentEngine) else None),
370
+ spreadsheet_engine=(
371
+ spreadsheet_engine
372
+ if isinstance(spreadsheet_engine, OdfdoSpreadsheetDocumentEngine)
373
+ else None
374
+ ),
375
+ presentation_engine=(
376
+ presentation_engine
377
+ if isinstance(presentation_engine, OdfdoPresentationDocumentEngine)
378
+ else None
379
+ ),
380
+ )
381
+ )
382
+
383
+
384
+ def _register_promoted_text_web_adapter(
385
+ registry: DocumentAdapterRegistry,
386
+ engine_registry: DocumentEngineRegistry,
387
+ ) -> None:
388
+ """Register one promoted adapter for text and web-export engines."""
389
+ from ummaya.tools.documents.formats.text_web import ( # noqa: PLC0415
390
+ TextWebDocumentAdapter,
391
+ TextWebDocumentEngine,
392
+ )
393
+
394
+ engines: dict[DocumentFormat, TextWebDocumentEngine] = {}
395
+ for document_format in _TEXT_WEB_PROMOTED_FORMATS:
396
+ engine = engine_registry.get(document_format)
397
+ if isinstance(engine, TextWebDocumentEngine):
398
+ engines[document_format] = engine
399
+ registry.register(TextWebDocumentAdapter(engines=engines or None))
400
+
401
+
402
+ def _register_promoted_data_adapter(
403
+ registry: DocumentAdapterRegistry,
404
+ engine_registry: DocumentEngineRegistry,
405
+ ) -> None:
406
+ """Register one promoted adapter for public-data engines."""
407
+ from ummaya.tools.documents.formats.data_file import ( # noqa: PLC0415
408
+ DataFileDocumentAdapter,
409
+ DataFileDocumentEngine,
410
+ )
411
+
412
+ engines: dict[DocumentFormat, DataFileDocumentEngine] = {}
413
+ for document_format in _DATA_PROMOTED_FORMATS:
414
+ engine = engine_registry.get(document_format)
415
+ if isinstance(engine, DataFileDocumentEngine):
416
+ engines[document_format] = engine
417
+ registry.register(DataFileDocumentAdapter(engines=engines or None))
418
+
419
+
420
+ def _register_promoted_code_adapter(
421
+ registry: DocumentAdapterRegistry,
422
+ engine_registry: DocumentEngineRegistry,
423
+ ) -> None:
424
+ """Register the promoted adapter for Python source attachments."""
425
+ from ummaya.tools.documents.formats.code_file import ( # noqa: PLC0415
426
+ PythonSourceDocumentAdapter,
427
+ PythonSourceDocumentEngine,
428
+ )
429
+
430
+ engine = engine_registry.get(DocumentFormat.python)
431
+ registry.register(
432
+ PythonSourceDocumentAdapter(
433
+ engine=(engine if isinstance(engine, PythonSourceDocumentEngine) else None)
434
+ )
435
+ )
436
+
437
+
438
+ def _register_engine_backed_adapter(
439
+ registry: DocumentAdapterRegistry,
440
+ *,
441
+ document_format: DocumentFormat,
442
+ engine: DocumentInspectionEngine,
443
+ ) -> None:
444
+ """Register the format adapter that owns one promoted engine."""
445
+ if document_format in {DocumentFormat.hwpx, DocumentFormat.owpml}:
446
+ from ummaya.tools.documents.formats.hwpx import HwpXDocumentAdapter # noqa: PLC0415
447
+
448
+ if registry.get_known(KnownDocumentFormat.hwpx) is not None:
449
+ return
450
+ registry.register(HwpXDocumentAdapter(inspection_engine=engine))
451
+ return
452
+ if document_format is DocumentFormat.docx:
453
+ from ummaya.tools.documents.formats.ooxml import DocxDocumentAdapter # noqa: PLC0415
454
+
455
+ registry.register(DocxDocumentAdapter(inspection_engine=engine))
456
+ return
457
+ if document_format is DocumentFormat.xlsx:
458
+ from ummaya.tools.documents.formats.ooxml import XlsxDocumentAdapter # noqa: PLC0415
459
+
460
+ registry.register(XlsxDocumentAdapter(inspection_engine=engine))
461
+ return
462
+ if document_format is DocumentFormat.pptx:
463
+ from ummaya.tools.documents.formats.ooxml import PptxDocumentAdapter # noqa: PLC0415
464
+
465
+ registry.register(PptxDocumentAdapter(inspection_engine=engine))
466
+ return
467
+ if document_format is DocumentFormat.pdf:
468
+ from ummaya.tools.documents.formats.pdf import PdfDocumentAdapter # noqa: PLC0415
469
+
470
+ registry.register(PdfDocumentAdapter(inspection_engine=engine))
471
+ return
472
+ registry.register(
473
+ EngineBackedDocumentAdapter(
474
+ adapter_id=f"{engine.engine_id}-adapter",
475
+ known_formats=_known_formats_for_promoted_format(document_format),
476
+ promoted_formats=(document_format,),
477
+ inspection_engine=engine,
478
+ )
479
+ )
480
+
481
+
482
+ def _known_formats_for_promoted_format(
483
+ document_format: DocumentFormat,
484
+ ) -> tuple[KnownDocumentFormat, ...]:
485
+ if document_format in {DocumentFormat.hwpx, DocumentFormat.owpml}:
486
+ return (KnownDocumentFormat.hwpx, KnownDocumentFormat.owpml)
487
+ return (KnownDocumentFormat(document_format.value),)
@@ -0,0 +1,167 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """Local archive/container promotion diagnostics."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import os
7
+ from collections.abc import Mapping, Sequence
8
+ from pathlib import Path
9
+ from shutil import which
10
+ from typing import Literal
11
+
12
+ from pydantic import BaseModel, ConfigDict, Field
13
+
14
+ from ummaya.tools.documents.models import DocumentFormatFamily, KnownDocumentFormat
15
+
16
+ ARCHIVE_CANDIDATE_ID = "archive-container-child-routing"
17
+ ARCHIVE_READ_ADAPTER_ID = "archive-document-set-read-only-adapter"
18
+ ARCHIVE_SOURCE_REFS = (
19
+ "upstream:python-3.12-zipfile",
20
+ "upstream:python-3.12-tarfile-data-filter",
21
+ "upstream:python-3.12-gzip",
22
+ "upstream:libarchive-bsdtar-7zip",
23
+ "upstream:owasp-file-upload-archive-limits",
24
+ )
25
+
26
+ ArchiveContainerProbeStatus = Literal["blocked", "candidate_available"]
27
+
28
+
29
+ class ArchiveContainerProbeReport(BaseModel):
30
+ """Current local availability of archive child-routing candidates."""
31
+
32
+ model_config = ConfigDict(frozen=True, extra="forbid")
33
+
34
+ candidate_id: str = Field(min_length=1)
35
+ known_format: KnownDocumentFormat
36
+ family: DocumentFormatFamily
37
+ status: ArchiveContainerProbeStatus
38
+ read_adapter_id: str = Field(min_length=1)
39
+ container_runtime_id: str = Field(min_length=1)
40
+ runtime_available: bool
41
+ runtime_executable: Path | None
42
+ child_routing_available: bool
43
+ direct_mutation_promoted: bool
44
+ reasons: tuple[str, ...]
45
+ required_gates: tuple[str, ...]
46
+ evidence_refs: tuple[str, ...]
47
+
48
+
49
+ def probe_archive_container_promotion(
50
+ *,
51
+ env: Mapping[str, str] | None = None,
52
+ search_path: Sequence[str] | None = None,
53
+ ) -> tuple[ArchiveContainerProbeReport, ...]:
54
+ """Report archive/container routing readiness without promoting repack writes."""
55
+ active_env = os.environ if env is None else env
56
+ bsdtar = _find_executable("bsdtar", active_env=active_env, search_path=search_path)
57
+ seven_z_available = bsdtar is not None
58
+ return (
59
+ _report(
60
+ known_format=KnownDocumentFormat.epub,
61
+ runtime_id="python-stdlib-zipfile-epub-container",
62
+ runtime_available=True,
63
+ runtime_executable=None,
64
+ child_routing_available=True,
65
+ reasons=(
66
+ "archive_child_derivative_promoted",
67
+ "epub_child_payload_writer_promoted",
68
+ "no_in_place_archive_mutation",
69
+ ),
70
+ ),
71
+ _report(
72
+ known_format=KnownDocumentFormat.zip,
73
+ runtime_id="python-stdlib-zipfile",
74
+ runtime_available=True,
75
+ runtime_executable=None,
76
+ child_routing_available=True,
77
+ reasons=(
78
+ "archive_child_derivative_promoted",
79
+ "no_in_place_archive_mutation",
80
+ ),
81
+ ),
82
+ _report(
83
+ known_format=KnownDocumentFormat.seven_z,
84
+ runtime_id="libarchive-bsdtar-7zip",
85
+ runtime_available=seven_z_available,
86
+ runtime_executable=bsdtar,
87
+ child_routing_available=seven_z_available,
88
+ reasons=(
89
+ (
90
+ "bsdtar_7zip_runtime_promoted"
91
+ if seven_z_available
92
+ else "bsdtar_7zip_runtime_not_found"
93
+ ),
94
+ "archive_child_derivative_promoted" if seven_z_available else "7z_repack_blocked",
95
+ "no_in_place_archive_mutation",
96
+ ),
97
+ ),
98
+ _report(
99
+ known_format=KnownDocumentFormat.tar,
100
+ runtime_id="python-stdlib-tarfile",
101
+ runtime_available=True,
102
+ runtime_executable=None,
103
+ child_routing_available=True,
104
+ reasons=(
105
+ "archive_child_derivative_promoted",
106
+ "tarfile_data_filter_required",
107
+ "no_in_place_archive_mutation",
108
+ ),
109
+ ),
110
+ _report(
111
+ known_format=KnownDocumentFormat.gz,
112
+ runtime_id="python-stdlib-gzip",
113
+ runtime_available=True,
114
+ runtime_executable=None,
115
+ child_routing_available=True,
116
+ reasons=(
117
+ "archive_child_derivative_promoted",
118
+ "gzip_single_child_candidate",
119
+ "no_in_place_archive_mutation",
120
+ ),
121
+ ),
122
+ )
123
+
124
+
125
+ def _report(
126
+ *,
127
+ known_format: KnownDocumentFormat,
128
+ runtime_id: str,
129
+ runtime_available: bool,
130
+ runtime_executable: Path | None,
131
+ child_routing_available: bool,
132
+ reasons: tuple[str, ...],
133
+ ) -> ArchiveContainerProbeReport:
134
+ return ArchiveContainerProbeReport(
135
+ candidate_id=ARCHIVE_CANDIDATE_ID,
136
+ known_format=known_format,
137
+ family=DocumentFormatFamily.archive,
138
+ status="candidate_available" if child_routing_available else "blocked",
139
+ read_adapter_id=ARCHIVE_READ_ADAPTER_ID,
140
+ container_runtime_id=runtime_id,
141
+ runtime_available=runtime_available,
142
+ runtime_executable=runtime_executable,
143
+ child_routing_available=child_routing_available,
144
+ direct_mutation_promoted=False,
145
+ reasons=reasons,
146
+ required_gates=(
147
+ "archive_intake_security_gate",
148
+ "archive_child_routing_gate",
149
+ "child_document_promotion_gate",
150
+ "archive_repack_write_gate",
151
+ "archive_runtime_completion_promotion",
152
+ ),
153
+ evidence_refs=ARCHIVE_SOURCE_REFS,
154
+ )
155
+
156
+
157
+ def _find_executable(
158
+ name: str,
159
+ *,
160
+ active_env: Mapping[str, str],
161
+ search_path: Sequence[str] | None,
162
+ ) -> Path | None:
163
+ path_env = os.pathsep.join(search_path) if search_path is not None else active_env.get("PATH")
164
+ if not path_env:
165
+ return None
166
+ found = which(name, path=path_env)
167
+ return Path(found).resolve() if found else None