ummaya 0.2.4 → 0.2.6

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 (482) hide show
  1. package/README.md +15 -2
  2. package/bin/ummaya +10 -1
  3. package/bun.lock +180 -244
  4. package/npm-shrinkwrap.json +760 -1760
  5. package/package.json +39 -22
  6. package/prompts/manifest.yaml +1 -1
  7. package/prompts/system_v1.md +1 -0
  8. package/pyproject.toml +27 -2
  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/_canonical/baselines.yaml +113 -0
  12. package/src/ummaya/engine/engine.py +29 -132
  13. package/src/ummaya/evidence/__init__.py +21 -2
  14. package/src/ummaya/evidence/dataset_contract.py +193 -0
  15. package/src/ummaya/evidence/document_authoring_cases.py +33 -0
  16. package/src/ummaya/evidence/document_harness.py +313 -0
  17. package/src/ummaya/evidence/document_viewer_ux.py +391 -0
  18. package/src/ummaya/evidence/gates.py +70 -0
  19. package/src/ummaya/evidence/json_types.py +20 -0
  20. package/src/ummaya/evidence/models.py +88 -1
  21. package/src/ummaya/evidence/output_payload.py +89 -0
  22. package/src/ummaya/evidence/payload_documents.py +233 -0
  23. package/src/ummaya/evidence/route_contracts.py +224 -0
  24. package/src/ummaya/evidence/route_helpers.py +150 -0
  25. package/src/ummaya/evidence/runner.py +81 -212
  26. package/src/ummaya/evidence/source_provenance.py +246 -0
  27. package/src/ummaya/evidence/source_provenance_redaction.py +176 -0
  28. package/src/ummaya/evidence/tool_layer.py +39 -0
  29. package/src/ummaya/evidence/tool_layer_models.py +151 -0
  30. package/src/ummaya/ipc/adapter_manifest_emitter.py +26 -10
  31. package/src/ummaya/ipc/document_intent_normalization.py +185 -0
  32. package/src/ummaya/ipc/frame_schema.py +5 -5
  33. package/src/ummaya/ipc/route_diagnostics.py +73 -0
  34. package/src/ummaya/ipc/stdio.py +1109 -477
  35. package/src/ummaya/llm/client.py +102 -3
  36. package/src/ummaya/llm/config.py +8 -3
  37. package/src/ummaya/primitives/__init__.py +6 -2
  38. package/src/ummaya/primitives/delegation.py +1 -1
  39. package/src/ummaya/primitives/document.py +28 -0
  40. package/src/ummaya/settings.py +0 -3
  41. package/src/ummaya/tools/discovery_bridge.py +17 -1
  42. package/src/ummaya/tools/documents/__init__.py +297 -0
  43. package/src/ummaya/tools/documents/adapter_registry.py +487 -0
  44. package/src/ummaya/tools/documents/archive_container_probe.py +167 -0
  45. package/src/ummaya/tools/documents/artifact_store.py +454 -0
  46. package/src/ummaya/tools/documents/authoring.py +283 -0
  47. package/src/ummaya/tools/documents/baselines.py +132 -0
  48. package/src/ummaya/tools/documents/capability.py +331 -0
  49. package/src/ummaya/tools/documents/contracts.py +112 -0
  50. package/src/ummaya/tools/documents/conversion.py +521 -0
  51. package/src/ummaya/tools/documents/diff.py +275 -0
  52. package/src/ummaya/tools/documents/engines.py +163 -0
  53. package/src/ummaya/tools/documents/evaluation.py +291 -0
  54. package/src/ummaya/tools/documents/explicit_values.py +108 -0
  55. package/src/ummaya/tools/documents/fixtures.py +174 -0
  56. package/src/ummaya/tools/documents/format_completion_audit.py +471 -0
  57. package/src/ummaya/tools/documents/formats/__init__.py +2 -0
  58. package/src/ummaya/tools/documents/formats/archive.py +528 -0
  59. package/src/ummaya/tools/documents/formats/base.py +41 -0
  60. package/src/ummaya/tools/documents/formats/code_file.py +211 -0
  61. package/src/ummaya/tools/documents/formats/data_file.py +272 -0
  62. package/src/ummaya/tools/documents/formats/hwp.py +284 -0
  63. package/src/ummaya/tools/documents/formats/hwpx.py +1837 -0
  64. package/src/ummaya/tools/documents/formats/odf.py +435 -0
  65. package/src/ummaya/tools/documents/formats/ooxml.py +1030 -0
  66. package/src/ummaya/tools/documents/formats/passive.py +766 -0
  67. package/src/ummaya/tools/documents/formats/pdf.py +702 -0
  68. package/src/ummaya/tools/documents/formats/text_web.py +268 -0
  69. package/src/ummaya/tools/documents/hwp_conversion_probe.py +178 -0
  70. package/src/ummaya/tools/documents/hwp_direct_candidate.py +141 -0
  71. package/src/ummaya/tools/documents/inspection.py +289 -0
  72. package/src/ummaya/tools/documents/intake.py +1079 -0
  73. package/src/ummaya/tools/documents/legacy_office_promotion_probe.py +366 -0
  74. package/src/ummaya/tools/documents/models.py +1598 -0
  75. package/src/ummaya/tools/documents/odf_promotion_probe.py +167 -0
  76. package/src/ummaya/tools/documents/orchestrator.py +96 -0
  77. package/src/ummaya/tools/documents/passive_capability_probe.py +251 -0
  78. package/src/ummaya/tools/documents/patch.py +170 -0
  79. package/src/ummaya/tools/documents/pdfa_conformance.py +284 -0
  80. package/src/ummaya/tools/documents/pdfa_promotion_probe.py +198 -0
  81. package/src/ummaya/tools/documents/permissions.py +110 -0
  82. package/src/ummaya/tools/documents/planner.py +616 -0
  83. package/src/ummaya/tools/documents/registry.py +2733 -0
  84. package/src/ummaya/tools/documents/render.py +978 -0
  85. package/src/ummaya/tools/documents/render_comparison.py +113 -0
  86. package/src/ummaya/tools/documents/render_comparison_models.py +74 -0
  87. package/src/ummaya/tools/documents/render_comparison_regions.py +73 -0
  88. package/src/ummaya/tools/documents/render_comparison_style.py +161 -0
  89. package/src/ummaya/tools/documents/reread.py +157 -0
  90. package/src/ummaya/tools/documents/runtime_authoring.py +244 -0
  91. package/src/ummaya/tools/documents/runtime_authoring_bundle.py +76 -0
  92. package/src/ummaya/tools/documents/scorecard.py +184 -0
  93. package/src/ummaya/tools/documents/socratic_planner.py +193 -0
  94. package/src/ummaya/tools/documents/style.py +48 -0
  95. package/src/ummaya/tools/documents/tool_defs.py +523 -0
  96. package/src/ummaya/tools/documents/validate.py +347 -0
  97. package/src/ummaya/tools/executor.py +29 -0
  98. package/src/ummaya/tools/live_proxy.py +0 -3
  99. package/src/ummaya/tools/models.py +5 -1
  100. package/src/ummaya/tools/register_all.py +8 -0
  101. package/src/ummaya/tools/registry.py +10 -1
  102. package/src/ummaya/tools/routing/__init__.py +59 -0
  103. package/src/ummaya/tools/routing/builder.py +105 -0
  104. package/src/ummaya/tools/routing/cards.py +29 -0
  105. package/src/ummaya/tools/routing/decision_service.py +534 -0
  106. package/src/ummaya/tools/routing/decision_types.py +74 -0
  107. package/src/ummaya/tools/routing/feasibility.py +122 -0
  108. package/src/ummaya/tools/routing/intent.py +17 -0
  109. package/src/ummaya/tools/routing/intent_extractor.py +207 -0
  110. package/src/ummaya/tools/routing/intent_patterns.py +160 -0
  111. package/src/ummaya/tools/routing/intent_public_data.py +150 -0
  112. package/src/ummaya/tools/routing/intent_types.py +48 -0
  113. package/src/ummaya/tools/routing/lint.py +78 -0
  114. package/src/ummaya/tools/routing/metadata.py +174 -0
  115. package/src/ummaya/tools/routing/projection.py +340 -0
  116. package/src/ummaya/tools/routing/retrieval_policy.py +629 -0
  117. package/src/ummaya/tools/routing/schema.py +81 -0
  118. package/src/ummaya/tools/routing/types.py +96 -0
  119. package/src/ummaya/tools/routing_index.py +2 -2
  120. package/src/ummaya/tools/search.py +34 -746
  121. package/tests/fixtures/documents/public_forms/baselines.yaml +113 -0
  122. package/tui/bun.lock +126 -305
  123. package/tui/package.json +35 -22
  124. package/tui/src/.cc-byte-identical-whitelist.yaml +266 -0
  125. package/tui/src/QueryEngine.ts +12 -8
  126. package/tui/src/bridge/inboundAttachments.ts +3 -3
  127. package/tui/src/cli/handlers/auth.ts +3 -12
  128. package/tui/src/cli/handlers/mcp.tsx +0 -1
  129. package/tui/src/cli/print.ts +8 -9
  130. package/tui/src/commands/insights.ts +1 -1
  131. package/tui/src/commands/install-github-app/types.ts +8 -30
  132. package/tui/src/commands/plugin/types.ts +6 -28
  133. package/tui/src/commands/plugin/unifiedTypes.ts +4 -26
  134. package/tui/src/commands/rename/generateSessionName.ts +1 -1
  135. package/tui/src/components/Feedback.tsx +1 -1
  136. package/tui/src/components/LogoV2/EmergencyTip.tsx +11 -2
  137. package/tui/src/components/LogoV2/WelcomeV2.tsx +1 -3
  138. package/tui/src/components/ScrollKeybindingHandler.tsx +6 -6
  139. package/tui/src/components/Spinner/types.ts +6 -28
  140. package/tui/src/components/agents/generateAgent.ts +1 -1
  141. package/tui/src/components/agents/new-agent-creation/types.ts +4 -26
  142. package/tui/src/components/config/EnvSecretIsolatedEditor.tsx +1 -1
  143. package/tui/src/components/mcp/types.ts +16 -38
  144. package/tui/src/components/messages/AssistantToolUseMessage.tsx +3 -2
  145. package/tui/src/components/messages/UserCrossSessionMessage.ts +16 -4
  146. package/tui/src/components/messages/UserForkBoilerplateMessage.ts +16 -4
  147. package/tui/src/components/messages/UserGitHubWebhookMessage.ts +16 -4
  148. package/tui/src/components/messages/UserToolResultMessage/utils.tsx +3 -2
  149. package/tui/src/components/permissions/MonitorPermissionRequest/MonitorPermissionRequest.ts +9 -4
  150. package/tui/src/components/permissions/ReviewArtifactPermissionRequest/ReviewArtifactPermissionRequest.ts +9 -4
  151. package/tui/src/components/primitive/DocumentSocraticReviewBlock.tsx +129 -0
  152. package/tui/src/components/primitive/DocumentToolResultCard.tsx +224 -0
  153. package/tui/src/components/primitive/documentSocraticReview.ts +215 -0
  154. package/tui/src/components/primitive/index.tsx +43 -1
  155. package/tui/src/components/primitive/types.ts +137 -0
  156. package/tui/src/components/ui/option.ts +4 -26
  157. package/tui/src/constants/common.ts +0 -2
  158. package/tui/src/constants/prompts.ts +4 -3
  159. package/tui/src/constants/querySource.ts +4 -26
  160. package/tui/src/entrypoints/sdk/controlTypes.ts +26 -48
  161. package/tui/src/entrypoints/sdk/coreTypes.generated.ts +3 -25
  162. package/tui/src/entrypoints/sdk/runtimeTypes.ts +38 -60
  163. package/tui/src/entrypoints/sdk/sdkUtilityTypes.ts +4 -26
  164. package/tui/src/entrypoints/sdk/settingsTypes.generated.ts +3 -25
  165. package/tui/src/entrypoints/sdk/toolTypes.ts +3 -25
  166. package/tui/src/hooks/toolPermission/handlers/interactiveHandler.ts +10 -0
  167. package/tui/src/hooks/useApiKeyVerification.ts +1 -1
  168. package/tui/src/hooks/useVirtualScroll.ts +1 -1
  169. package/tui/src/ink/ink.tsx +33 -14
  170. package/tui/src/ink/reconciler.ts +2 -3
  171. package/tui/src/ink/render-to-screen.ts +30 -10
  172. package/tui/src/ipc/bridge.ts +62 -15
  173. package/tui/src/ipc/bridgeSingleton.ts +5 -1
  174. package/tui/src/ipc/codec.ts +3 -3
  175. package/tui/src/ipc/frames.generated.ts +12 -12
  176. package/tui/src/ipc/llmClient.ts +151 -27
  177. package/tui/src/ipc/schema/frame.schema.json +1 -1
  178. package/tui/src/keybindings/defaultBindings.ts +4 -0
  179. package/tui/src/main.tsx +32 -15
  180. package/tui/src/native-ts/file-index/index.ts +33 -3
  181. package/tui/src/observability/surface.ts +2 -2
  182. package/tui/src/probes/toolRegistryProbe.tsx +3 -1
  183. package/tui/src/projectOnboardingState.ts +7 -6
  184. package/tui/src/query/chatMessageTypes.ts +18 -0
  185. package/tui/src/query/chatMessagesBuilder.ts +1 -1
  186. package/tui/src/query/deps.ts +1 -1
  187. package/tui/src/query/messageGuards.ts +106 -0
  188. package/tui/src/query/publicDataTerminalRepair.ts +384 -0
  189. package/tui/src/query/run.ts +1075 -0
  190. package/tui/src/query/supportBoundary.ts +168 -0
  191. package/tui/src/query/toolResultErrors.ts +103 -0
  192. package/tui/src/query/toolRunner.ts +687 -0
  193. package/tui/src/query/unavailableToolRepair.ts +118 -0
  194. package/tui/src/query.ts +9 -2186
  195. package/tui/src/screens/REPL.tsx +40 -29
  196. package/tui/src/services/api/adapterManifest.ts +4 -0
  197. package/tui/src/services/api/backendChat/events.ts +117 -0
  198. package/tui/src/services/api/backendChat/finalMessage.ts +40 -0
  199. package/tui/src/services/api/backendChat/frame.ts +9 -0
  200. package/tui/src/services/api/backendChat/streaming.ts +430 -0
  201. package/tui/src/services/api/backendChat/types.ts +62 -0
  202. package/tui/src/services/api/backendChat.ts +1 -0
  203. package/tui/src/services/api/client.ts +65 -2
  204. package/tui/src/services/api/errorUtils.ts +5 -5
  205. package/tui/src/services/api/errors.ts +1 -1
  206. package/tui/src/services/api/logging.ts +1 -1
  207. package/tui/src/services/api/ummaya/evidence.ts +194 -0
  208. package/tui/src/services/api/ummaya/messages.ts +255 -0
  209. package/tui/src/services/api/ummaya/nonStreaming.ts +66 -0
  210. package/tui/src/services/api/ummaya/provider.ts +200 -0
  211. package/tui/src/services/api/ummaya/reasoning.ts +24 -0
  212. package/tui/src/services/api/ummaya/request.ts +200 -0
  213. package/tui/src/services/api/ummaya/selectionContext.ts +240 -0
  214. package/tui/src/services/api/ummaya/streaming.ts +365 -0
  215. package/tui/src/services/api/ummaya/streamingPayload.ts +129 -0
  216. package/tui/src/services/api/ummaya/streamingReader.ts +40 -0
  217. package/tui/src/services/api/ummaya/toolSelection.ts +217 -0
  218. package/tui/src/services/api/ummaya/types.ts +110 -0
  219. package/tui/src/services/api/ummaya/usage.ts +30 -0
  220. package/tui/src/services/api/ummaya.ts +26 -418
  221. package/tui/src/services/api/withRetry.ts +1 -1
  222. package/tui/src/services/awaySummary.ts +2 -2
  223. package/tui/src/services/claudeAiLimits.ts +1 -1
  224. package/tui/src/services/compact/autoCompact.ts +1 -1
  225. package/tui/src/services/compact/compact.ts +1 -1
  226. package/tui/src/services/lsp/types.ts +8 -30
  227. package/tui/src/services/tips/types.ts +6 -28
  228. package/tui/src/services/tokenEstimation.ts +1 -1
  229. package/tui/src/services/toolRegistry/bootGuard.ts +5 -5
  230. package/tui/src/services/toolUseSummary/toolUseSummaryGenerator.ts +1 -1
  231. package/tui/src/services/tools/toolExecution.ts +94 -1
  232. package/tui/src/store/pendingPermissionSlot.ts +1 -1
  233. package/tui/src/store/session-store.ts +10 -36
  234. package/tui/src/stubs/any-stub.ts +15 -10
  235. package/tui/src/stubs/color-diff-napi.ts +37 -23
  236. package/tui/src/stubs/globals.d.ts +3 -3
  237. package/tui/src/stubs/macro-preload.ts +23 -12
  238. package/tui/src/tools/AdapterTool/AdapterTool.ts +1207 -714
  239. package/tui/src/tools/AdapterTool/routeDiagnostics.ts +75 -0
  240. package/tui/src/tools/AgentTool/AgentTool.tsx +84 -1371
  241. package/tui/src/tools/AgentTool/agentToolHandoff.ts +114 -0
  242. package/tui/src/tools/AgentTool/agentToolPartialResult.ts +16 -0
  243. package/tui/src/tools/AgentTool/agentToolProgress.ts +32 -0
  244. package/tui/src/tools/AgentTool/agentToolResolver.ts +161 -0
  245. package/tui/src/tools/AgentTool/agentToolResult.ts +163 -0
  246. package/tui/src/tools/AgentTool/agentToolUtils.ts +14 -686
  247. package/tui/src/tools/AgentTool/asyncAgentLifecycle.ts +208 -0
  248. package/tui/src/tools/AgentTool/asyncLifecycle.ts +153 -0
  249. package/tui/src/tools/AgentTool/backgroundedCompletion.ts +126 -0
  250. package/tui/src/tools/AgentTool/backgroundedLifecycle.ts +174 -0
  251. package/tui/src/tools/AgentTool/foregroundBackground.ts +83 -0
  252. package/tui/src/tools/AgentTool/foregroundDrain.tsx +133 -0
  253. package/tui/src/tools/AgentTool/foregroundFinalize.ts +98 -0
  254. package/tui/src/tools/AgentTool/foregroundLifecycle.tsx +237 -0
  255. package/tui/src/tools/AgentTool/foregroundProgress.tsx +169 -0
  256. package/tui/src/tools/AgentTool/foregroundTask.ts +89 -0
  257. package/tui/src/tools/AgentTool/forkSubagent.ts +1 -12
  258. package/tui/src/tools/AgentTool/forkSubagentGate.ts +34 -0
  259. package/tui/src/tools/AgentTool/launchRouting.ts +203 -0
  260. package/tui/src/tools/AgentTool/lifecycle.ts +244 -0
  261. package/tui/src/tools/AgentTool/mcpRouting.ts +73 -0
  262. package/tui/src/tools/AgentTool/orchestrationSupport.ts +70 -0
  263. package/tui/src/tools/AgentTool/permissions.ts +39 -0
  264. package/tui/src/tools/AgentTool/promptSetup.ts +181 -0
  265. package/tui/src/tools/AgentTool/remoteRouting.ts +62 -0
  266. package/tui/src/tools/AgentTool/resultMapping.ts +116 -0
  267. package/tui/src/tools/AgentTool/resumeAgent.ts +39 -107
  268. package/tui/src/tools/AgentTool/resumeAgentHelpers.ts +140 -0
  269. package/tui/src/tools/AgentTool/runAgent.ts +1 -1
  270. package/tui/src/tools/AgentTool/runtimeConfig.ts +57 -0
  271. package/tui/src/tools/AgentTool/schemas.ts +196 -0
  272. package/tui/src/tools/AgentTool/sourceVerificationPropagation.ts +263 -0
  273. package/tui/src/tools/AgentTool/worktreeLifecycle.ts +105 -0
  274. package/tui/src/tools/AskUserQuestionTool/AskUserQuestionTool.tsx +174 -202
  275. package/tui/src/tools/BashTool/BashTool.tsx +71 -1072
  276. package/tui/src/tools/BashTool/bashCommandHelpers.ts +12 -12
  277. package/tui/src/tools/BashTool/bashPermissions/astPreflight.ts +173 -0
  278. package/tui/src/tools/BashTool/bashPermissions/classifierChecks.ts +199 -0
  279. package/tui/src/tools/BashTool/bashPermissions/compoundGuards.ts +53 -0
  280. package/tui/src/tools/BashTool/bashPermissions/constants.ts +99 -0
  281. package/tui/src/tools/BashTool/bashPermissions/index.ts +38 -0
  282. package/tui/src/tools/BashTool/bashPermissions/legacyMisparsing.ts +62 -0
  283. package/tui/src/tools/BashTool/bashPermissions/main.ts +135 -0
  284. package/tui/src/tools/BashTool/bashPermissions/normalizedCommands.ts +33 -0
  285. package/tui/src/tools/BashTool/bashPermissions/operatorFlow.ts +98 -0
  286. package/tui/src/tools/BashTool/bashPermissions/permissionChecks.ts +200 -0
  287. package/tui/src/tools/BashTool/bashPermissions/prefixSuggestions.ts +88 -0
  288. package/tui/src/tools/BashTool/bashPermissions/promptClassifierRules.ts +125 -0
  289. package/tui/src/tools/BashTool/bashPermissions/ruleDelegates.ts +19 -0
  290. package/tui/src/tools/BashTool/bashPermissions/ruleMatching.ts +145 -0
  291. package/tui/src/tools/BashTool/bashPermissions/sandboxAutoAllow.ts +75 -0
  292. package/tui/src/tools/BashTool/bashPermissions/subcommandFlow.ts +205 -0
  293. package/tui/src/tools/BashTool/bashPermissions/subcommandGuards.ts +73 -0
  294. package/tui/src/tools/BashTool/bashPermissions/subcommandResultHelpers.ts +116 -0
  295. package/tui/src/tools/BashTool/bashPermissions/types.ts +26 -0
  296. package/tui/src/tools/BashTool/bashPermissions/wrapperStripping.ts +139 -0
  297. package/tui/src/tools/BashTool/bashPermissions.ts +26 -2621
  298. package/tui/src/tools/BashTool/call.ts +202 -0
  299. package/tui/src/tools/BashTool/callLoader.ts +35 -0
  300. package/tui/src/tools/BashTool/commandClassification.ts +151 -0
  301. package/tui/src/tools/BashTool/commandClassificationLoader.ts +40 -0
  302. package/tui/src/tools/BashTool/cwdReset.ts +33 -0
  303. package/tui/src/tools/BashTool/lineTruncation.ts +11 -0
  304. package/tui/src/tools/BashTool/modeValidation.ts +13 -1
  305. package/tui/src/tools/BashTool/outputPersistence.ts +42 -0
  306. package/tui/src/tools/BashTool/permissionClassification.ts +66 -0
  307. package/tui/src/tools/BashTool/permissionLoader.ts +44 -0
  308. package/tui/src/tools/BashTool/resultLoader.ts +29 -0
  309. package/tui/src/tools/BashTool/resultMapping.ts +83 -0
  310. package/tui/src/tools/BashTool/sandboxPolicy.ts +79 -0
  311. package/tui/src/tools/BashTool/schemas.ts +65 -0
  312. package/tui/src/tools/BashTool/sedEditExecution.ts +59 -0
  313. package/tui/src/tools/BashTool/shellExecution.tsx +245 -0
  314. package/tui/src/tools/BashTool/shellOutputUtils.ts +85 -0
  315. package/tui/src/tools/BashTool/shellPermissionGauntlet.ts +97 -0
  316. package/tui/src/tools/BashTool/uiLoader.ts +37 -0
  317. package/tui/src/tools/BriefTool/upload.ts +1 -1
  318. package/tui/src/tools/CalculatorTool/parser.ts +2 -2
  319. package/tui/src/tools/DocumentPrimitive/DocumentPrimitive.ts +262 -0
  320. package/tui/src/tools/DocumentPrimitive/dispatchNormalization.ts +270 -0
  321. package/tui/src/tools/DocumentPrimitive/documentDestinationPath.ts +18 -0
  322. package/tui/src/tools/DocumentPrimitive/documentMutationGuard.ts +22 -0
  323. package/tui/src/tools/DocumentPrimitive/documentPatchNormalization.ts +248 -0
  324. package/tui/src/tools/DocumentPrimitive/documentSourceVerification.ts +245 -0
  325. package/tui/src/tools/DocumentPrimitive/documentSourceVerificationFields.ts +103 -0
  326. package/tui/src/tools/DocumentPrimitive/modelVisibleOutput.ts +40 -0
  327. package/tui/src/tools/DocumentPrimitive/prompt.ts +35 -0
  328. package/tui/src/tools/FileEditTool/FileEditTool.ts +9 -507
  329. package/tui/src/tools/FileEditTool/call.ts +228 -0
  330. package/tui/src/tools/FileEditTool/validateInput.ts +196 -0
  331. package/tui/src/tools/FileReadTool/imageProcessor.ts +13 -0
  332. package/tui/src/tools/FileWriteTool/FileWriteTool.ts +7 -300
  333. package/tui/src/tools/FileWriteTool/call.ts +223 -0
  334. package/tui/src/tools/FileWriteTool/validateInput.ts +80 -0
  335. package/tui/src/tools/ListMcpResourcesTool/ListMcpResourcesTool.ts +19 -3
  336. package/tui/src/tools/LookupPrimitive/LookupPrimitive.ts +25 -32
  337. package/tui/src/tools/LookupPrimitive/prompt.ts +0 -2
  338. package/tui/src/tools/MCPTool/trustPolicy.ts +118 -0
  339. package/tui/src/tools/McpAuthTool/McpAuthTool.ts +21 -3
  340. package/tui/src/tools/NotebookEditTool/NotebookEditTool.ts +7 -326
  341. package/tui/src/tools/NotebookEditTool/call.ts +254 -0
  342. package/tui/src/tools/NotebookEditTool/notebookModel.ts +51 -0
  343. package/tui/src/tools/NotebookEditTool/validateInput.ts +142 -0
  344. package/tui/src/tools/PowerShellTool/PowerShellTool.tsx +46 -937
  345. package/tui/src/tools/PowerShellTool/acceptEditsCommandValidation.ts +162 -0
  346. package/tui/src/tools/PowerShellTool/call.ts +179 -0
  347. package/tui/src/tools/PowerShellTool/callLoader.ts +37 -0
  348. package/tui/src/tools/PowerShellTool/commandClassification.ts +86 -0
  349. package/tui/src/tools/PowerShellTool/modeValidation.ts +25 -332
  350. package/tui/src/tools/PowerShellTool/outputPersistence.ts +42 -0
  351. package/tui/src/tools/PowerShellTool/permissionClassification.ts +28 -0
  352. package/tui/src/tools/PowerShellTool/resultLoader.ts +31 -0
  353. package/tui/src/tools/PowerShellTool/resultMapping.ts +75 -0
  354. package/tui/src/tools/PowerShellTool/schemas.ts +40 -0
  355. package/tui/src/tools/PowerShellTool/shellExecution.tsx +258 -0
  356. package/tui/src/tools/PowerShellTool/symlinkModeValidation.ts +44 -0
  357. package/tui/src/tools/PowerShellTool/uiLoader.ts +37 -0
  358. package/tui/src/tools/PowerShellTool/validation.ts +39 -0
  359. package/tui/src/tools/ReadMcpResourceTool/ReadMcpResourceTool.ts +19 -3
  360. package/tui/src/tools/ResolveLocationPrimitive/ResolveLocationPrimitive.ts +1 -11
  361. package/tui/src/tools/ResolveLocationPrimitive/prompt.ts +2 -6
  362. package/tui/src/tools/SkillTool/SkillTool.ts +2 -2
  363. package/tui/src/tools/SubmitPrimitive/SubmitPrimitive.ts +27 -10
  364. package/tui/src/tools/TaskCreateTool/TaskCreateTool.ts +16 -2
  365. package/tui/src/tools/TaskGetTool/TaskGetTool.ts +23 -3
  366. package/tui/src/tools/TaskListTool/TaskListTool.ts +22 -4
  367. package/tui/src/tools/TaskOutputTool/TaskOutputTool.tsx +46 -547
  368. package/tui/src/tools/TaskOutputTool/lookup.ts +216 -0
  369. package/tui/src/tools/TaskOutputTool/render.tsx +257 -0
  370. package/tui/src/tools/TaskOutputTool/schemas.ts +55 -0
  371. package/tui/src/tools/TaskOutputTool/serialization.ts +36 -0
  372. package/tui/src/tools/TaskStopTool/TaskStopTool.ts +10 -0
  373. package/tui/src/tools/TaskUpdateTool/TaskUpdateTool.ts +14 -364
  374. package/tui/src/tools/TaskUpdateTool/completion.ts +62 -0
  375. package/tui/src/tools/TaskUpdateTool/schemas.ts +62 -0
  376. package/tui/src/tools/TaskUpdateTool/serialization.ts +46 -0
  377. package/tui/src/tools/TaskUpdateTool/statusUpdate.ts +247 -0
  378. package/tui/src/tools/TodoWriteTool/TodoWriteTool.ts +21 -2
  379. package/tui/src/tools/ToolSearchTool/ToolSearchTool.ts +21 -302
  380. package/tui/src/tools/ToolSearchTool/ccSupportTools.ts +223 -0
  381. package/tui/src/tools/ToolSearchTool/descriptionCache.ts +50 -0
  382. package/tui/src/tools/ToolSearchTool/keywordSearch.ts +216 -0
  383. package/tui/src/tools/ToolSearchTool/prompt.ts +10 -4
  384. package/tui/src/tools/ToolSearchTool/resultMapping.ts +30 -0
  385. package/tui/src/tools/ToolSearchTool/schemas.ts +30 -0
  386. package/tui/src/tools/ToolSearchTool/searchPool.ts +47 -0
  387. package/tui/src/tools/ToolSearchTool/supportIntentHints.ts +140 -0
  388. package/tui/src/tools/TranslateTool/TranslateTool.ts +1 -1
  389. package/tui/src/tools/VerifyPrimitive/VerifyPrimitive.ts +2 -1
  390. package/tui/src/tools/WebFetchTool/WebFetchTool.ts +43 -138
  391. package/tui/src/tools/WebFetchTool/call.ts +227 -0
  392. package/tui/src/tools/WebFetchTool/resolvedAddressSafety.ts +78 -0
  393. package/tui/src/tools/WebFetchTool/sourceVerification.ts +204 -0
  394. package/tui/src/tools/WebFetchTool/types.ts +23 -0
  395. package/tui/src/tools/WebFetchTool/urlSafety.ts +181 -0
  396. package/tui/src/tools/WebFetchTool/utils.ts +1 -1
  397. package/tui/src/tools/WebSearchTool/UI.tsx +0 -1
  398. package/tui/src/tools/WebSearchTool/WebSearchTool.ts +9 -313
  399. package/tui/src/tools/WebSearchTool/call.ts +33 -0
  400. package/tui/src/tools/WebSearchTool/responseMapping.ts +190 -0
  401. package/tui/src/tools/WebSearchTool/resultBlock.ts +47 -0
  402. package/tui/src/tools/WebSearchTool/schemas.ts +47 -0
  403. package/tui/src/tools/WebSearchTool/toolSchema.ts +12 -0
  404. package/tui/src/tools/WorkspaceToolAdapter/WorkspaceToolAdapter.ts +79 -0
  405. package/tui/src/tools/WorkspaceToolAdapter/allowedRootPolicy.ts +85 -0
  406. package/tui/src/tools/WorkspaceToolAdapter/documentFormatGuards.ts +73 -0
  407. package/tui/src/tools/WorkspaceToolAdapter/inputNormalization.ts +105 -0
  408. package/tui/src/tools/WorkspaceToolAdapter/mcpExposurePolicy.ts +64 -0
  409. package/tui/src/tools/WorkspaceToolAdapter/toolDefFactory.ts +215 -0
  410. package/tui/src/tools/WorkspaceToolAdapter/toolNames.ts +6 -0
  411. package/tui/src/tools/WorkspaceToolAdapter/workspacePolicy.ts +15 -0
  412. package/tui/src/tools/_shared/dispatchPrimitive.ts +6 -6
  413. package/tui/src/tools/_shared/documentChangeToPatch.ts +125 -0
  414. package/tui/src/tools/_shared/documentDispatchArguments.ts +87 -0
  415. package/tui/src/tools/_shared/documentPrimitiveTimeout.ts +13 -0
  416. package/tui/src/tools/_shared/documentToolResultRender.ts +98 -0
  417. package/tui/src/tools/_shared/pendingCallRegistry.ts +1 -6
  418. package/tui/src/tools/_shared/rootPrimitiveInput.ts +1 -0
  419. package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPatterns.ts +58 -0
  420. package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPrompt.ts +271 -0
  421. package/tui/src/tools/_shared/toolChoiceRepair/documentRepair.ts +452 -0
  422. package/tui/src/tools/_shared/toolChoiceRepair/messageAccess.ts +80 -0
  423. package/tui/src/tools/_shared/toolChoiceRepair/publicDataRepair.ts +92 -0
  424. package/tui/src/tools/_shared/toolChoiceRepair/supportRepair.ts +135 -0
  425. package/tui/src/tools/_shared/toolChoiceRepair.ts +55 -860
  426. package/tui/src/tools/shared/mockDisclaimer.ts +1 -1
  427. package/tui/src/tools.ts +39 -190
  428. package/tui/src/types/fileSuggestion.ts +4 -26
  429. package/tui/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +186 -148
  430. package/tui/src/types/generated/events_mono/common/v1/auth.ts +25 -11
  431. package/tui/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +47 -30
  432. package/tui/src/types/generated/google/protobuf/timestamp.ts +21 -7
  433. package/tui/src/types/message.ts +80 -102
  434. package/tui/src/types/messageQueueTypes.ts +6 -28
  435. package/tui/src/types/notebook.ts +16 -38
  436. package/tui/src/types/statusLine.ts +4 -26
  437. package/tui/src/types/tools.ts +24 -46
  438. package/tui/src/types/utils.ts +6 -28
  439. package/tui/src/upstreamproxy/relay.ts +7 -3
  440. package/tui/src/upstreamproxy/upstreamproxy.ts +1 -1
  441. package/tui/src/utils/assistantMessageFactories.ts +9 -3
  442. package/tui/src/utils/auth.ts +129 -139
  443. package/tui/src/utils/bash/ast.ts +23 -23
  444. package/tui/src/utils/bash/bashParser.ts +5 -5
  445. package/tui/src/utils/billing.ts +1 -1
  446. package/tui/src/utils/claudeDesktop.ts +4 -4
  447. package/tui/src/utils/collapseReadSearch.ts +3 -3
  448. package/tui/src/utils/cronTasks.ts +1 -1
  449. package/tui/src/utils/execFileNoThrow.ts +1 -1
  450. package/tui/src/utils/filePersistence/types.ts +16 -38
  451. package/tui/src/utils/forkedAgent.ts +1 -1
  452. package/tui/src/utils/gracefulShutdown.ts +4 -4
  453. package/tui/src/utils/heapDumpService.ts +12 -8
  454. package/tui/src/utils/hooks/apiQueryHookHelper.ts +1 -1
  455. package/tui/src/utils/hooks/execPromptHook.ts +1 -1
  456. package/tui/src/utils/hooks/skillImprovement.ts +1 -1
  457. package/tui/src/utils/mcp/dateTimeParser.ts +1 -1
  458. package/tui/src/utils/messages.ts +18 -0
  459. package/tui/src/utils/migrateSessions.ts +3 -3
  460. package/tui/src/utils/model/model.ts +6 -6
  461. package/tui/src/utils/permissions/yoloClassifier.ts +1 -1
  462. package/tui/src/utils/plugins/headlessPluginInstall.ts +1 -1
  463. package/tui/src/utils/plugins/mcpPluginIntegration.ts +1 -1
  464. package/tui/src/utils/plugins/mcpbHandler.ts +1 -1
  465. package/tui/src/utils/plugins/pluginLoader.ts +8 -8
  466. package/tui/src/utils/protectedNamespace.ts +5 -3
  467. package/tui/src/utils/rawJsonToolCall.ts +242 -0
  468. package/tui/src/utils/ripgrep.ts +16 -7
  469. package/tui/src/utils/sessionTitle.ts +1 -1
  470. package/tui/src/utils/settings/permissionValidation.ts +14 -2
  471. package/tui/src/utils/shell/prefix.ts +1 -1
  472. package/tui/src/utils/sideQuery.ts +1 -1
  473. package/tui/src/utils/systemThemeWatcher.ts +13 -3
  474. package/tui/src/utils/teleport.tsx +1 -1
  475. package/uv.lock +426 -45
  476. package/tui/src/services/api/claude.ts +0 -3540
  477. package/tui/src/tools/_shared/directPublicDataGuard.ts +0 -362
  478. package/tui/src/tools/_shared/kmaAnalysisGuard.ts +0 -197
  479. package/tui/src/tools/_shared/kmaAviationGuard.ts +0 -70
  480. package/tui/src/tools/_shared/nmcAedGuard.ts +0 -234
  481. package/tui/src/tools/_shared/protectedCheckGuard.ts +0 -207
  482. package/tui/src/tools/_shared/textToolCallGuard.ts +0 -91
