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,247 @@
1
+ import type { ToolResult, ToolUseContext } from '../../Tool.js'
2
+ import { isAgentSwarmsEnabled } from '../../utils/agentSwarmsEnabled.js'
3
+ import {
4
+ blockTask,
5
+ deleteTask,
6
+ getTask,
7
+ getTaskListId,
8
+ type Task,
9
+ type TaskStatus,
10
+ updateTask,
11
+ } from '../../utils/tasks.js'
12
+ import { getAgentName, getTeammateColor } from '../../utils/teammate.js'
13
+ import { writeToMailbox } from '../../utils/teammateMailbox.js'
14
+ import { buildAgentSupportMetadata } from '../AgentTool/orchestrationSupport.js'
15
+ import {
16
+ collectCompletedHookErrors,
17
+ needsVerificationNudge,
18
+ } from './completion.js'
19
+ import type { Output, TaskUpdateToolInput } from './schemas.js'
20
+
21
+ type TaskUpdates = {
22
+ subject?: string
23
+ description?: string
24
+ activeForm?: string
25
+ status?: TaskStatus
26
+ owner?: string
27
+ metadata?: Record<string, unknown>
28
+ }
29
+
30
+ function expandTaskList(context: ToolUseContext): void {
31
+ context.setAppState(prev => {
32
+ if (prev.expandedView === 'tasks') return prev
33
+ return { ...prev, expandedView: 'tasks' }
34
+ })
35
+ }
36
+
37
+ function addChangedTextField(
38
+ updates: TaskUpdates,
39
+ updatedFields: string[],
40
+ field: 'subject' | 'description' | 'activeForm' | 'owner',
41
+ nextValue: string | undefined,
42
+ currentValue: string | undefined,
43
+ ): void {
44
+ if (nextValue === undefined || nextValue === currentValue) return
45
+ updates[field] = nextValue
46
+ updatedFields.push(field)
47
+ }
48
+
49
+ function applyMetadataUpdate(
50
+ updates: TaskUpdates,
51
+ updatedFields: string[],
52
+ existingTask: Task,
53
+ metadata: Record<string, unknown> | undefined,
54
+ ): void {
55
+ if (metadata === undefined) return
56
+
57
+ const merged = { ...(existingTask.metadata ?? {}) }
58
+ for (const [key, value] of Object.entries(metadata)) {
59
+ if (value === null) {
60
+ delete merged[key]
61
+ } else {
62
+ merged[key] = value
63
+ }
64
+ }
65
+ updates.metadata = merged
66
+ updatedFields.push('metadata')
67
+ }
68
+
69
+ function applyImplicitOwner(
70
+ updates: TaskUpdates,
71
+ updatedFields: string[],
72
+ input: TaskUpdateToolInput,
73
+ existingTask: Task,
74
+ ): void {
75
+ if (
76
+ !isAgentSwarmsEnabled() ||
77
+ input.status !== 'in_progress' ||
78
+ input.owner !== undefined ||
79
+ existingTask.owner
80
+ ) {
81
+ return
82
+ }
83
+
84
+ const agentName = getAgentName()
85
+ if (!agentName) return
86
+ updates.owner = agentName
87
+ updatedFields.push('owner')
88
+ }
89
+
90
+ async function notifyNewOwner(
91
+ taskListId: string,
92
+ updates: TaskUpdates,
93
+ input: TaskUpdateToolInput,
94
+ existingTask: Task,
95
+ ): Promise<void> {
96
+ if (!updates.owner || !isAgentSwarmsEnabled()) return
97
+
98
+ const senderName = getAgentName() || 'team-lead'
99
+ const assignmentMessage = JSON.stringify({
100
+ type: 'task_assignment',
101
+ taskId: input.taskId,
102
+ subject: existingTask.subject,
103
+ description: existingTask.description,
104
+ assignedBy: senderName,
105
+ timestamp: new Date().toISOString(),
106
+ })
107
+ await writeToMailbox(
108
+ updates.owner,
109
+ {
110
+ from: senderName,
111
+ text: assignmentMessage,
112
+ timestamp: new Date().toISOString(),
113
+ color: getTeammateColor(),
114
+ },
115
+ taskListId,
116
+ )
117
+ }
118
+
119
+ async function applyDependencyUpdates(
120
+ taskListId: string,
121
+ input: TaskUpdateToolInput,
122
+ existingTask: Task,
123
+ updatedFields: string[],
124
+ ): Promise<void> {
125
+ if (input.addBlocks && input.addBlocks.length > 0) {
126
+ const newBlocks = input.addBlocks.filter(
127
+ id => !existingTask.blocks.includes(id),
128
+ )
129
+ for (const blockId of newBlocks) {
130
+ await blockTask(taskListId, input.taskId, blockId)
131
+ }
132
+ if (newBlocks.length > 0) updatedFields.push('blocks')
133
+ }
134
+
135
+ if (input.addBlockedBy && input.addBlockedBy.length > 0) {
136
+ const newBlockedBy = input.addBlockedBy.filter(
137
+ id => !existingTask.blockedBy.includes(id),
138
+ )
139
+ for (const blockerId of newBlockedBy) {
140
+ await blockTask(taskListId, blockerId, input.taskId)
141
+ }
142
+ if (newBlockedBy.length > 0) updatedFields.push('blockedBy')
143
+ }
144
+ }
145
+
146
+ function supportFailure(
147
+ input: TaskUpdateToolInput,
148
+ context: ToolUseContext,
149
+ ): Output {
150
+ return {
151
+ success: false,
152
+ taskId: input.taskId,
153
+ updatedFields: [],
154
+ error: 'Task not found',
155
+ ...buildAgentSupportMetadata({
156
+ taskId: input.taskId,
157
+ parentToolUseId: context.toolUseId,
158
+ }),
159
+ }
160
+ }
161
+
162
+ export async function callTaskUpdateTool(
163
+ input: TaskUpdateToolInput,
164
+ context: ToolUseContext,
165
+ ): Promise<ToolResult<Output>> {
166
+ const taskListId = getTaskListId()
167
+ const supportMetadata = buildAgentSupportMetadata({
168
+ taskId: input.taskId,
169
+ parentToolUseId: context.toolUseId,
170
+ })
171
+ expandTaskList(context)
172
+
173
+ const existingTask = await getTask(taskListId, input.taskId)
174
+ if (!existingTask) return { data: supportFailure(input, context) }
175
+
176
+ if (input.status === 'deleted') {
177
+ const deleted = await deleteTask(taskListId, input.taskId)
178
+ return {
179
+ data: {
180
+ success: deleted,
181
+ taskId: input.taskId,
182
+ updatedFields: deleted ? ['deleted'] : [],
183
+ error: deleted ? undefined : 'Failed to delete task',
184
+ statusChange: deleted
185
+ ? { from: existingTask.status, to: 'deleted' }
186
+ : undefined,
187
+ ...supportMetadata,
188
+ },
189
+ }
190
+ }
191
+
192
+ const updatedFields: string[] = []
193
+ const updates: TaskUpdates = {}
194
+ addChangedTextField(updates, updatedFields, 'subject', input.subject, existingTask.subject)
195
+ addChangedTextField(updates, updatedFields, 'description', input.description, existingTask.description)
196
+ addChangedTextField(updates, updatedFields, 'activeForm', input.activeForm, existingTask.activeForm)
197
+ addChangedTextField(updates, updatedFields, 'owner', input.owner, existingTask.owner)
198
+ applyImplicitOwner(updates, updatedFields, input, existingTask)
199
+ applyMetadataUpdate(updates, updatedFields, existingTask, input.metadata)
200
+
201
+ if (input.status !== undefined && input.status !== existingTask.status) {
202
+ if (input.status === 'completed') {
203
+ const blockingErrors = await collectCompletedHookErrors(
204
+ input,
205
+ context,
206
+ existingTask,
207
+ )
208
+ if (blockingErrors.length > 0) {
209
+ return {
210
+ data: {
211
+ success: false,
212
+ taskId: input.taskId,
213
+ updatedFields: [],
214
+ error: blockingErrors.join('\n'),
215
+ ...supportMetadata,
216
+ },
217
+ }
218
+ }
219
+ }
220
+ updates.status = input.status
221
+ updatedFields.push('status')
222
+ }
223
+
224
+ if (Object.keys(updates).length > 0) {
225
+ await updateTask(taskListId, input.taskId, updates)
226
+ }
227
+ await notifyNewOwner(taskListId, updates, input, existingTask)
228
+ await applyDependencyUpdates(taskListId, input, existingTask, updatedFields)
229
+
230
+ return {
231
+ data: {
232
+ success: true,
233
+ taskId: input.taskId,
234
+ updatedFields,
235
+ statusChange:
236
+ updates.status !== undefined
237
+ ? { from: existingTask.status, to: updates.status }
238
+ : undefined,
239
+ verificationNudgeNeeded: await needsVerificationNudge(
240
+ taskListId,
241
+ context,
242
+ updates,
243
+ ),
244
+ ...supportMetadata,
245
+ },
246
+ }
247
+ }
@@ -7,6 +7,7 @@ import { lazySchema } from '../../utils/lazySchema.js'
7
7
  import { isTodoV2Enabled } from '../../utils/tasks.js'
