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
@@ -18,7 +18,7 @@ import { trace, SpanStatusCode } from '@opentelemetry/api'
18
18
  import type { Span } from '@opentelemetry/api'
19
19
  import type { IPCBridge } from './bridge.js'
20
20
  import { makeUUIDv7, makeBaseEnvelope } from './envelope.js'
21
- import type { AssistantChunkFrame, BackpressureSignalFrame, ChatMessage as IPCChatMessage, ChatRequestFrame, ErrorFrame, ToolCallFrame, ToolResultFrame, ToolDefinition as IPCToolDefinition } from './frames.generated.js'
21
+ import type { AssistantChunkFrame, BackpressureSignalFrame, ChatMessage as IPCChatMessage, ChatRequestFrame, ErrorFrame, ProgressEventFrame, ToolCallFrame, ToolResultFrame, ToolDefinition as IPCToolDefinition } from './frames.generated.js'
22
22
  import type { PendingCallRegistry } from '../tools/_shared/pendingCallRegistry.js'
23
23
  import { getOrCreatePendingCallRegistry } from './pendingCallSingleton.js'
24
24
  import type {
@@ -29,8 +29,13 @@ import type {
29
29
  UmmayaContentBlockParam,
30
30
  UmmayaStopReason,
31
31
  } from './llmTypes.js'
32
+ import {
33
+ extractTextualToolCallProposals,
34
+ parseTrailingRawJsonToolCallProposal,
35
+ } from '../utils/rawJsonToolCall.js'
32
36
 
33
37
  export const UMMAYA_DEFAULT_MODEL = 'LGAI-EXAONE/K-EXAONE-236B-A23B'
38
+ const TEXTUAL_TOOL_CALL_OPEN = '<tool_call>'
34
39
 
35
40
  export type LLMClientErrorClass = 'llm' | 'tool' | 'network'
36
41
 
@@ -78,11 +83,13 @@ const _tracer = trace.getTracer('ummaya.tui.llm', '0.1.0')
78
83
  interface _TurnAccumulator {
79
84
  messageId: string | null
80
85
  contentBlocks: UmmayaContentBlockParam[]
86
+ accumulatedText: string
87
+ emittedTextLength: number
88
+ shouldBufferTextDeltas: boolean
81
89
  usage: UmmayaUsage
82
90
  stopReason: UmmayaStopReason
83
- /** Index of the single text block. UMMAYA streams text into one block per
84
- * turn, so this stays at 0 and is the target of every `content_block_delta`
85
- * and the final `content_block_stop` for text. */
91
+ /** Index of the current text block. It is opened lazily on the first
92
+ * CC-compatible text delta, not at message_start. */
86
93
  blockIndex: number
87
94
  /** Monotonic counter for tool_use blocks within this turn. The nth
88
95
  * tool_use block lands at index `blockIndex + n` (so text is 0, tool
@@ -94,9 +101,11 @@ interface _TurnAccumulator {
94
101
  * channel is forwarded by the backend as `AssistantChunkFrame.thinking`;
95
102
  * llmClient mirrors CC's claude.ts:2148-2165 by routing those chunks to
96
103
  * a dedicated thinking content block (`type: 'thinking'`). The block
97
- * is opened lazily on the first thinking delta and closed at the same
98
- * time as the text block (done frame). Undefined until first delta. */
104
+ * is opened lazily on the first thinking delta and closed before text/tool
105
+ * blocks, matching CC's one-open-content-block stream shape. */
99
106
  thinkingBlockIndex: number | undefined
107
+ /** Currently open non-tool block. CC closes text/thinking before tool_use. */
108
+ openBlockIndex: number | undefined
100
109
  seenFirstChunk: boolean
101
110
  }
102
111
 
@@ -104,22 +113,34 @@ function _defaultAccumulator(): _TurnAccumulator {
104
113
  return {
105
114
  messageId: null,
106
115
  contentBlocks: [],
116
+ accumulatedText: '',
117
+ emittedTextLength: 0,
118
+ shouldBufferTextDeltas: false,
107
119
  usage: { input_tokens: 0, output_tokens: 0 },
108
120
  stopReason: 'end_turn',
109
- blockIndex: 0,
121
+ blockIndex: -1,
110
122
  toolBlockCounter: 0,
111
123
  thinkingBlockIndex: undefined,
124
+ openBlockIndex: undefined,
112
125
  seenFirstChunk: false,
113
126
  }
114
127
  }
115
128
 
129
+ function firstToolCallTextOffset(text: string): number {
130
+ const braceOffset = text.indexOf('{')
131
+ const tagOffset = text.indexOf(TEXTUAL_TOOL_CALL_OPEN)
132
+ if (braceOffset < 0) return tagOffset
133
+ if (tagOffset < 0) return braceOffset
134
+ return Math.min(braceOffset, tagOffset)
135
+ }
136
+
116
137
  // ---------------------------------------------------------------------------
117
138
  // Helper: extract usage from an AssistantChunkFrame done-trailer.
118
139
  //
119
140
  // Spec 032 does not currently define a typed usage payload on the frame itself;
120
141
  // the Python backend is expected to embed usage counts in the frame's `trailer`
121
142
  // extra fields or in a sibling ephemeral dict. Until the backend-side contract
122
- // is finalised in Spec 032 US4, we read from `(frame as any).usage` first
143
+ // is finalised in Spec 032 US4, we read from the typed legacy `usage` field first
123
144
  // (a forward-compatible extension field the backend may include) and fall back
124
145
  // to zeros. A TODO(T091) marks the binding point for the actual backend wiring.
125
146
  // ---------------------------------------------------------------------------
@@ -299,6 +320,9 @@ export class LLMClient {
299
320
  ...(params.system !== undefined ? { system: params.system } : {}),
300
321
  max_tokens: params.max_tokens,
301
322
  ...(params.temperature !== undefined ? { temperature: params.temperature } : {}),
323
+ ...(params.reasoning_mode !== undefined
324
+ ? { reasoning_mode: params.reasoning_mode }
325
+ : {}),
302
326
  }
303
327
 
304
328
  // ----------------------------------------------------------------
@@ -339,11 +363,206 @@ export class LLMClient {
339
363
  // primitive bridge for all tool dispatch; no server-side tools
340
364
  // ----------------------------------------------------------------
341
365
  let streamDone = false
366
+ const model = this.model
367
+ const ensureMessageStart = function* (
368
+ messageId: string,
369
+ ): Generator<UmmayaRawMessageStreamEvent, void, unknown> {
370
+ if (acc.seenFirstChunk) return
371
+ acc.seenFirstChunk = true
372
+ acc.messageId = messageId
373
+ yield {
374
+ type: 'message_start',
375
+ message: {
376
+ id: messageId,
377
+ role: 'assistant',
378
+ model,
379
+ },
380
+ } satisfies UmmayaRawMessageStreamEvent
381
+ }
382
+
383
+ const closeOpenBlock = function* (): Generator<
384
+ UmmayaRawMessageStreamEvent,
385
+ void,
386
+ unknown
387
+ > {
388
+ if (acc.openBlockIndex === undefined) return
389
+ yield {
390
+ type: 'content_block_stop',
391
+ index: acc.openBlockIndex,
392
+ } satisfies UmmayaRawMessageStreamEvent
393
+ acc.openBlockIndex = undefined
394
+ }
395
+
396
+ const ensureTextBlock = function* (): Generator<
397
+ UmmayaRawMessageStreamEvent,
398
+ void,
399
+ unknown
400
+ > {
401
+ if (acc.openBlockIndex === acc.blockIndex && acc.blockIndex >= 0) {
402
+ return
403
+ }
404
+ yield* closeOpenBlock()
405
+ const textIndex = acc.contentBlocks.length
406
+ acc.blockIndex = textIndex
407
+ acc.contentBlocks[textIndex] = { type: 'text', text: '' }
408
+ acc.openBlockIndex = textIndex
409
+ yield {
410
+ type: 'content_block_start',
411
+ index: textIndex,
412
+ content_block: { type: 'text', text: '' },
413
+ } satisfies UmmayaRawMessageStreamEvent
414
+ }
415
+
416
+ const ensureThinkingBlock = function* (): Generator<
417
+ UmmayaRawMessageStreamEvent,
418
+ void,
419
+ unknown
420
+ > {
421
+ if (
422
+ acc.thinkingBlockIndex !== undefined &&
423
+ acc.openBlockIndex === acc.thinkingBlockIndex
424
+ ) {
425
+ return
426
+ }
427
+ yield* closeOpenBlock()
428
+ const thinkingIdx = acc.contentBlocks.length
429
+ acc.thinkingBlockIndex = thinkingIdx
430
+ acc.contentBlocks[thinkingIdx] = { type: 'thinking', thinking: '' }
431
+ acc.openBlockIndex = thinkingIdx
432
+ yield {
433
+ type: 'content_block_start',
434
+ index: thinkingIdx,
435
+ content_block: { type: 'thinking', thinking: '' },
436
+ } satisfies UmmayaRawMessageStreamEvent
437
+ }
438
+
439
+ const appendVisibleTextDelta = function* (
440
+ text: string,
441
+ previousTextLength: number,
442
+ ): Generator<UmmayaRawMessageStreamEvent, void, unknown> {
443
+ if (text.length === 0) return
444
+ yield* ensureTextBlock()
445
+ yield {
446
+ type: 'content_block_delta',
447
+ index: acc.blockIndex,
448
+ delta: { type: 'text_delta', text },
449
+ } satisfies UmmayaRawMessageStreamEvent
450
+
451
+ const existing = acc.contentBlocks[acc.blockIndex]
452
+ if (existing && existing.type === 'text') {
453
+ existing.text += text
454
+ } else {
455
+ acc.contentBlocks[acc.blockIndex] = { type: 'text', text }
456
+ }
457
+ acc.emittedTextLength = previousTextLength + text.length
458
+ }
459
+
460
+ const appendAssistantText = function* (
461
+ text: string,
462
+ ): Generator<UmmayaRawMessageStreamEvent, void, unknown> {
463
+ if (text.length === 0) return
464
+ const previousTextLength = acc.accumulatedText.length
465
+ const bufferOffset = firstToolCallTextOffset(text)
466
+ const startsBuffering = !acc.shouldBufferTextDeltas && bufferOffset >= 0
467
+ if (startsBuffering) acc.shouldBufferTextDeltas = true
468
+ acc.accumulatedText += text
469
+ if (startsBuffering) {
470
+ if (bufferOffset > 0) {
471
+ yield* appendVisibleTextDelta(
472
+ text.slice(0, bufferOffset),
473
+ previousTextLength,
474
+ )
475
+ }
476
+ return
477
+ }
478
+ if (!acc.shouldBufferTextDeltas) {
479
+ yield* appendVisibleTextDelta(text, previousTextLength)
480
+ }
481
+ }
482
+
483
+ const flushBufferedText = function* (): Generator<
484
+ UmmayaRawMessageStreamEvent,
485
+ void,
486
+ unknown
487
+ > {
488
+ if (acc.accumulatedText.length <= acc.emittedTextLength) return
489
+ yield* appendVisibleTextDelta(
490
+ acc.accumulatedText.slice(acc.emittedTextLength),
491
+ acc.emittedTextLength,
492
+ )
493
+ }
494
+
495
+ const flushPreludeBeforeRawJsonToolUse = function* (
496
+ prelude: string,
497
+ ): Generator<UmmayaRawMessageStreamEvent, void, unknown> {
498
+ if (prelude.length <= acc.emittedTextLength) return
499
+ yield* appendVisibleTextDelta(
500
+ prelude.slice(acc.emittedTextLength),
501
+ acc.emittedTextLength,
502
+ )
503
+ }
504
+
505
+ const appendRawJsonToolUseBlock = function* (params: {
506
+ readonly name: string
507
+ readonly input: Record<string, unknown>
508
+ readonly id?: string
509
+ }): Generator<UmmayaRawMessageStreamEvent, void, unknown> {
510
+ const toolBlockIndex = acc.contentBlocks.length
511
+ acc.toolBlockCounter += 1
512
+ const toolUseId = params.id ?? 'call_raw_json_tool_0'
513
+ yield {
514
+ type: 'content_block_start',
515
+ index: toolBlockIndex,
516
+ content_block: {
517
+ type: 'tool_use',
518
+ id: toolUseId,
519
+ name: params.name,
520
+ input: params.input,
521
+ },
522
+ } satisfies UmmayaRawMessageStreamEvent
523
+ yield {
524
+ type: 'content_block_stop',
525
+ index: toolBlockIndex,
526
+ } satisfies UmmayaRawMessageStreamEvent
527
+ acc.contentBlocks[toolBlockIndex] = {
528
+ type: 'tool_use',
529
+ id: toolUseId,
530
+ name: params.name,
531
+ input: params.input,
532
+ }
533
+ acc.stopReason = 'tool_use'
534
+ }
342
535
 
343
536
  for await (const frame of this.bridge.frames()) {
344
537
  // Filter: only process frames for this turn's correlation_id.
345
538
  if (frame.correlation_id !== correlationId) continue
346
539
 
540
+ // ---- ProgressEventFrame ----------------------------------------
541
+ // Deterministic harness progress. This is safe UI state, not provider
542
+ // reasoning. It paints even when reasoning mode suppresses thinking.
543
+ if (frame.kind === 'progress_event') {
544
+ const progress = frame as ProgressEventFrame
545
+ yield* ensureMessageStart(`progress-${correlationId}`)
546
+ yield* ensureTextBlock()
547
+
548
+ const progressText = `${
549
+ progress.message_ko ?? progress.message_en ?? progress.phase
550
+ }\n`
551
+ yield {
552
+ type: 'content_block_delta',
553
+ index: acc.blockIndex,
554
+ delta: {
555
+ type: 'text_delta',
556
+ text: progressText,
557
+ },
558
+ } satisfies UmmayaRawMessageStreamEvent
559
+ const existing = acc.contentBlocks[acc.blockIndex]
560
+ if (existing && existing.type === 'text') {
561
+ existing.text += progressText
562
+ }
563
+ continue
564
+ }
565
+
347
566
  // ---- AssistantChunkFrame ----------------------------------------
348
567
  // CC reference: services/api/claude.ts:1980-2169 (the message_start +
349
568
  // content_block_start + content_block_delta + content_block_stop
@@ -356,26 +575,7 @@ export class LLMClient {
356
575
  // CC reference: services/api/claude.ts:1980 (message_start),
357
576
  // services/api/claude.ts:2019 (text content_block_start).
358
577
  if (!acc.seenFirstChunk) {
359
- acc.seenFirstChunk = true
360
- acc.messageId = chunk.message_id
361
-
362
- yield {
363
- type: 'message_start',
364
- message: {
365
- id: chunk.message_id,
366
- role: 'assistant',
367
- model: this.model,
368
- },
369
- } satisfies UmmayaRawMessageStreamEvent
370
-
371
- yield {
372
- type: 'content_block_start',
373
- index: 0,
374
- content_block: { type: 'text', text: '' },
375
- } satisfies UmmayaRawMessageStreamEvent
376
-
377
- acc.blockIndex = 0
378
- acc.contentBlocks[0] = { type: 'text', text: '' }
578
+ yield* ensureMessageStart(chunk.message_id)
379
579
  }
380
580
 
381
581
  // Thinking delta — K-EXAONE's reasoning_content channel arrives
@@ -384,17 +584,8 @@ export class LLMClient {
384
584
  // `type: 'thinking'` blocks and route them to the
385
585
  // AssistantThinkingMessage component (∴ Thinking dim italic).
386
586
  if (chunk.thinking && chunk.thinking.length > 0) {
387
- if (acc.thinkingBlockIndex === undefined) {
388
- const thinkingIdx = acc.contentBlocks.length
389
- acc.thinkingBlockIndex = thinkingIdx
390
- yield {
391
- type: 'content_block_start',
392
- index: thinkingIdx,
393
- content_block: { type: 'thinking', thinking: '' },
394
- } satisfies UmmayaRawMessageStreamEvent
395
- acc.contentBlocks[thinkingIdx] = { type: 'thinking', thinking: '' }
396
- }
397
- const thinkingIdx = acc.thinkingBlockIndex
587
+ yield* ensureThinkingBlock()
588
+ const thinkingIdx = acc.thinkingBlockIndex!
398
589
  yield {
399
590
  type: 'content_block_delta',
400
591
  index: thinkingIdx,
@@ -408,20 +599,7 @@ export class LLMClient {
408
599
 
409
600
  // Emit text delta (even if delta is empty — forward compat).
410
601
  if (chunk.delta.length > 0) {
411
- yield {
412
- type: 'content_block_delta',
413
- index: acc.blockIndex,
414
- delta: { type: 'text_delta', text: chunk.delta },
415
- } satisfies UmmayaRawMessageStreamEvent
416
-
417
- // Accumulate text into the content block for the final object.
418
- const existing = acc.contentBlocks[acc.blockIndex]
419
- if (existing && existing.type === 'text') {
420
- existing.text += chunk.delta
421
- } else {
422
- // First delta for this block index.
423
- acc.contentBlocks[acc.blockIndex] = { type: 'text', text: chunk.delta }
424
- }
602
+ yield* appendAssistantText(chunk.delta)
425
603
  }
426
604
  } else {
427
605
  // done=true: terminal chunk (V2 invariant satisfied here).
@@ -429,33 +607,42 @@ export class LLMClient {
429
607
  // If we never saw a first chunk (edge: backend sends done=true
430
608
  // immediately on an empty response), bootstrap the message events.
431
609
  if (!acc.seenFirstChunk) {
432
- acc.seenFirstChunk = true
433
- acc.messageId = chunk.message_id
434
- yield {
435
- type: 'message_start',
436
- message: { id: chunk.message_id, role: 'assistant', model: this.model },
437
- } satisfies UmmayaRawMessageStreamEvent
438
- yield {
439
- type: 'content_block_start',
440
- index: 0,
441
- content_block: { type: 'text', text: '' },
442
- } satisfies UmmayaRawMessageStreamEvent
443
- acc.blockIndex = 0
610
+ yield* ensureMessageStart(chunk.message_id)
444
611
  }
445
612
 
446
613
  // Emit any final delta text if present.
447
614
  if (chunk.delta.length > 0) {
448
- yield {
449
- type: 'content_block_delta',
450
- index: acc.blockIndex,
451
- delta: { type: 'text_delta', text: chunk.delta },
452
- } satisfies UmmayaRawMessageStreamEvent
453
- const existing = acc.contentBlocks[acc.blockIndex]
454
- if (existing && existing.type === 'text') {
455
- existing.text += chunk.delta
456
- } else {
457
- acc.contentBlocks[acc.blockIndex] = { type: 'text', text: chunk.delta }
615
+ yield* appendAssistantText(chunk.delta)
616
+ }
617
+
618
+ const textualToolUse = extractTextualToolCallProposals({
619
+ text: acc.accumulatedText,
620
+ })
621
+ const rawJsonToolUse = textualToolUse === undefined
622
+ ? parseTrailingRawJsonToolCallProposal({
623
+ text: acc.accumulatedText,
624
+ })
625
+ : undefined
626
+ if (textualToolUse !== undefined || rawJsonToolUse !== undefined) {
627
+ const prelude = textualToolUse?.text ?? rawJsonToolUse?.prelude ?? ''
628
+ yield* flushPreludeBeforeRawJsonToolUse(prelude)
629
+ yield* closeOpenBlock()
630
+ const proposals = textualToolUse?.proposals ??
631
+ (rawJsonToolUse !== undefined ? [rawJsonToolUse.proposal] : [])
632
+ for (let index = 0; index < proposals.length; index += 1) {
633
+ const proposal = proposals[index]
634
+ if (!proposal) continue
635
+ yield* appendRawJsonToolUseBlock({
636
+ name: proposal.name,
637
+ input: proposal.input,
638
+ id: textualToolUse !== undefined
639
+ ? `call_textual_tool_${index}`
640
+ : 'call_raw_json_tool_0',
641
+ })
458
642
  }
643
+ acc.accumulatedText = prelude
644
+ } else if (acc.shouldBufferTextDeltas) {
645
+ yield* flushBufferedText()
459
646
  }
460
647
 
461
648
  // Extract usage from the done-frame.
@@ -463,7 +650,7 @@ export class LLMClient {
463
650
  acc.usage = usage
464
651
 
465
652
  // CC reference: services/api/claude.ts:2171 (content_block_stop).
466
- yield { type: 'content_block_stop', index: acc.blockIndex } satisfies UmmayaRawMessageStreamEvent
653
+ yield* closeOpenBlock()
467
654
 
468
655
  // CC reference: services/api/claude.ts:2213 (message_delta with
469
656
  // stop_reason + usage).
@@ -490,6 +677,11 @@ export class LLMClient {
490
677
  // initial content_block_start payload.
491
678
  else if (frame.kind === 'tool_call') {
492
679
  const toolFrame = frame as ToolCallFrame
680
+ yield* ensureMessageStart(`tool-${correlationId}`)
681
+ if (acc.shouldBufferTextDeltas) {
682
+ yield* flushBufferedText()
683
+ }
684
+ yield* closeOpenBlock()
493
685
  // tool_call frames may arrive interleaved with text streaming AND
494
686
  // thinking streaming in a multi-turn / parallel-tool / K-EXAONE
495
687
  // reasoning scenario. Allocate the tool block at the next free
@@ -526,6 +718,17 @@ export class LLMClient {
526
718
  name: toolFrame.name,
527
719
  input: toolFrame.arguments as Record<string, unknown>,
528
720
  }
721
+
722
+ acc.stopReason = 'tool_use'
723
+ yield {
724
+ type: 'message_delta',
725
+ delta: { stop_reason: 'tool_use' },
726
+ usage: acc.usage,
727
+ } satisfies UmmayaRawMessageStreamEvent
728
+ yield { type: 'message_stop' } satisfies UmmayaRawMessageStreamEvent
729
+
730
+ streamDone = true
731
+ break
529
732
  }
530
733
 
531
734
  // ---- ToolResultFrame (I-D5 + Epic ζ smoke checkpoint, FR-013) ----
@@ -66,6 +66,7 @@ export type UmmayaMessageStreamParams = {
66
66
  tools?: UmmayaToolDefinition[]
67
67
  max_tokens: number
68
68
  temperature?: number
69
+ reasoning_mode?: import('../utils/kExaoneReasoning.js').ReasoningMode
69
70
  metadata?: Record<string, string>
70
71
  }
71
72
 
@@ -121,10 +122,24 @@ export type UmmayaThinkingDelta = {
121
122
  thinking: string
122
123
  }
123
124
 
125
+ export type UmmayaProgressDelta = {
126
+ type: 'progress_event'
127
+ phase: 'analysis' | 'tool_selection' | 'tool_call' | 'tool_result' | 'answer_synthesis'
128
+ message_ko: string
129
+ message_en: string
130
+ safe_to_persist: boolean
131
+ tool_id?: string | null
132
+ call_id?: string | null
133
+ }
134
+
124
135
  export type UmmayaContentBlockDelta = {
125
136
  type: 'content_block_delta'
126
137
  index: number
127
- delta: UmmayaTextDelta | UmmayaInputJsonDelta | UmmayaThinkingDelta
138
+ delta:
139
+ | UmmayaTextDelta
140
+ | UmmayaInputJsonDelta
141
+ | UmmayaThinkingDelta
142
+ | UmmayaProgressDelta
128
143
  }
129
144
 
130
145
  export type UmmayaContentBlockStop = {