ummaya 0.2.4 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (477) hide show
  1. package/README.md +15 -2
  2. package/bin/ummaya +10 -1
  3. package/npm-shrinkwrap.json +253 -2
  4. package/package.json +5 -1
  5. package/prompts/manifest.yaml +1 -1
  6. package/prompts/system_v1.md +1 -0
  7. package/pyproject.toml +26 -2
  8. package/specs/2803-document-production-hardening/contracts/document-tools.schema.json +1043 -0
  9. package/src/ummaya/_canonical/__init__.py +2 -0
  10. package/src/ummaya/engine/engine.py +29 -132
  11. package/src/ummaya/evidence/__init__.py +21 -2
  12. package/src/ummaya/evidence/dataset_contract.py +193 -0
  13. package/src/ummaya/evidence/document_authoring_cases.py +33 -0
  14. package/src/ummaya/evidence/document_harness.py +313 -0
  15. package/src/ummaya/evidence/document_viewer_ux.py +391 -0
  16. package/src/ummaya/evidence/gates.py +70 -0
  17. package/src/ummaya/evidence/json_types.py +20 -0
  18. package/src/ummaya/evidence/models.py +88 -1
  19. package/src/ummaya/evidence/output_payload.py +89 -0
  20. package/src/ummaya/evidence/payload_documents.py +233 -0
  21. package/src/ummaya/evidence/route_contracts.py +224 -0
  22. package/src/ummaya/evidence/route_helpers.py +150 -0
  23. package/src/ummaya/evidence/runner.py +81 -212
  24. package/src/ummaya/evidence/source_provenance.py +246 -0
  25. package/src/ummaya/evidence/source_provenance_redaction.py +176 -0
  26. package/src/ummaya/evidence/tool_layer.py +39 -0
  27. package/src/ummaya/evidence/tool_layer_models.py +151 -0
  28. package/src/ummaya/ipc/adapter_manifest_emitter.py +26 -10
  29. package/src/ummaya/ipc/document_intent_normalization.py +185 -0
  30. package/src/ummaya/ipc/frame_schema.py +5 -5
  31. package/src/ummaya/ipc/route_diagnostics.py +73 -0
  32. package/src/ummaya/ipc/stdio.py +1109 -477
  33. package/src/ummaya/llm/client.py +102 -3
  34. package/src/ummaya/llm/config.py +8 -3
  35. package/src/ummaya/primitives/__init__.py +6 -2
  36. package/src/ummaya/primitives/delegation.py +1 -1
  37. package/src/ummaya/primitives/document.py +28 -0
  38. package/src/ummaya/settings.py +0 -3
  39. package/src/ummaya/tools/discovery_bridge.py +17 -1
  40. package/src/ummaya/tools/documents/__init__.py +297 -0
  41. package/src/ummaya/tools/documents/adapter_registry.py +487 -0
  42. package/src/ummaya/tools/documents/archive_container_probe.py +167 -0
  43. package/src/ummaya/tools/documents/artifact_store.py +454 -0
  44. package/src/ummaya/tools/documents/authoring.py +283 -0
  45. package/src/ummaya/tools/documents/baselines.py +114 -0
  46. package/src/ummaya/tools/documents/capability.py +331 -0
  47. package/src/ummaya/tools/documents/contracts.py +112 -0
  48. package/src/ummaya/tools/documents/conversion.py +521 -0
  49. package/src/ummaya/tools/documents/diff.py +275 -0
  50. package/src/ummaya/tools/documents/engines.py +163 -0
  51. package/src/ummaya/tools/documents/evaluation.py +291 -0
  52. package/src/ummaya/tools/documents/explicit_values.py +108 -0
  53. package/src/ummaya/tools/documents/fixtures.py +174 -0
  54. package/src/ummaya/tools/documents/format_completion_audit.py +471 -0
  55. package/src/ummaya/tools/documents/formats/__init__.py +2 -0
  56. package/src/ummaya/tools/documents/formats/archive.py +528 -0
  57. package/src/ummaya/tools/documents/formats/base.py +41 -0
  58. package/src/ummaya/tools/documents/formats/code_file.py +211 -0
  59. package/src/ummaya/tools/documents/formats/data_file.py +272 -0
  60. package/src/ummaya/tools/documents/formats/hwp.py +284 -0
  61. package/src/ummaya/tools/documents/formats/hwpx.py +1837 -0
  62. package/src/ummaya/tools/documents/formats/odf.py +435 -0
  63. package/src/ummaya/tools/documents/formats/ooxml.py +1030 -0
  64. package/src/ummaya/tools/documents/formats/passive.py +766 -0
  65. package/src/ummaya/tools/documents/formats/pdf.py +702 -0
  66. package/src/ummaya/tools/documents/formats/text_web.py +268 -0
  67. package/src/ummaya/tools/documents/hwp_conversion_probe.py +178 -0
  68. package/src/ummaya/tools/documents/hwp_direct_candidate.py +141 -0
  69. package/src/ummaya/tools/documents/inspection.py +289 -0
  70. package/src/ummaya/tools/documents/intake.py +1079 -0
  71. package/src/ummaya/tools/documents/legacy_office_promotion_probe.py +366 -0
  72. package/src/ummaya/tools/documents/models.py +1598 -0
  73. package/src/ummaya/tools/documents/odf_promotion_probe.py +167 -0
  74. package/src/ummaya/tools/documents/orchestrator.py +96 -0
  75. package/src/ummaya/tools/documents/passive_capability_probe.py +251 -0
  76. package/src/ummaya/tools/documents/patch.py +170 -0
  77. package/src/ummaya/tools/documents/pdfa_conformance.py +284 -0
  78. package/src/ummaya/tools/documents/pdfa_promotion_probe.py +198 -0
  79. package/src/ummaya/tools/documents/permissions.py +110 -0
  80. package/src/ummaya/tools/documents/planner.py +616 -0
  81. package/src/ummaya/tools/documents/registry.py +2733 -0
  82. package/src/ummaya/tools/documents/render.py +978 -0
  83. package/src/ummaya/tools/documents/render_comparison.py +113 -0
  84. package/src/ummaya/tools/documents/render_comparison_models.py +74 -0
  85. package/src/ummaya/tools/documents/render_comparison_regions.py +73 -0
  86. package/src/ummaya/tools/documents/render_comparison_style.py +161 -0
  87. package/src/ummaya/tools/documents/reread.py +157 -0
  88. package/src/ummaya/tools/documents/runtime_authoring.py +244 -0
  89. package/src/ummaya/tools/documents/runtime_authoring_bundle.py +76 -0
  90. package/src/ummaya/tools/documents/scorecard.py +184 -0
  91. package/src/ummaya/tools/documents/socratic_planner.py +193 -0
  92. package/src/ummaya/tools/documents/style.py +48 -0
  93. package/src/ummaya/tools/documents/tool_defs.py +523 -0
  94. package/src/ummaya/tools/documents/validate.py +347 -0
  95. package/src/ummaya/tools/executor.py +29 -0
  96. package/src/ummaya/tools/live_proxy.py +0 -3
  97. package/src/ummaya/tools/models.py +5 -1
  98. package/src/ummaya/tools/register_all.py +8 -0
  99. package/src/ummaya/tools/registry.py +10 -1
  100. package/src/ummaya/tools/routing/__init__.py +59 -0
  101. package/src/ummaya/tools/routing/builder.py +105 -0
  102. package/src/ummaya/tools/routing/cards.py +29 -0
  103. package/src/ummaya/tools/routing/decision_service.py +534 -0
  104. package/src/ummaya/tools/routing/decision_types.py +74 -0
  105. package/src/ummaya/tools/routing/feasibility.py +122 -0
  106. package/src/ummaya/tools/routing/intent.py +17 -0
  107. package/src/ummaya/tools/routing/intent_extractor.py +207 -0
  108. package/src/ummaya/tools/routing/intent_patterns.py +160 -0
  109. package/src/ummaya/tools/routing/intent_public_data.py +150 -0
  110. package/src/ummaya/tools/routing/intent_types.py +48 -0
  111. package/src/ummaya/tools/routing/lint.py +78 -0
  112. package/src/ummaya/tools/routing/metadata.py +174 -0
  113. package/src/ummaya/tools/routing/projection.py +340 -0
  114. package/src/ummaya/tools/routing/retrieval_policy.py +629 -0
  115. package/src/ummaya/tools/routing/schema.py +81 -0
  116. package/src/ummaya/tools/routing/types.py +96 -0
  117. package/src/ummaya/tools/routing_index.py +2 -2
  118. package/src/ummaya/tools/search.py +34 -746
  119. package/tests/fixtures/documents/public_forms/baselines.yaml +113 -0
  120. package/tui/package.json +1 -1
  121. package/tui/src/.cc-byte-identical-whitelist.yaml +266 -0
  122. package/tui/src/QueryEngine.ts +12 -8
  123. package/tui/src/bridge/inboundAttachments.ts +3 -3
  124. package/tui/src/cli/handlers/auth.ts +3 -12
  125. package/tui/src/cli/print.ts +7 -7
  126. package/tui/src/commands/insights.ts +1 -1
  127. package/tui/src/commands/install-github-app/types.ts +8 -30
  128. package/tui/src/commands/plugin/types.ts +6 -28
  129. package/tui/src/commands/plugin/unifiedTypes.ts +4 -26
  130. package/tui/src/commands/rename/generateSessionName.ts +1 -1
  131. package/tui/src/components/Feedback.tsx +1 -1
  132. package/tui/src/components/LogoV2/EmergencyTip.tsx +11 -2
  133. package/tui/src/components/LogoV2/WelcomeV2.tsx +1 -3
  134. package/tui/src/components/ScrollKeybindingHandler.tsx +6 -6
  135. package/tui/src/components/Spinner/types.ts +6 -28
  136. package/tui/src/components/agents/generateAgent.ts +1 -1
  137. package/tui/src/components/agents/new-agent-creation/types.ts +4 -26
  138. package/tui/src/components/config/EnvSecretIsolatedEditor.tsx +1 -1
  139. package/tui/src/components/mcp/types.ts +16 -38
  140. package/tui/src/components/messages/AssistantToolUseMessage.tsx +3 -2
  141. package/tui/src/components/messages/UserCrossSessionMessage.ts +16 -4
  142. package/tui/src/components/messages/UserForkBoilerplateMessage.ts +16 -4
  143. package/tui/src/components/messages/UserGitHubWebhookMessage.ts +16 -4
  144. package/tui/src/components/messages/UserToolResultMessage/utils.tsx +3 -2
  145. package/tui/src/components/permissions/MonitorPermissionRequest/MonitorPermissionRequest.ts +9 -4
  146. package/tui/src/components/permissions/ReviewArtifactPermissionRequest/ReviewArtifactPermissionRequest.ts +9 -4
  147. package/tui/src/components/primitive/DocumentSocraticReviewBlock.tsx +129 -0
  148. package/tui/src/components/primitive/DocumentToolResultCard.tsx +224 -0
  149. package/tui/src/components/primitive/documentSocraticReview.ts +215 -0
  150. package/tui/src/components/primitive/index.tsx +43 -1
  151. package/tui/src/components/primitive/types.ts +137 -0
  152. package/tui/src/components/ui/option.ts +4 -26
  153. package/tui/src/constants/common.ts +0 -2
  154. package/tui/src/constants/prompts.ts +4 -3
  155. package/tui/src/constants/querySource.ts +4 -26
  156. package/tui/src/entrypoints/sdk/controlTypes.ts +26 -48
  157. package/tui/src/entrypoints/sdk/coreTypes.generated.ts +3 -25
  158. package/tui/src/entrypoints/sdk/runtimeTypes.ts +38 -60
  159. package/tui/src/entrypoints/sdk/sdkUtilityTypes.ts +4 -26
  160. package/tui/src/entrypoints/sdk/settingsTypes.generated.ts +3 -25
  161. package/tui/src/entrypoints/sdk/toolTypes.ts +3 -25
  162. package/tui/src/hooks/toolPermission/handlers/interactiveHandler.ts +10 -0
  163. package/tui/src/hooks/useApiKeyVerification.ts +1 -1
  164. package/tui/src/hooks/useVirtualScroll.ts +1 -1
  165. package/tui/src/ink/ink.tsx +33 -14
  166. package/tui/src/ink/reconciler.ts +2 -3
  167. package/tui/src/ink/render-to-screen.ts +30 -10
  168. package/tui/src/ipc/bridge.ts +62 -15
  169. package/tui/src/ipc/bridgeSingleton.ts +5 -1
  170. package/tui/src/ipc/codec.ts +3 -3
  171. package/tui/src/ipc/frames.generated.ts +12 -12
  172. package/tui/src/ipc/llmClient.ts +151 -27
  173. package/tui/src/ipc/schema/frame.schema.json +1 -1
  174. package/tui/src/keybindings/defaultBindings.ts +4 -0
  175. package/tui/src/main.tsx +29 -11
  176. package/tui/src/native-ts/file-index/index.ts +33 -3
  177. package/tui/src/observability/surface.ts +2 -2
  178. package/tui/src/probes/toolRegistryProbe.tsx +3 -1
  179. package/tui/src/projectOnboardingState.ts +7 -6
  180. package/tui/src/query/chatMessageTypes.ts +18 -0
  181. package/tui/src/query/chatMessagesBuilder.ts +1 -1
  182. package/tui/src/query/deps.ts +1 -1
  183. package/tui/src/query/messageGuards.ts +106 -0
  184. package/tui/src/query/publicDataTerminalRepair.ts +384 -0
  185. package/tui/src/query/run.ts +1075 -0
  186. package/tui/src/query/supportBoundary.ts +168 -0
  187. package/tui/src/query/toolResultErrors.ts +103 -0
  188. package/tui/src/query/toolRunner.ts +687 -0
  189. package/tui/src/query/unavailableToolRepair.ts +118 -0
  190. package/tui/src/query.ts +9 -2186
  191. package/tui/src/screens/REPL.tsx +40 -29
  192. package/tui/src/services/api/adapterManifest.ts +4 -0
  193. package/tui/src/services/api/backendChat/events.ts +117 -0
  194. package/tui/src/services/api/backendChat/finalMessage.ts +40 -0
  195. package/tui/src/services/api/backendChat/frame.ts +9 -0
  196. package/tui/src/services/api/backendChat/streaming.ts +430 -0
  197. package/tui/src/services/api/backendChat/types.ts +62 -0
  198. package/tui/src/services/api/backendChat.ts +1 -0
  199. package/tui/src/services/api/client.ts +65 -2
  200. package/tui/src/services/api/errorUtils.ts +5 -5
  201. package/tui/src/services/api/errors.ts +1 -1
  202. package/tui/src/services/api/logging.ts +1 -1
  203. package/tui/src/services/api/ummaya/evidence.ts +194 -0
  204. package/tui/src/services/api/ummaya/messages.ts +255 -0
  205. package/tui/src/services/api/ummaya/nonStreaming.ts +66 -0
  206. package/tui/src/services/api/ummaya/provider.ts +200 -0
  207. package/tui/src/services/api/ummaya/reasoning.ts +24 -0
  208. package/tui/src/services/api/ummaya/request.ts +200 -0
  209. package/tui/src/services/api/ummaya/selectionContext.ts +240 -0
  210. package/tui/src/services/api/ummaya/streaming.ts +365 -0
  211. package/tui/src/services/api/ummaya/streamingPayload.ts +129 -0
  212. package/tui/src/services/api/ummaya/streamingReader.ts +40 -0
  213. package/tui/src/services/api/ummaya/toolSelection.ts +217 -0
  214. package/tui/src/services/api/ummaya/types.ts +110 -0
  215. package/tui/src/services/api/ummaya/usage.ts +30 -0
  216. package/tui/src/services/api/ummaya.ts +26 -418
  217. package/tui/src/services/api/withRetry.ts +1 -1
  218. package/tui/src/services/awaySummary.ts +2 -2
  219. package/tui/src/services/claudeAiLimits.ts +1 -1
  220. package/tui/src/services/compact/autoCompact.ts +1 -1
  221. package/tui/src/services/compact/compact.ts +1 -1
  222. package/tui/src/services/lsp/types.ts +8 -30
  223. package/tui/src/services/tips/types.ts +6 -28
  224. package/tui/src/services/tokenEstimation.ts +1 -1
  225. package/tui/src/services/toolRegistry/bootGuard.ts +5 -5
  226. package/tui/src/services/toolUseSummary/toolUseSummaryGenerator.ts +1 -1
  227. package/tui/src/services/tools/toolExecution.ts +94 -1
  228. package/tui/src/store/pendingPermissionSlot.ts +1 -1
  229. package/tui/src/store/session-store.ts +10 -36
  230. package/tui/src/stubs/any-stub.ts +15 -10
  231. package/tui/src/stubs/color-diff-napi.ts +37 -23
  232. package/tui/src/stubs/globals.d.ts +3 -3
  233. package/tui/src/stubs/macro-preload.ts +23 -12
  234. package/tui/src/tools/AdapterTool/AdapterTool.ts +1207 -714
  235. package/tui/src/tools/AdapterTool/routeDiagnostics.ts +75 -0
  236. package/tui/src/tools/AgentTool/AgentTool.tsx +84 -1371
  237. package/tui/src/tools/AgentTool/agentToolHandoff.ts +114 -0
  238. package/tui/src/tools/AgentTool/agentToolPartialResult.ts +16 -0
  239. package/tui/src/tools/AgentTool/agentToolProgress.ts +32 -0
  240. package/tui/src/tools/AgentTool/agentToolResolver.ts +161 -0
  241. package/tui/src/tools/AgentTool/agentToolResult.ts +163 -0
  242. package/tui/src/tools/AgentTool/agentToolUtils.ts +14 -686
  243. package/tui/src/tools/AgentTool/asyncAgentLifecycle.ts +208 -0
  244. package/tui/src/tools/AgentTool/asyncLifecycle.ts +153 -0
  245. package/tui/src/tools/AgentTool/backgroundedCompletion.ts +126 -0
  246. package/tui/src/tools/AgentTool/backgroundedLifecycle.ts +174 -0
  247. package/tui/src/tools/AgentTool/foregroundBackground.ts +83 -0
  248. package/tui/src/tools/AgentTool/foregroundDrain.tsx +133 -0
  249. package/tui/src/tools/AgentTool/foregroundFinalize.ts +98 -0
  250. package/tui/src/tools/AgentTool/foregroundLifecycle.tsx +237 -0
  251. package/tui/src/tools/AgentTool/foregroundProgress.tsx +169 -0
  252. package/tui/src/tools/AgentTool/foregroundTask.ts +89 -0
  253. package/tui/src/tools/AgentTool/forkSubagent.ts +1 -12
  254. package/tui/src/tools/AgentTool/forkSubagentGate.ts +34 -0
  255. package/tui/src/tools/AgentTool/launchRouting.ts +203 -0
  256. package/tui/src/tools/AgentTool/lifecycle.ts +244 -0
  257. package/tui/src/tools/AgentTool/mcpRouting.ts +73 -0
  258. package/tui/src/tools/AgentTool/orchestrationSupport.ts +70 -0
  259. package/tui/src/tools/AgentTool/permissions.ts +39 -0
  260. package/tui/src/tools/AgentTool/promptSetup.ts +181 -0
  261. package/tui/src/tools/AgentTool/remoteRouting.ts +62 -0
  262. package/tui/src/tools/AgentTool/resultMapping.ts +116 -0
  263. package/tui/src/tools/AgentTool/resumeAgent.ts +39 -107
  264. package/tui/src/tools/AgentTool/resumeAgentHelpers.ts +140 -0
  265. package/tui/src/tools/AgentTool/runAgent.ts +1 -1
  266. package/tui/src/tools/AgentTool/runtimeConfig.ts +57 -0
  267. package/tui/src/tools/AgentTool/schemas.ts +196 -0
  268. package/tui/src/tools/AgentTool/sourceVerificationPropagation.ts +263 -0
  269. package/tui/src/tools/AgentTool/worktreeLifecycle.ts +105 -0
  270. package/tui/src/tools/AskUserQuestionTool/AskUserQuestionTool.tsx +174 -202
  271. package/tui/src/tools/BashTool/BashTool.tsx +71 -1072
  272. package/tui/src/tools/BashTool/bashCommandHelpers.ts +12 -12
  273. package/tui/src/tools/BashTool/bashPermissions/astPreflight.ts +173 -0
  274. package/tui/src/tools/BashTool/bashPermissions/classifierChecks.ts +199 -0
  275. package/tui/src/tools/BashTool/bashPermissions/compoundGuards.ts +53 -0
  276. package/tui/src/tools/BashTool/bashPermissions/constants.ts +99 -0
  277. package/tui/src/tools/BashTool/bashPermissions/index.ts +38 -0
  278. package/tui/src/tools/BashTool/bashPermissions/legacyMisparsing.ts +62 -0
  279. package/tui/src/tools/BashTool/bashPermissions/main.ts +135 -0
  280. package/tui/src/tools/BashTool/bashPermissions/normalizedCommands.ts +33 -0
  281. package/tui/src/tools/BashTool/bashPermissions/operatorFlow.ts +98 -0
  282. package/tui/src/tools/BashTool/bashPermissions/permissionChecks.ts +200 -0
  283. package/tui/src/tools/BashTool/bashPermissions/prefixSuggestions.ts +88 -0
  284. package/tui/src/tools/BashTool/bashPermissions/promptClassifierRules.ts +125 -0
  285. package/tui/src/tools/BashTool/bashPermissions/ruleDelegates.ts +19 -0
  286. package/tui/src/tools/BashTool/bashPermissions/ruleMatching.ts +145 -0
  287. package/tui/src/tools/BashTool/bashPermissions/sandboxAutoAllow.ts +75 -0
  288. package/tui/src/tools/BashTool/bashPermissions/subcommandFlow.ts +205 -0
  289. package/tui/src/tools/BashTool/bashPermissions/subcommandGuards.ts +73 -0
  290. package/tui/src/tools/BashTool/bashPermissions/subcommandResultHelpers.ts +116 -0
  291. package/tui/src/tools/BashTool/bashPermissions/types.ts +26 -0
  292. package/tui/src/tools/BashTool/bashPermissions/wrapperStripping.ts +139 -0
  293. package/tui/src/tools/BashTool/bashPermissions.ts +26 -2621
  294. package/tui/src/tools/BashTool/call.ts +202 -0
  295. package/tui/src/tools/BashTool/callLoader.ts +35 -0
  296. package/tui/src/tools/BashTool/commandClassification.ts +151 -0
  297. package/tui/src/tools/BashTool/commandClassificationLoader.ts +40 -0
  298. package/tui/src/tools/BashTool/cwdReset.ts +33 -0
  299. package/tui/src/tools/BashTool/lineTruncation.ts +11 -0
  300. package/tui/src/tools/BashTool/modeValidation.ts +13 -1
  301. package/tui/src/tools/BashTool/outputPersistence.ts +42 -0
  302. package/tui/src/tools/BashTool/permissionClassification.ts +66 -0
  303. package/tui/src/tools/BashTool/permissionLoader.ts +44 -0
  304. package/tui/src/tools/BashTool/resultLoader.ts +29 -0
  305. package/tui/src/tools/BashTool/resultMapping.ts +83 -0
  306. package/tui/src/tools/BashTool/sandboxPolicy.ts +79 -0
  307. package/tui/src/tools/BashTool/schemas.ts +65 -0
  308. package/tui/src/tools/BashTool/sedEditExecution.ts +59 -0
  309. package/tui/src/tools/BashTool/shellExecution.tsx +245 -0
  310. package/tui/src/tools/BashTool/shellOutputUtils.ts +85 -0
  311. package/tui/src/tools/BashTool/shellPermissionGauntlet.ts +97 -0
  312. package/tui/src/tools/BashTool/uiLoader.ts +37 -0
  313. package/tui/src/tools/BriefTool/upload.ts +1 -1
  314. package/tui/src/tools/CalculatorTool/parser.ts +2 -2
  315. package/tui/src/tools/DocumentPrimitive/DocumentPrimitive.ts +262 -0
  316. package/tui/src/tools/DocumentPrimitive/dispatchNormalization.ts +270 -0
  317. package/tui/src/tools/DocumentPrimitive/documentDestinationPath.ts +18 -0
  318. package/tui/src/tools/DocumentPrimitive/documentMutationGuard.ts +22 -0
  319. package/tui/src/tools/DocumentPrimitive/documentPatchNormalization.ts +248 -0
  320. package/tui/src/tools/DocumentPrimitive/documentSourceVerification.ts +245 -0
  321. package/tui/src/tools/DocumentPrimitive/documentSourceVerificationFields.ts +103 -0
  322. package/tui/src/tools/DocumentPrimitive/modelVisibleOutput.ts +40 -0
  323. package/tui/src/tools/DocumentPrimitive/prompt.ts +35 -0
  324. package/tui/src/tools/FileEditTool/FileEditTool.ts +9 -507
  325. package/tui/src/tools/FileEditTool/call.ts +228 -0
  326. package/tui/src/tools/FileEditTool/validateInput.ts +196 -0
  327. package/tui/src/tools/FileReadTool/imageProcessor.ts +13 -0
  328. package/tui/src/tools/FileWriteTool/FileWriteTool.ts +7 -300
  329. package/tui/src/tools/FileWriteTool/call.ts +223 -0
  330. package/tui/src/tools/FileWriteTool/validateInput.ts +80 -0
  331. package/tui/src/tools/ListMcpResourcesTool/ListMcpResourcesTool.ts +19 -3
  332. package/tui/src/tools/LookupPrimitive/LookupPrimitive.ts +25 -32
  333. package/tui/src/tools/LookupPrimitive/prompt.ts +0 -2
  334. package/tui/src/tools/MCPTool/trustPolicy.ts +118 -0
  335. package/tui/src/tools/McpAuthTool/McpAuthTool.ts +21 -3
  336. package/tui/src/tools/NotebookEditTool/NotebookEditTool.ts +7 -326
  337. package/tui/src/tools/NotebookEditTool/call.ts +254 -0
  338. package/tui/src/tools/NotebookEditTool/notebookModel.ts +51 -0
  339. package/tui/src/tools/NotebookEditTool/validateInput.ts +142 -0
  340. package/tui/src/tools/PowerShellTool/PowerShellTool.tsx +46 -937
  341. package/tui/src/tools/PowerShellTool/acceptEditsCommandValidation.ts +162 -0
  342. package/tui/src/tools/PowerShellTool/call.ts +179 -0
  343. package/tui/src/tools/PowerShellTool/callLoader.ts +37 -0
  344. package/tui/src/tools/PowerShellTool/commandClassification.ts +86 -0
  345. package/tui/src/tools/PowerShellTool/modeValidation.ts +25 -332
  346. package/tui/src/tools/PowerShellTool/outputPersistence.ts +42 -0
  347. package/tui/src/tools/PowerShellTool/permissionClassification.ts +28 -0
  348. package/tui/src/tools/PowerShellTool/resultLoader.ts +31 -0
  349. package/tui/src/tools/PowerShellTool/resultMapping.ts +75 -0
  350. package/tui/src/tools/PowerShellTool/schemas.ts +40 -0
  351. package/tui/src/tools/PowerShellTool/shellExecution.tsx +258 -0
  352. package/tui/src/tools/PowerShellTool/symlinkModeValidation.ts +44 -0
  353. package/tui/src/tools/PowerShellTool/uiLoader.ts +37 -0
  354. package/tui/src/tools/PowerShellTool/validation.ts +39 -0
  355. package/tui/src/tools/ReadMcpResourceTool/ReadMcpResourceTool.ts +19 -3
  356. package/tui/src/tools/ResolveLocationPrimitive/ResolveLocationPrimitive.ts +1 -11
  357. package/tui/src/tools/ResolveLocationPrimitive/prompt.ts +2 -6
  358. package/tui/src/tools/SkillTool/SkillTool.ts +2 -2
  359. package/tui/src/tools/SubmitPrimitive/SubmitPrimitive.ts +27 -10
  360. package/tui/src/tools/TaskCreateTool/TaskCreateTool.ts +16 -2
  361. package/tui/src/tools/TaskGetTool/TaskGetTool.ts +23 -3
  362. package/tui/src/tools/TaskListTool/TaskListTool.ts +22 -4
  363. package/tui/src/tools/TaskOutputTool/TaskOutputTool.tsx +46 -547
  364. package/tui/src/tools/TaskOutputTool/lookup.ts +216 -0
  365. package/tui/src/tools/TaskOutputTool/render.tsx +257 -0
  366. package/tui/src/tools/TaskOutputTool/schemas.ts +55 -0
  367. package/tui/src/tools/TaskOutputTool/serialization.ts +36 -0
  368. package/tui/src/tools/TaskStopTool/TaskStopTool.ts +10 -0
  369. package/tui/src/tools/TaskUpdateTool/TaskUpdateTool.ts +14 -364
  370. package/tui/src/tools/TaskUpdateTool/completion.ts +62 -0
  371. package/tui/src/tools/TaskUpdateTool/schemas.ts +62 -0
  372. package/tui/src/tools/TaskUpdateTool/serialization.ts +46 -0
  373. package/tui/src/tools/TaskUpdateTool/statusUpdate.ts +247 -0
  374. package/tui/src/tools/TodoWriteTool/TodoWriteTool.ts +21 -2
  375. package/tui/src/tools/ToolSearchTool/ToolSearchTool.ts +21 -302
  376. package/tui/src/tools/ToolSearchTool/ccSupportTools.ts +223 -0
  377. package/tui/src/tools/ToolSearchTool/descriptionCache.ts +50 -0
  378. package/tui/src/tools/ToolSearchTool/keywordSearch.ts +216 -0
  379. package/tui/src/tools/ToolSearchTool/prompt.ts +10 -4
  380. package/tui/src/tools/ToolSearchTool/resultMapping.ts +30 -0
  381. package/tui/src/tools/ToolSearchTool/schemas.ts +30 -0
  382. package/tui/src/tools/ToolSearchTool/searchPool.ts +47 -0
  383. package/tui/src/tools/ToolSearchTool/supportIntentHints.ts +140 -0
  384. package/tui/src/tools/TranslateTool/TranslateTool.ts +1 -1
  385. package/tui/src/tools/VerifyPrimitive/VerifyPrimitive.ts +2 -1
  386. package/tui/src/tools/WebFetchTool/WebFetchTool.ts +43 -138
  387. package/tui/src/tools/WebFetchTool/call.ts +227 -0
  388. package/tui/src/tools/WebFetchTool/resolvedAddressSafety.ts +78 -0
  389. package/tui/src/tools/WebFetchTool/sourceVerification.ts +204 -0
  390. package/tui/src/tools/WebFetchTool/types.ts +23 -0
  391. package/tui/src/tools/WebFetchTool/urlSafety.ts +181 -0
  392. package/tui/src/tools/WebFetchTool/utils.ts +1 -1
  393. package/tui/src/tools/WebSearchTool/UI.tsx +0 -1
  394. package/tui/src/tools/WebSearchTool/WebSearchTool.ts +9 -313
  395. package/tui/src/tools/WebSearchTool/call.ts +33 -0
  396. package/tui/src/tools/WebSearchTool/responseMapping.ts +190 -0
  397. package/tui/src/tools/WebSearchTool/resultBlock.ts +47 -0
  398. package/tui/src/tools/WebSearchTool/schemas.ts +47 -0
  399. package/tui/src/tools/WebSearchTool/toolSchema.ts +12 -0
  400. package/tui/src/tools/WorkspaceToolAdapter/WorkspaceToolAdapter.ts +79 -0
  401. package/tui/src/tools/WorkspaceToolAdapter/allowedRootPolicy.ts +85 -0
  402. package/tui/src/tools/WorkspaceToolAdapter/documentFormatGuards.ts +73 -0
  403. package/tui/src/tools/WorkspaceToolAdapter/inputNormalization.ts +105 -0
  404. package/tui/src/tools/WorkspaceToolAdapter/mcpExposurePolicy.ts +64 -0
  405. package/tui/src/tools/WorkspaceToolAdapter/toolDefFactory.ts +215 -0
  406. package/tui/src/tools/WorkspaceToolAdapter/toolNames.ts +6 -0
  407. package/tui/src/tools/WorkspaceToolAdapter/workspacePolicy.ts +15 -0
  408. package/tui/src/tools/_shared/dispatchPrimitive.ts +6 -6
  409. package/tui/src/tools/_shared/documentChangeToPatch.ts +125 -0
  410. package/tui/src/tools/_shared/documentDispatchArguments.ts +87 -0
  411. package/tui/src/tools/_shared/documentPrimitiveTimeout.ts +13 -0
  412. package/tui/src/tools/_shared/documentToolResultRender.ts +98 -0
  413. package/tui/src/tools/_shared/pendingCallRegistry.ts +1 -6
  414. package/tui/src/tools/_shared/rootPrimitiveInput.ts +1 -0
  415. package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPatterns.ts +58 -0
  416. package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPrompt.ts +271 -0
  417. package/tui/src/tools/_shared/toolChoiceRepair/documentRepair.ts +452 -0
  418. package/tui/src/tools/_shared/toolChoiceRepair/messageAccess.ts +80 -0
  419. package/tui/src/tools/_shared/toolChoiceRepair/publicDataRepair.ts +92 -0
  420. package/tui/src/tools/_shared/toolChoiceRepair/supportRepair.ts +135 -0
  421. package/tui/src/tools/_shared/toolChoiceRepair.ts +55 -860
  422. package/tui/src/tools/shared/mockDisclaimer.ts +1 -1
  423. package/tui/src/tools.ts +39 -190
  424. package/tui/src/types/fileSuggestion.ts +4 -26
  425. package/tui/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +186 -148
  426. package/tui/src/types/generated/events_mono/common/v1/auth.ts +25 -11
  427. package/tui/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +47 -30
  428. package/tui/src/types/generated/google/protobuf/timestamp.ts +21 -7
  429. package/tui/src/types/message.ts +80 -102
  430. package/tui/src/types/messageQueueTypes.ts +6 -28
  431. package/tui/src/types/notebook.ts +16 -38
  432. package/tui/src/types/statusLine.ts +4 -26
  433. package/tui/src/types/tools.ts +24 -46
  434. package/tui/src/types/utils.ts +6 -28
  435. package/tui/src/upstreamproxy/relay.ts +7 -3
  436. package/tui/src/upstreamproxy/upstreamproxy.ts +1 -1
  437. package/tui/src/utils/assistantMessageFactories.ts +9 -3
  438. package/tui/src/utils/auth.ts +129 -139
  439. package/tui/src/utils/bash/ast.ts +23 -23
  440. package/tui/src/utils/bash/bashParser.ts +5 -5
  441. package/tui/src/utils/billing.ts +1 -1
  442. package/tui/src/utils/collapseReadSearch.ts +3 -3
  443. package/tui/src/utils/cronTasks.ts +1 -1
  444. package/tui/src/utils/execFileNoThrow.ts +1 -1
  445. package/tui/src/utils/filePersistence/types.ts +16 -38
  446. package/tui/src/utils/forkedAgent.ts +1 -1
  447. package/tui/src/utils/gracefulShutdown.ts +4 -4
  448. package/tui/src/utils/heapDumpService.ts +12 -8
  449. package/tui/src/utils/hooks/apiQueryHookHelper.ts +1 -1
  450. package/tui/src/utils/hooks/execPromptHook.ts +1 -1
  451. package/tui/src/utils/hooks/skillImprovement.ts +1 -1
  452. package/tui/src/utils/mcp/dateTimeParser.ts +1 -1
  453. package/tui/src/utils/messages.ts +18 -0
  454. package/tui/src/utils/migrateSessions.ts +3 -3
  455. package/tui/src/utils/model/model.ts +6 -6
  456. package/tui/src/utils/permissions/yoloClassifier.ts +1 -1
  457. package/tui/src/utils/plugins/headlessPluginInstall.ts +1 -1
  458. package/tui/src/utils/plugins/mcpPluginIntegration.ts +1 -1
  459. package/tui/src/utils/plugins/mcpbHandler.ts +1 -1
  460. package/tui/src/utils/plugins/pluginLoader.ts +8 -8
  461. package/tui/src/utils/protectedNamespace.ts +5 -3
  462. package/tui/src/utils/rawJsonToolCall.ts +242 -0
  463. package/tui/src/utils/ripgrep.ts +16 -7
  464. package/tui/src/utils/sessionTitle.ts +1 -1
  465. package/tui/src/utils/settings/permissionValidation.ts +14 -2
  466. package/tui/src/utils/shell/prefix.ts +1 -1
  467. package/tui/src/utils/sideQuery.ts +1 -1
  468. package/tui/src/utils/systemThemeWatcher.ts +13 -3
  469. package/tui/src/utils/teleport.tsx +1 -1
  470. package/uv.lock +400 -14
  471. package/tui/src/services/api/claude.ts +0 -3540
  472. package/tui/src/tools/_shared/directPublicDataGuard.ts +0 -362
  473. package/tui/src/tools/_shared/kmaAnalysisGuard.ts +0 -197
  474. package/tui/src/tools/_shared/kmaAviationGuard.ts +0 -70
  475. package/tui/src/tools/_shared/nmcAedGuard.ts +0 -234
  476. package/tui/src/tools/_shared/protectedCheckGuard.ts +0 -207
  477. package/tui/src/tools/_shared/textToolCallGuard.ts +0 -91
