ummaya 0.2.4 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (482) hide show
  1. package/README.md +15 -2
  2. package/bin/ummaya +10 -1
  3. package/bun.lock +180 -244
  4. package/npm-shrinkwrap.json +760 -1760
  5. package/package.json +39 -22
  6. package/prompts/manifest.yaml +1 -1
  7. package/prompts/system_v1.md +1 -0
  8. package/pyproject.toml +27 -2
  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/_canonical/baselines.yaml +113 -0
  12. package/src/ummaya/engine/engine.py +29 -132
  13. package/src/ummaya/evidence/__init__.py +21 -2
  14. package/src/ummaya/evidence/dataset_contract.py +193 -0
  15. package/src/ummaya/evidence/document_authoring_cases.py +33 -0
  16. package/src/ummaya/evidence/document_harness.py +313 -0
  17. package/src/ummaya/evidence/document_viewer_ux.py +391 -0
  18. package/src/ummaya/evidence/gates.py +70 -0
  19. package/src/ummaya/evidence/json_types.py +20 -0
  20. package/src/ummaya/evidence/models.py +88 -1
  21. package/src/ummaya/evidence/output_payload.py +89 -0
  22. package/src/ummaya/evidence/payload_documents.py +233 -0
  23. package/src/ummaya/evidence/route_contracts.py +224 -0
  24. package/src/ummaya/evidence/route_helpers.py +150 -0
  25. package/src/ummaya/evidence/runner.py +81 -212
  26. package/src/ummaya/evidence/source_provenance.py +246 -0
  27. package/src/ummaya/evidence/source_provenance_redaction.py +176 -0
  28. package/src/ummaya/evidence/tool_layer.py +39 -0
  29. package/src/ummaya/evidence/tool_layer_models.py +151 -0
  30. package/src/ummaya/ipc/adapter_manifest_emitter.py +26 -10
  31. package/src/ummaya/ipc/document_intent_normalization.py +185 -0
  32. package/src/ummaya/ipc/frame_schema.py +5 -5
  33. package/src/ummaya/ipc/route_diagnostics.py +73 -0
  34. package/src/ummaya/ipc/stdio.py +1109 -477
  35. package/src/ummaya/llm/client.py +102 -3
  36. package/src/ummaya/llm/config.py +8 -3
  37. package/src/ummaya/primitives/__init__.py +6 -2
  38. package/src/ummaya/primitives/delegation.py +1 -1
  39. package/src/ummaya/primitives/document.py +28 -0
  40. package/src/ummaya/settings.py +0 -3
  41. package/src/ummaya/tools/discovery_bridge.py +17 -1
  42. package/src/ummaya/tools/documents/__init__.py +297 -0
  43. package/src/ummaya/tools/documents/adapter_registry.py +487 -0
  44. package/src/ummaya/tools/documents/archive_container_probe.py +167 -0
  45. package/src/ummaya/tools/documents/artifact_store.py +454 -0
  46. package/src/ummaya/tools/documents/authoring.py +283 -0
  47. package/src/ummaya/tools/documents/baselines.py +132 -0
  48. package/src/ummaya/tools/documents/capability.py +331 -0
  49. package/src/ummaya/tools/documents/contracts.py +112 -0
  50. package/src/ummaya/tools/documents/conversion.py +521 -0
  51. package/src/ummaya/tools/documents/diff.py +275 -0
  52. package/src/ummaya/tools/documents/engines.py +163 -0
  53. package/src/ummaya/tools/documents/evaluation.py +291 -0
  54. package/src/ummaya/tools/documents/explicit_values.py +108 -0
  55. package/src/ummaya/tools/documents/fixtures.py +174 -0
  56. package/src/ummaya/tools/documents/format_completion_audit.py +471 -0
  57. package/src/ummaya/tools/documents/formats/__init__.py +2 -0
  58. package/src/ummaya/tools/documents/formats/archive.py +528 -0
  59. package/src/ummaya/tools/documents/formats/base.py +41 -0
  60. package/src/ummaya/tools/documents/formats/code_file.py +211 -0
  61. package/src/ummaya/tools/documents/formats/data_file.py +272 -0
  62. package/src/ummaya/tools/documents/formats/hwp.py +284 -0
  63. package/src/ummaya/tools/documents/formats/hwpx.py +1837 -0
  64. package/src/ummaya/tools/documents/formats/odf.py +435 -0
  65. package/src/ummaya/tools/documents/formats/ooxml.py +1030 -0
  66. package/src/ummaya/tools/documents/formats/passive.py +766 -0
  67. package/src/ummaya/tools/documents/formats/pdf.py +702 -0
  68. package/src/ummaya/tools/documents/formats/text_web.py +268 -0
  69. package/src/ummaya/tools/documents/hwp_conversion_probe.py +178 -0
  70. package/src/ummaya/tools/documents/hwp_direct_candidate.py +141 -0
  71. package/src/ummaya/tools/documents/inspection.py +289 -0
  72. package/src/ummaya/tools/documents/intake.py +1079 -0
  73. package/src/ummaya/tools/documents/legacy_office_promotion_probe.py +366 -0
  74. package/src/ummaya/tools/documents/models.py +1598 -0
  75. package/src/ummaya/tools/documents/odf_promotion_probe.py +167 -0
  76. package/src/ummaya/tools/documents/orchestrator.py +96 -0
  77. package/src/ummaya/tools/documents/passive_capability_probe.py +251 -0
  78. package/src/ummaya/tools/documents/patch.py +170 -0
  79. package/src/ummaya/tools/documents/pdfa_conformance.py +284 -0
  80. package/src/ummaya/tools/documents/pdfa_promotion_probe.py +198 -0
  81. package/src/ummaya/tools/documents/permissions.py +110 -0
  82. package/src/ummaya/tools/documents/planner.py +616 -0
  83. package/src/ummaya/tools/documents/registry.py +2733 -0
  84. package/src/ummaya/tools/documents/render.py +978 -0
  85. package/src/ummaya/tools/documents/render_comparison.py +113 -0
  86. package/src/ummaya/tools/documents/render_comparison_models.py +74 -0
  87. package/src/ummaya/tools/documents/render_comparison_regions.py +73 -0
  88. package/src/ummaya/tools/documents/render_comparison_style.py +161 -0
  89. package/src/ummaya/tools/documents/reread.py +157 -0
  90. package/src/ummaya/tools/documents/runtime_authoring.py +244 -0
  91. package/src/ummaya/tools/documents/runtime_authoring_bundle.py +76 -0
  92. package/src/ummaya/tools/documents/scorecard.py +184 -0
  93. package/src/ummaya/tools/documents/socratic_planner.py +193 -0
  94. package/src/ummaya/tools/documents/style.py +48 -0
  95. package/src/ummaya/tools/documents/tool_defs.py +523 -0
  96. package/src/ummaya/tools/documents/validate.py +347 -0
  97. package/src/ummaya/tools/executor.py +29 -0
  98. package/src/ummaya/tools/live_proxy.py +0 -3
  99. package/src/ummaya/tools/models.py +5 -1
  100. package/src/ummaya/tools/register_all.py +8 -0
  101. package/src/ummaya/tools/registry.py +10 -1
  102. package/src/ummaya/tools/routing/__init__.py +59 -0
  103. package/src/ummaya/tools/routing/builder.py +105 -0
  104. package/src/ummaya/tools/routing/cards.py +29 -0
  105. package/src/ummaya/tools/routing/decision_service.py +534 -0
  106. package/src/ummaya/tools/routing/decision_types.py +74 -0
  107. package/src/ummaya/tools/routing/feasibility.py +122 -0
  108. package/src/ummaya/tools/routing/intent.py +17 -0
  109. package/src/ummaya/tools/routing/intent_extractor.py +207 -0
  110. package/src/ummaya/tools/routing/intent_patterns.py +160 -0
  111. package/src/ummaya/tools/routing/intent_public_data.py +150 -0
  112. package/src/ummaya/tools/routing/intent_types.py +48 -0
  113. package/src/ummaya/tools/routing/lint.py +78 -0
  114. package/src/ummaya/tools/routing/metadata.py +174 -0
  115. package/src/ummaya/tools/routing/projection.py +340 -0
  116. package/src/ummaya/tools/routing/retrieval_policy.py +629 -0
  117. package/src/ummaya/tools/routing/schema.py +81 -0
  118. package/src/ummaya/tools/routing/types.py +96 -0
  119. package/src/ummaya/tools/routing_index.py +2 -2
  120. package/src/ummaya/tools/search.py +34 -746
  121. package/tests/fixtures/documents/public_forms/baselines.yaml +113 -0
  122. package/tui/bun.lock +126 -305
  123. package/tui/package.json +35 -22
  124. package/tui/src/.cc-byte-identical-whitelist.yaml +266 -0
  125. package/tui/src/QueryEngine.ts +12 -8
  126. package/tui/src/bridge/inboundAttachments.ts +3 -3
  127. package/tui/src/cli/handlers/auth.ts +3 -12
  128. package/tui/src/cli/handlers/mcp.tsx +0 -1
  129. package/tui/src/cli/print.ts +8 -9
  130. package/tui/src/commands/insights.ts +1 -1
  131. package/tui/src/commands/install-github-app/types.ts +8 -30
  132. package/tui/src/commands/plugin/types.ts +6 -28
  133. package/tui/src/commands/plugin/unifiedTypes.ts +4 -26
  134. package/tui/src/commands/rename/generateSessionName.ts +1 -1
  135. package/tui/src/components/Feedback.tsx +1 -1
  136. package/tui/src/components/LogoV2/EmergencyTip.tsx +11 -2
  137. package/tui/src/components/LogoV2/WelcomeV2.tsx +1 -3
  138. package/tui/src/components/ScrollKeybindingHandler.tsx +6 -6
  139. package/tui/src/components/Spinner/types.ts +6 -28
  140. package/tui/src/components/agents/generateAgent.ts +1 -1
  141. package/tui/src/components/agents/new-agent-creation/types.ts +4 -26
  142. package/tui/src/components/config/EnvSecretIsolatedEditor.tsx +1 -1
  143. package/tui/src/components/mcp/types.ts +16 -38
  144. package/tui/src/components/messages/AssistantToolUseMessage.tsx +3 -2
  145. package/tui/src/components/messages/UserCrossSessionMessage.ts +16 -4
  146. package/tui/src/components/messages/UserForkBoilerplateMessage.ts +16 -4
  147. package/tui/src/components/messages/UserGitHubWebhookMessage.ts +16 -4
  148. package/tui/src/components/messages/UserToolResultMessage/utils.tsx +3 -2
  149. package/tui/src/components/permissions/MonitorPermissionRequest/MonitorPermissionRequest.ts +9 -4
  150. package/tui/src/components/permissions/ReviewArtifactPermissionRequest/ReviewArtifactPermissionRequest.ts +9 -4
  151. package/tui/src/components/primitive/DocumentSocraticReviewBlock.tsx +129 -0
  152. package/tui/src/components/primitive/DocumentToolResultCard.tsx +224 -0
  153. package/tui/src/components/primitive/documentSocraticReview.ts +215 -0
  154. package/tui/src/components/primitive/index.tsx +43 -1
  155. package/tui/src/components/primitive/types.ts +137 -0
  156. package/tui/src/components/ui/option.ts +4 -26
  157. package/tui/src/constants/common.ts +0 -2
  158. package/tui/src/constants/prompts.ts +4 -3
  159. package/tui/src/constants/querySource.ts +4 -26
  160. package/tui/src/entrypoints/sdk/controlTypes.ts +26 -48
  161. package/tui/src/entrypoints/sdk/coreTypes.generated.ts +3 -25
  162. package/tui/src/entrypoints/sdk/runtimeTypes.ts +38 -60
  163. package/tui/src/entrypoints/sdk/sdkUtilityTypes.ts +4 -26
  164. package/tui/src/entrypoints/sdk/settingsTypes.generated.ts +3 -25
  165. package/tui/src/entrypoints/sdk/toolTypes.ts +3 -25
  166. package/tui/src/hooks/toolPermission/handlers/interactiveHandler.ts +10 -0
  167. package/tui/src/hooks/useApiKeyVerification.ts +1 -1
  168. package/tui/src/hooks/useVirtualScroll.ts +1 -1
  169. package/tui/src/ink/ink.tsx +33 -14
  170. package/tui/src/ink/reconciler.ts +2 -3
  171. package/tui/src/ink/render-to-screen.ts +30 -10
  172. package/tui/src/ipc/bridge.ts +62 -15
  173. package/tui/src/ipc/bridgeSingleton.ts +5 -1
  174. package/tui/src/ipc/codec.ts +3 -3
  175. package/tui/src/ipc/frames.generated.ts +12 -12
  176. package/tui/src/ipc/llmClient.ts +151 -27
  177. package/tui/src/ipc/schema/frame.schema.json +1 -1
  178. package/tui/src/keybindings/defaultBindings.ts +4 -0
  179. package/tui/src/main.tsx +32 -15
  180. package/tui/src/native-ts/file-index/index.ts +33 -3
  181. package/tui/src/observability/surface.ts +2 -2
  182. package/tui/src/probes/toolRegistryProbe.tsx +3 -1
  183. package/tui/src/projectOnboardingState.ts +7 -6
  184. package/tui/src/query/chatMessageTypes.ts +18 -0
  185. package/tui/src/query/chatMessagesBuilder.ts +1 -1
  186. package/tui/src/query/deps.ts +1 -1
  187. package/tui/src/query/messageGuards.ts +106 -0
  188. package/tui/src/query/publicDataTerminalRepair.ts +384 -0
  189. package/tui/src/query/run.ts +1075 -0
  190. package/tui/src/query/supportBoundary.ts +168 -0
  191. package/tui/src/query/toolResultErrors.ts +103 -0
  192. package/tui/src/query/toolRunner.ts +687 -0
  193. package/tui/src/query/unavailableToolRepair.ts +118 -0
  194. package/tui/src/query.ts +9 -2186
  195. package/tui/src/screens/REPL.tsx +40 -29
  196. package/tui/src/services/api/adapterManifest.ts +4 -0
  197. package/tui/src/services/api/backendChat/events.ts +117 -0
  198. package/tui/src/services/api/backendChat/finalMessage.ts +40 -0
  199. package/tui/src/services/api/backendChat/frame.ts +9 -0
  200. package/tui/src/services/api/backendChat/streaming.ts +430 -0
  201. package/tui/src/services/api/backendChat/types.ts +62 -0
  202. package/tui/src/services/api/backendChat.ts +1 -0
  203. package/tui/src/services/api/client.ts +65 -2
  204. package/tui/src/services/api/errorUtils.ts +5 -5
  205. package/tui/src/services/api/errors.ts +1 -1
  206. package/tui/src/services/api/logging.ts +1 -1
  207. package/tui/src/services/api/ummaya/evidence.ts +194 -0
  208. package/tui/src/services/api/ummaya/messages.ts +255 -0
  209. package/tui/src/services/api/ummaya/nonStreaming.ts +66 -0
  210. package/tui/src/services/api/ummaya/provider.ts +200 -0
  211. package/tui/src/services/api/ummaya/reasoning.ts +24 -0
  212. package/tui/src/services/api/ummaya/request.ts +200 -0
  213. package/tui/src/services/api/ummaya/selectionContext.ts +240 -0
  214. package/tui/src/services/api/ummaya/streaming.ts +365 -0
  215. package/tui/src/services/api/ummaya/streamingPayload.ts +129 -0
  216. package/tui/src/services/api/ummaya/streamingReader.ts +40 -0
  217. package/tui/src/services/api/ummaya/toolSelection.ts +217 -0
  218. package/tui/src/services/api/ummaya/types.ts +110 -0
  219. package/tui/src/services/api/ummaya/usage.ts +30 -0
  220. package/tui/src/services/api/ummaya.ts +26 -418
  221. package/tui/src/services/api/withRetry.ts +1 -1
  222. package/tui/src/services/awaySummary.ts +2 -2
  223. package/tui/src/services/claudeAiLimits.ts +1 -1
  224. package/tui/src/services/compact/autoCompact.ts +1 -1
  225. package/tui/src/services/compact/compact.ts +1 -1
  226. package/tui/src/services/lsp/types.ts +8 -30
  227. package/tui/src/services/tips/types.ts +6 -28
  228. package/tui/src/services/tokenEstimation.ts +1 -1
  229. package/tui/src/services/toolRegistry/bootGuard.ts +5 -5
  230. package/tui/src/services/toolUseSummary/toolUseSummaryGenerator.ts +1 -1
  231. package/tui/src/services/tools/toolExecution.ts +94 -1
  232. package/tui/src/store/pendingPermissionSlot.ts +1 -1
  233. package/tui/src/store/session-store.ts +10 -36
  234. package/tui/src/stubs/any-stub.ts +15 -10
  235. package/tui/src/stubs/color-diff-napi.ts +37 -23
  236. package/tui/src/stubs/globals.d.ts +3 -3
  237. package/tui/src/stubs/macro-preload.ts +23 -12
  238. package/tui/src/tools/AdapterTool/AdapterTool.ts +1207 -714
  239. package/tui/src/tools/AdapterTool/routeDiagnostics.ts +75 -0
  240. package/tui/src/tools/AgentTool/AgentTool.tsx +84 -1371
  241. package/tui/src/tools/AgentTool/agentToolHandoff.ts +114 -0
  242. package/tui/src/tools/AgentTool/agentToolPartialResult.ts +16 -0
  243. package/tui/src/tools/AgentTool/agentToolProgress.ts +32 -0
  244. package/tui/src/tools/AgentTool/agentToolResolver.ts +161 -0
  245. package/tui/src/tools/AgentTool/agentToolResult.ts +163 -0
  246. package/tui/src/tools/AgentTool/agentToolUtils.ts +14 -686
  247. package/tui/src/tools/AgentTool/asyncAgentLifecycle.ts +208 -0
  248. package/tui/src/tools/AgentTool/asyncLifecycle.ts +153 -0
  249. package/tui/src/tools/AgentTool/backgroundedCompletion.ts +126 -0
  250. package/tui/src/tools/AgentTool/backgroundedLifecycle.ts +174 -0
  251. package/tui/src/tools/AgentTool/foregroundBackground.ts +83 -0
  252. package/tui/src/tools/AgentTool/foregroundDrain.tsx +133 -0
  253. package/tui/src/tools/AgentTool/foregroundFinalize.ts +98 -0
  254. package/tui/src/tools/AgentTool/foregroundLifecycle.tsx +237 -0
  255. package/tui/src/tools/AgentTool/foregroundProgress.tsx +169 -0
  256. package/tui/src/tools/AgentTool/foregroundTask.ts +89 -0
  257. package/tui/src/tools/AgentTool/forkSubagent.ts +1 -12
  258. package/tui/src/tools/AgentTool/forkSubagentGate.ts +34 -0
  259. package/tui/src/tools/AgentTool/launchRouting.ts +203 -0
  260. package/tui/src/tools/AgentTool/lifecycle.ts +244 -0
  261. package/tui/src/tools/AgentTool/mcpRouting.ts +73 -0
  262. package/tui/src/tools/AgentTool/orchestrationSupport.ts +70 -0
  263. package/tui/src/tools/AgentTool/permissions.ts +39 -0
  264. package/tui/src/tools/AgentTool/promptSetup.ts +181 -0
  265. package/tui/src/tools/AgentTool/remoteRouting.ts +62 -0
  266. package/tui/src/tools/AgentTool/resultMapping.ts +116 -0
  267. package/tui/src/tools/AgentTool/resumeAgent.ts +39 -107
  268. package/tui/src/tools/AgentTool/resumeAgentHelpers.ts +140 -0
  269. package/tui/src/tools/AgentTool/runAgent.ts +1 -1
  270. package/tui/src/tools/AgentTool/runtimeConfig.ts +57 -0
  271. package/tui/src/tools/AgentTool/schemas.ts +196 -0
  272. package/tui/src/tools/AgentTool/sourceVerificationPropagation.ts +263 -0
  273. package/tui/src/tools/AgentTool/worktreeLifecycle.ts +105 -0
  274. package/tui/src/tools/AskUserQuestionTool/AskUserQuestionTool.tsx +174 -202
  275. package/tui/src/tools/BashTool/BashTool.tsx +71 -1072
  276. package/tui/src/tools/BashTool/bashCommandHelpers.ts +12 -12
  277. package/tui/src/tools/BashTool/bashPermissions/astPreflight.ts +173 -0
  278. package/tui/src/tools/BashTool/bashPermissions/classifierChecks.ts +199 -0
  279. package/tui/src/tools/BashTool/bashPermissions/compoundGuards.ts +53 -0
  280. package/tui/src/tools/BashTool/bashPermissions/constants.ts +99 -0
  281. package/tui/src/tools/BashTool/bashPermissions/index.ts +38 -0
  282. package/tui/src/tools/BashTool/bashPermissions/legacyMisparsing.ts +62 -0
  283. package/tui/src/tools/BashTool/bashPermissions/main.ts +135 -0
  284. package/tui/src/tools/BashTool/bashPermissions/normalizedCommands.ts +33 -0
  285. package/tui/src/tools/BashTool/bashPermissions/operatorFlow.ts +98 -0
  286. package/tui/src/tools/BashTool/bashPermissions/permissionChecks.ts +200 -0
  287. package/tui/src/tools/BashTool/bashPermissions/prefixSuggestions.ts +88 -0
  288. package/tui/src/tools/BashTool/bashPermissions/promptClassifierRules.ts +125 -0
  289. package/tui/src/tools/BashTool/bashPermissions/ruleDelegates.ts +19 -0
  290. package/tui/src/tools/BashTool/bashPermissions/ruleMatching.ts +145 -0
  291. package/tui/src/tools/BashTool/bashPermissions/sandboxAutoAllow.ts +75 -0
  292. package/tui/src/tools/BashTool/bashPermissions/subcommandFlow.ts +205 -0
  293. package/tui/src/tools/BashTool/bashPermissions/subcommandGuards.ts +73 -0
  294. package/tui/src/tools/BashTool/bashPermissions/subcommandResultHelpers.ts +116 -0
  295. package/tui/src/tools/BashTool/bashPermissions/types.ts +26 -0
  296. package/tui/src/tools/BashTool/bashPermissions/wrapperStripping.ts +139 -0
  297. package/tui/src/tools/BashTool/bashPermissions.ts +26 -2621
  298. package/tui/src/tools/BashTool/call.ts +202 -0
  299. package/tui/src/tools/BashTool/callLoader.ts +35 -0
  300. package/tui/src/tools/BashTool/commandClassification.ts +151 -0
  301. package/tui/src/tools/BashTool/commandClassificationLoader.ts +40 -0
  302. package/tui/src/tools/BashTool/cwdReset.ts +33 -0
  303. package/tui/src/tools/BashTool/lineTruncation.ts +11 -0
  304. package/tui/src/tools/BashTool/modeValidation.ts +13 -1
  305. package/tui/src/tools/BashTool/outputPersistence.ts +42 -0
  306. package/tui/src/tools/BashTool/permissionClassification.ts +66 -0
  307. package/tui/src/tools/BashTool/permissionLoader.ts +44 -0
  308. package/tui/src/tools/BashTool/resultLoader.ts +29 -0
  309. package/tui/src/tools/BashTool/resultMapping.ts +83 -0
  310. package/tui/src/tools/BashTool/sandboxPolicy.ts +79 -0
  311. package/tui/src/tools/BashTool/schemas.ts +65 -0
  312. package/tui/src/tools/BashTool/sedEditExecution.ts +59 -0
  313. package/tui/src/tools/BashTool/shellExecution.tsx +245 -0
  314. package/tui/src/tools/BashTool/shellOutputUtils.ts +85 -0
  315. package/tui/src/tools/BashTool/shellPermissionGauntlet.ts +97 -0
  316. package/tui/src/tools/BashTool/uiLoader.ts +37 -0
  317. package/tui/src/tools/BriefTool/upload.ts +1 -1
  318. package/tui/src/tools/CalculatorTool/parser.ts +2 -2
  319. package/tui/src/tools/DocumentPrimitive/DocumentPrimitive.ts +262 -0
  320. package/tui/src/tools/DocumentPrimitive/dispatchNormalization.ts +270 -0
  321. package/tui/src/tools/DocumentPrimitive/documentDestinationPath.ts +18 -0
  322. package/tui/src/tools/DocumentPrimitive/documentMutationGuard.ts +22 -0
  323. package/tui/src/tools/DocumentPrimitive/documentPatchNormalization.ts +248 -0
  324. package/tui/src/tools/DocumentPrimitive/documentSourceVerification.ts +245 -0
  325. package/tui/src/tools/DocumentPrimitive/documentSourceVerificationFields.ts +103 -0
  326. package/tui/src/tools/DocumentPrimitive/modelVisibleOutput.ts +40 -0
  327. package/tui/src/tools/DocumentPrimitive/prompt.ts +35 -0
  328. package/tui/src/tools/FileEditTool/FileEditTool.ts +9 -507
  329. package/tui/src/tools/FileEditTool/call.ts +228 -0
  330. package/tui/src/tools/FileEditTool/validateInput.ts +196 -0
  331. package/tui/src/tools/FileReadTool/imageProcessor.ts +13 -0
  332. package/tui/src/tools/FileWriteTool/FileWriteTool.ts +7 -300
  333. package/tui/src/tools/FileWriteTool/call.ts +223 -0
  334. package/tui/src/tools/FileWriteTool/validateInput.ts +80 -0
  335. package/tui/src/tools/ListMcpResourcesTool/ListMcpResourcesTool.ts +19 -3
  336. package/tui/src/tools/LookupPrimitive/LookupPrimitive.ts +25 -32
  337. package/tui/src/tools/LookupPrimitive/prompt.ts +0 -2
  338. package/tui/src/tools/MCPTool/trustPolicy.ts +118 -0
  339. package/tui/src/tools/McpAuthTool/McpAuthTool.ts +21 -3
  340. package/tui/src/tools/NotebookEditTool/NotebookEditTool.ts +7 -326
  341. package/tui/src/tools/NotebookEditTool/call.ts +254 -0
  342. package/tui/src/tools/NotebookEditTool/notebookModel.ts +51 -0
  343. package/tui/src/tools/NotebookEditTool/validateInput.ts +142 -0
  344. package/tui/src/tools/PowerShellTool/PowerShellTool.tsx +46 -937
  345. package/tui/src/tools/PowerShellTool/acceptEditsCommandValidation.ts +162 -0
  346. package/tui/src/tools/PowerShellTool/call.ts +179 -0
  347. package/tui/src/tools/PowerShellTool/callLoader.ts +37 -0
  348. package/tui/src/tools/PowerShellTool/commandClassification.ts +86 -0
  349. package/tui/src/tools/PowerShellTool/modeValidation.ts +25 -332
  350. package/tui/src/tools/PowerShellTool/outputPersistence.ts +42 -0
  351. package/tui/src/tools/PowerShellTool/permissionClassification.ts +28 -0
  352. package/tui/src/tools/PowerShellTool/resultLoader.ts +31 -0
  353. package/tui/src/tools/PowerShellTool/resultMapping.ts +75 -0
  354. package/tui/src/tools/PowerShellTool/schemas.ts +40 -0
  355. package/tui/src/tools/PowerShellTool/shellExecution.tsx +258 -0
  356. package/tui/src/tools/PowerShellTool/symlinkModeValidation.ts +44 -0
  357. package/tui/src/tools/PowerShellTool/uiLoader.ts +37 -0
  358. package/tui/src/tools/PowerShellTool/validation.ts +39 -0
  359. package/tui/src/tools/ReadMcpResourceTool/ReadMcpResourceTool.ts +19 -3
  360. package/tui/src/tools/ResolveLocationPrimitive/ResolveLocationPrimitive.ts +1 -11
  361. package/tui/src/tools/ResolveLocationPrimitive/prompt.ts +2 -6
  362. package/tui/src/tools/SkillTool/SkillTool.ts +2 -2
  363. package/tui/src/tools/SubmitPrimitive/SubmitPrimitive.ts +27 -10
  364. package/tui/src/tools/TaskCreateTool/TaskCreateTool.ts +16 -2
  365. package/tui/src/tools/TaskGetTool/TaskGetTool.ts +23 -3
  366. package/tui/src/tools/TaskListTool/TaskListTool.ts +22 -4
  367. package/tui/src/tools/TaskOutputTool/TaskOutputTool.tsx +46 -547
  368. package/tui/src/tools/TaskOutputTool/lookup.ts +216 -0
  369. package/tui/src/tools/TaskOutputTool/render.tsx +257 -0
  370. package/tui/src/tools/TaskOutputTool/schemas.ts +55 -0
  371. package/tui/src/tools/TaskOutputTool/serialization.ts +36 -0
  372. package/tui/src/tools/TaskStopTool/TaskStopTool.ts +10 -0
  373. package/tui/src/tools/TaskUpdateTool/TaskUpdateTool.ts +14 -364
  374. package/tui/src/tools/TaskUpdateTool/completion.ts +62 -0
  375. package/tui/src/tools/TaskUpdateTool/schemas.ts +62 -0
  376. package/tui/src/tools/TaskUpdateTool/serialization.ts +46 -0
  377. package/tui/src/tools/TaskUpdateTool/statusUpdate.ts +247 -0
  378. package/tui/src/tools/TodoWriteTool/TodoWriteTool.ts +21 -2
  379. package/tui/src/tools/ToolSearchTool/ToolSearchTool.ts +21 -302
  380. package/tui/src/tools/ToolSearchTool/ccSupportTools.ts +223 -0
  381. package/tui/src/tools/ToolSearchTool/descriptionCache.ts +50 -0
  382. package/tui/src/tools/ToolSearchTool/keywordSearch.ts +216 -0
  383. package/tui/src/tools/ToolSearchTool/prompt.ts +10 -4
  384. package/tui/src/tools/ToolSearchTool/resultMapping.ts +30 -0
  385. package/tui/src/tools/ToolSearchTool/schemas.ts +30 -0
  386. package/tui/src/tools/ToolSearchTool/searchPool.ts +47 -0
  387. package/tui/src/tools/ToolSearchTool/supportIntentHints.ts +140 -0
  388. package/tui/src/tools/TranslateTool/TranslateTool.ts +1 -1
  389. package/tui/src/tools/VerifyPrimitive/VerifyPrimitive.ts +2 -1
  390. package/tui/src/tools/WebFetchTool/WebFetchTool.ts +43 -138
  391. package/tui/src/tools/WebFetchTool/call.ts +227 -0
  392. package/tui/src/tools/WebFetchTool/resolvedAddressSafety.ts +78 -0
  393. package/tui/src/tools/WebFetchTool/sourceVerification.ts +204 -0
  394. package/tui/src/tools/WebFetchTool/types.ts +23 -0
  395. package/tui/src/tools/WebFetchTool/urlSafety.ts +181 -0
  396. package/tui/src/tools/WebFetchTool/utils.ts +1 -1
  397. package/tui/src/tools/WebSearchTool/UI.tsx +0 -1
  398. package/tui/src/tools/WebSearchTool/WebSearchTool.ts +9 -313
  399. package/tui/src/tools/WebSearchTool/call.ts +33 -0
  400. package/tui/src/tools/WebSearchTool/responseMapping.ts +190 -0
  401. package/tui/src/tools/WebSearchTool/resultBlock.ts +47 -0
  402. package/tui/src/tools/WebSearchTool/schemas.ts +47 -0
  403. package/tui/src/tools/WebSearchTool/toolSchema.ts +12 -0
  404. package/tui/src/tools/WorkspaceToolAdapter/WorkspaceToolAdapter.ts +79 -0
  405. package/tui/src/tools/WorkspaceToolAdapter/allowedRootPolicy.ts +85 -0
  406. package/tui/src/tools/WorkspaceToolAdapter/documentFormatGuards.ts +73 -0
  407. package/tui/src/tools/WorkspaceToolAdapter/inputNormalization.ts +105 -0
  408. package/tui/src/tools/WorkspaceToolAdapter/mcpExposurePolicy.ts +64 -0
  409. package/tui/src/tools/WorkspaceToolAdapter/toolDefFactory.ts +215 -0
  410. package/tui/src/tools/WorkspaceToolAdapter/toolNames.ts +6 -0
  411. package/tui/src/tools/WorkspaceToolAdapter/workspacePolicy.ts +15 -0
  412. package/tui/src/tools/_shared/dispatchPrimitive.ts +6 -6
  413. package/tui/src/tools/_shared/documentChangeToPatch.ts +125 -0
  414. package/tui/src/tools/_shared/documentDispatchArguments.ts +87 -0
  415. package/tui/src/tools/_shared/documentPrimitiveTimeout.ts +13 -0
  416. package/tui/src/tools/_shared/documentToolResultRender.ts +98 -0
  417. package/tui/src/tools/_shared/pendingCallRegistry.ts +1 -6
  418. package/tui/src/tools/_shared/rootPrimitiveInput.ts +1 -0
  419. package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPatterns.ts +58 -0
  420. package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPrompt.ts +271 -0
  421. package/tui/src/tools/_shared/toolChoiceRepair/documentRepair.ts +452 -0
  422. package/tui/src/tools/_shared/toolChoiceRepair/messageAccess.ts +80 -0
  423. package/tui/src/tools/_shared/toolChoiceRepair/publicDataRepair.ts +92 -0
  424. package/tui/src/tools/_shared/toolChoiceRepair/supportRepair.ts +135 -0
  425. package/tui/src/tools/_shared/toolChoiceRepair.ts +55 -860
  426. package/tui/src/tools/shared/mockDisclaimer.ts +1 -1
  427. package/tui/src/tools.ts +39 -190
  428. package/tui/src/types/fileSuggestion.ts +4 -26
  429. package/tui/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +186 -148
  430. package/tui/src/types/generated/events_mono/common/v1/auth.ts +25 -11
  431. package/tui/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +47 -30
  432. package/tui/src/types/generated/google/protobuf/timestamp.ts +21 -7
  433. package/tui/src/types/message.ts +80 -102
  434. package/tui/src/types/messageQueueTypes.ts +6 -28
  435. package/tui/src/types/notebook.ts +16 -38
  436. package/tui/src/types/statusLine.ts +4 -26
  437. package/tui/src/types/tools.ts +24 -46
  438. package/tui/src/types/utils.ts +6 -28
  439. package/tui/src/upstreamproxy/relay.ts +7 -3
  440. package/tui/src/upstreamproxy/upstreamproxy.ts +1 -1
  441. package/tui/src/utils/assistantMessageFactories.ts +9 -3
  442. package/tui/src/utils/auth.ts +129 -139
  443. package/tui/src/utils/bash/ast.ts +23 -23
  444. package/tui/src/utils/bash/bashParser.ts +5 -5
  445. package/tui/src/utils/billing.ts +1 -1
  446. package/tui/src/utils/claudeDesktop.ts +4 -4
  447. package/tui/src/utils/collapseReadSearch.ts +3 -3
  448. package/tui/src/utils/cronTasks.ts +1 -1
  449. package/tui/src/utils/execFileNoThrow.ts +1 -1
  450. package/tui/src/utils/filePersistence/types.ts +16 -38
  451. package/tui/src/utils/forkedAgent.ts +1 -1
  452. package/tui/src/utils/gracefulShutdown.ts +4 -4
  453. package/tui/src/utils/heapDumpService.ts +12 -8
  454. package/tui/src/utils/hooks/apiQueryHookHelper.ts +1 -1
  455. package/tui/src/utils/hooks/execPromptHook.ts +1 -1
  456. package/tui/src/utils/hooks/skillImprovement.ts +1 -1
  457. package/tui/src/utils/mcp/dateTimeParser.ts +1 -1
  458. package/tui/src/utils/messages.ts +18 -0
  459. package/tui/src/utils/migrateSessions.ts +3 -3
  460. package/tui/src/utils/model/model.ts +6 -6
  461. package/tui/src/utils/permissions/yoloClassifier.ts +1 -1
  462. package/tui/src/utils/plugins/headlessPluginInstall.ts +1 -1
  463. package/tui/src/utils/plugins/mcpPluginIntegration.ts +1 -1
  464. package/tui/src/utils/plugins/mcpbHandler.ts +1 -1
  465. package/tui/src/utils/plugins/pluginLoader.ts +8 -8
  466. package/tui/src/utils/protectedNamespace.ts +5 -3
  467. package/tui/src/utils/rawJsonToolCall.ts +242 -0
  468. package/tui/src/utils/ripgrep.ts +16 -7
  469. package/tui/src/utils/sessionTitle.ts +1 -1
  470. package/tui/src/utils/settings/permissionValidation.ts +14 -2
  471. package/tui/src/utils/shell/prefix.ts +1 -1
  472. package/tui/src/utils/sideQuery.ts +1 -1
  473. package/tui/src/utils/systemThemeWatcher.ts +13 -3
  474. package/tui/src/utils/teleport.tsx +1 -1
  475. package/uv.lock +426 -45
  476. package/tui/src/services/api/claude.ts +0 -3540
  477. package/tui/src/tools/_shared/directPublicDataGuard.ts +0 -362
  478. package/tui/src/tools/_shared/kmaAnalysisGuard.ts +0 -197
  479. package/tui/src/tools/_shared/kmaAviationGuard.ts +0 -70
  480. package/tui/src/tools/_shared/nmcAedGuard.ts +0 -234
  481. package/tui/src/tools/_shared/protectedCheckGuard.ts +0 -207
  482. package/tui/src/tools/_shared/textToolCallGuard.ts +0 -91
