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,29 @@
1
+ import { createRequire } from 'node:module'
2
+ import type { ToolResultBlockParam } from '@anthropic-ai/sdk/resources/index.mjs'
3
+ import type { Out } from './schemas.js'
4
+
5
+ type BashResultRuntime = {
6
+ readonly mapBashToolResultToBlock: (
7
+ output: Out,
8
+ toolUseID: string,
9
+ ) => ToolResultBlockParam
10
+ }
11
+
12
+ const requireModule = createRequire(import.meta.url)
13
+ let cachedRuntime: BashResultRuntime | undefined
14
+
15
+ function isBashResultRuntime(value: unknown): value is BashResultRuntime {
16
+ if (typeof value !== 'object' || value === null) return false
17
+ const module = value as Partial<Record<keyof BashResultRuntime, unknown>>
18
+ return typeof module.mapBashToolResultToBlock === 'function'
19
+ }
20
+
21
+ export function loadBashResultRuntime(): BashResultRuntime {
22
+ if (cachedRuntime !== undefined) return cachedRuntime
23
+ const loaded: unknown = requireModule('./resultMapping.js')
24
+ if (!isBashResultRuntime(loaded)) {
25
+ throw new Error('Bash result module did not expose expected mapper')
26
+ }
27
+ cachedRuntime = loaded
28
+ return loaded
29
+ }
@@ -0,0 +1,83 @@
1
+ import type { ToolResultBlockParam } from '@anthropic-ai/sdk/resources/index.mjs';
2
+ import { getTaskOutputPath } from '../../utils/task/diskOutput.js';
3
+ import { buildLargeToolResultMessage, generatePreview, PREVIEW_SIZE_BYTES } from '../../utils/toolResultStorage.js';
4
+ import { buildImageToolResult } from './shellOutputUtils.js';
5
+ import type { Out } from './schemas.js';
6
+
7
+ const EOL = '\n';
8
+ const ASSISTANT_BLOCKING_BUDGET_MS = 15_000;
9
+
10
+ export function mapBashToolResultToBlock({
11
+ interrupted,
12
+ stdout,
13
+ stderr,
14
+ isImage,
15
+ backgroundTaskId,
16
+ backgroundedByUser,
17
+ assistantAutoBackgrounded,
18
+ structuredContent,
19
+ persistedOutputPath,
20
+ persistedOutputSize
21
+ }: Out, toolUseID: string): ToolResultBlockParam {
22
+ if (structuredContent && structuredContent.length > 0) {
23
+ return {
24
+ tool_use_id: toolUseID,
25
+ type: 'tool_result',
26
+ content: structuredContent
27
+ };
28
+ }
29
+ if (isImage) {
30
+ const block = buildImageToolResult(stdout, toolUseID);
31
+ if (block) return block;
32
+ }
33
+ let processedStdout = stdout;
34
+ if (stdout) {
35
+ processedStdout = stdout.replace(/^(\s*\n)+/, '').trimEnd();
36
+ }
37
+ if (persistedOutputPath) {
38
+ const preview = generatePreview(processedStdout, PREVIEW_SIZE_BYTES);
39
+ processedStdout = buildLargeToolResultMessage({
40
+ filepath: persistedOutputPath,
41
+ originalSize: persistedOutputSize ?? 0,
42
+ isJson: false,
43
+ preview: preview.preview,
44
+ hasMore: preview.hasMore
45
+ });
46
+ }
47
+ let errorMessage = stderr.trim();
48
+ if (interrupted) {
49
+ if (stderr) errorMessage += EOL;
50
+ errorMessage += '<error>Command was aborted before completion</error>';
51
+ }
52
+ const backgroundInfo = formatBackgroundInfo({
53
+ backgroundTaskId,
54
+ backgroundedByUser,
55
+ assistantAutoBackgrounded
56
+ });
57
+ return {
58
+ tool_use_id: toolUseID,
59
+ type: 'tool_result',
60
+ content: [processedStdout, errorMessage, backgroundInfo].filter(Boolean).join('\n'),
61
+ is_error: interrupted
62
+ };
63
+ }
64
+
65
+ type BackgroundInfoInput = Pick<Out, 'backgroundTaskId' | 'backgroundedByUser' | 'assistantAutoBackgrounded'>;
66
+
67
+ function formatBackgroundInfo({
68
+ backgroundTaskId,
69
+ backgroundedByUser,
70
+ assistantAutoBackgrounded
71
+ }: BackgroundInfoInput): string {
72
+ if (!backgroundTaskId) {
73
+ return '';
74
+ }
75
+ const outputPath = getTaskOutputPath(backgroundTaskId);
76
+ if (assistantAutoBackgrounded) {
77
+ return `Command exceeded the assistant-mode blocking budget (${ASSISTANT_BLOCKING_BUDGET_MS / 1000}s) and was moved to the background with ID: ${backgroundTaskId}. It is still running — you will be notified when it completes. Output is being written to: ${outputPath}. In assistant mode, delegate long-running work to a subagent or use run_in_background to keep this conversation responsive.`;
78
+ }
79
+ if (backgroundedByUser) {
80
+ return `Command was manually backgrounded by user with ID: ${backgroundTaskId}. Output is being written to: ${outputPath}`;
81
+ }
82
+ return `Command running in background with ID: ${backgroundTaskId}. Output is being written to: ${outputPath}`;
83
+ }
@@ -0,0 +1,79 @@
1
+ import { createRequire } from 'node:module'
2
+
3
+ type SandboxInput = {
4
+ readonly command?: string
5
+ readonly dangerouslyDisableSandbox?: boolean
6
+ }
7
+
8
+ type ShouldUseSandbox = (input: SandboxInput) => boolean
9
+ type ShellSandboxManager = {
10
+ readonly annotateStderrWithSandboxFailures: (
11
+ command: string,
12
+ stderr: string,
13
+ ) => string
14
+ readonly isSandboxEnabledInSettings: () => boolean
15
+ readonly areUnsandboxedCommandsAllowed: () => boolean
16
+ }
17
+
18
+ const requireModule = createRequire(import.meta.url)
19
+ let cachedShouldUseSandbox: ShouldUseSandbox | undefined
20
+ let cachedSandboxManager: ShellSandboxManager | undefined
21
+
22
+ function isSandboxModule(
23
+ value: unknown,
24
+ ): value is { readonly shouldUseSandbox: ShouldUseSandbox } {
25
+ if (typeof value !== 'object' || value === null) return false
26
+ const module = value as { readonly shouldUseSandbox?: unknown }
27
+ return typeof module.shouldUseSandbox === 'function'
28
+ }
29
+
30
+ export function shouldUseSandboxForShell(input: SandboxInput): boolean {
31
+ if (cachedShouldUseSandbox !== undefined) return cachedShouldUseSandbox(input)
32
+ const loaded: unknown = requireModule('./shouldUseSandbox.js')
33
+ if (!isSandboxModule(loaded)) {
34
+ throw new Error('Bash sandbox policy module did not expose shouldUseSandbox')
35
+ }
36
+ cachedShouldUseSandbox = loaded.shouldUseSandbox
37
+ return loaded.shouldUseSandbox(input)
38
+ }
39
+
40
+ function isSandboxAdapterModule(
41
+ value: unknown,
42
+ ): value is { readonly SandboxManager: ShellSandboxManager } {
43
+ if (typeof value !== 'object' || value === null) return false
44
+ const module = value as { readonly SandboxManager?: unknown }
45
+ if (typeof module.SandboxManager !== 'object' || module.SandboxManager === null) {
46
+ return false
47
+ }
48
+ const manager = module.SandboxManager as Partial<ShellSandboxManager>
49
+ return (
50
+ typeof manager.annotateStderrWithSandboxFailures === 'function' &&
51
+ typeof manager.isSandboxEnabledInSettings === 'function' &&
52
+ typeof manager.areUnsandboxedCommandsAllowed === 'function'
53
+ )
54
+ }
55
+
56
+ function loadSandboxManager(): ShellSandboxManager {
57
+ if (cachedSandboxManager !== undefined) return cachedSandboxManager
58
+ const loaded: unknown = requireModule('../../utils/sandbox/sandbox-adapter.js')
59
+ if (!isSandboxAdapterModule(loaded)) {
60
+ throw new Error('Sandbox adapter module did not expose SandboxManager')
61
+ }
62
+ cachedSandboxManager = loaded.SandboxManager
63
+ return loaded.SandboxManager
64
+ }
65
+
66
+ export function annotateShellStderrWithSandboxFailures(
67
+ command: string,
68
+ stderr: string,
69
+ ): string {
70
+ return loadSandboxManager().annotateStderrWithSandboxFailures(command, stderr)
71
+ }
72
+
73
+ export function isShellSandboxEnabledInSettings(): boolean {
74
+ return loadSandboxManager().isSandboxEnabledInSettings()
75
+ }
76
+
77
+ export function areUnsandboxedShellCommandsAllowed(): boolean {
78
+ return loadSandboxManager().areUnsandboxedCommandsAllowed()
79
+ }
@@ -0,0 +1,65 @@
1
+ import type { ToolResultBlockParam } from '@anthropic-ai/sdk/resources/index.mjs';
2
+ import { z } from 'zod/v4';
3
+ import { isEnvTruthy } from '../../utils/envUtils.js';
4
+ import { lazySchema } from '../../utils/lazySchema.js';
5
+ import { semanticBoolean } from '../../utils/semanticBoolean.js';
6
+ import { semanticNumber } from '../../utils/semanticNumber.js';
7
+ import { getMaxBashTimeoutMs } from '../../utils/timeouts.js';
8
+
9
+ export const isBackgroundTasksDisabled =
10
+ // eslint-disable-next-line custom-rules/no-process-env-top-level -- Intentional: schema must be defined at module load
11
+ isEnvTruthy(process.env.CLAUDE_CODE_DISABLE_BACKGROUND_TASKS);
12
+
13
+ export const fullInputSchema = lazySchema(() => z.strictObject({
14
+ command: z.string().describe('The command to execute'),
15
+ timeout: semanticNumber(z.number().optional()).describe(`Optional timeout in milliseconds (max ${getMaxBashTimeoutMs()})`),
16
+ description: z.string().optional().describe(`Clear, concise description of what this command does in active voice. Never use words like "complex" or "risk" in the description - just describe what it does.
17
+
18
+ For simple commands (git, npm, standard CLI tools), keep it brief (5-10 words):
19
+ - ls -> "List files in current directory"
20
+ - git status -> "Show working tree status"
21
+ - npm install -> "Install package dependencies"
22
+
23
+ For commands that are harder to parse at a glance (piped commands, obscure flags, etc.), add enough context to clarify what it does:
24
+ - find . -name "*.tmp" -exec rm {} \\; -> "Find and delete all .tmp files recursively"
25
+ - git reset --hard origin/main -> "Discard all local changes and match remote main"
26
+ - curl -s url | jq '.data[]' -> "Fetch JSON from URL and extract data array elements"`),
27
+ run_in_background: semanticBoolean(z.boolean().optional()).describe(`Set to true to run this command in the background. Use Read to read the output later.`),
28
+ dangerouslyDisableSandbox: semanticBoolean(z.boolean().optional()).describe('Set this to true to dangerously override sandbox mode and run commands without sandboxing.'),
29
+ _simulatedSedEdit: z.object({
30
+ filePath: z.string(),
31
+ newContent: z.string()
32
+ }).optional().describe('Internal: pre-computed sed edit result from preview')
33
+ }));
34
+
35
+ export const inputSchema = lazySchema(() => isBackgroundTasksDisabled ? fullInputSchema().omit({
36
+ run_in_background: true,
37
+ _simulatedSedEdit: true
38
+ }) : fullInputSchema().omit({
39
+ _simulatedSedEdit: true
40
+ }));
41
+
42
+ type StructuredContent = Exclude<ToolResultBlockParam['content'], string>;
43
+ const structuredContentSchema = z.custom<StructuredContent>((value): value is StructuredContent => Array.isArray(value));
44
+
45
+ export const outputSchema = lazySchema(() => z.object({
46
+ stdout: z.string().describe('The standard output of the command'),
47
+ stderr: z.string().describe('The standard error output of the command'),
48
+ rawOutputPath: z.string().optional().describe('Path to raw output file for large MCP tool outputs'),
49
+ interrupted: z.boolean().describe('Whether the command was interrupted'),
50
+ isImage: z.boolean().optional().describe('Flag to indicate if stdout contains image data'),
51
+ backgroundTaskId: z.string().optional().describe('ID of the background task if command is running in background'),
52
+ backgroundedByUser: z.boolean().optional().describe('True if the user manually backgrounded the command with Ctrl+B'),
53
+ assistantAutoBackgrounded: z.boolean().optional().describe('True if assistant-mode auto-backgrounded a long-running blocking command'),
54
+ dangerouslyDisableSandbox: z.boolean().optional().describe('Flag to indicate if sandbox mode was overridden'),
55
+ returnCodeInterpretation: z.string().optional().describe('Semantic interpretation for non-error exit codes with special meaning'),
56
+ noOutputExpected: z.boolean().optional().describe('Whether the command is expected to produce no output on success'),
57
+ structuredContent: structuredContentSchema.optional().describe('Structured content blocks'),
58
+ persistedOutputPath: z.string().optional().describe('Path to the persisted full output in tool-results dir (set when output is too large for inline)'),
59
+ persistedOutputSize: z.number().optional().describe('Total size of the output in bytes (set when output is too large for inline)')
60
+ }));
61
+
62
+ export type InputSchema = ReturnType<typeof inputSchema>;
63
+ export type BashToolInput = z.infer<ReturnType<typeof fullInputSchema>>;
64
+ export type OutputSchema = ReturnType<typeof outputSchema>;
65
+ export type Out = z.infer<OutputSchema>;
@@ -0,0 +1,59 @@
1
+ import { notifyVscodeFileUpdated } from '../../services/mcp/vscodeSdkMcp.js';
2
+ import type { ToolUseContext } from '../../Tool.js';
3
+ import type { AssistantMessage } from '../../types/message.js';
4
+ import { isENOENT } from '../../utils/errors.js';
5
+ import { detectFileEncoding, detectLineEndings, getFileModificationTime, writeTextContent } from '../../utils/file.js';
6
+ import { fileHistoryEnabled, fileHistoryTrackEdit } from '../../utils/fileHistory.js';
7
+ import { getFsImplementation } from '../../utils/fsOperations.js';
8
+ import { expandPath } from '../../utils/path.js';
9
+ import type { Out } from './schemas.js';
10
+
11
+ type SimulatedSedEditResult = {
12
+ readonly data: Out;
13
+ };
14
+
15
+ type SimulatedSedEditContext = Pick<ToolUseContext, 'readFileState' | 'updateFileHistoryState'>;
16
+
17
+ export async function applySedEdit(simulatedEdit: {
18
+ readonly filePath: string;
19
+ readonly newContent: string;
20
+ }, toolUseContext: SimulatedSedEditContext, parentMessage?: AssistantMessage): Promise<SimulatedSedEditResult> {
21
+ const { filePath, newContent } = simulatedEdit;
22
+ const absoluteFilePath = expandPath(filePath);
23
+ const fs = getFsImplementation();
24
+ const encoding = detectFileEncoding(absoluteFilePath);
25
+ let originalContent: string;
26
+ try {
27
+ originalContent = await fs.readFile(absoluteFilePath, { encoding });
28
+ } catch (error) {
29
+ if (isENOENT(error)) {
30
+ return {
31
+ data: {
32
+ stdout: '',
33
+ stderr: `sed: ${filePath}: No such file or directory\nExit code 1`,
34
+ interrupted: false
35
+ }
36
+ };
37
+ }
38
+ throw error;
39
+ }
40
+ if (fileHistoryEnabled() && parentMessage) {
41
+ await fileHistoryTrackEdit(toolUseContext.updateFileHistoryState, absoluteFilePath, parentMessage.uuid);
42
+ }
43
+ const endings = detectLineEndings(absoluteFilePath);
44
+ writeTextContent(absoluteFilePath, newContent, encoding, endings);
45
+ notifyVscodeFileUpdated(absoluteFilePath, originalContent, newContent);
46
+ toolUseContext.readFileState.set(absoluteFilePath, {
47
+ content: newContent,
48
+ timestamp: getFileModificationTime(absoluteFilePath),
49
+ offset: undefined,
50
+ limit: undefined
51
+ });
52
+ return {
53
+ data: {
54
+ stdout: '',
55
+ stderr: '',
56
+ interrupted: false
57
+ }
58
+ };
59
+ }
@@ -0,0 +1,245 @@
1
+ import { feature } from 'bun:bundle';
2
+ import * as React from 'react';
3
+ import type { SetToolJSXFn } from '../../Tool.js';
4
+ import { backgroundExistingForegroundTask, markTaskNotified, registerForeground, spawnShellTask, unregisterForeground } from '../../tasks/LocalShellTask/LocalShellTask.js';
5
+ import type { AgentId } from '../../types/ids.js';
6
+ import type { AppState } from '../../state/AppState.js';
7
+ import { getKairosActive } from '../../bootstrap/state.js';
8
+ import { logEvent } from '../../services/analytics/index.js';
9
+ import { exec } from '../../utils/Shell.js';
10
+ import type { ExecResult } from '../../utils/ShellCommand.js';
11
+ import { TaskOutput } from '../../utils/task/TaskOutput.js';
12
+ import { getDefaultTimeoutMs } from './prompt.js';
13
+ import { shouldUseSandboxForShell } from './sandboxPolicy.js';
14
+ import type { BashToolInput } from './schemas.js';
15
+ import { isBackgroundTasksDisabled } from './schemas.js';
16
+ import { getCommandTypeForLogging, isAutobackgroundingAllowed } from './commandClassification.js';
17
+ import { loadBashUI } from './uiLoader.js';
18
+
19
+ const PROGRESS_THRESHOLD_MS = 2000;
20
+ const ASSISTANT_BLOCKING_BUDGET_MS = 15_000;
21
+
22
+ export type BashExecutionProgress = {
23
+ readonly type: 'progress'; readonly output: string; readonly fullOutput: string;
24
+ readonly elapsedTimeSeconds: number; readonly totalLines: number;
25
+ readonly totalBytes?: number; readonly taskId?: string; readonly timeoutMs?: number;
26
+ };
27
+
28
+ type RunShellCommandInput = {
29
+ readonly input: BashToolInput; readonly abortController: AbortController;
30
+ readonly setAppState: (f: (prev: AppState) => AppState) => void;
31
+ readonly setToolJSX?: SetToolJSXFn; readonly preventCwdChanges?: boolean;
32
+ readonly isMainThread?: boolean; readonly toolUseId?: string; readonly agentId?: AgentId;
33
+ };
34
+
35
+ export async function* runShellCommand({
36
+ input,
37
+ abortController,
38
+ setAppState,
39
+ setToolJSX,
40
+ preventCwdChanges,
41
+ isMainThread,
42
+ toolUseId,
43
+ agentId
44
+ }: RunShellCommandInput): AsyncGenerator<BashExecutionProgress, ExecResult, void> {
45
+ const { command, description, timeout, run_in_background } = input;
46
+ const timeoutMs = timeout || getDefaultTimeoutMs();
47
+ let fullOutput = '';
48
+ let lastProgressOutput = '';
49
+ let lastTotalLines = 0;
50
+ let lastTotalBytes = 0;
51
+ let backgroundShellId: string | undefined = undefined;
52
+ let assistantAutoBackgrounded = false;
53
+ let resolveProgress: (() => void) | null = null;
54
+ function createProgressSignal(): Promise<null> {
55
+ return new Promise<null>(resolve => {
56
+ resolveProgress = () => resolve(null);
57
+ });
58
+ }
59
+ const shouldAutoBackground = !isBackgroundTasksDisabled && isAutobackgroundingAllowed(command);
60
+ const shellCommand = await exec(command, abortController.signal, 'bash', {
61
+ timeout: timeoutMs,
62
+ onProgress(lastLines, allLines, totalLines, totalBytes, isIncomplete) {
63
+ lastProgressOutput = lastLines;
64
+ fullOutput = allLines;
65
+ lastTotalLines = totalLines;
66
+ lastTotalBytes = isIncomplete ? totalBytes : 0;
67
+ const resolve = resolveProgress;
68
+ if (resolve) {
69
+ resolveProgress = null;
70
+ resolve();
71
+ }
72
+ },
73
+ preventCwdChanges,
74
+ shouldUseSandbox: shouldUseSandboxForShell(input),
75
+ shouldAutoBackground
76
+ });
77
+ const resultPromise = shellCommand.result;
78
+ async function spawnBackgroundTask(): Promise<string> {
79
+ const handle = await spawnShellTask({
80
+ command,
81
+ description: description || command,
82
+ shellCommand,
83
+ toolUseId,
84
+ agentId
85
+ }, {
86
+ abortController,
87
+ getAppState: () => {
88
+ throw new Error('getAppState not available in runShellCommand context');
89
+ },
90
+ setAppState
91
+ });
92
+ return handle.taskId;
93
+ }
94
+ function startBackgrounding(eventName: string, backgroundFn?: (shellId: string) => void): void {
95
+ if (foregroundTaskId) {
96
+ if (!backgroundExistingForegroundTask(foregroundTaskId, shellCommand, description || command, setAppState, toolUseId)) {
97
+ return;
98
+ }
99
+ backgroundShellId = foregroundTaskId;
100
+ logEvent(eventName, {
101
+ command_type: getCommandTypeForLogging(command)
102
+ });
103
+ backgroundFn?.(foregroundTaskId);
104
+ return;
105
+ }
106
+ void spawnBackgroundTask().then(shellId => {
107
+ backgroundShellId = shellId;
108
+ const resolve = resolveProgress;
109
+ if (resolve) {
110
+ resolveProgress = null;
111
+ resolve();
112
+ }
113
+ logEvent(eventName, {
114
+ command_type: getCommandTypeForLogging(command)
115
+ });
116
+ if (backgroundFn) {
117
+ backgroundFn(shellId);
118
+ }
119
+ });
120
+ }
121
+ if (shellCommand.onTimeout && shouldAutoBackground) {
122
+ shellCommand.onTimeout(backgroundFn => {
123
+ startBackgrounding('tengu_bash_command_timeout_backgrounded', backgroundFn);
124
+ });
125
+ }
126
+ if (feature('KAIROS') && getKairosActive() && isMainThread && !isBackgroundTasksDisabled && run_in_background !== true) {
127
+ setTimeout(() => {
128
+ if (shellCommand.status === 'running' && backgroundShellId === undefined) {
129
+ assistantAutoBackgrounded = true;
130
+ startBackgrounding('tengu_bash_command_assistant_auto_backgrounded');
131
+ }
132
+ }, ASSISTANT_BLOCKING_BUDGET_MS).unref();
133
+ }
134
+ if (run_in_background === true && !isBackgroundTasksDisabled) {
135
+ const shellId = await spawnBackgroundTask();
136
+ logEvent('tengu_bash_command_explicitly_backgrounded', {
137
+ command_type: getCommandTypeForLogging(command)
138
+ });
139
+ return {
140
+ stdout: '',
141
+ stderr: '',
142
+ code: 0,
143
+ interrupted: false,
144
+ backgroundTaskId: shellId
145
+ };
146
+ }
147
+ const startTime = Date.now();
148
+ let foregroundTaskId: string | undefined = undefined;
149
+ {
150
+ const initialResult = await Promise.race([resultPromise, new Promise<null>(resolve => {
151
+ const timer = setTimeout((done: (value: null) => void) => done(null), PROGRESS_THRESHOLD_MS, resolve);
152
+ timer.unref();
153
+ })]);
154
+ if (initialResult !== null) {
155
+ shellCommand.cleanup();
156
+ return initialResult;
157
+ }
158
+ if (backgroundShellId) {
159
+ return {
160
+ stdout: '',
161
+ stderr: '',
162
+ code: 0,
163
+ interrupted: false,
164
+ backgroundTaskId: backgroundShellId,
165
+ assistantAutoBackgrounded
166
+ };
167
+ }
168
+ }
169
+ TaskOutput.startPolling(shellCommand.taskOutput.taskId);
170
+ try {
171
+ while (true) {
172
+ const progressSignal = createProgressSignal();
173
+ const result = await Promise.race([resultPromise, progressSignal]);
174
+ if (result !== null) {
175
+ if (result.backgroundTaskId !== undefined) {
176
+ markTaskNotified(result.backgroundTaskId, setAppState);
177
+ const fixedResult: ExecResult = { ...result, backgroundTaskId: undefined };
178
+ const { taskOutput } = shellCommand;
179
+ if (taskOutput.stdoutToFile && !taskOutput.outputFileRedundant) {
180
+ fixedResult.outputFilePath = taskOutput.path;
181
+ fixedResult.outputFileSize = taskOutput.outputFileSize;
182
+ fixedResult.outputTaskId = taskOutput.taskId;
183
+ }
184
+ shellCommand.cleanup();
185
+ return fixedResult;
186
+ }
187
+ if (foregroundTaskId) {
188
+ unregisterForeground(foregroundTaskId, setAppState);
189
+ }
190
+ shellCommand.cleanup();
191
+ return result;
192
+ }
193
+ if (backgroundShellId) {
194
+ return {
195
+ stdout: '',
196
+ stderr: '',
197
+ code: 0,
198
+ interrupted: false,
199
+ backgroundTaskId: backgroundShellId,
200
+ assistantAutoBackgrounded
201
+ };
202
+ }
203
+ if (foregroundTaskId && shellCommand.status === 'backgrounded') {
204
+ return {
205
+ stdout: '',
206
+ stderr: '',
207
+ code: 0,
208
+ interrupted: false,
209
+ backgroundTaskId: foregroundTaskId,
210
+ backgroundedByUser: true
211
+ };
212
+ }
213
+ const elapsedSeconds = Math.floor((Date.now() - startTime) / 1000);
214
+ if (!isBackgroundTasksDisabled && backgroundShellId === undefined && elapsedSeconds >= PROGRESS_THRESHOLD_MS / 1000 && setToolJSX) {
215
+ if (!foregroundTaskId) {
216
+ foregroundTaskId = registerForeground({
217
+ command,
218
+ description: description || command,
219
+ shellCommand,
220
+ agentId
221
+ }, setAppState, toolUseId);
222
+ }
223
+ const { BackgroundHint } = loadBashUI();
224
+ setToolJSX({
225
+ jsx: <BackgroundHint />,
226
+ shouldHidePromptInput: false,
227
+ shouldContinueAnimation: true,
228
+ showSpinner: true
229
+ });
230
+ }
231
+ yield {
232
+ type: 'progress',
233
+ fullOutput,
234
+ output: lastProgressOutput,
235
+ elapsedTimeSeconds: elapsedSeconds,
236
+ totalLines: lastTotalLines,
237
+ totalBytes: lastTotalBytes,
238
+ taskId: shellCommand.taskOutput.taskId,
239
+ ...(timeout ? { timeoutMs } : undefined)
240
+ };
241
+ }
242
+ } finally {
243
+ TaskOutput.stopPolling(shellCommand.taskOutput.taskId);
244
+ }
245
+ }
@@ -0,0 +1,85 @@
1
+ import type {
2
+ Base64ImageSource,
3
+ ToolResultBlockParam,
4
+ } from '@anthropic-ai/sdk/resources/index.mjs'
5
+ import { readFile, stat } from 'fs/promises'
6
+ import { getOriginalCwd } from '../../bootstrap/state.js'
7
+ import { maybeResizeAndDownsampleImageBuffer } from '../../utils/imageResizer.js'
8
+
9
+ export function stripEmptyLines(content: string): string {
10
+ const lines = content.split('\n')
11
+ let startIndex = 0
12
+ while (startIndex < lines.length && lines[startIndex]?.trim() === '') {
13
+ startIndex++
14
+ }
15
+ let endIndex = lines.length - 1
16
+ while (endIndex >= 0 && lines[endIndex]?.trim() === '') {
17
+ endIndex--
18
+ }
19
+ if (startIndex > endIndex) return ''
20
+ return lines.slice(startIndex, endIndex + 1).join('\n')
21
+ }
22
+
23
+ export function isImageOutput(content: string): boolean {
24
+ return /^data:image\/[a-z0-9.+_-]+;base64,/i.test(content)
25
+ }
26
+
27
+ const DATA_URI_RE = /^data:([^;]+);base64,(.+)$/
28
+
29
+ function parseDataUri(
30
+ value: string,
31
+ ): { readonly mediaType: string; readonly data: string } | null {
32
+ const match = value.trim().match(DATA_URI_RE)
33
+ if (!match || !match[1] || !match[2]) return null
34
+ return { mediaType: match[1], data: match[2] }
35
+ }
36
+
37
+ export function buildImageToolResult(
38
+ stdout: string,
39
+ toolUseID: string,
40
+ ): ToolResultBlockParam | null {
41
+ const parsed = parseDataUri(stdout)
42
+ if (!parsed) return null
43
+ return {
44
+ tool_use_id: toolUseID,
45
+ type: 'tool_result',
46
+ content: [
47
+ {
48
+ type: 'image',
49
+ source: {
50
+ type: 'base64',
51
+ media_type: parsed.mediaType as Base64ImageSource['media_type'],
52
+ data: parsed.data,
53
+ },
54
+ },
55
+ ],
56
+ }
57
+ }
58
+
59
+ const MAX_IMAGE_FILE_SIZE = 20 * 1024 * 1024
60
+
61
+ export async function resizeShellImageOutput(
62
+ stdout: string,
63
+ outputFilePath: string | undefined,
64
+ outputFileSize: number | undefined,
65
+ ): Promise<string | null> {
66
+ let source = stdout
67
+ if (outputFilePath) {
68
+ const size = outputFileSize ?? (await stat(outputFilePath)).size
69
+ if (size > MAX_IMAGE_FILE_SIZE) return null
70
+ source = await readFile(outputFilePath, 'utf8')
71
+ }
72
+ const parsed = parseDataUri(source)
73
+ if (!parsed) return null
74
+ const buffer = Buffer.from(parsed.data, 'base64')
75
+ const extension = parsed.mediaType.split('/')[1] || 'png'
76
+ const resized = await maybeResizeAndDownsampleImageBuffer(
77
+ buffer,
78
+ buffer.length,
79
+ extension,
80
+ )
81
+ return `data:image/${resized.mediaType};base64,${resized.buffer.toString('base64')}`
82
+ }
83
+
84
+ export const stdErrAppendShellResetMessage = (stderr: string): string =>
85
+ `${stderr.trim()}\nShell cwd was reset to ${getOriginalCwd()}`