ummaya 0.2.3 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (534) hide show
  1. package/README.md +17 -3
  2. package/bin/ummaya +10 -1
  3. package/npm-shrinkwrap.json +253 -2
  4. package/package.json +5 -1
  5. package/prompts/manifest.yaml +2 -2
  6. package/prompts/session_guidance_v1.md +3 -1
  7. package/prompts/system_v1.md +9 -7
  8. package/pyproject.toml +26 -7
  9. package/specs/2803-document-production-hardening/contracts/document-tools.schema.json +1043 -0
  10. package/src/ummaya/_canonical/__init__.py +2 -0
  11. package/src/ummaya/context/builder.py +17 -11
  12. package/src/ummaya/engine/engine.py +30 -113
  13. package/src/ummaya/engine/query.py +20 -0
  14. package/src/ummaya/evidence/__init__.py +44 -0
  15. package/src/ummaya/evidence/__main__.py +7 -0
  16. package/src/ummaya/evidence/dataset_contract.py +193 -0
  17. package/src/ummaya/evidence/document_authoring_cases.py +33 -0
  18. package/src/ummaya/evidence/document_harness.py +313 -0
  19. package/src/ummaya/evidence/document_viewer_ux.py +391 -0
  20. package/src/ummaya/evidence/gates.py +70 -0
  21. package/src/ummaya/evidence/json_types.py +20 -0
  22. package/src/ummaya/evidence/models.py +145 -0
  23. package/src/ummaya/evidence/output_payload.py +89 -0
  24. package/src/ummaya/evidence/payload_documents.py +233 -0
  25. package/src/ummaya/evidence/route_contracts.py +224 -0
  26. package/src/ummaya/evidence/route_helpers.py +150 -0
  27. package/src/ummaya/evidence/runner.py +177 -0
  28. package/src/ummaya/evidence/source_provenance.py +246 -0
  29. package/src/ummaya/evidence/source_provenance_redaction.py +176 -0
  30. package/src/ummaya/evidence/task_registry.py +264 -0
  31. package/src/ummaya/evidence/tool_layer.py +39 -0
  32. package/src/ummaya/evidence/tool_layer_models.py +151 -0
  33. package/src/ummaya/ipc/adapter_manifest_emitter.py +26 -10
  34. package/src/ummaya/ipc/document_intent_normalization.py +185 -0
  35. package/src/ummaya/ipc/frame_schema.py +52 -5
  36. package/src/ummaya/ipc/route_diagnostics.py +73 -0
  37. package/src/ummaya/ipc/stdio.py +2282 -417
  38. package/src/ummaya/llm/client.py +234 -59
  39. package/src/ummaya/llm/config.py +8 -3
  40. package/src/ummaya/llm/reasoning.py +84 -0
  41. package/src/ummaya/primitives/__init__.py +6 -2
  42. package/src/ummaya/primitives/delegation.py +1 -1
  43. package/src/ummaya/primitives/document.py +28 -0
  44. package/src/ummaya/settings.py +0 -3
  45. package/src/ummaya/tools/discovery_bridge.py +34 -2
  46. package/src/ummaya/tools/documents/__init__.py +297 -0
  47. package/src/ummaya/tools/documents/adapter_registry.py +487 -0
  48. package/src/ummaya/tools/documents/archive_container_probe.py +167 -0
  49. package/src/ummaya/tools/documents/artifact_store.py +454 -0
  50. package/src/ummaya/tools/documents/authoring.py +283 -0
  51. package/src/ummaya/tools/documents/baselines.py +114 -0
  52. package/src/ummaya/tools/documents/capability.py +331 -0
  53. package/src/ummaya/tools/documents/contracts.py +112 -0
  54. package/src/ummaya/tools/documents/conversion.py +521 -0
  55. package/src/ummaya/tools/documents/diff.py +275 -0
  56. package/src/ummaya/tools/documents/engines.py +163 -0
  57. package/src/ummaya/tools/documents/evaluation.py +291 -0
  58. package/src/ummaya/tools/documents/explicit_values.py +108 -0
  59. package/src/ummaya/tools/documents/fixtures.py +174 -0
  60. package/src/ummaya/tools/documents/format_completion_audit.py +471 -0
  61. package/src/ummaya/tools/documents/formats/__init__.py +2 -0
  62. package/src/ummaya/tools/documents/formats/archive.py +528 -0
  63. package/src/ummaya/tools/documents/formats/base.py +41 -0
  64. package/src/ummaya/tools/documents/formats/code_file.py +211 -0
  65. package/src/ummaya/tools/documents/formats/data_file.py +272 -0
  66. package/src/ummaya/tools/documents/formats/hwp.py +284 -0
  67. package/src/ummaya/tools/documents/formats/hwpx.py +1837 -0
  68. package/src/ummaya/tools/documents/formats/odf.py +435 -0
  69. package/src/ummaya/tools/documents/formats/ooxml.py +1030 -0
  70. package/src/ummaya/tools/documents/formats/passive.py +766 -0
  71. package/src/ummaya/tools/documents/formats/pdf.py +702 -0
  72. package/src/ummaya/tools/documents/formats/text_web.py +268 -0
  73. package/src/ummaya/tools/documents/hwp_conversion_probe.py +178 -0
  74. package/src/ummaya/tools/documents/hwp_direct_candidate.py +141 -0
  75. package/src/ummaya/tools/documents/inspection.py +289 -0
  76. package/src/ummaya/tools/documents/intake.py +1079 -0
  77. package/src/ummaya/tools/documents/legacy_office_promotion_probe.py +366 -0
  78. package/src/ummaya/tools/documents/models.py +1598 -0
  79. package/src/ummaya/tools/documents/odf_promotion_probe.py +167 -0
  80. package/src/ummaya/tools/documents/orchestrator.py +96 -0
  81. package/src/ummaya/tools/documents/passive_capability_probe.py +251 -0
  82. package/src/ummaya/tools/documents/patch.py +170 -0
  83. package/src/ummaya/tools/documents/pdfa_conformance.py +284 -0
  84. package/src/ummaya/tools/documents/pdfa_promotion_probe.py +198 -0
  85. package/src/ummaya/tools/documents/permissions.py +110 -0
  86. package/src/ummaya/tools/documents/planner.py +616 -0
  87. package/src/ummaya/tools/documents/registry.py +2733 -0
  88. package/src/ummaya/tools/documents/render.py +978 -0
  89. package/src/ummaya/tools/documents/render_comparison.py +113 -0
  90. package/src/ummaya/tools/documents/render_comparison_models.py +74 -0
  91. package/src/ummaya/tools/documents/render_comparison_regions.py +73 -0
  92. package/src/ummaya/tools/documents/render_comparison_style.py +161 -0
  93. package/src/ummaya/tools/documents/reread.py +157 -0
  94. package/src/ummaya/tools/documents/runtime_authoring.py +244 -0
  95. package/src/ummaya/tools/documents/runtime_authoring_bundle.py +76 -0
  96. package/src/ummaya/tools/documents/scorecard.py +184 -0
  97. package/src/ummaya/tools/documents/socratic_planner.py +193 -0
  98. package/src/ummaya/tools/documents/style.py +48 -0
  99. package/src/ummaya/tools/documents/tool_defs.py +523 -0
  100. package/src/ummaya/tools/documents/validate.py +347 -0
  101. package/src/ummaya/tools/executor.py +61 -12
  102. package/src/ummaya/tools/geocoding/kakao_client.py +1 -2
  103. package/src/ummaya/tools/kma/apihub_catalog.py +984 -1
  104. package/src/ummaya/tools/kma/apihub_structured_adapter.py +86 -6
  105. package/src/ummaya/tools/kma/apihub_url_adapter.py +593 -0
  106. package/src/ummaya/tools/kma/apihub_url_catalog.py +296 -0
  107. package/src/ummaya/tools/live_proxy.py +0 -3
  108. package/src/ummaya/tools/location_adapters.py +8 -6
  109. package/src/ummaya/tools/manifest_metadata.py +16 -3
  110. package/src/ummaya/tools/models.py +5 -1
  111. package/src/ummaya/tools/mvp_surface.py +2 -2
  112. package/src/ummaya/tools/nmc/emergency_search.py +8 -6
  113. package/src/ummaya/tools/register_all.py +17 -0
  114. package/src/ummaya/tools/registry.py +10 -1
  115. package/src/ummaya/tools/resolve_location.py +4 -4
  116. package/src/ummaya/tools/routing/__init__.py +59 -0
  117. package/src/ummaya/tools/routing/builder.py +105 -0
  118. package/src/ummaya/tools/routing/cards.py +29 -0
  119. package/src/ummaya/tools/routing/decision_service.py +534 -0
  120. package/src/ummaya/tools/routing/decision_types.py +74 -0
  121. package/src/ummaya/tools/routing/feasibility.py +122 -0
  122. package/src/ummaya/tools/routing/intent.py +17 -0
  123. package/src/ummaya/tools/routing/intent_extractor.py +207 -0
  124. package/src/ummaya/tools/routing/intent_patterns.py +160 -0
  125. package/src/ummaya/tools/routing/intent_public_data.py +150 -0
  126. package/src/ummaya/tools/routing/intent_types.py +48 -0
  127. package/src/ummaya/tools/routing/lint.py +78 -0
  128. package/src/ummaya/tools/routing/metadata.py +174 -0
  129. package/src/ummaya/tools/routing/projection.py +340 -0
  130. package/src/ummaya/tools/routing/retrieval_policy.py +629 -0
  131. package/src/ummaya/tools/routing/schema.py +81 -0
  132. package/src/ummaya/tools/routing/types.py +96 -0
  133. package/src/ummaya/tools/routing_index.py +2 -2
  134. package/src/ummaya/tools/search.py +40 -106
  135. package/src/ummaya/tools/verified_data_go_kr/_manifest.py +115 -25
  136. package/src/ummaya/tools/verified_data_go_kr/airkorea_air_quality.py +109 -4
  137. package/src/ummaya/tools/verified_data_go_kr/nmc_aed_site.py +108 -2
  138. package/src/ummaya/tools/verified_data_go_kr/pps_bid_public_info.py +174 -9
  139. package/src/ummaya/tools/verified_data_go_kr/tago_bus_arrival.py +66 -3
  140. package/src/ummaya/tools/verified_data_go_kr/tago_bus_location.py +12 -2
  141. package/src/ummaya/tools/verified_data_go_kr/tago_bus_route.py +8 -2
  142. package/src/ummaya/tools/verified_data_go_kr/tago_bus_route_station.py +114 -0
  143. package/src/ummaya/tools/verified_data_go_kr/tago_bus_station.py +14 -3
  144. package/src/ummaya/tools/verify_canonical_map.py +21 -0
  145. package/tests/fixtures/documents/public_forms/baselines.yaml +113 -0
  146. package/tui/package.json +1 -2
  147. package/tui/src/.cc-byte-identical-whitelist.yaml +266 -0
  148. package/tui/src/QueryEngine.ts +12 -4
  149. package/tui/src/bridge/inboundAttachments.ts +3 -3
  150. package/tui/src/cli/handlers/auth.ts +4 -13
  151. package/tui/src/cli/handlers/mcp.tsx +3 -3
  152. package/tui/src/cli/print.ts +69 -18
  153. package/tui/src/cli/update.ts +13 -13
  154. package/tui/src/commands/copy/index.ts +1 -1
  155. package/tui/src/commands/cost/cost.ts +2 -2
  156. package/tui/src/commands/init-verifiers.ts +5 -5
  157. package/tui/src/commands/init.ts +30 -30
  158. package/tui/src/commands/insights.ts +44 -44
  159. package/tui/src/commands/install-github-app/install-github-app.tsx +2 -2
  160. package/tui/src/commands/install-github-app/setupGitHubActions.ts +3 -3
  161. package/tui/src/commands/install-github-app/types.ts +8 -30
  162. package/tui/src/commands/install.tsx +5 -5
  163. package/tui/src/commands/mcp/addCommand.ts +5 -5
  164. package/tui/src/commands/mcp/xaaIdpCommand.ts +2 -2
  165. package/tui/src/commands/plugin/ManageMarketplaces.tsx +2 -2
  166. package/tui/src/commands/plugin/types.ts +6 -28
  167. package/tui/src/commands/plugin/unifiedTypes.ts +4 -26
  168. package/tui/src/commands/reasoning/index.ts +13 -0
  169. package/tui/src/commands/reasoning/reasoning.tsx +177 -0
  170. package/tui/src/commands/rename/generateSessionName.ts +1 -1
  171. package/tui/src/commands/thinkback/thinkback.tsx +3 -3
  172. package/tui/src/commands.ts +2 -0
  173. package/tui/src/components/Feedback.tsx +1 -1
  174. package/tui/src/components/LogoV2/EmergencyTip.tsx +11 -2
  175. package/tui/src/components/LogoV2/WelcomeV2.tsx +1 -3
  176. package/tui/src/components/Messages.tsx +2 -1
  177. package/tui/src/components/ScrollKeybindingHandler.tsx +6 -6
  178. package/tui/src/components/Spinner/types.ts +6 -28
  179. package/tui/src/components/Spinner.tsx +2 -2
  180. package/tui/src/components/agents/generateAgent.ts +1 -1
  181. package/tui/src/components/agents/new-agent-creation/types.ts +4 -26
  182. package/tui/src/components/config/EnvSecretIsolatedEditor.tsx +1 -1
  183. package/tui/src/components/design-system/LoadingState.tsx +2 -2
  184. package/tui/src/components/mcp/types.ts +16 -38
  185. package/tui/src/components/messages/AssistantToolUseMessage.tsx +3 -2
  186. package/tui/src/components/messages/UserCrossSessionMessage.ts +16 -4
  187. package/tui/src/components/messages/UserForkBoilerplateMessage.ts +16 -4
  188. package/tui/src/components/messages/UserGitHubWebhookMessage.ts +16 -4
  189. package/tui/src/components/messages/UserToolResultMessage/utils.tsx +3 -2
  190. package/tui/src/components/permissions/MonitorPermissionRequest/MonitorPermissionRequest.ts +9 -4
  191. package/tui/src/components/permissions/ReviewArtifactPermissionRequest/ReviewArtifactPermissionRequest.ts +9 -4
  192. package/tui/src/components/primitive/DocumentSocraticReviewBlock.tsx +129 -0
  193. package/tui/src/components/primitive/DocumentToolResultCard.tsx +224 -0
  194. package/tui/src/components/primitive/documentSocraticReview.ts +215 -0
  195. package/tui/src/components/primitive/index.tsx +43 -1
  196. package/tui/src/components/primitive/types.ts +137 -0
  197. package/tui/src/components/ui/option.ts +4 -26
  198. package/tui/src/constants/common.ts +0 -2
  199. package/tui/src/constants/prompts.ts +4 -3
  200. package/tui/src/constants/querySource.ts +4 -26
  201. package/tui/src/entrypoints/sdk/controlTypes.ts +26 -48
  202. package/tui/src/entrypoints/sdk/coreTypes.generated.ts +3 -25
  203. package/tui/src/entrypoints/sdk/runtimeTypes.ts +38 -60
  204. package/tui/src/entrypoints/sdk/sdkUtilityTypes.ts +4 -26
  205. package/tui/src/entrypoints/sdk/settingsTypes.generated.ts +3 -25
  206. package/tui/src/entrypoints/sdk/toolTypes.ts +3 -25
  207. package/tui/src/hooks/toolPermission/handlers/interactiveHandler.ts +10 -0
  208. package/tui/src/hooks/useApiKeyVerification.ts +1 -1
  209. package/tui/src/hooks/useVirtualScroll.ts +1 -1
  210. package/tui/src/ink/ink.tsx +33 -14
  211. package/tui/src/ink/reconciler.ts +2 -3
  212. package/tui/src/ink/render-to-screen.ts +30 -10
  213. package/tui/src/ipc/bridge.ts +62 -15
  214. package/tui/src/ipc/bridgeSingleton.ts +5 -1
  215. package/tui/src/ipc/codec.ts +29 -3
  216. package/tui/src/ipc/frames.generated.ts +407 -312
  217. package/tui/src/ipc/llmClient.ts +279 -76
  218. package/tui/src/ipc/llmTypes.ts +16 -1
  219. package/tui/src/ipc/schema/frame.schema.json +1 -3475
  220. package/tui/src/keybindings/defaultBindings.ts +4 -0
  221. package/tui/src/main.tsx +32 -11
  222. package/tui/src/native-ts/file-index/index.ts +33 -3
  223. package/tui/src/observability/surface.ts +2 -2
  224. package/tui/src/probes/toolRegistryProbe.tsx +3 -1
  225. package/tui/src/projectOnboardingState.ts +7 -6
  226. package/tui/src/query/chatMessageTypes.ts +18 -0
  227. package/tui/src/query/chatMessagesBuilder.ts +1 -1
  228. package/tui/src/query/deps.ts +1 -1
  229. package/tui/src/query/messageGuards.ts +106 -0
  230. package/tui/src/query/publicDataTerminalRepair.ts +384 -0
  231. package/tui/src/query/run.ts +1075 -0
  232. package/tui/src/query/supportBoundary.ts +168 -0
  233. package/tui/src/query/toolResultErrors.ts +103 -0
  234. package/tui/src/query/toolRunner.ts +687 -0
  235. package/tui/src/query/unavailableToolRepair.ts +118 -0
  236. package/tui/src/query.ts +9 -1721
  237. package/tui/src/screens/REPL.tsx +42 -31
  238. package/tui/src/services/api/adapterManifest.ts +4 -0
  239. package/tui/src/services/api/backendChat/events.ts +117 -0
  240. package/tui/src/services/api/backendChat/finalMessage.ts +40 -0
  241. package/tui/src/services/api/backendChat/frame.ts +9 -0
  242. package/tui/src/services/api/backendChat/streaming.ts +430 -0
  243. package/tui/src/services/api/backendChat/types.ts +62 -0
  244. package/tui/src/services/api/backendChat.ts +1 -0
  245. package/tui/src/services/api/client.ts +98 -14
  246. package/tui/src/services/api/errorUtils.ts +5 -5
  247. package/tui/src/services/api/errors.ts +1 -1
  248. package/tui/src/services/api/logging.ts +1 -1
  249. package/tui/src/services/api/ummaya/evidence.ts +194 -0
  250. package/tui/src/services/api/ummaya/messages.ts +255 -0
  251. package/tui/src/services/api/ummaya/nonStreaming.ts +66 -0
  252. package/tui/src/services/api/ummaya/provider.ts +200 -0
  253. package/tui/src/services/api/ummaya/reasoning.ts +24 -0
  254. package/tui/src/services/api/ummaya/request.ts +200 -0
  255. package/tui/src/services/api/ummaya/selectionContext.ts +240 -0
  256. package/tui/src/services/api/ummaya/streaming.ts +365 -0
  257. package/tui/src/services/api/ummaya/streamingPayload.ts +129 -0
  258. package/tui/src/services/api/ummaya/streamingReader.ts +40 -0
  259. package/tui/src/services/api/ummaya/toolSelection.ts +217 -0
  260. package/tui/src/services/api/ummaya/types.ts +110 -0
  261. package/tui/src/services/api/ummaya/usage.ts +30 -0
  262. package/tui/src/services/api/ummaya.ts +26 -364
  263. package/tui/src/services/api/withRetry.ts +1 -1
  264. package/tui/src/services/awaySummary.ts +2 -2
  265. package/tui/src/services/claudeAiLimits.ts +1 -1
  266. package/tui/src/services/compact/autoCompact.ts +1 -1
  267. package/tui/src/services/compact/compact.ts +1 -1
  268. package/tui/src/services/lsp/types.ts +8 -30
  269. package/tui/src/services/tips/types.ts +6 -28
  270. package/tui/src/services/tokenEstimation.ts +1 -1
  271. package/tui/src/services/toolRegistry/bootGuard.ts +5 -5
  272. package/tui/src/services/toolUseSummary/toolUseSummaryGenerator.ts +1 -1
  273. package/tui/src/services/tools/toolExecution.ts +94 -1
  274. package/tui/src/skills/bundled/stuck.ts +12 -12
  275. package/tui/src/state/AppStateStore.ts +7 -0
  276. package/tui/src/store/pendingPermissionSlot.ts +1 -1
  277. package/tui/src/store/session-store.ts +10 -36
  278. package/tui/src/stubs/any-stub.ts +15 -10
  279. package/tui/src/stubs/color-diff-napi.ts +37 -23
  280. package/tui/src/stubs/globals.d.ts +3 -3
  281. package/tui/src/stubs/macro-preload.ts +23 -12
  282. package/tui/src/tools/AdapterTool/AdapterTool.ts +1239 -163
  283. package/tui/src/tools/AdapterTool/routeDiagnostics.ts +75 -0
  284. package/tui/src/tools/AgentTool/AgentTool.tsx +84 -1371
  285. package/tui/src/tools/AgentTool/agentToolHandoff.ts +114 -0
  286. package/tui/src/tools/AgentTool/agentToolPartialResult.ts +16 -0
  287. package/tui/src/tools/AgentTool/agentToolProgress.ts +32 -0
  288. package/tui/src/tools/AgentTool/agentToolResolver.ts +161 -0
  289. package/tui/src/tools/AgentTool/agentToolResult.ts +163 -0
  290. package/tui/src/tools/AgentTool/agentToolUtils.ts +14 -686
  291. package/tui/src/tools/AgentTool/asyncAgentLifecycle.ts +208 -0
  292. package/tui/src/tools/AgentTool/asyncLifecycle.ts +153 -0
  293. package/tui/src/tools/AgentTool/backgroundedCompletion.ts +126 -0
  294. package/tui/src/tools/AgentTool/backgroundedLifecycle.ts +174 -0
  295. package/tui/src/tools/AgentTool/foregroundBackground.ts +83 -0
  296. package/tui/src/tools/AgentTool/foregroundDrain.tsx +133 -0
  297. package/tui/src/tools/AgentTool/foregroundFinalize.ts +98 -0
  298. package/tui/src/tools/AgentTool/foregroundLifecycle.tsx +237 -0
  299. package/tui/src/tools/AgentTool/foregroundProgress.tsx +169 -0
  300. package/tui/src/tools/AgentTool/foregroundTask.ts +89 -0
  301. package/tui/src/tools/AgentTool/forkSubagent.ts +1 -12
  302. package/tui/src/tools/AgentTool/forkSubagentGate.ts +34 -0
  303. package/tui/src/tools/AgentTool/launchRouting.ts +203 -0
  304. package/tui/src/tools/AgentTool/lifecycle.ts +244 -0
  305. package/tui/src/tools/AgentTool/mcpRouting.ts +73 -0
  306. package/tui/src/tools/AgentTool/orchestrationSupport.ts +70 -0
  307. package/tui/src/tools/AgentTool/permissions.ts +39 -0
  308. package/tui/src/tools/AgentTool/promptSetup.ts +181 -0
  309. package/tui/src/tools/AgentTool/remoteRouting.ts +62 -0
  310. package/tui/src/tools/AgentTool/resultMapping.ts +116 -0
  311. package/tui/src/tools/AgentTool/resumeAgent.ts +39 -107
  312. package/tui/src/tools/AgentTool/resumeAgentHelpers.ts +140 -0
  313. package/tui/src/tools/AgentTool/runAgent.ts +1 -1
  314. package/tui/src/tools/AgentTool/runtimeConfig.ts +57 -0
  315. package/tui/src/tools/AgentTool/schemas.ts +196 -0
  316. package/tui/src/tools/AgentTool/sourceVerificationPropagation.ts +263 -0
  317. package/tui/src/tools/AgentTool/worktreeLifecycle.ts +105 -0
  318. package/tui/src/tools/AskUserQuestionTool/AskUserQuestionTool.tsx +174 -202
  319. package/tui/src/tools/BashTool/BashTool.tsx +71 -1072
  320. package/tui/src/tools/BashTool/bashCommandHelpers.ts +12 -12
  321. package/tui/src/tools/BashTool/bashPermissions/astPreflight.ts +173 -0
  322. package/tui/src/tools/BashTool/bashPermissions/classifierChecks.ts +199 -0
  323. package/tui/src/tools/BashTool/bashPermissions/compoundGuards.ts +53 -0
  324. package/tui/src/tools/BashTool/bashPermissions/constants.ts +99 -0
  325. package/tui/src/tools/BashTool/bashPermissions/index.ts +38 -0
  326. package/tui/src/tools/BashTool/bashPermissions/legacyMisparsing.ts +62 -0
  327. package/tui/src/tools/BashTool/bashPermissions/main.ts +135 -0
  328. package/tui/src/tools/BashTool/bashPermissions/normalizedCommands.ts +33 -0
  329. package/tui/src/tools/BashTool/bashPermissions/operatorFlow.ts +98 -0
  330. package/tui/src/tools/BashTool/bashPermissions/permissionChecks.ts +200 -0
  331. package/tui/src/tools/BashTool/bashPermissions/prefixSuggestions.ts +88 -0
  332. package/tui/src/tools/BashTool/bashPermissions/promptClassifierRules.ts +125 -0
  333. package/tui/src/tools/BashTool/bashPermissions/ruleDelegates.ts +19 -0
  334. package/tui/src/tools/BashTool/bashPermissions/ruleMatching.ts +145 -0
  335. package/tui/src/tools/BashTool/bashPermissions/sandboxAutoAllow.ts +75 -0
  336. package/tui/src/tools/BashTool/bashPermissions/subcommandFlow.ts +205 -0
  337. package/tui/src/tools/BashTool/bashPermissions/subcommandGuards.ts +73 -0
  338. package/tui/src/tools/BashTool/bashPermissions/subcommandResultHelpers.ts +116 -0
  339. package/tui/src/tools/BashTool/bashPermissions/types.ts +26 -0
  340. package/tui/src/tools/BashTool/bashPermissions/wrapperStripping.ts +139 -0
  341. package/tui/src/tools/BashTool/bashPermissions.ts +26 -2621
  342. package/tui/src/tools/BashTool/call.ts +202 -0
  343. package/tui/src/tools/BashTool/callLoader.ts +35 -0
  344. package/tui/src/tools/BashTool/commandClassification.ts +151 -0
  345. package/tui/src/tools/BashTool/commandClassificationLoader.ts +40 -0
  346. package/tui/src/tools/BashTool/cwdReset.ts +33 -0
  347. package/tui/src/tools/BashTool/lineTruncation.ts +11 -0
  348. package/tui/src/tools/BashTool/modeValidation.ts +13 -1
  349. package/tui/src/tools/BashTool/outputPersistence.ts +42 -0
  350. package/tui/src/tools/BashTool/permissionClassification.ts +66 -0
  351. package/tui/src/tools/BashTool/permissionLoader.ts +44 -0
  352. package/tui/src/tools/BashTool/resultLoader.ts +29 -0
  353. package/tui/src/tools/BashTool/resultMapping.ts +83 -0
  354. package/tui/src/tools/BashTool/sandboxPolicy.ts +79 -0
  355. package/tui/src/tools/BashTool/schemas.ts +65 -0
  356. package/tui/src/tools/BashTool/sedEditExecution.ts +59 -0
  357. package/tui/src/tools/BashTool/shellExecution.tsx +245 -0
  358. package/tui/src/tools/BashTool/shellOutputUtils.ts +85 -0
  359. package/tui/src/tools/BashTool/shellPermissionGauntlet.ts +97 -0
  360. package/tui/src/tools/BashTool/uiLoader.ts +37 -0
  361. package/tui/src/tools/BriefTool/upload.ts +1 -1
  362. package/tui/src/tools/CalculatorTool/parser.ts +2 -2
  363. package/tui/src/tools/DocumentPrimitive/DocumentPrimitive.ts +262 -0
  364. package/tui/src/tools/DocumentPrimitive/dispatchNormalization.ts +270 -0
  365. package/tui/src/tools/DocumentPrimitive/documentDestinationPath.ts +18 -0
  366. package/tui/src/tools/DocumentPrimitive/documentMutationGuard.ts +22 -0
  367. package/tui/src/tools/DocumentPrimitive/documentPatchNormalization.ts +248 -0
  368. package/tui/src/tools/DocumentPrimitive/documentSourceVerification.ts +245 -0
  369. package/tui/src/tools/DocumentPrimitive/documentSourceVerificationFields.ts +103 -0
  370. package/tui/src/tools/DocumentPrimitive/modelVisibleOutput.ts +40 -0
  371. package/tui/src/tools/DocumentPrimitive/prompt.ts +35 -0
  372. package/tui/src/tools/FileEditTool/FileEditTool.ts +9 -507
  373. package/tui/src/tools/FileEditTool/call.ts +228 -0
  374. package/tui/src/tools/FileEditTool/validateInput.ts +196 -0
  375. package/tui/src/tools/FileReadTool/imageProcessor.ts +13 -0
  376. package/tui/src/tools/FileWriteTool/FileWriteTool.ts +7 -300
  377. package/tui/src/tools/FileWriteTool/call.ts +223 -0
  378. package/tui/src/tools/FileWriteTool/validateInput.ts +80 -0
  379. package/tui/src/tools/ListMcpResourcesTool/ListMcpResourcesTool.ts +19 -3
  380. package/tui/src/tools/LookupPrimitive/LookupPrimitive.ts +48 -29
  381. package/tui/src/tools/LookupPrimitive/prompt.ts +6 -7
  382. package/tui/src/tools/MCPTool/trustPolicy.ts +118 -0
  383. package/tui/src/tools/McpAuthTool/McpAuthTool.ts +21 -3
  384. package/tui/src/tools/NotebookEditTool/NotebookEditTool.ts +7 -326
  385. package/tui/src/tools/NotebookEditTool/call.ts +254 -0
  386. package/tui/src/tools/NotebookEditTool/notebookModel.ts +51 -0
  387. package/tui/src/tools/NotebookEditTool/validateInput.ts +142 -0
  388. package/tui/src/tools/PowerShellTool/PowerShellTool.tsx +46 -937
  389. package/tui/src/tools/PowerShellTool/acceptEditsCommandValidation.ts +162 -0
  390. package/tui/src/tools/PowerShellTool/call.ts +179 -0
  391. package/tui/src/tools/PowerShellTool/callLoader.ts +37 -0
  392. package/tui/src/tools/PowerShellTool/commandClassification.ts +86 -0
  393. package/tui/src/tools/PowerShellTool/modeValidation.ts +25 -332
  394. package/tui/src/tools/PowerShellTool/outputPersistence.ts +42 -0
  395. package/tui/src/tools/PowerShellTool/permissionClassification.ts +28 -0
  396. package/tui/src/tools/PowerShellTool/resultLoader.ts +31 -0
  397. package/tui/src/tools/PowerShellTool/resultMapping.ts +75 -0
  398. package/tui/src/tools/PowerShellTool/schemas.ts +40 -0
  399. package/tui/src/tools/PowerShellTool/shellExecution.tsx +258 -0
  400. package/tui/src/tools/PowerShellTool/symlinkModeValidation.ts +44 -0
  401. package/tui/src/tools/PowerShellTool/uiLoader.ts +37 -0
  402. package/tui/src/tools/PowerShellTool/validation.ts +39 -0
  403. package/tui/src/tools/ReadMcpResourceTool/ReadMcpResourceTool.ts +19 -3
  404. package/tui/src/tools/ResolveLocationPrimitive/ResolveLocationPrimitive.ts +30 -19
  405. package/tui/src/tools/ResolveLocationPrimitive/prompt.ts +2 -6
  406. package/tui/src/tools/SkillTool/SkillTool.ts +2 -2
  407. package/tui/src/tools/SubmitPrimitive/SubmitPrimitive.ts +51 -18
  408. package/tui/src/tools/TaskCreateTool/TaskCreateTool.ts +16 -2
  409. package/tui/src/tools/TaskGetTool/TaskGetTool.ts +23 -3
  410. package/tui/src/tools/TaskListTool/TaskListTool.ts +22 -4
  411. package/tui/src/tools/TaskOutputTool/TaskOutputTool.tsx +46 -547
  412. package/tui/src/tools/TaskOutputTool/lookup.ts +216 -0
  413. package/tui/src/tools/TaskOutputTool/render.tsx +257 -0
  414. package/tui/src/tools/TaskOutputTool/schemas.ts +55 -0
  415. package/tui/src/tools/TaskOutputTool/serialization.ts +36 -0
  416. package/tui/src/tools/TaskStopTool/TaskStopTool.ts +10 -0
  417. package/tui/src/tools/TaskUpdateTool/TaskUpdateTool.ts +14 -364
  418. package/tui/src/tools/TaskUpdateTool/completion.ts +62 -0
  419. package/tui/src/tools/TaskUpdateTool/schemas.ts +62 -0
  420. package/tui/src/tools/TaskUpdateTool/serialization.ts +46 -0
  421. package/tui/src/tools/TaskUpdateTool/statusUpdate.ts +247 -0
  422. package/tui/src/tools/TodoWriteTool/TodoWriteTool.ts +21 -2
  423. package/tui/src/tools/ToolSearchTool/ToolSearchTool.ts +21 -302
  424. package/tui/src/tools/ToolSearchTool/ccSupportTools.ts +223 -0
  425. package/tui/src/tools/ToolSearchTool/descriptionCache.ts +50 -0
  426. package/tui/src/tools/ToolSearchTool/keywordSearch.ts +216 -0
  427. package/tui/src/tools/ToolSearchTool/prompt.ts +10 -4
  428. package/tui/src/tools/ToolSearchTool/resultMapping.ts +30 -0
  429. package/tui/src/tools/ToolSearchTool/schemas.ts +30 -0
  430. package/tui/src/tools/ToolSearchTool/searchPool.ts +47 -0
  431. package/tui/src/tools/ToolSearchTool/supportIntentHints.ts +140 -0
  432. package/tui/src/tools/TranslateTool/TranslateTool.ts +1 -1
  433. package/tui/src/tools/VerifyPrimitive/VerifyPrimitive.ts +27 -10
  434. package/tui/src/tools/WebFetchTool/WebFetchTool.ts +43 -138
  435. package/tui/src/tools/WebFetchTool/call.ts +227 -0
  436. package/tui/src/tools/WebFetchTool/resolvedAddressSafety.ts +78 -0
  437. package/tui/src/tools/WebFetchTool/sourceVerification.ts +204 -0
  438. package/tui/src/tools/WebFetchTool/types.ts +23 -0
  439. package/tui/src/tools/WebFetchTool/urlSafety.ts +181 -0
  440. package/tui/src/tools/WebFetchTool/utils.ts +1 -1
  441. package/tui/src/tools/WebSearchTool/UI.tsx +0 -1
  442. package/tui/src/tools/WebSearchTool/WebSearchTool.ts +9 -313
  443. package/tui/src/tools/WebSearchTool/call.ts +33 -0
  444. package/tui/src/tools/WebSearchTool/responseMapping.ts +190 -0
  445. package/tui/src/tools/WebSearchTool/resultBlock.ts +47 -0
  446. package/tui/src/tools/WebSearchTool/schemas.ts +47 -0
  447. package/tui/src/tools/WebSearchTool/toolSchema.ts +12 -0
  448. package/tui/src/tools/WorkspaceToolAdapter/WorkspaceToolAdapter.ts +79 -0
  449. package/tui/src/tools/WorkspaceToolAdapter/allowedRootPolicy.ts +85 -0
  450. package/tui/src/tools/WorkspaceToolAdapter/documentFormatGuards.ts +73 -0
  451. package/tui/src/tools/WorkspaceToolAdapter/inputNormalization.ts +105 -0
  452. package/tui/src/tools/WorkspaceToolAdapter/mcpExposurePolicy.ts +64 -0
  453. package/tui/src/tools/WorkspaceToolAdapter/toolDefFactory.ts +215 -0
  454. package/tui/src/tools/WorkspaceToolAdapter/toolNames.ts +6 -0
  455. package/tui/src/tools/WorkspaceToolAdapter/workspacePolicy.ts +15 -0
  456. package/tui/src/tools/_shared/citizenUserText.ts +49 -0
  457. package/tui/src/tools/_shared/dispatchPrimitive.ts +6 -6
  458. package/tui/src/tools/_shared/documentChangeToPatch.ts +125 -0
  459. package/tui/src/tools/_shared/documentDispatchArguments.ts +87 -0
  460. package/tui/src/tools/_shared/documentPrimitiveTimeout.ts +13 -0
  461. package/tui/src/tools/_shared/documentToolResultRender.ts +98 -0
  462. package/tui/src/tools/_shared/locationInputRepair.ts +112 -0
  463. package/tui/src/tools/_shared/pendingCallRegistry.ts +1 -6
  464. package/tui/src/tools/_shared/rootPrimitiveInput.ts +68 -0
  465. package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPatterns.ts +58 -0
  466. package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPrompt.ts +271 -0
  467. package/tui/src/tools/_shared/toolChoiceRepair/documentRepair.ts +452 -0
  468. package/tui/src/tools/_shared/toolChoiceRepair/messageAccess.ts +80 -0
  469. package/tui/src/tools/_shared/toolChoiceRepair/publicDataRepair.ts +92 -0
  470. package/tui/src/tools/_shared/toolChoiceRepair/supportRepair.ts +135 -0
  471. package/tui/src/tools/_shared/toolChoiceRepair.ts +61 -0
  472. package/tui/src/tools/shared/mockDisclaimer.ts +1 -1
  473. package/tui/src/tools.ts +39 -190
  474. package/tui/src/types/fileSuggestion.ts +4 -26
  475. package/tui/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +186 -148
  476. package/tui/src/types/generated/events_mono/common/v1/auth.ts +25 -11
  477. package/tui/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +47 -30
  478. package/tui/src/types/generated/google/protobuf/timestamp.ts +21 -7
  479. package/tui/src/types/message.ts +80 -102
  480. package/tui/src/types/messageQueueTypes.ts +6 -28
  481. package/tui/src/types/notebook.ts +16 -38
  482. package/tui/src/types/statusLine.ts +4 -26
  483. package/tui/src/types/tools.ts +24 -46
  484. package/tui/src/types/utils.ts +6 -28
  485. package/tui/src/upstreamproxy/relay.ts +7 -3
  486. package/tui/src/upstreamproxy/upstreamproxy.ts +1 -1
  487. package/tui/src/utils/assistantMessageFactories.ts +9 -3
  488. package/tui/src/utils/attachments.ts +1 -1
  489. package/tui/src/utils/auth.ts +129 -139
  490. package/tui/src/utils/bash/ast.ts +23 -23
  491. package/tui/src/utils/bash/bashParser.ts +5 -5
  492. package/tui/src/utils/billing.ts +1 -1
  493. package/tui/src/utils/collapseReadSearch.ts +3 -3
  494. package/tui/src/utils/cronTasks.ts +1 -1
  495. package/tui/src/utils/execFileNoThrow.ts +1 -1
  496. package/tui/src/utils/filePersistence/types.ts +16 -38
  497. package/tui/src/utils/forkedAgent.ts +1 -1
  498. package/tui/src/utils/gracefulShutdown.ts +4 -4
  499. package/tui/src/utils/heapDumpService.ts +12 -8
  500. package/tui/src/utils/hooks/apiQueryHookHelper.ts +1 -1
  501. package/tui/src/utils/hooks/execPromptHook.ts +1 -1
  502. package/tui/src/utils/hooks/skillImprovement.ts +1 -1
  503. package/tui/src/utils/kExaoneReasoning.ts +138 -0
  504. package/tui/src/utils/mcp/dateTimeParser.ts +1 -1
  505. package/tui/src/utils/messages.ts +19 -0
  506. package/tui/src/utils/migrateSessions.ts +3 -3
  507. package/tui/src/utils/model/model.ts +6 -6
  508. package/tui/src/utils/multiToolLayout.ts +13 -0
  509. package/tui/src/utils/permissions/yoloClassifier.ts +1 -1
  510. package/tui/src/utils/plugins/headlessPluginInstall.ts +1 -1
  511. package/tui/src/utils/plugins/mcpPluginIntegration.ts +1 -1
  512. package/tui/src/utils/plugins/mcpbHandler.ts +1 -1
  513. package/tui/src/utils/plugins/pluginLoader.ts +8 -8
  514. package/tui/src/utils/processUserInput/processSlashCommand.tsx +2 -2
  515. package/tui/src/utils/processUserInput/processUserInput.ts +26 -0
  516. package/tui/src/utils/protectedNamespace.ts +5 -3
  517. package/tui/src/utils/rawJsonToolCall.ts +242 -0
  518. package/tui/src/utils/ripgrep.ts +16 -7
  519. package/tui/src/utils/sessionTitle.ts +1 -1
  520. package/tui/src/utils/settings/applySettingsChange.ts +4 -0
  521. package/tui/src/utils/settings/permissionValidation.ts +14 -2
  522. package/tui/src/utils/settings/types.ts +9 -3
  523. package/tui/src/utils/shell/prefix.ts +1 -1
  524. package/tui/src/utils/sideQuery.ts +1 -1
  525. package/tui/src/utils/stats.ts +1 -1
  526. package/tui/src/utils/systemThemeWatcher.ts +13 -3
  527. package/tui/src/utils/teleport.tsx +1 -1
  528. package/uv.lock +394 -22
  529. package/assets/copilot-gate-logo.svg +0 -58
  530. package/assets/govon-logo.svg +0 -40
  531. package/src/ummaya/eval/__init__.py +0 -5
  532. package/src/ummaya/eval/retrieval.py +0 -713
  533. package/tui/src/services/api/claude.ts +0 -3510
  534. package/tui/src/utils/messageStream.ts +0 -186
