ummaya 0.2.3 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (534) hide show
  1. package/README.md +17 -3
  2. package/bin/ummaya +10 -1
  3. package/npm-shrinkwrap.json +253 -2
  4. package/package.json +5 -1
  5. package/prompts/manifest.yaml +2 -2
  6. package/prompts/session_guidance_v1.md +3 -1
  7. package/prompts/system_v1.md +9 -7
  8. package/pyproject.toml +26 -7
  9. package/specs/2803-document-production-hardening/contracts/document-tools.schema.json +1043 -0
  10. package/src/ummaya/_canonical/__init__.py +2 -0
  11. package/src/ummaya/context/builder.py +17 -11
  12. package/src/ummaya/engine/engine.py +30 -113
  13. package/src/ummaya/engine/query.py +20 -0
  14. package/src/ummaya/evidence/__init__.py +44 -0
  15. package/src/ummaya/evidence/__main__.py +7 -0
  16. package/src/ummaya/evidence/dataset_contract.py +193 -0
  17. package/src/ummaya/evidence/document_authoring_cases.py +33 -0
  18. package/src/ummaya/evidence/document_harness.py +313 -0
  19. package/src/ummaya/evidence/document_viewer_ux.py +391 -0
  20. package/src/ummaya/evidence/gates.py +70 -0
  21. package/src/ummaya/evidence/json_types.py +20 -0
  22. package/src/ummaya/evidence/models.py +145 -0
  23. package/src/ummaya/evidence/output_payload.py +89 -0
  24. package/src/ummaya/evidence/payload_documents.py +233 -0
  25. package/src/ummaya/evidence/route_contracts.py +224 -0
  26. package/src/ummaya/evidence/route_helpers.py +150 -0
  27. package/src/ummaya/evidence/runner.py +177 -0
  28. package/src/ummaya/evidence/source_provenance.py +246 -0
  29. package/src/ummaya/evidence/source_provenance_redaction.py +176 -0
  30. package/src/ummaya/evidence/task_registry.py +264 -0
  31. package/src/ummaya/evidence/tool_layer.py +39 -0
  32. package/src/ummaya/evidence/tool_layer_models.py +151 -0
  33. package/src/ummaya/ipc/adapter_manifest_emitter.py +26 -10
  34. package/src/ummaya/ipc/document_intent_normalization.py +185 -0
  35. package/src/ummaya/ipc/frame_schema.py +52 -5
  36. package/src/ummaya/ipc/route_diagnostics.py +73 -0
  37. package/src/ummaya/ipc/stdio.py +2282 -417
  38. package/src/ummaya/llm/client.py +234 -59
  39. package/src/ummaya/llm/config.py +8 -3
  40. package/src/ummaya/llm/reasoning.py +84 -0
  41. package/src/ummaya/primitives/__init__.py +6 -2
  42. package/src/ummaya/primitives/delegation.py +1 -1
  43. package/src/ummaya/primitives/document.py +28 -0
  44. package/src/ummaya/settings.py +0 -3
  45. package/src/ummaya/tools/discovery_bridge.py +34 -2
  46. package/src/ummaya/tools/documents/__init__.py +297 -0
  47. package/src/ummaya/tools/documents/adapter_registry.py +487 -0
  48. package/src/ummaya/tools/documents/archive_container_probe.py +167 -0
  49. package/src/ummaya/tools/documents/artifact_store.py +454 -0
  50. package/src/ummaya/tools/documents/authoring.py +283 -0
  51. package/src/ummaya/tools/documents/baselines.py +114 -0
  52. package/src/ummaya/tools/documents/capability.py +331 -0
  53. package/src/ummaya/tools/documents/contracts.py +112 -0
  54. package/src/ummaya/tools/documents/conversion.py +521 -0
  55. package/src/ummaya/tools/documents/diff.py +275 -0
  56. package/src/ummaya/tools/documents/engines.py +163 -0
  57. package/src/ummaya/tools/documents/evaluation.py +291 -0
  58. package/src/ummaya/tools/documents/explicit_values.py +108 -0
  59. package/src/ummaya/tools/documents/fixtures.py +174 -0
  60. package/src/ummaya/tools/documents/format_completion_audit.py +471 -0
  61. package/src/ummaya/tools/documents/formats/__init__.py +2 -0
  62. package/src/ummaya/tools/documents/formats/archive.py +528 -0
  63. package/src/ummaya/tools/documents/formats/base.py +41 -0
  64. package/src/ummaya/tools/documents/formats/code_file.py +211 -0
  65. package/src/ummaya/tools/documents/formats/data_file.py +272 -0
  66. package/src/ummaya/tools/documents/formats/hwp.py +284 -0
  67. package/src/ummaya/tools/documents/formats/hwpx.py +1837 -0
  68. package/src/ummaya/tools/documents/formats/odf.py +435 -0
  69. package/src/ummaya/tools/documents/formats/ooxml.py +1030 -0
  70. package/src/ummaya/tools/documents/formats/passive.py +766 -0
  71. package/src/ummaya/tools/documents/formats/pdf.py +702 -0
  72. package/src/ummaya/tools/documents/formats/text_web.py +268 -0
  73. package/src/ummaya/tools/documents/hwp_conversion_probe.py +178 -0
  74. package/src/ummaya/tools/documents/hwp_direct_candidate.py +141 -0
  75. package/src/ummaya/tools/documents/inspection.py +289 -0
  76. package/src/ummaya/tools/documents/intake.py +1079 -0
  77. package/src/ummaya/tools/documents/legacy_office_promotion_probe.py +366 -0
  78. package/src/ummaya/tools/documents/models.py +1598 -0
  79. package/src/ummaya/tools/documents/odf_promotion_probe.py +167 -0
  80. package/src/ummaya/tools/documents/orchestrator.py +96 -0
  81. package/src/ummaya/tools/documents/passive_capability_probe.py +251 -0
  82. package/src/ummaya/tools/documents/patch.py +170 -0
  83. package/src/ummaya/tools/documents/pdfa_conformance.py +284 -0
  84. package/src/ummaya/tools/documents/pdfa_promotion_probe.py +198 -0
  85. package/src/ummaya/tools/documents/permissions.py +110 -0
  86. package/src/ummaya/tools/documents/planner.py +616 -0
  87. package/src/ummaya/tools/documents/registry.py +2733 -0
  88. package/src/ummaya/tools/documents/render.py +978 -0
  89. package/src/ummaya/tools/documents/render_comparison.py +113 -0
  90. package/src/ummaya/tools/documents/render_comparison_models.py +74 -0
  91. package/src/ummaya/tools/documents/render_comparison_regions.py +73 -0
  92. package/src/ummaya/tools/documents/render_comparison_style.py +161 -0
  93. package/src/ummaya/tools/documents/reread.py +157 -0
  94. package/src/ummaya/tools/documents/runtime_authoring.py +244 -0
  95. package/src/ummaya/tools/documents/runtime_authoring_bundle.py +76 -0
  96. package/src/ummaya/tools/documents/scorecard.py +184 -0
  97. package/src/ummaya/tools/documents/socratic_planner.py +193 -0
  98. package/src/ummaya/tools/documents/style.py +48 -0
  99. package/src/ummaya/tools/documents/tool_defs.py +523 -0
  100. package/src/ummaya/tools/documents/validate.py +347 -0
  101. package/src/ummaya/tools/executor.py +61 -12
  102. package/src/ummaya/tools/geocoding/kakao_client.py +1 -2
  103. package/src/ummaya/tools/kma/apihub_catalog.py +984 -1
  104. package/src/ummaya/tools/kma/apihub_structured_adapter.py +86 -6
  105. package/src/ummaya/tools/kma/apihub_url_adapter.py +593 -0
  106. package/src/ummaya/tools/kma/apihub_url_catalog.py +296 -0
  107. package/src/ummaya/tools/live_proxy.py +0 -3
  108. package/src/ummaya/tools/location_adapters.py +8 -6
  109. package/src/ummaya/tools/manifest_metadata.py +16 -3
  110. package/src/ummaya/tools/models.py +5 -1
  111. package/src/ummaya/tools/mvp_surface.py +2 -2
  112. package/src/ummaya/tools/nmc/emergency_search.py +8 -6
  113. package/src/ummaya/tools/register_all.py +17 -0
  114. package/src/ummaya/tools/registry.py +10 -1
  115. package/src/ummaya/tools/resolve_location.py +4 -4
  116. package/src/ummaya/tools/routing/__init__.py +59 -0
  117. package/src/ummaya/tools/routing/builder.py +105 -0
  118. package/src/ummaya/tools/routing/cards.py +29 -0
  119. package/src/ummaya/tools/routing/decision_service.py +534 -0
  120. package/src/ummaya/tools/routing/decision_types.py +74 -0
  121. package/src/ummaya/tools/routing/feasibility.py +122 -0
  122. package/src/ummaya/tools/routing/intent.py +17 -0
  123. package/src/ummaya/tools/routing/intent_extractor.py +207 -0
  124. package/src/ummaya/tools/routing/intent_patterns.py +160 -0
  125. package/src/ummaya/tools/routing/intent_public_data.py +150 -0
  126. package/src/ummaya/tools/routing/intent_types.py +48 -0
  127. package/src/ummaya/tools/routing/lint.py +78 -0
  128. package/src/ummaya/tools/routing/metadata.py +174 -0
  129. package/src/ummaya/tools/routing/projection.py +340 -0
  130. package/src/ummaya/tools/routing/retrieval_policy.py +629 -0
  131. package/src/ummaya/tools/routing/schema.py +81 -0
  132. package/src/ummaya/tools/routing/types.py +96 -0
  133. package/src/ummaya/tools/routing_index.py +2 -2
  134. package/src/ummaya/tools/search.py +40 -106
  135. package/src/ummaya/tools/verified_data_go_kr/_manifest.py +115 -25
  136. package/src/ummaya/tools/verified_data_go_kr/airkorea_air_quality.py +109 -4
  137. package/src/ummaya/tools/verified_data_go_kr/nmc_aed_site.py +108 -2
  138. package/src/ummaya/tools/verified_data_go_kr/pps_bid_public_info.py +174 -9
  139. package/src/ummaya/tools/verified_data_go_kr/tago_bus_arrival.py +66 -3
  140. package/src/ummaya/tools/verified_data_go_kr/tago_bus_location.py +12 -2
  141. package/src/ummaya/tools/verified_data_go_kr/tago_bus_route.py +8 -2
  142. package/src/ummaya/tools/verified_data_go_kr/tago_bus_route_station.py +114 -0
  143. package/src/ummaya/tools/verified_data_go_kr/tago_bus_station.py +14 -3
  144. package/src/ummaya/tools/verify_canonical_map.py +21 -0
  145. package/tests/fixtures/documents/public_forms/baselines.yaml +113 -0
  146. package/tui/package.json +1 -2
  147. package/tui/src/.cc-byte-identical-whitelist.yaml +266 -0
  148. package/tui/src/QueryEngine.ts +12 -4
  149. package/tui/src/bridge/inboundAttachments.ts +3 -3
  150. package/tui/src/cli/handlers/auth.ts +4 -13
  151. package/tui/src/cli/handlers/mcp.tsx +3 -3
  152. package/tui/src/cli/print.ts +69 -18
  153. package/tui/src/cli/update.ts +13 -13
  154. package/tui/src/commands/copy/index.ts +1 -1
  155. package/tui/src/commands/cost/cost.ts +2 -2
  156. package/tui/src/commands/init-verifiers.ts +5 -5
  157. package/tui/src/commands/init.ts +30 -30
  158. package/tui/src/commands/insights.ts +44 -44
  159. package/tui/src/commands/install-github-app/install-github-app.tsx +2 -2
  160. package/tui/src/commands/install-github-app/setupGitHubActions.ts +3 -3
  161. package/tui/src/commands/install-github-app/types.ts +8 -30
  162. package/tui/src/commands/install.tsx +5 -5
  163. package/tui/src/commands/mcp/addCommand.ts +5 -5
  164. package/tui/src/commands/mcp/xaaIdpCommand.ts +2 -2
  165. package/tui/src/commands/plugin/ManageMarketplaces.tsx +2 -2
  166. package/tui/src/commands/plugin/types.ts +6 -28
  167. package/tui/src/commands/plugin/unifiedTypes.ts +4 -26
  168. package/tui/src/commands/reasoning/index.ts +13 -0
  169. package/tui/src/commands/reasoning/reasoning.tsx +177 -0
  170. package/tui/src/commands/rename/generateSessionName.ts +1 -1
  171. package/tui/src/commands/thinkback/thinkback.tsx +3 -3
  172. package/tui/src/commands.ts +2 -0
  173. package/tui/src/components/Feedback.tsx +1 -1
  174. package/tui/src/components/LogoV2/EmergencyTip.tsx +11 -2
  175. package/tui/src/components/LogoV2/WelcomeV2.tsx +1 -3
  176. package/tui/src/components/Messages.tsx +2 -1
  177. package/tui/src/components/ScrollKeybindingHandler.tsx +6 -6
  178. package/tui/src/components/Spinner/types.ts +6 -28
  179. package/tui/src/components/Spinner.tsx +2 -2
  180. package/tui/src/components/agents/generateAgent.ts +1 -1
  181. package/tui/src/components/agents/new-agent-creation/types.ts +4 -26
  182. package/tui/src/components/config/EnvSecretIsolatedEditor.tsx +1 -1
  183. package/tui/src/components/design-system/LoadingState.tsx +2 -2
  184. package/tui/src/components/mcp/types.ts +16 -38
  185. package/tui/src/components/messages/AssistantToolUseMessage.tsx +3 -2
  186. package/tui/src/components/messages/UserCrossSessionMessage.ts +16 -4
  187. package/tui/src/components/messages/UserForkBoilerplateMessage.ts +16 -4
  188. package/tui/src/components/messages/UserGitHubWebhookMessage.ts +16 -4
  189. package/tui/src/components/messages/UserToolResultMessage/utils.tsx +3 -2
  190. package/tui/src/components/permissions/MonitorPermissionRequest/MonitorPermissionRequest.ts +9 -4
  191. package/tui/src/components/permissions/ReviewArtifactPermissionRequest/ReviewArtifactPermissionRequest.ts +9 -4
  192. package/tui/src/components/primitive/DocumentSocraticReviewBlock.tsx +129 -0
  193. package/tui/src/components/primitive/DocumentToolResultCard.tsx +224 -0
  194. package/tui/src/components/primitive/documentSocraticReview.ts +215 -0
  195. package/tui/src/components/primitive/index.tsx +43 -1
  196. package/tui/src/components/primitive/types.ts +137 -0
  197. package/tui/src/components/ui/option.ts +4 -26
  198. package/tui/src/constants/common.ts +0 -2
  199. package/tui/src/constants/prompts.ts +4 -3
  200. package/tui/src/constants/querySource.ts +4 -26
  201. package/tui/src/entrypoints/sdk/controlTypes.ts +26 -48
  202. package/tui/src/entrypoints/sdk/coreTypes.generated.ts +3 -25
  203. package/tui/src/entrypoints/sdk/runtimeTypes.ts +38 -60
  204. package/tui/src/entrypoints/sdk/sdkUtilityTypes.ts +4 -26
  205. package/tui/src/entrypoints/sdk/settingsTypes.generated.ts +3 -25
  206. package/tui/src/entrypoints/sdk/toolTypes.ts +3 -25
  207. package/tui/src/hooks/toolPermission/handlers/interactiveHandler.ts +10 -0
  208. package/tui/src/hooks/useApiKeyVerification.ts +1 -1
  209. package/tui/src/hooks/useVirtualScroll.ts +1 -1
  210. package/tui/src/ink/ink.tsx +33 -14
  211. package/tui/src/ink/reconciler.ts +2 -3
  212. package/tui/src/ink/render-to-screen.ts +30 -10
  213. package/tui/src/ipc/bridge.ts +62 -15
  214. package/tui/src/ipc/bridgeSingleton.ts +5 -1
  215. package/tui/src/ipc/codec.ts +29 -3
  216. package/tui/src/ipc/frames.generated.ts +407 -312
  217. package/tui/src/ipc/llmClient.ts +279 -76
  218. package/tui/src/ipc/llmTypes.ts +16 -1
  219. package/tui/src/ipc/schema/frame.schema.json +1 -3475
  220. package/tui/src/keybindings/defaultBindings.ts +4 -0
  221. package/tui/src/main.tsx +32 -11
  222. package/tui/src/native-ts/file-index/index.ts +33 -3
  223. package/tui/src/observability/surface.ts +2 -2
  224. package/tui/src/probes/toolRegistryProbe.tsx +3 -1
  225. package/tui/src/projectOnboardingState.ts +7 -6
  226. package/tui/src/query/chatMessageTypes.ts +18 -0
  227. package/tui/src/query/chatMessagesBuilder.ts +1 -1
  228. package/tui/src/query/deps.ts +1 -1
  229. package/tui/src/query/messageGuards.ts +106 -0
  230. package/tui/src/query/publicDataTerminalRepair.ts +384 -0
  231. package/tui/src/query/run.ts +1075 -0
  232. package/tui/src/query/supportBoundary.ts +168 -0
  233. package/tui/src/query/toolResultErrors.ts +103 -0
  234. package/tui/src/query/toolRunner.ts +687 -0
  235. package/tui/src/query/unavailableToolRepair.ts +118 -0
  236. package/tui/src/query.ts +9 -1721
  237. package/tui/src/screens/REPL.tsx +42 -31
  238. package/tui/src/services/api/adapterManifest.ts +4 -0
  239. package/tui/src/services/api/backendChat/events.ts +117 -0
  240. package/tui/src/services/api/backendChat/finalMessage.ts +40 -0
  241. package/tui/src/services/api/backendChat/frame.ts +9 -0
  242. package/tui/src/services/api/backendChat/streaming.ts +430 -0
  243. package/tui/src/services/api/backendChat/types.ts +62 -0
  244. package/tui/src/services/api/backendChat.ts +1 -0
  245. package/tui/src/services/api/client.ts +98 -14
  246. package/tui/src/services/api/errorUtils.ts +5 -5
  247. package/tui/src/services/api/errors.ts +1 -1
  248. package/tui/src/services/api/logging.ts +1 -1
  249. package/tui/src/services/api/ummaya/evidence.ts +194 -0
  250. package/tui/src/services/api/ummaya/messages.ts +255 -0
  251. package/tui/src/services/api/ummaya/nonStreaming.ts +66 -0
  252. package/tui/src/services/api/ummaya/provider.ts +200 -0
  253. package/tui/src/services/api/ummaya/reasoning.ts +24 -0
  254. package/tui/src/services/api/ummaya/request.ts +200 -0
  255. package/tui/src/services/api/ummaya/selectionContext.ts +240 -0
  256. package/tui/src/services/api/ummaya/streaming.ts +365 -0
  257. package/tui/src/services/api/ummaya/streamingPayload.ts +129 -0
  258. package/tui/src/services/api/ummaya/streamingReader.ts +40 -0
  259. package/tui/src/services/api/ummaya/toolSelection.ts +217 -0
  260. package/tui/src/services/api/ummaya/types.ts +110 -0
  261. package/tui/src/services/api/ummaya/usage.ts +30 -0
  262. package/tui/src/services/api/ummaya.ts +26 -364
  263. package/tui/src/services/api/withRetry.ts +1 -1
  264. package/tui/src/services/awaySummary.ts +2 -2
  265. package/tui/src/services/claudeAiLimits.ts +1 -1
  266. package/tui/src/services/compact/autoCompact.ts +1 -1
  267. package/tui/src/services/compact/compact.ts +1 -1
  268. package/tui/src/services/lsp/types.ts +8 -30
  269. package/tui/src/services/tips/types.ts +6 -28
  270. package/tui/src/services/tokenEstimation.ts +1 -1
  271. package/tui/src/services/toolRegistry/bootGuard.ts +5 -5
  272. package/tui/src/services/toolUseSummary/toolUseSummaryGenerator.ts +1 -1
  273. package/tui/src/services/tools/toolExecution.ts +94 -1
  274. package/tui/src/skills/bundled/stuck.ts +12 -12
  275. package/tui/src/state/AppStateStore.ts +7 -0
  276. package/tui/src/store/pendingPermissionSlot.ts +1 -1
  277. package/tui/src/store/session-store.ts +10 -36
  278. package/tui/src/stubs/any-stub.ts +15 -10
  279. package/tui/src/stubs/color-diff-napi.ts +37 -23
  280. package/tui/src/stubs/globals.d.ts +3 -3
  281. package/tui/src/stubs/macro-preload.ts +23 -12
  282. package/tui/src/tools/AdapterTool/AdapterTool.ts +1239 -163
  283. package/tui/src/tools/AdapterTool/routeDiagnostics.ts +75 -0
  284. package/tui/src/tools/AgentTool/AgentTool.tsx +84 -1371
  285. package/tui/src/tools/AgentTool/agentToolHandoff.ts +114 -0
  286. package/tui/src/tools/AgentTool/agentToolPartialResult.ts +16 -0
  287. package/tui/src/tools/AgentTool/agentToolProgress.ts +32 -0
  288. package/tui/src/tools/AgentTool/agentToolResolver.ts +161 -0
  289. package/tui/src/tools/AgentTool/agentToolResult.ts +163 -0
  290. package/tui/src/tools/AgentTool/agentToolUtils.ts +14 -686
  291. package/tui/src/tools/AgentTool/asyncAgentLifecycle.ts +208 -0
  292. package/tui/src/tools/AgentTool/asyncLifecycle.ts +153 -0
  293. package/tui/src/tools/AgentTool/backgroundedCompletion.ts +126 -0
  294. package/tui/src/tools/AgentTool/backgroundedLifecycle.ts +174 -0
  295. package/tui/src/tools/AgentTool/foregroundBackground.ts +83 -0
  296. package/tui/src/tools/AgentTool/foregroundDrain.tsx +133 -0
  297. package/tui/src/tools/AgentTool/foregroundFinalize.ts +98 -0
  298. package/tui/src/tools/AgentTool/foregroundLifecycle.tsx +237 -0
  299. package/tui/src/tools/AgentTool/foregroundProgress.tsx +169 -0
  300. package/tui/src/tools/AgentTool/foregroundTask.ts +89 -0
  301. package/tui/src/tools/AgentTool/forkSubagent.ts +1 -12
  302. package/tui/src/tools/AgentTool/forkSubagentGate.ts +34 -0
  303. package/tui/src/tools/AgentTool/launchRouting.ts +203 -0
  304. package/tui/src/tools/AgentTool/lifecycle.ts +244 -0
  305. package/tui/src/tools/AgentTool/mcpRouting.ts +73 -0
  306. package/tui/src/tools/AgentTool/orchestrationSupport.ts +70 -0
  307. package/tui/src/tools/AgentTool/permissions.ts +39 -0
  308. package/tui/src/tools/AgentTool/promptSetup.ts +181 -0
  309. package/tui/src/tools/AgentTool/remoteRouting.ts +62 -0
  310. package/tui/src/tools/AgentTool/resultMapping.ts +116 -0
  311. package/tui/src/tools/AgentTool/resumeAgent.ts +39 -107
  312. package/tui/src/tools/AgentTool/resumeAgentHelpers.ts +140 -0
  313. package/tui/src/tools/AgentTool/runAgent.ts +1 -1
  314. package/tui/src/tools/AgentTool/runtimeConfig.ts +57 -0
  315. package/tui/src/tools/AgentTool/schemas.ts +196 -0
  316. package/tui/src/tools/AgentTool/sourceVerificationPropagation.ts +263 -0
  317. package/tui/src/tools/AgentTool/worktreeLifecycle.ts +105 -0
  318. package/tui/src/tools/AskUserQuestionTool/AskUserQuestionTool.tsx +174 -202
  319. package/tui/src/tools/BashTool/BashTool.tsx +71 -1072
  320. package/tui/src/tools/BashTool/bashCommandHelpers.ts +12 -12
  321. package/tui/src/tools/BashTool/bashPermissions/astPreflight.ts +173 -0
  322. package/tui/src/tools/BashTool/bashPermissions/classifierChecks.ts +199 -0
  323. package/tui/src/tools/BashTool/bashPermissions/compoundGuards.ts +53 -0
  324. package/tui/src/tools/BashTool/bashPermissions/constants.ts +99 -0
  325. package/tui/src/tools/BashTool/bashPermissions/index.ts +38 -0
  326. package/tui/src/tools/BashTool/bashPermissions/legacyMisparsing.ts +62 -0
  327. package/tui/src/tools/BashTool/bashPermissions/main.ts +135 -0
  328. package/tui/src/tools/BashTool/bashPermissions/normalizedCommands.ts +33 -0
  329. package/tui/src/tools/BashTool/bashPermissions/operatorFlow.ts +98 -0
  330. package/tui/src/tools/BashTool/bashPermissions/permissionChecks.ts +200 -0
  331. package/tui/src/tools/BashTool/bashPermissions/prefixSuggestions.ts +88 -0
  332. package/tui/src/tools/BashTool/bashPermissions/promptClassifierRules.ts +125 -0
  333. package/tui/src/tools/BashTool/bashPermissions/ruleDelegates.ts +19 -0
  334. package/tui/src/tools/BashTool/bashPermissions/ruleMatching.ts +145 -0
  335. package/tui/src/tools/BashTool/bashPermissions/sandboxAutoAllow.ts +75 -0
  336. package/tui/src/tools/BashTool/bashPermissions/subcommandFlow.ts +205 -0
  337. package/tui/src/tools/BashTool/bashPermissions/subcommandGuards.ts +73 -0
  338. package/tui/src/tools/BashTool/bashPermissions/subcommandResultHelpers.ts +116 -0
  339. package/tui/src/tools/BashTool/bashPermissions/types.ts +26 -0
  340. package/tui/src/tools/BashTool/bashPermissions/wrapperStripping.ts +139 -0
  341. package/tui/src/tools/BashTool/bashPermissions.ts +26 -2621
  342. package/tui/src/tools/BashTool/call.ts +202 -0
  343. package/tui/src/tools/BashTool/callLoader.ts +35 -0
  344. package/tui/src/tools/BashTool/commandClassification.ts +151 -0
  345. package/tui/src/tools/BashTool/commandClassificationLoader.ts +40 -0
  346. package/tui/src/tools/BashTool/cwdReset.ts +33 -0
  347. package/tui/src/tools/BashTool/lineTruncation.ts +11 -0
  348. package/tui/src/tools/BashTool/modeValidation.ts +13 -1
  349. package/tui/src/tools/BashTool/outputPersistence.ts +42 -0
  350. package/tui/src/tools/BashTool/permissionClassification.ts +66 -0
  351. package/tui/src/tools/BashTool/permissionLoader.ts +44 -0
  352. package/tui/src/tools/BashTool/resultLoader.ts +29 -0
  353. package/tui/src/tools/BashTool/resultMapping.ts +83 -0
  354. package/tui/src/tools/BashTool/sandboxPolicy.ts +79 -0
  355. package/tui/src/tools/BashTool/schemas.ts +65 -0
  356. package/tui/src/tools/BashTool/sedEditExecution.ts +59 -0
  357. package/tui/src/tools/BashTool/shellExecution.tsx +245 -0
  358. package/tui/src/tools/BashTool/shellOutputUtils.ts +85 -0
  359. package/tui/src/tools/BashTool/shellPermissionGauntlet.ts +97 -0
  360. package/tui/src/tools/BashTool/uiLoader.ts +37 -0
  361. package/tui/src/tools/BriefTool/upload.ts +1 -1
  362. package/tui/src/tools/CalculatorTool/parser.ts +2 -2
  363. package/tui/src/tools/DocumentPrimitive/DocumentPrimitive.ts +262 -0
  364. package/tui/src/tools/DocumentPrimitive/dispatchNormalization.ts +270 -0
  365. package/tui/src/tools/DocumentPrimitive/documentDestinationPath.ts +18 -0
  366. package/tui/src/tools/DocumentPrimitive/documentMutationGuard.ts +22 -0
  367. package/tui/src/tools/DocumentPrimitive/documentPatchNormalization.ts +248 -0
  368. package/tui/src/tools/DocumentPrimitive/documentSourceVerification.ts +245 -0
  369. package/tui/src/tools/DocumentPrimitive/documentSourceVerificationFields.ts +103 -0
  370. package/tui/src/tools/DocumentPrimitive/modelVisibleOutput.ts +40 -0
  371. package/tui/src/tools/DocumentPrimitive/prompt.ts +35 -0
  372. package/tui/src/tools/FileEditTool/FileEditTool.ts +9 -507
  373. package/tui/src/tools/FileEditTool/call.ts +228 -0
  374. package/tui/src/tools/FileEditTool/validateInput.ts +196 -0
  375. package/tui/src/tools/FileReadTool/imageProcessor.ts +13 -0
  376. package/tui/src/tools/FileWriteTool/FileWriteTool.ts +7 -300
  377. package/tui/src/tools/FileWriteTool/call.ts +223 -0
  378. package/tui/src/tools/FileWriteTool/validateInput.ts +80 -0
  379. package/tui/src/tools/ListMcpResourcesTool/ListMcpResourcesTool.ts +19 -3
  380. package/tui/src/tools/LookupPrimitive/LookupPrimitive.ts +48 -29
  381. package/tui/src/tools/LookupPrimitive/prompt.ts +6 -7
  382. package/tui/src/tools/MCPTool/trustPolicy.ts +118 -0
  383. package/tui/src/tools/McpAuthTool/McpAuthTool.ts +21 -3
  384. package/tui/src/tools/NotebookEditTool/NotebookEditTool.ts +7 -326
  385. package/tui/src/tools/NotebookEditTool/call.ts +254 -0
  386. package/tui/src/tools/NotebookEditTool/notebookModel.ts +51 -0
  387. package/tui/src/tools/NotebookEditTool/validateInput.ts +142 -0
  388. package/tui/src/tools/PowerShellTool/PowerShellTool.tsx +46 -937
  389. package/tui/src/tools/PowerShellTool/acceptEditsCommandValidation.ts +162 -0
  390. package/tui/src/tools/PowerShellTool/call.ts +179 -0
  391. package/tui/src/tools/PowerShellTool/callLoader.ts +37 -0
  392. package/tui/src/tools/PowerShellTool/commandClassification.ts +86 -0
  393. package/tui/src/tools/PowerShellTool/modeValidation.ts +25 -332
  394. package/tui/src/tools/PowerShellTool/outputPersistence.ts +42 -0
  395. package/tui/src/tools/PowerShellTool/permissionClassification.ts +28 -0
  396. package/tui/src/tools/PowerShellTool/resultLoader.ts +31 -0
  397. package/tui/src/tools/PowerShellTool/resultMapping.ts +75 -0
  398. package/tui/src/tools/PowerShellTool/schemas.ts +40 -0
  399. package/tui/src/tools/PowerShellTool/shellExecution.tsx +258 -0
  400. package/tui/src/tools/PowerShellTool/symlinkModeValidation.ts +44 -0
  401. package/tui/src/tools/PowerShellTool/uiLoader.ts +37 -0
  402. package/tui/src/tools/PowerShellTool/validation.ts +39 -0
  403. package/tui/src/tools/ReadMcpResourceTool/ReadMcpResourceTool.ts +19 -3
  404. package/tui/src/tools/ResolveLocationPrimitive/ResolveLocationPrimitive.ts +30 -19
  405. package/tui/src/tools/ResolveLocationPrimitive/prompt.ts +2 -6
  406. package/tui/src/tools/SkillTool/SkillTool.ts +2 -2
  407. package/tui/src/tools/SubmitPrimitive/SubmitPrimitive.ts +51 -18
  408. package/tui/src/tools/TaskCreateTool/TaskCreateTool.ts +16 -2
  409. package/tui/src/tools/TaskGetTool/TaskGetTool.ts +23 -3
  410. package/tui/src/tools/TaskListTool/TaskListTool.ts +22 -4
  411. package/tui/src/tools/TaskOutputTool/TaskOutputTool.tsx +46 -547
  412. package/tui/src/tools/TaskOutputTool/lookup.ts +216 -0
  413. package/tui/src/tools/TaskOutputTool/render.tsx +257 -0
  414. package/tui/src/tools/TaskOutputTool/schemas.ts +55 -0
  415. package/tui/src/tools/TaskOutputTool/serialization.ts +36 -0
  416. package/tui/src/tools/TaskStopTool/TaskStopTool.ts +10 -0
  417. package/tui/src/tools/TaskUpdateTool/TaskUpdateTool.ts +14 -364
  418. package/tui/src/tools/TaskUpdateTool/completion.ts +62 -0
  419. package/tui/src/tools/TaskUpdateTool/schemas.ts +62 -0
  420. package/tui/src/tools/TaskUpdateTool/serialization.ts +46 -0
  421. package/tui/src/tools/TaskUpdateTool/statusUpdate.ts +247 -0
  422. package/tui/src/tools/TodoWriteTool/TodoWriteTool.ts +21 -2
  423. package/tui/src/tools/ToolSearchTool/ToolSearchTool.ts +21 -302
  424. package/tui/src/tools/ToolSearchTool/ccSupportTools.ts +223 -0
  425. package/tui/src/tools/ToolSearchTool/descriptionCache.ts +50 -0
  426. package/tui/src/tools/ToolSearchTool/keywordSearch.ts +216 -0
  427. package/tui/src/tools/ToolSearchTool/prompt.ts +10 -4
  428. package/tui/src/tools/ToolSearchTool/resultMapping.ts +30 -0
  429. package/tui/src/tools/ToolSearchTool/schemas.ts +30 -0
  430. package/tui/src/tools/ToolSearchTool/searchPool.ts +47 -0
  431. package/tui/src/tools/ToolSearchTool/supportIntentHints.ts +140 -0
  432. package/tui/src/tools/TranslateTool/TranslateTool.ts +1 -1
  433. package/tui/src/tools/VerifyPrimitive/VerifyPrimitive.ts +27 -10
  434. package/tui/src/tools/WebFetchTool/WebFetchTool.ts +43 -138
  435. package/tui/src/tools/WebFetchTool/call.ts +227 -0
  436. package/tui/src/tools/WebFetchTool/resolvedAddressSafety.ts +78 -0
  437. package/tui/src/tools/WebFetchTool/sourceVerification.ts +204 -0
  438. package/tui/src/tools/WebFetchTool/types.ts +23 -0
  439. package/tui/src/tools/WebFetchTool/urlSafety.ts +181 -0
  440. package/tui/src/tools/WebFetchTool/utils.ts +1 -1
  441. package/tui/src/tools/WebSearchTool/UI.tsx +0 -1
  442. package/tui/src/tools/WebSearchTool/WebSearchTool.ts +9 -313
  443. package/tui/src/tools/WebSearchTool/call.ts +33 -0
  444. package/tui/src/tools/WebSearchTool/responseMapping.ts +190 -0
  445. package/tui/src/tools/WebSearchTool/resultBlock.ts +47 -0
  446. package/tui/src/tools/WebSearchTool/schemas.ts +47 -0
  447. package/tui/src/tools/WebSearchTool/toolSchema.ts +12 -0
  448. package/tui/src/tools/WorkspaceToolAdapter/WorkspaceToolAdapter.ts +79 -0
  449. package/tui/src/tools/WorkspaceToolAdapter/allowedRootPolicy.ts +85 -0
  450. package/tui/src/tools/WorkspaceToolAdapter/documentFormatGuards.ts +73 -0
  451. package/tui/src/tools/WorkspaceToolAdapter/inputNormalization.ts +105 -0
  452. package/tui/src/tools/WorkspaceToolAdapter/mcpExposurePolicy.ts +64 -0
  453. package/tui/src/tools/WorkspaceToolAdapter/toolDefFactory.ts +215 -0
  454. package/tui/src/tools/WorkspaceToolAdapter/toolNames.ts +6 -0
  455. package/tui/src/tools/WorkspaceToolAdapter/workspacePolicy.ts +15 -0
  456. package/tui/src/tools/_shared/citizenUserText.ts +49 -0
  457. package/tui/src/tools/_shared/dispatchPrimitive.ts +6 -6
  458. package/tui/src/tools/_shared/documentChangeToPatch.ts +125 -0
  459. package/tui/src/tools/_shared/documentDispatchArguments.ts +87 -0
  460. package/tui/src/tools/_shared/documentPrimitiveTimeout.ts +13 -0
  461. package/tui/src/tools/_shared/documentToolResultRender.ts +98 -0
  462. package/tui/src/tools/_shared/locationInputRepair.ts +112 -0
  463. package/tui/src/tools/_shared/pendingCallRegistry.ts +1 -6
  464. package/tui/src/tools/_shared/rootPrimitiveInput.ts +68 -0
  465. package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPatterns.ts +58 -0
  466. package/tui/src/tools/_shared/toolChoiceRepair/documentCompletionPrompt.ts +271 -0
  467. package/tui/src/tools/_shared/toolChoiceRepair/documentRepair.ts +452 -0
  468. package/tui/src/tools/_shared/toolChoiceRepair/messageAccess.ts +80 -0
  469. package/tui/src/tools/_shared/toolChoiceRepair/publicDataRepair.ts +92 -0
  470. package/tui/src/tools/_shared/toolChoiceRepair/supportRepair.ts +135 -0
  471. package/tui/src/tools/_shared/toolChoiceRepair.ts +61 -0
  472. package/tui/src/tools/shared/mockDisclaimer.ts +1 -1
  473. package/tui/src/tools.ts +39 -190
  474. package/tui/src/types/fileSuggestion.ts +4 -26
  475. package/tui/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +186 -148
  476. package/tui/src/types/generated/events_mono/common/v1/auth.ts +25 -11
  477. package/tui/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +47 -30
  478. package/tui/src/types/generated/google/protobuf/timestamp.ts +21 -7
  479. package/tui/src/types/message.ts +80 -102
  480. package/tui/src/types/messageQueueTypes.ts +6 -28
  481. package/tui/src/types/notebook.ts +16 -38
  482. package/tui/src/types/statusLine.ts +4 -26
  483. package/tui/src/types/tools.ts +24 -46
  484. package/tui/src/types/utils.ts +6 -28
  485. package/tui/src/upstreamproxy/relay.ts +7 -3
  486. package/tui/src/upstreamproxy/upstreamproxy.ts +1 -1
  487. package/tui/src/utils/assistantMessageFactories.ts +9 -3
  488. package/tui/src/utils/attachments.ts +1 -1
  489. package/tui/src/utils/auth.ts +129 -139
  490. package/tui/src/utils/bash/ast.ts +23 -23
  491. package/tui/src/utils/bash/bashParser.ts +5 -5
  492. package/tui/src/utils/billing.ts +1 -1
  493. package/tui/src/utils/collapseReadSearch.ts +3 -3
  494. package/tui/src/utils/cronTasks.ts +1 -1
  495. package/tui/src/utils/execFileNoThrow.ts +1 -1
  496. package/tui/src/utils/filePersistence/types.ts +16 -38
  497. package/tui/src/utils/forkedAgent.ts +1 -1
  498. package/tui/src/utils/gracefulShutdown.ts +4 -4
  499. package/tui/src/utils/heapDumpService.ts +12 -8
  500. package/tui/src/utils/hooks/apiQueryHookHelper.ts +1 -1
  501. package/tui/src/utils/hooks/execPromptHook.ts +1 -1
  502. package/tui/src/utils/hooks/skillImprovement.ts +1 -1
  503. package/tui/src/utils/kExaoneReasoning.ts +138 -0
  504. package/tui/src/utils/mcp/dateTimeParser.ts +1 -1
  505. package/tui/src/utils/messages.ts +19 -0
  506. package/tui/src/utils/migrateSessions.ts +3 -3
  507. package/tui/src/utils/model/model.ts +6 -6
  508. package/tui/src/utils/multiToolLayout.ts +13 -0
  509. package/tui/src/utils/permissions/yoloClassifier.ts +1 -1
  510. package/tui/src/utils/plugins/headlessPluginInstall.ts +1 -1
  511. package/tui/src/utils/plugins/mcpPluginIntegration.ts +1 -1
  512. package/tui/src/utils/plugins/mcpbHandler.ts +1 -1
  513. package/tui/src/utils/plugins/pluginLoader.ts +8 -8
  514. package/tui/src/utils/processUserInput/processSlashCommand.tsx +2 -2
  515. package/tui/src/utils/processUserInput/processUserInput.ts +26 -0
  516. package/tui/src/utils/protectedNamespace.ts +5 -3
  517. package/tui/src/utils/rawJsonToolCall.ts +242 -0
  518. package/tui/src/utils/ripgrep.ts +16 -7
  519. package/tui/src/utils/sessionTitle.ts +1 -1
  520. package/tui/src/utils/settings/applySettingsChange.ts +4 -0
  521. package/tui/src/utils/settings/permissionValidation.ts +14 -2
  522. package/tui/src/utils/settings/types.ts +9 -3
  523. package/tui/src/utils/shell/prefix.ts +1 -1
  524. package/tui/src/utils/sideQuery.ts +1 -1
  525. package/tui/src/utils/stats.ts +1 -1
  526. package/tui/src/utils/systemThemeWatcher.ts +13 -3
  527. package/tui/src/utils/teleport.tsx +1 -1
  528. package/uv.lock +394 -22
  529. package/assets/copilot-gate-logo.svg +0 -58
  530. package/assets/govon-logo.svg +0 -40
  531. package/src/ummaya/eval/__init__.py +0 -5
  532. package/src/ummaya/eval/retrieval.py +0 -713
  533. package/tui/src/services/api/claude.ts +0 -3510
  534. package/tui/src/utils/messageStream.ts +0 -186
