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,430 @@
1
+ import { randomUUID } from 'crypto'
2
+ import { APIUserAbortError } from 'src/sdk-compat.js'
3
+ import {
4
+ getOrCreateUmmayaBridge,
5
+ getUmmayaBridgeSessionId,
6
+ } from '../../../ipc/bridgeSingleton.js'
7
+ import type {
8
+ ChatRequestFrame,
9
+ IPCFrame,
10
+ } from '../../../ipc/frames.generated.js'
11
+ import { buildChatMessagesFromTranscript } from '../../../query/chatMessagesBuilder.js'
12
+ import { getToolDefinitionsForFrame } from '../../../query/toolSerialization.js'
13
+ import { assertFriendliApiKeyForUse } from '../../../utils/auth.js'
14
+ import { createAssistantMessage } from '../../../utils/assistantMessageFactories.js'
15
+ import {
16
+ extractTextualToolCallProposals,
17
+ parseTrailingRawJsonToolCallProposal,
18
+ } from '../../../utils/rawJsonToolCall.js'
19
+ import {
20
+ createContentBlockStopEvent,
21
+ createMessageDeltaEvent,
22
+ createMessageStartStreamEvent,
23
+ createMessageStopEvent,
24
+ createTextBlockStartEvent,
25
+ createTextDeltaEvent,
26
+ createThinkingBlockStartEvent,
27
+ createThinkingDeltaEvent,
28
+ createToolUseBlockStartEvent,
29
+ } from './events.js'
30
+ import { createFinalAssistantMessage } from './finalMessage.js'
31
+ import { toNonEmptyMessages } from './frame.js'
32
+ import {
33
+ createBackendChatState,
34
+ hasAssistantPayload,
35
+ type BackendChatParams,
36
+ type BackendChatState,
37
+ } from './types.js'
38
+
39
+ const LLM_STREAM_ERROR_CODE = 'llm_stream_error'
40
+ const STREAM_TIMEOUT_PATTERN = /\b(?:timeout|timed out|idle)\b/iu
41
+ const LLM_STREAM_TIMEOUT_HANDOFF =
42
+ 'K-EXAONE 응답이 지연되어 이번 요청을 이어갈 수 없습니다. 잠시 후 다시 시도해 주세요.'
43
+ const DEFAULT_FRAME_IDLE_TIMEOUT_MS = 90_000
44
+ const TEXTUAL_TOOL_CALL_OPEN = '<tool_call>'
45
+
46
+ export async function* queryModelWithStreaming(
47
+ params: BackendChatParams,
48
+ ): AsyncGenerator<unknown> {
49
+ const { messages, signal } = params
50
+ assertFriendliApiKeyForUse()
51
+
52
+ const correlationId = randomUUID()
53
+ const messageUuid = randomUUID()
54
+ const innerMessageId = randomUUID()
55
+ const turnStartedAt = performance.now()
56
+ const bridge = getOrCreateUmmayaBridge()
57
+ const requestFrame: ChatRequestFrame = {
58
+ session_id: getUmmayaBridgeSessionId(),
59
+ correlation_id: correlationId,
60
+ ts: new Date().toISOString(),
61
+ role: 'tui',
62
+ kind: 'chat_request',
63
+ messages: toNonEmptyMessages(buildChatMessagesFromTranscript(messages)),
64
+ tools: await getToolDefinitionsForFrame(),
65
+ }
66
+
67
+ yield { type: 'stream_request_start' as const }
68
+
69
+ const sent = bridge.send(requestFrame)
70
+ if (!sent) {
71
+ throw new Error('UMMAYA bridge send failed (backend exited)')
72
+ }
73
+
74
+ const persistThinking = process.env.UMMAYA_PERSIST_THINKING === '1'
75
+ const state = createBackendChatState()
76
+ const frameIdleTimeoutMs = getFrameIdleTimeoutMs()
77
+ const frameIterator = bridge.frames()[Symbol.asyncIterator]()
78
+ let correlatedFrameDeadline = performance.now() + frameIdleTimeoutMs
79
+
80
+ while (true) {
81
+ if (signal?.aborted) throw new APIUserAbortError()
82
+ const timeoutMs = correlatedFrameDeadline - performance.now()
83
+ const nextFrame = await readNextFrame(frameIterator, timeoutMs)
84
+ if (nextFrame === 'timeout') {
85
+ yield createAssistantMessage({
86
+ content: LLM_STREAM_TIMEOUT_HANDOFF,
87
+ })
88
+ yield* stopOpenBlocks(state)
89
+ if (state.messageStartEmitted) yield createMessageStopEvent()
90
+ return
91
+ }
92
+ if (nextFrame.done) break
93
+ const frame = nextFrame.value
94
+ if (frame.correlation_id !== correlationId) continue
95
+ correlatedFrameDeadline = performance.now() + frameIdleTimeoutMs
96
+
97
+ if (frame.kind === 'assistant_chunk') {
98
+ yield* handleAssistantChunk({
99
+ frame,
100
+ state,
101
+ persistThinking,
102
+ turnStartedAt,
103
+ innerMessageId,
104
+ messageUuid,
105
+ })
106
+ if (frame.done) return
107
+ } else if (frame.kind === 'tool_call') {
108
+ yield* handleToolCallFrame({
109
+ frame,
110
+ state,
111
+ persistThinking,
112
+ turnStartedAt,
113
+ innerMessageId,
114
+ messageUuid,
115
+ })
116
+ return
117
+ } else if (frame.kind === 'error') {
118
+ yield createAssistantMessage({
119
+ content: formatBackendErrorMessage(frame),
120
+ })
121
+ yield* stopOpenBlocks(state)
122
+ if (state.messageStartEmitted) yield createMessageStopEvent()
123
+ return
124
+ }
125
+ }
126
+
127
+ if (hasAssistantPayload(state, persistThinking) || !state.messageStartEmitted) {
128
+ yield createFinalAssistantMessage({
129
+ accumulated: state.accumulated,
130
+ accumulatedThinking: state.accumulatedThinking,
131
+ messageUuid,
132
+ innerMessageId,
133
+ pendingContentBlocks: state.pendingContentBlocks,
134
+ persistThinking,
135
+ })
136
+ }
137
+ if (state.messageStartEmitted) {
138
+ yield* stopOpenBlocks(state)
139
+ yield createMessageStopEvent()
140
+ }
141
+ }
142
+
143
+ function getFrameIdleTimeoutMs(): number {
144
+ const raw = process.env.UMMAYA_TUI_FRAME_IDLE_TIMEOUT_MS
145
+ if (raw === undefined) return DEFAULT_FRAME_IDLE_TIMEOUT_MS
146
+ const parsed = Number.parseInt(raw, 10)
147
+ if (!Number.isFinite(parsed) || parsed <= 0) return DEFAULT_FRAME_IDLE_TIMEOUT_MS
148
+ return parsed
149
+ }
150
+
151
+ async function readNextFrame(
152
+ iterator: AsyncIterator<IPCFrame>,
153
+ timeoutMs: number,
154
+ ): Promise<IteratorResult<IPCFrame> | 'timeout'> {
155
+ if (timeoutMs <= 0) return 'timeout'
156
+ let timeoutId: ReturnType<typeof setTimeout> | undefined
157
+ const timeout = new Promise<'timeout'>(resolve => {
158
+ timeoutId = setTimeout(() => resolve('timeout'), timeoutMs)
159
+ })
160
+ const result = await Promise.race([iterator.next(), timeout])
161
+ if (timeoutId !== undefined) clearTimeout(timeoutId)
162
+ if (result === 'timeout') {
163
+ void iterator.return?.()
164
+ }
165
+ return result
166
+ }
167
+
168
+ function formatBackendErrorMessage(
169
+ frame: Extract<IPCFrame, { kind?: 'error' }>,
170
+ ): string {
171
+ if (
172
+ frame.code === LLM_STREAM_ERROR_CODE &&
173
+ STREAM_TIMEOUT_PATTERN.test(frame.message)
174
+ ) {
175
+ return LLM_STREAM_TIMEOUT_HANDOFF
176
+ }
177
+ return `[UMMAYA backend error] ${frame.message}`
178
+ }
179
+
180
+ function* handleAssistantChunk({
181
+ frame,
182
+ state,
183
+ persistThinking,
184
+ turnStartedAt,
185
+ innerMessageId,
186
+ messageUuid,
187
+ }: {
188
+ readonly frame: Extract<IPCFrame, { kind?: 'assistant_chunk' }>
189
+ readonly state: BackendChatState
190
+ readonly persistThinking: boolean
191
+ readonly turnStartedAt: number
192
+ readonly innerMessageId: string
193
+ readonly messageUuid: string
194
+ }): Generator<unknown> {
195
+ yield* startMessageIfNeeded(state, innerMessageId, turnStartedAt)
196
+ const thinkingText = frame.thinking ?? ''
197
+ if (thinkingText.length > 0) yield* appendThinking(state, thinkingText, persistThinking)
198
+
199
+ const deltaText = frame.delta ?? ''
200
+ state.accumulated += deltaText
201
+ if (deltaText.length > 0) yield* appendText(state, deltaText)
202
+
203
+ if (!frame.done) return
204
+ const textualToolUse = extractTextualToolCallProposals({
205
+ text: state.accumulated,
206
+ })
207
+ const rawJsonToolUse = textualToolUse === undefined
208
+ ? parseTrailingRawJsonToolCallProposal({
209
+ text: state.accumulated,
210
+ })
211
+ : undefined
212
+ if (
213
+ (textualToolUse !== undefined || rawJsonToolUse !== undefined) &&
214
+ state.pendingContentBlocks.length === 0
215
+ ) {
216
+ const prelude = textualToolUse?.text ?? rawJsonToolUse?.prelude ?? ''
217
+ yield* flushTextPreludeBeforeRawJsonToolUse(state, prelude)
218
+ yield* stopOpenBlocks(state)
219
+ const proposals = textualToolUse?.proposals ??
220
+ (rawJsonToolUse !== undefined ? [rawJsonToolUse.proposal] : [])
221
+ for (let index = 0; index < proposals.length; index += 1) {
222
+ const proposal = proposals[index]
223
+ if (!proposal) continue
224
+ yield* appendRawJsonToolUseBlock({
225
+ state,
226
+ name: proposal.name,
227
+ input: proposal.input,
228
+ id: textualToolUse !== undefined
229
+ ? `call_textual_tool_${index}`
230
+ : 'call_raw_json_tool_0',
231
+ })
232
+ }
233
+ state.accumulated = prelude
234
+ yield createFinalAssistantMessage({
235
+ accumulated: state.accumulated,
236
+ accumulatedThinking: state.accumulatedThinking,
237
+ messageUuid,
238
+ innerMessageId,
239
+ pendingContentBlocks: state.pendingContentBlocks,
240
+ persistThinking,
241
+ })
242
+ yield createMessageDeltaEvent('tool_use')
243
+ yield createMessageStopEvent()
244
+ return
245
+ }
246
+ if (state.shouldBufferTextDeltas) {
247
+ yield* flushBufferedText(state)
248
+ }
249
+ yield* stopOpenBlocks(state)
250
+ if (hasAssistantPayload(state, persistThinking) || !state.messageStartEmitted) {
251
+ yield createFinalAssistantMessage({
252
+ accumulated: state.accumulated,
253
+ accumulatedThinking: state.accumulatedThinking,
254
+ messageUuid,
255
+ innerMessageId,
256
+ pendingContentBlocks: state.pendingContentBlocks,
257
+ persistThinking,
258
+ })
259
+ }
260
+ if (state.messageStartEmitted) {
261
+ yield createMessageDeltaEvent('end_turn')
262
+ yield createMessageStopEvent()
263
+ }
264
+ }
265
+
266
+ function* handleToolCallFrame({
267
+ frame,
268
+ state,
269
+ persistThinking,
270
+ turnStartedAt,
271
+ innerMessageId,
272
+ messageUuid,
273
+ }: {
274
+ readonly frame: Extract<IPCFrame, { kind?: 'tool_call' }>
275
+ readonly state: BackendChatState
276
+ readonly persistThinking: boolean
277
+ readonly turnStartedAt: number
278
+ readonly innerMessageId: string
279
+ readonly messageUuid: string
280
+ }): Generator<unknown> {
281
+ yield* startMessageIfNeeded(state, innerMessageId, turnStartedAt)
282
+ if (state.shouldBufferTextDeltas) {
283
+ yield* flushBufferedText(state)
284
+ }
285
+ yield* stopOpenBlocks(state)
286
+
287
+ const toolUseBlock = {
288
+ type: 'tool_use' as const,
289
+ id: frame.call_id,
290
+ name: frame.name,
291
+ input: frame.arguments,
292
+ }
293
+ state.pendingContentBlocks.push(toolUseBlock)
294
+ const toolBlockIndex = state.nextContentBlockIndex
295
+ state.nextContentBlockIndex += 1
296
+
297
+ yield createToolUseBlockStartEvent(toolBlockIndex, toolUseBlock)
298
+ yield createContentBlockStopEvent(toolBlockIndex)
299
+ yield createFinalAssistantMessage({
300
+ accumulated: state.accumulated,
301
+ accumulatedThinking: state.accumulatedThinking,
302
+ messageUuid,
303
+ innerMessageId,
304
+ pendingContentBlocks: state.pendingContentBlocks,
305
+ persistThinking,
306
+ })
307
+ yield createMessageDeltaEvent('tool_use')
308
+ yield createMessageStopEvent()
309
+ }
310
+
311
+ function* startMessageIfNeeded(
312
+ state: BackendChatState,
313
+ innerMessageId: string,
314
+ turnStartedAt: number,
315
+ ): Generator<unknown> {
316
+ if (state.messageStartEmitted) return
317
+ yield createMessageStartStreamEvent(innerMessageId, performance.now() - turnStartedAt)
318
+ state.messageStartEmitted = true
319
+ }
320
+
321
+ function* appendThinking(
322
+ state: BackendChatState,
323
+ text: string,
324
+ persistThinking: boolean,
325
+ ): Generator<unknown> {
326
+ if (state.thinkingBlockIndex === null) {
327
+ yield createThinkingBlockStartEvent(state.nextContentBlockIndex)
328
+ state.thinkingBlockIndex = state.nextContentBlockIndex
329
+ state.nextContentBlockIndex += 1
330
+ }
331
+ if (persistThinking) state.accumulatedThinking += text
332
+ yield createThinkingDeltaEvent(state.thinkingBlockIndex, text)
333
+ }
334
+
335
+ function* appendText(state: BackendChatState, text: string): Generator<unknown> {
336
+ const previousTextLength = state.accumulated.length - text.length
337
+ const bufferOffset = firstToolCallTextOffset(text)
338
+ const startsBuffering = !state.shouldBufferTextDeltas && bufferOffset >= 0
339
+ if (startsBuffering) state.shouldBufferTextDeltas = true
340
+ if (startsBuffering) {
341
+ if (bufferOffset > 0) {
342
+ yield* appendVisibleTextDelta(
343
+ state,
344
+ text.slice(0, bufferOffset),
345
+ previousTextLength,
346
+ )
347
+ }
348
+ return
349
+ }
350
+ if (state.shouldBufferTextDeltas) return
351
+ yield* appendVisibleTextDelta(state, text, previousTextLength)
352
+ }
353
+
354
+ function* appendVisibleTextDelta(
355
+ state: BackendChatState,
356
+ text: string,
357
+ previousTextLength: number,
358
+ ): Generator<unknown> {
359
+ if (text.length === 0) return
360
+ if (state.thinkingBlockIndex !== null && !state.thinkingBlockStopped) {
361
+ yield createContentBlockStopEvent(state.thinkingBlockIndex)
362
+ state.thinkingBlockStopped = true
363
+ }
364
+ if (state.textBlockIndex === null) {
365
+ yield createTextBlockStartEvent(state.nextContentBlockIndex)
366
+ state.textBlockIndex = state.nextContentBlockIndex
367
+ state.nextContentBlockIndex += 1
368
+ }
369
+ yield createTextDeltaEvent(state.textBlockIndex, text)
370
+ state.emittedTextLength = previousTextLength + text.length
371
+ }
372
+
373
+ function* flushBufferedText(state: BackendChatState): Generator<unknown> {
374
+ if (state.accumulated.length <= state.emittedTextLength) return
375
+ yield* appendVisibleTextDelta(
376
+ state,
377
+ state.accumulated.slice(state.emittedTextLength),
378
+ state.emittedTextLength,
379
+ )
380
+ }
381
+
382
+ function* flushTextPreludeBeforeRawJsonToolUse(
383
+ state: BackendChatState,
384
+ prelude: string,
385
+ ): Generator<unknown> {
386
+ if (prelude.length <= state.emittedTextLength) return
387
+ yield* appendVisibleTextDelta(
388
+ state,
389
+ prelude.slice(state.emittedTextLength),
390
+ state.emittedTextLength,
391
+ )
392
+ }
393
+
394
+ function* appendRawJsonToolUseBlock(params: {
395
+ readonly state: BackendChatState
396
+ readonly name: string
397
+ readonly input: Record<string, unknown>
398
+ readonly id?: string
399
+ }): Generator<unknown> {
400
+ const toolUseBlock = {
401
+ type: 'tool_use' as const,
402
+ id: params.id ?? 'call_raw_json_tool_0',
403
+ name: params.name,
404
+ input: params.input,
405
+ }
406
+ params.state.pendingContentBlocks.push(toolUseBlock)
407
+ const toolBlockIndex = params.state.nextContentBlockIndex
408
+ params.state.nextContentBlockIndex += 1
409
+ yield createToolUseBlockStartEvent(toolBlockIndex, toolUseBlock)
410
+ yield createContentBlockStopEvent(toolBlockIndex)
411
+ }
412
+
413
+ function firstToolCallTextOffset(text: string): number {
414
+ const braceOffset = text.indexOf('{')
415
+ const tagOffset = text.indexOf(TEXTUAL_TOOL_CALL_OPEN)
416
+ if (braceOffset < 0) return tagOffset
417
+ if (tagOffset < 0) return braceOffset
418
+ return Math.min(braceOffset, tagOffset)
419
+ }
420
+
421
+ function* stopOpenBlocks(state: BackendChatState): Generator<unknown> {
422
+ if (state.thinkingBlockIndex !== null && !state.thinkingBlockStopped) {
423
+ yield createContentBlockStopEvent(state.thinkingBlockIndex)
424
+ state.thinkingBlockStopped = true
425
+ }
426
+ if (state.textBlockIndex !== null && !state.textBlockStopped) {
427
+ yield createContentBlockStopEvent(state.textBlockIndex)
428
+ state.textBlockStopped = true
429
+ }
430
+ }
@@ -0,0 +1,62 @@
1
+ import type { ToolCallFrame } from '../../../ipc/frames.generated.js'
2
+
3
+ export type BackendChatParams = {
4
+ readonly messages: readonly unknown[]
5
+ readonly systemPrompt: unknown
6
+ readonly thinkingConfig?: unknown
7
+ readonly tools?: unknown
8
+ readonly signal?: AbortSignal
9
+ readonly options?: {
10
+ readonly model?: string
11
+ readonly querySource?: string
12
+ readonly [key: string]: unknown
13
+ }
14
+ }
15
+
16
+ export type PendingToolUseBlock = {
17
+ readonly type: 'tool_use'
18
+ readonly id: string
19
+ readonly name: string
20
+ readonly input: ToolCallFrame['arguments']
21
+ }
22
+
23
+ export type BackendChatState = {
24
+ accumulated: string
25
+ accumulatedThinking: string
26
+ emittedTextLength: number
27
+ messageStartEmitted: boolean
28
+ nextContentBlockIndex: number
29
+ shouldBufferTextDeltas: boolean
30
+ textBlockIndex: number | null
31
+ textBlockStopped: boolean
32
+ thinkingBlockIndex: number | null
33
+ thinkingBlockStopped: boolean
34
+ readonly pendingContentBlocks: PendingToolUseBlock[]
35
+ }
36
+
37
+ export function createBackendChatState(): BackendChatState {
38
+ return {
39
+ accumulated: '',
40
+ accumulatedThinking: '',
41
+ emittedTextLength: 0,
42
+ messageStartEmitted: false,
43
+ nextContentBlockIndex: 0,
44
+ shouldBufferTextDeltas: false,
45
+ textBlockIndex: null,
46
+ textBlockStopped: false,
47
+ thinkingBlockIndex: null,
48
+ thinkingBlockStopped: false,
49
+ pendingContentBlocks: [],
50
+ }
51
+ }
52
+
53
+ export function hasAssistantPayload(
54
+ state: BackendChatState,
55
+ persistThinking: boolean,
56
+ ): boolean {
57
+ return (
58
+ state.accumulated.trimStart().length > 0 ||
59
+ state.pendingContentBlocks.length > 0 ||
60
+ (persistThinking && state.accumulatedThinking.length > 0)
61
+ )
62
+ }
@@ -0,0 +1 @@
1
+ export { queryModelWithStreaming } from './backendChat/streaming.js'
@@ -1,7 +1,7 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // UMMAYA FriendliAI client shim for the CC-restored provider.
3
3
  //
