@bastani/atomic 0.8.28-alpha.1 → 0.8.28-alpha.3

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 (428) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +120 -118
  3. package/dist/builtin/intercom/package.json +1 -1
  4. package/dist/builtin/mcp/package.json +1 -1
  5. package/dist/builtin/subagents/package.json +1 -1
  6. package/dist/builtin/web-access/package.json +1 -1
  7. package/dist/builtin/workflows/CHANGELOG.md +26 -0
  8. package/dist/builtin/workflows/README.md +1 -1
  9. package/dist/builtin/workflows/builtin/open-claude-design.ts +150 -13
  10. package/dist/builtin/workflows/package.json +1 -1
  11. package/dist/builtin/workflows/src/authoring.d.ts +5 -2
  12. package/dist/builtin/workflows/src/extension/dispatcher.ts +2 -0
  13. package/dist/builtin/workflows/src/extension/index.ts +8 -0
  14. package/dist/builtin/workflows/src/extension/render-result.ts +5 -2
  15. package/dist/builtin/workflows/src/extension/workflow-schema.ts +18 -0
  16. package/dist/builtin/workflows/src/runs/background/status.ts +4 -0
  17. package/dist/builtin/workflows/src/runs/foreground/executor.ts +1251 -110
  18. package/dist/builtin/workflows/src/shared/authoring-contract.d.ts +34 -10
  19. package/dist/builtin/workflows/src/shared/expanded-workflow-graph.ts +10 -2
  20. package/dist/builtin/workflows/src/shared/persistence-restore.ts +28 -9
  21. package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +9 -3
  22. package/dist/builtin/workflows/src/shared/store-types.ts +10 -3
  23. package/dist/builtin/workflows/src/shared/store.ts +29 -7
  24. package/dist/builtin/workflows/src/shared/types.ts +12 -10
  25. package/dist/builtin/workflows/src/tui/chat-surface.ts +32 -33
  26. package/dist/builtin/workflows/src/tui/run-detail.ts +23 -4
  27. package/dist/builtin/workflows/src/tui/status-helpers.ts +4 -0
  28. package/dist/builtin/workflows/src/tui/status-list.ts +47 -3
  29. package/dist/builtin/workflows/src/tui/store-widget-installer.ts +1 -1
  30. package/dist/builtin/workflows/src/tui/widget.ts +12 -3
  31. package/dist/builtin/workflows/src/workflows/define-workflow.ts +3 -3
  32. package/dist/cli/args.d.ts +4 -0
  33. package/dist/cli/args.d.ts.map +1 -1
  34. package/dist/cli/args.js +35 -0
  35. package/dist/cli/args.js.map +1 -1
  36. package/dist/cli/project-trust.d.ts +10 -0
  37. package/dist/cli/project-trust.d.ts.map +1 -0
  38. package/dist/cli/project-trust.js +36 -0
  39. package/dist/cli/project-trust.js.map +1 -0
  40. package/dist/cli/startup-ui.d.ts +7 -0
  41. package/dist/cli/startup-ui.d.ts.map +1 -0
  42. package/dist/cli/startup-ui.js +57 -0
  43. package/dist/cli/startup-ui.js.map +1 -0
  44. package/dist/config.d.ts.map +1 -1
  45. package/dist/config.js +24 -3
  46. package/dist/config.js.map +1 -1
  47. package/dist/core/agent-session-runtime.d.ts +3 -1
  48. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  49. package/dist/core/agent-session-runtime.js +1 -0
  50. package/dist/core/agent-session-runtime.js.map +1 -1
  51. package/dist/core/agent-session-services.d.ts +3 -1
  52. package/dist/core/agent-session-services.d.ts.map +1 -1
  53. package/dist/core/agent-session-services.js +3 -2
  54. package/dist/core/agent-session-services.js.map +1 -1
  55. package/dist/core/agent-session.d.ts +9 -1
  56. package/dist/core/agent-session.d.ts.map +1 -1
  57. package/dist/core/agent-session.js +70 -21
  58. package/dist/core/agent-session.js.map +1 -1
  59. package/dist/core/auth-storage.d.ts.map +1 -1
  60. package/dist/core/auth-storage.js +4 -3
  61. package/dist/core/auth-storage.js.map +1 -1
  62. package/dist/core/compaction/branch-summarization.d.ts +3 -1
  63. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  64. package/dist/core/compaction/branch-summarization.js +9 -3
  65. package/dist/core/compaction/branch-summarization.js.map +1 -1
  66. package/dist/core/compaction/compaction.d.ts.map +1 -1
  67. package/dist/core/compaction/compaction.js +18 -24
  68. package/dist/core/compaction/compaction.js.map +1 -1
  69. package/dist/core/compaction/utils.d.ts +1 -1
  70. package/dist/core/compaction/utils.d.ts.map +1 -1
  71. package/dist/core/compaction/utils.js +1 -1
  72. package/dist/core/compaction/utils.js.map +1 -1
  73. package/dist/core/experimental.d.ts +2 -0
  74. package/dist/core/experimental.d.ts.map +1 -0
  75. package/dist/core/experimental.js +5 -0
  76. package/dist/core/experimental.js.map +1 -0
  77. package/dist/core/export-html/template.js +19 -6
  78. package/dist/core/extensions/index.d.ts +1 -1
  79. package/dist/core/extensions/index.d.ts.map +1 -1
  80. package/dist/core/extensions/index.js.map +1 -1
  81. package/dist/core/extensions/loader.d.ts +1 -1
  82. package/dist/core/extensions/loader.d.ts.map +1 -1
  83. package/dist/core/extensions/loader.js +6 -4
  84. package/dist/core/extensions/loader.js.map +1 -1
  85. package/dist/core/extensions/runner.d.ts +11 -4
  86. package/dist/core/extensions/runner.d.ts.map +1 -1
  87. package/dist/core/extensions/runner.js +53 -3
  88. package/dist/core/extensions/runner.js.map +1 -1
  89. package/dist/core/extensions/types.d.ts +34 -4
  90. package/dist/core/extensions/types.d.ts.map +1 -1
  91. package/dist/core/extensions/types.js.map +1 -1
  92. package/dist/core/footer-data-provider.d.ts +2 -0
  93. package/dist/core/footer-data-provider.d.ts.map +1 -1
  94. package/dist/core/footer-data-provider.js +27 -1
  95. package/dist/core/footer-data-provider.js.map +1 -1
  96. package/dist/core/index.d.ts +2 -0
  97. package/dist/core/index.d.ts.map +1 -1
  98. package/dist/core/index.js +2 -0
  99. package/dist/core/index.js.map +1 -1
  100. package/dist/core/model-registry.d.ts.map +1 -1
  101. package/dist/core/model-registry.js +64 -7
  102. package/dist/core/model-registry.js.map +1 -1
  103. package/dist/core/model-resolver.d.ts.map +1 -1
  104. package/dist/core/model-resolver.js +1 -0
  105. package/dist/core/model-resolver.js.map +1 -1
  106. package/dist/core/output-guard.d.ts +1 -0
  107. package/dist/core/output-guard.d.ts.map +1 -1
  108. package/dist/core/output-guard.js +52 -22
  109. package/dist/core/output-guard.js.map +1 -1
  110. package/dist/core/package-manager.d.ts +1 -0
  111. package/dist/core/package-manager.d.ts.map +1 -1
  112. package/dist/core/package-manager.js +20 -8
  113. package/dist/core/package-manager.js.map +1 -1
  114. package/dist/core/project-trust.d.ts +15 -0
  115. package/dist/core/project-trust.d.ts.map +1 -0
  116. package/dist/core/project-trust.js +58 -0
  117. package/dist/core/project-trust.js.map +1 -0
  118. package/dist/core/prompt-templates.d.ts +5 -4
  119. package/dist/core/prompt-templates.d.ts.map +1 -1
  120. package/dist/core/prompt-templates.js +30 -29
  121. package/dist/core/prompt-templates.js.map +1 -1
  122. package/dist/core/provider-attribution.d.ts +4 -0
  123. package/dist/core/provider-attribution.d.ts.map +1 -0
  124. package/dist/core/provider-attribution.js +73 -0
  125. package/dist/core/provider-attribution.js.map +1 -0
  126. package/dist/core/provider-display-names.d.ts.map +1 -1
  127. package/dist/core/provider-display-names.js +3 -0
  128. package/dist/core/provider-display-names.js.map +1 -1
  129. package/dist/core/resolve-config-value.d.ts +9 -1
  130. package/dist/core/resolve-config-value.d.ts.map +1 -1
  131. package/dist/core/resolve-config-value.js +134 -11
  132. package/dist/core/resolve-config-value.js.map +1 -1
  133. package/dist/core/resource-loader.d.ts +12 -2
  134. package/dist/core/resource-loader.d.ts.map +1 -1
  135. package/dist/core/resource-loader.js +108 -18
  136. package/dist/core/resource-loader.js.map +1 -1
  137. package/dist/core/sdk.d.ts +4 -2
  138. package/dist/core/sdk.d.ts.map +1 -1
  139. package/dist/core/sdk.js +13 -42
  140. package/dist/core/sdk.js.map +1 -1
  141. package/dist/core/session-manager.d.ts +6 -7
  142. package/dist/core/session-manager.d.ts.map +1 -1
  143. package/dist/core/session-manager.js +99 -35
  144. package/dist/core/session-manager.js.map +1 -1
  145. package/dist/core/settings-manager.d.ts +15 -2
  146. package/dist/core/settings-manager.d.ts.map +1 -1
  147. package/dist/core/settings-manager.js +69 -10
  148. package/dist/core/settings-manager.js.map +1 -1
  149. package/dist/core/slash-commands.d.ts.map +1 -1
  150. package/dist/core/slash-commands.js +1 -0
  151. package/dist/core/slash-commands.js.map +1 -1
  152. package/dist/core/system-prompt.d.ts.map +1 -1
  153. package/dist/core/system-prompt.js +0 -3
  154. package/dist/core/system-prompt.js.map +1 -1
  155. package/dist/core/tools/ask-user-question/state/inline-input.d.ts +28 -0
  156. package/dist/core/tools/ask-user-question/state/inline-input.d.ts.map +1 -0
  157. package/dist/core/tools/ask-user-question/state/inline-input.js +56 -0
  158. package/dist/core/tools/ask-user-question/state/inline-input.js.map +1 -0
  159. package/dist/core/tools/ask-user-question/state/key-router.d.ts.map +1 -1
  160. package/dist/core/tools/ask-user-question/state/key-router.js +30 -4
  161. package/dist/core/tools/ask-user-question/state/key-router.js.map +1 -1
  162. package/dist/core/tools/ask-user-question/state/questionnaire-session.d.ts.map +1 -1
  163. package/dist/core/tools/ask-user-question/state/questionnaire-session.js +9 -8
  164. package/dist/core/tools/ask-user-question/state/questionnaire-session.js.map +1 -1
  165. package/dist/core/tools/ask-user-question/state/row-intent.d.ts +3 -2
  166. package/dist/core/tools/ask-user-question/state/row-intent.d.ts.map +1 -1
  167. package/dist/core/tools/ask-user-question/state/row-intent.js +1 -1
  168. package/dist/core/tools/ask-user-question/state/row-intent.js.map +1 -1
  169. package/dist/core/tools/ask-user-question/state/selectors/contract.d.ts +2 -0
  170. package/dist/core/tools/ask-user-question/state/selectors/contract.d.ts.map +1 -1
  171. package/dist/core/tools/ask-user-question/state/selectors/contract.js.map +1 -1
  172. package/dist/core/tools/ask-user-question/state/selectors/projections.d.ts.map +1 -1
  173. package/dist/core/tools/ask-user-question/state/selectors/projections.js +2 -0
  174. package/dist/core/tools/ask-user-question/state/selectors/projections.js.map +1 -1
  175. package/dist/core/tools/ask-user-question/state/state-reducer.d.ts.map +1 -1
  176. package/dist/core/tools/ask-user-question/state/state-reducer.js +36 -24
  177. package/dist/core/tools/ask-user-question/state/state-reducer.js.map +1 -1
  178. package/dist/core/tools/ask-user-question/state/state.d.ts +8 -0
  179. package/dist/core/tools/ask-user-question/state/state.d.ts.map +1 -1
  180. package/dist/core/tools/ask-user-question/state/state.js.map +1 -1
  181. package/dist/core/tools/ask-user-question/tool/format-answer.d.ts +6 -0
  182. package/dist/core/tools/ask-user-question/tool/format-answer.d.ts.map +1 -1
  183. package/dist/core/tools/ask-user-question/tool/format-answer.js +19 -1
  184. package/dist/core/tools/ask-user-question/tool/format-answer.js.map +1 -1
  185. package/dist/core/tools/ask-user-question/tool/response-envelope.d.ts +3 -2
  186. package/dist/core/tools/ask-user-question/tool/response-envelope.d.ts.map +1 -1
  187. package/dist/core/tools/ask-user-question/tool/response-envelope.js +15 -3
  188. package/dist/core/tools/ask-user-question/tool/response-envelope.js.map +1 -1
  189. package/dist/core/tools/ask-user-question/tool/types.d.ts +2 -1
  190. package/dist/core/tools/ask-user-question/tool/types.d.ts.map +1 -1
  191. package/dist/core/tools/ask-user-question/tool/types.js.map +1 -1
  192. package/dist/core/tools/ask-user-question/view/components/chat-row-view.d.ts +5 -2
  193. package/dist/core/tools/ask-user-question/view/components/chat-row-view.d.ts.map +1 -1
  194. package/dist/core/tools/ask-user-question/view/components/chat-row-view.js +2 -0
  195. package/dist/core/tools/ask-user-question/view/components/chat-row-view.js.map +1 -1
  196. package/dist/core/tools/ask-user-question/view/components/wrapping-select.d.ts +1 -0
  197. package/dist/core/tools/ask-user-question/view/components/wrapping-select.d.ts.map +1 -1
  198. package/dist/core/tools/ask-user-question/view/components/wrapping-select.js +2 -1
  199. package/dist/core/tools/ask-user-question/view/components/wrapping-select.js.map +1 -1
  200. package/dist/core/tools/ask-user-question/view/props-adapter.d.ts +3 -3
  201. package/dist/core/tools/ask-user-question/view/props-adapter.d.ts.map +1 -1
  202. package/dist/core/tools/ask-user-question/view/props-adapter.js +11 -4
  203. package/dist/core/tools/ask-user-question/view/props-adapter.js.map +1 -1
  204. package/dist/core/tools/bash-policy.d.ts +62 -0
  205. package/dist/core/tools/bash-policy.d.ts.map +1 -0
  206. package/dist/core/tools/bash-policy.js +1069 -0
  207. package/dist/core/tools/bash-policy.js.map +1 -0
  208. package/dist/core/tools/bash.d.ts +5 -0
  209. package/dist/core/tools/bash.d.ts.map +1 -1
  210. package/dist/core/tools/bash.js +9 -1
  211. package/dist/core/tools/bash.js.map +1 -1
  212. package/dist/core/tools/edit.d.ts.map +1 -1
  213. package/dist/core/tools/edit.js +7 -10
  214. package/dist/core/tools/edit.js.map +1 -1
  215. package/dist/core/tools/find.d.ts.map +1 -1
  216. package/dist/core/tools/find.js +1 -1
  217. package/dist/core/tools/find.js.map +1 -1
  218. package/dist/core/tools/grep.d.ts.map +1 -1
  219. package/dist/core/tools/grep.js +1 -1
  220. package/dist/core/tools/grep.js.map +1 -1
  221. package/dist/core/tools/index.d.ts +1 -0
  222. package/dist/core/tools/index.d.ts.map +1 -1
  223. package/dist/core/tools/index.js +1 -0
  224. package/dist/core/tools/index.js.map +1 -1
  225. package/dist/core/tools/ls.d.ts.map +1 -1
  226. package/dist/core/tools/ls.js +1 -1
  227. package/dist/core/tools/ls.js.map +1 -1
  228. package/dist/core/tools/oversized-tool-result.d.ts +53 -0
  229. package/dist/core/tools/oversized-tool-result.d.ts.map +1 -0
  230. package/dist/core/tools/oversized-tool-result.js +206 -0
  231. package/dist/core/tools/oversized-tool-result.js.map +1 -0
  232. package/dist/core/tools/read.d.ts +12 -0
  233. package/dist/core/tools/read.d.ts.map +1 -1
  234. package/dist/core/tools/read.js +99 -34
  235. package/dist/core/tools/read.js.map +1 -1
  236. package/dist/core/tools/render-utils.d.ts +6 -0
  237. package/dist/core/tools/render-utils.d.ts.map +1 -1
  238. package/dist/core/tools/render-utils.js +17 -1
  239. package/dist/core/tools/render-utils.js.map +1 -1
  240. package/dist/core/tools/tool-definition-wrapper.d.ts +6 -0
  241. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  242. package/dist/core/tools/tool-definition-wrapper.js +2 -0
  243. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  244. package/dist/core/tools/tool-limits.d.ts +25 -0
  245. package/dist/core/tools/tool-limits.d.ts.map +1 -0
  246. package/dist/core/tools/tool-limits.js +25 -0
  247. package/dist/core/tools/tool-limits.js.map +1 -0
  248. package/dist/core/tools/write.d.ts.map +1 -1
  249. package/dist/core/tools/write.js +1 -1
  250. package/dist/core/tools/write.js.map +1 -1
  251. package/dist/core/trust-manager.d.ts +31 -0
  252. package/dist/core/trust-manager.d.ts.map +1 -0
  253. package/dist/core/trust-manager.js +196 -0
  254. package/dist/core/trust-manager.js.map +1 -0
  255. package/dist/index.d.ts +11 -6
  256. package/dist/index.d.ts.map +1 -1
  257. package/dist/index.js +6 -2
  258. package/dist/index.js.map +1 -1
  259. package/dist/main.d.ts.map +1 -1
  260. package/dist/main.js +142 -30
  261. package/dist/main.js.map +1 -1
  262. package/dist/migrations.d.ts +3 -1
  263. package/dist/migrations.d.ts.map +1 -1
  264. package/dist/migrations.js +325 -7
  265. package/dist/migrations.js.map +1 -1
  266. package/dist/modes/index.d.ts +1 -1
  267. package/dist/modes/index.d.ts.map +1 -1
  268. package/dist/modes/index.js.map +1 -1
  269. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  270. package/dist/modes/interactive/components/bash-execution.js +2 -2
  271. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  272. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  273. package/dist/modes/interactive/components/footer.js +6 -0
  274. package/dist/modes/interactive/components/footer.js.map +1 -1
  275. package/dist/modes/interactive/components/index.d.ts +1 -0
  276. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  277. package/dist/modes/interactive/components/index.js +1 -0
  278. package/dist/modes/interactive/components/index.js.map +1 -1
  279. package/dist/modes/interactive/components/login-dialog.d.ts +1 -1
  280. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  281. package/dist/modes/interactive/components/login-dialog.js +9 -16
  282. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  283. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  284. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  285. package/dist/modes/interactive/components/settings-selector.js +20 -0
  286. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  287. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  288. package/dist/modes/interactive/components/tool-execution.js +22 -0
  289. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  290. package/dist/modes/interactive/components/trust-selector.d.ts +23 -0
  291. package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -0
  292. package/dist/modes/interactive/components/trust-selector.js +85 -0
  293. package/dist/modes/interactive/components/trust-selector.js.map +1 -0
  294. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  295. package/dist/modes/interactive/components/user-message.js +1 -1
  296. package/dist/modes/interactive/components/user-message.js.map +1 -1
  297. package/dist/modes/interactive/interactive-mode.d.ts +9 -0
  298. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  299. package/dist/modes/interactive/interactive-mode.js +130 -9
  300. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  301. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  302. package/dist/modes/interactive/theme/theme.js +10 -0
  303. package/dist/modes/interactive/theme/theme.js.map +1 -1
  304. package/dist/modes/print-mode.d.ts.map +1 -1
  305. package/dist/modes/print-mode.js +1 -0
  306. package/dist/modes/print-mode.js.map +1 -1
  307. package/dist/modes/rpc/rpc-client.d.ts +3 -0
  308. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  309. package/dist/modes/rpc/rpc-client.js +50 -6
  310. package/dist/modes/rpc/rpc-client.js.map +1 -1
  311. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  312. package/dist/modes/rpc/rpc-mode.js +23 -4
  313. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  314. package/dist/modes/rpc/rpc-types.d.ts +1 -0
  315. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  316. package/dist/modes/rpc/rpc-types.js.map +1 -1
  317. package/dist/package-manager-cli.d.ts +6 -2
  318. package/dist/package-manager-cli.d.ts.map +1 -1
  319. package/dist/package-manager-cli.js +104 -10
  320. package/dist/package-manager-cli.js.map +1 -1
  321. package/dist/utils/changelog.d.ts +1 -0
  322. package/dist/utils/changelog.d.ts.map +1 -1
  323. package/dist/utils/changelog.js +72 -0
  324. package/dist/utils/changelog.js.map +1 -1
  325. package/dist/utils/deprecation.d.ts +4 -0
  326. package/dist/utils/deprecation.d.ts.map +1 -0
  327. package/dist/utils/deprecation.js +13 -0
  328. package/dist/utils/deprecation.js.map +1 -0
  329. package/dist/utils/git.d.ts.map +1 -1
  330. package/dist/utils/git.js +54 -22
  331. package/dist/utils/git.js.map +1 -1
  332. package/dist/utils/json.d.ts +3 -0
  333. package/dist/utils/json.d.ts.map +1 -0
  334. package/dist/utils/json.js +7 -0
  335. package/dist/utils/json.js.map +1 -0
  336. package/dist/utils/open-browser.d.ts +9 -0
  337. package/dist/utils/open-browser.d.ts.map +1 -0
  338. package/dist/utils/open-browser.js +22 -0
  339. package/dist/utils/open-browser.js.map +1 -0
  340. package/docs/containerization.md +111 -0
  341. package/docs/custom-provider.md +9 -9
  342. package/docs/development.md +1 -1
  343. package/docs/docs.json +2 -0
  344. package/docs/extensions.md +40 -4
  345. package/docs/index.md +2 -0
  346. package/docs/models.md +10 -10
  347. package/docs/packages.md +1 -1
  348. package/docs/prompt-templates.md +9 -2
  349. package/docs/providers.md +18 -5
  350. package/docs/quickstart.md +1 -0
  351. package/docs/rpc.md +3 -2
  352. package/docs/sdk.md +47 -0
  353. package/docs/security.md +58 -0
  354. package/docs/session-format.md +2 -2
  355. package/docs/sessions.md +8 -0
  356. package/docs/settings.md +21 -4
  357. package/docs/skills.md +1 -1
  358. package/docs/terminal-setup.md +44 -2
  359. package/docs/themes.md +1 -1
  360. package/docs/tmux.md +4 -2
  361. package/docs/tui.md +14 -5
  362. package/docs/usage.md +17 -3
  363. package/docs/workflows.md +127 -15
  364. package/examples/README.md +1 -1
  365. package/examples/extensions/README.md +8 -5
  366. package/examples/extensions/bash-spawn-hook.ts +1 -1
  367. package/examples/extensions/built-in-tool-renderer.ts +1 -1
  368. package/examples/extensions/claude-rules.ts +1 -1
  369. package/examples/extensions/commands.ts +1 -1
  370. package/examples/extensions/custom-header.ts +1 -1
  371. package/examples/extensions/custom-provider-anthropic/index.ts +3 -3
  372. package/examples/extensions/custom-provider-anthropic/package-lock.json +4 -4
  373. package/examples/extensions/custom-provider-anthropic/package.json +6 -6
  374. package/examples/extensions/custom-provider-gitlab-duo/index.ts +55 -4
  375. package/examples/extensions/custom-provider-gitlab-duo/package.json +3 -3
  376. package/examples/extensions/doom-overlay/README.md +1 -1
  377. package/examples/extensions/doom-overlay/index.ts +2 -2
  378. package/examples/extensions/git-merge-and-resolve.ts +115 -0
  379. package/examples/extensions/gondolin/index.ts +523 -0
  380. package/examples/extensions/gondolin/package-lock.json +185 -0
  381. package/examples/extensions/gondolin/package.json +19 -0
  382. package/examples/extensions/handoff.ts +1 -1
  383. package/examples/extensions/hidden-thinking-label.ts +1 -1
  384. package/examples/extensions/inline-bash.ts +2 -2
  385. package/examples/extensions/input-transform-streaming.ts +39 -0
  386. package/examples/extensions/input-transform.ts +3 -3
  387. package/examples/extensions/interactive-shell.ts +2 -2
  388. package/examples/extensions/mac-system-theme.ts +2 -2
  389. package/examples/extensions/minimal-mode.ts +1 -1
  390. package/examples/extensions/modal-editor.ts +1 -1
  391. package/examples/extensions/model-status.ts +1 -1
  392. package/examples/extensions/overlay-qa-tests.ts +198 -179
  393. package/examples/extensions/overlay-test.ts +1 -1
  394. package/examples/extensions/pirate.ts +1 -1
  395. package/examples/extensions/preset.ts +14 -12
  396. package/examples/extensions/project-trust.ts +64 -0
  397. package/examples/extensions/prompt-customizer.ts +1 -1
  398. package/examples/extensions/qna.ts +1 -1
  399. package/examples/extensions/question.ts +1 -1
  400. package/examples/extensions/questionnaire.ts +1 -1
  401. package/examples/extensions/rainbow-editor.ts +1 -1
  402. package/examples/extensions/sandbox/index.ts +16 -14
  403. package/examples/extensions/sandbox/package-lock.json +90 -90
  404. package/examples/extensions/sandbox/package.json +17 -17
  405. package/examples/extensions/snake.ts +1 -1
  406. package/examples/extensions/space-invaders.ts +1 -1
  407. package/examples/extensions/ssh.ts +2 -2
  408. package/examples/extensions/subagent/README.md +13 -13
  409. package/examples/extensions/subagent/agents.ts +4 -2
  410. package/examples/extensions/subagent/index.ts +6 -6
  411. package/examples/extensions/summarize.ts +1 -1
  412. package/examples/extensions/tic-tac-toe.ts +1 -1
  413. package/examples/extensions/titlebar-spinner.ts +1 -1
  414. package/examples/extensions/todo.ts +1 -1
  415. package/examples/extensions/tool-override.ts +1 -1
  416. package/examples/extensions/tools.ts +6 -1
  417. package/examples/extensions/with-deps/package-lock.json +4 -4
  418. package/examples/extensions/with-deps/package.json +7 -7
  419. package/examples/extensions/working-indicator.ts +4 -4
  420. package/examples/extensions/working-message-test.ts +1 -1
  421. package/examples/sdk/01-minimal.ts +1 -1
  422. package/examples/sdk/03-custom-prompt.ts +1 -1
  423. package/examples/sdk/04-skills.ts +1 -1
  424. package/examples/sdk/06-extensions.ts +2 -2
  425. package/examples/sdk/08-prompt-templates.ts +1 -1
  426. package/examples/sdk/09-api-keys-and-oauth.ts +2 -2
  427. package/examples/sdk/README.md +2 -2
  428. package/package.json +4 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bash-policy.js","sourceRoot":"","sources":["../../../src/core/tools/bash-policy.ts"],"names":[],"mappings":"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","sourcesContent":["export type BashCommandRule =\n\t| string\n\t| { readonly prefix: string }\n\t| { readonly glob: string }\n\t| { readonly regex: string; readonly flags?: string };\n\nexport type BashCommandPolicyDefault = \"allow\" | \"deny\";\nexport type BashCommandPolicyMatchMode = \"whole\" | \"segments\";\n\nexport interface BashCommandPolicy {\n\treadonly default?: BashCommandPolicyDefault;\n\treadonly allow?: readonly BashCommandRule[];\n\treadonly deny?: readonly BashCommandRule[];\n\treadonly match?: BashCommandPolicyMatchMode;\n}\n\nexport type BashCommandSegmentSource = \"top-level\" | \"command-substitution\" | \"process-substitution\" | \"backtick\";\n\nexport interface BashCommandSegment {\n\treadonly raw: string;\n\treadonly target: string;\n\treadonly head: string;\n\treadonly start: number;\n\treadonly end: number;\n\treadonly source: BashCommandSegmentSource;\n}\n\nexport interface BashCommandParseError {\n\treadonly reason: string;\n\treadonly offset: number;\n\treadonly source: BashCommandSegmentSource;\n}\n\nexport type BashCommandParseResult =\n\t| { readonly ok: true; readonly segments: readonly BashCommandSegment[] }\n\t| { readonly ok: false; readonly error: BashCommandParseError };\n\nexport type BashCommandPolicyDenialReason =\n\t| \"invalid-policy\"\n\t| \"unsupported-shell-syntax\"\n\t| \"matched-deny\"\n\t| \"default-deny\";\n\nexport interface BashCommandPolicyRejection {\n\treadonly reason: BashCommandPolicyDenialReason;\n\treadonly message: string;\n\treadonly target?: BashCommandSegment;\n\treadonly matchedRule?: BashCommandRule;\n\treadonly parseError?: BashCommandParseError;\n}\n\nexport type BashCommandPolicyDecision =\n\t| {\n\t\t\treadonly allowed: true;\n\t\t\treadonly mode: BashCommandPolicyMatchMode;\n\t\t\treadonly targets: readonly BashCommandSegment[];\n\t }\n\t| {\n\t\t\treadonly allowed: false;\n\t\t\treadonly mode: BashCommandPolicyMatchMode;\n\t\t\treadonly targets: readonly BashCommandSegment[];\n\t\t\treadonly rejection: BashCommandPolicyRejection;\n\t };\n\ntype CompiledRule =\n\t| { readonly kind: \"exact\"; readonly source: BashCommandRule; readonly value: string }\n\t| { readonly kind: \"prefix\"; readonly source: BashCommandRule; readonly value: string }\n\t| { readonly kind: \"glob\"; readonly source: BashCommandRule; readonly value: RegExp }\n\t| { readonly kind: \"regex\"; readonly source: BashCommandRule; readonly value: RegExp };\n\ninterface CompiledBashCommandPolicy {\n\treadonly defaultDecision: BashCommandPolicyDefault;\n\treadonly match: BashCommandPolicyMatchMode;\n\treadonly allow: readonly CompiledRule[];\n\treadonly deny: readonly CompiledRule[];\n}\n\ntype CompileResult =\n\t| { readonly ok: true; readonly policy: CompiledBashCommandPolicy }\n\t| { readonly ok: false; readonly message: string };\n\ntype CompileRuleResult =\n\t| { readonly ok: true; readonly rule: CompiledRule }\n\t| { readonly ok: false; readonly message: string };\n\ntype CompileRulesResult =\n\t| { readonly ok: true; readonly rules: readonly CompiledRule[] }\n\t| { readonly ok: false; readonly message: string };\n\ntype SegmentBuildResult =\n\t| { readonly ok: true; readonly segment?: BashCommandSegment }\n\t| { readonly ok: false; readonly error: BashCommandParseError };\n\ntype ClosingParenResult =\n\t| { readonly ok: true; readonly closeIndex: number }\n\t| { readonly ok: false; readonly reason: string; readonly offset: number };\n\ntype ClosingBacktickResult =\n\t| { readonly ok: true; readonly closeIndex: number }\n\t| { readonly ok: false; readonly reason: string; readonly offset: number };\n\ntype ShellQuoteState = \"none\" | \"single\" | \"double\";\n\ninterface ShellWordMetadata {\n\treadonly sawSingleQuote: boolean;\n\treadonly sawDoubleQuote: boolean;\n\treadonly sawEscape: boolean;\n\treadonly sawParameterExpansion: boolean;\n\treadonly sawCommandSubstitution: boolean;\n\treadonly sawProcessSubstitution: boolean;\n\treadonly sawBacktick: boolean;\n\treadonly sawGlobPattern: boolean;\n\treadonly sawBraceExpansion: boolean;\n\treadonly sawTildePrefix: boolean;\n}\n\ntype ShellWordReadResult =\n\t| { readonly ok: true; readonly word: string; readonly end: number; readonly metadata: ShellWordMetadata }\n\t| { readonly ok: false; readonly reason: string; readonly offset: number };\n\ntype LiteralCommandHeadValidation =\n\t| { readonly ok: true }\n\t| { readonly ok: false; readonly reason: string };\n\nconst UNSUPPORTED_CONTROL_HEADS = new Set([\n\t\"!\",\n\t\"[[\",\n\t\"]]\",\n\t\"case\",\n\t\"coproc\",\n\t\"do\",\n\t\"done\",\n\t\"elif\",\n\t\"else\",\n\t\"esac\",\n\t\"fi\",\n\t\"for\",\n\t\"function\",\n\t\"if\",\n\t\"in\",\n\t\"select\",\n\t\"then\",\n\t\"time\",\n\t\"until\",\n\t\"while\",\n\t\"{\",\n\t\"}\",\n]);\n\nconst DIAGNOSTIC_TEXT_LIMIT = 220;\n\nfunction truncateDiagnostic(text: string): string {\n\tif (text.length <= DIAGNOSTIC_TEXT_LIMIT) return text;\n\treturn `${text.slice(0, DIAGNOSTIC_TEXT_LIMIT - 1)}…`;\n}\n\ntype RuntimePropertyValue =\n\t| string\n\t| number\n\t| boolean\n\t| bigint\n\t| symbol\n\t| null\n\t| object\n\t| ((...args: readonly never[]) => RuntimePropertyValue)\n\t| undefined;\n\ntype RuleObjectKey = \"prefix\" | \"glob\" | \"regex\" | \"flags\";\n\nconst BASH_POLICY_TOP_LEVEL_KEYS = [\"default\", \"allow\", \"deny\", \"match\"] as const;\nconst BASH_POLICY_TOP_LEVEL_KEY_SET: ReadonlySet<string> = new Set(BASH_POLICY_TOP_LEVEL_KEYS);\n\nfunction hasOwnRuleKey<Key extends RuleObjectKey>(\n\tvalue: object,\n\tkey: Key,\n): value is Record<Key, RuntimePropertyValue> {\n\treturn Object.prototype.hasOwnProperty.call(value, key);\n}\n\nfunction hasOnlyRuleKeys(value: object, allowedKeys: readonly string[]): boolean {\n\treturn Object.keys(value).every((key) => allowedKeys.includes(key));\n}\n\nfunction unknownBashPolicyTopLevelKeys(policy: object): readonly string[] {\n\treturn Object.keys(policy).filter((key) => !BASH_POLICY_TOP_LEVEL_KEY_SET.has(key));\n}\n\nfunction escapeRegexLiteral(value: string): string {\n\treturn value.replace(/[\\\\^$.*+?()[\\]{}|]/g, \"\\\\$&\");\n}\n\nfunction escapeGlobClassCharacter(char: string): string {\n\tif (char === \"\\\\\") return \"\\\\\\\\\";\n\tif (char === \"]\") return \"\\\\]\";\n\tif (char === \"[\") return \"\\\\[\";\n\treturn char;\n}\n\nfunction escapeEscapedGlobClassCharacter(char: string): string {\n\tif (char === \"\\\\\") return \"\\\\\\\\\";\n\tif (char === \"-\") return \"\\\\-\";\n\tif (char === \"^\") return \"\\\\^\";\n\tif (char === \"]\") return \"\\\\]\";\n\tif (char === \"[\") return \"\\\\[\";\n\treturn char;\n}\n\nfunction readGlobBracketClass(\n\tpattern: string,\n\topenIndex: number,\n): { readonly regexSource: string; readonly closeIndex: number } | undefined {\n\tlet cursor = openIndex + 1;\n\tlet negated = false;\n\tlet hasContent = false;\n\tlet content = \"\";\n\n\tif (cursor >= pattern.length) return undefined;\n\tif (pattern[cursor] === \"!\" || pattern[cursor] === \"^\") {\n\t\tnegated = true;\n\t\tcursor += 1;\n\t}\n\tif (pattern[cursor] === \"]\") {\n\t\tcontent += \"\\\\]\";\n\t\thasContent = true;\n\t\tcursor += 1;\n\t}\n\n\tfor (; cursor < pattern.length; cursor += 1) {\n\t\tconst char = pattern[cursor]!;\n\t\tif (char === \"]\") {\n\t\t\tif (!hasContent) return undefined;\n\t\t\treturn { regexSource: `[${negated ? \"^\" : \"\"}${content}]`, closeIndex: cursor };\n\t\t}\n\t\thasContent = true;\n\t\tif (char === \"\\\\\" && cursor + 1 < pattern.length) {\n\t\t\tcursor += 1;\n\t\t\tcontent += escapeEscapedGlobClassCharacter(pattern[cursor]!);\n\t\t\tcontinue;\n\t\t}\n\t\tcontent += escapeGlobClassCharacter(char);\n\t}\n\n\treturn undefined;\n}\n\nfunction compileCommandStringGlob(pattern: string): RegExp {\n\tlet source = \"^\";\n\tfor (let index = 0; index < pattern.length; index += 1) {\n\t\tconst char = pattern[index]!;\n\t\tif (char === \"*\") {\n\t\t\tsource += \".*\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"?\") {\n\t\t\tsource += \".\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"[\") {\n\t\t\tconst bracket = readGlobBracketClass(pattern, index);\n\t\t\tif (bracket !== undefined) {\n\t\t\t\tsource += bracket.regexSource;\n\t\t\t\tindex = bracket.closeIndex;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tif (char === \"\\\\\" && index + 1 < pattern.length) {\n\t\t\tindex += 1;\n\t\t\tsource += escapeRegexLiteral(pattern[index]!);\n\t\t\tcontinue;\n\t\t}\n\t\tsource += escapeRegexLiteral(char);\n\t}\n\treturn new RegExp(`${source}$`);\n}\n\nfunction compileRule(rule: BashCommandRule, listName: \"allow\" | \"deny\", index: number): CompileRuleResult {\n\tif (typeof rule === \"string\") {\n\t\tif (rule.length === 0) {\n\t\t\treturn { ok: false, message: `${listName}[${index}] exact rule must not be empty` };\n\t\t}\n\t\treturn { ok: true, rule: { kind: \"exact\", source: rule, value: rule } };\n\t}\n\n\tif (typeof rule !== \"object\" || rule === null || Array.isArray(rule)) {\n\t\treturn { ok: false, message: `${listName}[${index}] rule must be a non-empty string or an object rule` };\n\t}\n\n\tconst hasPrefix = hasOwnRuleKey(rule, \"prefix\");\n\tconst hasGlob = hasOwnRuleKey(rule, \"glob\");\n\tconst hasRegex = hasOwnRuleKey(rule, \"regex\");\n\tconst variantCount = (hasPrefix ? 1 : 0) + (hasGlob ? 1 : 0) + (hasRegex ? 1 : 0);\n\tif (variantCount !== 1) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\tmessage: `${listName}[${index}] must specify exactly one of prefix, glob, or regex`,\n\t\t};\n\t}\n\n\tif (hasPrefix) {\n\t\tif (!hasOnlyRuleKeys(rule, [\"prefix\"])) {\n\t\t\treturn { ok: false, message: `${listName}[${index}] prefix rule must only contain prefix` };\n\t\t}\n\t\tif (typeof rule.prefix !== \"string\") {\n\t\t\treturn { ok: false, message: `${listName}[${index}].prefix must be a string` };\n\t\t}\n\t\tif (rule.prefix.length === 0) {\n\t\t\treturn { ok: false, message: `${listName}[${index}].prefix must not be empty` };\n\t\t}\n\t\treturn { ok: true, rule: { kind: \"prefix\", source: rule, value: rule.prefix } };\n\t}\n\n\tif (hasGlob) {\n\t\tif (!hasOnlyRuleKeys(rule, [\"glob\"])) {\n\t\t\treturn { ok: false, message: `${listName}[${index}] glob rule must only contain glob` };\n\t\t}\n\t\tif (typeof rule.glob !== \"string\") {\n\t\t\treturn { ok: false, message: `${listName}[${index}].glob must be a string` };\n\t\t}\n\t\tif (rule.glob.length === 0) {\n\t\t\treturn { ok: false, message: `${listName}[${index}].glob must not be empty` };\n\t\t}\n\t\ttry {\n\t\t\treturn { ok: true, rule: { kind: \"glob\", source: rule, value: compileCommandStringGlob(rule.glob) } };\n\t\t} catch {\n\t\t\treturn { ok: false, message: `${listName}[${index}].glob is not a valid command string glob` };\n\t\t}\n\t}\n\n\tif (!hasOnlyRuleKeys(rule, [\"regex\", \"flags\"])) {\n\t\treturn { ok: false, message: `${listName}[${index}] regex rule must only contain regex and optional flags` };\n\t}\n\tif (typeof rule.regex !== \"string\") {\n\t\treturn { ok: false, message: `${listName}[${index}].regex must be a string` };\n\t}\n\tif (rule.regex.length === 0) {\n\t\treturn { ok: false, message: `${listName}[${index}].regex must not be empty` };\n\t}\n\tconst hasFlags = hasOwnRuleKey(rule, \"flags\");\n\tif (hasFlags && typeof rule.flags !== \"string\") {\n\t\treturn { ok: false, message: `${listName}[${index}].flags must be a string when present` };\n\t}\n\tconst flags = hasFlags && typeof rule.flags === \"string\" ? rule.flags : \"\";\n\tif (/[gy]/.test(flags)) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\tmessage: `${listName}[${index}].flags must not include stateful g or y regex flags`,\n\t\t};\n\t}\n\ttry {\n\t\treturn { ok: true, rule: { kind: \"regex\", source: rule, value: new RegExp(rule.regex, flags) } };\n\t} catch {\n\t\treturn { ok: false, message: `${listName}[${index}].regex is not a valid JavaScript RegExp` };\n\t}\n}\n\nfunction compileRules(rules: readonly BashCommandRule[] | undefined, listName: \"allow\" | \"deny\"): CompileRulesResult {\n\tconst compiled: CompiledRule[] = [];\n\tif (rules === undefined) return { ok: true, rules: compiled };\n\tfor (let index = 0; index < rules.length; index += 1) {\n\t\tconst rule = rules[index]!;\n\t\tconst result = compileRule(rule, listName, index);\n\t\tif (!result.ok) return result;\n\t\tcompiled.push(result.rule);\n\t}\n\treturn { ok: true, rules: compiled };\n}\n\nfunction compilePolicy(policy: BashCommandPolicy): CompileResult {\n\tif (typeof policy !== \"object\" || policy === null || Array.isArray(policy)) {\n\t\treturn { ok: false, message: \"bash policy must be a non-null object\" };\n\t}\n\n\tconst unknownKeys = unknownBashPolicyTopLevelKeys(policy);\n\tif (unknownKeys.length > 0) {\n\t\tconst formattedKeys = unknownKeys.map((key) => JSON.stringify(key)).join(\", \");\n\t\treturn {\n\t\t\tok: false,\n\t\t\tmessage: `bash policy contains unknown top-level key${unknownKeys.length === 1 ? \"\" : \"s\"} ${formattedKeys}; allowed keys are default, allow, deny, and match`,\n\t\t};\n\t}\n\n\tconst defaultDecision = policy.default === undefined ? \"allow\" : policy.default;\n\tif (defaultDecision !== \"allow\" && defaultDecision !== \"deny\") {\n\t\treturn { ok: false, message: `bash policy default must be \"allow\" or \"deny\"` };\n\t}\n\tconst match = policy.match === undefined ? \"segments\" : policy.match;\n\tif (match !== \"whole\" && match !== \"segments\") {\n\t\treturn { ok: false, message: `bash policy match must be \"whole\" or \"segments\"` };\n\t}\n\tif (policy.allow !== undefined && !Array.isArray(policy.allow)) {\n\t\treturn { ok: false, message: \"bash policy allow must be an array\" };\n\t}\n\tif (policy.deny !== undefined && !Array.isArray(policy.deny)) {\n\t\treturn { ok: false, message: \"bash policy deny must be an array\" };\n\t}\n\n\tconst allow = compileRules(policy.allow, \"allow\");\n\tif (!allow.ok) return allow;\n\tconst deny = compileRules(policy.deny, \"deny\");\n\tif (!deny.ok) return deny;\n\n\treturn {\n\t\tok: true,\n\t\tpolicy: {\n\t\t\tdefaultDecision,\n\t\t\tmatch,\n\t\t\tallow: allow.rules,\n\t\t\tdeny: deny.rules,\n\t\t},\n\t};\n}\n\nexport function validateBashCommandPolicy(policy: BashCommandPolicy): void {\n\tconst compiled = compilePolicy(policy);\n\tif (!compiled.ok) {\n\t\tthrow new Error(`Invalid bash command policy: ${compiled.message}`);\n\t}\n}\n\nfunction shellError(reason: string, offset: number, source: BashCommandSegmentSource): BashCommandParseResult {\n\treturn { ok: false, error: { reason, offset, source } };\n}\n\nfunction isWhitespace(char: string): boolean {\n\treturn char === \" \" || char === \"\\t\" || char === \"\\n\" || char === \"\\r\";\n}\n\nfunction lineTerminatorLengthAt(input: string, index: number): number {\n\tconst char = input[index];\n\tif (char === \"\\r\") return input[index + 1] === \"\\n\" ? 2 : 1;\n\tif (char === \"\\n\") return 1;\n\treturn 0;\n}\n\nfunction previousNonWhitespace(input: string, index: number): string | undefined {\n\tfor (let i = index - 1; i >= 0; i -= 1) {\n\t\tconst char = input[i]!;\n\t\tif (!isWhitespace(char)) return char;\n\t}\n\treturn undefined;\n}\n\nfunction isRedirectionAmpersand(input: string, index: number): boolean {\n\tconst previous = previousNonWhitespace(input, index);\n\tconst next = input[index + 1];\n\treturn previous === \">\" || previous === \"<\" || next === \">\";\n}\n\nfunction operatorLengthAt(input: string, index: number): number {\n\tconst char = input[index];\n\tconst next = input[index + 1];\n\tif (char === \"|\" && input[index - 1] === \">\") return 0;\n\tif (char === \"|\" && next === \"&\") return 2;\n\tif (char === \"&\" && next === \"&\") return 2;\n\tif (char === \"|\" && next === \"|\") return 2;\n\tif (char === \"|\") return 1;\n\tif (char === \";\") return 1;\n\tif (char === \"&\" && !isRedirectionAmpersand(input, index)) return 1;\n\treturn 0;\n}\n\nfunction isHereDocumentAt(input: string, index: number): boolean {\n\treturn input[index] === \"<\" && input[index + 1] === \"<\";\n}\n\nfunction isCommandSubstitutionAt(input: string, index: number): boolean {\n\treturn input[index] === \"$\" && input[index + 1] === \"(\";\n}\n\nfunction isProcessSubstitutionAt(input: string, index: number): boolean {\n\tconst char = input[index];\n\treturn (char === \"<\" || char === \">\") && input[index + 1] === \"(\";\n}\n\nfunction findClosingBacktick(input: string, openIndex: number): ClosingBacktickResult {\n\tfor (let i = openIndex + 1; i < input.length; i += 1) {\n\t\tconst char = input[i]!;\n\t\tif (char === \"\\\\\") {\n\t\t\tif (i + 1 >= input.length) {\n\t\t\t\treturn { ok: false, reason: \"trailing escape in backtick command substitution\", offset: i };\n\t\t\t}\n\t\t\ti += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"`\") return { ok: true, closeIndex: i };\n\t}\n\treturn { ok: false, reason: \"unclosed backtick command substitution\", offset: openIndex };\n}\n\nfunction findClosingParen(input: string, openIndex: number, construct: string): ClosingParenResult {\n\tlet quote: ShellQuoteState = \"none\";\n\tlet depth = 1;\n\tfor (let i = openIndex + 1; i < input.length; i += 1) {\n\t\tconst char = input[i]!;\n\n\t\tif (quote === \"single\") {\n\t\t\tif (char === \"'\") quote = \"none\";\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"\\\\\") {\n\t\t\tif (i + 1 >= input.length) {\n\t\t\t\treturn { ok: false, reason: `trailing escape in ${construct}`, offset: i };\n\t\t\t}\n\t\t\ti += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (quote === \"double\") {\n\t\t\tif (char === \"\\\"\") {\n\t\t\t\tquote = \"none\";\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (isCommandSubstitutionAt(input, i) || isProcessSubstitutionAt(input, i)) {\n\t\t\t\tdepth += 1;\n\t\t\t\ti += 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (char === \"`\") {\n\t\t\t\tconst close = findClosingBacktick(input, i);\n\t\t\t\tif (!close.ok) return close;\n\t\t\t\ti = close.closeIndex;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"'\") {\n\t\t\tquote = \"single\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"\\\"\") {\n\t\t\tquote = \"double\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (isCommandSubstitutionAt(input, i) || isProcessSubstitutionAt(input, i)) {\n\t\t\tdepth += 1;\n\t\t\ti += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"`\") {\n\t\t\tconst close = findClosingBacktick(input, i);\n\t\t\tif (!close.ok) return close;\n\t\t\ti = close.closeIndex;\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"(\") {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\treason: `unsupported shell grouping parentheses in ${construct}`,\n\t\t\t\toffset: i,\n\t\t\t};\n\t\t}\n\t\tif (char === \")\") {\n\t\t\tdepth -= 1;\n\t\t\tif (depth === 0) return { ok: true, closeIndex: i };\n\t\t}\n\t}\n\n\tif (quote === \"single\") return { ok: false, reason: `unclosed single quote in ${construct}`, offset: openIndex };\n\tif (quote === \"double\") return { ok: false, reason: `unclosed double quote in ${construct}`, offset: openIndex };\n\treturn { ok: false, reason: `unclosed ${construct}`, offset: openIndex };\n}\n\nfunction readShellWord(input: string, start: number): ShellWordReadResult {\n\tlet quote: ShellQuoteState = \"none\";\n\tlet sawSingleQuote = false;\n\tlet sawDoubleQuote = false;\n\tlet sawEscape = false;\n\tlet sawParameterExpansion = false;\n\tlet sawCommandSubstitution = false;\n\tlet sawProcessSubstitution = false;\n\tlet sawBacktick = false;\n\tlet sawGlobPattern = false;\n\tlet sawBraceExpansion = false;\n\tlet sawTildePrefix = false;\n\n\tconst metadata = (): ShellWordMetadata => ({\n\t\tsawSingleQuote,\n\t\tsawDoubleQuote,\n\t\tsawEscape,\n\t\tsawParameterExpansion,\n\t\tsawCommandSubstitution,\n\t\tsawProcessSubstitution,\n\t\tsawBacktick,\n\t\tsawGlobPattern,\n\t\tsawBraceExpansion,\n\t\tsawTildePrefix,\n\t});\n\n\tfor (let i = start; i < input.length; i += 1) {\n\t\tconst char = input[i]!;\n\t\tif (quote === \"single\") {\n\t\t\tif (char === \"'\") quote = \"none\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"\\\\\") {\n\t\t\tsawEscape = true;\n\t\t\tif (i + 1 >= input.length) return { ok: false, reason: \"trailing escape in shell word\", offset: i };\n\t\t\ti += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tif (quote === \"double\") {\n\t\t\tif (char === \"\\\"\") {\n\t\t\t\tquote = \"none\";\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (isCommandSubstitutionAt(input, i) || isProcessSubstitutionAt(input, i)) {\n\t\t\t\tif (isCommandSubstitutionAt(input, i)) {\n\t\t\t\t\tsawCommandSubstitution = true;\n\t\t\t\t} else {\n\t\t\t\t\tsawProcessSubstitution = true;\n\t\t\t\t}\n\t\t\t\tconst close = findClosingParen(input, i + 1, isCommandSubstitutionAt(input, i) ? \"command substitution `$(`\" : \"process substitution\");\n\t\t\t\tif (!close.ok) return { ok: false, reason: close.reason, offset: close.offset };\n\t\t\t\ti = close.closeIndex;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (char === \"`\") {\n\t\t\t\tsawBacktick = true;\n\t\t\t\tconst close = findClosingBacktick(input, i);\n\t\t\t\tif (!close.ok) return { ok: false, reason: close.reason, offset: close.offset };\n\t\t\t\ti = close.closeIndex;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (char === \"$\") sawParameterExpansion = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (isWhitespace(char)) {\n\t\t\treturn { ok: true, word: input.slice(start, i), end: i, metadata: metadata() };\n\t\t}\n\t\tif (char === \"'\") {\n\t\t\tsawSingleQuote = true;\n\t\t\tquote = \"single\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"\\\"\") {\n\t\t\tsawDoubleQuote = true;\n\t\t\tquote = \"double\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (i === start && char === \"~\") {\n\t\t\tsawTildePrefix = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (isCommandSubstitutionAt(input, i) || isProcessSubstitutionAt(input, i)) {\n\t\t\tif (isCommandSubstitutionAt(input, i)) {\n\t\t\t\tsawCommandSubstitution = true;\n\t\t\t} else {\n\t\t\t\tsawProcessSubstitution = true;\n\t\t\t}\n\t\t\tconst close = findClosingParen(input, i + 1, isCommandSubstitutionAt(input, i) ? \"command substitution `$(`\" : \"process substitution\");\n\t\t\tif (!close.ok) return { ok: false, reason: close.reason, offset: close.offset };\n\t\t\ti = close.closeIndex;\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"`\") {\n\t\t\tsawBacktick = true;\n\t\t\tconst close = findClosingBacktick(input, i);\n\t\t\tif (!close.ok) return { ok: false, reason: close.reason, offset: close.offset };\n\t\t\ti = close.closeIndex;\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"$\") {\n\t\t\tsawParameterExpansion = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"*\" || char === \"?\" || char === \"[\" || char === \"]\") {\n\t\t\tsawGlobPattern = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"{\" || char === \"}\") {\n\t\t\tsawBraceExpansion = true;\n\t\t}\n\t}\n\tif (quote === \"single\") return { ok: false, reason: \"unclosed single quote in shell word\", offset: start };\n\tif (quote === \"double\") return { ok: false, reason: \"unclosed double quote in shell word\", offset: start };\n\treturn { ok: true, word: input.slice(start), end: input.length, metadata: metadata() };\n}\n\nfunction isAsciiDigit(char: string | undefined): boolean {\n\treturn char !== undefined && char >= \"0\" && char <= \"9\";\n}\n\nfunction leadingRedirectionTokenAt(input: string, index: number): string | undefined {\n\tlet operatorStart = index;\n\twhile (isAsciiDigit(input[operatorStart])) operatorStart += 1;\n\n\tconst hasDescriptorPrefix = operatorStart > index;\n\tconst char = input[operatorStart];\n\tconst next = input[operatorStart + 1];\n\tconst afterNext = input[operatorStart + 2];\n\n\tif (char === undefined) return undefined;\n\tif (hasDescriptorPrefix && char !== \"<\" && char !== \">\") return undefined;\n\n\tif (!hasDescriptorPrefix && (char === \"<\" || char === \">\") && next === \"(\") {\n\t\treturn undefined;\n\t}\n\n\tlet operator: string | undefined;\n\tif (char === \"&\" && next === \">\") {\n\t\toperator = afterNext === \">\" ? \"&>>\" : \"&>\";\n\t} else if (char === \"<\") {\n\t\tif (next === \"<\") operator = \"<<\";\n\t\telse if (next === \"&\") operator = \"<&\";\n\t\telse if (next === \">\") operator = \"<>\";\n\t\telse operator = \"<\";\n\t} else if (char === \">\") {\n\t\tif (next === \">\") operator = \">>\";\n\t\telse if (next === \"|\") operator = \">|\";\n\t\telse if (next === \"&\") operator = \">&\";\n\t\telse operator = \">\";\n\t}\n\n\treturn operator === undefined ? undefined : `${input.slice(index, operatorStart)}${operator}`;\n}\n\nfunction isEnvAssignmentWord(word: string): boolean {\n\treturn /^[A-Za-z_][A-Za-z0-9_]*(?:\\+)?=/.test(word);\n}\n\ninterface AttachedRedirectionToken {\n\treadonly token: string;\n\treadonly offset: number;\n}\n\nfunction attachedRedirectionOperatorAt(input: string, index: number): string | undefined {\n\tconst char = input[index];\n\tconst next = input[index + 1];\n\tconst afterNext = input[index + 2];\n\n\tif ((char === \"<\" || char === \">\") && next === \"(\") {\n\t\treturn undefined;\n\t}\n\tif (char === \"&\" && next === \">\") {\n\t\treturn afterNext === \">\" ? \"&>>\" : \"&>\";\n\t}\n\tif (char === \"<\") {\n\t\tif (next === \"<\") return \"<<\";\n\t\tif (next === \"&\") return \"<&\";\n\t\tif (next === \">\") return \"<>\";\n\t\treturn \"<\";\n\t}\n\tif (char === \">\") {\n\t\tif (next === \">\") return \">>\";\n\t\tif (next === \"|\") return \">|\";\n\t\tif (next === \"&\") return \">&\";\n\t\treturn \">\";\n\t}\n\treturn undefined;\n}\n\nfunction attachedCommandHeadRedirection(\n\tinput: string,\n\tstart: number,\n\tend: number,\n): AttachedRedirectionToken | undefined {\n\tlet quote: ShellQuoteState = \"none\";\n\n\tfor (let i = start; i < end; i += 1) {\n\t\tconst char = input[i]!;\n\t\tif (quote === \"single\") {\n\t\t\tif (char === \"'\") quote = \"none\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"\\\\\") {\n\t\t\ti += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tif (quote === \"double\") {\n\t\t\tif (char === \"\\\"\") {\n\t\t\t\tquote = \"none\";\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (isCommandSubstitutionAt(input, i) || isProcessSubstitutionAt(input, i)) {\n\t\t\t\tconst close = findClosingParen(input, i + 1, isCommandSubstitutionAt(input, i) ? \"command substitution `$(`\" : \"process substitution\");\n\t\t\t\tif (close.ok) i = close.closeIndex;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (char === \"`\") {\n\t\t\t\tconst close = findClosingBacktick(input, i);\n\t\t\t\tif (close.ok) i = close.closeIndex;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"'\") {\n\t\t\tquote = \"single\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"\\\"\") {\n\t\t\tquote = \"double\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (isCommandSubstitutionAt(input, i) || isProcessSubstitutionAt(input, i)) {\n\t\t\tconst close = findClosingParen(input, i + 1, isCommandSubstitutionAt(input, i) ? \"command substitution `$(`\" : \"process substitution\");\n\t\t\tif (close.ok) i = close.closeIndex;\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"`\") {\n\t\t\tconst close = findClosingBacktick(input, i);\n\t\t\tif (close.ok) i = close.closeIndex;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst operator = attachedRedirectionOperatorAt(input, i);\n\t\tif (operator !== undefined && i > start) {\n\t\t\treturn { token: operator, offset: i };\n\t\t}\n\t}\n\n\treturn undefined;\n}\n\nfunction validateLiteralCommandHead(head: string, metadata: ShellWordMetadata): LiteralCommandHeadValidation {\n\tif (head.length === 0) {\n\t\treturn { ok: false, reason: \"empty command heads are not supported by bash policy segments mode\" };\n\t}\n\tif (metadata.sawSingleQuote || metadata.sawDoubleQuote) {\n\t\treturn { ok: false, reason: \"quoted or quote-constructed command heads are not supported by bash policy segments mode\" };\n\t}\n\tif (metadata.sawEscape) {\n\t\treturn { ok: false, reason: \"escape-constructed command heads are not supported by bash policy segments mode\" };\n\t}\n\tif (metadata.sawCommandSubstitution || metadata.sawProcessSubstitution || metadata.sawBacktick) {\n\t\treturn { ok: false, reason: \"command, process, and backtick substitutions are not supported in command heads by bash policy segments mode\" };\n\t}\n\tif (metadata.sawParameterExpansion) {\n\t\treturn { ok: false, reason: \"parameter-expanded command heads are not supported by bash policy segments mode\" };\n\t}\n\tif (metadata.sawTildePrefix) {\n\t\treturn { ok: false, reason: \"tilde-expanded command heads are not supported by bash policy segments mode\" };\n\t}\n\tif (metadata.sawGlobPattern) {\n\t\treturn { ok: false, reason: \"glob-expanded command heads are not supported by bash policy segments mode\" };\n\t}\n\tif (metadata.sawBraceExpansion) {\n\t\treturn { ok: false, reason: \"brace-expanded command heads are not supported by bash policy segments mode\" };\n\t}\n\treturn { ok: true };\n}\n\nfunction buildSegment(\n\trawSegment: string,\n\tabsoluteStart: number,\n\tabsoluteEnd: number,\n\tsource: BashCommandSegmentSource,\n): SegmentBuildResult {\n\tlet cursor = 0;\n\twhile (cursor < rawSegment.length && isWhitespace(rawSegment[cursor]!)) cursor += 1;\n\tif (cursor >= rawSegment.length) return { ok: true };\n\n\twhile (cursor < rawSegment.length) {\n\t\twhile (cursor < rawSegment.length && isWhitespace(rawSegment[cursor]!)) cursor += 1;\n\t\tif (cursor >= rawSegment.length) return { ok: true };\n\n\t\tconst leadingRedirection = leadingRedirectionTokenAt(rawSegment, cursor);\n\t\tif (leadingRedirection !== undefined) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: {\n\t\t\t\t\treason: `leading shell redirection ${JSON.stringify(leadingRedirection)} is not supported by bash policy segments mode`,\n\t\t\t\t\toffset: absoluteStart + cursor,\n\t\t\t\t\tsource,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst word = readShellWord(rawSegment, cursor);\n\t\tif (!word.ok) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: { reason: word.reason, offset: absoluteStart + word.offset, source },\n\t\t\t};\n\t\t}\n\n\t\tconst attachedRedirection = attachedCommandHeadRedirection(rawSegment, cursor, word.end);\n\t\tif (attachedRedirection !== undefined) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: {\n\t\t\t\t\treason: `attached shell redirection ${JSON.stringify(attachedRedirection.token)} in the command head is not supported by bash policy segments mode`,\n\t\t\t\t\toffset: absoluteStart + attachedRedirection.offset,\n\t\t\t\t\tsource,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tif (isEnvAssignmentWord(word.word)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: {\n\t\t\t\t\treason: \"environment assignment words are not supported by bash policy segments mode\",\n\t\t\t\t\toffset: absoluteStart + cursor,\n\t\t\t\t\tsource,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst target = rawSegment.slice(cursor).trim();\n\t\tconst head = word.word;\n\t\tif (UNSUPPORTED_CONTROL_HEADS.has(head)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: {\n\t\t\t\t\treason: `unsupported shell reserved or compound syntax starting with ${JSON.stringify(head)}`,\n\t\t\t\t\toffset: absoluteStart + cursor,\n\t\t\t\t\tsource,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tconst literalHead = validateLiteralCommandHead(head, word.metadata);\n\t\tif (!literalHead.ok) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: {\n\t\t\t\t\treason: literalHead.reason,\n\t\t\t\t\toffset: absoluteStart + cursor,\n\t\t\t\t\tsource,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tok: true,\n\t\t\tsegment: {\n\t\t\t\traw: rawSegment.trim(),\n\t\t\t\ttarget,\n\t\t\t\thead,\n\t\t\t\tstart: absoluteStart + cursor,\n\t\t\t\tend: absoluteEnd,\n\t\t\t\tsource,\n\t\t\t},\n\t\t};\n\t}\n\n\treturn { ok: true };\n}\n\nfunction parseSegmentsInSource(\n\tinput: string,\n\tbaseOffset: number,\n\tsource: BashCommandSegmentSource,\n): BashCommandParseResult {\n\tconst segments: BashCommandSegment[] = [];\n\tlet quote: ShellQuoteState = \"none\";\n\tlet segmentStart = 0;\n\tlet nestedForCurrentSegment: BashCommandSegment[] = [];\n\n\tconst commitSegment = (end: number): BashCommandParseResult | undefined => {\n\t\tconst built = buildSegment(input.slice(segmentStart, end), baseOffset + segmentStart, baseOffset + end, source);\n\t\tif (!built.ok) return { ok: false, error: built.error };\n\t\tif (built.segment) segments.push(built.segment);\n\t\tsegments.push(...nestedForCurrentSegment);\n\t\tnestedForCurrentSegment = [];\n\t\treturn undefined;\n\t};\n\n\tfor (let i = 0; i < input.length; i += 1) {\n\t\tconst char = input[i]!;\n\n\t\tif (quote === \"single\") {\n\t\t\tif (char === \"'\") quote = \"none\";\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"\\\\\") {\n\t\t\tif (i + 1 >= input.length) {\n\t\t\t\treturn shellError(\"trailing escape\", baseOffset + i, source);\n\t\t\t}\n\t\t\ti += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (quote === \"double\") {\n\t\t\tif (char === \"\\\"\") {\n\t\t\t\tquote = \"none\";\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (isCommandSubstitutionAt(input, i)) {\n\t\t\t\tconst close = findClosingParen(input, i + 1, \"command substitution `$(`\");\n\t\t\t\tif (!close.ok) return shellError(close.reason, baseOffset + close.offset, source);\n\t\t\t\tconst nested = parseSegmentsInSource(input.slice(i + 2, close.closeIndex), baseOffset + i + 2, \"command-substitution\");\n\t\t\t\tif (!nested.ok) return nested;\n\t\t\t\tnestedForCurrentSegment.push(...nested.segments);\n\t\t\t\ti = close.closeIndex;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (char === \"`\") {\n\t\t\t\tconst close = findClosingBacktick(input, i);\n\t\t\t\tif (!close.ok) return shellError(close.reason, baseOffset + close.offset, source);\n\t\t\t\tconst nested = parseSegmentsInSource(input.slice(i + 1, close.closeIndex), baseOffset + i + 1, \"backtick\");\n\t\t\t\tif (!nested.ok) return nested;\n\t\t\t\tnestedForCurrentSegment.push(...nested.segments);\n\t\t\t\ti = close.closeIndex;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"'\") {\n\t\t\tquote = \"single\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"\\\"\") {\n\t\t\tquote = \"double\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (isHereDocumentAt(input, i)) {\n\t\t\treturn shellError(\"here-documents are not supported by bash policy segments mode\", baseOffset + i, source);\n\t\t}\n\t\tif (isCommandSubstitutionAt(input, i)) {\n\t\t\tconst close = findClosingParen(input, i + 1, \"command substitution `$(`\");\n\t\t\tif (!close.ok) return shellError(close.reason, baseOffset + close.offset, source);\n\t\t\tconst nested = parseSegmentsInSource(input.slice(i + 2, close.closeIndex), baseOffset + i + 2, \"command-substitution\");\n\t\t\tif (!nested.ok) return nested;\n\t\t\tnestedForCurrentSegment.push(...nested.segments);\n\t\t\ti = close.closeIndex;\n\t\t\tcontinue;\n\t\t}\n\t\tif (isProcessSubstitutionAt(input, i)) {\n\t\t\tconst close = findClosingParen(input, i + 1, \"process substitution\");\n\t\t\tif (!close.ok) return shellError(close.reason, baseOffset + close.offset, source);\n\t\t\tconst nested = parseSegmentsInSource(input.slice(i + 2, close.closeIndex), baseOffset + i + 2, \"process-substitution\");\n\t\t\tif (!nested.ok) return nested;\n\t\t\tnestedForCurrentSegment.push(...nested.segments);\n\t\t\ti = close.closeIndex;\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"`\") {\n\t\t\tconst close = findClosingBacktick(input, i);\n\t\t\tif (!close.ok) return shellError(close.reason, baseOffset + close.offset, source);\n\t\t\tconst nested = parseSegmentsInSource(input.slice(i + 1, close.closeIndex), baseOffset + i + 1, \"backtick\");\n\t\t\tif (!nested.ok) return nested;\n\t\t\tnestedForCurrentSegment.push(...nested.segments);\n\t\t\ti = close.closeIndex;\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"(\" || char === \")\") {\n\t\t\treturn shellError(\"unsupported shell grouping parentheses\", baseOffset + i, source);\n\t\t}\n\n\t\tconst lineTerminatorLength = lineTerminatorLengthAt(input, i);\n\t\tif (lineTerminatorLength > 0) {\n\t\t\tconst committed = commitSegment(i);\n\t\t\tif (committed) return committed;\n\t\t\ti += lineTerminatorLength - 1;\n\t\t\tsegmentStart = i + 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst operatorLength = operatorLengthAt(input, i);\n\t\tif (operatorLength > 0) {\n\t\t\tconst committed = commitSegment(i);\n\t\t\tif (committed) return committed;\n\t\t\ti += operatorLength - 1;\n\t\t\tsegmentStart = i + 1;\n\t\t}\n\t}\n\n\tif (quote === \"single\") return shellError(\"unclosed single quote\", baseOffset + input.length, source);\n\tif (quote === \"double\") return shellError(\"unclosed double quote\", baseOffset + input.length, source);\n\tconst committed = commitSegment(input.length);\n\tif (committed) return committed;\n\treturn { ok: true, segments };\n}\n\nexport function parseBashCommandSegments(command: string): BashCommandParseResult {\n\treturn parseSegmentsInSource(command, 0, \"top-level\");\n}\n\nfunction wholeCommandTarget(command: string): BashCommandSegment {\n\tconst target = command;\n\tconst trimmed = command.trimStart();\n\tconst leading = command.length - trimmed.length;\n\tconst firstSpace = trimmed.search(/\\s/);\n\tconst head = firstSpace === -1 ? trimmed : trimmed.slice(0, firstSpace);\n\treturn {\n\t\traw: command,\n\t\ttarget,\n\t\thead,\n\t\tstart: leading,\n\t\tend: command.length,\n\t\tsource: \"top-level\",\n\t};\n}\n\nfunction ruleMatches(rule: CompiledRule, target: string): boolean {\n\tswitch (rule.kind) {\n\t\tcase \"exact\":\n\t\t\treturn target === rule.value;\n\t\tcase \"prefix\":\n\t\t\treturn target.startsWith(rule.value);\n\t\tcase \"glob\":\n\t\t\treturn rule.value.test(target);\n\t\tcase \"regex\":\n\t\t\treturn rule.value.test(target);\n\t}\n}\n\nfunction firstMatchingRule(rules: readonly CompiledRule[], target: string): BashCommandRule | undefined {\n\tfor (const rule of rules) {\n\t\tif (ruleMatches(rule, target)) return rule.source;\n\t}\n\treturn undefined;\n}\n\nfunction invalidPolicyMode(policy: BashCommandPolicy): BashCommandPolicyMatchMode {\n\tif (typeof policy !== \"object\" || policy === null || Array.isArray(policy)) return \"segments\";\n\treturn policy.match === \"whole\" ? \"whole\" : \"segments\";\n}\n\nfunction isNoRuleDefaultAllowPolicy(policy: CompiledBashCommandPolicy): boolean {\n\treturn policy.defaultDecision === \"allow\" && policy.allow.length === 0 && policy.deny.length === 0;\n}\n\nexport function evaluateBashCommandPolicy(\n\tcommand: string,\n\tpolicy: BashCommandPolicy | undefined,\n): BashCommandPolicyDecision {\n\tif (policy === undefined) {\n\t\treturn { allowed: true, mode: \"segments\", targets: [] };\n\t}\n\n\tconst compiled = compilePolicy(policy);\n\tif (!compiled.ok) {\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\tmode: invalidPolicyMode(policy),\n\t\t\ttargets: [],\n\t\t\trejection: {\n\t\t\t\treason: \"invalid-policy\",\n\t\t\t\tmessage: compiled.message,\n\t\t\t},\n\t\t};\n\t}\n\n\tconst activePolicy = compiled.policy;\n\tif (isNoRuleDefaultAllowPolicy(activePolicy)) {\n\t\treturn { allowed: true, mode: activePolicy.match, targets: [] };\n\t}\n\n\tconst targetsResult: BashCommandParseResult = activePolicy.match === \"whole\"\n\t\t? { ok: true, segments: [wholeCommandTarget(command)] }\n\t\t: parseBashCommandSegments(command);\n\n\tif (!targetsResult.ok) {\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\tmode: activePolicy.match,\n\t\t\ttargets: [],\n\t\t\trejection: {\n\t\t\t\treason: \"unsupported-shell-syntax\",\n\t\t\t\tmessage: targetsResult.error.reason,\n\t\t\t\tparseError: targetsResult.error,\n\t\t\t},\n\t\t};\n\t}\n\n\tfor (const target of targetsResult.segments) {\n\t\tconst denyRule = firstMatchingRule(activePolicy.deny, target.target);\n\t\tif (denyRule !== undefined) {\n\t\t\treturn {\n\t\t\t\tallowed: false,\n\t\t\t\tmode: activePolicy.match,\n\t\t\t\ttargets: targetsResult.segments,\n\t\t\t\trejection: {\n\t\t\t\t\treason: \"matched-deny\",\n\t\t\t\t\tmessage: `command ${JSON.stringify(target.head)} matched a deny rule`,\n\t\t\t\t\ttarget,\n\t\t\t\t\tmatchedRule: denyRule,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst allowRule = firstMatchingRule(activePolicy.allow, target.target);\n\t\tif (allowRule !== undefined || activePolicy.defaultDecision === \"allow\") {\n\t\t\tcontinue;\n\t\t}\n\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\tmode: activePolicy.match,\n\t\t\ttargets: targetsResult.segments,\n\t\t\trejection: {\n\t\t\t\treason: \"default-deny\",\n\t\t\t\tmessage: `command ${JSON.stringify(target.head)} is not permitted by default-deny bash policy`,\n\t\t\t\ttarget,\n\t\t\t},\n\t\t};\n\t}\n\n\treturn { allowed: true, mode: activePolicy.match, targets: targetsResult.segments };\n}\n\nfunction formatRule(rule: BashCommandRule): string {\n\tif (typeof rule === \"string\") return JSON.stringify(rule);\n\tif (\"prefix\" in rule) return `{ prefix: ${JSON.stringify(rule.prefix)} }`;\n\tif (\"glob\" in rule) return `{ glob: ${JSON.stringify(rule.glob)} }`;\n\treturn rule.flags === undefined\n\t\t? `{ regex: ${JSON.stringify(rule.regex)} }`\n\t\t: `{ regex: ${JSON.stringify(rule.regex)}, flags: ${JSON.stringify(rule.flags)} }`;\n}\n\nexport function formatBashCommandPolicyRejection(\n\tdecision: Extract<BashCommandPolicyDecision, { readonly allowed: false }>,\n\tpolicyLabel = \"bash command policy\",\n): string {\n\tconst lines = [`Bash command blocked by ${policyLabel}.`, \"\"];\n\tconst rejection = decision.rejection;\n\n\tif (rejection.reason === \"unsupported-shell-syntax\") {\n\t\tlines.push(\n\t\t\t\"The command uses shell syntax that Atomic cannot safely parse in `segments` mode.\",\n\t\t\t`Reason: ${rejection.message}.`,\n\t\t);\n\t\tif (rejection.parseError) {\n\t\t\tlines.push(`Parser source: ${rejection.parseError.source} at offset ${rejection.parseError.offset}.`);\n\t\t}\n\t\tlines.push(\n\t\t\t\"Use match: \\\"whole\\\" only if the caller intentionally accepts raw-command matching semantics.\",\n\t\t);\n\t} else if (rejection.reason === \"invalid-policy\") {\n\t\tlines.push(\"The configured bash command policy is invalid.\", `Reason: ${rejection.message}.`);\n\t} else {\n\t\tconst target = rejection.target;\n\t\tif (target) {\n\t\t\tlines.push(\n\t\t\t\t`Command head: \\`${truncateDiagnostic(target.head)}\\``,\n\t\t\t\t`Rejected ${decision.mode === \"whole\" ? \"command\" : \"segment\"}: \\`${truncateDiagnostic(target.target)}\\``,\n\t\t\t\t`Segment source: ${target.source}`,\n\t\t\t);\n\t\t}\n\t\tif (rejection.reason === \"matched-deny\") {\n\t\t\tlines.push(\"Reason: matched a deny rule; deny rules take precedence over allow rules.\");\n\t\t\tif (rejection.matchedRule !== undefined) {\n\t\t\t\tlines.push(`Matched deny rule: ${formatRule(rejection.matchedRule)}`);\n\t\t\t}\n\t\t} else {\n\t\t\tlines.push(\"Reason: no allow rule matched and the policy default is deny.\");\n\t\t}\n\t}\n\n\tlines.push(`Policy mode: ${decision.mode}.`, \"\", \"No shell process was started.\");\n\treturn lines.join(\"\\n\");\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  import type { AgentTool } from "@earendil-works/pi-agent-core";
2
2
  import { type Static, Type } from "typebox";
3
3
  import type { ToolDefinition } from "../extensions/types.ts";
4
+ import { type BashCommandPolicy } from "./bash-policy.ts";
4
5
  import { type TruncationResult } from "./truncate.ts";
5
6
  declare const bashSchema: Type.TObject<{
6
7
  command: Type.TString;
@@ -56,6 +57,10 @@ export interface BashToolOptions {
56
57
  shellPath?: string;
57
58
  /** Hook to adjust command, cwd, or env before execution */
58
59
  spawnHook?: BashSpawnHook;
60
+ /** Optional command-level policy enforced before commandPrefix, spawnHook, or execution */
61
+ policy?: BashCommandPolicy;
62
+ /** Human-readable label used in policy denial errors */
63
+ policyLabel?: string;
59
64
  }
60
65
  type BashRenderState = {
61
66
  startedAt: number | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../../src/core/tools/bash.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAG/D,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAa5C,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,wBAAwB,CAAC;AAItF,OAAO,EAAoD,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAExG,QAAA,MAAM,UAAU;;;EAGd,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC/B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B;;;;;;OAMG;IACH,IAAI,EAAE,CACL,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,OAAO,EAAE;QACR,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;QAC/B,MAAM,CAAC,EAAE,WAAW,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;KACxB,KACG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;CAC1C;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,cAAc,CA4D1F;AAED,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;CACvB;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,gBAAgB,CAAC;AAO5E,MAAM,WAAW,eAAe;IAC/B,oEAAoE;IACpE,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,mFAAmF;IACnF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,aAAa,CAAC;CAC1B;AAKD,KAAK,eAAe,GAAG;IACtB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC,OAAO,GAAG,SAAS,CAAC;CACrC,CAAC;AAoHF,wBAAgB,wBAAwB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,eAAe,GACvB,cAAc,CAAC,OAAO,UAAU,EAAE,eAAe,GAAG,SAAS,EAAE,eAAe,CAAC,CAyKjF;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAEnG","sourcesContent":["import { constants } from \"node:fs\";\nimport { access as fsAccess } from \"node:fs/promises\";\nimport type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { Container, Text, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport { spawn } from \"child_process\";\nimport { type Static, Type } from \"typebox\";\nimport { APP_NAME } from \"../../config.ts\";\nimport { keyHint } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport { truncateToVisualLines } from \"../../modes/interactive/components/visual-truncate.ts\";\nimport { theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { waitForChildProcess } from \"../../utils/child-process.ts\";\nimport {\n\tgetShellConfig,\n\tgetShellEnv,\n\tkillProcessTree,\n\ttrackDetachedChildPid,\n\tuntrackDetachedChildPid,\n} from \"../../utils/shell.ts\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.ts\";\nimport { OutputAccumulator } from \"./output-accumulator.ts\";\nimport { getTextOutput, invalidArgText, str } from \"./render-utils.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationResult } from \"./truncate.ts\";\n\nconst bashSchema = Type.Object({\n\tcommand: Type.String({ description: \"Bash command to execute\" }),\n\ttimeout: Type.Optional(Type.Number({ description: \"Timeout in seconds (optional, no default timeout)\" })),\n});\n\nexport type BashToolInput = Static<typeof bashSchema>;\n\nexport interface BashToolDetails {\n\ttruncation?: TruncationResult;\n\tfullOutputPath?: string;\n}\n\n/**\n * Pluggable operations for the bash tool.\n * Override these to delegate command execution to remote systems (for example SSH).\n */\nexport interface BashOperations {\n\t/**\n\t * Execute a command and stream output.\n\t * @param command The command to execute\n\t * @param cwd Working directory\n\t * @param options Execution options\n\t * @returns Promise resolving to exit code (null if killed)\n\t */\n\texec: (\n\t\tcommand: string,\n\t\tcwd: string,\n\t\toptions: {\n\t\t\tonData: (data: Buffer) => void;\n\t\t\tsignal?: AbortSignal;\n\t\t\ttimeout?: number;\n\t\t\tenv?: NodeJS.ProcessEnv;\n\t\t},\n\t) => Promise<{ exitCode: number | null }>;\n}\n\n/**\n * Create bash operations using pi's built-in local shell execution backend.\n *\n * This is useful for extensions that intercept user_bash and still want pi's\n * standard local shell behavior while wrapping or rewriting commands.\n */\nexport function createLocalBashOperations(options?: { shellPath?: string }): BashOperations {\n\treturn {\n\t\texec: async (command, cwd, { onData, signal, timeout, env }) => {\n\t\t\tconst { shell, args } = getShellConfig(options?.shellPath);\n\t\t\ttry {\n\t\t\t\tawait fsAccess(cwd, constants.F_OK);\n\t\t\t} catch {\n\t\t\t\tthrow new Error(`Working directory does not exist: ${cwd}\\nCannot execute bash commands.`);\n\t\t\t}\n\t\t\tif (signal?.aborted) {\n\t\t\t\tthrow new Error(\"aborted\");\n\t\t\t}\n\n\t\t\tconst child = spawn(shell, [...args, command], {\n\t\t\t\tcwd,\n\t\t\t\tdetached: process.platform !== \"win32\",\n\t\t\t\tenv: env ?? getShellEnv(),\n\t\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\t\twindowsHide: true,\n\t\t\t});\n\t\t\tif (child.pid) trackDetachedChildPid(child.pid);\n\t\t\tlet timedOut = false;\n\t\t\tlet timeoutHandle: NodeJS.Timeout | undefined;\n\t\t\tconst onAbort = () => {\n\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t};\n\n\t\t\ttry {\n\t\t\t\t// Set timeout if provided.\n\t\t\t\tif (timeout !== undefined && timeout > 0) {\n\t\t\t\t\ttimeoutHandle = setTimeout(() => {\n\t\t\t\t\t\ttimedOut = true;\n\t\t\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t\t\t}, timeout * 1000);\n\t\t\t\t}\n\t\t\t\t// Stream stdout and stderr.\n\t\t\t\tchild.stdout?.on(\"data\", onData);\n\t\t\t\tchild.stderr?.on(\"data\", onData);\n\t\t\t\t// Handle abort signal by killing the entire process tree.\n\t\t\t\tif (signal) {\n\t\t\t\t\tif (signal.aborted) onAbort();\n\t\t\t\t\telse signal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\t}\n\t\t\t\t// Handle shell spawn errors and wait for the process to terminate without hanging\n\t\t\t\t// on inherited stdio handles held by detached descendants.\n\t\t\t\tconst exitCode = await waitForChildProcess(child);\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tthrow new Error(\"aborted\");\n\t\t\t\t}\n\t\t\t\tif (timedOut) {\n\t\t\t\t\tthrow new Error(`timeout:${timeout}`);\n\t\t\t\t}\n\t\t\t\treturn { exitCode };\n\t\t\t} finally {\n\t\t\t\tif (child.pid) untrackDetachedChildPid(child.pid);\n\t\t\t\tif (timeoutHandle) clearTimeout(timeoutHandle);\n\t\t\t\tif (signal) signal.removeEventListener(\"abort\", onAbort);\n\t\t\t}\n\t\t},\n\t};\n}\n\nexport interface BashSpawnContext {\n\tcommand: string;\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n}\n\nexport type BashSpawnHook = (context: BashSpawnContext) => BashSpawnContext;\n\nfunction resolveSpawnContext(command: string, cwd: string, spawnHook?: BashSpawnHook): BashSpawnContext {\n\tconst baseContext: BashSpawnContext = { command, cwd, env: { ...getShellEnv() } };\n\treturn spawnHook ? spawnHook(baseContext) : baseContext;\n}\n\nexport interface BashToolOptions {\n\t/** Custom operations for command execution. Default: local shell */\n\toperations?: BashOperations;\n\t/** Command prefix prepended to every command (for example shell setup commands) */\n\tcommandPrefix?: string;\n\t/** Optional explicit shell path from settings */\n\tshellPath?: string;\n\t/** Hook to adjust command, cwd, or env before execution */\n\tspawnHook?: BashSpawnHook;\n}\n\nconst BASH_PREVIEW_LINES = 5;\nconst BASH_UPDATE_THROTTLE_MS = 100;\n\ntype BashRenderState = {\n\tstartedAt: number | undefined;\n\tendedAt: number | undefined;\n\tinterval: NodeJS.Timeout | undefined;\n};\n\ntype BashResultRenderState = {\n\tcachedWidth: number | undefined;\n\tcachedLines: string[] | undefined;\n\tcachedSkipped: number | undefined;\n};\n\nclass BashResultRenderComponent extends Container {\n\tstate: BashResultRenderState = {\n\t\tcachedWidth: undefined,\n\t\tcachedLines: undefined,\n\t\tcachedSkipped: undefined,\n\t};\n}\n\nfunction formatDuration(ms: number): string {\n\tconst totalSeconds = Math.floor(Math.max(0, ms) / 1000);\n\tconst hours = Math.floor(totalSeconds / 3600);\n\tconst minutes = Math.floor((totalSeconds % 3600) / 60);\n\tconst seconds = totalSeconds % 60;\n\tif (hours > 0) return minutes > 0 ? `${hours}h ${minutes}m` : `${hours}h`;\n\tif (minutes > 0) return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;\n\treturn `${seconds}s`;\n}\n\nfunction formatBashCall(args: { command?: string; timeout?: number } | undefined): string {\n\tconst command = str(args?.command);\n\tconst timeout = args?.timeout as number | undefined;\n\tconst timeoutSuffix = timeout ? theme.fg(\"muted\", ` (timeout ${timeout}s)`) : \"\";\n\tconst commandDisplay = command === null ? invalidArgText(theme) : command ? command : theme.fg(\"toolOutput\", \"...\");\n\treturn theme.fg(\"toolTitle\", theme.bold(`$ ${commandDisplay}`)) + timeoutSuffix;\n}\n\nfunction rebuildBashResultRenderComponent(\n\tcomponent: BashResultRenderComponent,\n\tresult: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tdetails?: BashToolDetails;\n\t},\n\toptions: ToolRenderResultOptions,\n\tshowImages: boolean,\n\tstartedAt: number | undefined,\n\tendedAt: number | undefined,\n): void {\n\tconst state = component.state;\n\tcomponent.clear();\n\n\tlet output = getTextOutput(result, showImages).trim();\n\tconst truncation = result.details?.truncation;\n\tconst fullOutputPath = result.details?.fullOutputPath;\n\tif (!options.isPartial && truncation?.truncated && fullOutputPath && output.endsWith(\"]\")) {\n\t\tconst footerStart = output.lastIndexOf(\"\\n\\n[\");\n\t\tif (footerStart !== -1 && output.slice(footerStart).includes(fullOutputPath)) {\n\t\t\toutput = output.slice(0, footerStart).trimEnd();\n\t\t}\n\t}\n\n\tif (output) {\n\t\tconst styledOutput = output\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => theme.fg(\"toolOutput\", line))\n\t\t\t.join(\"\\n\");\n\n\t\tif (options.expanded) {\n\t\t\tcomponent.addChild(new Text(`\\n${styledOutput}`, 0, 0));\n\t\t} else {\n\t\t\tcomponent.addChild({\n\t\t\t\trender: (width: number) => {\n\t\t\t\t\tif (state.cachedLines === undefined || state.cachedWidth !== width) {\n\t\t\t\t\t\tconst preview = truncateToVisualLines(styledOutput, BASH_PREVIEW_LINES, width);\n\t\t\t\t\t\tstate.cachedLines = preview.visualLines;\n\t\t\t\t\t\tstate.cachedSkipped = preview.skippedCount;\n\t\t\t\t\t\tstate.cachedWidth = width;\n\t\t\t\t\t}\n\t\t\t\t\tif (state.cachedSkipped && state.cachedSkipped > 0) {\n\t\t\t\t\t\tconst hint =\n\t\t\t\t\t\t\ttheme.fg(\"muted\", `... (${state.cachedSkipped} earlier lines,`) +\n\t\t\t\t\t\t\t` ${keyHint(\"app.tools.expand\", \"Expand\")})`;\n\t\t\t\t\t\treturn [\"\", truncateToWidth(hint, width, \"...\"), ...(state.cachedLines ?? [])];\n\t\t\t\t\t}\n\t\t\t\t\treturn [\"\", ...(state.cachedLines ?? [])];\n\t\t\t\t},\n\t\t\t\tinvalidate: () => {\n\t\t\t\t\tstate.cachedWidth = undefined;\n\t\t\t\t\tstate.cachedLines = undefined;\n\t\t\t\t\tstate.cachedSkipped = undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\tif (truncation?.truncated || fullOutputPath) {\n\t\tconst warnings: string[] = [];\n\t\tif (fullOutputPath) {\n\t\t\twarnings.push(`Full output: ${fullOutputPath}`);\n\t\t}\n\t\tif (truncation?.truncated) {\n\t\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\t\twarnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`);\n\t\t\t} else {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"warning\", `[${warnings.join(\". \")}]`)}`, 0, 0));\n\t}\n\n\tif (startedAt !== undefined) {\n\t\tconst label = options.isPartial ? \"Elapsed\" : \"Took\";\n\t\tconst endTime = endedAt ?? Date.now();\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"muted\", `${label} ${formatDuration(endTime - startedAt)}`)}`, 0, 0));\n\t}\n}\n\nexport function createBashToolDefinition(\n\tcwd: string,\n\toptions?: BashToolOptions,\n): ToolDefinition<typeof bashSchema, BashToolDetails | undefined, BashRenderState> {\n\tconst ops = options?.operations ?? createLocalBashOperations({ shellPath: options?.shellPath });\n\tconst commandPrefix = options?.commandPrefix;\n\tconst spawnHook = options?.spawnHook;\n\treturn {\n\t\tname: \"bash\",\n\t\tlabel: \"bash\",\n\t\tdescription: `Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.`,\n\t\tpromptSnippet: \"Execute bash commands (ls, grep, find, etc.)\",\n\t\tparameters: bashSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ command, timeout }: { command: string; timeout?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t\tonUpdate?,\n\t\t\t_ctx?,\n\t\t) {\n\t\t\tconst resolvedCommand = commandPrefix ? `${commandPrefix}\\n${command}` : command;\n\t\t\tconst spawnContext = resolveSpawnContext(resolvedCommand, cwd, spawnHook);\n\t\t\tconst output = new OutputAccumulator({ tempFilePrefix: `${APP_NAME}-bash` });\n\t\t\tlet updateTimer: NodeJS.Timeout | undefined;\n\t\t\tlet updateDirty = false;\n\t\t\tlet lastUpdateAt = 0;\n\n\t\t\tconst emitOutputUpdate = () => {\n\t\t\t\tif (!onUpdate || !updateDirty) return;\n\t\t\t\tupdateDirty = false;\n\t\t\t\tlastUpdateAt = Date.now();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tonUpdate({\n\t\t\t\t\tcontent: [{ type: \"text\", text: snapshot.content || \"\" }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\ttruncation: snapshot.truncation.truncated ? snapshot.truncation : undefined,\n\t\t\t\t\t\tfullOutputPath: snapshot.fullOutputPath,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tconst clearUpdateTimer = () => {\n\t\t\t\tif (updateTimer) {\n\t\t\t\t\tclearTimeout(updateTimer);\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst scheduleOutputUpdate = () => {\n\t\t\t\tif (!onUpdate) return;\n\t\t\t\tupdateDirty = true;\n\t\t\t\tconst delay = BASH_UPDATE_THROTTLE_MS - (Date.now() - lastUpdateAt);\n\t\t\t\tif (delay <= 0) {\n\t\t\t\t\tclearUpdateTimer();\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tupdateTimer ??= setTimeout(() => {\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t}, delay);\n\t\t\t};\n\n\t\t\tif (onUpdate) {\n\t\t\t\tonUpdate({ content: [], details: undefined });\n\t\t\t}\n\n\t\t\tconst handleData = (data: Buffer) => {\n\t\t\t\toutput.append(data);\n\t\t\t\tscheduleOutputUpdate();\n\t\t\t};\n\n\t\t\tconst finishOutput = async () => {\n\t\t\t\toutput.finish();\n\t\t\t\tclearUpdateTimer();\n\t\t\t\temitOutputUpdate();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tawait output.closeTempFile();\n\t\t\t\treturn snapshot;\n\t\t\t};\n\n\t\t\tconst formatOutput = (snapshot: Awaited<ReturnType<typeof finishOutput>>, emptyText = \"(no output)\") => {\n\t\t\t\tconst truncation = snapshot.truncation;\n\t\t\t\tlet text = snapshot.content || emptyText;\n\t\t\t\tlet details: BashToolDetails | undefined;\n\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\tdetails = { truncation, fullOutputPath: snapshot.fullOutputPath };\n\t\t\t\t\tconst startLine = truncation.totalLines - truncation.outputLines + 1;\n\t\t\t\t\tconst endLine = truncation.totalLines;\n\t\t\t\t\tif (truncation.lastLinePartial) {\n\t\t\t\t\t\tconst lastLineSize = formatSize(output.getLastLineBytes());\n\t\t\t\t\t\ttext += `\\n\\n[Showing last ${formatSize(truncation.outputBytes)} of line ${endLine} (line is ${lastLineSize}). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else if (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines}. Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { text, details };\n\t\t\t};\n\n\t\t\tconst appendStatus = (text: string, status: string) => `${text ? `${text}\\n\\n` : \"\"}${status}`;\n\n\t\t\ttry {\n\t\t\t\tlet exitCode: number | null;\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await ops.exec(spawnContext.command, spawnContext.cwd, {\n\t\t\t\t\t\tonData: handleData,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\tenv: spawnContext.env,\n\t\t\t\t\t});\n\t\t\t\t\texitCode = result.exitCode;\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\t\tconst { text } = formatOutput(snapshot, \"\");\n\t\t\t\t\tif (err instanceof Error && err.message === \"aborted\") {\n\t\t\t\t\t\tthrow new Error(appendStatus(text, \"Command aborted\"));\n\t\t\t\t\t}\n\t\t\t\t\tif (err instanceof Error && err.message.startsWith(\"timeout:\")) {\n\t\t\t\t\t\tconst timeoutSecs = err.message.split(\":\")[1];\n\t\t\t\t\t\tthrow new Error(appendStatus(text, `Command timed out after ${timeoutSecs} seconds`));\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\n\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\tconst { text: outputText, details } = formatOutput(snapshot);\n\t\t\t\tif (exitCode !== 0 && exitCode !== null) {\n\t\t\t\t\tthrow new Error(appendStatus(outputText, `Command exited with code ${exitCode}`));\n\t\t\t\t}\n\t\t\t\treturn { content: [{ type: \"text\", text: outputText }], details };\n\t\t\t} finally {\n\t\t\t\tclearUpdateTimer();\n\t\t\t}\n\t\t},\n\t\trenderCall(args, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (context.executionStarted && state.startedAt === undefined) {\n\t\t\t\tstate.startedAt = Date.now();\n\t\t\t\tstate.endedAt = undefined;\n\t\t\t}\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatBashCall(args));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (state.startedAt !== undefined && options.isPartial && !state.interval) {\n\t\t\t\tstate.interval = setInterval(() => context.invalidate(), 1000);\n\t\t\t}\n\t\t\tif (!options.isPartial || context.isError) {\n\t\t\t\tstate.endedAt ??= Date.now();\n\t\t\t\tif (state.interval) {\n\t\t\t\t\tclearInterval(state.interval);\n\t\t\t\t\tstate.interval = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst component =\n\t\t\t\t(context.lastComponent as BashResultRenderComponent | undefined) ?? new BashResultRenderComponent();\n\t\t\trebuildBashResultRenderComponent(\n\t\t\t\tcomponent,\n\t\t\t\tresult,\n\t\t\t\toptions,\n\t\t\t\tcontext.showImages,\n\t\t\t\tstate.startedAt,\n\t\t\t\tstate.endedAt,\n\t\t\t);\n\t\t\tcomponent.invalidate();\n\t\t\treturn component;\n\t\t},\n\t};\n}\n\nexport function createBashTool(cwd: string, options?: BashToolOptions): AgentTool<typeof bashSchema> {\n\treturn wrapToolDefinition(createBashToolDefinition(cwd, options));\n}\n"]}
1
+ {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../../src/core/tools/bash.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAG/D,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAa5C,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAGN,KAAK,iBAAiB,EACtB,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EAAoD,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAExG,QAAA,MAAM,UAAU;;;EAGd,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC/B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B;;;;;;OAMG;IACH,IAAI,EAAE,CACL,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,OAAO,EAAE;QACR,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;QAC/B,MAAM,CAAC,EAAE,WAAW,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;KACxB,KACG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;CAC1C;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,cAAc,CA4D1F;AAED,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;CACvB;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,gBAAgB,CAAC;AAO5E,MAAM,WAAW,eAAe;IAC/B,oEAAoE;IACpE,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,mFAAmF;IACnF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,2FAA2F;IAC3F,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAKD,KAAK,eAAe,GAAG;IACtB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC,OAAO,GAAG,SAAS,CAAC;CACrC,CAAC;AAoHF,wBAAgB,wBAAwB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,eAAe,GACvB,cAAc,CAAC,OAAO,UAAU,EAAE,eAAe,GAAG,SAAS,EAAE,eAAe,CAAC,CAiLjF;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAEnG","sourcesContent":["import { constants } from \"node:fs\";\nimport { access as fsAccess } from \"node:fs/promises\";\nimport type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { Container, Text, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport { spawn } from \"child_process\";\nimport { type Static, Type } from \"typebox\";\nimport { APP_NAME } from \"../../config.ts\";\nimport { keyHint } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport { truncateToVisualLines } from \"../../modes/interactive/components/visual-truncate.ts\";\nimport { theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { waitForChildProcess } from \"../../utils/child-process.ts\";\nimport {\n\tgetShellConfig,\n\tgetShellEnv,\n\tkillProcessTree,\n\ttrackDetachedChildPid,\n\tuntrackDetachedChildPid,\n} from \"../../utils/shell.ts\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.ts\";\nimport {\n\tevaluateBashCommandPolicy,\n\tformatBashCommandPolicyRejection,\n\ttype BashCommandPolicy,\n} from \"./bash-policy.ts\";\nimport { OutputAccumulator } from \"./output-accumulator.ts\";\nimport { getTextOutput, invalidArgText, str } from \"./render-utils.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationResult } from \"./truncate.ts\";\n\nconst bashSchema = Type.Object({\n\tcommand: Type.String({ description: \"Bash command to execute\" }),\n\ttimeout: Type.Optional(Type.Number({ description: \"Timeout in seconds (optional, no default timeout)\" })),\n});\n\nexport type BashToolInput = Static<typeof bashSchema>;\n\nexport interface BashToolDetails {\n\ttruncation?: TruncationResult;\n\tfullOutputPath?: string;\n}\n\n/**\n * Pluggable operations for the bash tool.\n * Override these to delegate command execution to remote systems (for example SSH).\n */\nexport interface BashOperations {\n\t/**\n\t * Execute a command and stream output.\n\t * @param command The command to execute\n\t * @param cwd Working directory\n\t * @param options Execution options\n\t * @returns Promise resolving to exit code (null if killed)\n\t */\n\texec: (\n\t\tcommand: string,\n\t\tcwd: string,\n\t\toptions: {\n\t\t\tonData: (data: Buffer) => void;\n\t\t\tsignal?: AbortSignal;\n\t\t\ttimeout?: number;\n\t\t\tenv?: NodeJS.ProcessEnv;\n\t\t},\n\t) => Promise<{ exitCode: number | null }>;\n}\n\n/**\n * Create bash operations using pi's built-in local shell execution backend.\n *\n * This is useful for extensions that intercept user_bash and still want pi's\n * standard local shell behavior while wrapping or rewriting commands.\n */\nexport function createLocalBashOperations(options?: { shellPath?: string }): BashOperations {\n\treturn {\n\t\texec: async (command, cwd, { onData, signal, timeout, env }) => {\n\t\t\tconst { shell, args } = getShellConfig(options?.shellPath);\n\t\t\ttry {\n\t\t\t\tawait fsAccess(cwd, constants.F_OK);\n\t\t\t} catch {\n\t\t\t\tthrow new Error(`Working directory does not exist: ${cwd}\\nCannot execute bash commands.`);\n\t\t\t}\n\t\t\tif (signal?.aborted) {\n\t\t\t\tthrow new Error(\"aborted\");\n\t\t\t}\n\n\t\t\tconst child = spawn(shell, [...args, command], {\n\t\t\t\tcwd,\n\t\t\t\tdetached: process.platform !== \"win32\",\n\t\t\t\tenv: env ?? getShellEnv(),\n\t\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\t\twindowsHide: true,\n\t\t\t});\n\t\t\tif (child.pid) trackDetachedChildPid(child.pid);\n\t\t\tlet timedOut = false;\n\t\t\tlet timeoutHandle: NodeJS.Timeout | undefined;\n\t\t\tconst onAbort = () => {\n\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t};\n\n\t\t\ttry {\n\t\t\t\t// Set timeout if provided.\n\t\t\t\tif (timeout !== undefined && timeout > 0) {\n\t\t\t\t\ttimeoutHandle = setTimeout(() => {\n\t\t\t\t\t\ttimedOut = true;\n\t\t\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t\t\t}, timeout * 1000);\n\t\t\t\t}\n\t\t\t\t// Stream stdout and stderr.\n\t\t\t\tchild.stdout?.on(\"data\", onData);\n\t\t\t\tchild.stderr?.on(\"data\", onData);\n\t\t\t\t// Handle abort signal by killing the entire process tree.\n\t\t\t\tif (signal) {\n\t\t\t\t\tif (signal.aborted) onAbort();\n\t\t\t\t\telse signal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\t}\n\t\t\t\t// Handle shell spawn errors and wait for the process to terminate without hanging\n\t\t\t\t// on inherited stdio handles held by detached descendants.\n\t\t\t\tconst exitCode = await waitForChildProcess(child);\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tthrow new Error(\"aborted\");\n\t\t\t\t}\n\t\t\t\tif (timedOut) {\n\t\t\t\t\tthrow new Error(`timeout:${timeout}`);\n\t\t\t\t}\n\t\t\t\treturn { exitCode };\n\t\t\t} finally {\n\t\t\t\tif (child.pid) untrackDetachedChildPid(child.pid);\n\t\t\t\tif (timeoutHandle) clearTimeout(timeoutHandle);\n\t\t\t\tif (signal) signal.removeEventListener(\"abort\", onAbort);\n\t\t\t}\n\t\t},\n\t};\n}\n\nexport interface BashSpawnContext {\n\tcommand: string;\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n}\n\nexport type BashSpawnHook = (context: BashSpawnContext) => BashSpawnContext;\n\nfunction resolveSpawnContext(command: string, cwd: string, spawnHook?: BashSpawnHook): BashSpawnContext {\n\tconst baseContext: BashSpawnContext = { command, cwd, env: { ...getShellEnv() } };\n\treturn spawnHook ? spawnHook(baseContext) : baseContext;\n}\n\nexport interface BashToolOptions {\n\t/** Custom operations for command execution. Default: local shell */\n\toperations?: BashOperations;\n\t/** Command prefix prepended to every command (for example shell setup commands) */\n\tcommandPrefix?: string;\n\t/** Optional explicit shell path from settings */\n\tshellPath?: string;\n\t/** Hook to adjust command, cwd, or env before execution */\n\tspawnHook?: BashSpawnHook;\n\t/** Optional command-level policy enforced before commandPrefix, spawnHook, or execution */\n\tpolicy?: BashCommandPolicy;\n\t/** Human-readable label used in policy denial errors */\n\tpolicyLabel?: string;\n}\n\nconst BASH_PREVIEW_LINES = 5;\nconst BASH_UPDATE_THROTTLE_MS = 100;\n\ntype BashRenderState = {\n\tstartedAt: number | undefined;\n\tendedAt: number | undefined;\n\tinterval: NodeJS.Timeout | undefined;\n};\n\ntype BashResultRenderState = {\n\tcachedWidth: number | undefined;\n\tcachedLines: string[] | undefined;\n\tcachedSkipped: number | undefined;\n};\n\nclass BashResultRenderComponent extends Container {\n\tstate: BashResultRenderState = {\n\t\tcachedWidth: undefined,\n\t\tcachedLines: undefined,\n\t\tcachedSkipped: undefined,\n\t};\n}\n\nfunction formatDuration(ms: number): string {\n\tconst totalSeconds = Math.floor(Math.max(0, ms) / 1000);\n\tconst hours = Math.floor(totalSeconds / 3600);\n\tconst minutes = Math.floor((totalSeconds % 3600) / 60);\n\tconst seconds = totalSeconds % 60;\n\tif (hours > 0) return minutes > 0 ? `${hours}h ${minutes}m` : `${hours}h`;\n\tif (minutes > 0) return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;\n\treturn `${seconds}s`;\n}\n\nfunction formatBashCall(args: { command?: string; timeout?: number } | undefined): string {\n\tconst command = str(args?.command);\n\tconst timeout = args?.timeout as number | undefined;\n\tconst timeoutSuffix = timeout ? theme.fg(\"muted\", ` (timeout ${timeout}s)`) : \"\";\n\tconst commandDisplay = command === null ? invalidArgText(theme) : command ? command : theme.fg(\"toolOutput\", \"...\");\n\treturn theme.fg(\"toolTitle\", theme.bold(`$ ${commandDisplay}`)) + timeoutSuffix;\n}\n\nfunction rebuildBashResultRenderComponent(\n\tcomponent: BashResultRenderComponent,\n\tresult: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tdetails?: BashToolDetails;\n\t},\n\toptions: ToolRenderResultOptions,\n\tshowImages: boolean,\n\tstartedAt: number | undefined,\n\tendedAt: number | undefined,\n): void {\n\tconst state = component.state;\n\tcomponent.clear();\n\n\tlet output = getTextOutput(result, showImages).trim();\n\tconst truncation = result.details?.truncation;\n\tconst fullOutputPath = result.details?.fullOutputPath;\n\tif (!options.isPartial && truncation?.truncated && fullOutputPath && output.endsWith(\"]\")) {\n\t\tconst footerStart = output.lastIndexOf(\"\\n\\n[\");\n\t\tif (footerStart !== -1 && output.slice(footerStart).includes(fullOutputPath)) {\n\t\t\toutput = output.slice(0, footerStart).trimEnd();\n\t\t}\n\t}\n\n\tif (output) {\n\t\tconst styledOutput = output\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => theme.fg(\"toolOutput\", line))\n\t\t\t.join(\"\\n\");\n\n\t\tif (options.expanded) {\n\t\t\tcomponent.addChild(new Text(`\\n${styledOutput}`, 0, 0));\n\t\t} else {\n\t\t\tcomponent.addChild({\n\t\t\t\trender: (width: number) => {\n\t\t\t\t\tif (state.cachedLines === undefined || state.cachedWidth !== width) {\n\t\t\t\t\t\tconst preview = truncateToVisualLines(styledOutput, BASH_PREVIEW_LINES, width);\n\t\t\t\t\t\tstate.cachedLines = preview.visualLines;\n\t\t\t\t\t\tstate.cachedSkipped = preview.skippedCount;\n\t\t\t\t\t\tstate.cachedWidth = width;\n\t\t\t\t\t}\n\t\t\t\t\tif (state.cachedSkipped && state.cachedSkipped > 0) {\n\t\t\t\t\t\tconst hint =\n\t\t\t\t\t\t\ttheme.fg(\"muted\", `... (${state.cachedSkipped} earlier lines,`) +\n\t\t\t\t\t\t\t` ${keyHint(\"app.tools.expand\", \"Expand\")}${theme.fg(\"muted\", \")\")}`;\n\t\t\t\t\t\treturn [\"\", truncateToWidth(hint, width, \"...\"), ...(state.cachedLines ?? [])];\n\t\t\t\t\t}\n\t\t\t\t\treturn [\"\", ...(state.cachedLines ?? [])];\n\t\t\t\t},\n\t\t\t\tinvalidate: () => {\n\t\t\t\t\tstate.cachedWidth = undefined;\n\t\t\t\t\tstate.cachedLines = undefined;\n\t\t\t\t\tstate.cachedSkipped = undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\tif (truncation?.truncated || fullOutputPath) {\n\t\tconst warnings: string[] = [];\n\t\tif (fullOutputPath) {\n\t\t\twarnings.push(`Full output: ${fullOutputPath}`);\n\t\t}\n\t\tif (truncation?.truncated) {\n\t\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\t\twarnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`);\n\t\t\t} else {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"warning\", `[${warnings.join(\". \")}]`)}`, 0, 0));\n\t}\n\n\tif (startedAt !== undefined) {\n\t\tconst label = options.isPartial ? \"Elapsed\" : \"Took\";\n\t\tconst endTime = endedAt ?? Date.now();\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"muted\", `${label} ${formatDuration(endTime - startedAt)}`)}`, 0, 0));\n\t}\n}\n\nexport function createBashToolDefinition(\n\tcwd: string,\n\toptions?: BashToolOptions,\n): ToolDefinition<typeof bashSchema, BashToolDetails | undefined, BashRenderState> {\n\tconst ops = options?.operations ?? createLocalBashOperations({ shellPath: options?.shellPath });\n\tconst commandPrefix = options?.commandPrefix;\n\tconst spawnHook = options?.spawnHook;\n\tconst policy = options?.policy;\n\tconst policyLabel = options?.policyLabel;\n\treturn {\n\t\tname: \"bash\",\n\t\tlabel: \"bash\",\n\t\tdescription: `Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.`,\n\t\tpromptSnippet: \"Execute bash commands (ls, grep, find, etc.)\",\n\t\tparameters: bashSchema,\n\t\tmaxResultSizeChars: Infinity,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ command, timeout }: { command: string; timeout?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t\tonUpdate?,\n\t\t\t_ctx?,\n\t\t) {\n\t\t\tconst policyDecision = evaluateBashCommandPolicy(command, policy);\n\t\t\tif (!policyDecision.allowed) {\n\t\t\t\tthrow new Error(formatBashCommandPolicyRejection(policyDecision, policyLabel));\n\t\t\t}\n\n\t\t\tconst resolvedCommand = commandPrefix ? `${commandPrefix}\\n${command}` : command;\n\t\t\tconst spawnContext = resolveSpawnContext(resolvedCommand, cwd, spawnHook);\n\t\t\tconst output = new OutputAccumulator({ tempFilePrefix: `${APP_NAME}-bash` });\n\t\t\tlet updateTimer: NodeJS.Timeout | undefined;\n\t\t\tlet updateDirty = false;\n\t\t\tlet lastUpdateAt = 0;\n\n\t\t\tconst emitOutputUpdate = () => {\n\t\t\t\tif (!onUpdate || !updateDirty) return;\n\t\t\t\tupdateDirty = false;\n\t\t\t\tlastUpdateAt = Date.now();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tonUpdate({\n\t\t\t\t\tcontent: [{ type: \"text\", text: snapshot.content || \"\" }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\ttruncation: snapshot.truncation.truncated ? snapshot.truncation : undefined,\n\t\t\t\t\t\tfullOutputPath: snapshot.fullOutputPath,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tconst clearUpdateTimer = () => {\n\t\t\t\tif (updateTimer) {\n\t\t\t\t\tclearTimeout(updateTimer);\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst scheduleOutputUpdate = () => {\n\t\t\t\tif (!onUpdate) return;\n\t\t\t\tupdateDirty = true;\n\t\t\t\tconst delay = BASH_UPDATE_THROTTLE_MS - (Date.now() - lastUpdateAt);\n\t\t\t\tif (delay <= 0) {\n\t\t\t\t\tclearUpdateTimer();\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tupdateTimer ??= setTimeout(() => {\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t}, delay);\n\t\t\t};\n\n\t\t\tif (onUpdate) {\n\t\t\t\tonUpdate({ content: [], details: undefined });\n\t\t\t}\n\n\t\t\tconst handleData = (data: Buffer) => {\n\t\t\t\toutput.append(data);\n\t\t\t\tscheduleOutputUpdate();\n\t\t\t};\n\n\t\t\tconst finishOutput = async () => {\n\t\t\t\toutput.finish();\n\t\t\t\tclearUpdateTimer();\n\t\t\t\temitOutputUpdate();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tawait output.closeTempFile();\n\t\t\t\treturn snapshot;\n\t\t\t};\n\n\t\t\tconst formatOutput = (snapshot: Awaited<ReturnType<typeof finishOutput>>, emptyText = \"(no output)\") => {\n\t\t\t\tconst truncation = snapshot.truncation;\n\t\t\t\tlet text = snapshot.content || emptyText;\n\t\t\t\tlet details: BashToolDetails | undefined;\n\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\tdetails = { truncation, fullOutputPath: snapshot.fullOutputPath };\n\t\t\t\t\tconst startLine = truncation.totalLines - truncation.outputLines + 1;\n\t\t\t\t\tconst endLine = truncation.totalLines;\n\t\t\t\t\tif (truncation.lastLinePartial) {\n\t\t\t\t\t\tconst lastLineSize = formatSize(output.getLastLineBytes());\n\t\t\t\t\t\ttext += `\\n\\n[Showing last ${formatSize(truncation.outputBytes)} of line ${endLine} (line is ${lastLineSize}). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else if (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines}. Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { text, details };\n\t\t\t};\n\n\t\t\tconst appendStatus = (text: string, status: string) => `${text ? `${text}\\n\\n` : \"\"}${status}`;\n\n\t\t\ttry {\n\t\t\t\tlet exitCode: number | null;\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await ops.exec(spawnContext.command, spawnContext.cwd, {\n\t\t\t\t\t\tonData: handleData,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\tenv: spawnContext.env,\n\t\t\t\t\t});\n\t\t\t\t\texitCode = result.exitCode;\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\t\tconst { text } = formatOutput(snapshot, \"\");\n\t\t\t\t\tif (err instanceof Error && err.message === \"aborted\") {\n\t\t\t\t\t\tthrow new Error(appendStatus(text, \"Command aborted\"));\n\t\t\t\t\t}\n\t\t\t\t\tif (err instanceof Error && err.message.startsWith(\"timeout:\")) {\n\t\t\t\t\t\tconst timeoutSecs = err.message.split(\":\")[1];\n\t\t\t\t\t\tthrow new Error(appendStatus(text, `Command timed out after ${timeoutSecs} seconds`));\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\n\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\tconst { text: outputText, details } = formatOutput(snapshot);\n\t\t\t\tif (exitCode !== 0 && exitCode !== null) {\n\t\t\t\t\tthrow new Error(appendStatus(outputText, `Command exited with code ${exitCode}`));\n\t\t\t\t}\n\t\t\t\treturn { content: [{ type: \"text\", text: outputText }], details };\n\t\t\t} finally {\n\t\t\t\tclearUpdateTimer();\n\t\t\t}\n\t\t},\n\t\trenderCall(args, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (context.executionStarted && state.startedAt === undefined) {\n\t\t\t\tstate.startedAt = Date.now();\n\t\t\t\tstate.endedAt = undefined;\n\t\t\t}\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatBashCall(args));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (state.startedAt !== undefined && options.isPartial && !state.interval) {\n\t\t\t\tstate.interval = setInterval(() => context.invalidate(), 1000);\n\t\t\t}\n\t\t\tif (!options.isPartial || context.isError) {\n\t\t\t\tstate.endedAt ??= Date.now();\n\t\t\t\tif (state.interval) {\n\t\t\t\t\tclearInterval(state.interval);\n\t\t\t\t\tstate.interval = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst component =\n\t\t\t\t(context.lastComponent as BashResultRenderComponent | undefined) ?? new BashResultRenderComponent();\n\t\t\trebuildBashResultRenderComponent(\n\t\t\t\tcomponent,\n\t\t\t\tresult,\n\t\t\t\toptions,\n\t\t\t\tcontext.showImages,\n\t\t\t\tstate.startedAt,\n\t\t\t\tstate.endedAt,\n\t\t\t);\n\t\t\tcomponent.invalidate();\n\t\t\treturn component;\n\t\t},\n\t};\n}\n\nexport function createBashTool(cwd: string, options?: BashToolOptions): AgentTool<typeof bashSchema> {\n\treturn wrapToolDefinition(createBashToolDefinition(cwd, options));\n}\n"]}
@@ -9,6 +9,7 @@ import { truncateToVisualLines } from "../../modes/interactive/components/visual
9
9
  import { theme } from "../../modes/interactive/theme/theme.js";
10
10
  import { waitForChildProcess } from "../../utils/child-process.js";
11
11
  import { getShellConfig, getShellEnv, killProcessTree, trackDetachedChildPid, untrackDetachedChildPid, } from "../../utils/shell.js";
12
+ import { evaluateBashCommandPolicy, formatBashCommandPolicyRejection, } from "./bash-policy.js";
12
13
  import { OutputAccumulator } from "./output-accumulator.js";
13
14
  import { getTextOutput, invalidArgText, str } from "./render-utils.js";
14
15
  import { wrapToolDefinition } from "./tool-definition-wrapper.js";
@@ -157,7 +158,7 @@ function rebuildBashResultRenderComponent(component, result, options, showImages
157
158
  }
158
159
  if (state.cachedSkipped && state.cachedSkipped > 0) {
159
160
  const hint = theme.fg("muted", `... (${state.cachedSkipped} earlier lines,`) +
160
- ` ${keyHint("app.tools.expand", "Expand")})`;
161
+ ` ${keyHint("app.tools.expand", "Expand")}${theme.fg("muted", ")")}`;
161
162
  return ["", truncateToWidth(hint, width, "..."), ...(state.cachedLines ?? [])];
162
163
  }
163
164
  return ["", ...(state.cachedLines ?? [])];
@@ -195,13 +196,20 @@ export function createBashToolDefinition(cwd, options) {
195
196
  const ops = options?.operations ?? createLocalBashOperations({ shellPath: options?.shellPath });
196
197
  const commandPrefix = options?.commandPrefix;
197
198
  const spawnHook = options?.spawnHook;
199
+ const policy = options?.policy;
200
+ const policyLabel = options?.policyLabel;
198
201
  return {
199
202
  name: "bash",
200
203
  label: "bash",
201
204
  description: `Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.`,
202
205
  promptSnippet: "Execute bash commands (ls, grep, find, etc.)",
203
206
  parameters: bashSchema,
207
+ maxResultSizeChars: Infinity,
204
208
  async execute(_toolCallId, { command, timeout }, signal, onUpdate, _ctx) {
209
+ const policyDecision = evaluateBashCommandPolicy(command, policy);
210
+ if (!policyDecision.allowed) {
211
+ throw new Error(formatBashCommandPolicyRejection(policyDecision, policyLabel));
212
+ }
205
213
  const resolvedCommand = commandPrefix ? `${commandPrefix}\n${command}` : command;
206
214
  const spawnContext = resolveSpawnContext(resolvedCommand, cwd, spawnHook);
207
215
  const output = new OutputAccumulator({ tempFilePrefix: `${APP_NAME}-bash` });
@@ -1 +1 @@
1
- {"version":3,"file":"bash.js","sourceRoot":"","sources":["../../../src/core/tools/bash.ts"],"names":[],"mappings":"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","sourcesContent":["import { constants } from \"node:fs\";\nimport { access as fsAccess } from \"node:fs/promises\";\nimport type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { Container, Text, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport { spawn } from \"child_process\";\nimport { type Static, Type } from \"typebox\";\nimport { APP_NAME } from \"../../config.ts\";\nimport { keyHint } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport { truncateToVisualLines } from \"../../modes/interactive/components/visual-truncate.ts\";\nimport { theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { waitForChildProcess } from \"../../utils/child-process.ts\";\nimport {\n\tgetShellConfig,\n\tgetShellEnv,\n\tkillProcessTree,\n\ttrackDetachedChildPid,\n\tuntrackDetachedChildPid,\n} from \"../../utils/shell.ts\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.ts\";\nimport { OutputAccumulator } from \"./output-accumulator.ts\";\nimport { getTextOutput, invalidArgText, str } from \"./render-utils.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationResult } from \"./truncate.ts\";\n\nconst bashSchema = Type.Object({\n\tcommand: Type.String({ description: \"Bash command to execute\" }),\n\ttimeout: Type.Optional(Type.Number({ description: \"Timeout in seconds (optional, no default timeout)\" })),\n});\n\nexport type BashToolInput = Static<typeof bashSchema>;\n\nexport interface BashToolDetails {\n\ttruncation?: TruncationResult;\n\tfullOutputPath?: string;\n}\n\n/**\n * Pluggable operations for the bash tool.\n * Override these to delegate command execution to remote systems (for example SSH).\n */\nexport interface BashOperations {\n\t/**\n\t * Execute a command and stream output.\n\t * @param command The command to execute\n\t * @param cwd Working directory\n\t * @param options Execution options\n\t * @returns Promise resolving to exit code (null if killed)\n\t */\n\texec: (\n\t\tcommand: string,\n\t\tcwd: string,\n\t\toptions: {\n\t\t\tonData: (data: Buffer) => void;\n\t\t\tsignal?: AbortSignal;\n\t\t\ttimeout?: number;\n\t\t\tenv?: NodeJS.ProcessEnv;\n\t\t},\n\t) => Promise<{ exitCode: number | null }>;\n}\n\n/**\n * Create bash operations using pi's built-in local shell execution backend.\n *\n * This is useful for extensions that intercept user_bash and still want pi's\n * standard local shell behavior while wrapping or rewriting commands.\n */\nexport function createLocalBashOperations(options?: { shellPath?: string }): BashOperations {\n\treturn {\n\t\texec: async (command, cwd, { onData, signal, timeout, env }) => {\n\t\t\tconst { shell, args } = getShellConfig(options?.shellPath);\n\t\t\ttry {\n\t\t\t\tawait fsAccess(cwd, constants.F_OK);\n\t\t\t} catch {\n\t\t\t\tthrow new Error(`Working directory does not exist: ${cwd}\\nCannot execute bash commands.`);\n\t\t\t}\n\t\t\tif (signal?.aborted) {\n\t\t\t\tthrow new Error(\"aborted\");\n\t\t\t}\n\n\t\t\tconst child = spawn(shell, [...args, command], {\n\t\t\t\tcwd,\n\t\t\t\tdetached: process.platform !== \"win32\",\n\t\t\t\tenv: env ?? getShellEnv(),\n\t\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\t\twindowsHide: true,\n\t\t\t});\n\t\t\tif (child.pid) trackDetachedChildPid(child.pid);\n\t\t\tlet timedOut = false;\n\t\t\tlet timeoutHandle: NodeJS.Timeout | undefined;\n\t\t\tconst onAbort = () => {\n\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t};\n\n\t\t\ttry {\n\t\t\t\t// Set timeout if provided.\n\t\t\t\tif (timeout !== undefined && timeout > 0) {\n\t\t\t\t\ttimeoutHandle = setTimeout(() => {\n\t\t\t\t\t\ttimedOut = true;\n\t\t\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t\t\t}, timeout * 1000);\n\t\t\t\t}\n\t\t\t\t// Stream stdout and stderr.\n\t\t\t\tchild.stdout?.on(\"data\", onData);\n\t\t\t\tchild.stderr?.on(\"data\", onData);\n\t\t\t\t// Handle abort signal by killing the entire process tree.\n\t\t\t\tif (signal) {\n\t\t\t\t\tif (signal.aborted) onAbort();\n\t\t\t\t\telse signal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\t}\n\t\t\t\t// Handle shell spawn errors and wait for the process to terminate without hanging\n\t\t\t\t// on inherited stdio handles held by detached descendants.\n\t\t\t\tconst exitCode = await waitForChildProcess(child);\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tthrow new Error(\"aborted\");\n\t\t\t\t}\n\t\t\t\tif (timedOut) {\n\t\t\t\t\tthrow new Error(`timeout:${timeout}`);\n\t\t\t\t}\n\t\t\t\treturn { exitCode };\n\t\t\t} finally {\n\t\t\t\tif (child.pid) untrackDetachedChildPid(child.pid);\n\t\t\t\tif (timeoutHandle) clearTimeout(timeoutHandle);\n\t\t\t\tif (signal) signal.removeEventListener(\"abort\", onAbort);\n\t\t\t}\n\t\t},\n\t};\n}\n\nexport interface BashSpawnContext {\n\tcommand: string;\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n}\n\nexport type BashSpawnHook = (context: BashSpawnContext) => BashSpawnContext;\n\nfunction resolveSpawnContext(command: string, cwd: string, spawnHook?: BashSpawnHook): BashSpawnContext {\n\tconst baseContext: BashSpawnContext = { command, cwd, env: { ...getShellEnv() } };\n\treturn spawnHook ? spawnHook(baseContext) : baseContext;\n}\n\nexport interface BashToolOptions {\n\t/** Custom operations for command execution. Default: local shell */\n\toperations?: BashOperations;\n\t/** Command prefix prepended to every command (for example shell setup commands) */\n\tcommandPrefix?: string;\n\t/** Optional explicit shell path from settings */\n\tshellPath?: string;\n\t/** Hook to adjust command, cwd, or env before execution */\n\tspawnHook?: BashSpawnHook;\n}\n\nconst BASH_PREVIEW_LINES = 5;\nconst BASH_UPDATE_THROTTLE_MS = 100;\n\ntype BashRenderState = {\n\tstartedAt: number | undefined;\n\tendedAt: number | undefined;\n\tinterval: NodeJS.Timeout | undefined;\n};\n\ntype BashResultRenderState = {\n\tcachedWidth: number | undefined;\n\tcachedLines: string[] | undefined;\n\tcachedSkipped: number | undefined;\n};\n\nclass BashResultRenderComponent extends Container {\n\tstate: BashResultRenderState = {\n\t\tcachedWidth: undefined,\n\t\tcachedLines: undefined,\n\t\tcachedSkipped: undefined,\n\t};\n}\n\nfunction formatDuration(ms: number): string {\n\tconst totalSeconds = Math.floor(Math.max(0, ms) / 1000);\n\tconst hours = Math.floor(totalSeconds / 3600);\n\tconst minutes = Math.floor((totalSeconds % 3600) / 60);\n\tconst seconds = totalSeconds % 60;\n\tif (hours > 0) return minutes > 0 ? `${hours}h ${minutes}m` : `${hours}h`;\n\tif (minutes > 0) return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;\n\treturn `${seconds}s`;\n}\n\nfunction formatBashCall(args: { command?: string; timeout?: number } | undefined): string {\n\tconst command = str(args?.command);\n\tconst timeout = args?.timeout as number | undefined;\n\tconst timeoutSuffix = timeout ? theme.fg(\"muted\", ` (timeout ${timeout}s)`) : \"\";\n\tconst commandDisplay = command === null ? invalidArgText(theme) : command ? command : theme.fg(\"toolOutput\", \"...\");\n\treturn theme.fg(\"toolTitle\", theme.bold(`$ ${commandDisplay}`)) + timeoutSuffix;\n}\n\nfunction rebuildBashResultRenderComponent(\n\tcomponent: BashResultRenderComponent,\n\tresult: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tdetails?: BashToolDetails;\n\t},\n\toptions: ToolRenderResultOptions,\n\tshowImages: boolean,\n\tstartedAt: number | undefined,\n\tendedAt: number | undefined,\n): void {\n\tconst state = component.state;\n\tcomponent.clear();\n\n\tlet output = getTextOutput(result, showImages).trim();\n\tconst truncation = result.details?.truncation;\n\tconst fullOutputPath = result.details?.fullOutputPath;\n\tif (!options.isPartial && truncation?.truncated && fullOutputPath && output.endsWith(\"]\")) {\n\t\tconst footerStart = output.lastIndexOf(\"\\n\\n[\");\n\t\tif (footerStart !== -1 && output.slice(footerStart).includes(fullOutputPath)) {\n\t\t\toutput = output.slice(0, footerStart).trimEnd();\n\t\t}\n\t}\n\n\tif (output) {\n\t\tconst styledOutput = output\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => theme.fg(\"toolOutput\", line))\n\t\t\t.join(\"\\n\");\n\n\t\tif (options.expanded) {\n\t\t\tcomponent.addChild(new Text(`\\n${styledOutput}`, 0, 0));\n\t\t} else {\n\t\t\tcomponent.addChild({\n\t\t\t\trender: (width: number) => {\n\t\t\t\t\tif (state.cachedLines === undefined || state.cachedWidth !== width) {\n\t\t\t\t\t\tconst preview = truncateToVisualLines(styledOutput, BASH_PREVIEW_LINES, width);\n\t\t\t\t\t\tstate.cachedLines = preview.visualLines;\n\t\t\t\t\t\tstate.cachedSkipped = preview.skippedCount;\n\t\t\t\t\t\tstate.cachedWidth = width;\n\t\t\t\t\t}\n\t\t\t\t\tif (state.cachedSkipped && state.cachedSkipped > 0) {\n\t\t\t\t\t\tconst hint =\n\t\t\t\t\t\t\ttheme.fg(\"muted\", `... (${state.cachedSkipped} earlier lines,`) +\n\t\t\t\t\t\t\t` ${keyHint(\"app.tools.expand\", \"Expand\")})`;\n\t\t\t\t\t\treturn [\"\", truncateToWidth(hint, width, \"...\"), ...(state.cachedLines ?? [])];\n\t\t\t\t\t}\n\t\t\t\t\treturn [\"\", ...(state.cachedLines ?? [])];\n\t\t\t\t},\n\t\t\t\tinvalidate: () => {\n\t\t\t\t\tstate.cachedWidth = undefined;\n\t\t\t\t\tstate.cachedLines = undefined;\n\t\t\t\t\tstate.cachedSkipped = undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\tif (truncation?.truncated || fullOutputPath) {\n\t\tconst warnings: string[] = [];\n\t\tif (fullOutputPath) {\n\t\t\twarnings.push(`Full output: ${fullOutputPath}`);\n\t\t}\n\t\tif (truncation?.truncated) {\n\t\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\t\twarnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`);\n\t\t\t} else {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"warning\", `[${warnings.join(\". \")}]`)}`, 0, 0));\n\t}\n\n\tif (startedAt !== undefined) {\n\t\tconst label = options.isPartial ? \"Elapsed\" : \"Took\";\n\t\tconst endTime = endedAt ?? Date.now();\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"muted\", `${label} ${formatDuration(endTime - startedAt)}`)}`, 0, 0));\n\t}\n}\n\nexport function createBashToolDefinition(\n\tcwd: string,\n\toptions?: BashToolOptions,\n): ToolDefinition<typeof bashSchema, BashToolDetails | undefined, BashRenderState> {\n\tconst ops = options?.operations ?? createLocalBashOperations({ shellPath: options?.shellPath });\n\tconst commandPrefix = options?.commandPrefix;\n\tconst spawnHook = options?.spawnHook;\n\treturn {\n\t\tname: \"bash\",\n\t\tlabel: \"bash\",\n\t\tdescription: `Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.`,\n\t\tpromptSnippet: \"Execute bash commands (ls, grep, find, etc.)\",\n\t\tparameters: bashSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ command, timeout }: { command: string; timeout?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t\tonUpdate?,\n\t\t\t_ctx?,\n\t\t) {\n\t\t\tconst resolvedCommand = commandPrefix ? `${commandPrefix}\\n${command}` : command;\n\t\t\tconst spawnContext = resolveSpawnContext(resolvedCommand, cwd, spawnHook);\n\t\t\tconst output = new OutputAccumulator({ tempFilePrefix: `${APP_NAME}-bash` });\n\t\t\tlet updateTimer: NodeJS.Timeout | undefined;\n\t\t\tlet updateDirty = false;\n\t\t\tlet lastUpdateAt = 0;\n\n\t\t\tconst emitOutputUpdate = () => {\n\t\t\t\tif (!onUpdate || !updateDirty) return;\n\t\t\t\tupdateDirty = false;\n\t\t\t\tlastUpdateAt = Date.now();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tonUpdate({\n\t\t\t\t\tcontent: [{ type: \"text\", text: snapshot.content || \"\" }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\ttruncation: snapshot.truncation.truncated ? snapshot.truncation : undefined,\n\t\t\t\t\t\tfullOutputPath: snapshot.fullOutputPath,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tconst clearUpdateTimer = () => {\n\t\t\t\tif (updateTimer) {\n\t\t\t\t\tclearTimeout(updateTimer);\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst scheduleOutputUpdate = () => {\n\t\t\t\tif (!onUpdate) return;\n\t\t\t\tupdateDirty = true;\n\t\t\t\tconst delay = BASH_UPDATE_THROTTLE_MS - (Date.now() - lastUpdateAt);\n\t\t\t\tif (delay <= 0) {\n\t\t\t\t\tclearUpdateTimer();\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tupdateTimer ??= setTimeout(() => {\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t}, delay);\n\t\t\t};\n\n\t\t\tif (onUpdate) {\n\t\t\t\tonUpdate({ content: [], details: undefined });\n\t\t\t}\n\n\t\t\tconst handleData = (data: Buffer) => {\n\t\t\t\toutput.append(data);\n\t\t\t\tscheduleOutputUpdate();\n\t\t\t};\n\n\t\t\tconst finishOutput = async () => {\n\t\t\t\toutput.finish();\n\t\t\t\tclearUpdateTimer();\n\t\t\t\temitOutputUpdate();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tawait output.closeTempFile();\n\t\t\t\treturn snapshot;\n\t\t\t};\n\n\t\t\tconst formatOutput = (snapshot: Awaited<ReturnType<typeof finishOutput>>, emptyText = \"(no output)\") => {\n\t\t\t\tconst truncation = snapshot.truncation;\n\t\t\t\tlet text = snapshot.content || emptyText;\n\t\t\t\tlet details: BashToolDetails | undefined;\n\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\tdetails = { truncation, fullOutputPath: snapshot.fullOutputPath };\n\t\t\t\t\tconst startLine = truncation.totalLines - truncation.outputLines + 1;\n\t\t\t\t\tconst endLine = truncation.totalLines;\n\t\t\t\t\tif (truncation.lastLinePartial) {\n\t\t\t\t\t\tconst lastLineSize = formatSize(output.getLastLineBytes());\n\t\t\t\t\t\ttext += `\\n\\n[Showing last ${formatSize(truncation.outputBytes)} of line ${endLine} (line is ${lastLineSize}). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else if (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines}. Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { text, details };\n\t\t\t};\n\n\t\t\tconst appendStatus = (text: string, status: string) => `${text ? `${text}\\n\\n` : \"\"}${status}`;\n\n\t\t\ttry {\n\t\t\t\tlet exitCode: number | null;\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await ops.exec(spawnContext.command, spawnContext.cwd, {\n\t\t\t\t\t\tonData: handleData,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\tenv: spawnContext.env,\n\t\t\t\t\t});\n\t\t\t\t\texitCode = result.exitCode;\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\t\tconst { text } = formatOutput(snapshot, \"\");\n\t\t\t\t\tif (err instanceof Error && err.message === \"aborted\") {\n\t\t\t\t\t\tthrow new Error(appendStatus(text, \"Command aborted\"));\n\t\t\t\t\t}\n\t\t\t\t\tif (err instanceof Error && err.message.startsWith(\"timeout:\")) {\n\t\t\t\t\t\tconst timeoutSecs = err.message.split(\":\")[1];\n\t\t\t\t\t\tthrow new Error(appendStatus(text, `Command timed out after ${timeoutSecs} seconds`));\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\n\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\tconst { text: outputText, details } = formatOutput(snapshot);\n\t\t\t\tif (exitCode !== 0 && exitCode !== null) {\n\t\t\t\t\tthrow new Error(appendStatus(outputText, `Command exited with code ${exitCode}`));\n\t\t\t\t}\n\t\t\t\treturn { content: [{ type: \"text\", text: outputText }], details };\n\t\t\t} finally {\n\t\t\t\tclearUpdateTimer();\n\t\t\t}\n\t\t},\n\t\trenderCall(args, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (context.executionStarted && state.startedAt === undefined) {\n\t\t\t\tstate.startedAt = Date.now();\n\t\t\t\tstate.endedAt = undefined;\n\t\t\t}\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatBashCall(args));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (state.startedAt !== undefined && options.isPartial && !state.interval) {\n\t\t\t\tstate.interval = setInterval(() => context.invalidate(), 1000);\n\t\t\t}\n\t\t\tif (!options.isPartial || context.isError) {\n\t\t\t\tstate.endedAt ??= Date.now();\n\t\t\t\tif (state.interval) {\n\t\t\t\t\tclearInterval(state.interval);\n\t\t\t\t\tstate.interval = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst component =\n\t\t\t\t(context.lastComponent as BashResultRenderComponent | undefined) ?? new BashResultRenderComponent();\n\t\t\trebuildBashResultRenderComponent(\n\t\t\t\tcomponent,\n\t\t\t\tresult,\n\t\t\t\toptions,\n\t\t\t\tcontext.showImages,\n\t\t\t\tstate.startedAt,\n\t\t\t\tstate.endedAt,\n\t\t\t);\n\t\t\tcomponent.invalidate();\n\t\t\treturn component;\n\t\t},\n\t};\n}\n\nexport function createBashTool(cwd: string, options?: BashToolOptions): AgentTool<typeof bashSchema> {\n\treturn wrapToolDefinition(createBashToolDefinition(cwd, options));\n}\n"]}
1
+ {"version":3,"file":"bash.js","sourceRoot":"","sources":["../../../src/core/tools/bash.ts"],"names":[],"mappings":"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","sourcesContent":["import { constants } from \"node:fs\";\nimport { access as fsAccess } from \"node:fs/promises\";\nimport type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { Container, Text, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport { spawn } from \"child_process\";\nimport { type Static, Type } from \"typebox\";\nimport { APP_NAME } from \"../../config.ts\";\nimport { keyHint } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport { truncateToVisualLines } from \"../../modes/interactive/components/visual-truncate.ts\";\nimport { theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { waitForChildProcess } from \"../../utils/child-process.ts\";\nimport {\n\tgetShellConfig,\n\tgetShellEnv,\n\tkillProcessTree,\n\ttrackDetachedChildPid,\n\tuntrackDetachedChildPid,\n} from \"../../utils/shell.ts\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.ts\";\nimport {\n\tevaluateBashCommandPolicy,\n\tformatBashCommandPolicyRejection,\n\ttype BashCommandPolicy,\n} from \"./bash-policy.ts\";\nimport { OutputAccumulator } from \"./output-accumulator.ts\";\nimport { getTextOutput, invalidArgText, str } from \"./render-utils.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationResult } from \"./truncate.ts\";\n\nconst bashSchema = Type.Object({\n\tcommand: Type.String({ description: \"Bash command to execute\" }),\n\ttimeout: Type.Optional(Type.Number({ description: \"Timeout in seconds (optional, no default timeout)\" })),\n});\n\nexport type BashToolInput = Static<typeof bashSchema>;\n\nexport interface BashToolDetails {\n\ttruncation?: TruncationResult;\n\tfullOutputPath?: string;\n}\n\n/**\n * Pluggable operations for the bash tool.\n * Override these to delegate command execution to remote systems (for example SSH).\n */\nexport interface BashOperations {\n\t/**\n\t * Execute a command and stream output.\n\t * @param command The command to execute\n\t * @param cwd Working directory\n\t * @param options Execution options\n\t * @returns Promise resolving to exit code (null if killed)\n\t */\n\texec: (\n\t\tcommand: string,\n\t\tcwd: string,\n\t\toptions: {\n\t\t\tonData: (data: Buffer) => void;\n\t\t\tsignal?: AbortSignal;\n\t\t\ttimeout?: number;\n\t\t\tenv?: NodeJS.ProcessEnv;\n\t\t},\n\t) => Promise<{ exitCode: number | null }>;\n}\n\n/**\n * Create bash operations using pi's built-in local shell execution backend.\n *\n * This is useful for extensions that intercept user_bash and still want pi's\n * standard local shell behavior while wrapping or rewriting commands.\n */\nexport function createLocalBashOperations(options?: { shellPath?: string }): BashOperations {\n\treturn {\n\t\texec: async (command, cwd, { onData, signal, timeout, env }) => {\n\t\t\tconst { shell, args } = getShellConfig(options?.shellPath);\n\t\t\ttry {\n\t\t\t\tawait fsAccess(cwd, constants.F_OK);\n\t\t\t} catch {\n\t\t\t\tthrow new Error(`Working directory does not exist: ${cwd}\\nCannot execute bash commands.`);\n\t\t\t}\n\t\t\tif (signal?.aborted) {\n\t\t\t\tthrow new Error(\"aborted\");\n\t\t\t}\n\n\t\t\tconst child = spawn(shell, [...args, command], {\n\t\t\t\tcwd,\n\t\t\t\tdetached: process.platform !== \"win32\",\n\t\t\t\tenv: env ?? getShellEnv(),\n\t\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\t\twindowsHide: true,\n\t\t\t});\n\t\t\tif (child.pid) trackDetachedChildPid(child.pid);\n\t\t\tlet timedOut = false;\n\t\t\tlet timeoutHandle: NodeJS.Timeout | undefined;\n\t\t\tconst onAbort = () => {\n\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t};\n\n\t\t\ttry {\n\t\t\t\t// Set timeout if provided.\n\t\t\t\tif (timeout !== undefined && timeout > 0) {\n\t\t\t\t\ttimeoutHandle = setTimeout(() => {\n\t\t\t\t\t\ttimedOut = true;\n\t\t\t\t\t\tif (child.pid) killProcessTree(child.pid);\n\t\t\t\t\t}, timeout * 1000);\n\t\t\t\t}\n\t\t\t\t// Stream stdout and stderr.\n\t\t\t\tchild.stdout?.on(\"data\", onData);\n\t\t\t\tchild.stderr?.on(\"data\", onData);\n\t\t\t\t// Handle abort signal by killing the entire process tree.\n\t\t\t\tif (signal) {\n\t\t\t\t\tif (signal.aborted) onAbort();\n\t\t\t\t\telse signal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\t}\n\t\t\t\t// Handle shell spawn errors and wait for the process to terminate without hanging\n\t\t\t\t// on inherited stdio handles held by detached descendants.\n\t\t\t\tconst exitCode = await waitForChildProcess(child);\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tthrow new Error(\"aborted\");\n\t\t\t\t}\n\t\t\t\tif (timedOut) {\n\t\t\t\t\tthrow new Error(`timeout:${timeout}`);\n\t\t\t\t}\n\t\t\t\treturn { exitCode };\n\t\t\t} finally {\n\t\t\t\tif (child.pid) untrackDetachedChildPid(child.pid);\n\t\t\t\tif (timeoutHandle) clearTimeout(timeoutHandle);\n\t\t\t\tif (signal) signal.removeEventListener(\"abort\", onAbort);\n\t\t\t}\n\t\t},\n\t};\n}\n\nexport interface BashSpawnContext {\n\tcommand: string;\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n}\n\nexport type BashSpawnHook = (context: BashSpawnContext) => BashSpawnContext;\n\nfunction resolveSpawnContext(command: string, cwd: string, spawnHook?: BashSpawnHook): BashSpawnContext {\n\tconst baseContext: BashSpawnContext = { command, cwd, env: { ...getShellEnv() } };\n\treturn spawnHook ? spawnHook(baseContext) : baseContext;\n}\n\nexport interface BashToolOptions {\n\t/** Custom operations for command execution. Default: local shell */\n\toperations?: BashOperations;\n\t/** Command prefix prepended to every command (for example shell setup commands) */\n\tcommandPrefix?: string;\n\t/** Optional explicit shell path from settings */\n\tshellPath?: string;\n\t/** Hook to adjust command, cwd, or env before execution */\n\tspawnHook?: BashSpawnHook;\n\t/** Optional command-level policy enforced before commandPrefix, spawnHook, or execution */\n\tpolicy?: BashCommandPolicy;\n\t/** Human-readable label used in policy denial errors */\n\tpolicyLabel?: string;\n}\n\nconst BASH_PREVIEW_LINES = 5;\nconst BASH_UPDATE_THROTTLE_MS = 100;\n\ntype BashRenderState = {\n\tstartedAt: number | undefined;\n\tendedAt: number | undefined;\n\tinterval: NodeJS.Timeout | undefined;\n};\n\ntype BashResultRenderState = {\n\tcachedWidth: number | undefined;\n\tcachedLines: string[] | undefined;\n\tcachedSkipped: number | undefined;\n};\n\nclass BashResultRenderComponent extends Container {\n\tstate: BashResultRenderState = {\n\t\tcachedWidth: undefined,\n\t\tcachedLines: undefined,\n\t\tcachedSkipped: undefined,\n\t};\n}\n\nfunction formatDuration(ms: number): string {\n\tconst totalSeconds = Math.floor(Math.max(0, ms) / 1000);\n\tconst hours = Math.floor(totalSeconds / 3600);\n\tconst minutes = Math.floor((totalSeconds % 3600) / 60);\n\tconst seconds = totalSeconds % 60;\n\tif (hours > 0) return minutes > 0 ? `${hours}h ${minutes}m` : `${hours}h`;\n\tif (minutes > 0) return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;\n\treturn `${seconds}s`;\n}\n\nfunction formatBashCall(args: { command?: string; timeout?: number } | undefined): string {\n\tconst command = str(args?.command);\n\tconst timeout = args?.timeout as number | undefined;\n\tconst timeoutSuffix = timeout ? theme.fg(\"muted\", ` (timeout ${timeout}s)`) : \"\";\n\tconst commandDisplay = command === null ? invalidArgText(theme) : command ? command : theme.fg(\"toolOutput\", \"...\");\n\treturn theme.fg(\"toolTitle\", theme.bold(`$ ${commandDisplay}`)) + timeoutSuffix;\n}\n\nfunction rebuildBashResultRenderComponent(\n\tcomponent: BashResultRenderComponent,\n\tresult: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tdetails?: BashToolDetails;\n\t},\n\toptions: ToolRenderResultOptions,\n\tshowImages: boolean,\n\tstartedAt: number | undefined,\n\tendedAt: number | undefined,\n): void {\n\tconst state = component.state;\n\tcomponent.clear();\n\n\tlet output = getTextOutput(result, showImages).trim();\n\tconst truncation = result.details?.truncation;\n\tconst fullOutputPath = result.details?.fullOutputPath;\n\tif (!options.isPartial && truncation?.truncated && fullOutputPath && output.endsWith(\"]\")) {\n\t\tconst footerStart = output.lastIndexOf(\"\\n\\n[\");\n\t\tif (footerStart !== -1 && output.slice(footerStart).includes(fullOutputPath)) {\n\t\t\toutput = output.slice(0, footerStart).trimEnd();\n\t\t}\n\t}\n\n\tif (output) {\n\t\tconst styledOutput = output\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => theme.fg(\"toolOutput\", line))\n\t\t\t.join(\"\\n\");\n\n\t\tif (options.expanded) {\n\t\t\tcomponent.addChild(new Text(`\\n${styledOutput}`, 0, 0));\n\t\t} else {\n\t\t\tcomponent.addChild({\n\t\t\t\trender: (width: number) => {\n\t\t\t\t\tif (state.cachedLines === undefined || state.cachedWidth !== width) {\n\t\t\t\t\t\tconst preview = truncateToVisualLines(styledOutput, BASH_PREVIEW_LINES, width);\n\t\t\t\t\t\tstate.cachedLines = preview.visualLines;\n\t\t\t\t\t\tstate.cachedSkipped = preview.skippedCount;\n\t\t\t\t\t\tstate.cachedWidth = width;\n\t\t\t\t\t}\n\t\t\t\t\tif (state.cachedSkipped && state.cachedSkipped > 0) {\n\t\t\t\t\t\tconst hint =\n\t\t\t\t\t\t\ttheme.fg(\"muted\", `... (${state.cachedSkipped} earlier lines,`) +\n\t\t\t\t\t\t\t` ${keyHint(\"app.tools.expand\", \"Expand\")}${theme.fg(\"muted\", \")\")}`;\n\t\t\t\t\t\treturn [\"\", truncateToWidth(hint, width, \"...\"), ...(state.cachedLines ?? [])];\n\t\t\t\t\t}\n\t\t\t\t\treturn [\"\", ...(state.cachedLines ?? [])];\n\t\t\t\t},\n\t\t\t\tinvalidate: () => {\n\t\t\t\t\tstate.cachedWidth = undefined;\n\t\t\t\t\tstate.cachedLines = undefined;\n\t\t\t\t\tstate.cachedSkipped = undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\tif (truncation?.truncated || fullOutputPath) {\n\t\tconst warnings: string[] = [];\n\t\tif (fullOutputPath) {\n\t\t\twarnings.push(`Full output: ${fullOutputPath}`);\n\t\t}\n\t\tif (truncation?.truncated) {\n\t\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\t\twarnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`);\n\t\t\t} else {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"warning\", `[${warnings.join(\". \")}]`)}`, 0, 0));\n\t}\n\n\tif (startedAt !== undefined) {\n\t\tconst label = options.isPartial ? \"Elapsed\" : \"Took\";\n\t\tconst endTime = endedAt ?? Date.now();\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"muted\", `${label} ${formatDuration(endTime - startedAt)}`)}`, 0, 0));\n\t}\n}\n\nexport function createBashToolDefinition(\n\tcwd: string,\n\toptions?: BashToolOptions,\n): ToolDefinition<typeof bashSchema, BashToolDetails | undefined, BashRenderState> {\n\tconst ops = options?.operations ?? createLocalBashOperations({ shellPath: options?.shellPath });\n\tconst commandPrefix = options?.commandPrefix;\n\tconst spawnHook = options?.spawnHook;\n\tconst policy = options?.policy;\n\tconst policyLabel = options?.policyLabel;\n\treturn {\n\t\tname: \"bash\",\n\t\tlabel: \"bash\",\n\t\tdescription: `Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.`,\n\t\tpromptSnippet: \"Execute bash commands (ls, grep, find, etc.)\",\n\t\tparameters: bashSchema,\n\t\tmaxResultSizeChars: Infinity,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ command, timeout }: { command: string; timeout?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t\tonUpdate?,\n\t\t\t_ctx?,\n\t\t) {\n\t\t\tconst policyDecision = evaluateBashCommandPolicy(command, policy);\n\t\t\tif (!policyDecision.allowed) {\n\t\t\t\tthrow new Error(formatBashCommandPolicyRejection(policyDecision, policyLabel));\n\t\t\t}\n\n\t\t\tconst resolvedCommand = commandPrefix ? `${commandPrefix}\\n${command}` : command;\n\t\t\tconst spawnContext = resolveSpawnContext(resolvedCommand, cwd, spawnHook);\n\t\t\tconst output = new OutputAccumulator({ tempFilePrefix: `${APP_NAME}-bash` });\n\t\t\tlet updateTimer: NodeJS.Timeout | undefined;\n\t\t\tlet updateDirty = false;\n\t\t\tlet lastUpdateAt = 0;\n\n\t\t\tconst emitOutputUpdate = () => {\n\t\t\t\tif (!onUpdate || !updateDirty) return;\n\t\t\t\tupdateDirty = false;\n\t\t\t\tlastUpdateAt = Date.now();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tonUpdate({\n\t\t\t\t\tcontent: [{ type: \"text\", text: snapshot.content || \"\" }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\ttruncation: snapshot.truncation.truncated ? snapshot.truncation : undefined,\n\t\t\t\t\t\tfullOutputPath: snapshot.fullOutputPath,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tconst clearUpdateTimer = () => {\n\t\t\t\tif (updateTimer) {\n\t\t\t\t\tclearTimeout(updateTimer);\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst scheduleOutputUpdate = () => {\n\t\t\t\tif (!onUpdate) return;\n\t\t\t\tupdateDirty = true;\n\t\t\t\tconst delay = BASH_UPDATE_THROTTLE_MS - (Date.now() - lastUpdateAt);\n\t\t\t\tif (delay <= 0) {\n\t\t\t\t\tclearUpdateTimer();\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tupdateTimer ??= setTimeout(() => {\n\t\t\t\t\tupdateTimer = undefined;\n\t\t\t\t\temitOutputUpdate();\n\t\t\t\t}, delay);\n\t\t\t};\n\n\t\t\tif (onUpdate) {\n\t\t\t\tonUpdate({ content: [], details: undefined });\n\t\t\t}\n\n\t\t\tconst handleData = (data: Buffer) => {\n\t\t\t\toutput.append(data);\n\t\t\t\tscheduleOutputUpdate();\n\t\t\t};\n\n\t\t\tconst finishOutput = async () => {\n\t\t\t\toutput.finish();\n\t\t\t\tclearUpdateTimer();\n\t\t\t\temitOutputUpdate();\n\t\t\t\tconst snapshot = output.snapshot({ persistIfTruncated: true });\n\t\t\t\tawait output.closeTempFile();\n\t\t\t\treturn snapshot;\n\t\t\t};\n\n\t\t\tconst formatOutput = (snapshot: Awaited<ReturnType<typeof finishOutput>>, emptyText = \"(no output)\") => {\n\t\t\t\tconst truncation = snapshot.truncation;\n\t\t\t\tlet text = snapshot.content || emptyText;\n\t\t\t\tlet details: BashToolDetails | undefined;\n\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\tdetails = { truncation, fullOutputPath: snapshot.fullOutputPath };\n\t\t\t\t\tconst startLine = truncation.totalLines - truncation.outputLines + 1;\n\t\t\t\t\tconst endLine = truncation.totalLines;\n\t\t\t\t\tif (truncation.lastLinePartial) {\n\t\t\t\t\t\tconst lastLineSize = formatSize(output.getLastLineBytes());\n\t\t\t\t\t\ttext += `\\n\\n[Showing last ${formatSize(truncation.outputBytes)} of line ${endLine} (line is ${lastLineSize}). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else if (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines}. Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttext += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Full output: ${snapshot.fullOutputPath}]`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { text, details };\n\t\t\t};\n\n\t\t\tconst appendStatus = (text: string, status: string) => `${text ? `${text}\\n\\n` : \"\"}${status}`;\n\n\t\t\ttry {\n\t\t\t\tlet exitCode: number | null;\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await ops.exec(spawnContext.command, spawnContext.cwd, {\n\t\t\t\t\t\tonData: handleData,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\ttimeout,\n\t\t\t\t\t\tenv: spawnContext.env,\n\t\t\t\t\t});\n\t\t\t\t\texitCode = result.exitCode;\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\t\tconst { text } = formatOutput(snapshot, \"\");\n\t\t\t\t\tif (err instanceof Error && err.message === \"aborted\") {\n\t\t\t\t\t\tthrow new Error(appendStatus(text, \"Command aborted\"));\n\t\t\t\t\t}\n\t\t\t\t\tif (err instanceof Error && err.message.startsWith(\"timeout:\")) {\n\t\t\t\t\t\tconst timeoutSecs = err.message.split(\":\")[1];\n\t\t\t\t\t\tthrow new Error(appendStatus(text, `Command timed out after ${timeoutSecs} seconds`));\n\t\t\t\t\t}\n\t\t\t\t\tthrow err;\n\t\t\t\t}\n\n\t\t\t\tconst snapshot = await finishOutput();\n\t\t\t\tconst { text: outputText, details } = formatOutput(snapshot);\n\t\t\t\tif (exitCode !== 0 && exitCode !== null) {\n\t\t\t\t\tthrow new Error(appendStatus(outputText, `Command exited with code ${exitCode}`));\n\t\t\t\t}\n\t\t\t\treturn { content: [{ type: \"text\", text: outputText }], details };\n\t\t\t} finally {\n\t\t\t\tclearUpdateTimer();\n\t\t\t}\n\t\t},\n\t\trenderCall(args, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (context.executionStarted && state.startedAt === undefined) {\n\t\t\t\tstate.startedAt = Date.now();\n\t\t\t\tstate.endedAt = undefined;\n\t\t\t}\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatBashCall(args));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (state.startedAt !== undefined && options.isPartial && !state.interval) {\n\t\t\t\tstate.interval = setInterval(() => context.invalidate(), 1000);\n\t\t\t}\n\t\t\tif (!options.isPartial || context.isError) {\n\t\t\t\tstate.endedAt ??= Date.now();\n\t\t\t\tif (state.interval) {\n\t\t\t\t\tclearInterval(state.interval);\n\t\t\t\t\tstate.interval = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst component =\n\t\t\t\t(context.lastComponent as BashResultRenderComponent | undefined) ?? new BashResultRenderComponent();\n\t\t\trebuildBashResultRenderComponent(\n\t\t\t\tcomponent,\n\t\t\t\tresult,\n\t\t\t\toptions,\n\t\t\t\tcontext.showImages,\n\t\t\t\tstate.startedAt,\n\t\t\t\tstate.endedAt,\n\t\t\t);\n\t\t\tcomponent.invalidate();\n\t\t\treturn component;\n\t\t},\n\t};\n}\n\nexport function createBashTool(cwd: string, options?: BashToolOptions): AgentTool<typeof bashSchema> {\n\treturn wrapToolDefinition(createBashToolDefinition(cwd, options));\n}\n"]}