@@ -0,0 +1,202 @@
1
+ import type { CanUseToolFn } from 'src/hooks/useCanUseTool.js';
2
+ import { type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, logEvent } from '../../services/analytics/index.js';
3
+ import type { ToolCallProgress, ToolUseContext } from '../../Tool.js';
4
+ import type { AssistantMessage } from '../../types/message.js';
5
+ import type { BashProgress } from '../../types/tools.js';
6
+ import { extractClaudeCodeHints } from '../../utils/claudeCodeHints.js';
7
+ import { detectCodeIndexingFromCommand } from '../../utils/codeIndexing.js';
8
+ import { ShellError } from '../../utils/errors.js';
9
+ import { EndTruncatingAccumulator } from '../../utils/stringUtils.js';
10
+ import { maybeRecordPluginHint } from '../../utils/plugins/hintRecommendation.js';
11
+ import type { ExecResult } from '../../utils/ShellCommand.js';
12
+ import { resetShellCwdIfOutsideProject } from './cwdReset.js';
13
+ import { resizeShellImageOutput, stdErrAppendShellResetMessage, stripEmptyLines, isImageOutput } from './shellOutputUtils.js';
14
+ import { interpretCommandResult } from './commandSemantics.js';
15
+ import { trackGitOperations } from '../shared/gitOperationTracking.js';
16
+ import { runShellCommand } from './shellExecution.js';
17
+ import { persistLargeShellOutput } from './outputPersistence.js';
18
+ import { applySedEdit } from './sedEditExecution.js';
19
+ import { isSilentBashCommand } from './commandClassification.js';
20
+ import type { BashToolInput, Out } from './schemas.js';
21
+ import { annotateShellStderrWithSandboxFailures } from './sandboxPolicy.js';
22
+
23
+ const EOL = '\n';
24
+
25
+ export async function callBashTool(
26
+ input: BashToolInput,
27
+ toolUseContext: ToolUseContext,
28
+ _canUseTool?: CanUseToolFn,
29
+ parentMessage?: AssistantMessage,
30
+ onProgress?: ToolCallProgress<BashProgress>
31
+ ): Promise<{ readonly data: Out }> {
32
+ if (input._simulatedSedEdit) {
33
+ return applySedEdit(input._simulatedSedEdit, toolUseContext, parentMessage);
34
+ }
35
+ const { abortController, getAppState, setAppState, setToolJSX } = toolUseContext;
36
+ const stdoutAccumulator = new EndTruncatingAccumulator();
37
+ let stderrForShellReset = '';
38
+ let interpretationResult: ReturnType<typeof interpretCommandResult> | undefined;
39
+ let wasInterrupted = false;
40
+ const isMainThread = !toolUseContext.agentId;
41
+ const preventCwdChanges = !isMainThread;
42
+ const { execResult } = await consumeBashCommand({
43
+ input,
44
+ toolUseContext,
45
+ preventCwdChanges,
46
+ isMainThread,
47
+ onProgress
48
+ });
49
+ try {
50
+ trackGitOperations(input.command, execResult.code, execResult.stdout);
51
+ const isInterrupt = execResult.interrupted && abortController.signal.reason === 'interrupt';
52
+ stdoutAccumulator.append((execResult.stdout || '').trimEnd() + EOL);
53
+ interpretationResult = interpretCommandResult(input.command, execResult.code, execResult.stdout || '', '');
54
+ if (execResult.stdout && execResult.stdout.includes(".git/index.lock': File exists")) {
55
+ logEvent('tengu_git_index_lock_error', {});
56
+ }
57
+ if (interpretationResult.isError && !isInterrupt && execResult.code !== 0) {
58
+ stdoutAccumulator.append(`Exit code ${execResult.code}`);
59
+ }
60
+ if (!preventCwdChanges) {
61
+ const appState = getAppState();
62
+ if (resetShellCwdIfOutsideProject(appState.toolPermissionContext)) {
63
+ stderrForShellReset = stdErrAppendShellResetMessage('');
64
+ }
65
+ }
66
+ const outputWithSbFailures = annotateShellStderrWithSandboxFailures(input.command, execResult.stdout || '');
67
+ if (execResult.preSpawnError) {
68
+ throw new Error(execResult.preSpawnError);
69
+ }
70
+ if (interpretationResult.isError && !isInterrupt) {
71
+ throw new ShellError('', outputWithSbFailures, execResult.code, execResult.interrupted);
72
+ }
73
+ wasInterrupted = execResult.interrupted;
74
+ } finally {
75
+ if (setToolJSX) setToolJSX(null);
76
+ }
77
+ const stdout = stdoutAccumulator.toString();
78
+ const persisted = await persistLargeShellOutput(execResult);
79
+ logShellExecution(input.command, stdout, execResult.code, wasInterrupted);
80
+ let strippedStdout = stripEmptyLines(stdout);
81
+ const extracted = extractClaudeCodeHints(strippedStdout, input.command);
82
+ strippedStdout = extracted.stripped;
83
+ if (isMainThread && extracted.hints.length > 0) {
84
+ for (const hint of extracted.hints) maybeRecordPluginHint(hint);
85
+ }
86
+ const imageResult = await normalizeImageOutput(strippedStdout, execResult.outputFilePath, persisted.size);
87
+ return {
88
+ data: {
89
+ stdout: imageResult.stdout,
90
+ stderr: stderrForShellReset,
91
+ interrupted: wasInterrupted,
92
+ isImage: imageResult.isImage,
93
+ returnCodeInterpretation: interpretationResult?.message,
94
+ noOutputExpected: isSilentBashCommand(input.command),
95
+ backgroundTaskId: execResult.backgroundTaskId,
96
+ backgroundedByUser: execResult.backgroundedByUser,
97
+ assistantAutoBackgrounded: execResult.assistantAutoBackgrounded,
98
+ dangerouslyDisableSandbox: 'dangerouslyDisableSandbox' in input ? input.dangerouslyDisableSandbox : undefined,
99
+ persistedOutputPath: persisted.path,
100
+ persistedOutputSize: persisted.size
101
+ }
102
+ };
103
+ }
104
+
105
+ type ConsumeInput = {
106
+ readonly input: BashToolInput;
107
+ readonly toolUseContext: ToolUseContext;
108
+ readonly preventCwdChanges: boolean;
109
+ readonly isMainThread: boolean;
110
+ readonly onProgress?: ToolCallProgress<BashProgress>;
111
+ };
112
+
113
+ type ConsumeResult = {
114
+ readonly execResult: ExecResult;
115
+ };
116
+
117
+ async function consumeBashCommand({
118
+ input,
119
+ toolUseContext,
120
+ preventCwdChanges,
121
+ isMainThread,
122
+ onProgress
123
+ }: ConsumeInput): Promise<ConsumeResult> {
124
+ const commandGenerator = runShellCommand({
125
+ input,
126
+ abortController: toolUseContext.abortController,
127
+ setAppState: toolUseContext.setAppStateForTasks ?? toolUseContext.setAppState,
128
+ setToolJSX: toolUseContext.setToolJSX,
129
+ preventCwdChanges,
130
+ isMainThread,
131
+ toolUseId: toolUseContext.toolUseId,
132
+ agentId: toolUseContext.agentId
133
+ });
134
+ let progressCounter = 0;
135
+ let generatorResult;
136
+ do {
137
+ generatorResult = await commandGenerator.next();
138
+ if (!generatorResult.done && onProgress) {
139
+ const progress = generatorResult.value;
140
+ onProgress({
141
+ toolUseID: `bash-progress-${progressCounter++}`,
142
+ data: {
143
+ type: 'bash_progress',
144
+ output: progress.output,
145
+ fullOutput: progress.fullOutput,
146
+ elapsedTimeSeconds: progress.elapsedTimeSeconds,
147
+ totalLines: progress.totalLines,
148
+ totalBytes: progress.totalBytes,
149
+ taskId: progress.taskId,
150
+ timeoutMs: progress.timeoutMs
151
+ }
152
+ });
153
+ }
154
+ } while (!generatorResult.done);
155
+ return {
156
+ execResult: generatorResult.value
157
+ };
158
+ }
159
+
160
+ function logShellExecution(command: string, stdout: string, code: number, interrupted: boolean): void {
161
+ const commandType = command.split(' ')[0];
162
+ logEvent('tengu_bash_tool_command_executed', {
163
+ command_type: commandType as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
164
+ stdout_length: stdout.length,
165
+ stderr_length: 0,
166
+ exit_code: code,
167
+ interrupted
168
+ });
169
+ const codeIndexingTool = detectCodeIndexingFromCommand(command);
170
+ if (codeIndexingTool) {
171
+ logEvent('tengu_code_indexing_tool_used', {
172
+ tool: codeIndexingTool as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
173
+ source: 'cli' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
174
+ success: code === 0
175
+ });
176
+ }
177
+ }
178
+
179
+ type ImageOutput = {
180
+ readonly stdout: string;
181
+ readonly isImage: boolean;
182
+ };
183
+
184
+ async function normalizeImageOutput(stdout: string, outputFilePath?: string, persistedOutputSize?: number): Promise<ImageOutput> {
185
+ if (!isImageOutput(stdout)) {
186
+ return {
187
+ stdout,
188
+ isImage: false
189
+ };
190
+ }
191
+ const resized = await resizeShellImageOutput(stdout, outputFilePath, persistedOutputSize);
192
+ if (resized) {
193
+ return {
194
+ stdout: resized,
195
+ isImage: true
196
+ };
197
+ }
198
+ return {
199
+ stdout,
200
+ isImage: false
201
+ };
202
+ }
@@ -0,0 +1,35 @@
1
+ import { createRequire } from 'node:module'
2
+ import type { CanUseToolFn } from 'src/hooks/useCanUseTool.js'
3
+ import type { ToolCallProgress, ToolUseContext } from '../../Tool.js'
4
+ import type { AssistantMessage } from '../../types/message.js'
5
+ import type { BashProgress } from '../../types/tools.js'
6
+ import type { BashToolInput, Out } from './schemas.js'
7
+
8
+ type BashCallRuntime = {
9
+ readonly callBashTool: (
10
+ input: BashToolInput,
11
+ toolUseContext: ToolUseContext,
12
+ canUseTool?: CanUseToolFn,
13
+ parentMessage?: AssistantMessage,
14
+ onProgress?: ToolCallProgress<BashProgress>,
15
+ ) => Promise<{ readonly data: Out }>
16
+ }
17
+
18
+ const requireModule = createRequire(import.meta.url)
19
+ let cachedRuntime: BashCallRuntime | undefined
20
+
21
+ function isBashCallRuntime(value: unknown): value is BashCallRuntime {
22
+ if (typeof value !== 'object' || value === null) return false
23
+ const module = value as Partial<Record<keyof BashCallRuntime, unknown>>
24
+ return typeof module.callBashTool === 'function'
25
+ }
26
+
27
+ export function loadBashCallRuntime(): BashCallRuntime {
28
+ if (cachedRuntime !== undefined) return cachedRuntime
29
+ const loaded: unknown = requireModule('./call.js')
30
+ if (!isBashCallRuntime(loaded)) {
31
+ throw new Error('Bash call module did not expose expected lifecycle')
32
+ }
33
+ cachedRuntime = loaded
34
+ return loaded
35
+ }
@@ -0,0 +1,151 @@
1
+ import type { AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS } from '../../services/analytics/index.js';
2
+ import { splitCommand_DEPRECATED, splitCommandWithOperators } from '../../utils/bash/commands.js';
3
+
4
+ const BASH_SEARCH_COMMANDS = new Set(['find', 'grep', 'rg', 'ag', 'ack', 'locate', 'which', 'whereis']);
5
+ const BASH_READ_COMMANDS = new Set(['cat', 'head', 'tail', 'less', 'more', 'wc', 'stat', 'file', 'strings', 'jq', 'awk', 'cut', 'sort', 'uniq', 'tr']);
6
+ const BASH_LIST_COMMANDS = new Set(['ls', 'tree', 'du']);
7
+ const BASH_SEMANTIC_NEUTRAL_COMMANDS = new Set(['echo', 'printf', 'true', 'false', ':']);
8
+ const BASH_SILENT_COMMANDS = new Set(['mv', 'cp', 'rm', 'mkdir', 'rmdir', 'chmod', 'chown', 'chgrp', 'touch', 'ln', 'cd', 'export', 'unset', 'wait']);
9
+ const DISALLOWED_AUTO_BACKGROUND_COMMANDS = ['sleep'];
10
+ const COMMON_BACKGROUND_COMMANDS = ['npm', 'yarn', 'pnpm', 'node', 'python', 'python3', 'go', 'cargo', 'make', 'docker', 'terraform', 'webpack', 'vite', 'jest', 'pytest', 'curl', 'wget', 'build', 'test', 'serve', 'watch', 'dev'] as const;
11
+
12
+ type SearchReadClassification = {
13
+ readonly isSearch: boolean;
14
+ readonly isRead: boolean;
15
+ readonly isList: boolean;
16
+ };
17
+
18
+ const NOT_SEARCH_OR_READ: SearchReadClassification = {
19
+ isSearch: false,
20
+ isRead: false,
21
+ isList: false
22
+ };
23
+
24
+ export function isSearchOrReadBashCommand(command: string): SearchReadClassification {
25
+ let partsWithOperators: string[];
26
+ try {
27
+ partsWithOperators = splitCommandWithOperators(command);
28
+ } catch (error) {
29
+ if (error instanceof Error) {
30
+ return NOT_SEARCH_OR_READ;
31
+ }
32
+ throw error;
33
+ }
34
+ if (partsWithOperators.length === 0) {
35
+ return NOT_SEARCH_OR_READ;
36
+ }
37
+ let hasSearch = false;
38
+ let hasRead = false;
39
+ let hasList = false;
40
+ let hasNonNeutralCommand = false;
41
+ let skipNextAsRedirectTarget = false;
42
+ for (const part of partsWithOperators) {
43
+ if (skipNextAsRedirectTarget) {
44
+ skipNextAsRedirectTarget = false;
45
+ continue;
46
+ }
47
+ if (part === '>' || part === '>>' || part === '>&') {
48
+ skipNextAsRedirectTarget = true;
49
+ continue;
50
+ }
51
+ if (part === '||' || part === '&&' || part === '|' || part === ';') {
52
+ continue;
53
+ }
54
+ const baseCommand = part.trim().split(/\s+/)[0];
55
+ if (!baseCommand || BASH_SEMANTIC_NEUTRAL_COMMANDS.has(baseCommand)) {
56
+ continue;
57
+ }
58
+ hasNonNeutralCommand = true;
59
+ const isPartSearch = BASH_SEARCH_COMMANDS.has(baseCommand);
60
+ const isPartRead = BASH_READ_COMMANDS.has(baseCommand);
61
+ const isPartList = BASH_LIST_COMMANDS.has(baseCommand);
62
+ if (!isPartSearch && !isPartRead && !isPartList) {
63
+ return NOT_SEARCH_OR_READ;
64
+ }
65
+ if (isPartSearch) hasSearch = true;
66
+ if (isPartRead) hasRead = true;
67
+ if (isPartList) hasList = true;
68
+ }
69
+ if (!hasNonNeutralCommand) {
70
+ return NOT_SEARCH_OR_READ;
71
+ }
72
+ return {
73
+ isSearch: hasSearch,
74
+ isRead: hasRead,
75
+ isList: hasList
76
+ };
77
+ }
78
+
79
+ export function isSilentBashCommand(command: string): boolean {
80
+ let partsWithOperators: string[];
81
+ try {
82
+ partsWithOperators = splitCommandWithOperators(command);
83
+ } catch (error) {
84
+ if (error instanceof Error) {
85
+ return false;
86
+ }
87
+ throw error;
88
+ }
89
+ if (partsWithOperators.length === 0) {
90
+ return false;
91
+ }
92
+ let hasNonFallbackCommand = false;
93
+ let lastOperator: string | null = null;
94
+ let skipNextAsRedirectTarget = false;
95
+ for (const part of partsWithOperators) {
96
+ if (skipNextAsRedirectTarget) {
97
+ skipNextAsRedirectTarget = false;
98
+ continue;
99
+ }
100
+ if (part === '>' || part === '>>' || part === '>&') {
101
+ skipNextAsRedirectTarget = true;
102
+ continue;
103
+ }
104
+ if (part === '||' || part === '&&' || part === '|' || part === ';') {
105
+ lastOperator = part;
106
+ continue;
107
+ }
108
+ const baseCommand = part.trim().split(/\s+/)[0];
109
+ if (!baseCommand || (lastOperator === '||' && BASH_SEMANTIC_NEUTRAL_COMMANDS.has(baseCommand))) {
110
+ continue;
111
+ }
112
+ hasNonFallbackCommand = true;
113
+ if (!BASH_SILENT_COMMANDS.has(baseCommand)) {
114
+ return false;
115
+ }
116
+ }
117
+ return hasNonFallbackCommand;
118
+ }
119
+
120
+ export function isAutobackgroundingAllowed(command: string): boolean {
121
+ const parts = splitCommand_DEPRECATED(command);
122
+ if (parts.length === 0) return true;
123
+ const baseCommand = parts[0]?.trim();
124
+ if (!baseCommand) return true;
125
+ return !DISALLOWED_AUTO_BACKGROUND_COMMANDS.includes(baseCommand);
126
+ }
127
+
128
+ export function detectBlockedSleepPattern(command: string): string | null {
129
+ const parts = splitCommand_DEPRECATED(command);
130
+ if (parts.length === 0) return null;
131
+ const first = parts[0]?.trim() ?? '';
132
+ const match = /^sleep\s+(\d+)\s*$/.exec(first);
133
+ const secondsText = match?.[1];
134
+ if (!secondsText) return null;
135
+ const seconds = parseInt(secondsText, 10);
136
+ if (seconds < 2) return null;
137
+ const rest = parts.slice(1).join(' ').trim();
138
+ return rest ? `sleep ${seconds} followed by: ${rest}` : `standalone sleep ${seconds}`;
139
+ }
140
+
141
+ export function getCommandTypeForLogging(command: string): AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS {
142
+ const parts = splitCommand_DEPRECATED(command);
143
+ if (parts.length === 0) return 'other' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS;
144
+ for (const part of parts) {
145
+ const baseCommand = part.split(' ')[0] || '';
146
+ if (COMMON_BACKGROUND_COMMANDS.includes(baseCommand as (typeof COMMON_BACKGROUND_COMMANDS)[number])) {
147
+ return baseCommand as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS;
148
+ }
149
+ }
150
+ return 'other' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS;
151
+ }
@@ -0,0 +1,40 @@
1
+ import { createRequire } from 'node:module'
2
+
3
+ type SearchReadClassification = {
4
+ readonly isSearch: boolean
5
+ readonly isRead: boolean
6
+ readonly isList: boolean
7
+ }
8
+
9
+ type BashCommandClassificationRuntime = {
10
+ readonly isSearchOrReadBashCommand: (
11
+ command: string,
12
+ ) => SearchReadClassification
13
+ readonly detectBlockedSleepPattern: (command: string) => string | null
14
+ }
15
+
16
+ const requireModule = createRequire(import.meta.url)
17
+ let cachedRuntime: BashCommandClassificationRuntime | undefined
18
+
19
+ function isBashCommandClassificationRuntime(
20
+ value: unknown,
21
+ ): value is BashCommandClassificationRuntime {
22
+ if (typeof value !== 'object' || value === null) return false
23
+ const module = value as Partial<
24
+ Record<keyof BashCommandClassificationRuntime, unknown>
25
+ >
26
+ return (
27
+ typeof module.isSearchOrReadBashCommand === 'function' &&
28
+ typeof module.detectBlockedSleepPattern === 'function'
29
+ )
30
+ }
31
+
32
+ export function loadBashCommandClassificationRuntime(): BashCommandClassificationRuntime {
33
+ if (cachedRuntime !== undefined) return cachedRuntime
34
+ const loaded: unknown = requireModule('./commandClassification.js')
35
+ if (!isBashCommandClassificationRuntime(loaded)) {
36
+ throw new Error('Bash command classification module shape mismatch')
37
+ }
38
+ cachedRuntime = loaded
39
+ return loaded
40
+ }
@@ -0,0 +1,33 @@
1
+ import { createRequire } from 'node:module'
2
+ import type { ToolPermissionContext } from '../../Tool.js'
3
+
4
+ type CwdResetRuntime = {
5
+ readonly resetCwdIfOutsideProject: (
6
+ toolPermissionContext: ToolPermissionContext,
7
+ ) => boolean
8
+ }
9
+
10
+ const requireModule = createRequire(import.meta.url)
11
+ let cachedRuntime: CwdResetRuntime | undefined
12
+
13
+ function isCwdResetRuntime(value: unknown): value is CwdResetRuntime {
14
+ if (typeof value !== 'object' || value === null) return false
15
+ const module = value as Partial<Record<keyof CwdResetRuntime, unknown>>
16
+ return typeof module.resetCwdIfOutsideProject === 'function'
17
+ }
18
+
19
+ function loadCwdResetRuntime(): CwdResetRuntime {
20
+ if (cachedRuntime !== undefined) return cachedRuntime
21
+ const loaded: unknown = requireModule('./utils.js')
22
+ if (!isCwdResetRuntime(loaded)) {
23
+ throw new Error('Bash utility module did not expose cwd reset helper')
24
+ }
25
+ cachedRuntime = loaded
26
+ return loaded
27
+ }
28
+
29
+ export function resetShellCwdIfOutsideProject(
30
+ toolPermissionContext: ToolPermissionContext,
31
+ ): boolean {
32
+ return loadCwdResetRuntime().resetCwdIfOutsideProject(toolPermissionContext)
33
+ }
@@ -0,0 +1,11 @@
1
+ const MAX_LINES_TO_SHOW = 3
2
+
3
+ export function isShellOutputLineTruncated(content: string): boolean {
4
+ let position = 0
5
+ for (let line = 0; line <= MAX_LINES_TO_SHOW; line++) {
6
+ position = content.indexOf('\n', position)
7
+ if (position === -1) return false
8
+ position++
9
+ }
10
+ return position < content.length
11
+ }
@@ -3,6 +3,9 @@ import type { ToolPermissionContext } from '../../Tool.js'
3
3
  import { splitCommand_DEPRECATED } from '../../utils/bash/commands.js'
