@greppleai/grip 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (569) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +2 -2
  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.map +1 -1
  27. package/dist/core/agent-session.d.ts +27 -0
  28. package/dist/core/agent-session.d.ts.map +1 -1
  29. package/dist/core/agent-session.js +117 -152
  30. package/dist/core/agent-session.js.map +1 -1
  31. package/dist/core/auth-guidance.d.ts.map +1 -1
  32. package/dist/core/auth-guidance.js.map +1 -1
  33. package/dist/core/auth-storage.d.ts +4 -0
  34. package/dist/core/auth-storage.d.ts.map +1 -1
  35. package/dist/core/auth-storage.js +6 -11
  36. package/dist/core/auth-storage.js.map +1 -1
  37. package/dist/core/bash-executor.d.ts.map +1 -1
  38. package/dist/core/bash-executor.js +19 -23
  39. package/dist/core/bash-executor.js.map +1 -1
  40. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  41. package/dist/core/compaction/branch-summarization.js.map +1 -1
  42. package/dist/core/compaction/compaction.d.ts.map +1 -1
  43. package/dist/core/compaction/compaction.js.map +1 -1
  44. package/dist/core/compaction/compression-detection-ledger.d.ts.map +1 -1
  45. package/dist/core/compaction/compression-detection-ledger.js.map +1 -1
  46. package/dist/core/compaction/compression-detector.d.ts +1 -0
  47. package/dist/core/compaction/compression-detector.d.ts.map +1 -1
  48. package/dist/core/compaction/compression-detector.js +10 -21
  49. package/dist/core/compaction/compression-detector.js.map +1 -1
  50. package/dist/core/compaction/compression-economics.d.ts.map +1 -1
  51. package/dist/core/compaction/compression-economics.js.map +1 -1
  52. package/dist/core/compaction/utils.d.ts.map +1 -1
  53. package/dist/core/compaction/utils.js.map +1 -1
  54. package/dist/core/defaults.d.ts.map +1 -1
  55. package/dist/core/diagnostics.d.ts.map +1 -1
  56. package/dist/core/event-bus.d.ts.map +1 -1
  57. package/dist/core/event-bus.js.map +1 -1
  58. package/dist/core/exec.d.ts.map +1 -1
  59. package/dist/core/exec.js.map +1 -1
  60. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
  61. package/dist/core/export-html/ansi-to-html.js.map +1 -1
  62. package/dist/core/export-html/index.d.ts.map +1 -1
  63. package/dist/core/export-html/index.js.map +1 -1
  64. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  65. package/dist/core/export-html/tool-renderer.js.map +1 -1
  66. package/dist/core/extensions/loader.d.ts.map +1 -1
  67. package/dist/core/extensions/loader.js.map +1 -1
  68. package/dist/core/extensions/runner.d.ts.map +1 -1
  69. package/dist/core/extensions/runner.js +18 -30
  70. package/dist/core/extensions/runner.js.map +1 -1
  71. package/dist/core/extensions/types.d.ts.map +1 -1
  72. package/dist/core/extensions/types.js.map +1 -1
  73. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  74. package/dist/core/extensions/wrapper.js.map +1 -1
  75. package/dist/core/footer-data-provider.d.ts.map +1 -1
  76. package/dist/core/footer-data-provider.js +15 -16
  77. package/dist/core/footer-data-provider.js.map +1 -1
  78. package/dist/core/grip-agent.d.ts.map +1 -1
  79. package/dist/core/grip-agent.js +11 -23
  80. package/dist/core/grip-agent.js.map +1 -1
  81. package/dist/core/grip-manifest.d.ts.map +1 -1
  82. package/dist/core/grip-manifest.js.map +1 -1
  83. package/dist/core/hooks/aggregate.d.ts.map +1 -1
  84. package/dist/core/hooks/aggregate.js.map +1 -1
  85. package/dist/core/hooks/config.d.ts.map +1 -1
  86. package/dist/core/hooks/config.js.map +1 -1
  87. package/dist/core/hooks/executor.d.ts.map +1 -1
  88. package/dist/core/hooks/executor.js.map +1 -1
  89. package/dist/core/hooks/index.d.ts.map +1 -1
  90. package/dist/core/hooks/index.js.map +1 -1
  91. package/dist/core/hooks/matcher.d.ts.map +1 -1
  92. package/dist/core/hooks/matcher.js.map +1 -1
  93. package/dist/core/hooks/trust-store.d.ts.map +1 -1
  94. package/dist/core/hooks/trust-store.js +0 -3
  95. package/dist/core/hooks/trust-store.js.map +1 -1
  96. package/dist/core/hooks/types.d.ts.map +1 -1
  97. package/dist/core/hooks/types.js.map +1 -1
  98. package/dist/core/http-dispatcher.d.ts.map +1 -1
  99. package/dist/core/http-dispatcher.js.map +1 -1
  100. package/dist/core/instruction-resource-loader.d.ts.map +1 -1
  101. package/dist/core/instruction-resource-loader.js +0 -3
  102. package/dist/core/instruction-resource-loader.js.map +1 -1
  103. package/dist/core/keybindings.d.ts.map +1 -1
  104. package/dist/core/keybindings.js +0 -1
  105. package/dist/core/keybindings.js.map +1 -1
  106. package/dist/core/lsp/abort.d.ts.map +1 -1
  107. package/dist/core/lsp/abort.js.map +1 -1
  108. package/dist/core/lsp/client.d.ts.map +1 -1
  109. package/dist/core/lsp/client.js +8 -22
  110. package/dist/core/lsp/client.js.map +1 -1
  111. package/dist/core/lsp/config-loader.d.ts.map +1 -1
  112. package/dist/core/lsp/config-loader.js.map +1 -1
  113. package/dist/core/lsp/config.d.ts.map +1 -1
  114. package/dist/core/lsp/config.js.map +1 -1
  115. package/dist/core/lsp/diagnostics.d.ts.map +1 -1
  116. package/dist/core/lsp/diagnostics.js.map +1 -1
  117. package/dist/core/lsp/file-sync.d.ts.map +1 -1
  118. package/dist/core/lsp/file-sync.js +7 -9
  119. package/dist/core/lsp/file-sync.js.map +1 -1
  120. package/dist/core/lsp/integration.d.ts.map +1 -1
  121. package/dist/core/lsp/integration.js.map +1 -1
  122. package/dist/core/lsp/language-map.d.ts.map +1 -1
  123. package/dist/core/lsp/language-map.js +2 -7
  124. package/dist/core/lsp/language-map.js.map +1 -1
  125. package/dist/core/lsp/manager.d.ts.map +1 -1
  126. package/dist/core/lsp/manager.js +18 -29
  127. package/dist/core/lsp/manager.js.map +1 -1
  128. package/dist/core/lsp/navigation.d.ts.map +1 -1
  129. package/dist/core/lsp/navigation.js.map +1 -1
  130. package/dist/core/lsp/portable-path.d.ts.map +1 -1
  131. package/dist/core/lsp/portable-path.js.map +1 -1
  132. package/dist/core/lsp/refactor.d.ts.map +1 -1
  133. package/dist/core/lsp/refactor.js.map +1 -1
  134. package/dist/core/lsp/transport.d.ts.map +1 -1
  135. package/dist/core/lsp/transport.js.map +1 -1
  136. package/dist/core/messages.d.ts.map +1 -1
  137. package/dist/core/messages.js.map +1 -1
  138. package/dist/core/model-registry.d.ts.map +1 -1
  139. package/dist/core/model-registry.js +5 -7
  140. package/dist/core/model-registry.js.map +1 -1
  141. package/dist/core/model-resolver.d.ts.map +1 -1
  142. package/dist/core/model-resolver.js.map +1 -1
  143. package/dist/core/output-guard.d.ts.map +1 -1
  144. package/dist/core/output-guard.js.map +1 -1
  145. package/dist/core/package-manager.d.ts.map +1 -1
  146. package/dist/core/package-manager.js +0 -6
  147. package/dist/core/package-manager.js.map +1 -1
  148. package/dist/core/prompt-templates.d.ts.map +1 -1
  149. package/dist/core/prompt-templates.js.map +1 -1
  150. package/dist/core/provider-display-names.d.ts.map +1 -1
  151. package/dist/core/remote-workspace-protocol/contract.d.ts.map +1 -1
  152. package/dist/core/remote-workspace-protocol/contract.js +4 -2
  153. package/dist/core/remote-workspace-protocol/contract.js.map +1 -1
  154. package/dist/core/remote-workspace-protocol/guest-shared-client.d.ts.map +1 -1
  155. package/dist/core/remote-workspace-protocol/guest-shared-client.js +1 -5
  156. package/dist/core/remote-workspace-protocol/guest-shared-client.js.map +1 -1
  157. package/dist/core/remote-workspace-protocol/guest-shared-outbound-scheduler.d.ts.map +1 -1
  158. package/dist/core/remote-workspace-protocol/guest-shared-outbound-scheduler.js +5 -10
  159. package/dist/core/remote-workspace-protocol/guest-shared-outbound-scheduler.js.map +1 -1
  160. package/dist/core/remote-workspace-protocol/guest-shared-uplink.d.ts.map +1 -1
  161. package/dist/core/remote-workspace-protocol/guest-shared-uplink.js +2 -9
  162. package/dist/core/remote-workspace-protocol/guest-shared-uplink.js.map +1 -1
  163. package/dist/core/remote-workspace-protocol/lima-owner-directory.d.ts.map +1 -1
  164. package/dist/core/remote-workspace-protocol/lima-owner-directory.js.map +1 -1
  165. package/dist/core/remote-workspace-protocol/lima-owner-lock.d.ts.map +1 -1
  166. package/dist/core/remote-workspace-protocol/lima-owner-lock.js.map +1 -1
  167. package/dist/core/remote-workspace-protocol/session.d.ts.map +1 -1
  168. package/dist/core/remote-workspace-protocol/session.js +27 -65
  169. package/dist/core/remote-workspace-protocol/session.js.map +1 -1
  170. package/dist/core/remote-workspace-protocol/shared-transport.d.ts.map +1 -1
  171. package/dist/core/remote-workspace-protocol/shared-transport.js.map +1 -1
  172. package/dist/core/resolve-config-value.d.ts.map +1 -1
  173. package/dist/core/resolve-config-value.js.map +1 -1
  174. package/dist/core/resource-loader.d.ts.map +1 -1
  175. package/dist/core/resource-loader.js +0 -48
  176. package/dist/core/resource-loader.js.map +1 -1
  177. package/dist/core/rules.d.ts.map +1 -1
  178. package/dist/core/rules.js.map +1 -1
  179. package/dist/core/sandbox/command.d.ts.map +1 -1
  180. package/dist/core/sandbox/command.js.map +1 -1
  181. package/dist/core/sandbox/config.d.ts.map +1 -1
  182. package/dist/core/sandbox/config.js.map +1 -1
  183. package/dist/core/sandbox/lima-guest-binary.d.ts.map +1 -1
  184. package/dist/core/sandbox/lima-guest-binary.js.map +1 -1
  185. package/dist/core/sandbox/lima.d.ts +2 -0
  186. package/dist/core/sandbox/lima.d.ts.map +1 -1
  187. package/dist/core/sandbox/lima.js +9 -15
  188. package/dist/core/sandbox/lima.js.map +1 -1
  189. package/dist/core/sandbox/shared-lima-roots.d.ts.map +1 -1
  190. package/dist/core/sandbox/shared-lima-roots.js.map +1 -1
  191. package/dist/core/sandbox/update-shared-guest-binary.d.ts.map +1 -1
  192. package/dist/core/sandbox/update-shared-guest-binary.js.map +1 -1
  193. package/dist/core/session/constants.d.ts.map +1 -1
  194. package/dist/core/session/context-metadata.d.ts.map +1 -1
  195. package/dist/core/session/context-metadata.js.map +1 -1
  196. package/dist/core/session/context.d.ts.map +1 -1
  197. package/dist/core/session/context.js.map +1 -1
  198. package/dist/core/session/ids.d.ts.map +1 -1
  199. package/dist/core/session/ids.js.map +1 -1
  200. package/dist/core/session/in-memory-session-manager.d.ts.map +1 -1
  201. package/dist/core/session/in-memory-session-manager.js +0 -1
  202. package/dist/core/session/in-memory-session-manager.js.map +1 -1
  203. package/dist/core/session/in-memory-session.d.ts.map +1 -1
  204. package/dist/core/session/in-memory-session.js.map +1 -1
  205. package/dist/core/session/jsonl-errors.d.ts.map +1 -1
  206. package/dist/core/session/jsonl-errors.js +0 -11
  207. package/dist/core/session/jsonl-errors.js.map +1 -1
  208. package/dist/core/session/jsonl-helpers.d.ts.map +1 -1
  209. package/dist/core/session/jsonl-helpers.js.map +1 -1
  210. package/dist/core/session/local-session-manager.d.ts.map +1 -1
  211. package/dist/core/session/local-session-manager.js +4 -6
  212. package/dist/core/session/local-session-manager.js.map +1 -1
  213. package/dist/core/session/local-session.d.ts.map +1 -1
  214. package/dist/core/session/local-session.js.map +1 -1
  215. package/dist/core/session/migrations.d.ts.map +1 -1
  216. package/dist/core/session/migrations.js.map +1 -1
  217. package/dist/core/session/remote-session-client.d.ts.map +1 -1
  218. package/dist/core/session/remote-session-client.js +0 -6
  219. package/dist/core/session/remote-session-client.js.map +1 -1
  220. package/dist/core/session/remote-session-manager.d.ts.map +1 -1
  221. package/dist/core/session/remote-session-manager.js +0 -3
  222. package/dist/core/session/remote-session-manager.js.map +1 -1
  223. package/dist/core/session/remote-session.d.ts.map +1 -1
  224. package/dist/core/session/remote-session.js +0 -1
  225. package/dist/core/session/remote-session.js.map +1 -1
  226. package/dist/core/session/session-manager.d.ts.map +1 -1
  227. package/dist/core/session/session.d.ts.map +1 -1
  228. package/dist/core/session/session.js +1 -5
  229. package/dist/core/session/session.js.map +1 -1
  230. package/dist/core/session/stores/in-memory-session-store.d.ts.map +1 -1
  231. package/dist/core/session/stores/in-memory-session-store.js +7 -6
  232. package/dist/core/session/stores/in-memory-session-store.js.map +1 -1
  233. package/dist/core/session/stores/jsonl-session-store.d.ts.map +1 -1
  234. package/dist/core/session/stores/jsonl-session-store.js +6 -14
  235. package/dist/core/session/stores/jsonl-session-store.js.map +1 -1
  236. package/dist/core/session/stores/remote-session-store.d.ts.map +1 -1
  237. package/dist/core/session/stores/remote-session-store.js +3 -8
  238. package/dist/core/session/stores/remote-session-store.js.map +1 -1
  239. package/dist/core/session/stores/session-store.d.ts.map +1 -1
  240. package/dist/core/session/types.d.ts.map +1 -1
  241. package/dist/core/session/usage-ledger.d.ts.map +1 -1
  242. package/dist/core/session/usage-ledger.js.map +1 -1
  243. package/dist/core/session-cwd.d.ts.map +1 -1
  244. package/dist/core/session-cwd.js +0 -1
  245. package/dist/core/session-cwd.js.map +1 -1
  246. package/dist/core/settings-manager.d.ts.map +1 -1
  247. package/dist/core/settings-manager.js +9 -17
  248. package/dist/core/settings-manager.js.map +1 -1
  249. package/dist/core/skills.d.ts.map +1 -1
  250. package/dist/core/skills.js.map +1 -1
  251. package/dist/core/slash-commands.d.ts.map +1 -1
  252. package/dist/core/source-info.d.ts.map +1 -1
  253. package/dist/core/source-info.js.map +1 -1
  254. package/dist/core/system-prompt.d.ts.map +1 -1
  255. package/dist/core/system-prompt.js.map +1 -1
  256. package/dist/core/telemetry.d.ts.map +1 -1
  257. package/dist/core/telemetry.js.map +1 -1
  258. package/dist/core/timings.d.ts.map +1 -1
  259. package/dist/core/timings.js.map +1 -1
  260. package/dist/core/tools/bash.d.ts.map +1 -1
  261. package/dist/core/tools/bash.js +8 -5
  262. package/dist/core/tools/bash.js.map +1 -1
  263. package/dist/core/tools/compress-context.d.ts.map +1 -1
  264. package/dist/core/tools/compress-context.js.map +1 -1
  265. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  266. package/dist/core/tools/edit-diff.js.map +1 -1
  267. package/dist/core/tools/edit.d.ts.map +1 -1
  268. package/dist/core/tools/edit.js.map +1 -1
  269. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
  270. package/dist/core/tools/file-mutation-queue.js.map +1 -1
  271. package/dist/core/tools/find.d.ts.map +1 -1
  272. package/dist/core/tools/find.js.map +1 -1
  273. package/dist/core/tools/grep.d.ts.map +1 -1
  274. package/dist/core/tools/grep.js.map +1 -1
  275. package/dist/core/tools/hash-store.d.ts.map +1 -1
  276. package/dist/core/tools/hash-store.js.map +1 -1
  277. package/dist/core/tools/hashline/apply.d.ts.map +1 -1
  278. package/dist/core/tools/hashline/apply.js.map +1 -1
  279. package/dist/core/tools/hashline/hash.d.ts.map +1 -1
  280. package/dist/core/tools/hashline/hash.js.map +1 -1
  281. package/dist/core/tools/hashline/parse.d.ts.map +1 -1
  282. package/dist/core/tools/hashline/parse.js.map +1 -1
  283. package/dist/core/tools/hashline/resolve.d.ts.map +1 -1
  284. package/dist/core/tools/hashline/resolve.js.map +1 -1
  285. package/dist/core/tools/hashline-utils.d.ts.map +1 -1
  286. package/dist/core/tools/hashline-utils.js.map +1 -1
  287. package/dist/core/tools/index.d.ts.map +1 -1
  288. package/dist/core/tools/index.js.map +1 -1
  289. package/dist/core/tools/ls.d.ts.map +1 -1
  290. package/dist/core/tools/ls.js.map +1 -1
  291. package/dist/core/tools/operations.d.ts +5 -0
  292. package/dist/core/tools/operations.d.ts.map +1 -1
  293. package/dist/core/tools/operations.js +26 -24
  294. package/dist/core/tools/operations.js.map +1 -1
  295. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  296. package/dist/core/tools/output-accumulator.js +12 -18
  297. package/dist/core/tools/output-accumulator.js.map +1 -1
  298. package/dist/core/tools/path-utils.d.ts.map +1 -1
  299. package/dist/core/tools/path-utils.js.map +1 -1
  300. package/dist/core/tools/read.d.ts.map +1 -1
  301. package/dist/core/tools/read.js.map +1 -1
  302. package/dist/core/tools/render-utils.d.ts.map +1 -1
  303. package/dist/core/tools/render-utils.js.map +1 -1
  304. package/dist/core/tools/replace-diff.d.ts.map +1 -1
  305. package/dist/core/tools/replace-diff.js.map +1 -1
  306. package/dist/core/tools/replace-normalize.d.ts.map +1 -1
  307. package/dist/core/tools/replace-normalize.js.map +1 -1
  308. package/dist/core/tools/replace-render.d.ts +1 -1
  309. package/dist/core/tools/replace-render.d.ts.map +1 -1
  310. package/dist/core/tools/replace-render.js.map +1 -1
  311. package/dist/core/tools/runtime.d.ts.map +1 -1
  312. package/dist/core/tools/runtime.js.map +1 -1
  313. package/dist/core/tools/session-history.d.ts.map +1 -1
  314. package/dist/core/tools/session-history.js.map +1 -1
  315. package/dist/core/tools/subagent-agents.d.ts.map +1 -1
  316. package/dist/core/tools/subagent-agents.js.map +1 -1
  317. package/dist/core/tools/subagent.d.ts.map +1 -1
  318. package/dist/core/tools/subagent.js.map +1 -1
  319. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  320. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  321. package/dist/core/tools/truncate.d.ts.map +1 -1
  322. package/dist/core/tools/truncate.js.map +1 -1
  323. package/dist/core/tools/websearch.d.ts.map +1 -1
  324. package/dist/core/tools/websearch.js.map +1 -1
  325. package/dist/core/tools/workspace-tool-host.d.ts +1 -0
  326. package/dist/core/tools/workspace-tool-host.d.ts.map +1 -1
  327. package/dist/core/tools/workspace-tool-host.js +36 -22
  328. package/dist/core/tools/workspace-tool-host.js.map +1 -1
  329. package/dist/core/tools/write.d.ts.map +1 -1
  330. package/dist/core/tools/write.js +0 -1
  331. package/dist/core/tools/write.js.map +1 -1
  332. package/dist/core/workspace-identity.d.ts.map +1 -1
  333. package/dist/daemon/activity-budget.d.ts.map +1 -1
  334. package/dist/daemon/activity-budget.js +2 -3
  335. package/dist/daemon/activity-budget.js.map +1 -1
  336. package/dist/daemon/command.d.ts.map +1 -1
  337. package/dist/daemon/command.js.map +1 -1
  338. package/dist/daemon/config.d.ts +2 -0
  339. package/dist/daemon/config.d.ts.map +1 -1
  340. package/dist/daemon/config.js +4 -0
  341. package/dist/daemon/config.js.map +1 -1
  342. package/dist/daemon/help.d.ts.map +1 -1
  343. package/dist/daemon/help.js +4 -3
  344. package/dist/daemon/help.js.map +1 -1
  345. package/dist/daemon/lsp-config.d.ts.map +1 -1
  346. package/dist/daemon/lsp-config.js.map +1 -1
  347. package/dist/daemon/outbound-budget.d.ts.map +1 -1
  348. package/dist/daemon/outbound-budget.js +2 -4
  349. package/dist/daemon/outbound-budget.js.map +1 -1
  350. package/dist/daemon/security.d.ts.map +1 -1
  351. package/dist/daemon/security.js.map +1 -1
  352. package/dist/daemon/server.d.ts.map +1 -1
  353. package/dist/daemon/server.js.map +1 -1
  354. package/dist/daemon/shared-connection.d.ts.map +1 -1
  355. package/dist/daemon/shared-connection.js +10 -15
  356. package/dist/daemon/shared-connection.js.map +1 -1
  357. package/dist/daemon/shared-revision.d.ts.map +1 -1
  358. package/dist/daemon/shared-revision.js +2 -1
  359. package/dist/daemon/shared-revision.js.map +1 -1
  360. package/dist/daemon/shared-roots.d.ts.map +1 -1
  361. package/dist/daemon/shared-roots.js +0 -1
  362. package/dist/daemon/shared-roots.js.map +1 -1
  363. package/dist/daemon/workspace-runtime.d.ts +2 -0
  364. package/dist/daemon/workspace-runtime.d.ts.map +1 -1
  365. package/dist/daemon/workspace-runtime.js +43 -15
  366. package/dist/daemon/workspace-runtime.js.map +1 -1
  367. package/dist/index.d.ts.map +1 -1
  368. package/dist/main.d.ts.map +1 -1
  369. package/dist/main.js.map +1 -1
  370. package/dist/migrations.d.ts.map +1 -1
  371. package/dist/migrations.js.map +1 -1
  372. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  373. package/dist/modes/interactive/components/assistant-message.js +21 -17
  374. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  375. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  376. package/dist/modes/interactive/components/bash-execution.js +4 -9
  377. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  378. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  379. package/dist/modes/interactive/components/bordered-loader.js +0 -3
  380. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  381. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  382. package/dist/modes/interactive/components/branch-summary-message.js +1 -3
  383. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  384. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  385. package/dist/modes/interactive/components/compaction-summary-message.js +1 -3
  386. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  387. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  388. package/dist/modes/interactive/components/config-selector.js +6 -16
  389. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  390. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
  391. package/dist/modes/interactive/components/countdown-timer.js +0 -5
  392. package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
  393. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  394. package/dist/modes/interactive/components/custom-editor.js +1 -8
  395. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  396. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  397. package/dist/modes/interactive/components/custom-message.js +1 -6
  398. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  399. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  400. package/dist/modes/interactive/components/diff.js.map +1 -1
  401. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  402. package/dist/modes/interactive/components/dynamic-border.js +0 -1
  403. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  404. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  405. package/dist/modes/interactive/components/extension-editor.js +1 -7
  406. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  407. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  408. package/dist/modes/interactive/components/extension-input.js +2 -8
  409. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  410. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  411. package/dist/modes/interactive/components/extension-selector.js +1 -9
  412. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  413. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  414. package/dist/modes/interactive/components/footer.js +1 -3
  415. package/dist/modes/interactive/components/footer.js.map +1 -1
  416. package/dist/modes/interactive/components/hook-execution.d.ts.map +1 -1
  417. package/dist/modes/interactive/components/hook-execution.js +2 -5
  418. package/dist/modes/interactive/components/hook-execution.js.map +1 -1
  419. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  420. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  421. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  422. package/dist/modes/interactive/components/login-dialog.js +3 -9
  423. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  424. package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -1
  425. package/dist/modes/interactive/components/markdown-transform.js.map +1 -1
  426. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
  427. package/dist/modes/interactive/components/mermaid.js.map +1 -1
  428. package/dist/modes/interactive/components/message-card.d.ts.map +1 -1
  429. package/dist/modes/interactive/components/message-card.js +0 -1
  430. package/dist/modes/interactive/components/message-card.js.map +1 -1
  431. package/dist/modes/interactive/components/model-selector.d.ts +26 -18
  432. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  433. package/dist/modes/interactive/components/model-selector.js +223 -210
  434. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  435. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  436. package/dist/modes/interactive/components/oauth-selector.js +3 -12
  437. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  438. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  439. package/dist/modes/interactive/components/scoped-models-selector.js +9 -13
  440. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  441. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  442. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  443. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  444. package/dist/modes/interactive/components/session-selector.js +33 -58
  445. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  446. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  447. package/dist/modes/interactive/components/settings-selector.js +0 -4
  448. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  449. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  450. package/dist/modes/interactive/components/show-images-selector.js +0 -1
  451. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  452. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  453. package/dist/modes/interactive/components/skill-invocation-message.js +1 -3
  454. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  455. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  456. package/dist/modes/interactive/components/theme-selector.js +0 -2
  457. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  458. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  459. package/dist/modes/interactive/components/thinking-selector.js +0 -1
  460. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  461. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  462. package/dist/modes/interactive/components/tool-execution.js +9 -24
  463. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  464. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  465. package/dist/modes/interactive/components/tree-selector.js +18 -34
  466. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  467. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  468. package/dist/modes/interactive/components/user-message-selector.js +3 -6
  469. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  470. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  471. package/dist/modes/interactive/components/user-message.js +0 -4
  472. package/dist/modes/interactive/components/user-message.js.map +1 -1
  473. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  474. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  475. package/dist/modes/interactive/interactive-mode.d.ts +14 -0
  476. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  477. package/dist/modes/interactive/interactive-mode.js +223 -137
  478. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  479. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  480. package/dist/modes/interactive/theme/theme.js +0 -7
  481. package/dist/modes/interactive/theme/theme.js.map +1 -1
  482. package/dist/modes/json-event.d.ts.map +1 -1
  483. package/dist/modes/json-event.js.map +1 -1
  484. package/dist/modes/print-mode.d.ts.map +1 -1
  485. package/dist/modes/print-mode.js.map +1 -1
  486. package/dist/modes/rpc/jsonl.d.ts.map +1 -1
  487. package/dist/modes/rpc/jsonl.js.map +1 -1
  488. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  489. package/dist/modes/rpc/rpc-client.js +10 -11
  490. package/dist/modes/rpc/rpc-client.js.map +1 -1
  491. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  492. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  493. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  494. package/dist/package-manager-cli.d.ts.map +1 -1
  495. package/dist/package-manager-cli.js.map +1 -1
  496. package/dist/utils/ansi.d.ts.map +1 -1
  497. package/dist/utils/ansi.js.map +1 -1
  498. package/dist/utils/changelog.d.ts.map +1 -1
  499. package/dist/utils/changelog.js.map +1 -1
  500. package/dist/utils/child-process.d.ts.map +1 -1
  501. package/dist/utils/child-process.js.map +1 -1
  502. package/dist/utils/clipboard-image.d.ts.map +1 -1
  503. package/dist/utils/clipboard-image.js.map +1 -1
  504. package/dist/utils/clipboard-native.d.ts.map +1 -1
  505. package/dist/utils/clipboard-native.js.map +1 -1
  506. package/dist/utils/clipboard.d.ts.map +1 -1
  507. package/dist/utils/clipboard.js.map +1 -1
  508. package/dist/utils/deprecation.d.ts.map +1 -1
  509. package/dist/utils/deprecation.js.map +1 -1
  510. package/dist/utils/directory-completions.d.ts.map +1 -1
  511. package/dist/utils/directory-completions.js.map +1 -1
  512. package/dist/utils/exif-orientation.d.ts.map +1 -1
  513. package/dist/utils/exif-orientation.js.map +1 -1
  514. package/dist/utils/frontmatter.d.ts.map +1 -1
  515. package/dist/utils/frontmatter.js.map +1 -1
  516. package/dist/utils/fs-watch.d.ts.map +1 -1
  517. package/dist/utils/fs-watch.js.map +1 -1
  518. package/dist/utils/git.d.ts.map +1 -1
  519. package/dist/utils/git.js.map +1 -1
  520. package/dist/utils/grip-user-agent.d.ts.map +1 -1
  521. package/dist/utils/grip-user-agent.js +1 -1
  522. package/dist/utils/grip-user-agent.js.map +1 -1
  523. package/dist/utils/html.d.ts.map +1 -1
  524. package/dist/utils/html.js.map +1 -1
  525. package/dist/utils/image-convert.d.ts.map +1 -1
  526. package/dist/utils/image-convert.js.map +1 -1
  527. package/dist/utils/image-process.d.ts.map +1 -1
  528. package/dist/utils/image-process.js.map +1 -1
  529. package/dist/utils/image-resize-core.d.ts.map +1 -1
  530. package/dist/utils/image-resize-core.js.map +1 -1
  531. package/dist/utils/image-resize-worker.d.ts.map +1 -1
  532. package/dist/utils/image-resize-worker.js.map +1 -1
  533. package/dist/utils/image-resize.d.ts.map +1 -1
  534. package/dist/utils/image-resize.js.map +1 -1
  535. package/dist/utils/json.d.ts.map +1 -1
  536. package/dist/utils/json.js.map +1 -1
  537. package/dist/utils/mime.d.ts.map +1 -1
  538. package/dist/utils/mime.js.map +1 -1
  539. package/dist/utils/open-browser.d.ts.map +1 -1
  540. package/dist/utils/open-browser.js.map +1 -1
  541. package/dist/utils/paths.d.ts.map +1 -1
  542. package/dist/utils/paths.js.map +1 -1
  543. package/dist/utils/photon.d.ts.map +1 -1
  544. package/dist/utils/photon.js +10 -5
  545. package/dist/utils/photon.js.map +1 -1
  546. package/dist/utils/shell.d.ts.map +1 -1
  547. package/dist/utils/shell.js.map +1 -1
  548. package/dist/utils/sleep.d.ts.map +1 -1
  549. package/dist/utils/sleep.js.map +1 -1
  550. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  551. package/dist/utils/syntax-highlight.js +1 -1
  552. package/dist/utils/syntax-highlight.js.map +1 -1
  553. package/dist/utils/tools-manager.d.ts.map +1 -1
  554. package/dist/utils/tools-manager.js.map +1 -1
  555. package/dist/utils/version-check.d.ts.map +1 -1
  556. package/dist/utils/version-check.js.map +1 -1
  557. package/dist/utils/windows-self-update.d.ts.map +1 -1
  558. package/dist/utils/windows-self-update.js.map +1 -1
  559. package/docs/keybindings.md +3 -1
  560. package/docs/providers.md +3 -1
  561. package/docs/sandbox.md +7 -1
  562. package/docs/sessions.md +1 -1
  563. package/docs/usage.md +39 -2
  564. package/examples/extensions/custom-provider-anthropic/package.json +2 -2
  565. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  566. package/examples/extensions/sandbox/package.json +2 -2
  567. package/examples/extensions/with-deps/package.json +1 -1
  568. package/npm-shrinkwrap.json +601 -833
  569. package/package.json +20 -21
