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,97 @@
1
+ import type { ToolPermissionContext } from '../../Tool.js'
2
+ import type { PermissionResult } from '../../utils/permissions/PermissionResult.js'
3
+
4
+ type ShellRiskClass = {
5
+ readonly kind: 'destructive' | 'protected-ax'
6
+ readonly reason: string
7
+ }
8
+
9
+ type DestructiveWarningFn = (command: string) => string | null
10
+
11
+ const PROTECTED_AX_PATTERNS: readonly { readonly pattern: RegExp; readonly reason: string }[] = [
12
+ {
13
+ pattern:
14
+ /\b(?:curl|wget|http|https|invoke-webrequest|invoke-restmethod|iwr|irm)\b[\s\S]*(?:data\.go\.kr|www\.gov\.kr|gov\.kr|hometax\.go\.kr|wetax\.go\.kr|openbanking|kftc|mobileid|omnidid|omni[-_ ]?one)/iu,
15
+ reason:
16
+ 'Shell command appears to call Korean public-service, identity, payment, or government infrastructure',
17
+ },
18
+ {
19
+ pattern:
20
+ /\b(?:hometax|government24|gov24|wetax|openbanking|kftc|mobile[-_ ]?id|certificate|public[-_ ]?certificate|identity|payment|pipa|정부24|홈택스|위택스|모바일신분증|공동인증서|금융인증서)\b/iu,
21
+ reason:
22
+ 'Shell command references protected national AX, identity, certificate, or payment surfaces',
23
+ },
24
+ {
25
+ pattern:
26
+ /\bUMMAYA_[A-Z0-9_]*(?:TOKEN|SECRET|PASSWORD|CERT|CERTIFICATE|API_KEY|AUTH_KEY|SERVICE_KEY)\b/u,
27
+ reason:
28
+ 'Shell command references UMMAYA credential material for protected infrastructure access',
29
+ },
30
+ ]
31
+
32
+ function shouldTreatModeAsBypass(toolPermissionContext: ToolPermissionContext): boolean {
33
+ return (
34
+ toolPermissionContext.mode === 'bypassPermissions' ||
35
+ (toolPermissionContext.mode === 'plan' &&
36
+ toolPermissionContext.isBypassPermissionsModeAvailable)
37
+ )
38
+ }
39
+
40
+ export function classifyShellRiskForPermissionGauntlet(
41
+ command: string,
42
+ getDestructiveWarning: DestructiveWarningFn,
43
+ ): ShellRiskClass | null {
44
+ const destructiveWarning = getDestructiveWarning(command)
45
+ if (destructiveWarning !== null) {
46
+ return {
47
+ kind: 'destructive',
48
+ reason: destructiveWarning,
49
+ }
50
+ }
51
+
52
+ for (const { pattern, reason } of PROTECTED_AX_PATTERNS) {
53
+ if (pattern.test(command)) {
54
+ return {
55
+ kind: 'protected-ax',
56
+ reason,
57
+ }
58
+ }
59
+ }
60
+
61
+ return null
62
+ }
63
+
64
+ export function getBypassImmuneShellPermissionResult(
65
+ command: string,
66
+ toolName: string,
67
+ toolPermissionContext: ToolPermissionContext,
68
+ getDestructiveWarning: DestructiveWarningFn,
69
+ ): PermissionResult | null {
70
+ if (!shouldTreatModeAsBypass(toolPermissionContext)) {
71
+ return null
72
+ }
73
+
74
+ const risk = classifyShellRiskForPermissionGauntlet(
75
+ command,
76
+ getDestructiveWarning,
77
+ )
78
+ if (risk === null) {
79
+ return null
80
+ }
81
+
82
+ const reason =
83
+ risk.kind === 'destructive'
84
+ ? `Destructive shell command requires explicit approval even in bypassPermissions mode: ${risk.reason}`
85
+ : `Protected AX-adjacent shell command requires explicit approval even in bypassPermissions mode: ${risk.reason}`
86
+
87
+ return {
88
+ behavior: 'ask',
89
+ message: `${toolName} command requires explicit approval. ${reason}`,
90
+ decisionReason: {
91
+ type: 'safetyCheck',
92
+ reason,
93
+ classifierApprovable: false,
94
+ },
95
+ suggestions: [],
96
+ }
97
+ }
@@ -0,0 +1,37 @@
1
+ import { createRequire } from 'node:module'
2
+
3
+ type BashUIRuntime = Pick<
4
+ typeof import('./UI.js'),
5
+ | 'BackgroundHint'
6
+ | 'renderToolResultMessage'
7
+ | 'renderToolUseErrorMessage'
8
+ | 'renderToolUseMessage'
9
+ | 'renderToolUseProgressMessage'
10
+ | 'renderToolUseQueuedMessage'
11
+ >
12
+
13
+ const requireModule = createRequire(import.meta.url)
14
+ let cachedBashUI: BashUIRuntime | undefined
15
+
16
+ function isBashUIRuntime(value: unknown): value is BashUIRuntime {
17
+ if (typeof value !== 'object' || value === null) return false
18
+ const module = value as Partial<Record<keyof BashUIRuntime, unknown>>
19
+ return (
20
+ typeof module.BackgroundHint === 'function' &&
21
+ typeof module.renderToolResultMessage === 'function' &&
22
+ typeof module.renderToolUseErrorMessage === 'function' &&
23
+ typeof module.renderToolUseMessage === 'function' &&
24
+ typeof module.renderToolUseProgressMessage === 'function' &&
25
+ typeof module.renderToolUseQueuedMessage === 'function'
26
+ )
27
+ }
28
+
29
+ export function loadBashUI(): BashUIRuntime {
30
+ if (cachedBashUI !== undefined) return cachedBashUI
31
+ const loaded: unknown = requireModule('./UI.js')
32
+ if (!isBashUIRuntime(loaded)) {
33
+ throw new Error('Bash UI module did not expose the expected renderers')
34
+ }
35
+ cachedBashUI = loaded
36
+ return loaded
37
+ }
@@ -7,7 +7,7 @@
7
7
  * returned file_uuid alongside the path. Web resolves file_uuid → preview;