@@ -0,0 +1,211 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """Promoted bounded Python source document engine."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import ast
7
+ import html
8
+ import re
9
+ from pathlib import Path
10
+ from typing import NoReturn
11
+
12
+ from ummaya.tools.documents.engines import DocumentMutationBlockedError
13
+ from ummaya.tools.documents.models import (
14
+ BlockedReason,
15
+ DocumentExtraction,
16
+ DocumentFormat,
17
+ DocumentPatch,
18
+ DocumentPatchOperation,
19
+ KnownDocumentFormat,
20
+ MetadataValue,
21
+ OperationType,
22
+ ParagraphBlock,
23
+ )
24
+ from ummaya.tools.documents.tool_defs import DocumentFieldPatch
25
+
26
+ _CODE_BODY_TARGET = "/code/body"
27
+ _CODE_LINE_RE = re.compile(r"^/code/lines/(?P<index>[1-9][0-9]*)$")
28
+
29
+
30
+ class PythonSourceDocumentEngine:
31
+ """Bounded writer for UTF-8 Python source attachments."""
32
+
33
+ document_format = DocumentFormat.python
34
+ engine_id = "python-source"
35
+ render_engine_id = "python-source-structural-svg"
36
+ render_artifact_extension = "svg"
37
+ render_mime_type = "image/svg+xml"
38
+
39
+ def inspect(self, path: Path, *, artifact_id: str) -> DocumentExtraction:
40
+ """Extract Python source as line-addressable document IR."""
41
+ source = _read_python_source(path)
42
+ _validate_python_source(source)
43
+ return DocumentExtraction(
44
+ artifact_id=artifact_id,
45
+ paragraphs=_paragraphs_from_source(source),
46
+ metadata=_metadata(path, line_count=len(source.splitlines())),
47
+ )
48
+
49
+ def apply_patch(self, path: Path, patch: DocumentPatch) -> bytes:
50
+ """Apply a bounded source replacement and return derivative bytes."""
51
+ source = _read_python_source(path)
52
+ _validate_python_source(source)
53
+ for operation in patch.operations:
54
+ source = _apply_code_operation(source, operation)
55
+ _validate_python_source(source)
56
+ return source.encode("utf-8")
57
+
58
+ def render(self, path: Path, *, artifact_id: str, output_dir: Path) -> tuple[bytes, ...]:
59
+ """Render Python source as structural SVG evidence."""
60
+ _ = output_dir
61
+ extraction = self.inspect(path, artifact_id=artifact_id)
62
+ lines = [paragraph.text for paragraph in extraction.paragraphs]
63
+ return (_render_code_svg(lines, title="Python source document"),)
64
+
65
+
66
+ class PythonSourceDocumentAdapter:
67
+ """Format adapter for promoted Python source attachments."""
68
+
69
+ adapter_id = "python-source-document-adapter"
70
+ known_formats: tuple[KnownDocumentFormat, ...] = (KnownDocumentFormat.python,)
71
+ promoted_formats: tuple[DocumentFormat, ...] = (DocumentFormat.python,)
72
+
73
+ def __init__(self, engine: PythonSourceDocumentEngine | None = None) -> None:
74
+ self._engine = engine or PythonSourceDocumentEngine()
75
+
76
+ @property
77
+ def engine_id(self) -> str:
78
+ """Return the wrapped engine id for diagnostics."""
79
+ return self._engine.engine_id
80
+
81
+ def inspect(self, path: Path, *, artifact_id: str) -> DocumentExtraction:
82
+ """Inspect a Python source artifact."""
83
+ return self._engine.inspect(path, artifact_id=artifact_id)
84
+
85
+ def normalize_fill_patches(
86
+ self,
87
+ patches: tuple[DocumentFieldPatch, ...],
88
+ *,
89
+ extraction: DocumentExtraction | None,
90
+ ) -> tuple[DocumentFieldPatch, ...]:
91
+ """Return code patches unchanged; `/code/*` paths are native."""
92
+ _ = extraction
93
+ return patches
94
+
95
+
96
+ def _read_python_source(path: Path) -> str:
97
+ try:
98
+ payload = path.read_bytes()
99
+ except OSError as exc:
100
+ raise DocumentMutationBlockedError(
101
+ BlockedReason.unsupported_operation,
102
+ f"Could not read Python source document: {path}",
103
+ ) from exc
104
+ if b"\x00" in payload:
105
+ raise DocumentMutationBlockedError(
106
+ BlockedReason.validation_failed,
107
+ "Python source document contains NUL bytes.",
108
+ )
109
+ try:
110
+ return payload.decode("utf-8")
111
+ except UnicodeDecodeError as exc:
112
+ raise DocumentMutationBlockedError(
113
+ BlockedReason.validation_failed,
114
+ "Python source document must be UTF-8.",
115
+ ) from exc
116
+
117
+
118
+ def _validate_python_source(source: str) -> None:
119
+ if not source.strip():
120
+ raise DocumentMutationBlockedError(
121
+ BlockedReason.validation_failed,
122
+ "Python source document cannot be empty.",
123
+ )
124
+ try:
125
+ ast.parse(source)
126
+ except SyntaxError as exc:
127
+ raise DocumentMutationBlockedError(
128
+ BlockedReason.validation_failed,
129
+ f"Python source document is not syntactically valid: {exc.msg}.",
130
+ ) from exc
131
+
132
+
133
+ def _apply_code_operation(source: str, operation: DocumentPatchOperation) -> str:
134
+ if operation.operation_type not in {OperationType.replace_text, OperationType.set_field_value}:
135
+ _raise_unsupported_operation(operation)
136
+ if operation.value is None:
137
+ _raise_unsupported_operation(operation)
138
+ replacement = str(operation.value)
139
+ if operation.target_path == _CODE_BODY_TARGET:
140
+ return _with_trailing_newline(replacement)
141
+ match = _CODE_LINE_RE.fullmatch(operation.target_path)
142
+ if match is None:
143
+ _raise_unsupported_operation(operation)
144
+ lines = source.splitlines(keepends=True)
145
+ line_index = int(match.group("index")) - 1
146
+ if line_index >= len(lines):
147
+ _raise_unsupported_operation(operation)
148
+ newline = "\n" if lines[line_index].endswith("\n") else ""
149
+ lines[line_index] = replacement.rstrip("\n") + newline
150
+ return "".join(lines)
151
+
152
+
153
+ def _with_trailing_newline(source: str) -> str:
154
+ return source if source.endswith("\n") else f"{source}\n"
155
+
156
+
157
+ def _paragraphs_from_source(source: str) -> list[ParagraphBlock]:
158
+ lines = source.splitlines()
159
+ return [
160
+ ParagraphBlock(
161
+ block_id=f"code-line-{index}",
162
+ text=line,
163
+ source_path=f"/code/lines/{index}",
164
+ )
165
+ for index, line in enumerate(lines, start=1)
166
+ ]
167
+
168
+
169
+ def _metadata(path: Path, *, line_count: int) -> dict[str, MetadataValue]:
170
+ return {
171
+ "adapter_id": PythonSourceDocumentAdapter.adapter_id,
172
+ "engine_id": PythonSourceDocumentEngine.engine_id,
173
+ "format": DocumentFormat.python.value,
174
+ "source_name": path.name,
175
+ "line_count": line_count,
176
+ "mutation_policy": "bounded_python_source_write_render_save",
177
+ "render_oracle": PythonSourceDocumentEngine.render_engine_id,
178
+ "execution_policy": "never_execute_source",
179
+ "syntax_gate": "python_ast_parse",
180
+ }
181
+
182
+
183
+ def _render_code_svg(lines: list[str], *, title: str) -> bytes:
184
+ escaped_title = html.escape(title)
185
+ safe_lines = [html.escape(line) for line in lines]
186
+ height = max(160, 72 + len(safe_lines) * 24)
187
+ line_nodes = [
188
+ (
189
+ f'<text x="32" y="{84 + index * 24}" font-size="13" '
190
+ 'font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" '
191
+ f'fill="#1f2937">{index + 1:>3} {line}</text>'
192
+ )
193
+ for index, line in enumerate(safe_lines)
194
+ ]
195
+ svg = (
196
+ f'<svg xmlns="http://www.w3.org/2000/svg" width="960" height="{height}" '
197
+ f'viewBox="0 0 960 {height}">'
198
+ '<rect width="100%" height="100%" fill="#ffffff"/>'
199
+ '<rect x="24" y="56" width="912" height="'
200
+ f'{max(72, len(safe_lines) * 24 + 24)}" fill="#f9fafb" stroke="#d1d5db"/>'
201
+ f'<text x="32" y="36" font-size="22" font-family="sans-serif" '
202
+ f'font-weight="700">{escaped_title}</text>' + "".join(line_nodes) + "</svg>"
203
+ )
204
+ return svg.encode("utf-8")
205
+
206
+
207
+ def _raise_unsupported_operation(operation: DocumentPatchOperation) -> NoReturn:
208
+ raise DocumentMutationBlockedError(
209
+ BlockedReason.unsupported_operation,
210
+ f"Unsupported Python source operation target: {operation.target_path}",
211
+ )
@@ -0,0 +1,272 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """Promoted structured public-data document engines."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import csv
7
+ import html
8
+ import io
9
+ import json
10
+ from pathlib import Path
11
+ from typing import NoReturn
12
+
13
+ import yaml
14
+ from defusedxml import ElementTree # type: ignore[import-untyped]
15
+
16
+ from ummaya.tools.documents.engines import DocumentMutationBlockedError
17
+ from ummaya.tools.documents.models import (
18
+ BlockedReason,
19
+ DocumentExtraction,
20
+ DocumentFormat,
21
+ DocumentPatch,
22
+ DocumentPatchOperation,
23
+ KnownDocumentFormat,
24
+ MetadataValue,
25
+ OperationType,
26
+ ParagraphBlock,
27
+ )
28
+ from ummaya.tools.documents.tool_defs import DocumentFieldPatch
29
+
30
+ _DATA_BODY_TARGET = "/data/body"
31
+ _DATA_FORMATS = (
32
+ DocumentFormat.csv,
33
+ DocumentFormat.tsv,
34
+ DocumentFormat.xml,
35
+ DocumentFormat.rdf,
36
+ DocumentFormat.ttl,
37
+ DocumentFormat.lod,
38
+ DocumentFormat.json,
39
+ DocumentFormat.jsonl,
40
+ DocumentFormat.yaml,
41
+ DocumentFormat.yml,
42
+ DocumentFormat.geojson,
43
+ DocumentFormat.gpx,
44
+ DocumentFormat.kml,
45
+ DocumentFormat.fasta,
46
+ DocumentFormat.sgml,
47
+ DocumentFormat.dtd,
48
+ DocumentFormat.hml,
49
+ DocumentFormat.etc,
50
+ )
51
+ _XML_FORMATS = {
52
+ DocumentFormat.xml,
53
+ DocumentFormat.rdf,
54
+ DocumentFormat.gpx,
55
+ DocumentFormat.kml,
56
+ DocumentFormat.hml,
57
+ }
58
+
59
+
60
+ class DataFileDocumentEngine:
61
+ """Bounded writer for UTF-8 structured public-data files."""
62
+
63
+ render_engine_id = "data-file-structural-svg"
64
+ render_artifact_extension = "svg"
65
+ render_mime_type = "image/svg+xml"
66
+
67
+ def __init__(self, document_format: DocumentFormat) -> None:
68
+ if document_format not in _DATA_FORMATS:
69
+ raise ValueError(f"unsupported data-file document format: {document_format.value}")
70
+ self.document_format = document_format
71
+ self.engine_id = f"data-file-{document_format.value}"
72
+
73
+ def inspect(self, path: Path, *, artifact_id: str) -> DocumentExtraction:
74
+ """Extract compact textual records from a data file."""
75
+ raw_text = path.read_text(encoding="utf-8", errors="replace")
76
+ visible_text = _visible_data_text(raw_text, document_format=self.document_format)
77
+ return DocumentExtraction(
78
+ artifact_id=artifact_id,
79
+ paragraphs=_paragraphs_from_text(visible_text),
80
+ metadata=_metadata(path, document_format=self.document_format),
81
+ )
82
+
83
+ def apply_patch(self, path: Path, patch: DocumentPatch) -> bytes:
84
+ """Replace a complete data-file body and return derivative bytes."""
85
+ raw_text = path.read_text(encoding="utf-8", errors="replace")
86
+ replacement = raw_text
87
+ for operation in patch.operations:
88
+ replacement = _apply_data_operation(replacement, operation)
89
+ _validate_data_text(replacement, document_format=self.document_format)
90
+ return replacement.encode("utf-8")
91
+
92
+ def render(self, path: Path, *, artifact_id: str, output_dir: Path) -> tuple[bytes, ...]:
93
+ """Render compact data text as structural SVG evidence."""
94
+ _ = output_dir
95
+ extraction = self.inspect(path, artifact_id=artifact_id)
96
+ lines = [paragraph.text for paragraph in extraction.paragraphs]
97
+ return (_render_lines_svg(lines, title=f"{self.document_format.value.upper()} data"),)
98
+
99
+
100
+ class DataFileDocumentAdapter:
101
+ """Format adapter for promoted public-data document engines."""
102
+
103
+ adapter_id = "data-file-document-adapter"
104
+ known_formats: tuple[KnownDocumentFormat, ...] = (
105
+ KnownDocumentFormat.csv,
106
+ KnownDocumentFormat.tsv,
107
+ KnownDocumentFormat.xml,
108
+ KnownDocumentFormat.rdf,
109
+ KnownDocumentFormat.ttl,
110
+ KnownDocumentFormat.lod,
111
+ KnownDocumentFormat.json,
112
+ KnownDocumentFormat.jsonl,
113
+ KnownDocumentFormat.yaml,
114
+ KnownDocumentFormat.yml,
115
+ KnownDocumentFormat.geojson,
116
+ KnownDocumentFormat.gpx,
117
+ KnownDocumentFormat.kml,
118
+ KnownDocumentFormat.fasta,
119
+ KnownDocumentFormat.sgml,
120
+ KnownDocumentFormat.dtd,
121
+ KnownDocumentFormat.hml,
122
+ KnownDocumentFormat.etc,
123
+ )
124
+ promoted_formats: tuple[DocumentFormat, ...] = _DATA_FORMATS
125
+
126
+ def __init__(self, engines: dict[DocumentFormat, DataFileDocumentEngine] | None = None) -> None:
127
+ self._engines = engines or {
128
+ document_format: DataFileDocumentEngine(document_format)
129
+ for document_format in _DATA_FORMATS
130
+ }
131
+
132
+ def inspect(self, path: Path, *, artifact_id: str) -> DocumentExtraction:
133
+ """Inspect a data artifact using its suffix-selected engine."""
134
+ return self._engine_for_path(path).inspect(path, artifact_id=artifact_id)
135
+
136
+ def normalize_fill_patches(
137
+ self,
138
+ patches: tuple[DocumentFieldPatch, ...],
139
+ *,
140
+ extraction: DocumentExtraction | None,
141
+ ) -> tuple[DocumentFieldPatch, ...]:
142
+ """Return data patches unchanged; `/data/body` is native."""
143
+ _ = extraction
144
+ return patches
145
+
146
+ def _engine_for_path(self, path: Path) -> DataFileDocumentEngine:
147
+ try:
148
+ document_format = DocumentFormat(path.suffix.lower().lstrip("."))
149
+ except ValueError as exc:
150
+ raise DocumentMutationBlockedError(
151
+ BlockedReason.unsupported_format,
152
+ f"Unsupported data suffix: {path.suffix}",
153
+ ) from exc
154
+ engine = self._engines.get(document_format)
155
+ if engine is None:
156
+ raise DocumentMutationBlockedError(
157
+ BlockedReason.unsupported_format,
158
+ f"Unsupported data suffix: {path.suffix}",
159
+ )
160
+ return engine
161
+
162
+
163
+ def _visible_data_text(raw_text: str, *, document_format: DocumentFormat) -> str:
164
+ if document_format in {DocumentFormat.json, DocumentFormat.geojson}:
165
+ return json.dumps(json.loads(raw_text), ensure_ascii=False, sort_keys=True)
166
+ if document_format == DocumentFormat.jsonl:
167
+ return "\n".join(
168
+ json.dumps(json.loads(line), ensure_ascii=False, sort_keys=True)
169
+ for line in raw_text.splitlines()
170
+ if line.strip()
171
+ )
172
+ if document_format in {DocumentFormat.yaml, DocumentFormat.yml}:
173
+ loaded = yaml.safe_load(raw_text)
174
+ return yaml.safe_dump(loaded, allow_unicode=True, sort_keys=True).strip()
175
+ if document_format in _XML_FORMATS:
176
+ root = ElementTree.fromstring(raw_text.encode("utf-8"))
177
+ return "\n".join(text.strip() for text in root.itertext() if text.strip())
178
+ return raw_text
179
+
180
+
181
+ def _apply_data_operation(text: str, operation: DocumentPatchOperation) -> str:
182
+ if operation.operation_type not in {OperationType.replace_text, OperationType.set_field_value}:
183
+ _raise_unsupported_operation(operation)
184
+ if operation.target_path != _DATA_BODY_TARGET:
185
+ _raise_unsupported_operation(operation)
186
+ value = operation.value
187
+ if value is None:
188
+ _raise_unsupported_operation(operation)
189
+ return str(value)
190
+
191
+
192
+ def _validate_data_text(text: str, *, document_format: DocumentFormat) -> None:
193
+ try:
194
+ if document_format in {DocumentFormat.json, DocumentFormat.geojson}:
195
+ json.loads(text)
196
+ return
197
+ if document_format == DocumentFormat.jsonl:
198
+ for line in text.splitlines():
199
+ if line.strip():
200
+ json.loads(line)
201
+ return
202
+ if document_format in {DocumentFormat.yaml, DocumentFormat.yml}:
203
+ yaml.safe_load(text)
204
+ return
205
+ if document_format in _XML_FORMATS:
206
+ ElementTree.fromstring(text.encode("utf-8"))
207
+ return
208
+ if document_format in {DocumentFormat.csv, DocumentFormat.tsv}:
209
+ delimiter = "\t" if document_format == DocumentFormat.tsv else ","
210
+ list(csv.reader(io.StringIO(text), delimiter=delimiter))
211
+ return
212
+ except (ElementTree.ParseError, json.JSONDecodeError, yaml.YAMLError, csv.Error) as exc:
213
+ raise DocumentMutationBlockedError(
214
+ BlockedReason.validation_failed,
215
+ f"Replacement body is not valid {document_format.value}: {exc}",
216
+ ) from exc
217
+ if not text.strip():
218
+ raise DocumentMutationBlockedError(
219
+ BlockedReason.validation_failed,
220
+ f"Replacement body is empty for {document_format.value}.",
221
+ )
222
+
223
+
224
+ def _paragraphs_from_text(text: str) -> list[ParagraphBlock]:
225
+ lines = [line.strip() for line in text.splitlines() if line.strip()]
226
+ if not lines and text.strip():
227
+ lines = [text.strip()]
228
+ return [
229
+ ParagraphBlock(
230
+ block_id=f"data-line-{index}",
231
+ text=line,
232
+ source_path=f"/data/lines/{index}",
233
+ )
234
+ for index, line in enumerate(lines[:200], start=1)
235
+ ]
236
+
237
+
238
+ def _metadata(path: Path, *, document_format: DocumentFormat) -> dict[str, MetadataValue]:
239
+ return {
240
+ "adapter_id": "data-file-document-adapter",
241
+ "engine_id": f"data-file-{document_format.value}",
242
+ "format": document_format.value,
243
+ "source_name": path.name,
244
+ "mutation_policy": "bounded_data_file_write_render_save",
245
+ "render_oracle": "data-file-structural-svg",
246
+ }
247
+
248
+
249
+ def _render_lines_svg(lines: list[str], *, title: str) -> bytes:
250
+ escaped_title = html.escape(title)
251
+ safe_lines = [html.escape(line) for line in lines if line]
252
+ height = max(160, 72 + len(safe_lines) * 28)
253
+ text_nodes = [
254
+ f'<text x="32" y="{84 + index * 28}" font-size="16" font-family="monospace">{line}</text>'
255
+ for index, line in enumerate(safe_lines)
256
+ ]
257
+ svg = (
258
+ f'<svg xmlns="http://www.w3.org/2000/svg" width="960" height="{height}" '
259
+ f'viewBox="0 0 960 {height}">'
260
+ '<rect width="100%" height="100%" fill="#ffffff"/>'
261
+ f'<text x="32" y="40" font-size="22" font-family="sans-serif" '
262
+ f'font-weight="700">{escaped_title}</text>' + "".join(text_nodes) + "</svg>"
263
+ )
264
+ return svg.encode("utf-8")
265
+
266
+
267
+ def _raise_unsupported_operation(operation: DocumentPatchOperation) -> NoReturn:
268
+ raise DocumentMutationBlockedError(
269
+ BlockedReason.unsupported_operation,
270
+ f"Data-file operation is not supported: "
271
+ f"{operation.operation_type.value} {operation.target_path}",
272
+ )