8
8
  import { TodoListSchema } from '../../utils/todo/types.js'
9
9
  import { VERIFICATION_AGENT_TYPE } from '../AgentTool/constants.js'
10
+ import { buildAgentSupportMetadata } from '../AgentTool/orchestrationSupport.js'
10
11
  import { TODO_WRITE_TOOL_NAME } from './constants.js'
11
12
  import { DESCRIPTION, PROMPT } from './prompt.js'
12
13
 
@@ -22,6 +23,10 @@ const outputSchema = lazySchema(() =>
22
23
  oldTodos: TodoListSchema().describe('The todo list before the update'),
23
24
  newTodos: TodoListSchema().describe('The todo list after the update'),
24
25
  verificationNudgeNeeded: z.boolean().optional(),
26
+ evidenceJoinKey: z.string(),
27
+ parentToolUseId: z.string(),
28
+ resumeToken: z.string(),
29
+ permissionFlow: z.literal('coordinator_parent_round_trip'),
25
30
  }),
26
31
  )
27
32
  type OutputSchema = ReturnType<typeof outputSchema>
@@ -98,18 +103,32 @@ export const TodoWriteTool = buildTool({
98
103
  oldTodos,
99
104
  newTodos: todos,
100
105
  verificationNudgeNeeded,
106
+ ...buildAgentSupportMetadata({
107
+ taskId: todoKey,
108
+ parentToolUseId: context.toolUseId,
109
+ }),
101
110
  },
102
111
  }