4
4
  import type { PermissionResult } from '../../utils/permissions/PermissionResult.js'
5
5
  import type { BashTool } from './BashTool.js'
6
+ import { getDestructiveCommandWarning } from './destructiveCommandWarning.js'
7
+ import { getBypassImmuneShellPermissionResult } from './shellPermissionGauntlet.js'
8
+ import { BASH_TOOL_NAME } from './toolName.js'
6
9
 
7
10
  const ACCEPT_EDITS_ALLOWED_COMMANDS = [
8
11
  'mkdir',
@@ -73,8 +76,17 @@ export function checkPermissionMode(
73
76
  input: z.infer<typeof BashTool.inputSchema>,
74
77
  toolPermissionContext: ToolPermissionContext,
75
78
  ): PermissionResult {
76
- // Skip if in bypass mode (handled elsewhere)
77
79
  if (toolPermissionContext.mode === 'bypassPermissions') {
80
+ const bypassImmuneResult = getBypassImmuneShellPermissionResult(
81
+ input.command,
82
+ BASH_TOOL_NAME,
83
+ toolPermissionContext,
84
+ getDestructiveCommandWarning,
85
+ )
86
+ if (bypassImmuneResult !== null) {
87
+ return bypassImmuneResult
88
+ }
89
+
78
90
  return {
79
91
  behavior: 'passthrough',
80
92
  message: 'Bypass mode is handled in main permission flow',
@@ -0,0 +1,42 @@
1
+ import { copyFile, link, stat as fsStat, truncate as fsTruncate } from 'fs/promises';
2
+ import { ensureToolResultsDir, getToolResultPath } from '../../utils/toolResultStorage.js';
3
+ import type { ExecResult } from '../../utils/ShellCommand.js';
4
+
5
+ const MAX_PERSISTED_SIZE = 64 * 1024 * 1024;
6
+
7
+ type PersistedOutput = {
8
+ readonly path?: string;
9
+ readonly size?: number;
10
+ };
11
+
12
+ export async function persistLargeShellOutput(result: ExecResult): Promise<PersistedOutput> {
13
+ if (!result.outputFilePath || !result.outputTaskId) {
14
+ return {};
15
+ }
16
+ try {
17
+ const fileStat = await fsStat(result.outputFilePath);
18
+ await ensureToolResultsDir();
19
+ const dest = getToolResultPath(result.outputTaskId, false);
20
+ if (fileStat.size > MAX_PERSISTED_SIZE) {
21
+ await fsTruncate(result.outputFilePath, MAX_PERSISTED_SIZE);
22
+ }
23
+ try {
24
+ await link(result.outputFilePath, dest);
25
+ } catch (error) {
26
+ if (error instanceof Error) {
27
+ await copyFile(result.outputFilePath, dest);
28
+ } else {
29
+ throw error;
30
+ }
31
+ }
32
+ return {
33
+ path: dest,
34
+ size: fileStat.size
35
+ };
36
+ } catch (error) {
37
+ if (error instanceof Error) {
38
+ return {};
39
+ }
40
+ throw error;
41
+ }
42
+ }
@@ -0,0 +1,66 @@
1
+ import { feature } from 'bun:bundle';
2
+ import type { ToolUseContext, ValidationResult } from '../../Tool.js';
3
+ import type { PermissionResult } from '../../utils/permissions/PermissionResult.js';
4
+ import { parseForSecurity } from '../../utils/bash/ast.js';
5
+ import { bashToolHasPermission, commandHasAnyCd, matchWildcardPattern, permissionRuleExtractPrefix } from './bashPermissions.js';
6
+ import { checkReadOnlyConstraints } from './readOnlyValidation.js';
7
+ import { getDestructiveCommandWarning } from './destructiveCommandWarning.js';
8
+ import { getBypassImmuneShellPermissionResult } from './shellPermissionGauntlet.js';
9
+ import { BASH_TOOL_NAME } from './toolName.js';
10
+ import { detectBlockedSleepPattern } from './commandClassification.js';
11
+ import { isBackgroundTasksDisabled } from './schemas.js';
12
+ import type { BashToolInput } from './schemas.js';
13
+
14
+ export async function validateBashInput(input: BashToolInput): Promise<ValidationResult> {
15
+ if (feature('MONITOR_TOOL') && !isBackgroundTasksDisabled && !input.run_in_background) {
16
+ const sleepPattern = detectBlockedSleepPattern(input.command);
17
+ if (sleepPattern !== null) {
18
+ return {
19
+ result: false,
20
+ message: `Blocked: ${sleepPattern}. Run blocking commands in the background with run_in_background: true — you'll get a completion notification when done. For streaming events (watching logs, polling APIs), use the Monitor tool. If you genuinely need a delay (rate limiting, deliberate pacing), keep it under 2 seconds.`,
21
+ errorCode: 10
22
+ };
23
+ }
24
+ }
25
+ return {
26
+ result: true
27
+ };
28
+ }
29
+
30
+ export function isBashReadOnly(input: BashToolInput): boolean {
31
+ const compoundCommandHasCd = commandHasAnyCd(input.command);
32
+ const result = checkReadOnlyConstraints(input, compoundCommandHasCd);
33
+ return result.behavior === 'allow';
34
+ }
35
+
36
+ export async function prepareBashPermissionMatcher({
37
+ command
38
+ }: BashToolInput): Promise<(pattern: string) => boolean> {
39
+ const parsed = await parseForSecurity(command);
40
+ if (parsed.kind !== 'simple') {
41
+ return () => true;
42
+ }
43
+ const subcommands = parsed.commands.map(c => c.argv.join(' '));
44
+ return pattern => {
45
+ const prefix = permissionRuleExtractPrefix(pattern);
46
+ return subcommands.some(cmd => {
47
+ if (prefix !== null) {
48
+ return cmd === prefix || cmd.startsWith(`${prefix} `);
49
+ }
50
+ return matchWildcardPattern(pattern, cmd);
51
+ });
52
+ };
53
+ }
54
+
55
+ export async function checkBashPermissions(input: BashToolInput, context: ToolUseContext): Promise<PermissionResult> {
56
+ const bypassImmuneResult = getBypassImmuneShellPermissionResult(
57
+ input.command,
58
+ BASH_TOOL_NAME,
59
+ context.getAppState().toolPermissionContext,
60
+ getDestructiveCommandWarning
61
+ );
62
+ if (bypassImmuneResult !== null) {
63
+ return bypassImmuneResult;
64
+ }
65
+ return bashToolHasPermission(input, context);
66
+ }
@@ -0,0 +1,44 @@
1
+ import { createRequire } from 'node:module'
2
+ import type { ToolUseContext, ValidationResult } from '../../Tool.js'
3
+ import type { PermissionResult } from '../../utils/permissions/PermissionResult.js'
4
+ import type { BashToolInput } from './schemas.js'
5
+
6
+ type BashPermissionRuntime = {
7
+ readonly validateBashInput: (
8
+ input: BashToolInput,
9
+ ) => Promise<ValidationResult>
10
+ readonly isBashReadOnly: (input: BashToolInput) => boolean
11
+ readonly prepareBashPermissionMatcher: (
12
+ input: BashToolInput,
13
+ ) => Promise<(pattern: string) => boolean>
14
+ readonly checkBashPermissions: (
15
+ input: BashToolInput,
16
+ context: ToolUseContext,
17
+ ) => Promise<PermissionResult>
18
+ }
19
+
20
+ const requireModule = createRequire(import.meta.url)
21
+ let cachedRuntime: BashPermissionRuntime | undefined
22
+
23
+ function isBashPermissionRuntime(
24
+ value: unknown,
25
+ ): value is BashPermissionRuntime {
26
+ if (typeof value !== 'object' || value === null) return false
27
+ const module = value as Partial<Record<keyof BashPermissionRuntime, unknown>>
28
+ return (
29
+ typeof module.validateBashInput === 'function' &&
30
+ typeof module.isBashReadOnly === 'function' &&
31
+ typeof module.prepareBashPermissionMatcher === 'function' &&
32
+ typeof module.checkBashPermissions === 'function'
33
+ )
34
+ }
35
+
36
+ export function loadBashPermissionRuntime(): BashPermissionRuntime {
37
+ if (cachedRuntime !== undefined) return cachedRuntime
38
+ const loaded: unknown = requireModule('./permissionClassification.js')
39
+ if (!isBashPermissionRuntime(loaded)) {
40
+ throw new Error('Bash permission module did not expose expected functions')
41
+ }
42
+ cachedRuntime = loaded
43
+ return loaded
44
+ }