@greppleai/grip 0.1.5 → 0.1.7

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 (587) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +1 -1
  3. package/dist/bun/cli.d.ts.map +1 -1
  4. package/dist/bun/cli.js.map +1 -1
  5. package/dist/bun/embedded-assets.d.ts.map +1 -1
  6. package/dist/bun/embedded-assets.js.map +1 -1
  7. package/dist/bun/register-bedrock.d.ts.map +1 -1
  8. package/dist/bun/restore-sandbox-env.d.ts.map +1 -1
  9. package/dist/bun/restore-sandbox-env.js.map +1 -1
  10. package/dist/cli/args.d.ts.map +1 -1
  11. package/dist/cli/args.js.map +1 -1
  12. package/dist/cli/config-selector.d.ts.map +1 -1
  13. package/dist/cli/config-selector.js.map +1 -1
  14. package/dist/cli/file-processor.d.ts.map +1 -1
  15. package/dist/cli/file-processor.js.map +1 -1
  16. package/dist/cli/initial-message.d.ts +1 -1
  17. package/dist/cli/initial-message.d.ts.map +1 -1
  18. package/dist/cli/initial-message.js.map +1 -1
  19. package/dist/cli/list-models.d.ts.map +1 -1
  20. package/dist/cli/list-models.js.map +1 -1
  21. package/dist/cli/session-picker.d.ts.map +1 -1
  22. package/dist/cli/session-picker.js.map +1 -1
  23. package/dist/cli.d.ts.map +1 -1
  24. package/dist/cli.js.map +1 -1
  25. package/dist/config.d.ts.map +1 -1
  26. package/dist/config.js +2 -0
  27. package/dist/config.js.map +1 -1
  28. package/dist/core/agent-session.d.ts +38 -1
  29. package/dist/core/agent-session.d.ts.map +1 -1
  30. package/dist/core/agent-session.js +289 -154
  31. package/dist/core/agent-session.js.map +1 -1
  32. package/dist/core/auth-guidance.d.ts.map +1 -1
  33. package/dist/core/auth-guidance.js.map +1 -1
  34. package/dist/core/auth-storage.d.ts +4 -0
  35. package/dist/core/auth-storage.d.ts.map +1 -1
  36. package/dist/core/auth-storage.js +3 -10
  37. package/dist/core/auth-storage.js.map +1 -1
  38. package/dist/core/bash-executor.d.ts.map +1 -1
  39. package/dist/core/bash-executor.js +19 -23
  40. package/dist/core/bash-executor.js.map +1 -1
  41. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  42. package/dist/core/compaction/branch-summarization.js.map +1 -1
  43. package/dist/core/compaction/compaction.d.ts.map +1 -1
  44. package/dist/core/compaction/compaction.js +9 -2
  45. package/dist/core/compaction/compaction.js.map +1 -1
  46. package/dist/core/compaction/compression-detection-ledger.d.ts.map +1 -1
  47. package/dist/core/compaction/compression-detection-ledger.js.map +1 -1
  48. package/dist/core/compaction/compression-detector.d.ts +1 -0
  49. package/dist/core/compaction/compression-detector.d.ts.map +1 -1
  50. package/dist/core/compaction/compression-detector.js +10 -21
  51. package/dist/core/compaction/compression-detector.js.map +1 -1
  52. package/dist/core/compaction/compression-economics.d.ts.map +1 -1
  53. package/dist/core/compaction/compression-economics.js.map +1 -1
  54. package/dist/core/compaction/utils.d.ts.map +1 -1
  55. package/dist/core/compaction/utils.js.map +1 -1
  56. package/dist/core/defaults.d.ts.map +1 -1
  57. package/dist/core/diagnostics.d.ts.map +1 -1
  58. package/dist/core/event-bus.d.ts.map +1 -1
  59. package/dist/core/event-bus.js.map +1 -1
  60. package/dist/core/exec.d.ts.map +1 -1
  61. package/dist/core/exec.js.map +1 -1
  62. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
  63. package/dist/core/export-html/ansi-to-html.js.map +1 -1
  64. package/dist/core/export-html/index.d.ts.map +1 -1
  65. package/dist/core/export-html/index.js.map +1 -1
  66. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  67. package/dist/core/export-html/tool-renderer.js.map +1 -1
  68. package/dist/core/extensions/loader.d.ts.map +1 -1
  69. package/dist/core/extensions/loader.js.map +1 -1
  70. package/dist/core/extensions/runner.d.ts +3 -0
  71. package/dist/core/extensions/runner.d.ts.map +1 -1
  72. package/dist/core/extensions/runner.js +40 -30
  73. package/dist/core/extensions/runner.js.map +1 -1
  74. package/dist/core/extensions/types.d.ts +21 -1
  75. package/dist/core/extensions/types.d.ts.map +1 -1
  76. package/dist/core/extensions/types.js.map +1 -1
  77. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  78. package/dist/core/extensions/wrapper.js.map +1 -1
  79. package/dist/core/footer-data-provider.d.ts.map +1 -1
  80. package/dist/core/footer-data-provider.js +15 -16
  81. package/dist/core/footer-data-provider.js.map +1 -1
  82. package/dist/core/grip-agent.d.ts.map +1 -1
  83. package/dist/core/grip-agent.js +7 -21
  84. package/dist/core/grip-agent.js.map +1 -1
  85. package/dist/core/grip-manifest.d.ts.map +1 -1
  86. package/dist/core/grip-manifest.js.map +1 -1
  87. package/dist/core/hooks/aggregate.d.ts.map +1 -1
  88. package/dist/core/hooks/aggregate.js.map +1 -1
  89. package/dist/core/hooks/config.d.ts.map +1 -1
  90. package/dist/core/hooks/config.js.map +1 -1
  91. package/dist/core/hooks/executor.d.ts.map +1 -1
  92. package/dist/core/hooks/executor.js.map +1 -1
  93. package/dist/core/hooks/index.d.ts.map +1 -1
  94. package/dist/core/hooks/index.js.map +1 -1
  95. package/dist/core/hooks/matcher.d.ts.map +1 -1
  96. package/dist/core/hooks/matcher.js.map +1 -1
  97. package/dist/core/hooks/trust-store.d.ts.map +1 -1
  98. package/dist/core/hooks/trust-store.js +0 -3
  99. package/dist/core/hooks/trust-store.js.map +1 -1
  100. package/dist/core/hooks/types.d.ts.map +1 -1
  101. package/dist/core/hooks/types.js.map +1 -1
  102. package/dist/core/http-dispatcher.d.ts.map +1 -1
  103. package/dist/core/http-dispatcher.js.map +1 -1
  104. package/dist/core/instruction-resource-loader.d.ts +1 -0
  105. package/dist/core/instruction-resource-loader.d.ts.map +1 -1
  106. package/dist/core/instruction-resource-loader.js +2 -4
  107. package/dist/core/instruction-resource-loader.js.map +1 -1
  108. package/dist/core/keybindings.d.ts.map +1 -1
  109. package/dist/core/keybindings.js +0 -1
  110. package/dist/core/keybindings.js.map +1 -1
  111. package/dist/core/lsp/abort.d.ts.map +1 -1
  112. package/dist/core/lsp/abort.js.map +1 -1
  113. package/dist/core/lsp/client.d.ts.map +1 -1
  114. package/dist/core/lsp/client.js +8 -22
  115. package/dist/core/lsp/client.js.map +1 -1
  116. package/dist/core/lsp/config-loader.d.ts.map +1 -1
  117. package/dist/core/lsp/config-loader.js.map +1 -1
  118. package/dist/core/lsp/config.d.ts.map +1 -1
  119. package/dist/core/lsp/config.js.map +1 -1
  120. package/dist/core/lsp/diagnostics.d.ts.map +1 -1
  121. package/dist/core/lsp/diagnostics.js.map +1 -1
  122. package/dist/core/lsp/file-sync.d.ts.map +1 -1
  123. package/dist/core/lsp/file-sync.js +7 -9
  124. package/dist/core/lsp/file-sync.js.map +1 -1
  125. package/dist/core/lsp/integration.d.ts.map +1 -1
  126. package/dist/core/lsp/integration.js.map +1 -1
  127. package/dist/core/lsp/language-map.d.ts.map +1 -1
  128. package/dist/core/lsp/language-map.js +2 -7
  129. package/dist/core/lsp/language-map.js.map +1 -1
  130. package/dist/core/lsp/manager.d.ts.map +1 -1
  131. package/dist/core/lsp/manager.js +18 -29
  132. package/dist/core/lsp/manager.js.map +1 -1
  133. package/dist/core/lsp/navigation.d.ts.map +1 -1
  134. package/dist/core/lsp/navigation.js.map +1 -1
  135. package/dist/core/lsp/portable-path.d.ts.map +1 -1
  136. package/dist/core/lsp/portable-path.js.map +1 -1
  137. package/dist/core/lsp/refactor.d.ts.map +1 -1
  138. package/dist/core/lsp/refactor.js.map +1 -1
  139. package/dist/core/lsp/transport.d.ts.map +1 -1
  140. package/dist/core/lsp/transport.js.map +1 -1
  141. package/dist/core/messages.d.ts.map +1 -1
  142. package/dist/core/messages.js +30 -1
  143. package/dist/core/messages.js.map +1 -1
  144. package/dist/core/model-registry.d.ts.map +1 -1
  145. package/dist/core/model-registry.js +5 -7
  146. package/dist/core/model-registry.js.map +1 -1
  147. package/dist/core/model-resolver.d.ts.map +1 -1
  148. package/dist/core/model-resolver.js.map +1 -1
  149. package/dist/core/output-guard.d.ts.map +1 -1
  150. package/dist/core/output-guard.js.map +1 -1
  151. package/dist/core/package-manager.d.ts.map +1 -1
  152. package/dist/core/package-manager.js +0 -6
  153. package/dist/core/package-manager.js.map +1 -1
  154. package/dist/core/prompt-templates.d.ts.map +1 -1
  155. package/dist/core/prompt-templates.js.map +1 -1
  156. package/dist/core/provider-display-names.d.ts.map +1 -1
  157. package/dist/core/remote-workspace-protocol/contract.d.ts.map +1 -1
  158. package/dist/core/remote-workspace-protocol/contract.js +4 -2
  159. package/dist/core/remote-workspace-protocol/contract.js.map +1 -1
  160. package/dist/core/remote-workspace-protocol/guest-shared-client.d.ts.map +1 -1
  161. package/dist/core/remote-workspace-protocol/guest-shared-client.js +1 -5
  162. package/dist/core/remote-workspace-protocol/guest-shared-client.js.map +1 -1
  163. package/dist/core/remote-workspace-protocol/guest-shared-outbound-scheduler.d.ts.map +1 -1
  164. package/dist/core/remote-workspace-protocol/guest-shared-outbound-scheduler.js +5 -10
  165. package/dist/core/remote-workspace-protocol/guest-shared-outbound-scheduler.js.map +1 -1
  166. package/dist/core/remote-workspace-protocol/guest-shared-uplink.d.ts.map +1 -1
  167. package/dist/core/remote-workspace-protocol/guest-shared-uplink.js +2 -9
  168. package/dist/core/remote-workspace-protocol/guest-shared-uplink.js.map +1 -1
  169. package/dist/core/remote-workspace-protocol/lima-owner-directory.d.ts.map +1 -1
  170. package/dist/core/remote-workspace-protocol/lima-owner-directory.js.map +1 -1
  171. package/dist/core/remote-workspace-protocol/lima-owner-lock.d.ts.map +1 -1
  172. package/dist/core/remote-workspace-protocol/lima-owner-lock.js.map +1 -1
  173. package/dist/core/remote-workspace-protocol/session.d.ts.map +1 -1
  174. package/dist/core/remote-workspace-protocol/session.js +27 -65
  175. package/dist/core/remote-workspace-protocol/session.js.map +1 -1
  176. package/dist/core/remote-workspace-protocol/shared-transport.d.ts.map +1 -1
  177. package/dist/core/remote-workspace-protocol/shared-transport.js.map +1 -1
  178. package/dist/core/resolve-config-value.d.ts.map +1 -1
  179. package/dist/core/resolve-config-value.js.map +1 -1
  180. package/dist/core/resource-loader.d.ts.map +1 -1
  181. package/dist/core/resource-loader.js +0 -48
  182. package/dist/core/resource-loader.js.map +1 -1
  183. package/dist/core/rules.d.ts.map +1 -1
  184. package/dist/core/rules.js.map +1 -1
  185. package/dist/core/sandbox/command.d.ts.map +1 -1
  186. package/dist/core/sandbox/command.js.map +1 -1
  187. package/dist/core/sandbox/config.d.ts.map +1 -1
  188. package/dist/core/sandbox/config.js.map +1 -1
  189. package/dist/core/sandbox/lima-guest-binary.d.ts.map +1 -1
  190. package/dist/core/sandbox/lima-guest-binary.js.map +1 -1
  191. package/dist/core/sandbox/lima.d.ts +2 -0
  192. package/dist/core/sandbox/lima.d.ts.map +1 -1
  193. package/dist/core/sandbox/lima.js +3 -9
  194. package/dist/core/sandbox/lima.js.map +1 -1
  195. package/dist/core/sandbox/shared-lima-roots.d.ts.map +1 -1
  196. package/dist/core/sandbox/shared-lima-roots.js.map +1 -1
  197. package/dist/core/sandbox/update-shared-guest-binary.d.ts.map +1 -1
  198. package/dist/core/sandbox/update-shared-guest-binary.js.map +1 -1
  199. package/dist/core/session/constants.d.ts.map +1 -1
  200. package/dist/core/session/context-metadata.d.ts.map +1 -1
  201. package/dist/core/session/context-metadata.js.map +1 -1
  202. package/dist/core/session/context.d.ts.map +1 -1
  203. package/dist/core/session/context.js.map +1 -1
  204. package/dist/core/session/ids.d.ts.map +1 -1
  205. package/dist/core/session/ids.js.map +1 -1
  206. package/dist/core/session/in-memory-session-manager.d.ts.map +1 -1
  207. package/dist/core/session/in-memory-session-manager.js +0 -1
  208. package/dist/core/session/in-memory-session-manager.js.map +1 -1
  209. package/dist/core/session/in-memory-session.d.ts.map +1 -1
  210. package/dist/core/session/in-memory-session.js.map +1 -1
  211. package/dist/core/session/jsonl-errors.d.ts.map +1 -1
  212. package/dist/core/session/jsonl-errors.js +0 -11
  213. package/dist/core/session/jsonl-errors.js.map +1 -1
  214. package/dist/core/session/jsonl-helpers.d.ts.map +1 -1
  215. package/dist/core/session/jsonl-helpers.js.map +1 -1
  216. package/dist/core/session/local-session-manager.d.ts.map +1 -1
  217. package/dist/core/session/local-session-manager.js +4 -6
  218. package/dist/core/session/local-session-manager.js.map +1 -1
  219. package/dist/core/session/local-session.d.ts.map +1 -1
  220. package/dist/core/session/local-session.js.map +1 -1
  221. package/dist/core/session/migrations.d.ts.map +1 -1
  222. package/dist/core/session/migrations.js.map +1 -1
  223. package/dist/core/session/remote-session-client.d.ts.map +1 -1
  224. package/dist/core/session/remote-session-client.js +0 -6
  225. package/dist/core/session/remote-session-client.js.map +1 -1
  226. package/dist/core/session/remote-session-manager.d.ts.map +1 -1
  227. package/dist/core/session/remote-session-manager.js +0 -3
  228. package/dist/core/session/remote-session-manager.js.map +1 -1
  229. package/dist/core/session/remote-session.d.ts.map +1 -1
  230. package/dist/core/session/remote-session.js +0 -1
  231. package/dist/core/session/remote-session.js.map +1 -1
  232. package/dist/core/session/session-manager.d.ts.map +1 -1
  233. package/dist/core/session/session.d.ts.map +1 -1
  234. package/dist/core/session/session.js +1 -5
  235. package/dist/core/session/session.js.map +1 -1
  236. package/dist/core/session/stores/in-memory-session-store.d.ts.map +1 -1
  237. package/dist/core/session/stores/in-memory-session-store.js +7 -6
  238. package/dist/core/session/stores/in-memory-session-store.js.map +1 -1
  239. package/dist/core/session/stores/jsonl-session-store.d.ts.map +1 -1
  240. package/dist/core/session/stores/jsonl-session-store.js +6 -14
  241. package/dist/core/session/stores/jsonl-session-store.js.map +1 -1
  242. package/dist/core/session/stores/remote-session-store.d.ts.map +1 -1
  243. package/dist/core/session/stores/remote-session-store.js +3 -8
  244. package/dist/core/session/stores/remote-session-store.js.map +1 -1
  245. package/dist/core/session/stores/session-store.d.ts.map +1 -1
  246. package/dist/core/session/types.d.ts.map +1 -1
  247. package/dist/core/session/usage-ledger.d.ts.map +1 -1
  248. package/dist/core/session/usage-ledger.js.map +1 -1
  249. package/dist/core/session-cwd.d.ts.map +1 -1
  250. package/dist/core/session-cwd.js +0 -1
  251. package/dist/core/session-cwd.js.map +1 -1
  252. package/dist/core/settings-manager.d.ts.map +1 -1
  253. package/dist/core/settings-manager.js +9 -17
  254. package/dist/core/settings-manager.js.map +1 -1
  255. package/dist/core/skills.d.ts.map +1 -1
  256. package/dist/core/skills.js +3 -2
  257. package/dist/core/skills.js.map +1 -1
  258. package/dist/core/slash-commands.d.ts.map +1 -1
  259. package/dist/core/source-info.d.ts.map +1 -1
  260. package/dist/core/source-info.js.map +1 -1
  261. package/dist/core/system-prompt.d.ts +1 -1
  262. package/dist/core/system-prompt.d.ts.map +1 -1
  263. package/dist/core/system-prompt.js +3 -2
  264. package/dist/core/system-prompt.js.map +1 -1
  265. package/dist/core/telemetry.d.ts.map +1 -1
  266. package/dist/core/telemetry.js.map +1 -1
  267. package/dist/core/timings.d.ts.map +1 -1
  268. package/dist/core/timings.js.map +1 -1
  269. package/dist/core/tools/bash.d.ts +1 -0
  270. package/dist/core/tools/bash.d.ts.map +1 -1
  271. package/dist/core/tools/bash.js +34 -28
  272. package/dist/core/tools/bash.js.map +1 -1
  273. package/dist/core/tools/compress-context.d.ts.map +1 -1
  274. package/dist/core/tools/compress-context.js.map +1 -1
  275. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  276. package/dist/core/tools/edit-diff.js.map +1 -1
  277. package/dist/core/tools/edit.d.ts.map +1 -1
  278. package/dist/core/tools/edit.js.map +1 -1
  279. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  280. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  281. package/dist/core/tools/find.d.ts.map +1 -1
  282. package/dist/core/tools/find.js.map +1 -1
  283. package/dist/core/tools/grep.d.ts.map +1 -1
  284. package/dist/core/tools/grep.js.map +1 -1
  285. package/dist/core/tools/hash-store.d.ts.map +1 -1
  286. package/dist/core/tools/hash-store.js.map +1 -1
  287. package/dist/core/tools/hashline/apply.d.ts.map +1 -1
  288. package/dist/core/tools/hashline/apply.js.map +1 -1
  289. package/dist/core/tools/hashline/hash.d.ts.map +1 -1
  290. package/dist/core/tools/hashline/hash.js.map +1 -1
  291. package/dist/core/tools/hashline/parse.d.ts.map +1 -1
  292. package/dist/core/tools/hashline/parse.js.map +1 -1
  293. package/dist/core/tools/hashline/resolve.d.ts.map +1 -1
  294. package/dist/core/tools/hashline/resolve.js.map +1 -1
  295. package/dist/core/tools/hashline-utils.d.ts.map +1 -1
  296. package/dist/core/tools/hashline-utils.js.map +1 -1
  297. package/dist/core/tools/index.d.ts.map +1 -1
  298. package/dist/core/tools/index.js.map +1 -1
  299. package/dist/core/tools/ls.d.ts.map +1 -1
  300. package/dist/core/tools/ls.js.map +1 -1
  301. package/dist/core/tools/operations.d.ts +11 -0
  302. package/dist/core/tools/operations.d.ts.map +1 -1
  303. package/dist/core/tools/operations.js +54 -28
  304. package/dist/core/tools/operations.js.map +1 -1
  305. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  306. package/dist/core/tools/output-accumulator.js +12 -18
  307. package/dist/core/tools/output-accumulator.js.map +1 -1
  308. package/dist/core/tools/path-utils.d.ts.map +1 -1
  309. package/dist/core/tools/path-utils.js.map +1 -1
  310. package/dist/core/tools/read.d.ts.map +1 -1
  311. package/dist/core/tools/read.js.map +1 -1
  312. package/dist/core/tools/render-utils.d.ts.map +1 -1
  313. package/dist/core/tools/render-utils.js.map +1 -1
  314. package/dist/core/tools/replace-diff.d.ts.map +1 -1
  315. package/dist/core/tools/replace-diff.js.map +1 -1
  316. package/dist/core/tools/replace-normalize.d.ts.map +1 -1
  317. package/dist/core/tools/replace-normalize.js.map +1 -1
  318. package/dist/core/tools/replace-render.d.ts +1 -1
  319. package/dist/core/tools/replace-render.d.ts.map +1 -1
  320. package/dist/core/tools/replace-render.js.map +1 -1
  321. package/dist/core/tools/runtime.d.ts.map +1 -1
  322. package/dist/core/tools/runtime.js.map +1 -1
  323. package/dist/core/tools/session-history.d.ts.map +1 -1
  324. package/dist/core/tools/session-history.js.map +1 -1
  325. package/dist/core/tools/subagent-agents.d.ts.map +1 -1
  326. package/dist/core/tools/subagent-agents.js.map +1 -1
  327. package/dist/core/tools/subagent.d.ts.map +1 -1
  328. package/dist/core/tools/subagent.js.map +1 -1
  329. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  330. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  331. package/dist/core/tools/truncate.d.ts.map +1 -1
  332. package/dist/core/tools/truncate.js.map +1 -1
  333. package/dist/core/tools/websearch.d.ts.map +1 -1
  334. package/dist/core/tools/websearch.js.map +1 -1
  335. package/dist/core/tools/workspace-tool-host.d.ts +1 -0
  336. package/dist/core/tools/workspace-tool-host.d.ts.map +1 -1
  337. package/dist/core/tools/workspace-tool-host.js +36 -22
  338. package/dist/core/tools/workspace-tool-host.js.map +1 -1
  339. package/dist/core/tools/write.d.ts.map +1 -1
  340. package/dist/core/tools/write.js +0 -1
  341. package/dist/core/tools/write.js.map +1 -1
  342. package/dist/core/workspace-identity.d.ts.map +1 -1
  343. package/dist/daemon/activity-budget.d.ts.map +1 -1
  344. package/dist/daemon/activity-budget.js +2 -3
  345. package/dist/daemon/activity-budget.js.map +1 -1
  346. package/dist/daemon/command.d.ts.map +1 -1
  347. package/dist/daemon/command.js.map +1 -1
  348. package/dist/daemon/config.d.ts +2 -0
  349. package/dist/daemon/config.d.ts.map +1 -1
  350. package/dist/daemon/config.js +4 -0
  351. package/dist/daemon/config.js.map +1 -1
  352. package/dist/daemon/help.d.ts.map +1 -1
  353. package/dist/daemon/help.js +4 -3
  354. package/dist/daemon/help.js.map +1 -1
  355. package/dist/daemon/lsp-config.d.ts.map +1 -1
  356. package/dist/daemon/lsp-config.js.map +1 -1
  357. package/dist/daemon/outbound-budget.d.ts.map +1 -1
  358. package/dist/daemon/outbound-budget.js +2 -4
  359. package/dist/daemon/outbound-budget.js.map +1 -1
  360. package/dist/daemon/security.d.ts.map +1 -1
  361. package/dist/daemon/security.js.map +1 -1
  362. package/dist/daemon/server.d.ts.map +1 -1
  363. package/dist/daemon/server.js.map +1 -1
  364. package/dist/daemon/shared-connection.d.ts.map +1 -1
  365. package/dist/daemon/shared-connection.js +10 -15
  366. package/dist/daemon/shared-connection.js.map +1 -1
  367. package/dist/daemon/shared-revision.d.ts.map +1 -1
  368. package/dist/daemon/shared-revision.js +2 -1
  369. package/dist/daemon/shared-revision.js.map +1 -1
  370. package/dist/daemon/shared-roots.d.ts.map +1 -1
  371. package/dist/daemon/shared-roots.js +0 -1
  372. package/dist/daemon/shared-roots.js.map +1 -1
  373. package/dist/daemon/workspace-runtime.d.ts +2 -0
  374. package/dist/daemon/workspace-runtime.d.ts.map +1 -1
  375. package/dist/daemon/workspace-runtime.js +43 -15
  376. package/dist/daemon/workspace-runtime.js.map +1 -1
  377. package/dist/index.d.ts +1 -1
  378. package/dist/index.d.ts.map +1 -1
  379. package/dist/index.js.map +1 -1
  380. package/dist/main.d.ts.map +1 -1
  381. package/dist/main.js +8 -3
  382. package/dist/main.js.map +1 -1
  383. package/dist/migrations.d.ts.map +1 -1
  384. package/dist/migrations.js.map +1 -1
  385. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  386. package/dist/modes/interactive/components/assistant-message.js +3 -10
  387. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  388. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  389. package/dist/modes/interactive/components/bash-execution.js +4 -9
  390. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  391. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  392. package/dist/modes/interactive/components/bordered-loader.js +0 -3
  393. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  394. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  395. package/dist/modes/interactive/components/branch-summary-message.js +1 -3
  396. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  397. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  398. package/dist/modes/interactive/components/compaction-summary-message.js +1 -3
  399. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  400. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  401. package/dist/modes/interactive/components/config-selector.js +6 -16
  402. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  403. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  404. package/dist/modes/interactive/components/countdown-timer.js +0 -5
  405. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  406. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  407. package/dist/modes/interactive/components/custom-editor.js +1 -8
  408. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  409. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  410. package/dist/modes/interactive/components/custom-message.js +1 -6
  411. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  412. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  413. package/dist/modes/interactive/components/diff.js.map +1 -1
  414. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  415. package/dist/modes/interactive/components/dynamic-border.js +0 -1
  416. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  417. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  418. package/dist/modes/interactive/components/extension-editor.js +1 -7
  419. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  420. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  421. package/dist/modes/interactive/components/extension-input.js +2 -8
  422. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  423. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  424. package/dist/modes/interactive/components/extension-selector.js +1 -9
  425. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  426. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  427. package/dist/modes/interactive/components/footer.js +8 -4
  428. package/dist/modes/interactive/components/footer.js.map +1 -1
  429. package/dist/modes/interactive/components/hook-execution.d.ts.map +1 -1
  430. package/dist/modes/interactive/components/hook-execution.js +2 -5
  431. package/dist/modes/interactive/components/hook-execution.js.map +1 -1
  432. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  433. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  434. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  435. package/dist/modes/interactive/components/login-dialog.js +3 -9
  436. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  437. package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -1
  438. package/dist/modes/interactive/components/markdown-transform.js.map +1 -1
  439. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
  440. package/dist/modes/interactive/components/mermaid.js.map +1 -1
  441. package/dist/modes/interactive/components/message-card.d.ts.map +1 -1
  442. package/dist/modes/interactive/components/message-card.js +0 -1
  443. package/dist/modes/interactive/components/message-card.js.map +1 -1
  444. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  445. package/dist/modes/interactive/components/model-selector.js +13 -28
  446. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  447. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  448. package/dist/modes/interactive/components/oauth-selector.js +3 -12
  449. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  450. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  451. package/dist/modes/interactive/components/scoped-models-selector.js +9 -13
  452. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  453. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  454. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  455. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  456. package/dist/modes/interactive/components/session-selector.js +33 -58
  457. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  458. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  459. package/dist/modes/interactive/components/settings-selector.js +0 -4
  460. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  461. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  462. package/dist/modes/interactive/components/show-images-selector.js +0 -1
  463. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  464. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  465. package/dist/modes/interactive/components/skill-invocation-message.js +1 -3
  466. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  467. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  468. package/dist/modes/interactive/components/theme-selector.js +0 -2
  469. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  470. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  471. package/dist/modes/interactive/components/thinking-selector.js +0 -1
  472. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  473. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  474. package/dist/modes/interactive/components/tool-execution.js +9 -24
  475. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  476. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  477. package/dist/modes/interactive/components/tree-selector.js +18 -34
  478. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  479. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  480. package/dist/modes/interactive/components/user-message-selector.js +3 -6
  481. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  482. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  483. package/dist/modes/interactive/components/user-message.js +0 -4
  484. package/dist/modes/interactive/components/user-message.js.map +1 -1
  485. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  486. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  487. package/dist/modes/interactive/interactive-mode.d.ts +13 -0
  488. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  489. package/dist/modes/interactive/interactive-mode.js +162 -136
  490. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  491. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  492. package/dist/modes/interactive/theme/theme.js +0 -7
  493. package/dist/modes/interactive/theme/theme.js.map +1 -1
  494. package/dist/modes/json-event.d.ts.map +1 -1
  495. package/dist/modes/json-event.js.map +1 -1
  496. package/dist/modes/print-mode.d.ts.map +1 -1
  497. package/dist/modes/print-mode.js.map +1 -1
  498. package/dist/modes/rpc/jsonl.d.ts.map +1 -1
  499. package/dist/modes/rpc/jsonl.js.map +1 -1
  500. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  501. package/dist/modes/rpc/rpc-client.js +10 -11
  502. package/dist/modes/rpc/rpc-client.js.map +1 -1
  503. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  504. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  505. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  506. package/dist/package-manager-cli.d.ts.map +1 -1
  507. package/dist/package-manager-cli.js +33 -2
  508. package/dist/package-manager-cli.js.map +1 -1
  509. package/dist/utils/ansi.d.ts.map +1 -1
  510. package/dist/utils/ansi.js.map +1 -1
  511. package/dist/utils/binary-self-update.d.ts +25 -0
  512. package/dist/utils/binary-self-update.d.ts.map +1 -0
  513. package/dist/utils/binary-self-update.js +159 -0
  514. package/dist/utils/binary-self-update.js.map +1 -0
  515. package/dist/utils/changelog.d.ts.map +1 -1
  516. package/dist/utils/changelog.js.map +1 -1
  517. package/dist/utils/child-process.d.ts.map +1 -1
  518. package/dist/utils/child-process.js.map +1 -1
  519. package/dist/utils/clipboard-image.d.ts.map +1 -1
  520. package/dist/utils/clipboard-image.js.map +1 -1
  521. package/dist/utils/clipboard-native.d.ts.map +1 -1
  522. package/dist/utils/clipboard-native.js.map +1 -1
  523. package/dist/utils/clipboard.d.ts.map +1 -1
  524. package/dist/utils/clipboard.js.map +1 -1
  525. package/dist/utils/deprecation.d.ts.map +1 -1
  526. package/dist/utils/deprecation.js.map +1 -1
  527. package/dist/utils/directory-completions.d.ts +8 -0
  528. package/dist/utils/directory-completions.d.ts.map +1 -1
  529. package/dist/utils/directory-completions.js +42 -1
  530. package/dist/utils/directory-completions.js.map +1 -1
  531. package/dist/utils/exif-orientation.d.ts.map +1 -1
  532. package/dist/utils/exif-orientation.js.map +1 -1
  533. package/dist/utils/frontmatter.d.ts.map +1 -1
  534. package/dist/utils/frontmatter.js.map +1 -1
  535. package/dist/utils/fs-watch.d.ts.map +1 -1
  536. package/dist/utils/fs-watch.js.map +1 -1
  537. package/dist/utils/git.d.ts.map +1 -1
  538. package/dist/utils/git.js.map +1 -1
  539. package/dist/utils/grip-user-agent.d.ts.map +1 -1
  540. package/dist/utils/grip-user-agent.js.map +1 -1
  541. package/dist/utils/html.d.ts.map +1 -1
  542. package/dist/utils/html.js.map +1 -1
  543. package/dist/utils/image-convert.d.ts.map +1 -1
  544. package/dist/utils/image-convert.js.map +1 -1
  545. package/dist/utils/image-process.d.ts.map +1 -1
  546. package/dist/utils/image-process.js.map +1 -1
  547. package/dist/utils/image-resize-core.d.ts.map +1 -1
  548. package/dist/utils/image-resize-core.js.map +1 -1
  549. package/dist/utils/image-resize-worker.d.ts.map +1 -1
  550. package/dist/utils/image-resize-worker.js.map +1 -1
  551. package/dist/utils/image-resize.d.ts.map +1 -1
  552. package/dist/utils/image-resize.js.map +1 -1
  553. package/dist/utils/json.d.ts.map +1 -1
  554. package/dist/utils/json.js.map +1 -1
  555. package/dist/utils/mime.d.ts.map +1 -1
  556. package/dist/utils/mime.js.map +1 -1
  557. package/dist/utils/open-browser.d.ts.map +1 -1
  558. package/dist/utils/open-browser.js.map +1 -1
  559. package/dist/utils/paths.d.ts.map +1 -1
  560. package/dist/utils/paths.js.map +1 -1
  561. package/dist/utils/photon.d.ts.map +1 -1
  562. package/dist/utils/photon.js +10 -5
  563. package/dist/utils/photon.js.map +1 -1
  564. package/dist/utils/shell.d.ts.map +1 -1
  565. package/dist/utils/shell.js.map +1 -1
  566. package/dist/utils/sleep.d.ts.map +1 -1
  567. package/dist/utils/sleep.js.map +1 -1
  568. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  569. package/dist/utils/syntax-highlight.js +1 -1
  570. package/dist/utils/syntax-highlight.js.map +1 -1
  571. package/dist/utils/tools-manager.d.ts.map +1 -1
  572. package/dist/utils/tools-manager.js.map +1 -1
  573. package/dist/utils/version-check.d.ts.map +1 -1
  574. package/dist/utils/version-check.js.map +1 -1
  575. package/dist/utils/windows-self-update.d.ts.map +1 -1
  576. package/dist/utils/windows-self-update.js.map +1 -1
  577. package/docs/extensions.md +31 -1
  578. package/docs/sandbox.md +6 -0
  579. package/docs/sessions.md +1 -1
  580. package/docs/skills.md +4 -4
  581. package/docs/usage.md +2 -1
  582. package/examples/extensions/custom-provider-anthropic/package.json +2 -2
  583. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  584. package/examples/extensions/sandbox/package.json +2 -2
  585. package/examples/extensions/with-deps/package.json +1 -1
  586. package/npm-shrinkwrap.json +602 -834
  587. package/package.json +20 -21