@@ -0,0 +1,39 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ from __future__ import annotations
3
+
4
+ from dataclasses import dataclass
5
+
6
+ from ummaya.evidence.models import RouteTraceRecord
7
+ from ummaya.evidence.tool_layer_models import ToolLayerEvidenceEvent
8
+
9
+
10
+ @dataclass(frozen=True, slots=True)
11
+ class ToolLayerEvidenceJoinError(ValueError):
12
+ """Raised when a tool-layer artifact cannot be joined to route evidence."""
13
+
14
+ event_id: str
15
+
16
+ def __str__(self) -> str:
17
+ return f"tool-layer event does not join to route evidence: {self.event_id}"
18
+
19
+
20
+ def build_tool_layer_events(
21
+ route_trace_records: tuple[RouteTraceRecord, ...],
22
+ *,
23
+ observed_events: tuple[ToolLayerEvidenceEvent, ...] = (),
24
+ ) -> tuple[ToolLayerEvidenceEvent, ...]:
25
+ """Return validated tool-layer artifacts without synthesizing sample events."""
26
+
27
+ if not observed_events:
28
+ return ()
29
+
30
+ route_keys = {
31
+ (record.scenario_id, record.trace_id, record.correlation_id)
32
+ for record in route_trace_records
33
+ if record.trace_kind == "scenario_route"
34
+ }
35
+ for event in observed_events:
36
+ event_key = (event.scenario_id, event.trace_id, event.correlation_id)
37
+ if event_key not in route_keys:
38
+ raise ToolLayerEvidenceJoinError(event_id=event.event_id)
39
+ return observed_events
@@ -0,0 +1,151 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """Tool-layer Evidence Fabric event models."""
3
+
4
+ from __future__ import annotations
5
+
6
+ from typing import Literal, Self, assert_never
7
+
8
+ from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
9
+ from pydantic_core import PydanticCustomError
10
+
11
+ ToolLayerExposureState = Literal[
12
+ "always-loaded",
13
+ "deferred-searchable",
14
+ "permission-gated-callable",
15
+ "hidden",
16
+ "unsupported",
17
+ ]
18
+ ToolLayerTrustTier = Literal[0, 1, 2, 3, 4, 5]
19
+ ToolLayerPermissionDecision = Literal[
20
+ "not_required",
21
+ "approved",
22
+ "denied",
23
+ "blocked_pending_approval",
24
+ "policy_preapproved",
25
+ ]
26
+ ToolLayerResultStatus = Literal["succeeded", "failed", "blocked"]
27
+ ToolLayerBlockedState = Literal[
28
+ "not_blocked",
29
+ "blocked_by_permission",
30
+ "blocked_by_policy",
31
+ "blocked_by_missing_source",
32
+ "blocked_by_unsupported",
33
+ ]
34
+ ToolLayerRenderFrame = Literal[
35
+ "permission_prompt",
36
+ "tool_call",
37
+ "tool_result",
38
+ "blocked_state",
39
+ ]
40
+ ToolLayerPromptInjectionState = Literal["detected", "not_detected"]
41
+ ToolLayerSourceTrust = Literal["trusted", "untrusted"]
42
+ ToolLayerSourceInstructionVisibility = Literal["evidence_only"]
43
+
44
+
45
+ def _validation_error(code: str, message: str) -> PydanticCustomError:
46
+ return PydanticCustomError(code, message)
47
+
48
+
49
+ class ToolLayerEvidenceEvent(BaseModel):
50
+ """One recovered Claude Code support-tool exposure and provenance event."""
51
+
52
+ model_config = ConfigDict(frozen=True, extra="forbid")
53
+
54
+ event_id: str = Field(min_length=1)
55
+ scenario_id: str = Field(min_length=1)
56
+ trace_id: str = Field(min_length=1)
57
+ correlation_id: str = Field(min_length=1)
58
+ frame_hash: str = Field(min_length=64, max_length=64)
59
+ render_frame: ToolLayerRenderFrame
60
+ selected_tool: str = Field(min_length=1)
61
+ exposure_state: ToolLayerExposureState
62
+ trust_tier: ToolLayerTrustTier
63
+ permission_decision: ToolLayerPermissionDecision
64
+ source_url: str | None
65
+ source_local_handle: str | None
66
+ source_citation_id: str = Field(min_length=1)
67
+ provenance_id: str = Field(min_length=1)
68
+ source_trust: ToolLayerSourceTrust
69
+ source_prompt_injection: ToolLayerPromptInjectionState
70
+ source_instruction_visibility: ToolLayerSourceInstructionVisibility = "evidence_only"
71
+ result_status: ToolLayerResultStatus
72
+ result_summary: str | None
73
+ error_summary: str | None
74
+ blocked_state: ToolLayerBlockedState
75
+
76
+ @field_validator("frame_hash")
77
+ @classmethod
78
+ def _validate_frame_hash(cls, value: str) -> str:
79
+ if len(value) != 64 or any(ch not in "0123456789abcdef" for ch in value):
80
+ raise _validation_error(
81
+ "tool_layer_frame_hash", "frame_hash must be lowercase SHA-256 hex"
82
+ )
83
+ return value
84
+
85
+ @field_validator("source_url", "source_local_handle", "source_citation_id", "provenance_id")
86
+ @classmethod
87
+ def _reject_model_visible_leakage_keys(cls, value: str | None) -> str | None:
88
+ if value is not None and ("adapter_id" in value or "expected_tool" in value):
89
+ raise _validation_error(
90
+ "tool_layer_model_visible_leakage",
91
+ "tool-layer evidence cannot carry model-visible leakage keys",
92
+ )
93
+ return value
94
+
95
+ @field_validator("result_summary", "error_summary")
96
+ @classmethod
97
+ def _reject_empty_summary(cls, value: str | None) -> str | None:
98
+ if value is not None and not value.strip():
99
+ raise _validation_error(
100
+ "tool_layer_blank_summary", "tool-layer summaries cannot be blank"
101
+ )
102
+ return value
103
+
104
+ @model_validator(mode="after")
105
+ def _requires_source_reference(self) -> Self:
106
+ if self.source_url is None and self.source_local_handle is None:
107
+ raise _validation_error(
108
+ "tool_layer_missing_source",
109
+ "tool-layer evidence requires source_url or source_local_handle",
110
+ )
111
+ return self
112
+
113
+ @model_validator(mode="after")
114
+ def _requires_status_payload(self) -> Self:
115
+ match self.result_status:
116
+ case "succeeded":
117
+ if self.result_summary is None:
118
+ raise _validation_error(
119
+ "tool_layer_missing_result_summary",
120
+ "succeeded tool-layer event requires result_summary",
121
+ )
122
+ if self.error_summary is not None:
123
+ raise _validation_error(
124
+ "tool_layer_unexpected_error_summary",
125
+ "succeeded tool-layer event cannot carry error_summary",
126
+ )
127
+ if self.blocked_state != "not_blocked":
128
+ raise _validation_error(
129
+ "tool_layer_unexpected_blocked_state",
130
+ "succeeded tool-layer event must not be blocked",
131
+ )
132
+ case "failed":
133
+ if self.error_summary is None:
134
+ raise _validation_error(
135
+ "tool_layer_failed_without_error",
136
+ "failed tool-layer event requires error_summary",
137
+ )
138
+ case "blocked":
139
+ if self.error_summary is None:
140
+ raise _validation_error(
141
+ "tool_layer_blocked_without_error",
142
+ "blocked tool-layer event requires error_summary",
143
+ )
144
+ if self.blocked_state == "not_blocked":
145
+ raise _validation_error(
146
+ "tool_layer_blocked_without_state",
147
+ "blocked tool-layer event requires a blocked_state",
148
+ )
149
+ case unreachable:
150
+ assert_never(unreachable)
151
+ return self
@@ -47,6 +47,7 @@ import importlib
47
47
  import json