103
112
  },
104
- mapToolResultToToolResultBlockParam({ verificationNudgeNeeded }, toolUseID) {
113
+ mapToolResultToToolResultBlockParam(
114
+ {
115
+ verificationNudgeNeeded,
116
+ evidenceJoinKey,
117
+ parentToolUseId,
118
+ resumeToken,
119
+ permissionFlow,
120
+ },
121
+ toolUseID,
122
+ ) {
105
123
  const base = `Todos have been modified successfully. Ensure that you continue to use the todo list to track your progress. Please proceed with the current tasks if applicable`
124
+ const support = `\n\nevidence_join_key: ${evidenceJoinKey}\nparent_tool_use_id: ${parentToolUseId}\nresume_token: ${resumeToken}\npermission_flow: ${permissionFlow}`
106
125
  const nudge = verificationNudgeNeeded
107
126
  ? `\n\nNOTE: You just closed out 3+ tasks and none of them was a verification step. Before writing your final summary, spawn the verification agent (subagent_type="${VERIFICATION_AGENT_TYPE}"). You cannot self-assign PARTIAL by listing caveats in your summary \u2014 only the verifier issues a verdict.`
108
127
  : ''
109
128
  return {
110
129
  tool_use_id: toolUseID,
111
130
  type: 'tool_result',
112
- content: base + nudge,
131
+ content: base + support + nudge,
113
132
  }
114
133
  },
115
134
  } satisfies ToolDef<InputSchema, Output>)
@@ -1,305 +1,26 @@
1
1
  import type { ToolResultBlockParam } from '@anthropic-ai/sdk/resources/index.mjs'
2
- import memoize from 'lodash-es/memoize.js'
3
- import { z } from 'zod/v4'
4
2
  import {
5
3
  type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
6
4
  logEvent,
7
5
  } from '../../services/analytics/index.js'
8
- import {
9
- buildTool,
10
- findToolByName,
11
- type Tool,
12
- type ToolDef,
13
- type Tools,
14
- } from '../../Tool.js'
6
+ import { buildTool, findToolByName, type ToolDef } from '../../Tool.js'
15
7
  import { logForDebugging } from '../../utils/debug.js'
16
- import { lazySchema } from '../../utils/lazySchema.js'
17
- import { escapeRegExp } from '../../utils/stringUtils.js'
18
8
  import { isToolSearchEnabledOptimistic } from '../../utils/toolSearch.js'