@@ -0,0 +1,452 @@
1
+ import { createHash } from 'node:crypto'
2
+ import type { Tools } from '../../../Tool.js'
3
+ import type { Message } from '../../../types/message.js'
4
+ import type {
5
+ ForcedUmmayaToolUse,
6
+ UmmayaBackendRepairReceipt,
7
+ } from '../toolChoiceRepair.js'
8
+ import {
9
+ buildDocumentCompletionPrompt,
10
+ hasTerminalDocumentCompletion,
11
+ mentionsDocumentWork,
12
+ } from './documentCompletionPrompt.js'
13
+ import {
14
+ DOCUMENT_INTENT_RE,
15
+ DOCUMENT_READ_ONLY_RE,
16
+ DOCUMENT_RENDER_TOOL_NAME,
17
+ DOCUMENT_TOOL_NAME,
18
+ DOCUMENT_WRITE_RE,
19
+ documentExpectedFormatFromPath,
20
+ isExactLocalReadOnlyDocumentPrompt,
21
+ localDocumentPathFromText,
22
+ type DocumentExpectedFormat,
23
+ } from './documentCompletionPatterns.js'
24
+ import {
25
+ isRecord,
26
+ latestUserMessageIndex,
27
+ latestUserText,
28
+ messageContent,
29
+ textFromContent,
30
+ } from './messageAccess.js'
31
+
32
+ const DOCUMENT_EXPLICIT_PATH_SCAN_RE =
33
+ /(?:^|[\s:'"(])((?:~|\/|[A-Za-z]:\\|\.{1,2}\/)[^\s:'"]+\.(hwpx|hwp|docx|pdf|xlsx|pptx))\b/giu
34
+ const DOCUMENT_ARTIFACT_ID_RE =
35
+ /(?:^|[\s"'`(])(?:artifact_id|artifact\s*id|artifact|아티팩트)?\s*((?:source|working|derivative|render|export|viewport)-[A-Za-z0-9][A-Za-z0-9_.-]{0,127})(?=$|[^A-Za-z0-9_.-])/iu
36
+ const DOCUMENT_FORMAT_RE = /\b(?:hwpx|hwp|docx|pdf|xlsx|pptx)\b/iu
37
+ const DOCUMENT_REVIEW_RE =
38
+ /(diff|compact|변경사항|렌더|미리보기|render|viewport|page)/iu
39
+ const DOCUMENT_LOCAL_HINT_RE =
40
+ /(다운로드|downloads?|폴더|파일|양식|서식|활동일지|신청서|등본|증명서)/iu
41
+
42
+ function toolAvailable(tools: Tools, toolName: string): boolean {
43
+ return tools.some(tool => tool.name === toolName)
44
+ }
45
+
46
+ function documentCandidateText(candidate: unknown): string {
47
+ if (typeof candidate === 'string') return candidate
48
+ if (!isRecord(candidate)) return ''
49
+ const message = isRecord(candidate.message) ? candidate.message : candidate
50
+ return textFromContent(messageContent(message))
51
+ }
52
+
53
+ type DocumentDispatchRepair =
54
+ | {
55
+ readonly kind: 'ready'
56
+ readonly input: Record<string, unknown>
57
+ }
58
+ | {
59
+ readonly kind: 'blocked'
60
+ readonly message: string
61
+ }
62
+
63
+ type DocumentPathRef = {
64
+ readonly path: string
65
+ readonly expectedFormat: DocumentExpectedFormat
66
+ }
67
+
68
+ export function repairUmmayaDocumentToolInputForDispatch({
69
+ toolName,
70
+ input,
71
+ messages,
72
+ }: {
73
+ readonly toolName: string
74
+ readonly input: Record<string, unknown>
75
+ readonly messages: readonly Message[]
76
+ }): DocumentDispatchRepair {
77
+ if (toolName !== DOCUMENT_TOOL_NAME) {
78
+ return { kind: 'ready', input }
79
+ }
80
+
81
+ const userText = latestUserText(messages)
82
+ const exactReadOnlyInspect = isExactLocalReadOnlyDocumentPrompt(userText)
83
+ if (hasDocumentDispatchContract(input) && !exactReadOnlyInspect) {
84
+ return { kind: 'ready', input }
85
+ }
86
+
87
+ if (!exactReadOnlyInspect) {
88
+ return {
89
+ kind: 'blocked',
90
+ message:
91
+ 'Document boundary blocked: provider emitted malformed document input, and the latest user request was not an exact local read-only inspect prompt. The document tool was not dispatched.',
92
+ }
93
+ }
94
+
95
+ const path = localDocumentPathFromText(userText)
96
+ if (path === undefined) {
97
+ return {
98
+ kind: 'blocked',
99
+ message:
100
+ 'Document boundary blocked: provider emitted malformed document input, and no exact local document path could be recovered from the latest user request. Provide an exact existing file path.',
101
+ }
102
+ }
103
+
104
+ const expectedFormat = documentExpectedFormatFromPath(path)
105
+ return {
106
+ kind: 'ready',
107
+ input: {
108
+ correlation_id:
109
+ nonEmptyString(input.correlation_id) ??
110
+ `client-repaired-document-${shortHash(`${path}\n${userText}`)}`,
111
+ document: {
112
+ path,
113
+ ...(expectedFormat === undefined ? {} : { expected_format: expectedFormat }),
114
+ },
115
+ operation: 'inspect',
116
+ instruction: documentInstruction(input, userText),
117
+ __ummaya_user_query: userText,
118
+ },
119
+ }
120
+ }
121
+
122
+ function hasDocumentDispatchContract(input: Record<string, unknown>): boolean {
123
+ const document = isRecord(input.document) ? input.document : undefined
124
+ return nonEmptyString(input.correlation_id) !== undefined &&
125
+ document !== undefined &&
126
+ (nonEmptyString(document.path) !== undefined ||
127
+ nonEmptyString(document.artifact_id) !== undefined) &&
128
+ nonEmptyString(input.instruction) !== undefined
129
+ }
130
+
131
+ function documentInstruction(
132
+ input: Record<string, unknown>,
133
+ userText: string,
134
+ ): string {
135
+ const instruction = nonEmptyString(input.instruction)
136
+ if (instruction === undefined) return userText
137
+ if (instruction.includes(userText)) return instruction
138
+ return `${instruction}\n\nOriginal user request:\n${userText}`
139
+ }
140
+
141
+ function nonEmptyString(value: unknown): string | undefined {
142
+ return typeof value === 'string' && value.trim().length > 0
143
+ ? value
144
+ : undefined
145
+ }
146
+
147
+ function shortHash(text: string): string {
148
+ return createHash('sha256').update(text).digest('hex').slice(0, 8)
149
+ }
150
+
151
+ function hasBackendRepairReceipt(
152
+ receipt: UmmayaBackendRepairReceipt | undefined,
153
+ ): boolean {
154
+ return receipt !== undefined &&
155
+ (receipt.source === 'backend_route_decision' ||
156
+ receipt.source === 'backend_validation') &&
157
+ receipt.reason.trim() !== '' &&
158
+ receipt.evidenceEvent.startsWith('ummaya.')
159
+ }
160
+
161
+ function isDocumentHarnessQuery(text: string): boolean {
162
+ return localDocumentPathFromText(text) !== undefined ||
163
+ DOCUMENT_ARTIFACT_ID_RE.test(text) ||
164
+ ((DOCUMENT_FORMAT_RE.test(text) || DOCUMENT_ARTIFACT_ID_RE.test(text)) &&
165
+ DOCUMENT_INTENT_RE.test(text)) ||
166
+ (DOCUMENT_INTENT_RE.test(text) &&
167
+ DOCUMENT_WRITE_RE.test(text) &&
168
+ DOCUMENT_LOCAL_HINT_RE.test(text))
169
+ }
170
+
171
+ function hasExplicitDocumentLocator(text: string): boolean {
172
+ return localDocumentPathFromText(text) !== undefined ||
173
+ DOCUMENT_ARTIFACT_ID_RE.test(text)
174
+ }
175
+
176
+ function explicitDocumentPathRefs(userText: string): readonly DocumentPathRef[] {
177
+ return [...userText.matchAll(DOCUMENT_EXPLICIT_PATH_SCAN_RE)].map(match => ({
178
+ path: match[1]!,
179
+ expectedFormat: match[2]!.toLowerCase() as DocumentExpectedFormat,
180
+ }))
181
+ }
182
+
183
+ function stableDocumentCorrelationId(userText: string): string {
184
+ return `client-forced-document-${shortHash(userText)}`
185
+ }
186
+
187
+ function forcedDocumentInputFromExplicitPath(
188
+ userText: string,
189
+ ): Record<string, unknown> | undefined {
190
+ if (!isDocumentHarnessQuery(userText)) return undefined
191
+ const wantsWrite =
192
+ DOCUMENT_WRITE_RE.test(userText) && !DOCUMENT_READ_ONLY_RE.test(userText)
193
+ const wantsReview = DOCUMENT_REVIEW_RE.test(userText)
194
+ const wantsReadOnly = DOCUMENT_READ_ONLY_RE.test(userText)
195
+ if (!wantsWrite && !wantsReview && !wantsReadOnly) return undefined
196
+
197
+ const paths = explicitDocumentPathRefs(userText)
198
+ const source = paths[0]
199
+ if (!source) return undefined
200
+
201
+ const input: Record<string, unknown> = {
202
+ correlation_id: stableDocumentCorrelationId(userText),
203
+ document: {
204
+ path: source.path,
205
+ expected_format: source.expectedFormat,
206
+ },
207
+ operation: wantsWrite ? 'fill' : 'inspect',
208
+ instruction: userText,
209
+ }
210
+ const destination = paths.find(candidate => candidate.path !== source.path)
211
+ if (destination !== undefined && wantsWrite) {
212
+ input.destination_path = destination.path
213
+ }
214
+ return input
215
+ }
216
+
217
+ function toolAvailableOrSynced(tools: Tools, toolName: string): boolean {
218
+ return toolAvailable(tools, toolName)
219
+ }
220
+
221
+ function hasExplicitMutationPayload(input: Record<string, unknown>): boolean {
222
+ return Array.isArray(input.patches) ||
223
+ Array.isArray(input.styles) ||
224
+ typeof input.destination_path === 'string'
225
+ }
226
+
227
+ function parseJsonRecord(value: string): Record<string, unknown> | undefined {
228
+ try {
229
+ const parsed: unknown = JSON.parse(value)
230
+ return isRecord(parsed) ? parsed : undefined
231
+ } catch {
232
+ return undefined
233
+ }
234
+ }
235
+
236
+ function documentResultPayload(value: unknown): Record<string, unknown> | undefined {
237
+ if (Array.isArray(value)) {
238
+ for (let index = value.length - 1; index >= 0; index -= 1) {
239
+ const nested = documentResultPayload(value[index])
240
+ if (nested !== undefined) return nested
241
+ }
242
+ return undefined
243
+ }
244
+ if (!isRecord(value)) return undefined
245
+ const toolId = typeof value.tool_id === 'string' ? value.tool_id : undefined
246
+ if (toolId === DOCUMENT_TOOL_NAME || toolId === DOCUMENT_RENDER_TOOL_NAME) {
247
+ return value
248
+ }
249
+ return documentResultPayload(value.result)
250
+ }
251
+
252
+ function isSuccessfulDocumentPayload(
253
+ payload: Record<string, unknown>,
254
+ acceptedToolNames: ReadonlySet<string>,
255
+ ): boolean {
256
+ const toolId = typeof payload.tool_id === 'string' ? payload.tool_id : undefined
257
+ if (toolId === undefined || !acceptedToolNames.has(toolId)) return false
258
+ const status = typeof payload.status === 'string'
259
+ ? payload.status.toLowerCase()
260
+ : 'ok'
261
+ const okFlag = typeof payload.ok === 'boolean' ? payload.ok : true
262
+ const hasError =
263
+ payload.kind === 'error' ||
264
+ typeof payload.error === 'string' ||
265
+ isRecord(payload.error)
266
+ return okFlag && !hasError &&
267
+ ['ok', 'succeeded', 'completed', 'ready'].includes(status)
268
+ }
269
+
270
+ function hasSuccessfulDocumentResultAfter(
271
+ messages: readonly Message[],
272
+ afterIndex: number,
273
+ acceptedToolNames: ReadonlySet<string>,
274
+ ): boolean {
275
+ for (let index = Math.max(0, afterIndex + 1); index < messages.length; index += 1) {
276
+ const content = messageContent(messages[index])
277
+ if (!Array.isArray(content)) continue
278
+ for (const block of content) {
279
+ if (!isRecord(block) || block.type !== 'tool_result') continue
280
+ if (block.is_error === true || typeof block.content !== 'string') continue
281
+ const payload = documentResultPayload(parseJsonRecord(block.content))
282
+ if (
283
+ payload !== undefined &&
284
+ isSuccessfulDocumentPayload(payload, acceptedToolNames)
285
+ ) {
286
+ return true
287
+ }
288
+ }
289
+ }
290
+ return false
291
+ }
292
+
293
+ export function repairUmmayaExplicitDocumentToolUseFromUserQuery({
294
+ input,
295
+ toolName,
296
+ messages,
297
+ tools,
298
+ backendRepairReceipt,
299
+ }: {
300
+ readonly toolName: string
301
+ readonly input: Record<string, unknown>
302
+ readonly messages: readonly Message[]
303
+ readonly tools: Tools
304
+ readonly backendRepairReceipt?: UmmayaBackendRepairReceipt
305
+ }): ForcedUmmayaToolUse | undefined {
306
+ if (!hasBackendRepairReceipt(backendRepairReceipt)) return undefined
307
+ if (!toolAvailableOrSynced(tools, DOCUMENT_TOOL_NAME)) return undefined
308
+
309
+ const userText = latestUserText(messages)
310
+ if (!hasExplicitDocumentLocator(userText)) return undefined
311
+ const forced = forcedDocumentInputFromExplicitPath(userText)
312
+ if (forced === undefined) return undefined
313
+
314
+ if (toolName === DOCUMENT_TOOL_NAME) {
315
+ const forcedOperation = typeof forced.operation === 'string'
316
+ ? forced.operation
317
+ : undefined
318
+ const currentOperation = typeof input.operation === 'string'
319
+ ? input.operation
320
+ : undefined
321
+ if (
322
+ forcedOperation === currentOperation ||
323
+ (forcedOperation !== 'inspect' && hasExplicitMutationPayload(input))
324
+ ) {
325
+ return undefined
326
+ }
327
+ }
328
+
329
+ return {
330
+ name: DOCUMENT_TOOL_NAME,
331
+ input: forced,
332
+ }
333
+ }
334
+
335
+ export function backfillUmmayaObservableToolInputFromUserQuery(_params: {
336
+ readonly toolName: string
337
+ readonly input: Record<string, unknown>
338
+ readonly messages: readonly Message[]
339
+ }): void {
340
+ if (_params.toolName !== DOCUMENT_TOOL_NAME) return
341
+ const operation = typeof _params.input.operation === 'string'
342
+ ? _params.input.operation
343
+ : undefined
344
+ if (operation !== 'inspect' && operation !== 'extract') return
345
+
346
+ const userText = latestUserText(_params.messages)
347
+ if (!isDocumentHarnessQuery(userText)) return
348
+ if (!DOCUMENT_WRITE_RE.test(userText) || DOCUMENT_READ_ONLY_RE.test(userText)) {
349
+ return
350
+ }
351
+ if (!hasExplicitDocumentLocator(userText)) return
352
+
353
+ _params.input.__ummaya_display_operation = 'fill'
354
+ }
355
+
356
+ export function selectUmmayaClientForcedToolUse({
357
+ messages,
358
+ tools,
359
+ backendRepairReceipt,
360
+ }: {
361
+ readonly messages: readonly Message[]
362
+ readonly tools: Tools
363
+ readonly backendRepairReceipt?: UmmayaBackendRepairReceipt
364
+ }): ForcedUmmayaToolUse | undefined {
365
+ if (!hasBackendRepairReceipt(backendRepairReceipt)) return undefined
366
+ if (!toolAvailableOrSynced(tools, DOCUMENT_TOOL_NAME)) return undefined
367
+ const input = forcedDocumentInputFromExplicitPath(latestUserText(messages))
368
+ if (input === undefined) return undefined
369
+ return {
370
+ name: DOCUMENT_TOOL_NAME,
371
+ input,
372
+ }
373
+ }
374
+
375
+ export function selectRecoveredDocumentToolChoiceNameForMessages({
376
+ messages,
377
+ tools,
378
+ }: {
379
+ readonly messages: readonly Message[]
380
+ readonly tools: Tools
381
+ }): string | undefined {
382
+ if (!isExactLocalReadOnlyDocumentPrompt(latestUserText(messages))) {
383
+ return undefined
384
+ }
385
+ return toolAvailable(tools, DOCUMENT_TOOL_NAME) ? DOCUMENT_TOOL_NAME : undefined
386
+ }
387
+
388
+ export function shouldWithholdIgnoredDocumentToolChoiceText({
389
+ toolChoiceName,
390
+ candidate,
391
+ }: {
392
+ readonly toolChoiceName: string
393
+ readonly candidate: unknown
394
+ }): boolean {
395
+ return toolChoiceName === DOCUMENT_TOOL_NAME &&
396
+ documentCandidateText(candidate).trim().length > 0
397
+ }
398
+
399
+ export function buildIgnoredDocumentToolChoiceBlockedText(
400
+ toolChoiceAvailable = true,
401
+ ): string {
402
+ const reason = toolChoiceAvailable
403
+ ? 'provider ignored forced document tool_choice.'
404
+ : 'document 도구가 현재 TUI 도구 풀에 없어 로컬 문서 검사를 실행할 수 없습니다.'
405
+ return [
406
+ '문서 도구 호출 차단: document tool_choice를 강제했지만 모델 응답에 document 도구 경계가 포함되지 않았습니다.',
407
+ `이유: ${reason}`,
408
+ '로컬 문서는 검색 또는 추측 답변으로 처리하지 않습니다.',
409
+ ].join(' ')
410
+ }
411
+
412
+ export function shouldCompleteAfterSuccessfulDocumentRender(_params: {
413
+ readonly messages: readonly Message[]
414
+ }): boolean {
415
+ const userText = latestUserText(_params.messages)
416
+ if (!isDocumentHarnessQuery(userText)) return false
417
+ if (!DOCUMENT_REVIEW_RE.test(userText)) return false
418
+ if (!DOCUMENT_ARTIFACT_ID_RE.test(userText)) return false
419
+ return hasSuccessfulDocumentResultAfter(
420
+ _params.messages,
421
+ latestUserMessageIndex(_params.messages),
422
+ new Set([DOCUMENT_TOOL_NAME, DOCUMENT_RENDER_TOOL_NAME]),
423
+ )
424
+ }
425
+
426
+ export function shouldCompleteAfterTerminalDocumentToolResult(_params: {
427
+ readonly messages: readonly Message[]
428
+ }): boolean {
429
+ const userText = latestUserText(_params.messages)
430
+ if (!mentionsDocumentWork(userText)) return false
431
+ return hasTerminalDocumentCompletion({
432
+ messages: _params.messages,
433
+ userText,
434
+ })
435
+ }
436
+
437
+ export function shouldSuppressDocumentToolCallsForAnswerSynthesis(params: {
438
+ readonly messages: readonly Message[]
439
+ }): boolean {
440
+ return shouldCompleteAfterSuccessfulDocumentRender(params) ||
441
+ shouldCompleteAfterTerminalDocumentToolResult(params)
442
+ }
443
+
444
+ export function buildDocumentCompletionPromptIfNeeded({
445
+ messages,
446
+ }: {
447
+ readonly messages: readonly Message[]
448
+ }): string | undefined {
449
+ const userText = latestUserText(messages)
450
+ if (!mentionsDocumentWork(userText)) return undefined
451
+ return buildDocumentCompletionPrompt({ messages, userText })
452
+ }
@@ -0,0 +1,80 @@
1
+ import type { Message } from '../../../types/message.js'
2
+
3
+ export function isRecord(value: unknown): value is Record<string, unknown> {
4
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
5
+ }
6
+
7
+ export function messageRecord(
8
+ message: unknown,
9
+ ): Record<string, unknown> | undefined {
10
+ if (!isRecord(message)) return undefined
11
+ return isRecord(message.message) ? message.message : undefined
12
+ }
13
+
14
+ export function messageRole(message: unknown): string | undefined {
15
+ const outer = isRecord(message) ? message : undefined
16
+ const inner = messageRecord(message)
17
+ if (typeof inner?.role === 'string') return inner.role
18
+ if (typeof outer?.role === 'string') return outer.role
19
+ return typeof outer?.type === 'string' ? outer.type : undefined
20
+ }
21
+
22
+ export function messageContent(message: unknown): unknown {
23
+ return messageRecord(message)?.content ?? (isRecord(message) ? message.content : undefined)
24
+ }
25
+
26
+ export function textFromContent(content: unknown): string {
27
+ if (typeof content === 'string') return content
28
+ if (!Array.isArray(content)) return ''
29
+ return content
30
+ .map(block => {
31
+ if (typeof block === 'string') return block
32
+ if (!isRecord(block)) return ''
33
+ if (block.type !== 'text') return ''
34
+ return typeof block.text === 'string' ? block.text : ''
35
+ })
36
+ .filter(text => text.length > 0)
37
+ .join('\n')
38
+ }
39
+
40
+ export function latestUserText(messages: readonly unknown[]): string {
41
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
42
+ if (messageRole(messages[index]) !== 'user') continue
43
+ const text = textFromContent(messageContent(messages[index])).trim()
44
+ if (text.length > 0) return text
45
+ }
46
+ return ''
47
+ }
48
+
49
+ export function latestUserMessageIndex(messages: readonly unknown[]): number {
50
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
51
+ if (messageRole(messages[index]) !== 'user') continue
52
+ const text = textFromContent(messageContent(messages[index])).trim()
53
+ if (text.length > 0) return index
54
+ }
55
+ return -1
56
+ }
57
+
58
+ export function toolUseNames(messages: readonly unknown[]): ReadonlySet<string> {
59
+ const names = new Set<string>()
60
+ for (const candidate of messages) {
61
+ const content = messageContent(candidate)
62
+ if (!Array.isArray(content)) continue
63
+ for (const block of content) {
64
+ if (isRecord(block) && block.type === 'tool_use' && typeof block.name === 'string') {
65
+ const input = isRecord(block.input) ? block.input : undefined
66
+ names.add(typeof input?.tool_id === 'string' ? input.tool_id : block.name)
67
+ }
68
+ }
69
+ }
70
+ return names
71
+ }
72
+
73
+ export function latestAssistantText(messages: readonly Message[]): string {
74
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
75
+ if (messageRole(messages[index]) !== 'assistant') continue
76
+ const text = textFromContent(messageContent(messages[index]))
77
+ if (text.trim().length > 0) return text
78
+ }
79
+ return ''
80
+ }
@@ -0,0 +1,92 @@
1
+ import type { Tools } from '../../../Tool.js'
2
+ import type { Message } from '../../../types/message.js'
3
+ import { isNonSyntheticUserMessageText } from '../citizenUserText.js'
4
+ import {
5
+ isRecord,
6
+ latestAssistantText,
7
+ messageContent,
8
+ messageRole,
9
+ textFromContent,
10
+ } from './messageAccess.js'
11
+
12
+ type PromptParams = { readonly messages: readonly Message[] }
13
+ type CandidateWithholdParams = PromptParams & { readonly candidate: Message }
14
+
15
+ const GENERIC_PENDING_FINAL_RE =
16
+ /(답변을?\s*제공하겠습니다|제공하겠습니다|확인해\s*보겠습니다|확인하겠습니다|조회하겠습니다|찾아보겠습니다|검색해\s*보겠습니다|검색하겠습니다|최종\s*답변은|final answer should|will\s+(?:answer|provide|check|search|look\s+up))/iu
17
+ const GENERIC_PENDING_FINAL_REPAIR_PROMPT =
18
+ 'Final answer repair: successful tool_result evidence already exists, but the previous assistant message was still a plan or promise to answer later. Write the final Korean answer now from the actual tool_result values only. Do not say 제공하겠습니다, 확인하겠습니다, 조회하겠습니다, 찾아보겠습니다, 검색해 보겠습니다, or describe what you will answer next.'
19
+ const GENERIC_PENDING_FINAL_TOOL_USE_BLOCKED_TEXT =
20
+ '이미 도구 결과가 반환되어 최종 답변 보정이 요청되었습니다. 이 단계에서는 추가 도구를 실행하지 않습니다. 현재 확인된 도구 결과만 근거로 답변을 마무리하고, 연결되지 않은 업무는 공식 채널 확인 또는 필요한 adapter/credential 준비로 넘겨야 합니다.'
21
+
22
+ export function buildGenericPendingFinalAnswerRepairPromptIfNeeded(
23
+ params: PromptParams,
24
+ ): string | undefined {
25
+ if (!hasToolResultAfterLatestUser(params.messages)) return undefined
26
+ if (hasGenericPendingFinalRepairPrompt(params.messages)) return undefined
27
+ if (!GENERIC_PENDING_FINAL_RE.test(latestAssistantText(params.messages))) {
28
+ return undefined
29
+ }
30
+ return GENERIC_PENDING_FINAL_REPAIR_PROMPT
31
+ }
32
+
33
+ export function shouldWithholdGenericPendingFinalAnswer(
34
+ params: CandidateWithholdParams,
35
+ ): boolean {
36
+ if (hasGenericPendingFinalRepairPrompt(params.messages)) return false
37
+ if (candidateHasToolUse(params.candidate)) return false
38
+ return buildGenericPendingFinalAnswerRepairPromptIfNeeded({
39
+ messages: [...params.messages, params.candidate],
40
+ }) !== undefined
41
+ }
42
+
43
+ export function shouldBlockToolUseAfterGenericPendingFinalAnswerRepair(
44
+ params: CandidateWithholdParams,
45
+ ): boolean {
46
+ return hasGenericPendingFinalRepairPrompt(params.messages) &&
47
+ candidateHasToolUse(params.candidate)
48
+ }
49
+
50
+ export function buildGenericPendingFinalAnswerToolUseBlockedText(): string {
51
+ return GENERIC_PENDING_FINAL_TOOL_USE_BLOCKED_TEXT
52
+ }
53
+
54
+ export function selectUmmayaClientForcedToolUseForPublicData(_params: {
55
+ readonly messages: readonly Message[]
56
+ readonly tools: Tools
57
+ }): undefined {
58
+ return undefined
59
+ }
60
+
61
+ function hasGenericPendingFinalRepairPrompt(messages: readonly Message[]): boolean {
62
+ return messages.some(message =>
63
+ textFromContent(messageContent(message)).includes(
64
+ 'Final answer repair: successful tool_result',
65
+ ),
66
+ )
67
+ }
68
+
69
+ function candidateHasToolUse(candidate: Message): boolean {
70
+ const content = messageContent(candidate)
71
+ return Array.isArray(content) &&
72
+ content.some(block => isRecord(block) && block.type === 'tool_use')
73
+ }
74
+
75
+ function hasToolResultAfterLatestUser(messages: readonly Message[]): boolean {
76
+ let latestUserIndex = -1
77
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
78
+ const message = messages[index]
79
+ if (messageRole(message) !== 'user') continue
80
+ const text = textFromContent(messageContent(message))
81
+ if (isNonSyntheticUserMessageText(message, text)) {
82
+ latestUserIndex = index
83
+ break
84
+ }
85
+ }
86
+ if (latestUserIndex < 0) return false
87
+ return messages.slice(latestUserIndex + 1).some(message => {
88
+ const content = messageContent(message)
89
+ return Array.isArray(content) &&
90
+ content.some(block => isRecord(block) && block.type === 'tool_result')
91
+ })
92
+ }