8
8
  * desktop/local try path first.
9
9
  *
10
- * Best-effort: any failure (no token, bridge off, network error, 4xx) logs
10
+ * Best-effort: each failure (no token, bridge off, network error, 4xx) logs
11
11
  * debug and returns undefined. The attachment still carries {path, size,
12
12
  * isImage}, so local-terminal and same-machine-desktop render unaffected.
13
13
  */
@@ -2,11 +2,11 @@
2
2
  * Restricted-grammar expression parser + evaluator using the shunting-yard algorithm.
3
3
  *
4
4
  * Allowed characters: 0-9 . + - * / % ( ) whitespace
5
- * Disallowed: any letter, underscore, $, !, ^, &, |, ~, <, >, =, etc.
5
+ * Disallowed: letters, underscore, $, !, ^, &, |, ~, <, >, =, etc.
6
6
  *
7
7
  * Numeric representation strategy:
8
8
  * - Parse every numeric literal as a string to avoid IEEE-754 precision loss.
9
- * - Track whether any division produces a non-integer result.
9
+ * - Track whether division produces a non-integer result.
10
10
  * - Arithmetic is carried out with BigInt when all operands are integers
11
11
  * (denominator check for /); otherwise falls back to JS number with
12
12
  * toFixed(precision) rounding, which is sufficient for the "up to 28 digits"