9
+ import {
10
+ clearToolSearchDescriptionCache,
11
+ maybeInvalidateCache,
12
+ } from './descriptionCache.js'
13
+ import { searchToolsWithKeywords } from './keywordSearch.js'
19
14
  import { getPrompt, isDeferredTool, TOOL_SEARCH_TOOL_NAME } from './prompt.js'
15
+ import {
16
+ buildSearchResult,
17
+ makeToolReferenceContent,
18
+ } from './resultMapping.js'
19
+ import type { InputSchema, Output, OutputSchema } from './schemas.js'
20
+ import { inputSchema, outputSchema } from './schemas.js'
21
+ import { getToolSearchPool } from './searchPool.js'
20
22
 
21
- export const inputSchema = lazySchema(() =>
22
- z.object({
23
- query: z
24
- .string()
25
- .describe(
26
- 'Query to find deferred tools. Use "select:<tool_name>" for direct selection, or keywords to search.',
27
- ),
28
- max_results: z
29
- .number()
30
- .optional()
31
- .default(5)
32
- .describe('Maximum number of results to return (default: 5)'),
33
- }),
34
- )
35
- type InputSchema = ReturnType<typeof inputSchema>
36
-
37
- export const outputSchema = lazySchema(() =>
38
- z.object({
39
- matches: z.array(z.string()),
40
- query: z.string(),
41
- total_deferred_tools: z.number(),
42
- pending_mcp_servers: z.array(z.string()).optional(),
43
- }),
44
- )
45
- type OutputSchema = ReturnType<typeof outputSchema>
46
-
47
- export type Output = z.infer<OutputSchema>
48
-
49
- // Track deferred tool names to detect when cache should be cleared
50
- let cachedDeferredToolNames: string | null = null
51
-
52
- /**
53
- * Get a cache key representing the current set of deferred tools.
54
- */
55
- function getDeferredToolsCacheKey(deferredTools: Tools): string {
56
- return deferredTools
57
- .map(t => t.name)
58
- .sort()
59
- .join(',')
60
- }
61
-
62
- /**
63
- * Get tool description, memoized by tool name.
64
- * Used for keyword search scoring.
65
- */
66
- const getToolDescriptionMemoized = memoize(
67
- async (toolName: string, tools: Tools): Promise<string> => {
68
- const tool = findToolByName(tools, toolName)
69
- if (!tool) {
70
- return ''
71
- }
72
- return tool.prompt({
73
- getToolPermissionContext: async () => ({
74
- mode: 'default' as const,
75
- additionalWorkingDirectories: new Map(),
76
- alwaysAllowRules: {},
77
- alwaysDenyRules: {},
78
- alwaysAskRules: {},
79
- isBypassPermissionsModeAvailable: false,
80
- }),
81
- tools,
82
- agents: [],
83
- })
84
- },
85
- (toolName: string) => toolName,
86
- )
87
-
88
- /**
89
- * Invalidate the description cache if deferred tools have changed.
90
- */
91
- function maybeInvalidateCache(deferredTools: Tools): void {
92
- const currentKey = getDeferredToolsCacheKey(deferredTools)
93
- if (cachedDeferredToolNames !== currentKey) {
94
- logForDebugging(
95
- `ToolSearchTool: cache invalidated - deferred tools changed`,
96
- )
97
- getToolDescriptionMemoized.cache.clear?.()
98
- cachedDeferredToolNames = currentKey
99
- }
100
- }
101
-
102
- export function clearToolSearchDescriptionCache(): void {
103
- getToolDescriptionMemoized.cache.clear?.()
104
- cachedDeferredToolNames = null
105
- }
106
-
107
- /**
108
- * Build the search result output structure.
109
- */
110
- function buildSearchResult(
111
- matches: string[],
112
- query: string,
113
- totalDeferredTools: number,
114
- pendingMcpServers?: string[],
115
- ): { data: Output } {
116
- return {
117
- data: {
118
- matches,
119
- query,
120
- total_deferred_tools: totalDeferredTools,
121
- ...(pendingMcpServers && pendingMcpServers.length > 0
122
- ? { pending_mcp_servers: pendingMcpServers }
123
- : {}),
124
- },
125
- }
126
- }
127
-
128
- /**
129
- * Parse tool name into searchable parts.
130
- * Handles both MCP tools (mcp__server__action) and regular tools (CamelCase).
131
- */
132
- function parseToolName(name: string): {
133
- parts: string[]
134
- full: string
135
- isMcp: boolean
136
- } {
137
- // Check if it's an MCP tool
138
- if (name.startsWith('mcp__')) {
139
- const withoutPrefix = name.replace(/^mcp__/, '').toLowerCase()
140
- const parts = withoutPrefix.split('__').flatMap(p => p.split('_'))
141
- return {
142
- parts: parts.filter(Boolean),
143
- full: withoutPrefix.replace(/__/g, ' ').replace(/_/g, ' '),
144
- isMcp: true,
145
- }
146
- }
147
-
148
- // Regular tool - split by CamelCase and underscores
149
- const parts = name
150
- .replace(/([a-z])([A-Z])/g, '$1 $2') // CamelCase to spaces
151
- .replace(/_/g, ' ')
152
- .toLowerCase()
153
- .split(/\s+/)
154
- .filter(Boolean)
155
-
156
- return {
157
- parts,
158
- full: parts.join(' '),
159
- isMcp: false,
160
- }
161
- }
162
-
163
- /**
164
- * Pre-compile word-boundary regexes for all search terms.
165
- * Called once per search instead of tools×terms×2 times.
166
- */
167
- function compileTermPatterns(terms: string[]): Map<string, RegExp> {
168
- const patterns = new Map<string, RegExp>()
169
- for (const term of terms) {
170
- if (!patterns.has(term)) {
171
- patterns.set(term, new RegExp(`\\b${escapeRegExp(term)}\\b`))
172
- }
173
- }
174
- return patterns
175
- }
176
-
177
- /**
178
- * Keyword-based search over tool names and descriptions.
179
- * Handles both MCP tools (mcp__server__action) and regular tools (CamelCase).
180
- *
181
- * The model typically queries with:
182
- * - Server names when it knows the integration (e.g., "slack", "github")
183
- * - Action words when looking for functionality (e.g., "read", "list", "create")
184
- * - Tool-specific terms (e.g., "notebook", "shell", "kill")
185
- */
186
- async function searchToolsWithKeywords(
187
- query: string,
188
- deferredTools: Tools,
189
- tools: Tools,
190
- maxResults: number,
191
- ): Promise<string[]> {
192
- const queryLower = query.toLowerCase().trim()
193
-
194
- // Fast path: if query matches a tool name exactly, return it directly.
195
- // Handles models using a bare tool name instead of select: prefix (seen
196
- // from subagents/post-compaction). Checks deferred first, then falls back
197
- // to the full tool set — selecting an already-loaded tool is a harmless
198
- // no-op that lets the model proceed without retry churn.
199
- const exactMatch =
200
- deferredTools.find(t => t.name.toLowerCase() === queryLower) ??
201
- tools.find(t => t.name.toLowerCase() === queryLower)
202
- if (exactMatch) {
203
- return [exactMatch.name]
204
- }
205
-
206
- // If query looks like an MCP tool prefix (mcp__server), find matching tools.
207
- // Handles models searching by server name with mcp__ prefix.
208
- if (queryLower.startsWith('mcp__') && queryLower.length > 5) {
209
- const prefixMatches = deferredTools
210
- .filter(t => t.name.toLowerCase().startsWith(queryLower))
211
- .slice(0, maxResults)
212
- .map(t => t.name)
213
- if (prefixMatches.length > 0) {
214
- return prefixMatches
215
- }
216
- }
217
-
218
- const queryTerms = queryLower.split(/\s+/).filter(term => term.length > 0)
219
-
220
- // Partition into required (+prefixed) and optional terms
221
- const requiredTerms: string[] = []
222
- const optionalTerms: string[] = []
223
- for (const term of queryTerms) {
224
- if (term.startsWith('+') && term.length > 1) {
225
- requiredTerms.push(term.slice(1))
226
- } else {
227
- optionalTerms.push(term)
228
- }
229
- }
230
-
231
- const allScoringTerms =
232
- requiredTerms.length > 0 ? [...requiredTerms, ...optionalTerms] : queryTerms
233
- const termPatterns = compileTermPatterns(allScoringTerms)
234
-
235
- // Pre-filter to tools matching ALL required terms in name or description
236
- let candidateTools = deferredTools
237
- if (requiredTerms.length > 0) {
238
- const matches = await Promise.all(
239
- deferredTools.map(async tool => {
240
- const parsed = parseToolName(tool.name)
241
- const description = await getToolDescriptionMemoized(tool.name, tools)
242
- const descNormalized = description.toLowerCase()
243
- const hintNormalized = tool.searchHint?.toLowerCase() ?? ''
244
- const matchesAll = requiredTerms.every(term => {
245
- const pattern = termPatterns.get(term)!
246
- return (
247
- parsed.parts.includes(term) ||
248
- parsed.parts.some(part => part.includes(term)) ||
249
- pattern.test(descNormalized) ||
250
- (hintNormalized && pattern.test(hintNormalized))
251
- )
252
- })
253
- return matchesAll ? tool : null
254
- }),
255
- )
256
- candidateTools = matches.filter((t): t is Tool => t !== null)
257
- }
258
-
259
- const scored = await Promise.all(
260
- candidateTools.map(async tool => {
261
- const parsed = parseToolName(tool.name)
262
- const description = await getToolDescriptionMemoized(tool.name, tools)
263
- const descNormalized = description.toLowerCase()
264
- const hintNormalized = tool.searchHint?.toLowerCase() ?? ''
265
-
266
- let score = 0
267
- for (const term of allScoringTerms) {
268
- const pattern = termPatterns.get(term)!
269
-
270
- // Exact part match (high weight for MCP server names, tool name parts)
271
- if (parsed.parts.includes(term)) {
272
- score += parsed.isMcp ? 12 : 10
273
- } else if (parsed.parts.some(part => part.includes(term))) {
274
- score += parsed.isMcp ? 6 : 5
275
- }
276
-
277
- // Full name fallback (for edge cases)
278
- if (parsed.full.includes(term) && score === 0) {
279
- score += 3
280
- }
281
-
282
- // searchHint match — curated capability phrase, higher signal than prompt
283
- if (hintNormalized && pattern.test(hintNormalized)) {
284
- score += 4
285
- }
286
-
287
- // Description match - use word boundary to avoid false positives
288
- if (pattern.test(descNormalized)) {
289
- score += 2
290
- }
291
- }
292
-
293
- return { name: tool.name, score }
294
- }),
295
- )
296
-
297
- return scored
298
- .filter(item => item.score > 0)
299
- .sort((a, b) => b.score - a.score)
300
- .slice(0, maxResults)
301
- .map(item => item.name)
302
- }
23
+ export { clearToolSearchDescriptionCache }
303
24
 
