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,200 @@
1
+ import { assertFriendliApiKeyForUse } from '../../../utils/auth.js'
2
+ import {
3
+ createAssistantAPIErrorMessage,
4
+ createAssistantMessage,
5
+ } from '../../../utils/messages.js'
6
+ import { ensureUmmayaAdapterManifest } from '../../../ipc/bridgeSingleton.js'
7
+ import { latestUserText } from './messages.js'
8
+ import { buildProviderRequest, getAPIMetadata } from './request.js'
9
+ import {
10
+ ProviderStreamIdleTimeoutError,
11
+ streamResponseToMessages,
12
+ } from './streaming.js'
13
+ import { shouldWaitForAdapterManifestForProviderRequest } from './toolSelection.js'
14
+ import type { QueryModelParams } from './types.js'
15
+ import {
16
+ appendProviderOutputEvidence,
17
+ appendProviderTurnEvidence,
18
+ createProviderTurnEvidenceContext,
19
+ } from './evidence.js'
20
+ import type { ProviderOptions } from './types.js'
21
+
22
+ export { getAPIMetadata }
23
+
24
+ export const PUBLIC_SERVICE_MANIFEST_SYNC_TIMEOUT_MS = 30_000
25
+ const PROVIDER_STREAM_TIMEOUT_HANDOFF =
26
+ 'K-EXAONE 응답이 지연되어 이번 요청을 이어갈 수 없습니다. 잠시 후 다시 시도해 주세요.'
27
+ const DEFAULT_PROVIDER_EVENT_IDLE_TIMEOUT_MS = 90_000
28
+ const PROVIDER_EVENT_IDLE_TIMEOUT_ENV = 'UMMAYA_TUI_PROVIDER_EVENT_IDLE_TIMEOUT_MS'
29
+ const FRAME_IDLE_TIMEOUT_ENV = 'UMMAYA_TUI_FRAME_IDLE_TIMEOUT_MS'
30
+ const FRIENDLI_CHAT_COMPLETIONS_URL =
31
+ 'https://api.friendli.ai/serverless/v1/chat/completions'
32
+ const TEST_PUBLIC_SERVICE_MANIFEST_SYNC_TIMEOUT_ENV =
33
+ 'UMMAYA_TEST_PUBLIC_SERVICE_MANIFEST_SYNC_TIMEOUT_MS'
34
+
35
+ function publicServiceManifestSyncTimeoutMs(): number {
36
+ const rawTimeout = process.env[TEST_PUBLIC_SERVICE_MANIFEST_SYNC_TIMEOUT_ENV]
37
+ if (rawTimeout === undefined) return PUBLIC_SERVICE_MANIFEST_SYNC_TIMEOUT_MS
38
+
39
+ const parsedTimeout = Number(rawTimeout)
40
+ if (!Number.isInteger(parsedTimeout) || parsedTimeout <= 0) {
41
+ return PUBLIC_SERVICE_MANIFEST_SYNC_TIMEOUT_MS
42
+ }
43
+ return parsedTimeout
44
+ }
45
+
46
+ function adapterManifestTimeoutMessage(timeoutMs: number): string {
47
+ return [
48
+ `public-service adapter manifest did not sync within ${timeoutMs}ms;`,
49
+ 'backend readiness is required before starting public-service provider requests.',
50
+ 'Retry after adapter_manifest_sync arrives from the backend.',
51
+ ].join(' ')
52
+ }
53
+
54
+ function providerEventIdleTimeoutMs(): number {
55
+ const rawTimeout =
56
+ process.env[PROVIDER_EVENT_IDLE_TIMEOUT_ENV] ??
57
+ process.env[FRAME_IDLE_TIMEOUT_ENV]
58
+ if (rawTimeout === undefined) return DEFAULT_PROVIDER_EVENT_IDLE_TIMEOUT_MS
59
+
60
+ const parsedTimeout = Number.parseInt(rawTimeout, 10)
61
+ if (!Number.isFinite(parsedTimeout) || parsedTimeout <= 0) {
62
+ return DEFAULT_PROVIDER_EVENT_IDLE_TIMEOUT_MS
63
+ }
64
+ return parsedTimeout
65
+ }
66
+
67
+ export function getExtraBodyParams(_betaHeaders?: readonly string[]): Record<string, unknown> {
68
+ return {}
69
+ }
70
+
71
+ export function configureTaskBudgetParams(
72
+ taskBudget: { readonly total: number; readonly remaining?: number } | undefined,
73
+ outputConfig: Record<string, unknown>,
74
+ _betas: string[],
75
+ ): void {
76
+ if (!taskBudget) return
77
+ outputConfig.task_budget = taskBudget
78
+ }
79
+
80
+ export async function verifyApiKey(
81
+ apiKey: string,
82
+ _isNonInteractiveSession: boolean,
83
+ ): Promise<boolean> {
84
+ return apiKey.trim().length > 0
85
+ }
86
+
87
+ export async function* queryModelWithStreaming(
88
+ params: QueryModelParams,
89
+ ): AsyncGenerator<unknown> {
90
+ assertFriendliApiKeyForUse()
91
+ const evidenceContext = createProviderTurnEvidenceContext(params)
92
+ const userText = latestUserText(params.messages)
93
+ if (
94
+ shouldWaitForAdapterManifestForProviderRequest({
95
+ querySource: params.options.querySource,
96
+ userText,
97
+ })
98
+ ) {
99
+ const timeoutMs = publicServiceManifestSyncTimeoutMs()
100
+ const manifestSynced = await ensureUmmayaAdapterManifest(timeoutMs)
101
+ if (!manifestSynced) {
102
+ yield createAssistantAPIErrorMessage({
103
+ content: adapterManifestTimeoutMessage(timeoutMs),
104
+ apiError: 'api_error',
105
+ })
106
+ return
107
+ }
108
+ }
109
+ const request = buildProviderRequest(params, evidenceContext)
110
+ const fetchImpl: NonNullable<ProviderOptions['fetchOverride']> =
111
+ params.options.fetchOverride ?? ((input, init) => fetch(input, init))
112
+ yield { type: 'stream_request_start' as const }
113
+ let providerTurnStarted = false
114
+ try {
115
+ appendProviderTurnEvidence('provider_turn_start', evidenceContext)
116
+ providerTurnStarted = true
117
+ const response = await fetchProviderResponse(
118
+ fetchImpl,
119
+ {
120
+ method: 'POST',
121
+ headers: {
122
+ 'content-type': 'application/json',
123
+ authorization: `Bearer ${process.env.UMMAYA_FRIENDLI_TOKEN ?? ''}`,
124
+ },
125
+ body: JSON.stringify(request),
126
+ signal: params.signal,
127
+ },
128
+ providerEventIdleTimeoutMs(),
129
+ )
130
+ for await (const event of streamResponseToMessages(response, {
131
+ dataIdleTimeoutMs: providerEventIdleTimeoutMs(),
132
+ availableToolNames: rawJsonToolCallNamesForRequest(request),
133
+ includeReasoning: request.include_reasoning === true,
134
+ })) {
135
+ appendProviderOutputEvidence(event, evidenceContext)
136
+ yield event
137
+ }
138
+ } catch (error) {
139
+ if (error instanceof ProviderStreamIdleTimeoutError) {
140
+ yield createAssistantMessage({
141
+ content: PROVIDER_STREAM_TIMEOUT_HANDOFF,
142
+ })
143
+ return
144
+ }
145
+ throw error
146
+ } finally {
147
+ if (providerTurnStarted) {
148
+ appendProviderTurnEvidence('provider_turn_complete', evidenceContext)
149
+ }
150
+ }
151
+ }
152
+
153
+ function rawJsonToolCallNamesForRequest(request: {
154
+ readonly tools?: readonly {
155
+ readonly function: { readonly name: string }
156
+ }[]
157
+ }): readonly string[] {
158
+ const names = new Set<string>()
159
+ for (const tool of request.tools ?? []) {
160
+ const name = tool.function.name.trim()
161
+ if (name.length > 0) names.add(name)
162
+ }
163
+ return [...names]
164
+ }
165
+
166
+ async function fetchProviderResponse(
167
+ fetchImpl: NonNullable<ProviderOptions['fetchOverride']>,
168
+ init: RequestInit,
169
+ timeoutMs: number,
170
+ ): Promise<Response> {
171
+ const controller = new AbortController()
172
+ const upstreamSignal = init.signal
173
+ const abortFromUpstream = () => {
174
+ controller.abort(upstreamSignal?.reason)
175
+ }
176
+ if (upstreamSignal?.aborted) {
177
+ controller.abort(upstreamSignal.reason)
178
+ } else {
179
+ upstreamSignal?.addEventListener('abort', abortFromUpstream, { once: true })
180
+ }
181
+ let timeoutId: ReturnType<typeof setTimeout> | undefined
182
+ const timeout = new Promise<never>((_, reject) => {
183
+ timeoutId = setTimeout(() => {
184
+ controller.abort()
185
+ reject(new ProviderStreamIdleTimeoutError(timeoutMs))
186
+ }, timeoutMs)
187
+ })
188
+ try {
189
+ return await Promise.race([
190
+ fetchImpl(FRIENDLI_CHAT_COMPLETIONS_URL, {
191
+ ...init,
192
+ signal: controller.signal,
193
+ }),
194
+ timeout,
195
+ ])
196
+ } finally {
197
+ if (timeoutId !== undefined) clearTimeout(timeoutId)
198
+ upstreamSignal?.removeEventListener('abort', abortFromUpstream)
199
+ }
200
+ }
@@ -0,0 +1,24 @@
1
+ import {
2
+ getInitialReasoningModeSetting,
3
+ providerReasoningPayload,
4
+ resolveKExaoneReasoningPolicy,
5
+ } from '../../../utils/kExaoneReasoning.js'
6
+
7
+ export function providerReasoningRequestPayload(): {
8
+ readonly chat_template_kwargs: { readonly enable_thinking: boolean }
9
+ readonly parse_reasoning: boolean
10
+ readonly include_reasoning: boolean
11
+ } {
12
+ const envResolvedPolicy = resolveKExaoneReasoningPolicy()
13
+ if (
14
+ envResolvedPolicy.source === 'env' ||
15
+ envResolvedPolicy.source === 'legacy-env'
16
+ ) {
17
+ return providerReasoningPayload(envResolvedPolicy)
18
+ }
19
+ return providerReasoningPayload(
20
+ resolveKExaoneReasoningPolicy({
21
+ userSettingsMode: getInitialReasoningModeSetting(),
22
+ }),
23
+ )
24
+ }
@@ -0,0 +1,200 @@
1
+ import { z } from 'zod/v4'
2
+ import type { Tool } from '../../../Tool.js'
3
+ import type {
4
+ OpenAITool,
5
+ ProviderOptions,
6
+ ProviderRequest,
7
+ QueryModelParams,
8
+ } from './types.js'
9
+ import { latestUserText, transcriptToOpenAIMessages } from './messages.js'
10
+ import {
11
+ selectProviderToolChoiceName,
12
+ selectProviderTools,
13
+ } from './toolSelection.js'
14
+ import type { ProviderTurnEvidenceContext } from './evidence.js'
15
+ import {
16
+ hasCurrentTurnLocationContext,
17
+ selectionTextWithPriorLocationContext,
18
+ } from './selectionContext.js'
19
+ import { providerReasoningRequestPayload } from './reasoning.js'
20
+
21
+ function forcedToolChoiceSystemInstruction(toolName: string): string {
22
+ if (toolName === 'workspace_bash') {
23
+ return [
24
+ `Mandatory tool call: the host selected ${toolName} for this turn.`,
25
+ 'Do not answer with prose, do not ask a follow-up question, and do not choose another tool.',
26
+ `Emit exactly one ${toolName} tool call with valid JSON arguments.`,
27
+ 'For sequenced shell requests, emit the next concrete shell command requested by the user rather than a status summary.',
28
+ 'If the user asks to attempt a destructive command and says they will deny the permission prompt, still emit that destructive command so the host permission gate can prompt and enforce the denial.',
29
+ 'Do not replace a requested delete command with ls/find/path-existence prose, and preserve leading dots in hidden paths such as .omo/...',
30
+ ].join(' ')
31
+ }
32
+ return `Mandatory tool call: the host selected ${toolName} for this turn. Do not answer with prose, do not ask a follow-up question, and do not choose another tool. Emit exactly one ${toolName} tool call with valid JSON arguments.`
33
+ }
34
+
35
+ function schemaForTool(tool: Tool): Record<string, unknown> {
36
+ if (tool.inputJSONSchema) {
37
+ return normalizeProviderParameterSchema(tool.inputJSONSchema)
38
+ }
39
+ const generatedSchema = z.toJSONSchema(tool.inputSchema)
40
+ return normalizeProviderParameterSchema(
41
+ isJsonObject(generatedSchema) ? generatedSchema : {},
42
+ )
43
+ }
44
+
45
+ function normalizeProviderParameterSchema(
46
+ schema: Record<string, unknown>,
47
+ ): Record<string, unknown> {
48
+ const normalized = normalizeSchemaNode(schema, schema, new Set<string>())
49
+ if (isJsonObject(normalized)) return normalized
50
+ return providerSafeUnresolvedRefSchema()
51
+ }
52
+
53
+ function normalizeSchemaNode(
54
+ value: unknown,
55
+ root: Record<string, unknown>,
56
+ refStack: ReadonlySet<string>,
57
+ ): unknown {
58
+ if (Array.isArray(value)) {
59
+ return value.map(item => normalizeSchemaNode(item, root, refStack))
60
+ }
61
+ if (!isJsonObject(value)) return value
62
+
63
+ const ref = typeof value.$ref === 'string' ? value.$ref : undefined
64
+ if (ref !== undefined) {
65
+ const inlined = inlineLocalSchemaRef(ref, value, root, refStack)
66
+ if (inlined !== undefined) return inlined
67
+ return providerSafeUnresolvedRefSchema()
68
+ }
69
+
70
+ const normalized: Record<string, unknown> = {}
71
+ for (const [key, child] of Object.entries(value)) {
72
+ if (key === '$defs' || key === 'definitions') continue
73
+ normalized[key] = normalizeSchemaNode(child, root, refStack)
74
+ }
75
+ return normalized
76
+ }
77
+
78
+ function inlineLocalSchemaRef(
79
+ ref: string,
80
+ schemaWithRef: Record<string, unknown>,
81
+ root: Record<string, unknown>,
82
+ refStack: ReadonlySet<string>,
83
+ ): unknown | undefined {
84
+ if (refStack.has(ref)) return undefined
85
+ const resolved = resolveLocalSchemaRef(root, ref)
86
+ if (resolved === undefined) return undefined
87
+ const nextStack = new Set(refStack)
88
+ nextStack.add(ref)
89
+ const normalizedResolved = normalizeSchemaNode(resolved, root, nextStack)
90
+ if (!isJsonObject(normalizedResolved)) return normalizedResolved
91
+
92
+ const normalizedSiblings: Record<string, unknown> = {}
93
+ for (const [key, child] of Object.entries(schemaWithRef)) {
94
+ if (key === '$ref' || key === '$defs' || key === 'definitions') continue
95
+ normalizedSiblings[key] = normalizeSchemaNode(child, root, nextStack)
96
+ }
97
+ return {
98
+ ...normalizedResolved,
99
+ ...normalizedSiblings,
100
+ }
101
+ }
102
+
103
+ function resolveLocalSchemaRef(
104
+ root: Record<string, unknown>,
105
+ ref: string,
106
+ ): unknown | undefined {
107
+ if (ref === '#') return root
108
+ if (!ref.startsWith('#/')) return undefined
109
+
110
+ let current: unknown = root
111
+ for (const segment of ref.slice(2).split('/').map(decodeJsonPointerSegment)) {
112
+ if (!isJsonObject(current)) return undefined
113
+ current = current[segment]
114
+ }
115
+ return current
116
+ }
117
+
118
+ function decodeJsonPointerSegment(segment: string): string {
119
+ return segment.replace(/~1/g, '/').replace(/~0/g, '~')
120
+ }
121
+
122
+ function providerSafeUnresolvedRefSchema(): Record<string, unknown> {
123
+ return {
124
+ type: 'object',
125
+ description:
126
+ 'Provider-safe open object for an unresolved local schema reference.',
127
+ properties: {},
128
+ additionalProperties: true,
129
+ }
130
+ }
131
+
132
+ function isJsonObject(value: unknown): value is Record<string, unknown> {
133
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
134
+ }
135
+
136
+ function toolToOpenAI(tool: Tool): OpenAITool {
137
+ return {
138
+ type: 'function',
139
+ function: {
140
+ name: tool.name,
141
+ description: tool.searchHint ?? tool.name,
142
+ parameters: schemaForTool(tool),
143
+ },
144
+ }
145
+ }
146
+
147
+ function toolChoiceFor(
148
+ toolName: string | undefined,
149
+ ): ProviderRequest['tool_choice'] {
150
+ if (toolName === undefined) return undefined
151
+ return {
152
+ type: 'function',
153
+ function: { name: toolName },
154
+ }
155
+ }
156
+
157
+ export function buildProviderRequest(
158
+ params: QueryModelParams,
159
+ evidenceContext?: ProviderTurnEvidenceContext,
160
+ ): ProviderRequest {
161
+ const forcedToolName =
162
+ params.options.toolChoice?.type === 'tool'
163
+ ? params.options.toolChoice.name
164
+ : undefined
165
+ const userText = selectionTextWithPriorLocationContext(params.messages)
166
+ const selectedToolChoiceName = selectProviderToolChoiceName({
167
+ tools: params.tools,
168
+ userText,
169
+ forcedToolName,
170
+ })
171
+ const tools = selectProviderTools({
172
+ tools: params.tools,
173
+ userText,
174
+ forcedToolName: selectedToolChoiceName,
175
+ disabledToolNames: params.options.disabledProviderToolNames ?? [],
176
+ querySource: params.options.querySource,
177
+ hasCurrentTurnLocationContext: hasCurrentTurnLocationContext(params.messages),
178
+ evidenceContext,
179
+ })
180
+ const toolChoice = toolChoiceFor(selectedToolChoiceName)
181
+ const toolPayload = tools.map(toolToOpenAI)
182
+ return {
183
+ model: params.options.model,
184
+ stream: true,
185
+ ...providerReasoningRequestPayload(),
186
+ messages: transcriptToOpenAIMessages(
187
+ params.messages,
188
+ params.systemPrompt,
189
+ selectedToolChoiceName
190
+ ? forcedToolChoiceSystemInstruction(selectedToolChoiceName)
191
+ : undefined,
192
+ ),
193
+ ...(toolPayload.length > 0 ? { tools: toolPayload } : {}),
194
+ ...(toolChoice ? { tool_choice: toolChoice } : {}),
195
+ }
196
+ }
197
+
198
+ export function getAPIMetadata(): Record<string, string> {
199
+ return { user_id: 'ummaya-local' }
200
+ }
@@ -0,0 +1,240 @@
1
+ import type { Message } from '../../../types/message.js'
2
+ import { latestUserText } from './messages.js'
3
+
4
+ const RELATIVE_LOCATION_PROMPT_RE =
5
+ /(주위|주변|인근|가까운|우리\s*동네|여기|이\s*근처|현재\s*위치|내\s*위치)/iu
6
+ const RELATIVE_HEALTH_PROMPT_RE =
7
+ /(응급|응급실|응급의료|병원|의원|진료|야간진료|약국|의료|건강|아파|다쳤|발열|hospital|clinic|pharmacy|emergency|ER)/iu
8
+
9
+ type ToolResultBlock = {
10
+ readonly type: 'tool_result'
11
+ readonly content?: unknown
12
+ readonly isError: boolean
13
+ }
14
+
15
+ function isRecord(value: unknown): value is Record<string, unknown> {
16
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
17
+ }
18
+
19
+ function asToolResultBlock(value: unknown): ToolResultBlock | undefined {
20
+ if (!isRecord(value)) return undefined
21
+ if (value.type !== 'tool_result') return undefined
22
+ return {
23
+ type: 'tool_result',
24
+ content: value.content,
25
+ isError: value.is_error === true,
26
+ }
27
+ }
28
+
29
+ function parseJsonObject(value: unknown): Record<string, unknown> | undefined {
30
+ if (isRecord(value)) return value
31
+ if (typeof value !== 'string' || !value.trim()) return undefined
32
+ try {
33
+ const parsed: unknown = JSON.parse(value)
34
+ return isRecord(parsed) ? parsed : undefined
35
+ } catch {
36
+ return undefined
37
+ }
38
+ }
39
+
40
+ function textField(
41
+ source: Record<string, unknown>,
42
+ fieldName: string,
43
+ ): string | undefined {
44
+ const value = source[fieldName]
45
+ return typeof value === 'string' && value.trim() ? value.trim() : undefined
46
+ }
47
+
48
+ function numberField(
49
+ source: Record<string, unknown>,
50
+ fieldName: string,
51
+ ): string | undefined {
52
+ const value = source[fieldName]
53
+ return typeof value === 'number' && Number.isFinite(value) ? String(value) : undefined
54
+ }
55
+
56
+ function fieldIndicatesFailure(value: unknown): boolean {
57
+ if (value === false) return true
58
+ if (typeof value !== 'string') return false
59
+ return /(error|fail|failed|failure|timeout|denied|unavailable|invalid)/iu.test(
60
+ value.trim(),
61
+ )
62
+ }
63
+
64
+ function hasExplicitFailure(source: Record<string, unknown>): boolean {
65
+ if (fieldIndicatesFailure(source.ok)) return true
66
+ if (fieldIndicatesFailure(source.success)) return true
67
+ if (fieldIndicatesFailure(source.status)) return true
68
+ const error = source.error
69
+ if (typeof error === 'string') return error.trim().length > 0
70
+ return error !== undefined && error !== null && error !== false
71
+ }
72
+
73
+ function payloadHasExplicitFailure(payload: Record<string, unknown>): boolean {
74
+ if (hasExplicitFailure(payload)) return true
75
+ const data = recordField(payload, 'data')
76
+ return data !== undefined && hasExplicitFailure(data)
77
+ }
78
+
79
+ function recordField(
80
+ source: Record<string, unknown>,
81
+ fieldName: string,
82
+ ): Record<string, unknown> | undefined {
83
+ const value = source[fieldName]
84
+ return isRecord(value) ? value : undefined
85
+ }
86
+
87
+ function firstTextField(
88
+ sources: readonly Record<string, unknown>[],
89
+ fieldNames: readonly string[],
90
+ ): string | undefined {
91
+ for (const source of sources) {
92
+ for (const fieldName of fieldNames) {
93
+ const value = textField(source, fieldName)
94
+ if (value !== undefined) return value
95
+ }
96
+ }
97
+ return undefined
98
+ }
99
+
100
+ function firstNumberField(
101
+ sources: readonly Record<string, unknown>[],
102
+ fieldNames: readonly string[],
103
+ ): string | undefined {
104
+ for (const source of sources) {
105
+ for (const fieldName of fieldNames) {
106
+ const value = numberField(source, fieldName)
107
+ if (value !== undefined) return value
108
+ }
109
+ }
110
+ return undefined
111
+ }
112
+
113
+ function locationCandidateRecords(
114
+ result: Record<string, unknown>,
115
+ ): readonly Record<string, unknown>[] {
116
+ const candidates = [result]
117
+ for (const slot of ['coords', 'poi', 'region', 'address', 'adm_cd'] as const) {
118
+ const nested = recordField(result, slot)
119
+ if (nested !== undefined) candidates.push(nested)
120
+ }
121
+ return candidates
122
+ }
123
+
124
+ function locationContextFromPayload(
125
+ payload: Record<string, unknown>,
126
+ ): string | undefined {
127
+ if (payloadHasExplicitFailure(payload)) return undefined
128
+ const data = isRecord(payload.data) ? payload.data : undefined
129
+ const result = isRecord(payload.result)
130
+ ? payload.result
131
+ : data !== undefined && isRecord(data.result)
132
+ ? data.result
133
+ : data ?? payload
134
+ const candidates = locationCandidateRecords(result)
135
+ const latitude = firstNumberField(candidates, ['lat', 'latitude'])
136
+ const longitude = firstNumberField(candidates, ['lon', 'longitude'])
137
+ const x =
138
+ firstTextField(candidates, ['x']) ??
139
+ firstNumberField(candidates, ['x', 'nx'])
140
+ const y =
141
+ firstTextField(candidates, ['y']) ??
142
+ firstNumberField(candidates, ['y', 'ny'])
143
+ const regionName =
144
+ firstTextField(candidates, ['rdd_da_name', 'address_name', 'name']) ??
145
+ [
146
+ firstTextField(candidates, ['region_1depth_name']),
147
+ firstTextField(candidates, ['region_2depth_name']),
148
+ firstTextField(candidates, ['region_3depth_name']),
149
+ ]
150
+ .filter(Boolean)
151
+ .join(' ')
152
+ .trim()
153
+ const address =
154
+ firstTextField(candidates, ['road_address', 'jibun_address'])
155
+ if (!latitude && !longitude && !x && !y && !regionName && !address) {
156
+ return undefined
157
+ }
158
+ return [
159
+ '[prior_location_context]',
160
+ regionName ? `region=${regionName}` : undefined,
161
+ address ? `address=${address}` : undefined,
162
+ latitude && longitude ? `lat=${latitude} lon=${longitude}` : undefined,
163
+ x && y ? `x=${x} y=${y}` : undefined,
164
+ ]
165
+ .filter(Boolean)
166
+ .join(' ')
167
+ }
168
+
169
+ function latestPriorLocationContext(messages: readonly Message[]): string | undefined {
170
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
171
+ const message = messages[index]
172
+ if (message?.type !== 'user') continue
173
+ const content = message.message.content
174
+ if (!Array.isArray(content)) continue
175
+ for (const block of content) {
176
+ const toolResult = asToolResultBlock(block)
177
+ if (toolResult === undefined) continue
178
+ if (toolResult.isError) continue
179
+ const parsed = parseJsonObject(toolResult.content)
180
+ if (parsed === undefined) continue
181
+ const context = locationContextFromPayload(parsed)
182
+ if (context !== undefined) return context
183
+ }
184
+ }
185
+ return undefined
186
+ }
187
+
188
+ function userTextForSelectionIndex(message: Message): string {
189
+ const content = message.message.content
190
+ if (typeof content === 'string') return content.trim()
191
+ if (!Array.isArray(content)) return ''
192
+ return content
193
+ .filter(isRecord)
194
+ .filter(block => block.type === 'text' && typeof block.text === 'string')
195
+ .map(block => String(block.text))
196
+ .join('')
197
+ .trim()
198
+ }
199
+
200
+ function latestCitizenTextIndex(messages: readonly Message[]): number {
201
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
202
+ const message = messages[index]
203
+ if (message?.type !== 'user' || message.isMeta === true) continue
204
+ if (userTextForSelectionIndex(message).length > 0) return index
205
+ }
206
+ return -1
207
+ }
208
+
209
+ export function hasCurrentTurnLocationContext(
210
+ messages: readonly Message[],
211
+ ): boolean {
212
+ const latestIndex = latestCitizenTextIndex(messages)
213
+ if (latestIndex < 0) return false
214
+ for (let index = latestIndex + 1; index < messages.length; index += 1) {
215
+ const message = messages[index]
216
+ if (message?.type !== 'user') continue
217
+ const content = message.message.content
218
+ if (!Array.isArray(content)) continue
219
+ for (const block of content) {
220
+ const toolResult = asToolResultBlock(block)
221
+ if (toolResult === undefined) continue
222
+ if (toolResult.isError) continue
223
+ const parsed = parseJsonObject(toolResult.content)
224
+ if (parsed !== undefined && locationContextFromPayload(parsed) !== undefined) {
225
+ return true
226
+ }
227
+ }
228
+ }
229
+ return false
230
+ }
231
+
232
+ export function selectionTextWithPriorLocationContext(
233
+ messages: readonly Message[],
234
+ ): string {
235
+ const latest = latestUserText(messages)
236
+ if (!RELATIVE_LOCATION_PROMPT_RE.test(latest)) return latest
237
+ if (!RELATIVE_HEALTH_PROMPT_RE.test(latest)) return latest
238
+ const locationContext = latestPriorLocationContext(messages)
239
+ return locationContext === undefined ? latest : `${latest}\n${locationContext}`
240
+ }