@@ -0,0 +1,262 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // UMMAYA-original — DocumentPrimitive.
3
+
4
+ import React from 'react'
5
+ import { z } from 'zod/v4'
6
+ import { Text } from '../../ink.js'
7
+ import { buildTool, type ToolDef } from '../../Tool.js'
8
+ import { lazySchema } from '../../utils/lazySchema.js'
9
+ import { getOrCreateUmmayaBridge } from '../../ipc/bridgeSingleton.js'
10
+ import { getOrCreatePendingCallRegistry } from '../../ipc/pendingCallSingleton.js'
11
+ import { dispatchPrimitive } from '../_shared/dispatchPrimitive.js'
12
+ import {
13
+ applyDocumentVisualRenderGateToOutput,
14
+ isDocumentVisualRenderFailedOutput,
15
+ renderDocumentToolResultIfPresent,
16
+ } from '../_shared/documentToolResultRender.js'
17
+ import {
18
+ renderVerboseInputJson,
19
+ renderVerboseOutputJson,
20
+ } from '../_shared/verboseRender.js'
21
+ import {
22
+ isPrimitiveResultPreviewTruncated,
23
+ renderCompactPrimitiveResult,
24
+ } from '../_shared/compactPrimitiveResult.js'
25
+ import { resolveDocumentPrimitiveTimeoutMs } from '../_shared/documentPrimitiveTimeout.js'
26
+ import {
27
+ DOCUMENT_TOOL_NAME,
28
+ DESCRIPTION,
29
+ DOCUMENT_TOOL_PROMPT,
30
+ } from './prompt.js'
31
+ import {
32
+ latestUserTextFromContext,
33
+ normalizeDocumentPrimitiveInputForDispatch as normalizeDispatchInput,
34
+ operationOf,
35
+ } from './dispatchNormalization.js'
36
+ import { modelVisibleDocumentOutput } from './modelVisibleOutput.js'
37
+
38
+ export { normalizeDocumentPrimitiveInputForDispatch } from './dispatchNormalization.js'
39
+
40
+ const documentRefSchema = z
41
+ .object({
42
+ path: z.string().min(1).optional(),
43
+ artifact_id: z.string().min(1).optional(),
44
+ expected_format: z
45
+ .enum(['hwpx', 'hwp', 'docx', 'pdf', 'xlsx', 'pptx'])
46
+ .optional(),
47
+ })
48
+ .passthrough()
49
+
50
+ const inputSchema = lazySchema(() =>
51
+ z
52
+ .object({
53
+ correlation_id: z.string().min(1),
54
+ document: documentRefSchema,
55
+ operation: z
56
+ .enum(['inspect', 'extract', 'fill', 'style', 'validate', 'save'])
57
+ .optional(),
58
+ instruction: z.string().min(1),
59
+ destination_path: z.string().min(1).optional(),
60
+ destination_display_name: z.string().min(1).optional(),
61
+ template_id: z.string().min(1).optional(),
62
+ patches: z.array(z.unknown()).optional(),
63
+ styles: z.array(z.unknown()).optional(),
64
+ })
65
+ .passthrough(),
66
+ )
67
+ type InputSchema = ReturnType<typeof inputSchema>
68
+ export type Input = z.infer<InputSchema>
69
+
70
+ const outputSchema = lazySchema(() =>
71
+ z.discriminatedUnion('ok', [
72
+ z.object({
73
+ ok: z.literal(true),
74
+ result: z.unknown(),
75
+ outbound_traces: z.array(z.unknown()).optional(),
76
+ }),
77
+ z.object({
78
+ ok: z.literal(false),
79
+ error: z.object({
80
+ kind: z.string(),
81
+ message: z.string(),
82
+ }),
83
+ result: z.unknown().optional(),
84
+ outbound_traces: z.array(z.unknown()).optional(),
85
+ }),
86
+ ]),
87
+ )
88
+ type OutputSchema = ReturnType<typeof outputSchema>
89
+ export type Output = z.infer<OutputSchema>
90
+
91
+ function documentTarget(input: Input): string {
92
+ const document = input.document as Record<string, unknown>
93
+ const path = typeof document.path === 'string' ? document.path : undefined
94
+ const artifactId =
95
+ typeof document.artifact_id === 'string' ? document.artifact_id : undefined
96
+ return path ?? artifactId ?? 'document'
97
+ }
98
+
99
+ function documentAction(input: Input): string {
100
+ switch (operationOf(input)) {
101
+ case 'inspect':
102
+ return 'Inspect document'
103
+ case 'extract':
104
+ return 'Read document'
105
+ case 'style':
106
+ return 'Apply document formatting'
107
+ case 'validate':
108
+ return 'Validate public-form rules'
109
+ case 'save':
110
+ return 'Save document'
111
+ case 'fill':
112
+ default:
113
+ return 'Write document'
114
+ }
115
+ }
116
+
117
+ function buildDocumentErrorRows(output: Extract<Output, { ok: false }>): React.ReactNode[] {
118
+ return [
119
+ React.createElement(
120
+ Text,
121
+ { key: 'document-error', color: 'red' },
122
+ `Document failed: ${output.error.message}`,
123
+ ),
124
+ ]
125
+ }
126
+
127
+ export const DocumentPrimitive = buildTool({
128
+ name: DOCUMENT_TOOL_NAME,
129
+
130
+ searchHint:
131
+ 'document hwpx hwp docx pdf xlsx pptx form fill render save diff public document',
132
+
133
+ maxResultSizeChars: 100_000,
134
+
135
+ get inputSchema(): InputSchema {
136
+ return inputSchema()
137
+ },
138
+
139
+ get outputSchema(): OutputSchema {
140
+ return outputSchema()
141
+ },
142
+
143
+ isEnabled() {
144
+ return true
145
+ },
146
+
147
+ isConcurrencySafe() {
148
+ return false
149
+ },
150
+
151
+ isReadOnly(input?: Input) {
152
+ const operation = input ? operationOf(input) : 'fill'
153
+ return operation === 'inspect' || operation === 'extract' || operation === 'validate'
154
+ },
155
+
156
+ isDestructive() {
157
+ return false
158
+ },
159
+
160
+ async description() {
161
+ return DESCRIPTION
162
+ },
163
+
164
+ async prompt() {
165
+ return DOCUMENT_TOOL_PROMPT
166
+ },
167
+
168
+ mapToolResultToToolResultBlockParam(output, toolUseID) {
169
+ const gatedOutput = applyDocumentVisualRenderGateToOutput(output)
170
+ return {
171
+ tool_use_id: toolUseID,
172
+ type: 'tool_result',
173
+ content: JSON.stringify(modelVisibleDocumentOutput(gatedOutput)),
174
+ ...(isDocumentVisualRenderFailedOutput(gatedOutput) ? { is_error: true } : {}),
175
+ }
176
+ },
177
+
178
+ renderToolUseMessage(input: Input, options: { verbose: boolean }) {
179
+ if (options.verbose) return renderVerboseInputJson(input)
180
+ return `${documentAction(input)}: ${documentTarget(input)}`
181
+ },
182
+
183
+ isMcp: false,
184
+
185
+ async validateInput(input: Input, _context: ToolUseContext) {
186
+ if (typeof input !== 'object' || input === null) {
187
+ return {
188
+ result: false as const,
189
+ message: 'document expects a JSON object argument.',
190
+ errorCode: 1,
191
+ }
192
+ }
193
+ const document = input.document as Record<string, unknown> | undefined
194
+ if (!document || typeof document !== 'object') {
195
+ return {
196
+ result: false as const,
197
+ message: 'document.document is required.',
198
+ errorCode: 1,
199
+ }
200
+ }
201
+ if (
202
+ typeof document.path !== 'string' &&
203
+ typeof document.artifact_id !== 'string'
204
+ ) {
205
+ return {
206
+ result: false as const,
207
+ message: 'document requires either document.path or document.artifact_id.',
208
+ errorCode: 1,
209
+ }
210
+ }
211
+ if (typeof input.instruction !== 'string' || input.instruction.trim() === '') {
212
+ return {
213
+ result: false as const,
214
+ message: 'document.instruction is required.',
215
+ errorCode: 1,
216
+ }
217
+ }
218
+ return { result: true as const }
219
+ },
220
+
221
+ renderToolResultMessage(
222
+ output: Output,
223
+ _progress: unknown,
224
+ options: { verbose: boolean; isTranscriptMode?: boolean } = { verbose: false },
225
+ ) {
226
+ const gatedOutput = applyDocumentVisualRenderGateToOutput(output) as Output
227
+ const documentResult = renderDocumentToolResultIfPresent(gatedOutput, options)
228
+ if (documentResult !== null) return documentResult
229
+ if (options.verbose || options.isTranscriptMode) {
230
+ return renderVerboseOutputJson(gatedOutput)
231
+ }
232
+ return renderCompactPrimitiveResult(
233
+ gatedOutput.ok
234
+ ? [React.createElement(Text, { key: 'document-ok' }, 'Document result received.')]
235
+ : buildDocumentErrorRows(gatedOutput),
236
+ )
237
+ },
238
+
239
+ isResultTruncated(output: Output): boolean {
240
+ if (output.ok) return false
241
+ return isPrimitiveResultPreviewTruncated(buildDocumentErrorRows(output))
242
+ },
243
+
244
+ async call(input, context) {
245
+ const args = normalizeDispatchInput(
246
+ input as Input,
247
+ latestUserTextFromContext(context),
248
+ )
249
+ const result = await dispatchPrimitive<Output>({
250
+ primitive: 'document',
251
+ args,
252
+ context,
253
+ registry: getOrCreatePendingCallRegistry(),
254
+ bridge: getOrCreateUmmayaBridge(),
255
+ timeoutMs: resolveDocumentPrimitiveTimeoutMs(),
256
+ })
257
+ return {
258
+ ...result,
259
+ data: applyDocumentVisualRenderGateToOutput(result.data) as Output,
260
+ }
261
+ },
262
+ } satisfies ToolDef<InputSchema, Output>)
@@ -0,0 +1,270 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+
3
+ import type { ToolUseContext } from '../../Tool.js'
4
+ import { lastLocalDocumentPath } from './documentDestinationPath.js'
5
+ import { normalizeDocumentMutationPayloadsForDispatch } from './documentPatchNormalization.js'
6
+
7
+ const WRITE_INTENT_RE =
8
+ /(작성|수정|편집|채우|채워|입력|변경|저장|보정|서식|글꼴|글자색|배경색|정렬|굵게|write|edit|fill|apply|save|style|format|bold)/iu
9
+ const READ_ONLY_INTENT_RE =
10
+ /(읽기\s*전용|수정\s*없이|변경\s*없이|저장\s*없이|열람만|확인만|추출|파악|쓰지\s*마|작성하지\s*마|반영하지\s*마|저장하지\s*마|inspect|extract|read\s*only)/iu
11
+ const DEFERRED_WRITE_INTENT_RE =
12
+ /((아직|먼저|초안).{0,40}(쓰지\s*마|작성하지\s*마|저장하지\s*마|반영하지\s*마))|((쓰지\s*마|작성하지\s*마|저장하지\s*마|반영하지\s*마).{0,40}(아직|먼저|초안))/iu
13
+ const APPROVED_DERIVATIVE_SAVE_RE =
14
+ /((승인|approved).{0,100}(저장|복사본|derivative|\/[^\s]+))|((저장|복사본|derivative|\/[^\s]+).{0,100}(승인|approved))/iu
15
+ const QUESTION_FIRST_AUTHORING_RE =
16
+ /(근거|질문|먼저\s*물|먼저\s*질문|초안|승인|evidence|question|draft|approval)/iu
17
+ const STRUCTURE_INSPECTION_RE =
18
+ /(구조|빈칸|문항|양식|필드|항목).*(확인|파악|검토)|(?:확인|파악|검토).*(구조|빈칸|문항|양식|필드|항목)/iu
19
+ const INTERNAL_DISPATCH_KEYS = new Set(['__ummaya_display_operation'])
20
+ const READ_ONLY_OPERATIONS = new Set(['inspect', 'extract', 'validate'])
21
+ const READ_ONLY_MUTATION_KEYS = new Set([
22
+ 'destination_path',
23
+ 'destination_display_name',
24
+ 'patches',
25
+ 'styles',
26
+ 'approved_draft_id',
27
+ 'approved_draft_sha256',
28
+ ])
29
+
30
+ export type DocumentPrimitiveDispatchInput = {
31
+ readonly document?: unknown
32
+ readonly operation?: string
33
+ readonly instruction?: string
34
+ readonly destination_path?: string
35
+ readonly patches?: readonly unknown[]
36
+ readonly styles?: readonly unknown[]
37
+ readonly [key: string]: unknown
38
+ }
39
+
40
+ export function normalizeDocumentPrimitiveInputForDispatch(
41
+ input: DocumentPrimitiveDispatchInput,
42
+ userText: string | undefined,
43
+ ): Record<string, unknown> {
44
+ const operation = operationOf(input, userText)
45
+ const text = `${input.instruction ?? ''}\n${userText ?? ''}`
46
+ const destinationPath =
47
+ typeof input.destination_path === 'string' ||
48
+ READ_ONLY_OPERATIONS.has(operation) ||
49
+ !hasApprovedDerivativeSaveIntent(input, text)
50
+ ? undefined
51
+ : lastLocalDocumentPath(text)
52
+ const args = normalizeDocumentLocatorForDispatch(
53
+ normalizeDocumentMutationPayloadsForDispatch(
54
+ stripDispatchOnlyFields({
55
+ ...input,
56
+ operation,
57
+ ...(destinationPath === undefined ? {} : { destination_path: destinationPath }),
58
+ }),
59
+ userText,
60
+ ),
61
+ )
62
+ if (userText === undefined || hasPatchOrStylePayload(input)) {
63
+ return args
64
+ }
65
+
66
+ const instruction = typeof input.instruction === 'string'
67
+ ? input.instruction.trim()
68
+ : ''
69
+ if (instruction.includes(userText)) {
70
+ return args
71
+ }
72
+ return {
73
+ ...args,
74
+ instruction: instruction
75
+ ? `${instruction}\n\nOriginal user request:\n${userText}`
76
+ : userText,
77
+ }
78
+ }
79
+
80
+ export function operationOf(
81
+ input: DocumentPrimitiveDispatchInput,
82
+ userText?: string,
83
+ ): string {
84
+ const operation = typeof input.operation === 'string' ? input.operation : 'fill'
85
+ if (hasReadOnlyIntentFromText(input, userText)) {
86
+ return operation === 'extract' ? 'extract' : 'inspect'
87
+ }
88
+ if (shouldPreserveQuestionFirstRead(input, userText, operation)) {
89
+ return operation
90
+ }
91
+ const displayOperation =
92
+ typeof input.__ummaya_display_operation === 'string'
93
+ ? input.__ummaya_display_operation
94
+ : undefined
95
+ if (
96
+ displayOperation === 'fill' ||
97
+ displayOperation === 'style' ||
98
+ displayOperation === 'save'
99
+ ) {
100
+ return displayOperation
101
+ }
102
+ if (
103
+ (operation === 'inspect' || operation === 'extract') &&
104
+ hasWriteIntentFromText(input, userText)
105
+ ) {
106
+ return 'fill'
107
+ }
108
+ return operation
109
+ }
110
+
111
+ export function latestUserTextFromContext(context: ToolUseContext): string | undefined {
112
+ const messages = contextRecord(context).messages
113
+ if (!Array.isArray(messages)) return undefined
114
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
115
+ const message = recordFrom(messages[index])
116
+ if (message === null) continue
117
+ const sdkMessage = recordFrom(message.message)
118
+ if (!isUserMessageRecord(message, sdkMessage)) continue
119
+ const content = sdkMessage?.content ?? message.content
120
+ const text = textFromMessageContent(content)
121
+ if (text !== undefined) return text
122
+ }
123
+ return undefined
124
+ }
125
+
126
+ function normalizeDocumentLocatorForDispatch(
127
+ args: Record<string, unknown>,
128
+ ): Record<string, unknown> {
129
+ const document = recordFrom(args.document)
130
+ if (document === null) {
131
+ return args
132
+ }
133
+ if (
134
+ nonEmptyString(document.artifact_id) === undefined ||
135
+ nonEmptyString(document.path) === undefined
136
+ ) {
137
+ return args
138
+ }
139
+ const normalizedDocument: Record<string, unknown> = {}
140
+ for (const [key, value] of Object.entries(document)) {
141
+ if (key !== 'path') {
142
+ normalizedDocument[key] = value
143
+ }
144
+ }
145
+ return {
146
+ ...args,
147
+ document: normalizedDocument,
148
+ }
149
+ }
150
+
151
+ function stripDispatchOnlyFields(args: Record<string, unknown>): Record<string, unknown> {
152
+ const operation = typeof args.operation === 'string' ? args.operation : 'fill'
153
+ const readOnlyOperation = READ_ONLY_OPERATIONS.has(operation)
154
+ const cleaned: Record<string, unknown> = {}
155
+ for (const [key, value] of Object.entries(args)) {
156
+ if (INTERNAL_DISPATCH_KEYS.has(key)) continue
157
+ if (readOnlyOperation && READ_ONLY_MUTATION_KEYS.has(key)) continue
158
+ cleaned[key] = value
159
+ }
160
+ return cleaned
161
+ }
162
+
163
+ function shouldPreserveQuestionFirstRead(
164
+ input: DocumentPrimitiveDispatchInput,
165
+ userText: string | undefined,
166
+ operation: string,
167
+ ): boolean {
168
+ if (operation !== 'inspect' && operation !== 'extract') {
169
+ return false
170
+ }
171
+ if (hasPatchOrStylePayload(input)) {
172
+ return false
173
+ }
174
+ const text = `${input.instruction ?? ''}\n${userText ?? ''}`
175
+ if (hasApprovedDerivativeSaveIntent(input, text)) {
176
+ return false
177
+ }
178
+ if (operation === 'inspect' && STRUCTURE_INSPECTION_RE.test(input.instruction ?? '')) {
179
+ return true
180
+ }
181
+ return QUESTION_FIRST_AUTHORING_RE.test(text) && WRITE_INTENT_RE.test(text)
182
+ }
183
+
184
+ function hasWriteIntentFromText(
185
+ input: DocumentPrimitiveDispatchInput,
186
+ userText: string | undefined,
187
+ ): boolean {
188
+ if (typeof input.destination_path === 'string') return true
189
+ if (hasPatchOrStylePayload(input)) return true
190
+ if (userText !== undefined) {
191
+ return !READ_ONLY_INTENT_RE.test(userText) && WRITE_INTENT_RE.test(userText)
192
+ }
193
+ if (READ_ONLY_INTENT_RE.test(input.instruction ?? '')) return false
194
+ return WRITE_INTENT_RE.test(input.instruction ?? '')
195
+ }
196
+
197
+ function hasReadOnlyIntentFromText(
198
+ input: DocumentPrimitiveDispatchInput,
199
+ userText: string | undefined,
200
+ ): boolean {
201
+ const text = userText ?? input.instruction ?? ''
202
+ if (!READ_ONLY_INTENT_RE.test(text)) {
203
+ return false
204
+ }
205
+ if (hasApprovedDerivativeSaveIntent(input, text)) {
206
+ return false
207
+ }
208
+ return true
209
+ }
210
+
211
+ function hasPatchOrStylePayload(input: DocumentPrimitiveDispatchInput): boolean {
212
+ return (Array.isArray(input.patches) && input.patches.length > 0) ||
213
+ (Array.isArray(input.styles) && input.styles.length > 0)
214
+ }
215
+
216
+ function hasApprovedDerivativeSaveIntent(
217
+ input: DocumentPrimitiveDispatchInput,
218
+ text: string,
219
+ ): boolean {
220
+ if (DEFERRED_WRITE_INTENT_RE.test(text)) {
221
+ return false
222
+ }
223
+ if (APPROVED_DERIVATIVE_SAVE_RE.test(text)) {
224
+ return true
225
+ }
226
+ return typeof input.destination_path === 'string' &&
227
+ /(승인|approved|검토용\s*복사본|원본은\s*건드리지\s*말)/iu.test(text) &&
228
+ /(저장|save|\/[^\s]+)/iu.test(text)
229
+ }
230
+
231
+ function textFromMessageContent(content: unknown): string | undefined {
232
+ if (typeof content === 'string' && content.trim() !== '') {
233
+ return content
234
+ }
235
+ if (!Array.isArray(content)) {
236
+ return undefined
237
+ }
238
+ const text = content
239
+ .map(block => {
240
+ const item = recordFrom(block)
241
+ return item?.type === 'text' && typeof item.text === 'string'
242
+ ? item.text
243
+ : ''
244
+ })
245
+ .filter(Boolean)
246
+ .join('\n')
247
+ .trim()
248
+ return text === '' ? undefined : text
249
+ }
250
+
251
+ function isUserMessageRecord(
252
+ message: Record<string, unknown>,
253
+ sdkMessage: Record<string, unknown> | null,
254
+ ): boolean {
255
+ return message.type === 'user' || message.role === 'user' || sdkMessage?.role === 'user'
256
+ }
257
+
258
+ function contextRecord(context: ToolUseContext): Record<string, unknown> {
259
+ return context
260
+ }
261
+
262
+ function recordFrom(value: unknown): Record<string, unknown> | null {
263
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
264
+ ? Object.fromEntries(Object.entries(value))
265
+ : null
266
+ }
267
+
268
+ function nonEmptyString(value: unknown): string | undefined {
269
+ return typeof value === 'string' && value.trim() !== '' ? value : undefined
270
+ }