4
- // services/api/claude.ts is the Claude Code streaming provider shape. This
4
+ // services/api/ummaya.ts is the Claude Code streaming provider shape. This
5
5
  // module supplies the one sanctioned swap: Anthropic SDK transport becomes
6
6
  // FriendliAI's OpenAI-compatible /chat/completions endpoint. query.ts still
7
7
  // owns the agentic loop; backend stdio remains only the tool executor for
@@ -26,6 +26,11 @@ import {
26
26
  } from '../../sdk-compat.js'
27
27
  import { assertFriendliApiKeyForUse } from '../../utils/auth.js'
28
28
  import { getUserAgent } from '../../utils/http.js'
29
+ import {
30
+ providerReasoningPayload,
31
+ resolveKExaoneReasoningPolicy,
32
+ type ReasoningMode,
33
+ } from '../../utils/kExaoneReasoning.js'
29
34
  import { UMMAYA_K_EXAONE_MODEL } from '../../utils/model/constants.js'
30
35
 
31
36
  export const CLIENT_REQUEST_ID_HEADER = 'x-client-request-id'
@@ -41,6 +46,11 @@ type RequestOptions = {
41
46
  headers?: Record<string, string>
42
47
  }
43
48
 
49
+ type FriendliMessageStreamParams = BetaMessageStreamParams & {
50
+ stream?: boolean
51
+ reasoning_mode?: ReasoningMode
52
+ }
53
+
44
54
  type FriendliClientArgs = {
45
55
  apiKey?: string
46
56
  maxRetries: number
@@ -130,7 +140,7 @@ class FriendliMessagesCompatClient {
130
140
  readonly beta: {
131
141
  messages: {
132
142
  create: (
133
- params: BetaMessageStreamParams & { stream?: boolean },
143
+ params: FriendliMessageStreamParams,
134
144
  options?: RequestOptions,
135
145
  ) => unknown
136
146
  }
@@ -159,7 +169,7 @@ class FriendliMessagesCompatClient {
159
169
  }
160
170
 
161
171
  private async streamWithResponse(
162
- params: BetaMessageStreamParams & { stream?: boolean },
172
+ params: FriendliMessageStreamParams,
163
173
  options?: RequestOptions,
164
174
  ): Promise<{
165
175
  data: Stream<BetaRawMessageStreamEvent>
@@ -188,7 +198,7 @@ class FriendliMessagesCompatClient {
188
198
  }
189
199
 
190
200
  private async complete(
191
- params: BetaMessageStreamParams,
201
+ params: FriendliMessageStreamParams,
192
202
  options?: RequestOptions,
193
203
  ): Promise<BetaMessage> {
194
204
  const response = await this.fetchChatCompletion(
@@ -279,6 +289,9 @@ class FriendliMessagesCompatClient {
279
289
  const toolStates = new Map<number, ToolStreamState>()
280
290
  let finalUsage: BetaUsage | undefined
281
291
  let stopReason: BetaMessage['stop_reason'] = 'end_turn'
292
+ const allowReasoning = resolveKExaoneReasoningPolicy({
293
+ explicitSessionMode: params.reasoning_mode,
294
+ }).includeReasoning
282
295
 
283
296
  const ensureMessageStart = function* () {
284
297
  if (messageStarted) return
@@ -301,6 +314,12 @@ class FriendliMessagesCompatClient {
301
314
  const ensureTextBlock = function* () {
302
315
  yield* ensureMessageStart()
303
316
  if (textBlockIndex === undefined) {
317
+ if (
318
+ thinkingBlockIndex !== undefined &&
319
+ openedBlocks.has(thinkingBlockIndex)
320
+ ) {
321
+ yield* closeNonToolBlocks()
322
+ }
304
323
  textBlockIndex = nextBlockIndex++
305
324
  openedBlocks.add(textBlockIndex)
306
325
  yield {
@@ -314,6 +333,9 @@ class FriendliMessagesCompatClient {
314
333
  const ensureThinkingBlock = function* () {
315
334
  yield* ensureMessageStart()
316
335
  if (thinkingBlockIndex === undefined) {
336
+ if (textBlockIndex !== undefined && openedBlocks.has(textBlockIndex)) {
337
+ yield* closeNonToolBlocks()
338
+ }
317
339
  thinkingBlockIndex = nextBlockIndex++
318
340
  openedBlocks.add(thinkingBlockIndex)
319
341
  yield {
@@ -385,7 +407,7 @@ class FriendliMessagesCompatClient {
385
407
 
386
408
  for (const choice of chunk.choices ?? []) {
387
409
  const delta = choice.delta ?? {}
388
- if (delta.reasoning_content) {
410
+ if (delta.reasoning_content && allowReasoning) {
389
411
  yield* ensureThinkingBlock()
390
412
  yield {
391
413
  type: 'content_block_delta' as const,
@@ -454,17 +476,20 @@ class FriendliMessagesCompatClient {
454
476
  }
455
477
 
456
478
  function buildOpenAIPayload(
457
- params: BetaMessageStreamParams & { stream?: boolean },
479
+ params: FriendliMessageStreamParams,
458
480
  ): Record<string, unknown> {
459
481
  const messages = convertMessages(params.messages, params.system)
460
482
  const tools = convertTools(params.tools)
483
+ const reasoning = providerReasoningPayload(
484
+ resolveKExaoneReasoningPolicy({
485
+ explicitSessionMode: params.reasoning_mode,
486
+ }),
487
+ )
461
488
  const payload: Record<string, unknown> = {
462
489
  model: params.model || UMMAYA_K_EXAONE_MODEL,
463
490
  messages,
464
491
  max_tokens: params.max_tokens,
465
- chat_template_kwargs: {
466
- enable_thinking: isTruthy(process.env.UMMAYA_K_EXAONE_THINKING),
467
- },
492
+ ...reasoning,
468
493
  ...(params.temperature !== undefined ? { temperature: params.temperature } : {}),
469
494
  ...(tools.length > 0
470
495
  ? {
@@ -576,7 +601,7 @@ function convertToolChoice(
576
601
  }
577
602
 
578
603
  function sanitizeSchema(schema: Record<string, unknown>): Record<string, unknown> {
579
- const clone = { ...schema }
604
+ const clone = inlineLocalJsonSchemaRefs(schema)
580
605
  delete clone.cache_control
581
606
  delete clone.defer_loading
582
607
  delete clone.eager_input_streaming
@@ -584,6 +609,69 @@ function sanitizeSchema(schema: Record<string, unknown>): Record<string, unknown
584
609
  return clone
585
610
  }
586
611
 
612
+ function inlineLocalJsonSchemaRefs(schema: Record<string, unknown>): Record<string, unknown> {
613
+ const defs = isRecord(schema.$defs) ? schema.$defs : {}
614
+ const inlined = inlineSchemaNode(schema, defs, [])
615
+ if (!isRecord(inlined)) {
616
+ throw new Error('OpenAI tool parameters schema must be a JSON object')
617
+ }
618
+ return inlined
619
+ }
620
+
621
+ function inlineSchemaNode(
622
+ node: unknown,
623
+ defs: Record<string, unknown>,
624
+ stack: string[],
625
+ ): unknown {
626
+ if (Array.isArray(node)) {
627
+ return node.map(item => inlineSchemaNode(item, defs, stack))
628
+ }
629
+ if (!isRecord(node)) return node
630
+
631
+ const refName = localDefRefName(node.$ref)
632
+ if (refName) {
633
+ if (stack.includes(refName)) {
634
+ throw new Error(`Cyclic JSON Schema reference is not supported: #/$defs/${refName}`)
635
+ }
636
+ if (!Object.prototype.hasOwnProperty.call(defs, refName)) {
637
+ throw new Error(`Unknown JSON Schema reference: #/$defs/${refName}`)
638
+ }
639
+
640
+ const expanded = inlineSchemaNode(defs[refName], defs, [...stack, refName])
641
+ const siblings = Object.fromEntries(
642
+ Object.entries(node).filter(([key]) => key !== '$ref' && key !== '$defs'),
643
+ )
644
+ if (Object.keys(siblings).length === 0) return expanded
645
+ if (!isRecord(expanded)) {
646
+ throw new Error(`JSON Schema reference target must be an object: #/$defs/${refName}`)
647
+ }
648
+ return {
649
+ ...expanded,
650
+ ...Object.fromEntries(
651
+ Object.entries(siblings).map(([key, value]) => [
652
+ key,
653
+ inlineSchemaNode(value, defs, stack),
654
+ ]),
655
+ ),
656
+ }
657
+ }
658
+
659
+ return Object.fromEntries(
660
+ Object.entries(node)
661
+ .filter(([key]) => key !== '$defs')
662
+ .map(([key, value]) => [key, inlineSchemaNode(value, defs, stack)]),
663
+ )
664
+ }
665
+
666
+ function localDefRefName(ref: unknown): string | null {
667
+ if (typeof ref !== 'string' || !ref.startsWith('#/$defs/')) return null
668
+ return ref.slice('#/$defs/'.length).replace(/~1/g, '/').replace(/~0/g, '~')
669
+ }
670
+
671
+ function isRecord(value: unknown): value is Record<string, unknown> {
672
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
673
+ }
674
+
587
675
  function systemToText(system: BetaMessageStreamParams['system']): string {
588
676
  if (!system) return ''
589
677
  if (typeof system === 'string') return system
@@ -740,7 +828,3 @@ function resolveFetch(fetchOverride: unknown): FetchLike {
740
828
  function trimSlash(value: string): string {
741
829
  return value.replace(/\/+$/, '')
742
830
  }
743
-
744
- function isTruthy(value: string | undefined): boolean {
745
- return value === '1' || value?.toLowerCase() === 'true' || value?.toLowerCase() === 'yes'
746
- }