@@ -1 +1 @@
1
- {"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAa,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAc,MAAM,aAAa,CAAC;AAuChE,SAAS,oBAAoB,GAAW;IACvC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1D,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACnD,OAAO,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;AAAA,CACjC;AAED,SAAS,qBAAqB,CAAC,UAAoB,EAAE,IAAiB,EAAE,SAAiB,EAAQ;IAChG,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;QAAE,OAAO;IAChC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACpB,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAAA,CAC3B;AAED,SAAS,sBAAsB,CAAC,KAAe,EAAE,oBAA0C,EAAU;IACpG,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,OAAO,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC;QAC/C,qBAAqB,CAAC,UAAU,EAAE,IAAI,EAAE,gDAAgD,CAAC,CAAC;IAC3F,CAAC;SAAM,IAAI,OAAO,IAAI,CAAC,OAAO,IAAI,OAAO,IAAI,KAAK,CAAC,EAAE,CAAC;QACrD,qBAAqB,CACpB,UAAU,EACV,IAAI,EACJ,wFAAwF,CACxF,CAAC;IACH,CAAC;IACD,KAAK,MAAM,SAAS,IAAI,oBAAoB,IAAI,EAAE,EAAE,CAAC;QACpD,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC;QACpC,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;YAAE,qBAAqB,CAAC,UAAU,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IAChF,CAAC;IACD,qBAAqB,CAAC,UAAU,EAAE,IAAI,EAAE,8BAA8B,CAAC,CAAC;IACxE,qBAAqB,CAAC,UAAU,EAAE,IAAI,EAAE,iDAAiD,CAAC,CAAC;IAC3F,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,KAAK,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAAA,CAClE;AAED,SAAS,oBAAoB,CAAC,KAAe,EAAE,YAAgD,EAAU;IACxG,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IACpE,OAAO,YAAY,CAAC,MAAM,GAAG,CAAC;QAC7B,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,KAAK,YAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QAC5E,CAAC,CAAC,QAAQ,CAAC;AAAA,CACZ;AAED,SAAS,yBAAyB,CAAC,WAAoB,EAAU;IAChE,IAAI,CAAC,WAAW;QAAE,OAAO,EAAE,CAAC;IAC5B,OAAO;;;;;;;;KAQH,CAAC,IAAI,EAAE,CAAC;AAAA,CACZ;AAED,SAAS,wBAAwB,CAAC,OAAiC,EAAE,KAAe,EAAU;IAC7F,MAAM,SAAS,GAAG,oBAAoB,CAAC,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IACpE,MAAM,UAAU,GAAG,sBAAsB,CAAC,KAAK,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC3E,MAAM,oBAAoB,GAAG,yBAAyB,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;IACnF,MAAM,uBAAuB,GAAG,KAAK,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QACjE,CAAC,CAAC;;;;;;;;;ulBASmlB;QACrlB,CAAC,CAAC,EAAE,CAAC;IACN,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;IACvC,OAAO;;EAEN,SAAS;;;EAGT,oBAAoB,CAAC,CAAC,CAAC,KAAK,oBAAoB,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,uBAAuB,CAAC,CAAC,CAAC,KAAK,uBAAuB,IAAI,CAAC,CAAC,CAAC,EAAE;;EAE3H,UAAU;;;wBAGY,UAAU;qBACb,QAAQ;cACf,YAAY;;;;4GAIkF,CAAC;AAAA,CAC5G;AAED,SAAS,oBAAoB,CAAC,MAAc,EAAE,OAAwC,EAAU;IAC/F,IAAI,OAAO,CAAC,kBAAkB;QAAE,MAAM,IAAI,OAAO,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAC9E,IAAI,OAAO,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,2BAA2B,CAAC;QACtC,MAAM,IAAI,mDAAmD,CAAC;QAC9D,KAAK,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;YACtD,MAAM,IAAI,+BAA+B,IAAI,OAAO,OAAO,+BAA+B,CAAC;QAC5F,CAAC;QACD,MAAM,IAAI,sBAAsB,CAAC;IAClC,CAAC;IACD,IAAI,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAClG,IAAI,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,oBAAoB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC/F,MAAM,IAAI,mBAAmB,OAAO,CAAC,IAAI,EAAE,CAAC;IAC5C,MAAM,IAAI,gCAAgC,OAAO,CAAC,SAAS,EAAE,CAAC;IAC9D,OAAO,MAAM,CAAC;AAAA,CACd;AAED,kEAAkE;AAClE,MAAM,UAAU,iBAAiB,CAAC,OAAiC,EAAU;IAC5E,MAAM,KAAK,GAAG,OAAO,CAAC,aAAa,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACzE,MAAM,UAAU,GAAG,OAAO,CAAC,YAAY,IAAI,wBAAwB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACpF,OAAO,oBAAoB,CAAC,UAAU,EAAE;QACvC,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;QAC9C,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;QAC1C,IAAI,EAAE,oBAAoB,EAAE;QAC5B,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,EAAE;QACxC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;QAC5B,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;QAC1B,OAAO,EAAE,CAAC,OAAO,CAAC,aAAa,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;KACzD,CAAC,CAAC;AAAA,CACH","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] */\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 +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"]}
@@ -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;;;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"}
@@ -45,11 +45,14 @@ function resolveSpawnContext(command, cwd, spawnHook, exposeSessionEnvironment,
45
45
  const BASH_PREVIEW_LINES = 5;
46
46
  const BASH_UPDATE_THROTTLE_MS = 100;
47
47
  class BashResultRenderComponent extends Container {
48
- state = {
49
- cachedWidth: undefined,
50
- cachedLines: undefined,
51
- cachedSkipped: undefined,
52
- };
48
+ constructor() {
49
+ super(...arguments);
50
+ this.state = {
51
+ cachedWidth: undefined,
52
+ cachedLines: undefined,
53
+ cachedSkipped: undefined,
54
+ };
55
+ }
53
56
  }
54
57
  function formatDuration(ms) {
55
58
  return `${(ms / 1000).toFixed(1)}s`;
@@ -1 +1 @@
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;CACzG,CAAC,CAAC;AAoBH,MAAM,UAAU,yBAAyB,CAAC,OAAoC,EAAkB;IAC/F,OAAO,IAAI,mBAAmB,CAAC,OAAO,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;AAAA,CACjG;AAYD,MAAM,UAAU,yBAAyB,CAAC,GAAiC,EAA0B;IACpG,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;AAAA,CACnB;AAED,SAAS,mBAAmB,CAC3B,OAAe,EACf,GAAW,EACX,SAAoC,EACpC,wBAAiC,EACjC,GAAiC,EACd;IACnB,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;AAAA,CACxD;AAWD,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAC7B,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAcpC,MAAM,yBAA0B,SAAQ,SAAS;IAChD,KAAK,GAA0B;QAC9B,WAAW,EAAE,SAAS;QACtB,WAAW,EAAE,SAAS;QACtB,aAAa,EAAE,SAAS;KACxB,CAAC;CACF;AAED,SAAS,cAAc,CAAC,EAAU,EAAU;IAC3C,OAAO,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;AAAA,CACpC;AAED,SAAS,mBAAmB,CAAC,WAAwC,EAAU;IAC9E,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;AAAA,CACtE;AAED,SAAS,cAAc,CAAC,IAAwC,EAAE,WAA6B,EAAU;IACxG,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,CAAC;IAC9B,MAAM,aAAa,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACjF,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;QAC9C,aAAa,CACb,CAAC;AAAA,CACF;AAED,SAAS,oBAAoB,CAC5B,MAAoD,EACpD,UAAmB,EACnB,SAAkB,EACT;IACT,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;AAAA,CAC9C;AAED,SAAS,aAAa,CACrB,SAAoC,EACpC,KAA4B,EAC5B,MAAc,EACd,OAAgC,EACzB;IACP,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,CAAC;YAC1B,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;QAAA,CAC1C;QACD,UAAU,EAAE,GAAG,EAAE,CAAC;YACjB,KAAK,CAAC,WAAW,GAAG,SAAS,CAAC;YAC9B,KAAK,CAAC,WAAW,GAAG,SAAS,CAAC;YAC9B,KAAK,CAAC,aAAa,GAAG,SAAS,CAAC;QAAA,CAChC;KACD,CAAC,CAAC;AAAA,CACH;AAED,SAAS,qBAAqB,CAC7B,SAAoC,EACpC,UAAwC,EACxC,cAAkC,EAC3B;IACP,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;AAAA,CAC3F;AAED,SAAS,gCAAgC,CACxC,SAAoC,EACpC,MAAoD,EACpD,OAAgC,EAChC,OAAgB,EAChB,UAAmB,EACnB,SAA6B,EAC7B,OAA2B,EAC3B,WAAwC,EACjC;IACP,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,mBAAmB,CAAC,WAAW,CAAC,EAAE,EAClK,CAAC,EACD,CAAC,CACD,CACD,CAAC;IACH,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,MAAM,EAAE,CAAC;QACjC,SAAS,CAAC,QAAQ,CAAC;YAClB,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC;gBAClB,IAAI,CAAC,KAAK,CAAC,aAAa,IAAI,KAAK,GAAG,CAAC;oBAAE,OAAO,EAAE,CAAC;gBACjD,MAAM,SAAS,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;gBAC9C,MAAM,IAAI,GACT,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,KAAK,CAAC,aAAa,eAAe,CAAC;oBAC1D,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAM,SAAS,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACpE,OAAO,CAAC,EAAE,EAAE,eAAe,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;YAAA,CACjD;YACD,UAAU,EAAE,GAAG,EAAE,CAAC,EAAC,CAAC;SACpB,CAAC,CAAC;IACJ,CAAC;AAAA,CACD;AAED,SAAS,gBAAgB,CAAC,IAAY,EAAE,MAAc,EAAU;IAC/D,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC;AAAA,CAC/C;AAED,SAAS,uBAAuB,CAAC,KAAc,EAAE,UAAkB,EAAS;IAC3E,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;AAAA,CACZ;AAID,MAAM,UAAU,wBAAwB,CAAC,UAA0B,EAAE,OAAyB,EAAsB;IACnH,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,mHAAmH,iBAAiB,aAAa,iBAAiB,GAAG,IAAI,0HAA0H;QAChT,aAAa,EAAE,8CAA8C;QAC7D,gBAAgB,EAAE,wBAAwB;YACzC,CAAC,CAAC,CAAC,6EAA6E,CAAC;YACjF,CAAC,CAAC,SAAS;QACZ,UAAU,EAAE,UAAU;QACtB,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,OAAO,EAAiB,EAAE,MAAoB,EAAE,QAAS,EAAE,GAAI,EAAE;YACtG,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,CAAC;gBAC9B,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;YAAA,CACH,CAAC;YAEF,MAAM,gBAAgB,GAAG,GAAG,EAAE,CAAC;gBAC9B,IAAI,WAAW,EAAE,CAAC;oBACjB,YAAY,CAAC,WAAW,CAAC,CAAC;oBAC1B,WAAW,GAAG,SAAS,CAAC;gBACzB,CAAC;YAAA,CACD,CAAC;YAEF,MAAM,oBAAoB,GAAG,GAAG,EAAE,CAAC;gBAClC,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,CAAC;oBAChC,WAAW,GAAG,SAAS,CAAC;oBACxB,gBAAgB,EAAE,CAAC;gBAAA,CACnB,EAAE,KAAK,CAAC,CAAC;YAAA,CACV,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,CAAC;gBACpC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACpB,oBAAoB,EAAE,CAAC;YAAA,CACvB,CAAC;YAEF,MAAM,YAAY,GAAG,KAAK,IAAI,EAAE,CAAC;gBAChC,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;YAAA,CAChB,CAAC;YAEF,MAAM,YAAY,GAAG,CAAC,QAAwB,EAAE,SAAS,GAAG,aAAa,EAAE,EAAE,CAAC;gBAC7E,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;YAAA,CACzB,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;QAAA,CACD;QACD,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;YACjC,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;QAAA,CACZ;QACD,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE;YAC9C,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,CACtB,CAAC;YACF,SAAS,CAAC,UAAU,EAAE,CAAC;YACvB,OAAO,SAAS,CAAC;QAAA,CACjB;KACD,CAAC;AAAA,CACF;AAED,MAAM,UAAU,cAAc,CAAC,UAA0B,EAAE,OAAyB,EAAgC;IACnH,OAAO,kBAAkB,CAAC,wBAAwB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;AAAA,CACzE","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":"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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 +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"]}
@@ -1 +1 @@
1
- {"version":3,"file":"edit-diff.d.ts","sourceRoot":"","sources":["../../../src/core/tools/edit-diff.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,OAAO,EAAE,KAAK,UAAU,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE9D,OAAO,EAAE,QAAQ,IAAI,QAAQ,EAAE,CAAC;AAEhC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,CAM5D;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAE3E;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAqB3D;AAED,MAAM,WAAW,gBAAgB;IAChC,gCAAgC;IAChC,KAAK,EAAE,OAAO,CAAC;IACf,4FAA4F;IAC5F,KAAK,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,cAAc,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,qBAAqB,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,IAAI;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CAChB;AASD,MAAM,WAAW,kBAAkB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAsChF;AA6CD;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAC5C,iBAAiB,EAAE,MAAM,EACzB,KAAK,EAAE,IAAI,EAAE,EACb,IAAI,EAAE,MAAM,GACV,kBAAkB,CA+DpB;AAED,yCAAyC;AACzC,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,SAAI,GAAG,MAAM,CAKnH;AA8FD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,SAAI,GAAG,cAAc,CAgC3G;AAGD,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC;AAED,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACrC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,IAAI,EAAE,EACb,UAAU,EAAE,cAAc,GACxB,OAAO,CAAC,cAAc,GAAG,aAAa,CAAC,CAyBzC;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACpC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,cAAc,GACxB,OAAO,CAAC,cAAc,GAAG,aAAa,CAAC,CAEzC","sourcesContent":["/**\n * Shared diff computation utilities for the edit tool.\n * Used by both edit.ts (for execution) and tool-execution.ts (for preview rendering).\n */\n\nimport * as Diff from \"diff\";\nimport type { ToolOperations } from \"./operations.ts\";\nimport { resolveToCwd } from \"./path-utils.ts\";\nimport { type LineEnding, stripBOM } from \"./replace-diff.ts\";\n\nexport { stripBOM as stripBom };\n\nexport function detectLineEnding(content: string): LineEnding {\n\tconst crlfIdx = content.indexOf(\"\\r\\n\");\n\tconst lfIdx = content.indexOf(\"\\n\");\n\tif (lfIdx === -1) return \"\\n\";\n\tif (crlfIdx === -1) return \"\\n\";\n\treturn crlfIdx < lfIdx ? \"\\r\\n\" : \"\\n\";\n}\n\nexport function normalizeToLF(text: string): string {\n\treturn text.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n}\n\nexport function restoreLineEndings(text: string, ending: LineEnding): string {\n\treturn ending === \"\\r\\n\" ? text.replace(/\\n/g, \"\\r\\n\") : text;\n}\n\n/**\n * Normalize text for fuzzy matching. Applies progressive transformations:\n * - Strip trailing whitespace from each line\n * - Normalize smart quotes to ASCII equivalents\n * - Normalize Unicode dashes/hyphens to ASCII hyphen\n * - Normalize special Unicode spaces to regular space\n */\nexport function normalizeForFuzzyMatch(text: string): string {\n\treturn (\n\t\ttext\n\t\t\t.normalize(\"NFKC\")\n\t\t\t// Strip trailing whitespace per line\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => line.trimEnd())\n\t\t\t.join(\"\\n\")\n\t\t\t// Smart single quotes → '\n\t\t\t.replace(/[\\u2018\\u2019\\u201A\\u201B]/g, \"'\")\n\t\t\t// Smart double quotes → \"\n\t\t\t.replace(/[\\u201C\\u201D\\u201E\\u201F]/g, '\"')\n\t\t\t// Various dashes/hyphens → -\n\t\t\t// U+2010 hyphen, U+2011 non-breaking hyphen, U+2012 figure dash,\n\t\t\t// U+2013 en-dash, U+2014 em-dash, U+2015 horizontal bar, U+2212 minus\n\t\t\t.replace(/[\\u2010\\u2011\\u2012\\u2013\\u2014\\u2015\\u2212]/g, \"-\")\n\t\t\t// Special spaces → regular space\n\t\t\t// U+00A0 NBSP, U+2002-U+200A various spaces, U+202F narrow NBSP,\n\t\t\t// U+205F medium math space, U+3000 ideographic space\n\t\t\t.replace(/[\\u00A0\\u2002-\\u200A\\u202F\\u205F\\u3000]/g, \" \")\n\t);\n}\n\nexport interface FuzzyMatchResult {\n\t/** Whether a match was found */\n\tfound: boolean;\n\t/** The index where the match starts (in the content that should be used for replacement) */\n\tindex: number;\n\t/** Length of the matched text */\n\tmatchLength: number;\n\t/** Whether fuzzy matching was used (false = exact match) */\n\tusedFuzzyMatch: boolean;\n\t/**\n\t * The content to use for replacement operations.\n\t * When exact match: original content. When fuzzy match: normalized content.\n\t */\n\tcontentForReplacement: string;\n}\n\nexport interface Edit {\n\toldText: string;\n\tnewText: string;\n}\n\ninterface MatchedEdit {\n\teditIndex: number;\n\tmatchIndex: number;\n\tmatchLength: number;\n\tnewText: string;\n}\n\nexport interface AppliedEditsResult {\n\tbaseContent: string;\n\tnewContent: string;\n}\n\n/**\n * Find oldText in content, trying exact match first, then fuzzy match.\n * When fuzzy matching is used, the returned contentForReplacement is the\n * fuzzy-normalized version of the content (trailing whitespace stripped,\n * Unicode quotes/dashes normalized to ASCII).\n */\nexport function fuzzyFindText(content: string, oldText: string): FuzzyMatchResult {\n\t// Try exact match first\n\tconst exactIndex = content.indexOf(oldText);\n\tif (exactIndex !== -1) {\n\t\treturn {\n\t\t\tfound: true,\n\t\t\tindex: exactIndex,\n\t\t\tmatchLength: oldText.length,\n\t\t\tusedFuzzyMatch: false,\n\t\t\tcontentForReplacement: content,\n\t\t};\n\t}\n\n\t// Try fuzzy match - work entirely in normalized space\n\tconst fuzzyContent = normalizeForFuzzyMatch(content);\n\tconst fuzzyOldText = normalizeForFuzzyMatch(oldText);\n\tconst fuzzyIndex = fuzzyContent.indexOf(fuzzyOldText);\n\n\tif (fuzzyIndex === -1) {\n\t\treturn {\n\t\t\tfound: false,\n\t\t\tindex: -1,\n\t\t\tmatchLength: 0,\n\t\t\tusedFuzzyMatch: false,\n\t\t\tcontentForReplacement: content,\n\t\t};\n\t}\n\n\t// When fuzzy matching, we work in the normalized space for replacement.\n\t// This means the output will have normalized whitespace/quotes/dashes,\n\t// which is acceptable since we're fixing minor formatting differences anyway.\n\treturn {\n\t\tfound: true,\n\t\tindex: fuzzyIndex,\n\t\tmatchLength: fuzzyOldText.length,\n\t\tusedFuzzyMatch: true,\n\t\tcontentForReplacement: fuzzyContent,\n\t};\n}\nfunction countOccurrences(content: string, oldText: string): number {\n\tconst fuzzyContent = normalizeForFuzzyMatch(content);\n\tconst fuzzyOldText = normalizeForFuzzyMatch(oldText);\n\treturn fuzzyContent.split(fuzzyOldText).length - 1;\n}\n\nfunction getNotFoundError(path: string, editIndex: number, totalEdits: number): Error {\n\tif (totalEdits === 1) {\n\t\treturn new Error(\n\t\t\t`Could not find the exact text in ${path}. The old text must match exactly including all whitespace and newlines.`,\n\t\t);\n\t}\n\treturn new Error(\n\t\t`Could not find edits[${editIndex}] in ${path}. The oldText must match exactly including all whitespace and newlines.`,\n\t);\n}\n\nfunction getDuplicateError(path: string, editIndex: number, totalEdits: number, occurrences: number): Error {\n\tif (totalEdits === 1) {\n\t\treturn new Error(\n\t\t\t`Found ${occurrences} occurrences of the text in ${path}. The text must be unique. Please provide more context to make it unique.`,\n\t\t);\n\t}\n\treturn new Error(\n\t\t`Found ${occurrences} occurrences of edits[${editIndex}] in ${path}. Each oldText must be unique. Please provide more context to make it unique.`,\n\t);\n}\n\nfunction getEmptyOldTextError(path: string, editIndex: number, totalEdits: number): Error {\n\tif (totalEdits === 1) {\n\t\treturn new Error(`oldText must not be empty in ${path}.`);\n\t}\n\treturn new Error(`edits[${editIndex}].oldText must not be empty in ${path}.`);\n}\n\nfunction getNoChangeError(path: string, totalEdits: number): Error {\n\tif (totalEdits === 1) {\n\t\treturn new Error(\n\t\t\t`No changes made to ${path}. The replacement produced identical content. This might indicate an issue with special characters or the text not existing as expected.`,\n\t\t);\n\t}\n\treturn new Error(`No changes made to ${path}. The replacements produced identical content.`);\n}\n\n/**\n * Apply one or more exact-text replacements to LF-normalized content.\n *\n * All edits are matched against the same original content. Replacements are\n * then applied in reverse order so offsets remain stable. If any edit needs\n * fuzzy matching, the operation runs in fuzzy-normalized content space to\n * preserve current single-edit behavior.\n */\nexport function applyEditsToNormalizedContent(\n\tnormalizedContent: string,\n\tedits: Edit[],\n\tpath: string,\n): AppliedEditsResult {\n\tconst normalizedEdits = edits.map((edit) => ({\n\t\toldText: normalizeToLF(edit.oldText),\n\t\tnewText: normalizeToLF(edit.newText),\n\t}));\n\n\tfor (let i = 0; i < normalizedEdits.length; i++) {\n\t\tif (normalizedEdits[i].oldText.length === 0) {\n\t\t\tthrow getEmptyOldTextError(path, i, normalizedEdits.length);\n\t\t}\n\t}\n\n\tconst initialMatches = normalizedEdits.map((edit) => fuzzyFindText(normalizedContent, edit.oldText));\n\tconst baseContent = initialMatches.some((match) => match.usedFuzzyMatch)\n\t\t? normalizeForFuzzyMatch(normalizedContent)\n\t\t: normalizedContent;\n\n\tconst matchedEdits: MatchedEdit[] = [];\n\tfor (let i = 0; i < normalizedEdits.length; i++) {\n\t\tconst edit = normalizedEdits[i];\n\t\tconst matchResult = fuzzyFindText(baseContent, edit.oldText);\n\t\tif (!matchResult.found) {\n\t\t\tthrow getNotFoundError(path, i, normalizedEdits.length);\n\t\t}\n\n\t\tconst occurrences = countOccurrences(baseContent, edit.oldText);\n\t\tif (occurrences > 1) {\n\t\t\tthrow getDuplicateError(path, i, normalizedEdits.length, occurrences);\n\t\t}\n\n\t\tmatchedEdits.push({\n\t\t\teditIndex: i,\n\t\t\tmatchIndex: matchResult.index,\n\t\t\tmatchLength: matchResult.matchLength,\n\t\t\tnewText: edit.newText,\n\t\t});\n\t}\n\n\tmatchedEdits.sort((a, b) => a.matchIndex - b.matchIndex);\n\tfor (let i = 1; i < matchedEdits.length; i++) {\n\t\tconst previous = matchedEdits[i - 1];\n\t\tconst current = matchedEdits[i];\n\t\tif (previous.matchIndex + previous.matchLength > current.matchIndex) {\n\t\t\tthrow new Error(\n\t\t\t\t`edits[${previous.editIndex}] and edits[${current.editIndex}] overlap in ${path}. Merge them into one edit or target disjoint regions.`,\n\t\t\t);\n\t\t}\n\t}\n\n\tlet newContent = baseContent;\n\tfor (let i = matchedEdits.length - 1; i >= 0; i--) {\n\t\tconst edit = matchedEdits[i];\n\t\tnewContent =\n\t\t\tnewContent.substring(0, edit.matchIndex) +\n\t\t\tedit.newText +\n\t\t\tnewContent.substring(edit.matchIndex + edit.matchLength);\n\t}\n\n\tif (baseContent === newContent) {\n\t\tthrow getNoChangeError(path, normalizedEdits.length);\n\t}\n\n\treturn { baseContent, newContent };\n}\n\n/** Generate a standard unified patch. */\nexport function generateUnifiedPatch(path: string, oldContent: string, newContent: string, contextLines = 4): string {\n\treturn Diff.createTwoFilesPatch(path, path, oldContent, newContent, undefined, undefined, {\n\t\tcontext: contextLines,\n\t\theaderOptions: Diff.FILE_HEADERS_ONLY,\n\t});\n}\n\ninterface DiffRenderState {\n\toutput: string[];\n\toldLineNumber: number;\n\tnewLineNumber: number;\n\tlineNumberWidth: number;\n\tfirstChangedLine: number | undefined;\n}\n\nfunction getDiffPartLines(part: Diff.Change): string[] {\n\tconst lines = part.value.split(\"\\n\");\n\tif (lines.at(-1) === \"\") lines.pop();\n\treturn lines;\n}\n\nfunction appendChangedDiffLines(state: DiffRenderState, part: Diff.Change, lines: string[]): void {\n\tstate.firstChangedLine ??= state.newLineNumber;\n\tfor (const line of lines) {\n\t\tif (part.added) {\n\t\t\tconst lineNumber = String(state.newLineNumber).padStart(state.lineNumberWidth, \" \");\n\t\t\tstate.output.push(`+${lineNumber} ${line}`);\n\t\t\tstate.newLineNumber++;\n\t\t} else {\n\t\t\tconst lineNumber = String(state.oldLineNumber).padStart(state.lineNumberWidth, \" \");\n\t\t\tstate.output.push(`-${lineNumber} ${line}`);\n\t\t\tstate.oldLineNumber++;\n\t\t}\n\t}\n}\n\nfunction appendContextDiffLines(state: DiffRenderState, lines: string[]): void {\n\tfor (const line of lines) {\n\t\tconst lineNumber = String(state.oldLineNumber).padStart(state.lineNumberWidth, \" \");\n\t\tstate.output.push(` ${lineNumber} ${line}`);\n\t\tstate.oldLineNumber++;\n\t\tstate.newLineNumber++;\n\t}\n}\n\nfunction appendSkippedDiffLines(state: DiffRenderState, count: number): void {\n\tif (count <= 0) return;\n\tstate.output.push(` ${\"\".padStart(state.lineNumberWidth, \" \")} ...`);\n\tstate.oldLineNumber += count;\n\tstate.newLineNumber += count;\n}\n\nfunction appendContextBetweenChanges(state: DiffRenderState, lines: string[], contextLines: number): void {\n\tif (lines.length <= contextLines * 2) {\n\t\tappendContextDiffLines(state, lines);\n\t\treturn;\n\t}\n\tconst leadingLines = lines.slice(0, contextLines);\n\tconst trailingLines = lines.slice(lines.length - contextLines);\n\tappendContextDiffLines(state, leadingLines);\n\tappendSkippedDiffLines(state, lines.length - leadingLines.length - trailingLines.length);\n\tappendContextDiffLines(state, trailingLines);\n}\n\nfunction appendContextAfterChange(state: DiffRenderState, lines: string[], contextLines: number): void {\n\tconst shownLines = lines.slice(0, contextLines);\n\tappendContextDiffLines(state, shownLines);\n\tappendSkippedDiffLines(state, lines.length - shownLines.length);\n}\n\nfunction appendContextBeforeChange(state: DiffRenderState, lines: string[], contextLines: number): void {\n\tconst skippedLines = Math.max(0, lines.length - contextLines);\n\tappendSkippedDiffLines(state, skippedLines);\n\tappendContextDiffLines(state, lines.slice(skippedLines));\n}\n\nfunction appendUnchangedDiffPart(\n\tstate: DiffRenderState,\n\tlines: string[],\n\thasLeadingChange: boolean,\n\thasTrailingChange: boolean,\n\tcontextLines: number,\n): void {\n\tif (hasLeadingChange && hasTrailingChange) {\n\t\tappendContextBetweenChanges(state, lines, contextLines);\n\t\treturn;\n\t}\n\tif (hasLeadingChange) {\n\t\tappendContextAfterChange(state, lines, contextLines);\n\t\treturn;\n\t}\n\tif (hasTrailingChange) {\n\t\tappendContextBeforeChange(state, lines, contextLines);\n\t\treturn;\n\t}\n\tstate.oldLineNumber += lines.length;\n\tstate.newLineNumber += lines.length;\n}\n\n/**\n * Generate a display-oriented diff string with line numbers and context.\n * Returns both the diff string and the first changed line number (in the new file).\n */\nexport function generateDiffString(oldContent: string, newContent: string, contextLines = 4): EditDiffResult {\n\tconst parts = Diff.diffLines(oldContent, newContent);\n\tconst maxLineNumber = Math.max(oldContent.split(\"\\n\").length, newContent.split(\"\\n\").length);\n\tconst state: DiffRenderState = {\n\t\toutput: [],\n\t\toldLineNumber: 1,\n\t\tnewLineNumber: 1,\n\t\tlineNumberWidth: String(maxLineNumber).length,\n\t\tfirstChangedLine: undefined,\n\t};\n\tlet lastWasChange = false;\n\n\tfor (let index = 0; index < parts.length; index++) {\n\t\tconst part = parts[index];\n\t\tconst lines = getDiffPartLines(part);\n\t\tif (part.added || part.removed) {\n\t\t\tappendChangedDiffLines(state, part, lines);\n\t\t\tlastWasChange = true;\n\t\t\tcontinue;\n\t\t}\n\t\tconst nextPart = parts[index + 1];\n\t\tappendUnchangedDiffPart(\n\t\t\tstate,\n\t\t\tlines,\n\t\t\tlastWasChange,\n\t\t\tindex < parts.length - 1 && Boolean(nextPart.added || nextPart.removed),\n\t\t\tcontextLines,\n\t\t);\n\t\tlastWasChange = false;\n\t}\n\n\treturn { diff: state.output.join(\"\\n\"), firstChangedLine: state.firstChangedLine };\n}\n\n// grip-ignore noNearIdenticalDataStructures: Plain line-number diffs and hashline-anchored diffs use distinct rendering formats and evolve independently.\nexport interface EditDiffResult {\n\tdiff: string;\n\tfirstChangedLine: number | undefined;\n}\n\nexport interface EditDiffError {\n\terror: string;\n}\n\n/**\n * Compute the diff for one or more edit operations without applying them.\n * Used for preview rendering in the TUI before the tool executes.\n */\nexport async function computeEditsDiff(\n\tpath: string,\n\tedits: Edit[],\n\toperations: ToolOperations,\n): Promise<EditDiffResult | EditDiffError> {\n\tconst absolutePath = resolveToCwd(path, operations.cwd);\n\n\ttry {\n\t\t// Check if file exists and is readable\n\t\ttry {\n\t\t\tawait operations.access(absolutePath, \"read\");\n\t\t} catch (error: unknown) {\n\t\t\tconst errorMessage = error instanceof Error && \"code\" in error ? `Error code: ${error.code}` : String(error);\n\t\t\treturn { error: `Could not edit file: ${path}. ${errorMessage}.` };\n\t\t}\n\n\t\t// Read the file\n\t\tconst rawContent = (await operations.readFile(absolutePath)).toString(\"utf-8\");\n\n\t\t// Strip BOM before matching (LLM won't include invisible BOM in oldText)\n\t\tconst { text: content } = stripBOM(rawContent);\n\t\tconst normalizedContent = normalizeToLF(content);\n\t\tconst { baseContent, newContent } = applyEditsToNormalizedContent(normalizedContent, edits, path);\n\n\t\t// Generate the diff\n\t\treturn generateDiffString(baseContent, newContent);\n\t} catch (err) {\n\t\treturn { error: err instanceof Error ? err.message : String(err) };\n\t}\n}\n\n/**\n * Compute the diff for a single edit operation without applying it.\n * Kept as a convenience wrapper for single-edit callers.\n */\nexport async function computeEditDiff(\n\tpath: string,\n\toldText: string,\n\tnewText: string,\n\toperations: ToolOperations,\n): Promise<EditDiffResult | EditDiffError> {\n\treturn computeEditsDiff(path, [{ oldText, newText }], operations);\n}\n"]}
1
+ {"version":3,"file":"edit-diff.d.ts","sourceRoot":"","sources":["../../../src/core/tools/edit-diff.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,OAAO,EAAE,KAAK,UAAU,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE9D,OAAO,EAAE,QAAQ,IAAI,QAAQ,EAAE,CAAC;AAEhC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,CAM5D;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAE3E;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAqB3D;AAED,MAAM,WAAW,gBAAgB;IAChC,gCAAgC;IAChC,KAAK,EAAE,OAAO,CAAC;IACf,4FAA4F;IAC5F,KAAK,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,cAAc,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,qBAAqB,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,IAAI;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CAChB;AASD,MAAM,WAAW,kBAAkB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAsChF;AA6CD;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAC5C,iBAAiB,EAAE,MAAM,EACzB,KAAK,EAAE,IAAI,EAAE,EACb,IAAI,EAAE,MAAM,GACV,kBAAkB,CA+DpB;AAED,yCAAyC;AACzC,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,SAAI,GAAG,MAAM,CAKnH;AA8FD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,SAAI,GAAG,cAAc,CAgC3G;AAGD,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC;AAED,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACrC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,IAAI,EAAE,EACb,UAAU,EAAE,cAAc,GACxB,OAAO,CAAC,cAAc,GAAG,aAAa,CAAC,CAyBzC;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACpC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,cAAc,GACxB,OAAO,CAAC,cAAc,GAAG,aAAa,CAAC,CAEzC"}