48
48
  import logging
49
49
  import os
50
+ import re
50
51
  from datetime import UTC, datetime
51
52
  from typing import IO, Any, Literal
52
53
 
@@ -255,7 +256,7 @@ def _build_entries( # noqa: C901, ANN401 — three-source walker, refactor defe
255
256
  except Exception:
256
257
  tools_list = []
257
258
 
258
- root_primitive_tool_ids = frozenset({"locate", "find", "check", "send"})
259
+ root_primitive_tool_ids = frozenset({"locate", "find", "check", "send", "document"})
259
260
 
260
261
  for tool in tools_list:
261
262
  tool_id_opt: str | None = tool.id if hasattr(tool, "id") else getattr(tool, "tool_id", None)
@@ -371,24 +372,39 @@ def _verify_family_llm_description(
371
372
  """Build model-facing prose for a verify-family manifest entry."""
372
373
 
373
374
  metadata = metadata or {}
374
- tool_id = str(metadata.get("tool_id") or family).strip()
375
375
  name = str(metadata.get("name_ko") or family).strip()
376
- scope_rules = str(metadata.get("scope_rules") or "").strip()
376
+ scope_rules = _safe_verify_scope_rules(str(metadata.get("scope_rules") or "").strip())
377
377
  scope_clause = f" {scope_rules}" if scope_rules else ""
378
378
  return (
379
- f"Internal check-family surface for {name} (family_hint='{family}', "
380
- f"bridged adapter id '{tool_id}'). Use this only through the core check "
381
- "primitive before a downstream protected find/send action needs delegated "
382
- "authorization. Params must follow input_schema_json exactly: scope_list "
383
- "contains '<verb>:<adapter_family>.<action>' scope strings, purpose_ko is "
384
- "the Korean citizen-facing consent purpose, and purpose_en is the audit-log "
379
+ f"Internal check-family surface for {name} (family_hint='{family}'). "
380
+ "Use this only through the core check primitive before a downstream "
381
+ "protected find/send action needs delegated authorization. Params must "
382
+ "follow input_schema_json exactly: scope_list contains "
383
+ "'<verb>:<adapter_family>.<action>' scope strings, purpose_ko is the "
384
+ "Korean citizen-facing consent purpose, and purpose_en is the audit-log "
385
385
  "English purpose. The manifest entry stays source_mode='internal' because "
386
386
  "the agency citation is emitted by the verify response transparency stamp, "
387
- "while the pre-call tool schema remains stable for the TUI and LLM loop."
387
+ "while the pre-call tool schema remains stable for the TUI and LLM loop. "
388
+ "Do not mention internal mock bridge identifiers in citizen-facing prose."
388
389
  f"{scope_clause}"
389
390
  )
390
391
 
391
392
 
393
+ def _safe_verify_scope_rules(scope_rules: str) -> str:
394
+ if not scope_rules:
395
+ return ""
396
+ safe_sentences: list[str] = []
397
+ for sentence in re.split(r"(?<=[.!?])\s+", scope_rules):
398
+ candidate = sentence.strip()
399
+ if not candidate:
400
+ continue
401
+ lowered = candidate.lower()
402
+ if "mock_verify" in lowered or "tool_id" in lowered:
403
+ continue
404
+ safe_sentences.append(candidate)
405
+ return " ".join(safe_sentences)
406
+
407
+
392
408
  def _string_list(value: object) -> list[str]:
393
409
  """Return non-empty strings from a loosely typed metadata list."""
394
410
 
@@ -0,0 +1,185 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ import uuid
7
+ from pathlib import Path
8
+ from typing import Final
9
+
10
+ _DOCUMENT_WRITE_REQUEST_RE: Final = re.compile(
11
+ r"(작성|수정|편집|채우|채워|입력|변경|저장|write|edit|fill|apply|save)",
12
+ re.IGNORECASE,
13
+ )
14
+ _DOCUMENT_SAVE_REQUEST_RE: Final = re.compile(
15
+ r"(저장|내보내|export|save)",
16
+ re.IGNORECASE,
17
+ )
18
+ _DOCUMENT_READ_ONLY_INSPECT_RE: Final = re.compile(
19
+ r"(구조.{0,30}빈칸.{0,30}확인|빈칸.{0,30}확인|구조.{0,30}확인|"
20
+ r"확인해\s*줘|검토만|inspect|read[- ]?only)",
21
+ re.IGNORECASE,
22
+ )
23
+ _DOCUMENT_MUTATION_PROHIBITION_RE: Final = re.compile(
24
+ r"(절대.{0,40}(?:수정|저장|작성|채우|입력|변경).{0,40}"
25
+ r"(?:하지\s*마|하지\s*말|금지)|"
26
+ r"(?:수정|저장|작성|채우|입력|변경).{0,30}(?:하지\s*마|하지\s*말)|"
27
+ r"(?:do not|don't).{0,40}(?:modify|save|write|edit|fill))",
28
+ re.IGNORECASE,
29
+ )
30
+ _QUESTION_FIRST_AUTHORING_RE: Final = re.compile(
31
+ r"(근거가\s*부족하면\s*먼저\s*질문|먼저\s*(?:확인|파악|검토|질문|물어)|"
32
+ r"초안을?\s*먼저|아직.{0,40}(?:쓰지\s*마|작성하지\s*마|저장하지\s*마|"
33
+ r"반영하지\s*마)|문서에는\s*쓰지\s*마)",
34
+ re.IGNORECASE,
35
+ )
36
+ _DOCUMENT_MUTATION_PARAM_KEYS: Final[frozenset[str]] = frozenset(
37
+ {
38
+ "approved_draft_id",
39
+ "destination_display_name",
40
+ "destination_path",
41
+ "dry_run",
42
+ "patches",
43
+ "styles",
44
+ "template_id",
45
+ }
46
+ )
47
+ _DOCUMENT_INTERNAL_USER_QUERY_KEY: Final = "__ummaya_user_query"
48
+ _DOCUMENT_ROOT_SYNTHESIS_KEYS: Final[frozenset[str]] = frozenset(
49
+ {_DOCUMENT_INTERNAL_USER_QUERY_KEY}
50
+ )
51
+ _DOCUMENT_EXPLICIT_LOCAL_PATH_RE: Final = re.compile(
52
+ r"(?P<path>(?:~|/)[^\s\"'<>]+?\."
53
+ r"(?:hwpx|hwp|docx|pdf|xlsx|pptx|odt|ods|odp|doc|xls|ppt|csv|txt|md|json|xml|html))",
54
+ re.IGNORECASE,
55
+ )
56
+
57
+
58
+ def _normalize_document_root_call_for_user_intent(
59
+ fname: str,
60
+ args_obj: dict[str, object],
61
+ latest_user_utt: str,
62
+ ) -> dict[str, object]:
63
+ if fname != "document" or args_obj.get("tool_id") != "document":
64
+ return args_obj
65
+ params_obj = args_obj.get("params")
66
+ if not isinstance(params_obj, dict):
67
+ return args_obj
68
+
69
+ intent_text = _document_intent_text(params_obj, latest_user_utt)
70
+ synthesized_params = _synthesize_document_read_params(params_obj, intent_text)
71
+ if synthesized_params is not None:
72
+ return {**args_obj, "params": synthesized_params}
73
+
74
+ normalized_params = dict(params_obj)
75
+ normalized_params.pop(_DOCUMENT_INTERNAL_USER_QUERY_KEY, None)
76
+ _normalize_document_path_from_user_query(normalized_params, intent_text)
77
+ if _is_explicit_read_only_inspect_intent(intent_text):
78
+ read_only_params = _strip_mutation_params(normalized_params)
79
+ read_only_params["operation"] = "inspect"
80
+ read_only_params["instruction"] = intent_text
81
+ return {**args_obj, "params": read_only_params}
82
+
83
+ operation = str(params_obj.get("operation") or "").casefold()
84
+ changed = normalized_params != params_obj
85
+ if (
86
+ operation in {"fill", "save"}
87
+ and intent_text
88
+ and _DOCUMENT_WRITE_REQUEST_RE.search(intent_text)
89
+ ):
90
+ if _DOCUMENT_SAVE_REQUEST_RE.search(intent_text):
91
+ normalized_params["operation"] = "save"
92
+ normalized_params["instruction"] = intent_text
93
+ return {**args_obj, "params": normalized_params}
94
+ if operation not in {"inspect", "extract"}:
95
+ return {**args_obj, "params": normalized_params} if changed else args_obj
96
+ if _should_keep_read_only_for_question_first_authoring(intent_text):
97
+ return {**args_obj, "params": normalized_params} if changed else args_obj
98
+ if not intent_text or not _DOCUMENT_WRITE_REQUEST_RE.search(intent_text):
99
+ return {**args_obj, "params": normalized_params} if changed else args_obj
100
+
101
+ normalized_params["operation"] = (
102
+ "save" if _DOCUMENT_SAVE_REQUEST_RE.search(intent_text) else "fill"
103
+ )
104
+ normalized_params["instruction"] = intent_text
105
+ return {**args_obj, "params": normalized_params}
106
+
107
+
108
+ def _document_intent_text(params_obj: dict[str, object], latest_user_utt: str) -> str:
109
+ internal_user_query = params_obj.get(_DOCUMENT_INTERNAL_USER_QUERY_KEY)
110
+ if isinstance(internal_user_query, str) and internal_user_query.strip():
111
+ return internal_user_query.strip()
112
+ return latest_user_utt
113
+
114
+
115
+ def _synthesize_document_read_params(
116
+ params_obj: dict[str, object],
117
+ intent_text: str,
118
+ ) -> dict[str, object] | None:
119
+ if (
120
+ not intent_text
121
+ or isinstance(params_obj.get("document"), dict)
122
+ or set(params_obj) - _DOCUMENT_ROOT_SYNTHESIS_KEYS
123
+ ):
124
+ return None
125
+ local_path = _first_existing_document_path(intent_text, None)
126
+ if local_path is None:
127
+ return None
128
+ document_format = local_path.suffix.removeprefix(".").lower()
129
+ return {
130
+ "correlation_id": f"document-intent-{uuid.uuid4().hex}",
131
+ "document": {"path": str(local_path), "expected_format": document_format},
132
+ "operation": "inspect",
133
+ "instruction": intent_text,
134
+ }
135
+
136
+
137
+ def _normalize_document_path_from_user_query(
138
+ normalized_params: dict[str, object],
139
+ intent_text: str,
140
+ ) -> None:
141
+ if not intent_text:
142
+ return
143
+ document_obj = normalized_params.get("document")
144
+ if not isinstance(document_obj, dict):
145
+ return
146
+ current_path = document_obj.get("path")
147
+ if isinstance(current_path, str) and Path(current_path).expanduser().exists():
148
+ return
149
+ expected_format = document_obj.get("expected_format")
150
+ expected_suffix = f".{expected_format}".lower() if isinstance(expected_format, str) else None
151
+ explicit_path = _first_existing_document_path(intent_text, expected_suffix)
152
+ if explicit_path is None:
153
+ return
154
+ normalized_params["document"] = {
155
+ **document_obj,
156
+ "path": str(explicit_path),
157
+ }
158
+
159
+
160
+ def _first_existing_document_path(intent_text: str, expected_suffix: str | None) -> Path | None:
161
+ for match in _DOCUMENT_EXPLICIT_LOCAL_PATH_RE.finditer(intent_text):
162
+ candidate = Path(match.group("path").rstrip(".,;:)]})")).expanduser()
163
+ if expected_suffix is not None and candidate.suffix.lower() != expected_suffix:
164
+ continue
165
+ if candidate.exists():
166
+ return candidate.resolve()
167
+ return None
168
+
169
+
170
+ def _should_keep_read_only_for_question_first_authoring(intent_text: str) -> bool:
171
+ return bool(intent_text and _QUESTION_FIRST_AUTHORING_RE.search(intent_text))
172
+
173
+
174
+ def _is_explicit_read_only_inspect_intent(intent_text: str) -> bool:
175
+ return bool(
176
+ intent_text
177
+ and _DOCUMENT_READ_ONLY_INSPECT_RE.search(intent_text)
178
+ and _DOCUMENT_MUTATION_PROHIBITION_RE.search(intent_text)
179
+ )
180
+
181
+
182
+ def _strip_mutation_params(params_obj: dict[str, object]) -> dict[str, object]:
183
+ return {
184
+ key: value for key, value in params_obj.items() if key not in _DOCUMENT_MUTATION_PARAM_KEYS
185
+ }
@@ -56,6 +56,7 @@ _ROLE_KIND_ALLOW_LIST: dict[str, frozenset[str]] = {
56
56
  # Spec 1978 ADR-0001 — tools-aware chat request from TUI
57
57
  "chat_request": frozenset({"tui"}),
58
58
  "assistant_chunk": frozenset({"backend", "llm"}),
59
+ "progress_event": frozenset({"backend"}),
59
60
  "tool_call": frozenset({"backend", "tool"}),
60
61
  "tool_result": frozenset({"backend", "tool"}),
61
62
  "coordinator_phase": frozenset({"backend"}),
@@ -385,6 +386,10 @@ class ChatRequestFrame(_BaseFrame):
385
386
  le=1.0,
386
387
  description="Nucleus sampling threshold.",
387
388
  )
389
+ reasoning_mode: Literal["fast", "balanced", "deep", "diagnostic", "auto"] | None = Field(
390
+ default=None,
391
+ description="K-EXAONE/FriendliAI reasoning policy for this assistant turn.",
392
+ )
388
393
 
389
394
  @model_validator(mode="after")
390
395
  def _v_tool_message_integrity(self) -> ChatRequestFrame:
@@ -449,6 +454,46 @@ class AssistantChunkFrame(_BaseFrame):
449
454
  done: bool = Field(description="True if this is the terminal chunk for this message_id.")
450
455
 
451
456
 
457
+ # ---------------------------------------------------------------------------
458
+ # Arm: progress_event (UMMAYA query-loop painting — deterministic and safe)
459
+ # ---------------------------------------------------------------------------
460
+
461
+
462
+ class ProgressEventFrame(_BaseFrame):
463
+ """backend -> TUI: deterministic query-loop progress.
464
+
465
+ This is intentionally separate from ``AssistantChunkFrame.thinking``.
466
+ ``progress_event`` carries safe harness state such as analysis, tool
467
+ selection, tool dispatch/result, and answer synthesis. Provider reasoning
468
+ remains on the gated ``thinking_delta`` channel.
469
+ """
470
+
471
+ kind: Literal["progress_event"] = Field(
472
+ default="progress_event", description="Frame discriminator."
473
+ )
474
+ phase: Literal[
475
+ "analysis",
476
+ "tool_selection",
477
+ "tool_call",
478
+ "tool_result",
479
+ "answer_synthesis",
480
+ ] = Field(description="Safe query-loop phase represented by this event.")
481
+ message_ko: str = Field(min_length=1, description="Korean progress text for the TUI.")
482
+ message_en: str = Field(min_length=1, description="English fallback progress text.")
483
+ safe_to_persist: bool = Field(
484
+ default=True,
485
+ description="True because this channel never carries raw provider chain-of-thought.",
486
+ )
487
+ tool_id: str | None = Field(
488
+ default=None,
489
+ description="Concrete adapter/tool id when this event is tied to one.",
490
+ )
491
+ call_id: str | None = Field(
492
+ default=None,
493
+ description="Tool call id when this event is tied to a specific invocation.",
494
+ )
495
+
496
+
452
497
  # ---------------------------------------------------------------------------
453
498
  # Arm: tool_call (Spec 287 baseline — arguments changed from Any to dict[str, object])
454
499
  # ---------------------------------------------------------------------------
@@ -483,7 +528,7 @@ class ToolResultEnvelope(BaseModel):
483
528
 
484
529
  model_config = ConfigDict(frozen=True, extra="allow", populate_by_name=True)
485
530
 
486
- kind: Literal["find", "locate", "send", "check"] = Field(
531
+ kind: Literal["find", "locate", "send", "check", "document"] = Field(
487
532
  description="Primitive kind discriminator per Spec 031."
488
533
  )
489
534
 
@@ -531,7 +576,7 @@ class WorkerStatusFrame(_BaseFrame):
531
576
  role_id: str = Field(
532
577
  description="Specialist label (e.g., transport-specialist, health-specialist)."
533
578
  )
534
- current_primitive: Literal["find", "locate", "send", "check"] = Field(
579
+ current_primitive: Literal["find", "locate", "send", "check", "document"] = Field(
535
580
  description="Primitive currently being invoked by this worker."
536
581
  )
537
582
  status: Literal["idle", "running", "waiting_permission", "error"] = Field(
@@ -554,7 +599,7 @@ class PermissionRequestFrame(_BaseFrame):
554
599
  description="ULID; round-trips in the matching permission_response frame."
555
600
  )
556
601
  worker_id: str = Field(description="Worker requesting permission.")
557
- primitive_kind: Literal["find", "locate", "send", "check"] = Field(
602
+ primitive_kind: Literal["find", "locate", "send", "check", "document"] = Field(
558
603
  description="The primitive the worker wants to invoke."
559
604
  )
560
605
  description_ko: str = Field(description="Korean-language description shown to the citizen.")
@@ -624,7 +669,7 @@ class PermissionResponseFrame(_BaseFrame):
624
669
  # `layer: 1, tool_name: 'unknown'` (UI-C-1 spec violation: Layer 2/3
625
670
  # submits were colour-coded green like a Layer 1 verify).
626
671
  # Both fields are optional so legacy backends remain wire-compatible.
627
- primitive_kind: Literal["find", "locate", "send", "check"] | None = Field(
672
+ primitive_kind: Literal["find", "locate", "send", "check", "document"] | None = Field(
628
673
  default=None,
629
674
  description=(
630
675
  "The primitive that was authorised. The TUI feeds this into "
@@ -1175,7 +1220,7 @@ class AdapterManifestEntry(BaseModel):
1175
1220
  max_length=80,
1176
1221
  description="Human-readable display name; bilingual permitted.",
1177
1222
  )
1178
- primitive: Literal["find", "send", "check", "locate"] = Field(
1223
+ primitive: Literal["find", "send", "check", "locate", "document"] = Field(
1179
1224
  description="Primitive verb the adapter is registered under (I6).",
1180
1225
  )
1181
1226
  policy_authority_url: str | None = Field(
@@ -1436,6 +1481,7 @@ IPCFrame = Annotated[
1436
1481
  UserInputFrame
1437
1482
  | ChatRequestFrame
1438
1483
  | AssistantChunkFrame
1484
+ | ProgressEventFrame
1439
1485
  | ToolCallFrame
1440
1486
  | ToolResultFrame
1441
1487
  | CoordinatorPhaseFrame
@@ -1505,6 +1551,7 @@ __all__ = [
1505
1551
  "ToolDefinition",
1506
1552
  "ToolDefinitionFunction",
1507
1553
  "AssistantChunkFrame",
1554
+ "ProgressEventFrame",
1508
1555
  "ToolCallFrame",
1509
1556
  "ToolResultFrame",
1510
1557
  "ToolResultEnvelope",
@@ -0,0 +1,73 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import logging
7
+ from typing import Literal
8
+
9
+ from pydantic import BaseModel, ConfigDict, Field
10
+
11
+ from ummaya.tools.routing import RouteDecision, RouteStopReason, SchemaProjectionLevel
12
+
13
+
14
+ class RouteDecisionDiagnosticPayload(BaseModel):
15
+ model_config = ConfigDict(frozen=True, extra="forbid")
16
+
17
+ turn_index: int = Field(ge=1)
18
+ session_id: str = Field(min_length=1)
19
+ correlation_id: str = Field(min_length=1)
20
+ decision_id: str = Field(min_length=1)
21
+ query_hash: str = Field(min_length=64, max_length=64)
22
+ manifest_hash: str = Field(min_length=64, max_length=64)
23
+ backend_label: str = Field(min_length=1)
24
+ selected_tools: tuple[str, ...]
25
+ candidate_count: int = Field(ge=0)
26
+ effective_top_k: int = Field(ge=0)
27
+ schema_projection_level: SchemaProjectionLevel
28
+ stop_reason: RouteStopReason
29
+ permission_gate: bool
30
+ clarification_reason: (
31
+ Literal[
32
+ "missing_slots",
33
+ "equal_candidates",
34
+ "side_effect_confirmation",
35
+ "execution_risk_input_fault",
36
+ ]
37
+ | None
38
+ )
39
+ evidence_events: tuple[str, ...]
40
+
41
+
42
+ def log_route_decision_diagnostic(
43
+ *,
44
+ logger: logging.Logger,
45
+ turn_index: int,
46
+ session_id: str,
47
+ correlation_id: str,
48
+ decision: RouteDecision | None,
49
+ ) -> None:
50
+ if decision is None:
51
+ return
52
+ clarification_reason = None if decision.clarification is None else decision.clarification.reason
53
+ payload = RouteDecisionDiagnosticPayload(
54
+ turn_index=turn_index,
55
+ session_id=session_id,
56
+ correlation_id=correlation_id,
57
+ decision_id=decision.decision_id,
58
+ query_hash=decision.query_hash,
59
+ manifest_hash=decision.manifest_hash,
60
+ backend_label=decision.backend_label,
61
+ selected_tools=decision.selected_tools,
62
+ candidate_count=len(decision.candidate_set),
63
+ effective_top_k=decision.effective_top_k,
64
+ schema_projection_level=decision.schema_projection_level,
65
+ stop_reason=decision.stop_reason,
66
+ permission_gate=decision.permission_gate,
67
+ clarification_reason=clarification_reason,
68
+ evidence_events=decision.evidence_events,
69
+ )
70
+ logger.info(
71
+ "[ROUTE_DECISION] payload=%s",
72
+ json.dumps(payload.model_dump(mode="json"), ensure_ascii=False, sort_keys=True),
73
+ )