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,687 @@
1
+ import { findToolByName, type Tool, type ToolUseContext } from '../Tool.js'
2
+ import type { AssistantMessage, Message, UserMessage } from '../types/message.js'
3
+ import { getAdapterToolByName } from '../tools/AdapterTool/AdapterTool.js'
4
+ import {
5
+ repairUmmayaDocumentToolInputForDispatch,
6
+ } from '../tools/_shared/toolChoiceRepair.js'
7
+ import { deriveLocationQueryFromUserText } from '../tools/_shared/locationInputRepair.js'
8
+ import { createUserMessage } from '../utils/messages.js'
9
+ import { isUnregisteredRawJsonToolUseId } from '../utils/rawJsonToolCall.js'
10
+ import { formatZodValidationError } from '../utils/toolErrors.js'
11
+ import {
12
+ latestTextUserMessageIndex,
13
+ messageText,
14
+ type ToolUseBlock,
15
+ } from './messageGuards.js'
16
+ import { createToolUnavailableErrorPayload } from './toolResultErrors.js'
17
+
18
+ function serializeToolResult(data: unknown): string {
19
+ if (typeof data === 'string') return data
20
+ if (data === null || data === undefined) return ''
21
+ try {
22
+ return JSON.stringify(data)
23
+ } catch {
24
+ return String(data)
25
+ }
26
+ }
27
+
28
+ function isRecord(value: unknown): value is Record<string, unknown> {
29
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
30
+ }
31
+
32
+ function parseJsonRecord(value: unknown): Record<string, unknown> | undefined {
33
+ if (isRecord(value)) return value
34
+ if (typeof value !== 'string') return undefined
35
+ try {
36
+ const parsed: unknown = JSON.parse(value)
37
+ return isRecord(parsed) ? parsed : undefined
38
+ } catch {
39
+ return undefined
40
+ }
41
+ }
42
+
43
+ function isStructuredFailureResult(value: unknown): boolean {
44
+ return parseJsonRecord(value)?.ok === false
45
+ }
46
+
47
+ function normalizeToolResultDataForModel(
48
+ toolName: string,
49
+ data: unknown,
50
+ ): unknown {
51
+ if (toolName !== 'document' || !isRecord(data) || data.ok !== false) {
52
+ return data
53
+ }
54
+ if (isRecord(data.result) && data.result.tool_id === 'document') {
55
+ return data
56
+ }
57
+ const error = isRecord(data.error) ? data.error : undefined
58
+ const message = typeof error?.message === 'string'
59
+ ? error.message
60
+ : 'Document tool failed before producing a document result.'
61
+ return {
62
+ ...data,
63
+ result: {
64
+ tool_id: 'document',
65
+ status: 'failed',
66
+ text_summary: message,
67
+ },
68
+ }
69
+ }
70
+
71
+ function permissionErrorMessage(message: string | undefined): string {
72
+ const trimmed = message?.trim()
73
+ return trimmed
74
+ ? `Permission denied: ${trimmed}`
75
+ : 'Permission denied: tool execution was not approved.'
76
+ }
77
+
78
+ type ToolInput = { readonly [key: string]: unknown }
79
+
80
+ type SuccessfulToolCall = {
81
+ readonly toolName: string
82
+ readonly input: ToolInput
83
+ }
84
+
85
+ const MAX_SUCCESSFUL_CALLS_PER_EFFECTIVE_TOOL = 2
86
+ const HOMETAX_LOOKUP_TOOL_NAME = 'mock_lookup_module_hometax_simplified'
87
+ const KMA_METAR_TOOL_NAME = 'kma_apihub_url_air_metar_decoded'
88
+ const ROOT_FIND_TOOL_NAME = 'find'
89
+ const KAKAO_LOCATION_TOOL_NAMES = new Set([
90
+ 'kakao_address_search',
91
+ 'kakao_keyword_search',
92
+ ])
93
+ const KMA_ORDINARY_WEATHER_TOOL_NAMES = new Set([
94
+ 'kma_apihub_upp_mtly_info_service_get_max_wind',
95
+ 'kma_current_observation',
96
+ 'kma_forecast_fetch',
97
+ 'kma_short_term_forecast',
98
+ 'kma_ultra_short_term_forecast',
99
+ ])
100
+
101
+ function stableJson(value: unknown): string {
102
+ if (Array.isArray(value)) {
103
+ return `[${value.map(stableJson).join(',')}]`
104
+ }
105
+ if (isRecord(value)) {
106
+ return `{${Object.keys(value)
107
+ .sort()
108
+ .map(key => `${JSON.stringify(key)}:${stableJson(value[key])}`)
109
+ .join(',')}}`
110
+ }
111
+ const encoded = JSON.stringify(value)
112
+ return encoded === undefined ? String(value) : encoded
113
+ }
114
+
115
+ function toolInputsEquivalent(
116
+ tool: Tool,
117
+ left: ToolInput,
118
+ right: ToolInput,
119
+ ): boolean {
120
+ return tool.inputsEquivalent?.(left, right) ?? stableJson(left) === stableJson(right)
121
+ }
122
+
123
+ function effectiveToolKey(toolName: string, input: ToolInput): string {
124
+ const concreteToolId = input.tool_id
125
+ if (typeof concreteToolId === 'string' && concreteToolId.trim().length > 0) {
126
+ return `${toolName}:${concreteToolId}`
127
+ }
128
+ return toolName
129
+ }
130
+
131
+ function isCitizenPromptMessage(message: Message): boolean {
132
+ if (message.type !== 'user') return false
133
+ if (message.isMeta === true) return false
134
+ const content = message.message.content
135
+ if (!Array.isArray(content)) return true
136
+ return !content.every(block => block.type === 'tool_result')
137
+ }
138
+
139
+ function latestCitizenPromptIndex(messages: readonly Message[]): number {
140
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
141
+ const message = messages[index]
142
+ if (message !== undefined && isCitizenPromptMessage(message)) {
143
+ return index
144
+ }
145
+ }
146
+ return -1
147
+ }
148
+
149
+ function latestCitizenPromptText(messages: readonly Message[]): string {
150
+ const index = latestTextUserMessageIndex(messages)
151
+ const message = index >= 0 ? messages[index] : undefined
152
+ return message ? messageText(message) : ''
153
+ }
154
+
155
+ function successfulToolResultIdsSinceLatestPrompt(
156
+ messages: readonly Message[],
157
+ ): ReadonlySet<string> {
158
+ const startIndex = latestCitizenPromptIndex(messages)
159
+ const ids = new Set<string>()
160
+ for (const message of messages.slice(startIndex + 1)) {
161
+ if (message.type !== 'user' || !Array.isArray(message.message.content)) {
162
+ continue
163
+ }
164
+ for (const block of message.message.content) {
165
+ if (
166
+ block.type === 'tool_result' &&
167
+ block.is_error !== true &&
168
+ !isStructuredFailureResult(block.content)
169
+ ) {
170
+ ids.add(block.tool_use_id)
171
+ }
172
+ }
173
+ }
174
+ return ids
175
+ }
176
+
177
+ function successfulToolCallsSinceLatestPrompt(
178
+ messages: readonly Message[],
179
+ ): readonly SuccessfulToolCall[] {
180
+ const startIndex = latestCitizenPromptIndex(messages)
181
+ const successfulResultIds = successfulToolResultIdsSinceLatestPrompt(messages)
182
+ const calls: SuccessfulToolCall[] = []
183
+ for (const message of messages.slice(startIndex + 1)) {
184
+ if (message.type !== 'assistant') continue
185
+ for (const block of message.message.content) {
186
+ if (
187
+ block.type === 'tool_use' &&
188
+ successfulResultIds.has(block.id) &&
189
+ isRecord(block.input)
190
+ ) {
191
+ calls.push({
192
+ toolName: block.name,
193
+ input: repairDirectLocationToolInputForValidation({
194
+ toolName: block.name,
195
+ input: block.input,
196
+ messages,
197
+ }),
198
+ })
199
+ }
200
+ }
201
+ }
202
+ return calls
203
+ }
204
+
205
+ type PriorToolResult = {
206
+ readonly toolName: string
207
+ readonly content: unknown
208
+ readonly isError: boolean
209
+ readonly isStructuredFailure: boolean
210
+ }
211
+
212
+ function toolResultsSinceLatestPrompt(
213
+ messages: readonly Message[],
214
+ ): readonly PriorToolResult[] {
215
+ const startIndex = latestCitizenPromptIndex(messages)
216
+ const toolNamesByUseId = new Map<string, string>()
217
+ const results: PriorToolResult[] = []
218
+ for (const message of messages.slice(startIndex + 1)) {
219
+ if (message.type === 'assistant') {
220
+ for (const block of message.message.content) {
221
+ if (block.type === 'tool_use') {
222
+ toolNamesByUseId.set(block.id, block.name)
223
+ }
224
+ }
225
+ continue
226
+ }
227
+ if (message.type !== 'user' || !Array.isArray(message.message.content)) {
228
+ continue
229
+ }
230
+ for (const block of message.message.content) {
231
+ if (block.type !== 'tool_result') continue
232
+ const toolName = toolNamesByUseId.get(block.tool_use_id)
233
+ if (toolName === undefined) continue
234
+ results.push({
235
+ toolName,
236
+ content: block.content,
237
+ isError: block.is_error === true,
238
+ isStructuredFailure: isStructuredFailureResult(block.content),
239
+ })
240
+ }
241
+ }
242
+ return results
243
+ }
244
+
245
+ function repeatedToolUseMessage(toolName: string): string {
246
+ return `<tool_use_error>RepeatedToolUseError: Tool '${toolName}' already returned a successful result for the same effective inputs in this query loop. Use the prior tool result, or call with different parameters only if the citizen goal requires a broader follow-up.</tool_use_error>`
247
+ }
248
+
249
+ function hometaxProgressionMessage(): string {
250
+ return [
251
+ 'Hometax lookup already returned a usable simplified-tax lookup result for this citizen request.',
252
+ 'Do not repeat the same lookup before the required 본인확인, 위임, and 동의 progression.',
253
+ 'Next valid step: call the verify tool for 본인확인/위임 동의, or write a Korean needs-input answer asking for that approval.',
254
+ ].join(' ')
255
+ }
256
+
257
+ function kmaAviationRepeatMessage(kind: 'usable' | 'blocked'): string {
258
+ return kind === 'usable'
259
+ ? [
260
+ 'KMA aviation lookup already returned usable METAR evidence for this airport request.',
261
+ 'Do not repeat the decoded METAR tool in the same query loop.',
262
+ 'Use the prior aviation tool_result to answer the delay-risk question and state any remaining manual notification limitation.',
263
+ ].join(' ')
264
+ : [
265
+ 'KMA aviation lookup already returned a blocked result for this airport request.',
266
+ 'Do not retry the decoded METAR tool without new credential/configuration evidence.',
267
+ 'Write a Korean handoff answer that names the aviation weather credential limitation.',
268
+ ].join(' ')
269
+ }
270
+
271
+ function kmaOrdinaryFallbackMessage(toolName: string): string {
272
+ return [
273
+ `Do not call ${toolName} as a fallback for airport aviation weather after aviation METAR evidence exists.`,
274
+ 'Do not ask the user for KMA nx/ny grid coordinates for an airport-flight risk question.',
275
+ 'Use the aviation weather evidence already returned, or give a Korean handoff answer for official airline/airport status checks.',
276
+ ].join(' ')
277
+ }
278
+
279
+ function kmaGridRepeatMessage(toolName: string): string {
280
+ return [
281
+ 'Do not repeat ordinary KMA current or forecast tools after a missing-grid or invalid-grid result.',
282
+ `Tool ${toolName} already failed for this route/weather turn without required grid parameters.`,
283
+ 'Answer from the existing location evidence and ask for a precise district/date-time only if more weather detail is required.',
284
+ ].join(' ')
285
+ }
286
+
287
+ function locationRepeatMessage(toolName: string, query: string): string {
288
+ return [
289
+ `Location lookup ${toolName} already returned usable Kakao coordinates for "${query}" in this query loop.`,
290
+ 'Do not repeat the same location lookup.',
291
+ 'Use the prior location evidence, or call the same adapter with a different origin, destination, radius, or refined query when the citizen goal requires it.',
292
+ ].join(' ')
293
+ }
294
+
295
+ function shouldUseGenericRepeatGuard(tool: Tool, toolName: string): boolean {
296
+ return tool.inputsEquivalent !== undefined || toolName === ROOT_FIND_TOOL_NAME
297
+ }
298
+
299
+ function priorKmaAviationResultKind(
300
+ priorResults: readonly PriorToolResult[],
301
+ ): 'usable' | 'blocked' | undefined {
302
+ const aviationResult = priorResults.find(
303
+ result => result.toolName === KMA_METAR_TOOL_NAME,
304
+ )
305
+ if (aviationResult === undefined) return undefined
306
+ return aviationResult.isStructuredFailure || aviationResult.isError
307
+ ? 'blocked'
308
+ : 'usable'
309
+ }
310
+
311
+ function isKmaGridFailureResult(result: PriorToolResult): boolean {
312
+ if (!KMA_ORDINARY_WEATHER_TOOL_NAMES.has(result.toolName)) return false
313
+ const text = serializeToolResult(result.content)
314
+ return /Missing or invalid fields|LOCATE FIRST|nx\/ny|base_date|base_time/iu.test(text)
315
+ }
316
+
317
+ function createGuardToolResult(
318
+ block: ToolUseBlock,
319
+ assistantMessage: AssistantMessage,
320
+ message: string,
321
+ ): UserMessage {
322
+ return createUserMessage({
323
+ content: [
324
+ {
325
+ type: 'tool_result',
326
+ tool_use_id: block.id,
327
+ content: message,
328
+ is_error: true,
329
+ },
330
+ ],
331
+ toolUseResult: `Error: ${message}`,
332
+ sourceToolAssistantUUID: assistantMessage.uuid,
333
+ })
334
+ }
335
+
336
+ function domainRepeatGuardMessage(params: {
337
+ readonly block: ToolUseBlock
338
+ readonly input: ToolInput
339
+ readonly priorResults: readonly PriorToolResult[]
340
+ readonly successfulCalls: readonly SuccessfulToolCall[]
341
+ }): string | undefined {
342
+ if (KAKAO_LOCATION_TOOL_NAMES.has(params.block.name)) {
343
+ const query = typeof params.input.query === 'string'
344
+ ? params.input.query.trim()
345
+ : ''
346
+ if (
347
+ query.length > 0 &&
348
+ params.successfulCalls.some(call =>
349
+ KAKAO_LOCATION_TOOL_NAMES.has(call.toolName) &&
350
+ typeof call.input.query === 'string' &&
351
+ call.input.query.trim() === query
352
+ )
353
+ ) {
354
+ return locationRepeatMessage(params.block.name, query)
355
+ }
356
+ }
357
+
358
+ if (
359
+ params.block.name === HOMETAX_LOOKUP_TOOL_NAME &&
360
+ params.successfulCalls.some(call => call.toolName === HOMETAX_LOOKUP_TOOL_NAME)
361
+ ) {
362
+ return hometaxProgressionMessage()
363
+ }
364
+
365
+ if (params.block.name === KMA_METAR_TOOL_NAME) {
366
+ const kind = priorKmaAviationResultKind(params.priorResults)
367
+ return kind ? kmaAviationRepeatMessage(kind) : undefined
368
+ }
369
+
370
+ const aviationKind = priorKmaAviationResultKind(params.priorResults)
371
+ if (aviationKind !== undefined) {
372
+ if (KMA_ORDINARY_WEATHER_TOOL_NAMES.has(params.block.name)) {
373
+ return kmaOrdinaryFallbackMessage(params.block.name)
374
+ }
375
+ if (
376
+ params.block.name === ROOT_FIND_TOOL_NAME &&
377
+ typeof params.block.input.tool_id === 'string' &&
378
+ KMA_ORDINARY_WEATHER_TOOL_NAMES.has(params.block.input.tool_id)
379
+ ) {
380
+ return kmaOrdinaryFallbackMessage(params.block.input.tool_id)
381
+ }
382
+ }
383
+
384
+ if (
385
+ KMA_ORDINARY_WEATHER_TOOL_NAMES.has(params.block.name) &&
386
+ params.priorResults.some(
387
+ result =>
388
+ result.toolName === params.block.name && isKmaGridFailureResult(result),
389
+ )
390
+ ) {
391
+ return kmaGridRepeatMessage(params.block.name)
392
+ }
393
+
394
+ return undefined
395
+ }
396
+
397
+ function repairDirectLocationToolInputForValidation(params: {
398
+ readonly toolName: string
399
+ readonly input: ToolInput
400
+ readonly messages: readonly Message[]
401
+ }): ToolInput {
402
+ if (
403
+ !KAKAO_LOCATION_TOOL_NAMES.has(params.toolName) ||
404
+ (typeof params.input.query === 'string' &&
405
+ params.input.query.trim().length > 0)
406
+ ) {
407
+ return params.input
408
+ }
409
+ const query = deriveLocationQueryFromUserText(
410
+ latestCitizenPromptText(params.messages),
411
+ )
412
+ return query === undefined ? params.input : { ...params.input, query }
413
+ }
414
+
415
+ function unexplainedRepeatedToolMessage(toolName: string): string {
416
+ return `<tool_use_error>RepeatedToolUseError: Tool '${toolName}' already returned a successful result in this query loop. Before calling the same tool again with different inputs, write a visible progress sentence explaining which parameter, radius, source, or scope is changing; otherwise answer from the prior tool_result.</tool_use_error>`
417
+ }
418
+
419
+ function excessiveRepeatedToolMessage(toolName: string): string {
420
+ return `<tool_use_error>RepeatedToolUseError: Tool '${toolName}' already returned multiple successful results in this query loop. Stop calling the same effective tool again; answer from the prior tool_result set or state the remaining limitation.</tool_use_error>`
421
+ }
422
+
423
+ function hasVisibleAssistantText(message: AssistantMessage): boolean {
424
+ return message.message.content.some(
425
+ block => block.type === 'text' && block.text.trim().length > 0,
426
+ )
427
+ }
428
+
429
+ export async function runToolUseBlocks(params: {
430
+ readonly blocks: readonly ToolUseBlock[]
431
+ readonly assistantMessage: AssistantMessage
432
+ readonly messages: readonly Message[]
433
+ readonly toolUseContext: ToolUseContext
434
+ readonly canUseTool: Parameters<
435
+ ToolUseContext['options']['tools'][number]['call']
436
+ >[2]
437
+ }): Promise<readonly UserMessage[]> {
438
+ const results: UserMessage[] = []
439
+ const successfulCalls: SuccessfulToolCall[] = [
440
+ ...successfulToolCallsSinceLatestPrompt(params.messages),
441
+ ]
442
+ for (const block of params.blocks) {
443
+ const localTool = findToolByName(params.toolUseContext.options.tools, block.name)
444
+ const tool = isUnregisteredRawJsonToolUseId(block.id)
445
+ ? undefined
446
+ : localTool ?? getAdapterToolByName(block.name)
447
+ if (!tool) {
448
+ const errorPayload = createToolUnavailableErrorPayload(block.name)
449
+ const errorContent = serializeToolResult(errorPayload)
450
+ results.push(
451
+ createUserMessage({
452
+ content: [
453
+ {
454
+ type: 'tool_result',
455
+ tool_use_id: block.id,
456
+ content: errorContent,
457
+ is_error: true,
458
+ },
459
+ ],
460
+ toolUseResult: errorPayload,
461
+ sourceToolAssistantUUID: params.assistantMessage.uuid,
462
+ }),
463
+ )
464
+ continue
465
+ }
466
+
467
+ const documentRepair = repairUmmayaDocumentToolInputForDispatch({
468
+ toolName: block.name,
469
+ input: block.input,
470
+ messages: params.messages,
471
+ })
472
+ if (documentRepair.kind === 'blocked') {
473
+ results.push(
474
+ createUserMessage({
475
+ content: [
476
+ {
477
+ type: 'tool_result',
478
+ tool_use_id: block.id,
479
+ content: documentRepair.message,
480
+ is_error: true,
481
+ },
482
+ ],
483
+ toolUseResult: documentRepair.message,
484
+ sourceToolAssistantUUID: params.assistantMessage.uuid,
485
+ }),
486
+ )
487
+ continue
488
+ }
489
+ const toolUseContext = {
490
+ ...params.toolUseContext,
491
+ messages: params.messages,
492
+ }
493
+ const inputForValidation = localTool === undefined
494
+ ? documentRepair.input
495
+ : repairDirectLocationToolInputForValidation({
496
+ toolName: block.name,
497
+ input: documentRepair.input,
498
+ messages: params.messages,
499
+ })
500
+ const parsedInput = tool.inputSchema.safeParse(inputForValidation)
501
+ if (!parsedInput.success) {
502
+ const errorContent = formatZodValidationError(
503
+ block.name,
504
+ parsedInput.error,
505
+ )
506
+ results.push(
507
+ createUserMessage({
508
+ content: [
509
+ {
510
+ type: 'tool_result',
511
+ tool_use_id: block.id,
512
+ content: `<tool_use_error>InputValidationError: ${errorContent}</tool_use_error>`,
513
+ is_error: true,
514
+ },
515
+ ],
516
+ toolUseResult: `InputValidationError: ${parsedInput.error.message}`,
517
+ sourceToolAssistantUUID: params.assistantMessage.uuid,
518
+ }),
519
+ )
520
+ continue
521
+ }
522
+ const priorResults = toolResultsSinceLatestPrompt(params.messages)
523
+ const domainGuardMessage = domainRepeatGuardMessage({
524
+ block,
525
+ input: parsedInput.data,
526
+ priorResults,
527
+ successfulCalls,
528
+ })
529
+ if (domainGuardMessage !== undefined) {
530
+ results.push(
531
+ createGuardToolResult(block, params.assistantMessage, domainGuardMessage),
532
+ )
533
+ continue
534
+ }
535
+ const repeatedSuccessfulCall = successfulCalls.some(
536
+ call =>
537
+ effectiveToolKey(call.toolName, call.input) ===
538
+ effectiveToolKey(block.name, parsedInput.data) &&
539
+ toolInputsEquivalent(tool, parsedInput.data, call.input),
540
+ )
541
+ if (repeatedSuccessfulCall && shouldUseGenericRepeatGuard(tool, block.name)) {
542
+ const errorContent = repeatedToolUseMessage(block.name)
543
+ results.push(
544
+ createUserMessage({
545
+ content: [
546
+ {
547
+ type: 'tool_result',
548
+ tool_use_id: block.id,
549
+ content: errorContent,
550
+ is_error: true,
551
+ },
552
+ ],
553
+ toolUseResult: `Error: ${errorContent}`,
554
+ sourceToolAssistantUUID: params.assistantMessage.uuid,
555
+ }),
556
+ )
557
+ continue
558
+ }
559
+ const successfulCallCountForEffectiveTool = successfulCalls.filter(
560
+ call =>
561
+ effectiveToolKey(call.toolName, call.input) ===
562
+ effectiveToolKey(block.name, parsedInput.data),
563
+ ).length
564
+ if (
565
+ successfulCallCountForEffectiveTool >=
566
+ MAX_SUCCESSFUL_CALLS_PER_EFFECTIVE_TOOL &&
567
+ shouldUseGenericRepeatGuard(tool, block.name)
568
+ ) {
569
+ const errorContent = excessiveRepeatedToolMessage(block.name)
570
+ results.push(
571
+ createUserMessage({
572
+ content: [
573
+ {
574
+ type: 'tool_result',
575
+ tool_use_id: block.id,
576
+ content: errorContent,
577
+ is_error: true,
578
+ },
579
+ ],
580
+ toolUseResult: `Error: ${errorContent}`,
581
+ sourceToolAssistantUUID: params.assistantMessage.uuid,
582
+ }),
583
+ )
584
+ continue
585
+ }
586
+ const sameToolAlreadySucceeded = successfulCallCountForEffectiveTool > 0
587
+ if (
588
+ sameToolAlreadySucceeded &&
589
+ shouldUseGenericRepeatGuard(tool, block.name) &&
590
+ !hasVisibleAssistantText(params.assistantMessage)
591
+ ) {
592
+ const errorContent = unexplainedRepeatedToolMessage(block.name)
593
+ results.push(
594
+ createUserMessage({
595
+ content: [
596
+ {
597
+ type: 'tool_result',
598
+ tool_use_id: block.id,
599
+ content: errorContent,
600
+ is_error: true,
601
+ },
602
+ ],
603
+ toolUseResult: `Error: ${errorContent}`,
604
+ sourceToolAssistantUUID: params.assistantMessage.uuid,
605
+ }),
606
+ )
607
+ continue
608
+ }
609
+ const isValidCall = await tool.validateInput?.(
610
+ parsedInput.data,
611
+ toolUseContext,
612
+ )
613
+ if (isValidCall?.result === false) {
614
+ results.push(
615
+ createUserMessage({
616
+ content: [
617
+ {
618
+ type: 'tool_result',
619
+ tool_use_id: block.id,
620
+ content: `<tool_use_error>${isValidCall.message}</tool_use_error>`,
621
+ is_error: true,
622
+ },
623
+ ],
624
+ toolUseResult: `Error: ${isValidCall.message}`,
625
+ sourceToolAssistantUUID: params.assistantMessage.uuid,
626
+ }),
627
+ )
628
+ continue
629
+ }
630
+ const permissionDecision = await params.canUseTool(
631
+ tool,
632
+ parsedInput.data,
633
+ toolUseContext,
634
+ params.assistantMessage,
635
+ block.id,
636
+ )
637
+ if (permissionDecision.behavior !== 'allow') {
638
+ const errorContent = permissionErrorMessage(permissionDecision.message)
639
+ results.push(
640
+ createUserMessage({
641
+ content: [
642
+ {
643
+ type: 'tool_result',
644
+ tool_use_id: block.id,
645
+ content: errorContent,
646
+ is_error: true,
647
+ },
648
+ ],
649
+ toolUseResult: `Error: ${errorContent}`,
650
+ sourceToolAssistantUUID: params.assistantMessage.uuid,
651
+ }),
652
+ )
653
+ continue
654
+ }
655
+ const callInput = permissionDecision.updatedInput ?? parsedInput.data
656
+ const result = await tool.call(
657
+ callInput,
658
+ {
659
+ ...toolUseContext,
660
+ toolUseId: block.id,
661
+ userModified: permissionDecision.userModified ?? false,
662
+ },
663
+ params.canUseTool,
664
+ params.assistantMessage,
665
+ )
666
+ const modelData = normalizeToolResultDataForModel(block.name, result.data)
667
+ const isStructuredFailure = isStructuredFailureResult(modelData)
668
+ results.push(
669
+ createUserMessage({
670
+ content: [
671
+ {
672
+ type: 'tool_result',
673
+ tool_use_id: block.id,
674
+ content: serializeToolResult(modelData),
675
+ ...(isStructuredFailure ? { is_error: true as const } : {}),
676
+ },
677
+ ],
678
+ toolUseResult: modelData,
679
+ sourceToolAssistantUUID: params.assistantMessage.uuid,
680
+ }),
681
+ )
682
+ if (!isStructuredFailure) {
683
+ successfulCalls.push({ toolName: block.name, input: parsedInput.data })
684
+ }
685
+ }
686
+ return results
687
+ }