@@ -1 +1 @@
1
- {"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport { getDocsPath, getExamplesPath, getReadmePath } from \"../config.ts\";\nimport { formatRulesForPrompt, type Rule } from \"./rules.ts\";\nimport { formatSkillsForPrompt, type Skill } from \"./skills.ts\";\n\n// grip-ignore noNearIdenticalDataStructures: System-prompt context requires loaded file content, while the interactive status fixture is display-only and permits path-only entries.\nexport interface SystemPromptContextFile {\n\tpath: string;\n\tcontent: string;\n}\n\nexport interface BuildSystemPromptOptions {\n\t/** Custom system prompt (replaces default). */\n\tcustomPrompt?: string;\n\t/** Tools to include in prompt. Default: [read, bash, edit, write] */\n\tselectedTools?: string[];\n\t/** Optional one-line tool snippets keyed by tool name. */\n\ttoolSnippets?: Record<string, string>;\n\t/** Additional guideline bullets appended to the default system prompt guidelines. */\n\tpromptGuidelines?: string[];\n\t/** Text to append to system prompt. */\n\tappendSystemPrompt?: string;\n\t/** Working directory. */\n\tcwd: string;\n\t/** Pre-loaded context files. */\n\tcontextFiles?: SystemPromptContextFile[];\n\t/** Pre-loaded skills. */\n\tskills?: Skill[];\n\t/** Pre-loaded rules. */\n\trules?: Rule[];\n}\n\ninterface SystemPromptFinalizationOptions {\n\tappendSystemPrompt?: string;\n\tpromptCwd: string;\n\tdate: string;\n\tcontextFiles: SystemPromptContextFile[];\n\tskills: Skill[];\n\trules: Rule[];\n\thasRead: boolean;\n}\n\nfunction getCurrentPromptDate(): string {\n\tconst now = new Date();\n\tconst year = now.getFullYear();\n\tconst month = String(now.getMonth() + 1).padStart(2, \"0\");\n\tconst day = String(now.getDate()).padStart(2, \"0\");\n\treturn `${year}-${month}-${day}`;\n}\n\nfunction appendUniqueGuideline(guidelines: string[], seen: Set<string>, guideline: string): void {\n\tif (seen.has(guideline)) return;\n\tseen.add(guideline);\n\tguidelines.push(guideline);\n}\n\nfunction formatPromptGuidelines(tools: string[], additionalGuidelines: string[] | undefined): string {\n\tconst guidelines: string[] = [];\n\tconst seen = new Set<string>();\n\tconst hasBash = tools.includes(\"bash\");\n\tconst hasGrep = tools.includes(\"grep\");\n\tconst hasFind = tools.includes(\"find\");\n\tconst hasLs = tools.includes(\"ls\");\n\tif (hasBash && !hasGrep && !hasFind && !hasLs) {\n\t\tappendUniqueGuideline(guidelines, seen, \"Use bash for file operations like ls, rg, find\");\n\t} else if (hasBash && (hasGrep || hasFind || hasLs)) {\n\t\tappendUniqueGuideline(\n\t\t\tguidelines,\n\t\t\tseen,\n\t\t\t\"Prefer grep/find/ls tools over bash for file exploration (faster, respects .gitignore)\",\n\t\t);\n\t}\n\tfor (const guideline of additionalGuidelines ?? []) {\n\t\tconst normalized = guideline.trim();\n\t\tif (normalized.length > 0) appendUniqueGuideline(guidelines, seen, normalized);\n\t}\n\tappendUniqueGuideline(guidelines, seen, \"Be concise in your responses\");\n\tappendUniqueGuideline(guidelines, seen, \"Show file paths clearly when working with files\");\n\treturn guidelines.map((guideline) => `- ${guideline}`).join(\"\\n\");\n}\n\nfunction formatAvailableTools(tools: string[], toolSnippets: Record<string, string> | undefined): string {\n\tconst visibleTools = tools.filter((name) => !!toolSnippets?.[name]);\n\treturn visibleTools.length > 0\n\t\t? visibleTools.map((name) => `- ${name}: ${toolSnippets![name]}`).join(\"\\n\")\n\t\t: \"(none)\";\n}\n\nfunction buildOrchestrationSection(hasSubagent: boolean): string {\n\tif (!hasSubagent) return \"\";\n\treturn `\n\t\t\t## Orchestration\n\nYou are the primary agent and final decision-maker. Use subagents as isolated workers for focused investigation, implementation alternatives, and independent review when delegation improves speed or confidence.\n\nGive each subagent a precise task and expected response format. Treat its output as evidence, not authority: reconcile conflicting findings, verify important claims against source or tests, and integrate the final result yourself.\n\nWork directly when delegation would cost more than completing the task. Do not delegate responsibility for the final answer.\n\t\t `.trim();\n}\n\nfunction buildDefaultSystemPrompt(options: BuildSystemPromptOptions, tools: string[]): string {\n\tconst toolsList = formatAvailableTools(tools, options.toolSnippets);\n\tconst guidelines = formatPromptGuidelines(tools, options.promptGuidelines);\n\tconst orchestrationSection = buildOrchestrationSection(tools.includes(\"subagent\"));\n\tconst stateCompressionSection = tools.includes(\"compress_context\")\n\t\t? `## State compression\nConsider compress_context at concrete checkpoints: when the user switches tasks, an investigation has yielded stable findings, an implementation slice is complete, or validation has finished and its raw logs are no longer needed. If older tool output or intermediate reasoning can be replaced by a concise account of decisions and current state, compress before starting the next slice; do not wait for a context percentage or an explicit request. Keep the active work and details needed for the next step intact. Do not compress a trivial exchange or interrupt an ongoing investigation, edit, or test.\n\nThe primary agent does not receive a context-utilization percentage. A background detector may send an advisory with an urgency score; treat it as a cue to evaluate the next safe checkpoint, not an instruction to compress immediately.\n\nYou receive model-only context metadata after user messages and completed tool-call batches, with session entry IDs but no utilization estimate. Use a user or assistant tool-call entry ID as a compression cut point; tool-result IDs are for lookup, not cuts. Do not repeat this metadata to the user.\n\nTurn batches of reads, searches, builds, and tests into concise state: findings and decisions, changed files, what passed or failed (including relevant errors), unresolved issues, and concrete next steps. Preserve important user instructions and constraints. Omit redundant tool output rather than carrying it forward.\n\nChoose a cut point from the entry IDs already visible in context metadata. Pass startEntryId and a summary to replace through the current tail, or add inclusive endEntryId to replace an older bounded range while retaining later messages. Never split a tool call from its results. Detector-suggested IDs are advisory; verify the range yourself before acting. Do not send a list of IDs. Call compress_context alone, not alongside other tools. session_search defaults to current model context; scope: branch/all retrieves historical entries for reference, not necessarily valid compression cut points.`\n\t\t: \"\";\n\tconst readmePath = getReadmePath();\n\tconst docsPath = getDocsPath();\n\tconst examplesPath = getExamplesPath();\n\treturn `You are an expert coding assistant operating inside grip, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.\nAvailable tools:\n${toolsList}\n\nIn addition to the tools above, you may have access to other custom tools depending on the project.\n${orchestrationSection ? `\\n${orchestrationSection}\\n` : \"\"}${stateCompressionSection ? `\\n${stateCompressionSection}\\n` : \"\"}\nGuidelines:\n${guidelines}\n\nGrip documentation (read only when the user asks about grip itself, its SDK, extensions, themes, skills, or TUI):\n- Main documentation: ${readmePath}\n- Additional docs: ${docsPath}\n- Examples: ${examplesPath} (extensions, custom tools, SDK)\n- When reading grip docs or examples, resolve docs/... under Additional docs and examples/... under Examples, not the current working directory\n- When asked about: extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), type TUI components (docs/tui.md), keybindings (docs/keybindings.md), SDK integrations (docs/sdk.md), custom providers (docs/custom-provider.md), adding models (docs/models.md), grip packages (docs/packages.md)\n- When working on grip topics, read the docs and examples, and follow .md cross-references before implementing\n- Always read grip .md files completely and follow links to related docs (e.g., tui.md for TUI API details)`;\n}\n\nfunction finalizeSystemPrompt(prompt: string, options: SystemPromptFinalizationOptions): string {\n\tif (options.appendSystemPrompt) prompt += `\\n\\n${options.appendSystemPrompt}`;\n\tif (options.contextFiles.length > 0) {\n\t\tprompt += \"\\n\\n<project_context>\\n\\n\";\n\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\tfor (const { path, content } of options.contextFiles) {\n\t\t\tprompt += `<project_instructions path=\"${path}\">\\n${content}\\n</project_instructions>\\n\\n`;\n\t\t}\n\t\tprompt += \"</project_context>\\n\";\n\t}\n\tif (options.hasRead && options.skills.length > 0) prompt += formatSkillsForPrompt(options.skills);\n\tif (options.hasRead && options.rules.length > 0) prompt += formatRulesForPrompt(options.rules);\n\tprompt += `\\nCurrent date: ${options.date}`;\n\tprompt += `\\nCurrent working directory: ${options.promptCwd}`;\n\treturn prompt;\n}\n\n/** Build the system prompt with tools, guidelines, and context */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions): string {\n\tconst tools = options.selectedTools || [\"read\", \"bash\", \"edit\", \"write\"];\n\tconst basePrompt = options.customPrompt || buildDefaultSystemPrompt(options, tools);\n\treturn finalizeSystemPrompt(basePrompt, {\n\t\tappendSystemPrompt: options.appendSystemPrompt,\n\t\tpromptCwd: options.cwd.replace(/\\\\/g, \"/\"),\n\t\tdate: getCurrentPromptDate(),\n\t\tcontextFiles: options.contextFiles ?? [],\n\t\tskills: options.skills ?? [],\n\t\trules: options.rules ?? [],\n\t\thasRead: !options.selectedTools || tools.includes(\"read\"),\n\t});\n}\n"]}
1
+ {"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport { getDocsPath, getExamplesPath, getReadmePath } from \"../config.ts\";\nimport { formatRulesForPrompt, type Rule } from \"./rules.ts\";\nimport { formatSkillsForPrompt, type Skill } from \"./skills.ts\";\n\n// grip-ignore noNearIdenticalDataStructures: System-prompt context requires loaded file content, while the interactive status fixture is display-only and permits path-only entries.\nexport interface SystemPromptContextFile {\n\tpath: string;\n\tcontent: string;\n}\n\nexport interface BuildSystemPromptOptions {\n\t/** Custom system prompt (replaces default). */\n\tcustomPrompt?: string;\n\t/** Tools to include in prompt. Default: [read, bash, edit, write, load_skill] */\n\tselectedTools?: string[];\n\t/** Optional one-line tool snippets keyed by tool name. */\n\ttoolSnippets?: Record<string, string>;\n\t/** Additional guideline bullets appended to the default system prompt guidelines. */\n\tpromptGuidelines?: string[];\n\t/** Text to append to system prompt. */\n\tappendSystemPrompt?: string;\n\t/** Working directory. */\n\tcwd: string;\n\t/** Pre-loaded context files. */\n\tcontextFiles?: SystemPromptContextFile[];\n\t/** Pre-loaded skills. */\n\tskills?: Skill[];\n\t/** Pre-loaded rules. */\n\trules?: Rule[];\n}\n\ninterface SystemPromptFinalizationOptions {\n\tappendSystemPrompt?: string;\n\tpromptCwd: string;\n\tdate: string;\n\tcontextFiles: SystemPromptContextFile[];\n\tskills: Skill[];\n\trules: Rule[];\n\thasRead: boolean;\n\thasLoadSkill: boolean;\n}\n\nfunction getCurrentPromptDate(): string {\n\tconst now = new Date();\n\tconst year = now.getFullYear();\n\tconst month = String(now.getMonth() + 1).padStart(2, \"0\");\n\tconst day = String(now.getDate()).padStart(2, \"0\");\n\treturn `${year}-${month}-${day}`;\n}\n\nfunction appendUniqueGuideline(guidelines: string[], seen: Set<string>, guideline: string): void {\n\tif (seen.has(guideline)) return;\n\tseen.add(guideline);\n\tguidelines.push(guideline);\n}\n\nfunction formatPromptGuidelines(tools: string[], additionalGuidelines: string[] | undefined): string {\n\tconst guidelines: string[] = [];\n\tconst seen = new Set<string>();\n\tconst hasBash = tools.includes(\"bash\");\n\tconst hasGrep = tools.includes(\"grep\");\n\tconst hasFind = tools.includes(\"find\");\n\tconst hasLs = tools.includes(\"ls\");\n\tif (hasBash && !hasGrep && !hasFind && !hasLs) {\n\t\tappendUniqueGuideline(guidelines, seen, \"Use bash for file operations like ls, rg, find\");\n\t} else if (hasBash && (hasGrep || hasFind || hasLs)) {\n\t\tappendUniqueGuideline(\n\t\t\tguidelines,\n\t\t\tseen,\n\t\t\t\"Prefer grep/find/ls tools over bash for file exploration (faster, respects .gitignore)\",\n\t\t);\n\t}\n\tfor (const guideline of additionalGuidelines ?? []) {\n\t\tconst normalized = guideline.trim();\n\t\tif (normalized.length > 0) appendUniqueGuideline(guidelines, seen, normalized);\n\t}\n\tappendUniqueGuideline(guidelines, seen, \"Be concise in your responses\");\n\tappendUniqueGuideline(guidelines, seen, \"Show file paths clearly when working with files\");\n\treturn guidelines.map((guideline) => `- ${guideline}`).join(\"\\n\");\n}\n\nfunction formatAvailableTools(tools: string[], toolSnippets: Record<string, string> | undefined): string {\n\tconst visibleTools = tools.filter((name) => !!toolSnippets?.[name]);\n\treturn visibleTools.length > 0\n\t\t? visibleTools.map((name) => `- ${name}: ${toolSnippets![name]}`).join(\"\\n\")\n\t\t: \"(none)\";\n}\n\nfunction buildOrchestrationSection(hasSubagent: boolean): string {\n\tif (!hasSubagent) return \"\";\n\treturn `\n\t\t\t## Orchestration\n\nYou are the primary agent and final decision-maker. Use subagents as isolated workers for focused investigation, implementation alternatives, and independent review when delegation improves speed or confidence.\n\nGive each subagent a precise task and expected response format. Treat its output as evidence, not authority: reconcile conflicting findings, verify important claims against source or tests, and integrate the final result yourself.\n\nWork directly when delegation would cost more than completing the task. Do not delegate responsibility for the final answer.\n\t\t `.trim();\n}\n\nfunction buildDefaultSystemPrompt(options: BuildSystemPromptOptions, tools: string[]): string {\n\tconst toolsList = formatAvailableTools(tools, options.toolSnippets);\n\tconst guidelines = formatPromptGuidelines(tools, options.promptGuidelines);\n\tconst orchestrationSection = buildOrchestrationSection(tools.includes(\"subagent\"));\n\tconst stateCompressionSection = tools.includes(\"compress_context\")\n\t\t? `## State compression\nConsider compress_context at concrete checkpoints: when the user switches tasks, an investigation has yielded stable findings, an implementation slice is complete, or validation has finished and its raw logs are no longer needed. If older tool output or intermediate reasoning can be replaced by a concise account of decisions and current state, compress before starting the next slice; do not wait for a context percentage or an explicit request. Keep the active work and details needed for the next step intact. Do not compress a trivial exchange or interrupt an ongoing investigation, edit, or test.\n\nThe primary agent does not receive a context-utilization percentage. A background detector may send an advisory with an urgency score; treat it as a cue to evaluate the next safe checkpoint, not an instruction to compress immediately.\n\nYou receive model-only context metadata after user messages and completed tool-call batches, with session entry IDs but no utilization estimate. Use a user or assistant tool-call entry ID as a compression cut point; tool-result IDs are for lookup, not cuts. Do not repeat this metadata to the user.\n\nTurn batches of reads, searches, builds, and tests into concise state: findings and decisions, changed files, what passed or failed (including relevant errors), unresolved issues, and concrete next steps. Preserve important user instructions and constraints. Omit redundant tool output rather than carrying it forward.\n\nChoose a cut point from the entry IDs already visible in context metadata. Pass startEntryId and a summary to replace through the current tail, or add inclusive endEntryId to replace an older bounded range while retaining later messages. Never split a tool call from its results. Detector-suggested IDs are advisory; verify the range yourself before acting. Do not send a list of IDs. Call compress_context alone, not alongside other tools. session_search defaults to current model context; scope: branch/all retrieves historical entries for reference, not necessarily valid compression cut points.`\n\t\t: \"\";\n\tconst readmePath = getReadmePath();\n\tconst docsPath = getDocsPath();\n\tconst examplesPath = getExamplesPath();\n\treturn `You are an expert coding assistant operating inside grip, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.\nAvailable tools:\n${toolsList}\n\nIn addition to the tools above, you may have access to other custom tools depending on the project.\n${orchestrationSection ? `\\n${orchestrationSection}\\n` : \"\"}${stateCompressionSection ? `\\n${stateCompressionSection}\\n` : \"\"}\nGuidelines:\n${guidelines}\n\nGrip documentation (read only when the user asks about grip itself, its SDK, extensions, themes, skills, or TUI):\n- Main documentation: ${readmePath}\n- Additional docs: ${docsPath}\n- Examples: ${examplesPath} (extensions, custom tools, SDK)\n- When reading grip docs or examples, resolve docs/... under Additional docs and examples/... under Examples, not the current working directory\n- When asked about: extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), type TUI components (docs/tui.md), keybindings (docs/keybindings.md), SDK integrations (docs/sdk.md), custom providers (docs/custom-provider.md), adding models (docs/models.md), grip packages (docs/packages.md)\n- When working on grip topics, read the docs and examples, and follow .md cross-references before implementing\n- Always read grip .md files completely and follow links to related docs (e.g., tui.md for TUI API details)`;\n}\n\nfunction finalizeSystemPrompt(prompt: string, options: SystemPromptFinalizationOptions): string {\n\tif (options.appendSystemPrompt) prompt += `\\n\\n${options.appendSystemPrompt}`;\n\tif (options.contextFiles.length > 0) {\n\t\tprompt += \"\\n\\n<project_context>\\n\\n\";\n\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\tfor (const { path, content } of options.contextFiles) {\n\t\t\tprompt += `<project_instructions path=\"${path}\">\\n${content}\\n</project_instructions>\\n\\n`;\n\t\t}\n\t\tprompt += \"</project_context>\\n\";\n\t}\n\tif (options.hasLoadSkill && options.skills.length > 0) prompt += formatSkillsForPrompt(options.skills);\n\tif (options.hasRead && options.rules.length > 0) prompt += formatRulesForPrompt(options.rules);\n\tprompt += `\\nCurrent date: ${options.date}`;\n\tprompt += `\\nCurrent working directory: ${options.promptCwd}`;\n\treturn prompt;\n}\n\n/** Build the system prompt with tools, guidelines, and context */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions): string {\n\tconst tools = options.selectedTools || [\"read\", \"bash\", \"edit\", \"write\", \"load_skill\"];\n\tconst basePrompt = options.customPrompt || buildDefaultSystemPrompt(options, tools);\n\treturn finalizeSystemPrompt(basePrompt, {\n\t\tappendSystemPrompt: options.appendSystemPrompt,\n\t\tpromptCwd: options.cwd.replace(/\\\\/g, \"/\"),\n\t\tdate: getCurrentPromptDate(),\n\t\tcontextFiles: options.contextFiles ?? [],\n\t\tskills: options.skills ?? [],\n\t\trules: options.rules ?? [],\n\t\thasRead: !options.selectedTools || tools.includes(\"read\"),\n\t\thasLoadSkill: tools.includes(\"load_skill\"),\n\t});\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/core/telemetry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAO7D,wBAAgB,yBAAyB,CACxC,eAAe,EAAE,eAAe,EAChC,YAAY,GAAE,MAAM,GAAG,SAAsC,GAC3D,OAAO,CAET","sourcesContent":["import type { SettingsManager } from \"./settings-manager.ts\";\n\nfunction isTruthyEnvFlag(value: string | undefined): boolean {\n\tif (!value) return false;\n\treturn value === \"1\" || value.toLowerCase() === \"true\" || value.toLowerCase() === \"yes\";\n}\n\nexport function isInstallTelemetryEnabled(\n\tsettingsManager: SettingsManager,\n\ttelemetryEnv: string | undefined = process.env.GRIP_TELEMETRY,\n): boolean {\n\treturn telemetryEnv !== undefined ? isTruthyEnvFlag(telemetryEnv) : settingsManager.getEnableInstallTelemetry();\n}\n"]}
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/core/telemetry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAO7D,wBAAgB,yBAAyB,CACxC,eAAe,EAAE,eAAe,EAChC,YAAY,GAAE,MAAM,GAAG,SAAsC,GAC3D,OAAO,CAET"}
@@ -1 +1 @@
1
- {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/core/telemetry.ts"],"names":[],"mappings":"AAEA,SAAS,eAAe,CAAC,KAAyB,EAAW;IAC5D,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,OAAO,KAAK,KAAK,GAAG,IAAI,KAAK,CAAC,WAAW,EAAE,KAAK,MAAM,IAAI,KAAK,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC;AAAA,CACxF;AAED,MAAM,UAAU,yBAAyB,CACxC,eAAgC,EAChC,YAAY,GAAuB,OAAO,CAAC,GAAG,CAAC,cAAc,EACnD;IACV,OAAO,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,yBAAyB,EAAE,CAAC;AAAA,CAChH","sourcesContent":["import type { SettingsManager } from \"./settings-manager.ts\";\n\nfunction isTruthyEnvFlag(value: string | undefined): boolean {\n\tif (!value) return false;\n\treturn value === \"1\" || value.toLowerCase() === \"true\" || value.toLowerCase() === \"yes\";\n}\n\nexport function isInstallTelemetryEnabled(\n\tsettingsManager: SettingsManager,\n\ttelemetryEnv: string | undefined = process.env.GRIP_TELEMETRY,\n): boolean {\n\treturn telemetryEnv !== undefined ? isTruthyEnvFlag(telemetryEnv) : settingsManager.getEnableInstallTelemetry();\n}\n"]}
1
+ {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/core/telemetry.ts"],"names":[],"mappings":"AAEA,SAAS,eAAe,CAAC,KAAyB;IACjD,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,OAAO,KAAK,KAAK,GAAG,IAAI,KAAK,CAAC,WAAW,EAAE,KAAK,MAAM,IAAI,KAAK,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC;AACzF,CAAC;AAED,MAAM,UAAU,yBAAyB,CACxC,eAAgC,EAChC,YAAY,GAAuB,OAAO,CAAC,GAAG,CAAC,cAAc;IAE7D,OAAO,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,yBAAyB,EAAE,CAAC;AACjH,CAAC","sourcesContent":["import type { SettingsManager } from \"./settings-manager.ts\";\n\nfunction isTruthyEnvFlag(value: string | undefined): boolean {\n\tif (!value) return false;\n\treturn value === \"1\" || value.toLowerCase() === \"true\" || value.toLowerCase() === \"yes\";\n}\n\nexport function isInstallTelemetryEnabled(\n\tsettingsManager: SettingsManager,\n\ttelemetryEnv: string | undefined = process.env.GRIP_TELEMETRY,\n): boolean {\n\treturn telemetryEnv !== undefined ? isTruthyEnvFlag(telemetryEnv) : settingsManager.getEnableInstallTelemetry();\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"timings.d.ts","sourceRoot":"","sources":["../../src/core/timings.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,KAAK,WAAW,GAAG,MAAM,GAAG,YAAY,CAAC;AAIzC,wBAAgB,YAAY,CAAC,SAAS,GAAE,WAAoB,GAAG,IAAI,CAGlE;AAED,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,GAAE,WAAoB,GAAG,IAAI,CAWzE;AAaD,wBAAgB,YAAY,IAAI,IAAI,CAKnC","sourcesContent":["/**\n * Central timing instrumentation for startup profiling.\n * Enable with GRIP_TIMING=1 environment variable.\n */\n\nconst ENABLED = process.env.GRIP_TIMING === \"1\";\ninterface TimingMeasurement {\n\tlabel: string;\n\tms: number;\n}\n\ninterface TimingNamespace {\n\ttimings: TimingMeasurement[];\n\tlastTime: number;\n}\n\ntype TimingLabel = \"main\" | \"extensions\";\n\nconst timingNamespaces = new Map<TimingLabel, TimingNamespace>();\n\nexport function resetTimings(namespace: TimingLabel = \"main\"): void {\n\tif (!ENABLED) return;\n\ttimingNamespaces.set(namespace, { timings: [], lastTime: Date.now() });\n}\n\nexport function time(label: string, namespace: TimingLabel = \"main\"): void {\n\tif (!ENABLED) return;\n\tconst now = Date.now();\n\n\tif (!timingNamespaces.has(namespace)) {\n\t\tresetTimings(namespace);\n\t}\n\n\tconst timingNamespace = timingNamespaces.get(namespace)!;\n\ttimingNamespace.timings.push({ label, ms: now - timingNamespace.lastTime });\n\ttimingNamespace.lastTime = now;\n}\n\nfunction printTimingGroup(title: string, timings: TimingMeasurement[]): void {\n\tconst printableTimings = timings.filter((timing) => timing.ms >= 0);\n\tif (printableTimings.length === 0) return;\n\tconsole.error(`\\n--- ${title} ---`);\n\tfor (const t of printableTimings) {\n\t\tconsole.error(` ${t.label}: ${t.ms}ms`);\n\t}\n\tconsole.error(` TOTAL: ${printableTimings.reduce((a, b) => a + b.ms, 0)}ms`);\n\tconsole.error(`${\"-\".repeat(title.length + 8)}\\n`);\n}\n\nexport function printTimings(): void {\n\tif (!ENABLED) return;\n\tfor (const [namespace, timingNamespace] of timingNamespaces) {\n\t\tprintTimingGroup(`Startup Timings: ${namespace}`, timingNamespace.timings);\n\t}\n}\n"]}
1
+ {"version":3,"file":"timings.d.ts","sourceRoot":"","sources":["../../src/core/timings.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,KAAK,WAAW,GAAG,MAAM,GAAG,YAAY,CAAC;AAIzC,wBAAgB,YAAY,CAAC,SAAS,GAAE,WAAoB,GAAG,IAAI,CAGlE;AAED,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,GAAE,WAAoB,GAAG,IAAI,CAWzE;AAaD,wBAAgB,YAAY,IAAI,IAAI,CAKnC"}
@@ -1 +1 @@
1
- {"version":3,"file":"timings.js","sourceRoot":"","sources":["../../src/core/timings.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,GAAG,CAAC;AAahD,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAgC,CAAC;AAEjE,MAAM,UAAU,YAAY,CAAC,SAAS,GAAgB,MAAM,EAAQ;IACnE,IAAI,CAAC,OAAO;QAAE,OAAO;IACrB,gBAAgB,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AAAA,CACvE;AAED,MAAM,UAAU,IAAI,CAAC,KAAa,EAAE,SAAS,GAAgB,MAAM,EAAQ;IAC1E,IAAI,CAAC,OAAO;QAAE,OAAO;IACrB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEvB,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QACtC,YAAY,CAAC,SAAS,CAAC,CAAC;IACzB,CAAC;IAED,MAAM,eAAe,GAAG,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAE,CAAC;IACzD,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,GAAG,eAAe,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC5E,eAAe,CAAC,QAAQ,GAAG,GAAG,CAAC;AAAA,CAC/B;AAED,SAAS,gBAAgB,CAAC,KAAa,EAAE,OAA4B,EAAQ;IAC5E,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IACpE,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC1C,OAAO,CAAC,KAAK,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC;IACpC,KAAK,MAAM,CAAC,IAAI,gBAAgB,EAAE,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,YAAY,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAC9E,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;AAAA,CACnD;AAED,MAAM,UAAU,YAAY,GAAS;IACpC,IAAI,CAAC,OAAO;QAAE,OAAO;IACrB,KAAK,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,IAAI,gBAAgB,EAAE,CAAC;QAC7D,gBAAgB,CAAC,oBAAoB,SAAS,EAAE,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IAC5E,CAAC;AAAA,CACD","sourcesContent":["/**\n * Central timing instrumentation for startup profiling.\n * Enable with GRIP_TIMING=1 environment variable.\n */\n\nconst ENABLED = process.env.GRIP_TIMING === \"1\";\ninterface TimingMeasurement {\n\tlabel: string;\n\tms: number;\n}\n\ninterface TimingNamespace {\n\ttimings: TimingMeasurement[];\n\tlastTime: number;\n}\n\ntype TimingLabel = \"main\" | \"extensions\";\n\nconst timingNamespaces = new Map<TimingLabel, TimingNamespace>();\n\nexport function resetTimings(namespace: TimingLabel = \"main\"): void {\n\tif (!ENABLED) return;\n\ttimingNamespaces.set(namespace, { timings: [], lastTime: Date.now() });\n}\n\nexport function time(label: string, namespace: TimingLabel = \"main\"): void {\n\tif (!ENABLED) return;\n\tconst now = Date.now();\n\n\tif (!timingNamespaces.has(namespace)) {\n\t\tresetTimings(namespace);\n\t}\n\n\tconst timingNamespace = timingNamespaces.get(namespace)!;\n\ttimingNamespace.timings.push({ label, ms: now - timingNamespace.lastTime });\n\ttimingNamespace.lastTime = now;\n}\n\nfunction printTimingGroup(title: string, timings: TimingMeasurement[]): void {\n\tconst printableTimings = timings.filter((timing) => timing.ms >= 0);\n\tif (printableTimings.length === 0) return;\n\tconsole.error(`\\n--- ${title} ---`);\n\tfor (const t of printableTimings) {\n\t\tconsole.error(` ${t.label}: ${t.ms}ms`);\n\t}\n\tconsole.error(` TOTAL: ${printableTimings.reduce((a, b) => a + b.ms, 0)}ms`);\n\tconsole.error(`${\"-\".repeat(title.length + 8)}\\n`);\n}\n\nexport function printTimings(): void {\n\tif (!ENABLED) return;\n\tfor (const [namespace, timingNamespace] of timingNamespaces) {\n\t\tprintTimingGroup(`Startup Timings: ${namespace}`, timingNamespace.timings);\n\t}\n}\n"]}
1
+ {"version":3,"file":"timings.js","sourceRoot":"","sources":["../../src/core/timings.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,GAAG,CAAC;AAahD,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAgC,CAAC;AAEjE,MAAM,UAAU,YAAY,CAAC,SAAS,GAAgB,MAAM;IAC3D,IAAI,CAAC,OAAO;QAAE,OAAO;IACrB,gBAAgB,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,KAAa,EAAE,SAAS,GAAgB,MAAM;IAClE,IAAI,CAAC,OAAO;QAAE,OAAO;IACrB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEvB,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QACtC,YAAY,CAAC,SAAS,CAAC,CAAC;IACzB,CAAC;IAED,MAAM,eAAe,GAAG,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAE,CAAC;IACzD,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,GAAG,eAAe,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC5E,eAAe,CAAC,QAAQ,GAAG,GAAG,CAAC;AAChC,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAa,EAAE,OAA4B;IACpE,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IACpE,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC1C,OAAO,CAAC,KAAK,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC;IACpC,KAAK,MAAM,CAAC,IAAI,gBAAgB,EAAE,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,YAAY,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAC9E,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,YAAY;IAC3B,IAAI,CAAC,OAAO;QAAE,OAAO;IACrB,KAAK,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,IAAI,gBAAgB,EAAE,CAAC;QAC7D,gBAAgB,CAAC,oBAAoB,SAAS,EAAE,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IAC5E,CAAC;AACF,CAAC","sourcesContent":["/**\n * Central timing instrumentation for startup profiling.\n * Enable with GRIP_TIMING=1 environment variable.\n */\n\nconst ENABLED = process.env.GRIP_TIMING === \"1\";\ninterface TimingMeasurement {\n\tlabel: string;\n\tms: number;\n}\n\ninterface TimingNamespace {\n\ttimings: TimingMeasurement[];\n\tlastTime: number;\n}\n\ntype TimingLabel = \"main\" | \"extensions\";\n\nconst timingNamespaces = new Map<TimingLabel, TimingNamespace>();\n\nexport function resetTimings(namespace: TimingLabel = \"main\"): void {\n\tif (!ENABLED) return;\n\ttimingNamespaces.set(namespace, { timings: [], lastTime: Date.now() });\n}\n\nexport function time(label: string, namespace: TimingLabel = \"main\"): void {\n\tif (!ENABLED) return;\n\tconst now = Date.now();\n\n\tif (!timingNamespaces.has(namespace)) {\n\t\tresetTimings(namespace);\n\t}\n\n\tconst timingNamespace = timingNamespaces.get(namespace)!;\n\ttimingNamespace.timings.push({ label, ms: now - timingNamespace.lastTime });\n\ttimingNamespace.lastTime = now;\n}\n\nfunction printTimingGroup(title: string, timings: TimingMeasurement[]): void {\n\tconst printableTimings = timings.filter((timing) => timing.ms >= 0);\n\tif (printableTimings.length === 0) return;\n\tconsole.error(`\\n--- ${title} ---`);\n\tfor (const t of printableTimings) {\n\t\tconsole.error(` ${t.label}: ${t.ms}ms`);\n\t}\n\tconsole.error(` TOTAL: ${printableTimings.reduce((a, b) => a + b.ms, 0)}ms`);\n\tconsole.error(`${\"-\".repeat(title.length + 8)}\\n`);\n}\n\nexport function printTimings(): void {\n\tif (!ENABLED) return;\n\tfor (const [namespace, timingNamespace] of timingNamespaces) {\n\t\tprintTimingGroup(`Startup Timings: ${namespace}`, timingNamespace.timings);\n\t}\n}\n"]}
@@ -6,6 +6,7 @@ import { type TruncationResult } from "./truncate.ts";
6
6
  declare const bashSchema: Type.TObject<{
7
7
  command: Type.TString;
8
8
  timeout: Type.TOptional<Type.TNumber>;
9
+ output_mode: Type.TOptional<Type.TUnion<[Type.TLiteral<"always">, Type.TLiteral<"on_fail">, Type.TLiteral<"never">]>>;
9
10
  }>;
10
11
  export type BashToolInput = Static<typeof bashSchema>;
11
12
  export interface BashToolDetails {
@@ -1 +1 @@
1
- {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../../src/core/tools/bash.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAmB,MAAM,4BAA4B,CAAC;AAE7E,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAK5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAA2B,MAAM,wBAAwB,CAAC;AACxG,OAAO,EAEN,KAAK,sBAAsB,EAG3B,KAAK,cAAc,EACnB,MAAM,iBAAiB,CAAC;AAIzB,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;;;;;GAKG;AACH,MAAM,WAAW,0BAA0B;IAC1C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,yBAAyB,CAAC,OAAO,CAAC,EAAE,0BAA0B,GAAG,cAAc,CAE9F;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;AAE5E,MAAM,MAAM,sBAAsB,GAAG,sBAAsB,CAAC;AAE5D,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,gBAAgB,GAAG,SAAS,GAAG,sBAAsB,CAanG;AAgBD,MAAM,WAAW,eAAe;IAC/B,mFAAmF;IACnF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0FAA0F;IAC1F,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,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;AAoKF,MAAM,MAAM,kBAAkB,GAAG,cAAc,CAAC,OAAO,UAAU,EAAE,eAAe,GAAG,SAAS,EAAE,eAAe,CAAC,CAAC;AAEjH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,kBAAkB,CAiKlH;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAElH","sourcesContent":["import type { AgentTool, AgentToolResult } from \"@greppleai/grip-agent-core\";\nimport { Container, Text, truncateToWidth } from \"@greppleai/grip-tui\";\nimport { type Static, Type } from \"typebox\";\nimport { keyText } 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 { getShellEnv } from \"../../utils/shell.ts\";\nimport type { ExtensionContext, ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.ts\";\nimport {\n\tGRIP_SESSION_ENVIRONMENT_NAMES,\n\ttype GripSessionEnvironment,\n\tLocalToolOperations,\n\ttype ToolBackendInfo,\n\ttype ToolOperations,\n} from \"./operations.ts\";\nimport { OutputAccumulator, type OutputSnapshot } from \"./output-accumulator.ts\";\nimport { formatBackendIcon, 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 * Create tool operations using grip's built-in local shell execution backend.\n *\n * This is useful for extensions that intercept user_bash and still want grip's\n * standard local shell behavior while wrapping or rewriting commands.\n */\nexport interface LocalBashOperationsOptions {\n\tcwd?: string;\n\tshellPath?: string;\n}\n\nexport function createLocalBashOperations(options?: LocalBashOperationsOptions): ToolOperations {\n\treturn new LocalToolOperations(options?.cwd ?? process.cwd(), { shellPath: options?.shellPath });\n}\n\nexport interface BashSpawnContext {\n\tcommand: string;\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n}\n\nexport type BashSpawnHook = (context: BashSpawnContext) => BashSpawnContext;\n\nexport type BashSessionEnvironment = GripSessionEnvironment;\n\nexport function getBashSessionEnvironment(ctx: ExtensionContext | undefined): BashSessionEnvironment {\n\tif (!ctx?.session) return {};\n\tconst environment: BashSessionEnvironment = {\n\t\tGRIP_SESSION_ID: ctx.session.getSessionId(),\n\t};\n\tif (ctx.thinkingLevel) environment.GRIP_REASONING_LEVEL = ctx.thinkingLevel;\n\tconst sessionFile = ctx.session.getSessionReference();\n\tif (sessionFile) environment.GRIP_SESSION_FILE = sessionFile;\n\tif (ctx.model) {\n\t\tenvironment.GRIP_PROVIDER = ctx.model.provider;\n\t\tenvironment.GRIP_MODEL = ctx.model.id;\n\t}\n\treturn environment;\n}\n\nfunction resolveSpawnContext(\n\tcommand: string,\n\tcwd: string,\n\tspawnHook: BashSpawnHook | undefined,\n\texposeSessionEnvironment: boolean,\n\tctx: ExtensionContext | undefined,\n): BashSpawnContext {\n\tconst env = { ...getShellEnv() };\n\tfor (const name of GRIP_SESSION_ENVIRONMENT_NAMES) delete env[name];\n\tif (exposeSessionEnvironment) Object.assign(env, getBashSessionEnvironment(ctx));\n\tconst baseContext: BashSpawnContext = { command, cwd, env };\n\treturn spawnHook ? spawnHook(baseContext) : baseContext;\n}\n\nexport interface BashToolOptions {\n\t/** Command prefix prepended to every command (for example shell setup commands) */\n\tcommandPrefix?: string;\n\t/** Expose current grip session metadata as GRIP_* environment variables. Default: true */\n\texposeSessionEnvironment?: boolean;\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\treturn `${(ms / 1000).toFixed(1)}s`;\n}\n\nfunction formatBackendSuffix(backendInfo: ToolBackendInfo | undefined): string {\n\tif (!backendInfo) return \"\";\n\tif (backendInfo.type === \"local\") return theme.fg(\"muted\", ` [local ${backendInfo.cwd}]`);\n\treturn backendInfo.configured\n\t\t? theme.fg(\"muted\", ` [remote ${backendInfo.url}:${backendInfo.cwd}]`)\n\t\t: theme.fg(\"warning\", ` [remote not configured ${backendInfo.cwd}]`);\n}\n\nfunction formatBashCall(args: Partial<BashToolInput> | undefined, backendInfo?: ToolBackendInfo): string {\n\tconst command = str(args?.command);\n\tconst timeout = args?.timeout;\n\tconst timeoutSuffix = timeout ? theme.fg(\"muted\", ` (timeout ${timeout}s)`) : \"\";\n\tconst commandDisplay = command === null ? invalidArgText(theme) : command ? command : theme.fg(\"toolOutput\", \"...\");\n\treturn (\n\t\tformatBackendIcon(backendInfo, theme) +\n\t\ttheme.fg(\"toolTitle\", theme.bold(\"$ \")) +\n\t\ttheme.fg(\"accent\", theme.bold(commandDisplay)) +\n\t\ttimeoutSuffix\n\t);\n}\n\nfunction getBashDisplayOutput(\n\tresult: AgentToolResult<BashToolDetails | undefined>,\n\tshowImages: boolean,\n\tisPartial: boolean,\n): string {\n\tconst output = getTextOutput(result, showImages).trim();\n\tconst truncation = result.details?.truncation;\n\tconst fullOutputPath = result.details?.fullOutputPath;\n\tif (isPartial || !truncation?.truncated || !fullOutputPath || !output.endsWith(\"]\")) return output;\n\tconst footerStart = output.lastIndexOf(\"\\n\\n[\");\n\tif (footerStart === -1 || !output.slice(footerStart).includes(fullOutputPath)) return output;\n\treturn output.slice(0, footerStart).trimEnd();\n}\n\nfunction addBashOutput(\n\tcomponent: BashResultRenderComponent,\n\tstate: BashResultRenderState,\n\toutput: string,\n\toptions: ToolRenderResultOptions,\n): void {\n\tif (!output) return;\n\tconst styledOutput = output\n\t\t.split(\"\\n\")\n\t\t.map((line) => theme.fg(\"toolOutput\", line))\n\t\t.join(\"\\n\");\n\tif (options.expanded) {\n\t\tcomponent.addChild(new Text(`\\n${styledOutput}`, 0, 0));\n\t\treturn;\n\t}\n\tcomponent.addChild({\n\t\trender: (width: number) => {\n\t\t\tif (state.cachedLines === undefined || state.cachedWidth !== width) {\n\t\t\t\tconst preview = truncateToVisualLines(styledOutput, BASH_PREVIEW_LINES, width);\n\t\t\t\tstate.cachedLines = preview.visualLines;\n\t\t\t\tstate.cachedSkipped = preview.skippedCount;\n\t\t\t\tstate.cachedWidth = width;\n\t\t\t}\n\t\t\treturn [\"\", ...(state.cachedLines ?? [])];\n\t\t},\n\t\tinvalidate: () => {\n\t\t\tstate.cachedWidth = undefined;\n\t\t\tstate.cachedLines = undefined;\n\t\t\tstate.cachedSkipped = undefined;\n\t\t},\n\t});\n}\n\nfunction addBashOutputWarnings(\n\tcomponent: BashResultRenderComponent,\n\ttruncation: TruncationResult | undefined,\n\tfullOutputPath: string | undefined,\n): void {\n\tif (!truncation?.truncated && !fullOutputPath) return;\n\tconst warnings: string[] = [];\n\tif (fullOutputPath) warnings.push(`Full output: ${fullOutputPath}`);\n\tif (truncation?.truncated) {\n\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\twarnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`);\n\t\t} else {\n\t\t\twarnings.push(\n\t\t\t\t`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`,\n\t\t\t);\n\t\t}\n\t}\n\tcomponent.addChild(new Text(`\\n${theme.fg(\"warning\", `[${warnings.join(\". \")}]`)}`, 0, 0));\n}\n\nfunction rebuildBashResultRenderComponent(\n\tcomponent: BashResultRenderComponent,\n\tresult: AgentToolResult<BashToolDetails | undefined>,\n\toptions: ToolRenderResultOptions,\n\tisError: boolean,\n\tshowImages: boolean,\n\tstartedAt: number | undefined,\n\tendedAt: number | undefined,\n\tbackendInfo: ToolBackendInfo | undefined,\n): void {\n\tconst state = component.state;\n\tcomponent.clear();\n\tconst output = getBashDisplayOutput(result, showImages, options.isPartial);\n\taddBashOutput(component, state, output, options);\n\taddBashOutputWarnings(component, result.details?.truncation, result.details?.fullOutputPath);\n\tif (startedAt !== undefined) {\n\t\tconst label = options.isPartial ? \"Elapsed\" : \"Took\";\n\t\tconst endTime = endedAt ?? Date.now();\n\t\tcomponent.addChild(\n\t\t\tnew Text(\n\t\t\t\t`\\n${theme.fg(options.isPartial ? \"muted\" : isError ? \"error\" : \"success\", `${label} ${formatDuration(endTime - startedAt)}`)}${formatBackendSuffix(backendInfo)}`,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t),\n\t\t);\n\t}\n\tif (!options.expanded && output) {\n\t\tcomponent.addChild({\n\t\t\trender: (width) => {\n\t\t\t\tif (!state.cachedSkipped || width < 1) return [];\n\t\t\t\tconst expandKey = keyText(\"app.tools.expand\");\n\t\t\t\tconst hint =\n\t\t\t\t\ttheme.fg(\"warning\", `${state.cachedSkipped} lines hidden`) +\n\t\t\t\t\t(expandKey ? theme.fg(\"accent\", ` · ${expandKey} to expand`) : \"\");\n\t\t\t\treturn [\"\", truncateToWidth(hint, width, \"...\")];\n\t\t\t},\n\t\t\tinvalidate: () => {},\n\t\t});\n\t}\n}\n\nfunction appendBashStatus(text: string, status: string): string {\n\treturn `${text ? `${text}\\n\\n` : \"\"}${status}`;\n}\n\nfunction throwBashExecutionError(error: unknown, outputText: string): never {\n\tif (error instanceof Error && error.message === \"aborted\") {\n\t\tthrow new Error(appendBashStatus(outputText, \"Command aborted\"));\n\t}\n\tif (error instanceof Error && error.message.startsWith(\"timeout:\")) {\n\t\tconst timeoutSeconds = error.message.split(\":\")[1];\n\t\tthrow new Error(appendBashStatus(outputText, `Command timed out after ${timeoutSeconds} seconds`));\n\t}\n\tthrow error;\n}\n\nexport type BashToolDefinition = ToolDefinition<typeof bashSchema, BashToolDetails | undefined, BashRenderState>;\n\nexport function createBashToolDefinition(operations: ToolOperations, options?: BashToolOptions): BashToolDefinition {\n\tconst ops = operations;\n\tconst commandPrefix = options?.commandPrefix;\n\tconst exposeSessionEnvironment = options?.exposeSessionEnvironment ?? true;\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\tpromptGuidelines: exposeSessionEnvironment\n\t\t\t? [\"Inspect GRIP_* environment variables for current model and session details.\"]\n\t\t\t: undefined,\n\t\tparameters: bashSchema,\n\t\tasync execute(_toolCallId, { command, timeout }: BashToolInput, signal?: AbortSignal, onUpdate?, ctx?) {\n\t\t\tconst resolvedCommand = commandPrefix ? `${commandPrefix}\\n${command}` : command;\n\t\t\tconst spawnContext = resolveSpawnContext(resolvedCommand, ops.cwd, spawnHook, exposeSessionEnvironment, ctx);\n\t\t\tconst output = new OutputAccumulator({ tempFilePrefix: \"grip-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: OutputSnapshot, 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\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, {\n\t\t\t\t\t\tcwd: 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\tthrowBashExecutionError(err, text);\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(appendBashStatus(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, ops.getBackendInfo?.()));\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 as any,\n\t\t\t\toptions,\n\t\t\t\tcontext.isError,\n\t\t\t\tcontext.showImages,\n\t\t\t\tstate.startedAt,\n\t\t\t\tstate.endedAt,\n\t\t\t\tops.getBackendInfo?.(),\n\t\t\t);\n\t\t\tcomponent.invalidate();\n\t\t\treturn component;\n\t\t},\n\t};\n}\n\nexport function createBashTool(operations: ToolOperations, options?: BashToolOptions): AgentTool<typeof bashSchema> {\n\treturn wrapToolDefinition(createBashToolDefinition(operations, options));\n}\n"]}
1
+ {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../../src/core/tools/bash.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAmB,MAAM,4BAA4B,CAAC;AAE7E,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAK5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAA2B,MAAM,wBAAwB,CAAC;AACxG,OAAO,EAEN,KAAK,sBAAsB,EAG3B,KAAK,cAAc,EACnB,MAAM,iBAAiB,CAAC;AAIzB,OAAO,EAAoD,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAExG,QAAA,MAAM,UAAU;;;;EASd,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;;;;;GAKG;AACH,MAAM,WAAW,0BAA0B;IAC1C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,yBAAyB,CAAC,OAAO,CAAC,EAAE,0BAA0B,GAAG,cAAc,CAE9F;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;AAE5E,MAAM,MAAM,sBAAsB,GAAG,sBAAsB,CAAC;AAE5D,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,gBAAgB,GAAG,SAAS,GAAG,sBAAsB,CAanG;AAgBD,MAAM,WAAW,eAAe;IAC/B,mFAAmF;IACnF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0FAA0F;IAC1F,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,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;AAoKF,MAAM,MAAM,kBAAkB,GAAG,cAAc,CAAC,OAAO,UAAU,EAAE,eAAe,GAAG,SAAS,EAAE,eAAe,CAAC,CAAC;AAEjH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,kBAAkB,CAkKlH;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAElH"}
@@ -12,6 +12,9 @@ import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize } from "./truncate.js"
12
12
  const bashSchema = Type.Object({
13
13
  command: Type.String({ description: "Bash command to execute" }),
14
14
  timeout: Type.Optional(Type.Number({ description: "Timeout in seconds (optional, no default timeout)" })),
15
+ output_mode: Type.Optional(Type.Union([Type.Literal("always"), Type.Literal("on_fail"), Type.Literal("never")], {
16
+ description: "Output sent to the model: always (default) includes stdout/stderr, on_fail includes it only if the command fails, never omits it even on failure. The UI and session history retain the output.",
17
+ })),
15
18
  });
16
19
  export function createLocalBashOperations(options) {
17
20
  return new LocalToolOperations(options?.cwd ?? process.cwd(), { shellPath: options?.shellPath });
@@ -45,11 +48,14 @@ function resolveSpawnContext(command, cwd, spawnHook, exposeSessionEnvironment,
45
48
  const BASH_PREVIEW_LINES = 5;
46
49
  const BASH_UPDATE_THROTTLE_MS = 100;
47
50
  class BashResultRenderComponent extends Container {
48
- state = {
49
- cachedWidth: undefined,
50
- cachedLines: undefined,
51
- cachedSkipped: undefined,
52
- };
51
+ constructor() {
52
+ super(...arguments);
53
+ this.state = {
54
+ cachedWidth: undefined,
55
+ cachedLines: undefined,
56
+ cachedSkipped: undefined,
57
+ };
58
+ }
53
59
  }
54
60
  function formatDuration(ms) {
55
61
  return `${(ms / 1000).toFixed(1)}s`;
@@ -65,13 +71,10 @@ function formatBackendSuffix(backendInfo) {
65
71
  }
66
72
  function formatBashCall(args, backendInfo) {
67
73
  const command = str(args?.command);
68
- const timeout = args?.timeout;
69
- const timeoutSuffix = timeout ? theme.fg("muted", ` (timeout ${timeout}s)`) : "";
70
74
  const commandDisplay = command === null ? invalidArgText(theme) : command ? command : theme.fg("toolOutput", "...");
71
75
  return (formatBackendIcon(backendInfo, theme) +
72
76
  theme.fg("toolTitle", theme.bold("$ ")) +
73
- theme.fg("accent", theme.bold(commandDisplay)) +
74
- timeoutSuffix);
77
+ theme.fg("accent", theme.bold(commandDisplay)));
75
78
  }
76
79
  function getBashDisplayOutput(result, showImages, isPartial) {
77
80
  const output = getTextOutput(result, showImages).trim();
@@ -128,7 +131,7 @@ function addBashOutputWarnings(component, truncation, fullOutputPath) {
128
131
  }
129
132
  component.addChild(new Text(`\n${theme.fg("warning", `[${warnings.join(". ")}]`)}`, 0, 0));
130
133
  }
131
- function rebuildBashResultRenderComponent(component, result, options, isError, showImages, startedAt, endedAt, backendInfo) {
134
+ function rebuildBashResultRenderComponent(component, result, options, isError, showImages, startedAt, endedAt, backendInfo, bashArgs) {
132
135
  const state = component.state;
133
136
  component.clear();
134
137
  const output = getBashDisplayOutput(result, showImages, options.isPartial);
@@ -137,21 +140,24 @@ function rebuildBashResultRenderComponent(component, result, options, isError, s
137
140
  if (startedAt !== undefined) {
138
141
  const label = options.isPartial ? "Elapsed" : "Took";
139
142
  const endTime = endedAt ?? Date.now();
140
- component.addChild(new Text(`\n${theme.fg(options.isPartial ? "muted" : isError ? "error" : "success", `${label} ${formatDuration(endTime - startedAt)}`)}${formatBackendSuffix(backendInfo)}`, 0, 0));
143
+ component.addChild(new Text(`\n${theme.fg(options.isPartial ? "muted" : isError ? "error" : "success", `${label} ${formatDuration(endTime - startedAt)}`)}${bashArgs?.timeout !== undefined ? theme.fg("muted", ` (timeout ${bashArgs.timeout}s)`) : ""}${formatBackendSuffix(backendInfo)}`, 0, 0));
141
144
  }
142
- if (!options.expanded && output) {
143
- component.addChild({
144
- render: (width) => {
145
- if (!state.cachedSkipped || width < 1)
146
- return [];
145
+ component.addChild({
146
+ render: (width) => {
147
+ if (width < 1)
148
+ return [];
149
+ let hint = theme.fg("muted", `model output: ${bashArgs?.output_mode ?? "always"}`);
150
+ if (!options.expanded && output && state.cachedSkipped) {
147
151
  const expandKey = keyText("app.tools.expand");
148
- const hint = theme.fg("warning", `${state.cachedSkipped} lines hidden`) +
149
- (expandKey ? theme.fg("accent", ` · ${expandKey} to expand`) : "");
150
- return ["", truncateToWidth(hint, width, "...")];
151
- },
152
- invalidate: () => { },
153
- });
154
- }
152
+ hint +=
153
+ theme.fg("dim", " · ") +
154
+ theme.fg("warning", `${state.cachedSkipped} lines hidden`) +
155
+ (expandKey ? theme.fg("accent", ` · ${expandKey} to expand`) : "");
156
+ }
157
+ return ["", truncateToWidth(hint, width, "...")];
158
+ },
159
+ invalidate: () => { },
160
+ });
155
161
  }
156
162
  function appendBashStatus(text, status) {
157
163
  return `${text ? `${text}\n\n` : ""}${status}`;
@@ -174,11 +180,11 @@ export function createBashToolDefinition(operations, options) {
174
180
  return {
175
181
  name: "bash",
176
182
  label: "bash",
177
- 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.`,
183
+ description: `Execute a bash command in the current working directory. By default, the model receives stdout and stderr; output_mode can omit them from model context while retaining the UI and session output. 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.`,
178
184
  promptSnippet: "Execute bash commands (ls, grep, find, etc.)",
179
- promptGuidelines: exposeSessionEnvironment
180
- ? ["Inspect GRIP_* environment variables for current model and session details."]
181
- : undefined,
185
+ promptGuidelines: [
186
+ "For bash checks such as tests or builds, use output_mode: on_fail when only success or failure matters. Use always (default) when output contains needed data or warnings; use never only if output is unnecessary even on failure.",
187
+ ],
182
188
  parameters: bashSchema,
183
189
  async execute(_toolCallId, { command, timeout }, signal, onUpdate, ctx) {
184
190
  const resolvedCommand = commandPrefix ? `${commandPrefix}\n${command}` : command;
@@ -309,7 +315,7 @@ export function createBashToolDefinition(operations, options) {
309
315
  }
310
316
  }
311
317
  const component = context.lastComponent ?? new BashResultRenderComponent();
312
- rebuildBashResultRenderComponent(component, result, options, context.isError, context.showImages, state.startedAt, state.endedAt, ops.getBackendInfo?.());
318
+ rebuildBashResultRenderComponent(component, result, options, context.isError, context.showImages, state.startedAt, state.endedAt, ops.getBackendInfo?.(), context.args);
313
319
  component.invalidate();
314
320
  return component;
315
321
  },
@@ -1 +1 @@
1
- {"version":3,"file":"bash.js","sourceRoot":"","sources":["../../../src/core/tools/bash.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool, AgentToolResult } from \"@greppleai/grip-agent-core\";\nimport { Container, Text, truncateToWidth } from \"@greppleai/grip-tui\";\nimport { type Static, Type } from \"typebox\";\nimport { keyText } 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 { getShellEnv } from \"../../utils/shell.ts\";\nimport type { ExtensionContext, ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.ts\";\nimport {\n\tGRIP_SESSION_ENVIRONMENT_NAMES,\n\ttype GripSessionEnvironment,\n\tLocalToolOperations,\n\ttype ToolBackendInfo,\n\ttype ToolOperations,\n} from \"./operations.ts\";\nimport { OutputAccumulator, type OutputSnapshot } from \"./output-accumulator.ts\";\nimport { formatBackendIcon, 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 * Create tool operations using grip's built-in local shell execution backend.\n *\n * This is useful for extensions that intercept user_bash and still want grip's\n * standard local shell behavior while wrapping or rewriting commands.\n */\nexport interface LocalBashOperationsOptions {\n\tcwd?: string;\n\tshellPath?: string;\n}\n\nexport function createLocalBashOperations(options?: LocalBashOperationsOptions): ToolOperations {\n\treturn new LocalToolOperations(options?.cwd ?? process.cwd(), { shellPath: options?.shellPath });\n}\n\nexport interface BashSpawnContext {\n\tcommand: string;\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n}\n\nexport type BashSpawnHook = (context: BashSpawnContext) => BashSpawnContext;\n\nexport type BashSessionEnvironment = GripSessionEnvironment;\n\nexport function getBashSessionEnvironment(ctx: ExtensionContext | undefined): BashSessionEnvironment {\n\tif (!ctx?.session) return {};\n\tconst environment: BashSessionEnvironment = {\n\t\tGRIP_SESSION_ID: ctx.session.getSessionId(),\n\t};\n\tif (ctx.thinkingLevel) environment.GRIP_REASONING_LEVEL = ctx.thinkingLevel;\n\tconst sessionFile = ctx.session.getSessionReference();\n\tif (sessionFile) environment.GRIP_SESSION_FILE = sessionFile;\n\tif (ctx.model) {\n\t\tenvironment.GRIP_PROVIDER = ctx.model.provider;\n\t\tenvironment.GRIP_MODEL = ctx.model.id;\n\t}\n\treturn environment;\n}\n\nfunction resolveSpawnContext(\n\tcommand: string,\n\tcwd: string,\n\tspawnHook: BashSpawnHook | undefined,\n\texposeSessionEnvironment: boolean,\n\tctx: ExtensionContext | undefined,\n): BashSpawnContext {\n\tconst env = { ...getShellEnv() };\n\tfor (const name of GRIP_SESSION_ENVIRONMENT_NAMES) delete env[name];\n\tif (exposeSessionEnvironment) Object.assign(env, getBashSessionEnvironment(ctx));\n\tconst baseContext: BashSpawnContext = { command, cwd, env };\n\treturn spawnHook ? spawnHook(baseContext) : baseContext;\n}\n\nexport interface BashToolOptions {\n\t/** Command prefix prepended to every command (for example shell setup commands) */\n\tcommandPrefix?: string;\n\t/** Expose current grip session metadata as GRIP_* environment variables. Default: true */\n\texposeSessionEnvironment?: boolean;\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\treturn `${(ms / 1000).toFixed(1)}s`;\n}\n\nfunction formatBackendSuffix(backendInfo: ToolBackendInfo | undefined): string {\n\tif (!backendInfo) return \"\";\n\tif (backendInfo.type === \"local\") return theme.fg(\"muted\", ` [local ${backendInfo.cwd}]`);\n\treturn backendInfo.configured\n\t\t? theme.fg(\"muted\", ` [remote ${backendInfo.url}:${backendInfo.cwd}]`)\n\t\t: theme.fg(\"warning\", ` [remote not configured ${backendInfo.cwd}]`);\n}\n\nfunction formatBashCall(args: Partial<BashToolInput> | undefined, backendInfo?: ToolBackendInfo): string {\n\tconst command = str(args?.command);\n\tconst timeout = args?.timeout;\n\tconst timeoutSuffix = timeout ? theme.fg(\"muted\", ` (timeout ${timeout}s)`) : \"\";\n\tconst commandDisplay = command === null ? invalidArgText(theme) : command ? command : theme.fg(\"toolOutput\", \"...\");\n\treturn (\n\t\tformatBackendIcon(backendInfo, theme) +\n\t\ttheme.fg(\"toolTitle\", theme.bold(\"$ \")) +\n\t\ttheme.fg(\"accent\", theme.bold(commandDisplay)) +\n\t\ttimeoutSuffix\n\t);\n}\n\nfunction getBashDisplayOutput(\n\tresult: AgentToolResult<BashToolDetails | undefined>,\n\tshowImages: boolean,\n\tisPartial: boolean,\n): string {\n\tconst output = getTextOutput(result, showImages).trim();\n\tconst truncation = result.details?.truncation;\n\tconst fullOutputPath = result.details?.fullOutputPath;\n\tif (isPartial || !truncation?.truncated || !fullOutputPath || !output.endsWith(\"]\")) return output;\n\tconst footerStart = output.lastIndexOf(\"\\n\\n[\");\n\tif (footerStart === -1 || !output.slice(footerStart).includes(fullOutputPath)) return output;\n\treturn output.slice(0, footerStart).trimEnd();\n}\n\nfunction addBashOutput(\n\tcomponent: BashResultRenderComponent,\n\tstate: BashResultRenderState,\n\toutput: string,\n\toptions: ToolRenderResultOptions,\n): void {\n\tif (!output) return;\n\tconst styledOutput = output\n\t\t.split(\"\\n\")\n\t\t.map((line) => theme.fg(\"toolOutput\", line))\n\t\t.join(\"\\n\");\n\tif (options.expanded) {\n\t\tcomponent.addChild(new Text(`\\n${styledOutput}`, 0, 0));\n\t\treturn;\n\t}\n\tcomponent.addChild({\n\t\trender: (width: number) => {\n\t\t\tif (state.cachedLines === undefined || state.cachedWidth !== width) {\n\t\t\t\tconst preview = truncateToVisualLines(styledOutput, BASH_PREVIEW_LINES, width);\n\t\t\t\tstate.cachedLines = preview.visualLines;\n\t\t\t\tstate.cachedSkipped = preview.skippedCount;\n\t\t\t\tstate.cachedWidth = width;\n\t\t\t}\n\t\t\treturn [\"\", ...(state.cachedLines ?? [])];\n\t\t},\n\t\tinvalidate: () => {\n\t\t\tstate.cachedWidth = undefined;\n\t\t\tstate.cachedLines = undefined;\n\t\t\tstate.cachedSkipped = undefined;\n\t\t},\n\t});\n}\n\nfunction addBashOutputWarnings(\n\tcomponent: BashResultRenderComponent,\n\ttruncation: TruncationResult | undefined,\n\tfullOutputPath: string | undefined,\n): void {\n\tif (!truncation?.truncated && !fullOutputPath) return;\n\tconst warnings: string[] = [];\n\tif (fullOutputPath) warnings.push(`Full output: ${fullOutputPath}`);\n\tif (truncation?.truncated) {\n\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\twarnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`);\n\t\t} else {\n\t\t\twarnings.push(\n\t\t\t\t`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`,\n\t\t\t);\n\t\t}\n\t}\n\tcomponent.addChild(new Text(`\\n${theme.fg(\"warning\", `[${warnings.join(\". \")}]`)}`, 0, 0));\n}\n\nfunction rebuildBashResultRenderComponent(\n\tcomponent: BashResultRenderComponent,\n\tresult: AgentToolResult<BashToolDetails | undefined>,\n\toptions: ToolRenderResultOptions,\n\tisError: boolean,\n\tshowImages: boolean,\n\tstartedAt: number | undefined,\n\tendedAt: number | undefined,\n\tbackendInfo: ToolBackendInfo | undefined,\n): void {\n\tconst state = component.state;\n\tcomponent.clear();\n\tconst output = getBashDisplayOutput(result, showImages, options.isPartial);\n\taddBashOutput(component, state, output, options);\n\taddBashOutputWarnings(component, result.details?.truncation, result.details?.fullOutputPath);\n\tif (startedAt !== undefined) {\n\t\tconst label = options.isPartial ? \"Elapsed\" : \"Took\";\n\t\tconst endTime = endedAt ?? Date.now();\n\t\tcomponent.addChild(\n\t\t\tnew Text(\n\t\t\t\t`\\n${theme.fg(options.isPartial ? \"muted\" : isError ? \"error\" : \"success\", `${label} ${formatDuration(endTime - startedAt)}`)}${formatBackendSuffix(backendInfo)}`,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t),\n\t\t);\n\t}\n\tif (!options.expanded && output) {\n\t\tcomponent.addChild({\n\t\t\trender: (width) => {\n\t\t\t\tif (!state.cachedSkipped || width < 1) return [];\n\t\t\t\tconst expandKey = keyText(\"app.tools.expand\");\n\t\t\t\tconst hint =\n\t\t\t\t\ttheme.fg(\"warning\", `${state.cachedSkipped} lines hidden`) +\n\t\t\t\t\t(expandKey ? theme.fg(\"accent\", ` · ${expandKey} to expand`) : \"\");\n\t\t\t\treturn [\"\", truncateToWidth(hint, width, \"...\")];\n\t\t\t},\n\t\t\tinvalidate: () => {},\n\t\t});\n\t}\n}\n\nfunction appendBashStatus(text: string, status: string): string {\n\treturn `${text ? `${text}\\n\\n` : \"\"}${status}`;\n}\n\nfunction throwBashExecutionError(error: unknown, outputText: string): never {\n\tif (error instanceof Error && error.message === \"aborted\") {\n\t\tthrow new Error(appendBashStatus(outputText, \"Command aborted\"));\n\t}\n\tif (error instanceof Error && error.message.startsWith(\"timeout:\")) {\n\t\tconst timeoutSeconds = error.message.split(\":\")[1];\n\t\tthrow new Error(appendBashStatus(outputText, `Command timed out after ${timeoutSeconds} seconds`));\n\t}\n\tthrow error;\n}\n\nexport type BashToolDefinition = ToolDefinition<typeof bashSchema, BashToolDetails | undefined, BashRenderState>;\n\nexport function createBashToolDefinition(operations: ToolOperations, options?: BashToolOptions): BashToolDefinition {\n\tconst ops = operations;\n\tconst commandPrefix = options?.commandPrefix;\n\tconst exposeSessionEnvironment = options?.exposeSessionEnvironment ?? true;\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\tpromptGuidelines: exposeSessionEnvironment\n\t\t\t? [\"Inspect GRIP_* environment variables for current model and session details.\"]\n\t\t\t: undefined,\n\t\tparameters: bashSchema,\n\t\tasync execute(_toolCallId, { command, timeout }: BashToolInput, signal?: AbortSignal, onUpdate?, ctx?) {\n\t\t\tconst resolvedCommand = commandPrefix ? `${commandPrefix}\\n${command}` : command;\n\t\t\tconst spawnContext = resolveSpawnContext(resolvedCommand, ops.cwd, spawnHook, exposeSessionEnvironment, ctx);\n\t\t\tconst output = new OutputAccumulator({ tempFilePrefix: \"grip-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: OutputSnapshot, 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\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, {\n\t\t\t\t\t\tcwd: 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\tthrowBashExecutionError(err, text);\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(appendBashStatus(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, ops.getBackendInfo?.()));\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 as any,\n\t\t\t\toptions,\n\t\t\t\tcontext.isError,\n\t\t\t\tcontext.showImages,\n\t\t\t\tstate.startedAt,\n\t\t\t\tstate.endedAt,\n\t\t\t\tops.getBackendInfo?.(),\n\t\t\t);\n\t\t\tcomponent.invalidate();\n\t\t\treturn component;\n\t\t},\n\t};\n}\n\nexport function createBashTool(operations: ToolOperations, options?: BashToolOptions): AgentTool<typeof bashSchema> {\n\treturn wrapToolDefinition(createBashToolDefinition(operations, options));\n}\n"]}
1
+ {"version":3,"file":"bash.js","sourceRoot":"","sources":["../../../src/core/tools/bash.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAe,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,wDAAwD,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,uDAAuD,CAAC;AAC9F,OAAO,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,OAAO,EACN,8BAA8B,EAE9B,mBAAmB,GAGnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,iBAAiB,EAAuB,MAAM,yBAAyB,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAC1F,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,UAAU,EAAyB,MAAM,eAAe,CAAC;AAExG,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC;IAC9B,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,yBAAyB,EAAE,CAAC;IAChE,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,mDAAmD,EAAE,CAAC,CAAC;IACzG,WAAW,EAAE,IAAI,CAAC,QAAQ,CACzB,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE;QACpF,WAAW,EACV,iMAAiM;KAClM,CAAC,CACF;CACD,CAAC,CAAC;AAoBH,MAAM,UAAU,yBAAyB,CAAC,OAAoC;IAC7E,OAAO,IAAI,mBAAmB,CAAC,OAAO,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;AAClG,CAAC;AAYD,MAAM,UAAU,yBAAyB,CAAC,GAAiC;IAC1E,IAAI,CAAC,GAAG,EAAE,OAAO;QAAE,OAAO,EAAE,CAAC;IAC7B,MAAM,WAAW,GAA2B;QAC3C,eAAe,EAAE,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE;KAC3C,CAAC;IACF,IAAI,GAAG,CAAC,aAAa;QAAE,WAAW,CAAC,oBAAoB,GAAG,GAAG,CAAC,aAAa,CAAC;IAC5E,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC;IACtD,IAAI,WAAW;QAAE,WAAW,CAAC,iBAAiB,GAAG,WAAW,CAAC;IAC7D,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;QACf,WAAW,CAAC,aAAa,GAAG,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC;QAC/C,WAAW,CAAC,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;IACvC,CAAC;IACD,OAAO,WAAW,CAAC;AACpB,CAAC;AAED,SAAS,mBAAmB,CAC3B,OAAe,EACf,GAAW,EACX,SAAoC,EACpC,wBAAiC,EACjC,GAAiC;IAEjC,MAAM,GAAG,GAAG,EAAE,GAAG,WAAW,EAAE,EAAE,CAAC;IACjC,KAAK,MAAM,IAAI,IAAI,8BAA8B;QAAE,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC;IACpE,IAAI,wBAAwB;QAAE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,yBAAyB,CAAC,GAAG,CAAC,CAAC,CAAC;IACjF,MAAM,WAAW,GAAqB,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;IAC5D,OAAO,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;AACzD,CAAC;AAWD,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAC7B,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAcpC,MAAM,yBAA0B,SAAQ,SAAS;IAAjD;;QACC,UAAK,GAA0B;YAC9B,WAAW,EAAE,SAAS;YACtB,WAAW,EAAE,SAAS;YACtB,aAAa,EAAE,SAAS;SACxB,CAAC;IACH,CAAC;CAAA;AAED,SAAS,cAAc,CAAC,EAAU;IACjC,OAAO,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;AACrC,CAAC;AAED,SAAS,mBAAmB,CAAC,WAAwC;IACpE,IAAI,CAAC,WAAW;QAAE,OAAO,EAAE,CAAC;IAC5B,IAAI,WAAW,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,WAAW,CAAC,GAAG,GAAG,CAAC,CAAC;IAC1F,OAAO,WAAW,CAAC,UAAU;QAC5B,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,WAAW,CAAC,GAAG,IAAI,WAAW,CAAC,GAAG,GAAG,CAAC;QACtE,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,2BAA2B,WAAW,CAAC,GAAG,GAAG,CAAC,CAAC;AACvE,CAAC;AAED,SAAS,cAAc,CAAC,IAAwC,EAAE,WAA6B;IAC9F,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACnC,MAAM,cAAc,GAAG,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IACpH,OAAO,CACN,iBAAiB,CAAC,WAAW,EAAE,KAAK,CAAC;QACrC,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAC9C,CAAC;AACH,CAAC;AAED,SAAS,oBAAoB,CAC5B,MAAoD,EACpD,UAAmB,EACnB,SAAkB;IAElB,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC;IACxD,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC;IAC9C,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,EAAE,cAAc,CAAC;IACtD,IAAI,SAAS,IAAI,CAAC,UAAU,EAAE,SAAS,IAAI,CAAC,cAAc,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,MAAM,CAAC;IACnG,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAChD,IAAI,WAAW,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC;QAAE,OAAO,MAAM,CAAC;IAC7F,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,OAAO,EAAE,CAAC;AAC/C,CAAC;AAED,SAAS,aAAa,CACrB,SAAoC,EACpC,KAA4B,EAC5B,MAAc,EACd,OAAgC;IAEhC,IAAI,CAAC,MAAM;QAAE,OAAO;IACpB,MAAM,YAAY,GAAG,MAAM;SACzB,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;SAC3C,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACtB,SAAS,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACxD,OAAO;IACR,CAAC;IACD,SAAS,CAAC,QAAQ,CAAC;QAClB,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACzB,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS,IAAI,KAAK,CAAC,WAAW,KAAK,KAAK,EAAE,CAAC;gBACpE,MAAM,OAAO,GAAG,qBAAqB,CAAC,YAAY,EAAE,kBAAkB,EAAE,KAAK,CAAC,CAAC;gBAC/E,KAAK,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;gBACxC,KAAK,CAAC,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;gBAC3C,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC;YAC3B,CAAC;YACD,OAAO,CAAC,EAAE,EAAE,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,CAAC;QAC3C,CAAC;QACD,UAAU,EAAE,GAAG,EAAE;YAChB,KAAK,CAAC,WAAW,GAAG,SAAS,CAAC;YAC9B,KAAK,CAAC,WAAW,GAAG,SAAS,CAAC;YAC9B,KAAK,CAAC,aAAa,GAAG,SAAS,CAAC;QACjC,CAAC;KACD,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAC7B,SAAoC,EACpC,UAAwC,EACxC,cAAkC;IAElC,IAAI,CAAC,UAAU,EAAE,SAAS,IAAI,CAAC,cAAc;QAAE,OAAO;IACtD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,cAAc;QAAE,QAAQ,CAAC,IAAI,CAAC,gBAAgB,cAAc,EAAE,CAAC,CAAC;IACpE,IAAI,UAAU,EAAE,SAAS,EAAE,CAAC;QAC3B,IAAI,UAAU,CAAC,WAAW,KAAK,OAAO,EAAE,CAAC;YACxC,QAAQ,CAAC,IAAI,CAAC,sBAAsB,UAAU,CAAC,WAAW,OAAO,UAAU,CAAC,UAAU,QAAQ,CAAC,CAAC;QACjG,CAAC;aAAM,CAAC;YACP,QAAQ,CAAC,IAAI,CACZ,cAAc,UAAU,CAAC,WAAW,iBAAiB,UAAU,CAAC,UAAU,CAAC,QAAQ,IAAI,iBAAiB,CAAC,SAAS,CAClH,CAAC;QACH,CAAC;IACF,CAAC;IACD,SAAS,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5F,CAAC;AAED,SAAS,gCAAgC,CACxC,SAAoC,EACpC,MAAoD,EACpD,OAAgC,EAChC,OAAgB,EAChB,UAAmB,EACnB,SAA6B,EAC7B,OAA2B,EAC3B,WAAwC,EACxC,QAA4C;IAE5C,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC;IAC9B,SAAS,CAAC,KAAK,EAAE,CAAC;IAClB,MAAM,MAAM,GAAG,oBAAoB,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC3E,aAAa,CAAC,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACjD,qBAAqB,CAAC,SAAS,EAAE,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IAC7F,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;QACrD,MAAM,OAAO,GAAG,OAAO,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QACtC,SAAS,CAAC,QAAQ,CACjB,IAAI,IAAI,CACP,KAAK,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,GAAG,KAAK,IAAI,cAAc,CAAC,OAAO,GAAG,SAAS,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,mBAAmB,CAAC,WAAW,CAAC,EAAE,EAChQ,CAAC,EACD,CAAC,CACD,CACD,CAAC;IACH,CAAC;IACD,SAAS,CAAC,QAAQ,CAAC;QAClB,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YACjB,IAAI,KAAK,GAAG,CAAC;gBAAE,OAAO,EAAE,CAAC;YACzB,IAAI,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,QAAQ,EAAE,WAAW,IAAI,QAAQ,EAAE,CAAC,CAAC;YACnF,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,MAAM,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;gBACxD,MAAM,SAAS,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;gBAC9C,IAAI;oBACH,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC;wBACtB,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,KAAK,CAAC,aAAa,eAAe,CAAC;wBAC1D,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,SAAS,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACrE,CAAC;YACD,OAAO,CAAC,EAAE,EAAE,eAAe,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;QAClD,CAAC;QACD,UAAU,EAAE,GAAG,EAAE,GAAE,CAAC;KACpB,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY,EAAE,MAAc;IACrD,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC;AAChD,CAAC;AAED,SAAS,uBAAuB,CAAC,KAAc,EAAE,UAAkB;IAClE,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAClE,CAAC;IACD,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACpE,MAAM,cAAc,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACnD,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,UAAU,EAAE,2BAA2B,cAAc,UAAU,CAAC,CAAC,CAAC;IACpG,CAAC;IACD,MAAM,KAAK,CAAC;AACb,CAAC;AAID,MAAM,UAAU,wBAAwB,CAAC,UAA0B,EAAE,OAAyB;IAC7F,MAAM,GAAG,GAAG,UAAU,CAAC;IACvB,MAAM,aAAa,GAAG,OAAO,EAAE,aAAa,CAAC;IAC7C,MAAM,wBAAwB,GAAG,OAAO,EAAE,wBAAwB,IAAI,IAAI,CAAC;IAC3E,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,CAAC;IACrC,OAAO;QACN,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,MAAM;QACb,WAAW,EAAE,kOAAkO,iBAAiB,aAAa,iBAAiB,GAAG,IAAI,0HAA0H;QAC/Z,aAAa,EAAE,8CAA8C;QAC7D,gBAAgB,EAAE;YACjB,qOAAqO;SACrO;QACD,UAAU,EAAE,UAAU;QACtB,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,OAAO,EAAiB,EAAE,MAAoB,EAAE,QAAS,EAAE,GAAI;YACpG,MAAM,eAAe,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,aAAa,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;YACjF,MAAM,YAAY,GAAG,mBAAmB,CAAC,eAAe,EAAE,GAAG,CAAC,GAAG,EAAE,SAAS,EAAE,wBAAwB,EAAE,GAAG,CAAC,CAAC;YAC7G,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC;YACtE,IAAI,WAAuC,CAAC;YAC5C,IAAI,WAAW,GAAG,KAAK,CAAC;YACxB,IAAI,YAAY,GAAG,CAAC,CAAC;YAErB,MAAM,gBAAgB,GAAG,GAAG,EAAE;gBAC7B,IAAI,CAAC,QAAQ,IAAI,CAAC,WAAW;oBAAE,OAAO;gBACtC,WAAW,GAAG,KAAK,CAAC;gBACpB,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAC1B,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC/D,QAAQ,CAAC;oBACR,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;oBACzD,OAAO,EAAE;wBACR,UAAU,EAAE,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;wBAC3E,cAAc,EAAE,QAAQ,CAAC,cAAc;qBACvC;iBACD,CAAC,CAAC;YACJ,CAAC,CAAC;YAEF,MAAM,gBAAgB,GAAG,GAAG,EAAE;gBAC7B,IAAI,WAAW,EAAE,CAAC;oBACjB,YAAY,CAAC,WAAW,CAAC,CAAC;oBAC1B,WAAW,GAAG,SAAS,CAAC;gBACzB,CAAC;YACF,CAAC,CAAC;YAEF,MAAM,oBAAoB,GAAG,GAAG,EAAE;gBACjC,IAAI,CAAC,QAAQ;oBAAE,OAAO;gBACtB,WAAW,GAAG,IAAI,CAAC;gBACnB,MAAM,KAAK,GAAG,uBAAuB,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY,CAAC,CAAC;gBACpE,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;oBAChB,gBAAgB,EAAE,CAAC;oBACnB,gBAAgB,EAAE,CAAC;oBACnB,OAAO;gBACR,CAAC;gBACD,WAAW,KAAK,UAAU,CAAC,GAAG,EAAE;oBAC/B,WAAW,GAAG,SAAS,CAAC;oBACxB,gBAAgB,EAAE,CAAC;gBACpB,CAAC,EAAE,KAAK,CAAC,CAAC;YACX,CAAC,CAAC;YAEF,IAAI,QAAQ,EAAE,CAAC;gBACd,QAAQ,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;YAC/C,CAAC;YAED,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,EAAE;gBACnC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACpB,oBAAoB,EAAE,CAAC;YACxB,CAAC,CAAC;YAEF,MAAM,YAAY,GAAG,KAAK,IAAI,EAAE;gBAC/B,MAAM,CAAC,MAAM,EAAE,CAAC;gBAChB,gBAAgB,EAAE,CAAC;gBACnB,gBAAgB,EAAE,CAAC;gBACnB,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC/D,MAAM,MAAM,CAAC,aAAa,EAAE,CAAC;gBAC7B,OAAO,QAAQ,CAAC;YACjB,CAAC,CAAC;YAEF,MAAM,YAAY,GAAG,CAAC,QAAwB,EAAE,SAAS,GAAG,aAAa,EAAE,EAAE;gBAC5E,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC;gBACvC,IAAI,IAAI,GAAG,QAAQ,CAAC,OAAO,IAAI,SAAS,CAAC;gBACzC,IAAI,OAAoC,CAAC;gBACzC,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;oBAC1B,OAAO,GAAG,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,CAAC,cAAc,EAAE,CAAC;oBAClE,MAAM,SAAS,GAAG,UAAU,CAAC,UAAU,GAAG,UAAU,CAAC,WAAW,GAAG,CAAC,CAAC;oBACrE,MAAM,OAAO,GAAG,UAAU,CAAC,UAAU,CAAC;oBACtC,IAAI,UAAU,CAAC,eAAe,EAAE,CAAC;wBAChC,MAAM,YAAY,GAAG,UAAU,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC;wBAC3D,IAAI,IAAI,qBAAqB,UAAU,CAAC,UAAU,CAAC,WAAW,CAAC,YAAY,OAAO,aAAa,YAAY,mBAAmB,QAAQ,CAAC,cAAc,GAAG,CAAC;oBAC1J,CAAC;yBAAM,IAAI,UAAU,CAAC,WAAW,KAAK,OAAO,EAAE,CAAC;wBAC/C,IAAI,IAAI,sBAAsB,SAAS,IAAI,OAAO,OAAO,UAAU,CAAC,UAAU,kBAAkB,QAAQ,CAAC,cAAc,GAAG,CAAC;oBAC5H,CAAC;yBAAM,CAAC;wBACP,IAAI,IAAI,sBAAsB,SAAS,IAAI,OAAO,OAAO,UAAU,CAAC,UAAU,KAAK,UAAU,CAAC,iBAAiB,CAAC,yBAAyB,QAAQ,CAAC,cAAc,GAAG,CAAC;oBACrK,CAAC;gBACF,CAAC;gBACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;YAC1B,CAAC,CAAC;YAEF,IAAI,CAAC;gBACJ,IAAI,QAAuB,CAAC;gBAC5B,IAAI,CAAC;oBACJ,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;wBACnD,GAAG,EAAE,YAAY,CAAC,GAAG;wBACrB,MAAM,EAAE,UAAU;wBAClB,MAAM;wBACN,OAAO;wBACP,GAAG,EAAE,YAAY,CAAC,GAAG;qBACrB,CAAC,CAAC;oBACH,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;gBAC5B,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACd,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;oBACtC,MAAM,EAAE,IAAI,EAAE,GAAG,YAAY,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;oBAC5C,uBAAuB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;gBACpC,CAAC;gBAED,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;gBACtC,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;gBAC7D,IAAI,QAAQ,KAAK,CAAC,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;oBACzC,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,UAAU,EAAE,4BAA4B,QAAQ,EAAE,CAAC,CAAC,CAAC;gBACvF,CAAC;gBACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;YACnE,CAAC;oBAAS,CAAC;gBACV,gBAAgB,EAAE,CAAC;YACpB,CAAC;QACF,CAAC;QACD,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO;YAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;YAC5B,IAAI,OAAO,CAAC,gBAAgB,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC/D,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAC7B,KAAK,CAAC,OAAO,GAAG,SAAS,CAAC;YAC3B,CAAC;YACD,MAAM,IAAI,GAAI,OAAO,CAAC,aAAkC,IAAI,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC/E,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC;YAC3D,OAAO,IAAI,CAAC;QACb,CAAC;QACD,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO;YAC5C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;YAC5B,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;gBAC3E,KAAK,CAAC,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,IAAI,CAAC,CAAC;YAChE,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBAC3C,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;gBAC7B,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;oBACpB,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;oBAC9B,KAAK,CAAC,QAAQ,GAAG,SAAS,CAAC;gBAC5B,CAAC;YACF,CAAC;YACD,MAAM,SAAS,GACb,OAAO,CAAC,aAAuD,IAAI,IAAI,yBAAyB,EAAE,CAAC;YACrG,gCAAgC,CAC/B,SAAS,EACT,MAAa,EACb,OAAO,EACP,OAAO,CAAC,OAAO,EACf,OAAO,CAAC,UAAU,EAClB,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,OAAO,EACb,GAAG,CAAC,cAAc,EAAE,EAAE,EACtB,OAAO,CAAC,IAA0C,CAClD,CAAC;YACF,SAAS,CAAC,UAAU,EAAE,CAAC;YACvB,OAAO,SAAS,CAAC;QAClB,CAAC;KACD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,UAA0B,EAAE,OAAyB;IACnF,OAAO,kBAAkB,CAAC,wBAAwB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;AAC1E,CAAC","sourcesContent":["import type { AgentTool, AgentToolResult } from \"@greppleai/grip-agent-core\";\nimport { Container, Text, truncateToWidth } from \"@greppleai/grip-tui\";\nimport { type Static, Type } from \"typebox\";\nimport { keyText } 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 { getShellEnv } from \"../../utils/shell.ts\";\nimport type { ExtensionContext, ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.ts\";\nimport {\n\tGRIP_SESSION_ENVIRONMENT_NAMES,\n\ttype GripSessionEnvironment,\n\tLocalToolOperations,\n\ttype ToolBackendInfo,\n\ttype ToolOperations,\n} from \"./operations.ts\";\nimport { OutputAccumulator, type OutputSnapshot } from \"./output-accumulator.ts\";\nimport { formatBackendIcon, 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\toutput_mode: Type.Optional(\n\t\tType.Union([Type.Literal(\"always\"), Type.Literal(\"on_fail\"), Type.Literal(\"never\")], {\n\t\t\tdescription:\n\t\t\t\t\"Output sent to the model: always (default) includes stdout/stderr, on_fail includes it only if the command fails, never omits it even on failure. The UI and session history retain the output.\",\n\t\t}),\n\t),\n});\n\nexport type BashToolInput = Static<typeof bashSchema>;\n\nexport interface BashToolDetails {\n\ttruncation?: TruncationResult;\n\tfullOutputPath?: string;\n}\n\n/**\n * Create tool operations using grip's built-in local shell execution backend.\n *\n * This is useful for extensions that intercept user_bash and still want grip's\n * standard local shell behavior while wrapping or rewriting commands.\n */\nexport interface LocalBashOperationsOptions {\n\tcwd?: string;\n\tshellPath?: string;\n}\n\nexport function createLocalBashOperations(options?: LocalBashOperationsOptions): ToolOperations {\n\treturn new LocalToolOperations(options?.cwd ?? process.cwd(), { shellPath: options?.shellPath });\n}\n\nexport interface BashSpawnContext {\n\tcommand: string;\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n}\n\nexport type BashSpawnHook = (context: BashSpawnContext) => BashSpawnContext;\n\nexport type BashSessionEnvironment = GripSessionEnvironment;\n\nexport function getBashSessionEnvironment(ctx: ExtensionContext | undefined): BashSessionEnvironment {\n\tif (!ctx?.session) return {};\n\tconst environment: BashSessionEnvironment = {\n\t\tGRIP_SESSION_ID: ctx.session.getSessionId(),\n\t};\n\tif (ctx.thinkingLevel) environment.GRIP_REASONING_LEVEL = ctx.thinkingLevel;\n\tconst sessionFile = ctx.session.getSessionReference();\n\tif (sessionFile) environment.GRIP_SESSION_FILE = sessionFile;\n\tif (ctx.model) {\n\t\tenvironment.GRIP_PROVIDER = ctx.model.provider;\n\t\tenvironment.GRIP_MODEL = ctx.model.id;\n\t}\n\treturn environment;\n}\n\nfunction resolveSpawnContext(\n\tcommand: string,\n\tcwd: string,\n\tspawnHook: BashSpawnHook | undefined,\n\texposeSessionEnvironment: boolean,\n\tctx: ExtensionContext | undefined,\n): BashSpawnContext {\n\tconst env = { ...getShellEnv() };\n\tfor (const name of GRIP_SESSION_ENVIRONMENT_NAMES) delete env[name];\n\tif (exposeSessionEnvironment) Object.assign(env, getBashSessionEnvironment(ctx));\n\tconst baseContext: BashSpawnContext = { command, cwd, env };\n\treturn spawnHook ? spawnHook(baseContext) : baseContext;\n}\n\nexport interface BashToolOptions {\n\t/** Command prefix prepended to every command (for example shell setup commands) */\n\tcommandPrefix?: string;\n\t/** Expose current grip session metadata as GRIP_* environment variables. Default: true */\n\texposeSessionEnvironment?: boolean;\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\treturn `${(ms / 1000).toFixed(1)}s`;\n}\n\nfunction formatBackendSuffix(backendInfo: ToolBackendInfo | undefined): string {\n\tif (!backendInfo) return \"\";\n\tif (backendInfo.type === \"local\") return theme.fg(\"muted\", ` [local ${backendInfo.cwd}]`);\n\treturn backendInfo.configured\n\t\t? theme.fg(\"muted\", ` [remote ${backendInfo.url}:${backendInfo.cwd}]`)\n\t\t: theme.fg(\"warning\", ` [remote not configured ${backendInfo.cwd}]`);\n}\n\nfunction formatBashCall(args: Partial<BashToolInput> | undefined, backendInfo?: ToolBackendInfo): string {\n\tconst command = str(args?.command);\n\tconst commandDisplay = command === null ? invalidArgText(theme) : command ? command : theme.fg(\"toolOutput\", \"...\");\n\treturn (\n\t\tformatBackendIcon(backendInfo, theme) +\n\t\ttheme.fg(\"toolTitle\", theme.bold(\"$ \")) +\n\t\ttheme.fg(\"accent\", theme.bold(commandDisplay))\n\t);\n}\n\nfunction getBashDisplayOutput(\n\tresult: AgentToolResult<BashToolDetails | undefined>,\n\tshowImages: boolean,\n\tisPartial: boolean,\n): string {\n\tconst output = getTextOutput(result, showImages).trim();\n\tconst truncation = result.details?.truncation;\n\tconst fullOutputPath = result.details?.fullOutputPath;\n\tif (isPartial || !truncation?.truncated || !fullOutputPath || !output.endsWith(\"]\")) return output;\n\tconst footerStart = output.lastIndexOf(\"\\n\\n[\");\n\tif (footerStart === -1 || !output.slice(footerStart).includes(fullOutputPath)) return output;\n\treturn output.slice(0, footerStart).trimEnd();\n}\n\nfunction addBashOutput(\n\tcomponent: BashResultRenderComponent,\n\tstate: BashResultRenderState,\n\toutput: string,\n\toptions: ToolRenderResultOptions,\n): void {\n\tif (!output) return;\n\tconst styledOutput = output\n\t\t.split(\"\\n\")\n\t\t.map((line) => theme.fg(\"toolOutput\", line))\n\t\t.join(\"\\n\");\n\tif (options.expanded) {\n\t\tcomponent.addChild(new Text(`\\n${styledOutput}`, 0, 0));\n\t\treturn;\n\t}\n\tcomponent.addChild({\n\t\trender: (width: number) => {\n\t\t\tif (state.cachedLines === undefined || state.cachedWidth !== width) {\n\t\t\t\tconst preview = truncateToVisualLines(styledOutput, BASH_PREVIEW_LINES, width);\n\t\t\t\tstate.cachedLines = preview.visualLines;\n\t\t\t\tstate.cachedSkipped = preview.skippedCount;\n\t\t\t\tstate.cachedWidth = width;\n\t\t\t}\n\t\t\treturn [\"\", ...(state.cachedLines ?? [])];\n\t\t},\n\t\tinvalidate: () => {\n\t\t\tstate.cachedWidth = undefined;\n\t\t\tstate.cachedLines = undefined;\n\t\t\tstate.cachedSkipped = undefined;\n\t\t},\n\t});\n}\n\nfunction addBashOutputWarnings(\n\tcomponent: BashResultRenderComponent,\n\ttruncation: TruncationResult | undefined,\n\tfullOutputPath: string | undefined,\n): void {\n\tif (!truncation?.truncated && !fullOutputPath) return;\n\tconst warnings: string[] = [];\n\tif (fullOutputPath) warnings.push(`Full output: ${fullOutputPath}`);\n\tif (truncation?.truncated) {\n\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\twarnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`);\n\t\t} else {\n\t\t\twarnings.push(\n\t\t\t\t`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`,\n\t\t\t);\n\t\t}\n\t}\n\tcomponent.addChild(new Text(`\\n${theme.fg(\"warning\", `[${warnings.join(\". \")}]`)}`, 0, 0));\n}\n\nfunction rebuildBashResultRenderComponent(\n\tcomponent: BashResultRenderComponent,\n\tresult: AgentToolResult<BashToolDetails | undefined>,\n\toptions: ToolRenderResultOptions,\n\tisError: boolean,\n\tshowImages: boolean,\n\tstartedAt: number | undefined,\n\tendedAt: number | undefined,\n\tbackendInfo: ToolBackendInfo | undefined,\n\tbashArgs: Partial<BashToolInput> | undefined,\n): void {\n\tconst state = component.state;\n\tcomponent.clear();\n\tconst output = getBashDisplayOutput(result, showImages, options.isPartial);\n\taddBashOutput(component, state, output, options);\n\taddBashOutputWarnings(component, result.details?.truncation, result.details?.fullOutputPath);\n\tif (startedAt !== undefined) {\n\t\tconst label = options.isPartial ? \"Elapsed\" : \"Took\";\n\t\tconst endTime = endedAt ?? Date.now();\n\t\tcomponent.addChild(\n\t\t\tnew Text(\n\t\t\t\t`\\n${theme.fg(options.isPartial ? \"muted\" : isError ? \"error\" : \"success\", `${label} ${formatDuration(endTime - startedAt)}`)}${bashArgs?.timeout !== undefined ? theme.fg(\"muted\", ` (timeout ${bashArgs.timeout}s)`) : \"\"}${formatBackendSuffix(backendInfo)}`,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t),\n\t\t);\n\t}\n\tcomponent.addChild({\n\t\trender: (width) => {\n\t\t\tif (width < 1) return [];\n\t\t\tlet hint = theme.fg(\"muted\", `model output: ${bashArgs?.output_mode ?? \"always\"}`);\n\t\t\tif (!options.expanded && output && state.cachedSkipped) {\n\t\t\t\tconst expandKey = keyText(\"app.tools.expand\");\n\t\t\t\thint +=\n\t\t\t\t\ttheme.fg(\"dim\", \" · \") +\n\t\t\t\t\ttheme.fg(\"warning\", `${state.cachedSkipped} lines hidden`) +\n\t\t\t\t\t(expandKey ? theme.fg(\"accent\", ` · ${expandKey} to expand`) : \"\");\n\t\t\t}\n\t\t\treturn [\"\", truncateToWidth(hint, width, \"...\")];\n\t\t},\n\t\tinvalidate: () => {},\n\t});\n}\n\nfunction appendBashStatus(text: string, status: string): string {\n\treturn `${text ? `${text}\\n\\n` : \"\"}${status}`;\n}\n\nfunction throwBashExecutionError(error: unknown, outputText: string): never {\n\tif (error instanceof Error && error.message === \"aborted\") {\n\t\tthrow new Error(appendBashStatus(outputText, \"Command aborted\"));\n\t}\n\tif (error instanceof Error && error.message.startsWith(\"timeout:\")) {\n\t\tconst timeoutSeconds = error.message.split(\":\")[1];\n\t\tthrow new Error(appendBashStatus(outputText, `Command timed out after ${timeoutSeconds} seconds`));\n\t}\n\tthrow error;\n}\n\nexport type BashToolDefinition = ToolDefinition<typeof bashSchema, BashToolDetails | undefined, BashRenderState>;\n\nexport function createBashToolDefinition(operations: ToolOperations, options?: BashToolOptions): BashToolDefinition {\n\tconst ops = operations;\n\tconst commandPrefix = options?.commandPrefix;\n\tconst exposeSessionEnvironment = options?.exposeSessionEnvironment ?? true;\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. By default, the model receives stdout and stderr; output_mode can omit them from model context while retaining the UI and session output. 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\tpromptGuidelines: [\n\t\t\t\"For bash checks such as tests or builds, use output_mode: on_fail when only success or failure matters. Use always (default) when output contains needed data or warnings; use never only if output is unnecessary even on failure.\",\n\t\t],\n\t\tparameters: bashSchema,\n\t\tasync execute(_toolCallId, { command, timeout }: BashToolInput, signal?: AbortSignal, onUpdate?, ctx?) {\n\t\t\tconst resolvedCommand = commandPrefix ? `${commandPrefix}\\n${command}` : command;\n\t\t\tconst spawnContext = resolveSpawnContext(resolvedCommand, ops.cwd, spawnHook, exposeSessionEnvironment, ctx);\n\t\t\tconst output = new OutputAccumulator({ tempFilePrefix: \"grip-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: OutputSnapshot, 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\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, {\n\t\t\t\t\t\tcwd: 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\tthrowBashExecutionError(err, text);\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(appendBashStatus(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, ops.getBackendInfo?.()));\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 as any,\n\t\t\t\toptions,\n\t\t\t\tcontext.isError,\n\t\t\t\tcontext.showImages,\n\t\t\t\tstate.startedAt,\n\t\t\t\tstate.endedAt,\n\t\t\t\tops.getBackendInfo?.(),\n\t\t\t\tcontext.args as Partial<BashToolInput> | undefined,\n\t\t\t);\n\t\t\tcomponent.invalidate();\n\t\t\treturn component;\n\t\t},\n\t};\n}\n\nexport function createBashTool(operations: ToolOperations, options?: BashToolOptions): AgentTool<typeof bashSchema> {\n\treturn wrapToolDefinition(createBashToolDefinition(operations, options));\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"compress-context.d.ts","sourceRoot":"","sources":["../../../src/core/tools/compress-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAI7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,QAAA,MAAM,MAAM;;;;EAYX,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,OAAO,MAAM,CAAC,CAAC;AACzD,MAAM,WAAW,yBAAyB;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;CACzB;AA0BD,2FAA2F;AAC3F,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,GAAG,YAAY,EAAE,CAInG;AAqCD,yGAAyG;AACzG,wBAAgB,iCAAiC,CAChD,OAAO,EAAE,eAAe,EACxB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GAChB,MAAM,GAAG,SAAS,CAOpB;AAED,8FAA8F;AAC9F,wBAAgB,gCAAgC,CAC/C,OAAO,EAAE,eAAe,EACxB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GAChB,OAAO,CAET;AAED,wBAAgB,mCAAmC,CAClD,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,CAAC,OAAO,EAAE,yBAAyB,KAAK,IAAI,GACpD,cAAc,CAAC,OAAO,MAAM,CAAC,CAsD/B","sourcesContent":["import type { Static } from \"typebox\";\nimport { Type } from \"typebox\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport { HOOK_EXECUTION_CUSTOM_TYPE } from \"../hooks/types.ts\";\nimport { STRUCTURED_RESPONSE_INTERNAL_CUSTOM_TYPE } from \"../messages.ts\";\nimport { getLatestCompactionEntry, projectSessionContextEntries } from \"../session/context.ts\";\nimport type { ReadonlySession } from \"../session/session.ts\";\nimport type { SessionEntry } from \"../session/types.ts\";\nimport { abortIf } from \"./runtime.ts\";\n\nconst schema = Type.Object(\n\t{\n\t\tstartEntryId: Type.String({ description: \"ID of the first message to replace\" }),\n\t\tendEntryId: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Inclusive last message to replace; must precede the current user request. Omit to compress through the last eligible entry.\",\n\t\t\t}),\n\t\t),\n\t\tsummary: Type.String({ description: \"Replacement context for the selected range\" }),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type CompressContextInput = Static<typeof schema>;\nexport interface PendingContextCompression {\n\ttoolCallId: string;\n\tstartEntryId: string;\n\tendEntryId?: string;\n\tsummary: string;\n\tassistantEntryId: string;\n}\n\nfunction isContextEntry(entry: SessionEntry, compactionId: string | undefined, toolCallId: string): boolean {\n\tif (entry.type === \"custom_message\") {\n\t\treturn (\n\t\t\tentry.customType !== STRUCTURED_RESPONSE_INTERNAL_CUSTOM_TYPE &&\n\t\t\tentry.customType !== HOOK_EXECUTION_CUSTOM_TYPE\n\t\t);\n\t}\n\tif (entry.type === \"compaction\") return entry.id === compactionId && entry.summary.length > 0;\n\tif (entry.type === \"branch_summary\") return true;\n\tif (entry.type !== \"message\") return false;\n\tconst message = entry.message;\n\tif (message.role === \"bashExecution\") return !message.excludeFromContext;\n\tif (message.role === \"custom\") {\n\t\treturn (\n\t\t\tmessage.customType !== STRUCTURED_RESPONSE_INTERNAL_CUSTOM_TYPE &&\n\t\t\tmessage.customType !== HOOK_EXECUTION_CUSTOM_TYPE\n\t\t);\n\t}\n\tif (message.role === \"assistant\") {\n\t\treturn !message.content.some((block) => block.type === \"toolCall\" && block.id === toolCallId);\n\t}\n\treturn true;\n}\n\n/** Collect entries in model-context order, excluding the currently executing tool call. */\nexport function getCompressibleEntries(session: ReadonlySession, toolCallId: string): SessionEntry[] {\n\tconst path = session.getBranch();\n\tconst compaction = getLatestCompactionEntry(path);\n\treturn projectSessionContextEntries(path).filter((entry) => isContextEntry(entry, compaction?.id, toolCallId));\n}\n\nfunction hasUnmatchedToolCall(entries: SessionEntry[]): boolean {\n\tconst pending = new Set<string>();\n\tfor (const entry of entries) {\n\t\tif (entry.type !== \"message\") continue;\n\t\tif (entry.message.role === \"assistant\") {\n\t\t\tfor (const block of entry.message.content) {\n\t\t\t\tif (block.type === \"toolCall\") pending.add(block.id);\n\t\t\t}\n\t\t} else if (entry.message.role === \"toolResult\") {\n\t\t\tpending.delete(entry.message.toolCallId);\n\t\t}\n\t}\n\treturn pending.size > 0;\n}\n\nfunction validateCompressionRange(entries: SessionEntry[], startEntryId: string, endEntryId?: string): void {\n\tconst startIndex = entries.findIndex((entry) => entry.id === startEntryId);\n\tif (startIndex < 0) throw new Error(\"startEntryId must be a message in the current model context.\");\n\tconst endIndex = endEntryId ? entries.findIndex((entry) => entry.id === endEntryId) : entries.length - 1;\n\tif (endIndex < 0) throw new Error(\"endEntryId must be a message in the current model context.\");\n\tif (endIndex < startIndex) throw new Error(\"endEntryId must not precede startEntryId.\");\n\tconst start = entries[startIndex];\n\tif (start.type === \"message\" && start.message.role === \"toolResult\") {\n\t\tthrow new Error(\"Cannot start compression at a tool result; start at its assistant tool call instead.\");\n\t}\n\tif (hasUnmatchedToolCall(entries.slice(0, startIndex))) {\n\t\tthrow new Error(\"Cannot leave an unmatched tool call in the preserved prefix; start at its assistant message.\");\n\t}\n\tif (endIndex - startIndex + 1 < 2)\n\t\tthrow new Error(\"compress_context requires at least two messages in the selected range.\");\n\tif (hasUnmatchedToolCall(entries.slice(startIndex, endIndex + 1))) {\n\t\tthrow new Error(\"Cannot split a tool call from its result; include all results in the selected range.\");\n\t}\n}\n\n/** Validate a detector suggestion against the live branch, returning a reason for a corrective retry. */\nexport function getSuggestedCompressionRangeError(\n\tsession: ReadonlySession,\n\tstartEntryId: string,\n\tendEntryId: string,\n): string | undefined {\n\ttry {\n\t\tvalidateCompressionRange(getCompressibleEntries(session, \"\"), startEntryId, endEntryId);\n\t\treturn undefined;\n\t} catch (error) {\n\t\treturn error instanceof Error ? error.message : \"Invalid range.\";\n\t}\n}\n\n/** Validate an advisory against the current branch before showing it to the primary agent. */\nexport function isValidSuggestedCompressionRange(\n\tsession: ReadonlySession,\n\tstartEntryId: string,\n\tendEntryId: string,\n): boolean {\n\treturn getSuggestedCompressionRangeError(session, startEntryId, endEntryId) === undefined;\n}\n\nexport function createCompressContextToolDefinition(\n\tsession: ReadonlySession,\n\tschedule: (request: PendingContextCompression) => void,\n): ToolDefinition<typeof schema> {\n\treturn {\n\t\tname: \"compress_context\",\n\t\tlabel: \"compress_context\",\n\t\tdescription:\n\t\t\t\"Replace at least two messages from startEntryId through optional inclusive endEntryId with your own summary. endEntryId must be before the current user request; do not use the current user's ID from context metadata as the end. Omit endEntryId to compress through the last entry before that request. The earlier prefix, current request, tool call, result, and any later messages remain in order. Use a user or assistant tool-call entry ID from model-only context metadata for the start, not a tool-result ID.\",\n\t\tpromptSnippet: \"Summarize a bounded range or the active session tail\",\n\t\tpromptGuidelines: [\n\t\t\t\"Pass startEntryId and a non-empty summary; add endEntryId to retain later messages. Keep tool calls paired with their results and preserve important decisions.\",\n\t\t],\n\t\tparameters: schema,\n\t\texecutionMode: \"sequential\",\n\t\tasync execute(toolCallId, { startEntryId, endEntryId, summary }: CompressContextInput, signal) {\n\t\t\tabortIf(signal);\n\t\t\tif (!startEntryId || !summary.trim()) {\n\t\t\t\tthrow new Error(\"Provide startEntryId and a non-empty summary to compress.\");\n\t\t\t}\n\t\t\tconst assistant = session.getLeafEntry();\n\t\t\tconst branch = session.getBranch();\n\t\t\tconst isCurrentCall =\n\t\t\t\tassistant?.type === \"message\" &&\n\t\t\t\tassistant.message.role === \"assistant\" &&\n\t\t\t\tassistant.message.content.some((block) => block.type === \"toolCall\" && block.id === toolCallId);\n\t\t\tconst triggerIndex = isCurrentCall\n\t\t\t\t? branch\n\t\t\t\t\t\t.slice(0, -1)\n\t\t\t\t\t\t.map((entry) => entry.type === \"message\" && entry.message.role === \"user\")\n\t\t\t\t\t\t.lastIndexOf(true)\n\t\t\t\t: -1;\n\t\t\tconst eligibleIds = new Set(branch.slice(0, triggerIndex).map((entry) => entry.id));\n\t\t\tif (endEntryId && triggerIndex >= 0 && endEntryId === branch[triggerIndex]?.id) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"endEntryId is the current user request; omit endEntryId to compress through the last entry before it.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst entries = getCompressibleEntries(session, toolCallId).filter(\n\t\t\t\t(entry) => triggerIndex < 0 || eligibleIds.has(entry.id),\n\t\t\t);\n\t\t\tvalidateCompressionRange(entries, startEntryId, endEntryId);\n\t\t\tif (\n\t\t\t\tassistant?.type !== \"message\" ||\n\t\t\t\tassistant.message.role !== \"assistant\" ||\n\t\t\t\tassistant.message.content.filter((block) => block.type === \"toolCall\").length !== 1 ||\n\t\t\t\t!assistant.message.content.some((block) => block.type === \"toolCall\" && block.id === toolCallId)\n\t\t\t)\n\t\t\t\tthrow new Error(\"compress_context must be the only tool call in its assistant message.\");\n\t\t\tabortIf(signal);\n\t\t\tschedule({ toolCallId, startEntryId, endEntryId, summary: summary.trim(), assistantEntryId: assistant.id });\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Compression complete. Continue with the current request.\" }],\n\t\t\t\tdetails: undefined,\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"compress-context.d.ts","sourceRoot":"","sources":["../../../src/core/tools/compress-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAI7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,QAAA,MAAM,MAAM;;;;EAYX,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,OAAO,MAAM,CAAC,CAAC;AACzD,MAAM,WAAW,yBAAyB;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;CACzB;AA0BD,2FAA2F;AAC3F,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,GAAG,YAAY,EAAE,CAInG;AAqCD,yGAAyG;AACzG,wBAAgB,iCAAiC,CAChD,OAAO,EAAE,eAAe,EACxB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GAChB,MAAM,GAAG,SAAS,CAOpB;AAED,8FAA8F;AAC9F,wBAAgB,gCAAgC,CAC/C,OAAO,EAAE,eAAe,EACxB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GAChB,OAAO,CAET;AAED,wBAAgB,mCAAmC,CAClD,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,CAAC,OAAO,EAAE,yBAAyB,KAAK,IAAI,GACpD,cAAc,CAAC,OAAO,MAAM,CAAC,CAsD/B"}
@@ -1 +1 @@
1
- {"version":3,"file":"compress-context.js","sourceRoot":"","sources":["../../../src/core/tools/compress-context.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Static } from \"typebox\";\nimport { Type } from \"typebox\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport { HOOK_EXECUTION_CUSTOM_TYPE } from \"../hooks/types.ts\";\nimport { STRUCTURED_RESPONSE_INTERNAL_CUSTOM_TYPE } from \"../messages.ts\";\nimport { getLatestCompactionEntry, projectSessionContextEntries } from \"../session/context.ts\";\nimport type { ReadonlySession } from \"../session/session.ts\";\nimport type { SessionEntry } from \"../session/types.ts\";\nimport { abortIf } from \"./runtime.ts\";\n\nconst schema = Type.Object(\n\t{\n\t\tstartEntryId: Type.String({ description: \"ID of the first message to replace\" }),\n\t\tendEntryId: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Inclusive last message to replace; must precede the current user request. Omit to compress through the last eligible entry.\",\n\t\t\t}),\n\t\t),\n\t\tsummary: Type.String({ description: \"Replacement context for the selected range\" }),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type CompressContextInput = Static<typeof schema>;\nexport interface PendingContextCompression {\n\ttoolCallId: string;\n\tstartEntryId: string;\n\tendEntryId?: string;\n\tsummary: string;\n\tassistantEntryId: string;\n}\n\nfunction isContextEntry(entry: SessionEntry, compactionId: string | undefined, toolCallId: string): boolean {\n\tif (entry.type === \"custom_message\") {\n\t\treturn (\n\t\t\tentry.customType !== STRUCTURED_RESPONSE_INTERNAL_CUSTOM_TYPE &&\n\t\t\tentry.customType !== HOOK_EXECUTION_CUSTOM_TYPE\n\t\t);\n\t}\n\tif (entry.type === \"compaction\") return entry.id === compactionId && entry.summary.length > 0;\n\tif (entry.type === \"branch_summary\") return true;\n\tif (entry.type !== \"message\") return false;\n\tconst message = entry.message;\n\tif (message.role === \"bashExecution\") return !message.excludeFromContext;\n\tif (message.role === \"custom\") {\n\t\treturn (\n\t\t\tmessage.customType !== STRUCTURED_RESPONSE_INTERNAL_CUSTOM_TYPE &&\n\t\t\tmessage.customType !== HOOK_EXECUTION_CUSTOM_TYPE\n\t\t);\n\t}\n\tif (message.role === \"assistant\") {\n\t\treturn !message.content.some((block) => block.type === \"toolCall\" && block.id === toolCallId);\n\t}\n\treturn true;\n}\n\n/** Collect entries in model-context order, excluding the currently executing tool call. */\nexport function getCompressibleEntries(session: ReadonlySession, toolCallId: string): SessionEntry[] {\n\tconst path = session.getBranch();\n\tconst compaction = getLatestCompactionEntry(path);\n\treturn projectSessionContextEntries(path).filter((entry) => isContextEntry(entry, compaction?.id, toolCallId));\n}\n\nfunction hasUnmatchedToolCall(entries: SessionEntry[]): boolean {\n\tconst pending = new Set<string>();\n\tfor (const entry of entries) {\n\t\tif (entry.type !== \"message\") continue;\n\t\tif (entry.message.role === \"assistant\") {\n\t\t\tfor (const block of entry.message.content) {\n\t\t\t\tif (block.type === \"toolCall\") pending.add(block.id);\n\t\t\t}\n\t\t} else if (entry.message.role === \"toolResult\") {\n\t\t\tpending.delete(entry.message.toolCallId);\n\t\t}\n\t}\n\treturn pending.size > 0;\n}\n\nfunction validateCompressionRange(entries: SessionEntry[], startEntryId: string, endEntryId?: string): void {\n\tconst startIndex = entries.findIndex((entry) => entry.id === startEntryId);\n\tif (startIndex < 0) throw new Error(\"startEntryId must be a message in the current model context.\");\n\tconst endIndex = endEntryId ? entries.findIndex((entry) => entry.id === endEntryId) : entries.length - 1;\n\tif (endIndex < 0) throw new Error(\"endEntryId must be a message in the current model context.\");\n\tif (endIndex < startIndex) throw new Error(\"endEntryId must not precede startEntryId.\");\n\tconst start = entries[startIndex];\n\tif (start.type === \"message\" && start.message.role === \"toolResult\") {\n\t\tthrow new Error(\"Cannot start compression at a tool result; start at its assistant tool call instead.\");\n\t}\n\tif (hasUnmatchedToolCall(entries.slice(0, startIndex))) {\n\t\tthrow new Error(\"Cannot leave an unmatched tool call in the preserved prefix; start at its assistant message.\");\n\t}\n\tif (endIndex - startIndex + 1 < 2)\n\t\tthrow new Error(\"compress_context requires at least two messages in the selected range.\");\n\tif (hasUnmatchedToolCall(entries.slice(startIndex, endIndex + 1))) {\n\t\tthrow new Error(\"Cannot split a tool call from its result; include all results in the selected range.\");\n\t}\n}\n\n/** Validate a detector suggestion against the live branch, returning a reason for a corrective retry. */\nexport function getSuggestedCompressionRangeError(\n\tsession: ReadonlySession,\n\tstartEntryId: string,\n\tendEntryId: string,\n): string | undefined {\n\ttry {\n\t\tvalidateCompressionRange(getCompressibleEntries(session, \"\"), startEntryId, endEntryId);\n\t\treturn undefined;\n\t} catch (error) {\n\t\treturn error instanceof Error ? error.message : \"Invalid range.\";\n\t}\n}\n\n/** Validate an advisory against the current branch before showing it to the primary agent. */\nexport function isValidSuggestedCompressionRange(\n\tsession: ReadonlySession,\n\tstartEntryId: string,\n\tendEntryId: string,\n): boolean {\n\treturn getSuggestedCompressionRangeError(session, startEntryId, endEntryId) === undefined;\n}\n\nexport function createCompressContextToolDefinition(\n\tsession: ReadonlySession,\n\tschedule: (request: PendingContextCompression) => void,\n): ToolDefinition<typeof schema> {\n\treturn {\n\t\tname: \"compress_context\",\n\t\tlabel: \"compress_context\",\n\t\tdescription:\n\t\t\t\"Replace at least two messages from startEntryId through optional inclusive endEntryId with your own summary. endEntryId must be before the current user request; do not use the current user's ID from context metadata as the end. Omit endEntryId to compress through the last entry before that request. The earlier prefix, current request, tool call, result, and any later messages remain in order. Use a user or assistant tool-call entry ID from model-only context metadata for the start, not a tool-result ID.\",\n\t\tpromptSnippet: \"Summarize a bounded range or the active session tail\",\n\t\tpromptGuidelines: [\n\t\t\t\"Pass startEntryId and a non-empty summary; add endEntryId to retain later messages. Keep tool calls paired with their results and preserve important decisions.\",\n\t\t],\n\t\tparameters: schema,\n\t\texecutionMode: \"sequential\",\n\t\tasync execute(toolCallId, { startEntryId, endEntryId, summary }: CompressContextInput, signal) {\n\t\t\tabortIf(signal);\n\t\t\tif (!startEntryId || !summary.trim()) {\n\t\t\t\tthrow new Error(\"Provide startEntryId and a non-empty summary to compress.\");\n\t\t\t}\n\t\t\tconst assistant = session.getLeafEntry();\n\t\t\tconst branch = session.getBranch();\n\t\t\tconst isCurrentCall =\n\t\t\t\tassistant?.type === \"message\" &&\n\t\t\t\tassistant.message.role === \"assistant\" &&\n\t\t\t\tassistant.message.content.some((block) => block.type === \"toolCall\" && block.id === toolCallId);\n\t\t\tconst triggerIndex = isCurrentCall\n\t\t\t\t? branch\n\t\t\t\t\t\t.slice(0, -1)\n\t\t\t\t\t\t.map((entry) => entry.type === \"message\" && entry.message.role === \"user\")\n\t\t\t\t\t\t.lastIndexOf(true)\n\t\t\t\t: -1;\n\t\t\tconst eligibleIds = new Set(branch.slice(0, triggerIndex).map((entry) => entry.id));\n\t\t\tif (endEntryId && triggerIndex >= 0 && endEntryId === branch[triggerIndex]?.id) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"endEntryId is the current user request; omit endEntryId to compress through the last entry before it.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst entries = getCompressibleEntries(session, toolCallId).filter(\n\t\t\t\t(entry) => triggerIndex < 0 || eligibleIds.has(entry.id),\n\t\t\t);\n\t\t\tvalidateCompressionRange(entries, startEntryId, endEntryId);\n\t\t\tif (\n\t\t\t\tassistant?.type !== \"message\" ||\n\t\t\t\tassistant.message.role !== \"assistant\" ||\n\t\t\t\tassistant.message.content.filter((block) => block.type === \"toolCall\").length !== 1 ||\n\t\t\t\t!assistant.message.content.some((block) => block.type === \"toolCall\" && block.id === toolCallId)\n\t\t\t)\n\t\t\t\tthrow new Error(\"compress_context must be the only tool call in its assistant message.\");\n\t\t\tabortIf(signal);\n\t\t\tschedule({ toolCallId, startEntryId, endEntryId, summary: summary.trim(), assistantEntryId: assistant.id });\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Compression complete. Continue with the current request.\" }],\n\t\t\t\tdetails: undefined,\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"compress-context.js","sourceRoot":"","sources":["../../../src/core/tools/compress-context.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Static } from \"typebox\";\nimport { Type } from \"typebox\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport { HOOK_EXECUTION_CUSTOM_TYPE } from \"../hooks/types.ts\";\nimport { STRUCTURED_RESPONSE_INTERNAL_CUSTOM_TYPE } from \"../messages.ts\";\nimport { getLatestCompactionEntry, projectSessionContextEntries } from \"../session/context.ts\";\nimport type { ReadonlySession } from \"../session/session.ts\";\nimport type { SessionEntry } from \"../session/types.ts\";\nimport { abortIf } from \"./runtime.ts\";\n\nconst schema = Type.Object(\n\t{\n\t\tstartEntryId: Type.String({ description: \"ID of the first message to replace\" }),\n\t\tendEntryId: Type.Optional(\n\t\t\tType.String({\n\t\t\t\tdescription:\n\t\t\t\t\t\"Inclusive last message to replace; must precede the current user request. Omit to compress through the last eligible entry.\",\n\t\t\t}),\n\t\t),\n\t\tsummary: Type.String({ description: \"Replacement context for the selected range\" }),\n\t},\n\t{ additionalProperties: false },\n);\n\nexport type CompressContextInput = Static<typeof schema>;\nexport interface PendingContextCompression {\n\ttoolCallId: string;\n\tstartEntryId: string;\n\tendEntryId?: string;\n\tsummary: string;\n\tassistantEntryId: string;\n}\n\nfunction isContextEntry(entry: SessionEntry, compactionId: string | undefined, toolCallId: string): boolean {\n\tif (entry.type === \"custom_message\") {\n\t\treturn (\n\t\t\tentry.customType !== STRUCTURED_RESPONSE_INTERNAL_CUSTOM_TYPE &&\n\t\t\tentry.customType !== HOOK_EXECUTION_CUSTOM_TYPE\n\t\t);\n\t}\n\tif (entry.type === \"compaction\") return entry.id === compactionId && entry.summary.length > 0;\n\tif (entry.type === \"branch_summary\") return true;\n\tif (entry.type !== \"message\") return false;\n\tconst message = entry.message;\n\tif (message.role === \"bashExecution\") return !message.excludeFromContext;\n\tif (message.role === \"custom\") {\n\t\treturn (\n\t\t\tmessage.customType !== STRUCTURED_RESPONSE_INTERNAL_CUSTOM_TYPE &&\n\t\t\tmessage.customType !== HOOK_EXECUTION_CUSTOM_TYPE\n\t\t);\n\t}\n\tif (message.role === \"assistant\") {\n\t\treturn !message.content.some((block) => block.type === \"toolCall\" && block.id === toolCallId);\n\t}\n\treturn true;\n}\n\n/** Collect entries in model-context order, excluding the currently executing tool call. */\nexport function getCompressibleEntries(session: ReadonlySession, toolCallId: string): SessionEntry[] {\n\tconst path = session.getBranch();\n\tconst compaction = getLatestCompactionEntry(path);\n\treturn projectSessionContextEntries(path).filter((entry) => isContextEntry(entry, compaction?.id, toolCallId));\n}\n\nfunction hasUnmatchedToolCall(entries: SessionEntry[]): boolean {\n\tconst pending = new Set<string>();\n\tfor (const entry of entries) {\n\t\tif (entry.type !== \"message\") continue;\n\t\tif (entry.message.role === \"assistant\") {\n\t\t\tfor (const block of entry.message.content) {\n\t\t\t\tif (block.type === \"toolCall\") pending.add(block.id);\n\t\t\t}\n\t\t} else if (entry.message.role === \"toolResult\") {\n\t\t\tpending.delete(entry.message.toolCallId);\n\t\t}\n\t}\n\treturn pending.size > 0;\n}\n\nfunction validateCompressionRange(entries: SessionEntry[], startEntryId: string, endEntryId?: string): void {\n\tconst startIndex = entries.findIndex((entry) => entry.id === startEntryId);\n\tif (startIndex < 0) throw new Error(\"startEntryId must be a message in the current model context.\");\n\tconst endIndex = endEntryId ? entries.findIndex((entry) => entry.id === endEntryId) : entries.length - 1;\n\tif (endIndex < 0) throw new Error(\"endEntryId must be a message in the current model context.\");\n\tif (endIndex < startIndex) throw new Error(\"endEntryId must not precede startEntryId.\");\n\tconst start = entries[startIndex];\n\tif (start.type === \"message\" && start.message.role === \"toolResult\") {\n\t\tthrow new Error(\"Cannot start compression at a tool result; start at its assistant tool call instead.\");\n\t}\n\tif (hasUnmatchedToolCall(entries.slice(0, startIndex))) {\n\t\tthrow new Error(\"Cannot leave an unmatched tool call in the preserved prefix; start at its assistant message.\");\n\t}\n\tif (endIndex - startIndex + 1 < 2)\n\t\tthrow new Error(\"compress_context requires at least two messages in the selected range.\");\n\tif (hasUnmatchedToolCall(entries.slice(startIndex, endIndex + 1))) {\n\t\tthrow new Error(\"Cannot split a tool call from its result; include all results in the selected range.\");\n\t}\n}\n\n/** Validate a detector suggestion against the live branch, returning a reason for a corrective retry. */\nexport function getSuggestedCompressionRangeError(\n\tsession: ReadonlySession,\n\tstartEntryId: string,\n\tendEntryId: string,\n): string | undefined {\n\ttry {\n\t\tvalidateCompressionRange(getCompressibleEntries(session, \"\"), startEntryId, endEntryId);\n\t\treturn undefined;\n\t} catch (error) {\n\t\treturn error instanceof Error ? error.message : \"Invalid range.\";\n\t}\n}\n\n/** Validate an advisory against the current branch before showing it to the primary agent. */\nexport function isValidSuggestedCompressionRange(\n\tsession: ReadonlySession,\n\tstartEntryId: string,\n\tendEntryId: string,\n): boolean {\n\treturn getSuggestedCompressionRangeError(session, startEntryId, endEntryId) === undefined;\n}\n\nexport function createCompressContextToolDefinition(\n\tsession: ReadonlySession,\n\tschedule: (request: PendingContextCompression) => void,\n): ToolDefinition<typeof schema> {\n\treturn {\n\t\tname: \"compress_context\",\n\t\tlabel: \"compress_context\",\n\t\tdescription:\n\t\t\t\"Replace at least two messages from startEntryId through optional inclusive endEntryId with your own summary. endEntryId must be before the current user request; do not use the current user's ID from context metadata as the end. Omit endEntryId to compress through the last entry before that request. The earlier prefix, current request, tool call, result, and any later messages remain in order. Use a user or assistant tool-call entry ID from model-only context metadata for the start, not a tool-result ID.\",\n\t\tpromptSnippet: \"Summarize a bounded range or the active session tail\",\n\t\tpromptGuidelines: [\n\t\t\t\"Pass startEntryId and a non-empty summary; add endEntryId to retain later messages. Keep tool calls paired with their results and preserve important decisions.\",\n\t\t],\n\t\tparameters: schema,\n\t\texecutionMode: \"sequential\",\n\t\tasync execute(toolCallId, { startEntryId, endEntryId, summary }: CompressContextInput, signal) {\n\t\t\tabortIf(signal);\n\t\t\tif (!startEntryId || !summary.trim()) {\n\t\t\t\tthrow new Error(\"Provide startEntryId and a non-empty summary to compress.\");\n\t\t\t}\n\t\t\tconst assistant = session.getLeafEntry();\n\t\t\tconst branch = session.getBranch();\n\t\t\tconst isCurrentCall =\n\t\t\t\tassistant?.type === \"message\" &&\n\t\t\t\tassistant.message.role === \"assistant\" &&\n\t\t\t\tassistant.message.content.some((block) => block.type === \"toolCall\" && block.id === toolCallId);\n\t\t\tconst triggerIndex = isCurrentCall\n\t\t\t\t? branch\n\t\t\t\t\t\t.slice(0, -1)\n\t\t\t\t\t\t.map((entry) => entry.type === \"message\" && entry.message.role === \"user\")\n\t\t\t\t\t\t.lastIndexOf(true)\n\t\t\t\t: -1;\n\t\t\tconst eligibleIds = new Set(branch.slice(0, triggerIndex).map((entry) => entry.id));\n\t\t\tif (endEntryId && triggerIndex >= 0 && endEntryId === branch[triggerIndex]?.id) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"endEntryId is the current user request; omit endEntryId to compress through the last entry before it.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst entries = getCompressibleEntries(session, toolCallId).filter(\n\t\t\t\t(entry) => triggerIndex < 0 || eligibleIds.has(entry.id),\n\t\t\t);\n\t\t\tvalidateCompressionRange(entries, startEntryId, endEntryId);\n\t\t\tif (\n\t\t\t\tassistant?.type !== \"message\" ||\n\t\t\t\tassistant.message.role !== \"assistant\" ||\n\t\t\t\tassistant.message.content.filter((block) => block.type === \"toolCall\").length !== 1 ||\n\t\t\t\t!assistant.message.content.some((block) => block.type === \"toolCall\" && block.id === toolCallId)\n\t\t\t)\n\t\t\t\tthrow new Error(\"compress_context must be the only tool call in its assistant message.\");\n\t\t\tabortIf(signal);\n\t\t\tschedule({ toolCallId, startEntryId, endEntryId, summary: summary.trim(), assistantEntryId: assistant.id });\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Compression complete. Continue with the current request.\" }],\n\t\t\t\tdetails: undefined,\n\t\t\t};\n\t\t},\n\t};\n}\n"]}