@@ -0,0 +1,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
@@ -601,7 +601,7 @@ function convertToolChoice(
601
601
  }
602
602
 
603
603
  function sanitizeSchema(schema: Record<string, unknown>): Record<string, unknown> {
604
- const clone = { ...schema }
604
+ const clone = inlineLocalJsonSchemaRefs(schema)
605
605
  delete clone.cache_control
606
606
  delete clone.defer_loading
607
607
  delete clone.eager_input_streaming
@@ -609,6 +609,69 @@ function sanitizeSchema(schema: Record<string, unknown>): Record<string, unknown
609
609
  return clone
610
610
  }
611
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
+
612
675
  function systemToText(system: BetaMessageStreamParams['system']): string {
613
676
  if (!system) return ''
614
677
  if (typeof system === 'string') return system
@@ -36,7 +36,7 @@ export type ConnectionErrorDetails = {
36
36
 
37
37
  /**
38
38
  * Extracts connection error details from the error cause chain.
39
- * The Anthropic SDK wraps underlying errors in the `cause` property.
39
+ * The legacy SDK wraps underlying errors in the `cause` property.
40
40
  * This function walks the cause chain to find the root error code/message.
41
41
  */
42
42
  export function extractConnectionErrorDetails(
@@ -96,7 +96,7 @@ export function getSSLErrorHint(error: unknown): string | null {
96
96
  if (!details?.isSSLError) {
97
97
  return null
98
98
  }
99
- return `SSL certificate error (${details.code}). If you are behind a corporate proxy or TLS-intercepting firewall, set NODE_EXTRA_CA_CERTS to your CA bundle path, or ask IT to allowlist *.anthropic.com. Run /doctor for details.`
99
+ return `SSL certificate error (${details.code}). If you are behind a corporate proxy or TLS-intercepting firewall, set NODE_EXTRA_CA_CERTS to your CA bundle path, or ask IT to allowlist the configured UMMAYA provider endpoint. Run /doctor for details.`
100
100
  }
101
101
 
102
102
  /**
@@ -136,7 +136,7 @@ export function sanitizeAPIError(apiError: APIError): string {
136
136
  * The actual message lives at different nesting levels depending on the provider:
137
137
  *
138
138
  * - Bedrock/proxy: `{ error: { message: "..." } }`
139
- * - Standard Anthropic API: `{ error: { error: { message: "..." } } }`
139
+ * - Provider API: `{ error: { error: { message: "..." } } }`
140
140
  * (the outer `.error` is the response body, the inner `.error` is the API error)
141
141
  *
142
142
  * See also: `getErrorMessage` in `logging.ts` which handles the same shapes.
@@ -163,7 +163,7 @@ function hasNestedError(value: unknown): value is NestedAPIError {
163
163
  * a top-level `.message`.
164
164
  *
165
165
  * Checks two nesting levels (deeper first for specificity):
166
- * 1. `error.error.error.message` — standard Anthropic API shape
166
+ * 1. `error.error.error.message` — provider API shape
167
167
  * 2. `error.error.message` — Bedrock shape
168
168
  */
169
169
  function extractNestedErrorMessage(error: APIError): string | null {
@@ -176,7 +176,7 @@ function extractNestedErrorMessage(error: APIError): string | null {
176
176
  const narrowed: NestedAPIError = error
177
177
  const nested = narrowed.error
178
178
 
179
- // Standard Anthropic API shape: { error: { error: { message } } }
179
+ // Provider API shape: { error: { error: { message } } }
180
180
  const deepMsg = nested?.error?.message
181
181
  if (typeof deepMsg === 'string' && deepMsg.length > 0) {
182
182
  const sanitized = sanitizeMessageHTML(deepMsg)
@@ -1,6 +1,6 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // SWAP/anti-anthropic-1p(2521): minimal stub for the byte-copied
3
- // services/api/claude.ts which references CC's Anthropic-API error envelopes.
3
+ // services/api/ummaya.ts which references CC's Anthropic-API error envelopes.
4
4
  // UMMAYA surfaces errors via the IPC ErrorFrame (Spec 032) and never reaches
5
5
  // these helpers. Stubs preserve the import shape only.
6
6
 
@@ -1,6 +1,6 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // SWAP/anti-anthropic-1p(2521): minimal stub for the byte-copied
3
- // services/api/claude.ts which references CC's Anthropic-API request/response
3
+ // services/api/ummaya.ts which references CC's Anthropic-API request/response
4
4
  // telemetry. UMMAYA uses OTEL spans (Spec 021) and audit ledger (Spec 024)
5
5
  // instead. Stubs preserve the import shape; functions are no-ops because the
6
6
  // byte-copy has zero callers in UMMAYA.