304
25
  export const ToolSearchTool = buildTool({
305
26
  isEnabled() {
@@ -328,7 +49,8 @@ export const ToolSearchTool = buildTool({
328
49
  async call(input, { options: { tools }, getAppState }) {
329
50
  const { query, max_results = 5 } = input
330
51
 
331
- const deferredTools = tools.filter(isDeferredTool)
52
+ const searchableTools = await getToolSearchPool(tools, getAppState, query)
53
+ const deferredTools = searchableTools.filter(isDeferredTool)
332
54
  maybeInvalidateCache(deferredTools)
333
55
 
334
56
  // Check for MCP servers still connecting
@@ -362,7 +84,7 @@ export const ToolSearchTool = buildTool({
362
84
  // is a harmless no-op that lets the model proceed without retry churn.
363
85
  const selectMatch = query.match(/^select:(.+)$/i)
364
86
  if (selectMatch) {
365
- const requested = selectMatch[1]!
87
+ const requested = (selectMatch[1] ?? '')
366
88
  .split(',')
367
89
  .map(s => s.trim())
368
90
  .filter(Boolean)
@@ -372,7 +94,7 @@ export const ToolSearchTool = buildTool({
372
94
  for (const toolName of requested) {
373
95
  const tool =
374
96
  findToolByName(deferredTools, toolName) ??
375
- findToolByName(tools, toolName)
97
+ findToolByName(searchableTools, toolName)
376
98
  if (tool) {
377
99
  if (!found.includes(tool.name)) found.push(tool.name)
378
100
  } else {
@@ -409,7 +131,7 @@ export const ToolSearchTool = buildTool({
409
131
  const matches = await searchToolsWithKeywords(
410
132
  query,
411
133
  deferredTools,
412
- tools,
134
+ searchableTools,
413
135
  max_results,
414
136
  )
415
137
 
@@ -462,10 +184,7 @@ export const ToolSearchTool = buildTool({
462
184
  return {
463
185
  type: 'tool_result',
464
186
  tool_use_id: toolUseID,
465
- content: content.matches.map(name => ({
466
- type: 'tool_reference' as const,
467
- tool_name: name,
468
- })),
469
- } as unknown as ToolResultBlockParam
187
+ content: makeToolReferenceContent(content.matches),
188
+ }
470
189
  },
471
190
  } satisfies ToolDef<InputSchema, Output>)