@greppleai/grip 0.0.0-stage → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1119) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/README.md +731 -2
  3. package/dist/bun/cli.d.ts +3 -0
  4. package/dist/bun/cli.d.ts.map +1 -0
  5. package/dist/bun/cli.js +13 -0
  6. package/dist/bun/cli.js.map +1 -0
  7. package/dist/bun/embedded-assets.d.ts +3 -0
  8. package/dist/bun/embedded-assets.d.ts.map +1 -0
  9. package/dist/bun/embedded-assets.js +52 -0
  10. package/dist/bun/embedded-assets.js.map +1 -0
  11. package/dist/bun/register-bedrock.d.ts +2 -0
  12. package/dist/bun/register-bedrock.d.ts.map +1 -0
  13. package/dist/bun/register-bedrock.js +4 -0
  14. package/dist/bun/register-bedrock.js.map +1 -0
  15. package/dist/bun/restore-sandbox-env.d.ts +13 -0
  16. package/dist/bun/restore-sandbox-env.d.ts.map +1 -0
  17. package/dist/bun/restore-sandbox-env.js +32 -0
  18. package/dist/bun/restore-sandbox-env.js.map +1 -0
  19. package/dist/cli/args.d.ts +70 -0
  20. package/dist/cli/args.d.ts.map +1 -0
  21. package/dist/cli/args.js +442 -0
  22. package/dist/cli/args.js.map +1 -0
  23. package/dist/cli/config-selector.d.ts +14 -0
  24. package/dist/cli/config-selector.d.ts.map +1 -0
  25. package/dist/cli/config-selector.js +31 -0
  26. package/dist/cli/config-selector.js.map +1 -0
  27. package/dist/cli/file-processor.d.ts +15 -0
  28. package/dist/cli/file-processor.d.ts.map +1 -0
  29. package/dist/cli/file-processor.js +60 -0
  30. package/dist/cli/file-processor.js.map +1 -0
  31. package/dist/cli/initial-message.d.ts +18 -0
  32. package/dist/cli/initial-message.d.ts.map +1 -0
  33. package/dist/cli/initial-message.js +22 -0
  34. package/dist/cli/initial-message.js.map +1 -0
  35. package/dist/cli/list-models.d.ts +9 -0
  36. package/dist/cli/list-models.d.ts.map +1 -0
  37. package/dist/cli/list-models.js +98 -0
  38. package/dist/cli/list-models.js.map +1 -0
  39. package/dist/cli/session-picker.d.ts +9 -0
  40. package/dist/cli/session-picker.d.ts.map +1 -0
  41. package/dist/cli/session-picker.js +35 -0
  42. package/dist/cli/session-picker.js.map +1 -0
  43. package/dist/cli.d.ts +3 -0
  44. package/dist/cli.d.ts.map +1 -0
  45. package/dist/cli.js +14 -0
  46. package/dist/cli.js.map +1 -0
  47. package/dist/config.d.ts +82 -0
  48. package/dist/config.d.ts.map +1 -0
  49. package/dist/config.js +406 -0
  50. package/dist/config.js.map +1 -0
  51. package/dist/core/agent-session.d.ts +970 -0
  52. package/dist/core/agent-session.d.ts.map +1 -0
  53. package/dist/core/agent-session.js +5191 -0
  54. package/dist/core/agent-session.js.map +1 -0
  55. package/dist/core/auth-guidance.d.ts +5 -0
  56. package/dist/core/auth-guidance.d.ts.map +1 -0
  57. package/dist/core/auth-guidance.js +21 -0
  58. package/dist/core/auth-guidance.js.map +1 -0
  59. package/dist/core/auth-storage.d.ts +150 -0
  60. package/dist/core/auth-storage.d.ts.map +1 -0
  61. package/dist/core/auth-storage.js +557 -0
  62. package/dist/core/auth-storage.js.map +1 -0
  63. package/dist/core/bash-executor.d.ts +26 -0
  64. package/dist/core/bash-executor.d.ts.map +1 -0
  65. package/dist/core/bash-executor.js +99 -0
  66. package/dist/core/bash-executor.js.map +1 -0
  67. package/dist/core/compaction/branch-summarization.d.ts +83 -0
  68. package/dist/core/compaction/branch-summarization.d.ts.map +1 -0
  69. package/dist/core/compaction/branch-summarization.js +220 -0
  70. package/dist/core/compaction/branch-summarization.js.map +1 -0
  71. package/dist/core/compaction/compaction.d.ts +65 -0
  72. package/dist/core/compaction/compaction.d.ts.map +1 -0
  73. package/dist/core/compaction/compaction.js +550 -0
  74. package/dist/core/compaction/compaction.js.map +1 -0
  75. package/dist/core/compaction/compression-detection-ledger.d.ts +34 -0
  76. package/dist/core/compaction/compression-detection-ledger.d.ts.map +1 -0
  77. package/dist/core/compaction/compression-detection-ledger.js +52 -0
  78. package/dist/core/compaction/compression-detection-ledger.js.map +1 -0
  79. package/dist/core/compaction/compression-detector.d.ts +71 -0
  80. package/dist/core/compaction/compression-detector.d.ts.map +1 -0
  81. package/dist/core/compaction/compression-detector.js +407 -0
  82. package/dist/core/compaction/compression-detector.js.map +1 -0
  83. package/dist/core/compaction/compression-economics.d.ts +55 -0
  84. package/dist/core/compaction/compression-economics.d.ts.map +1 -0
  85. package/dist/core/compaction/compression-economics.js +151 -0
  86. package/dist/core/compaction/compression-economics.js.map +1 -0
  87. package/dist/core/compaction/utils.d.ts +28 -0
  88. package/dist/core/compaction/utils.d.ts.map +1 -0
  89. package/dist/core/compaction/utils.js +165 -0
  90. package/dist/core/compaction/utils.js.map +1 -0
  91. package/dist/core/defaults.d.ts +3 -0
  92. package/dist/core/defaults.d.ts.map +1 -0
  93. package/dist/core/defaults.js +2 -0
  94. package/dist/core/defaults.js.map +1 -0
  95. package/dist/core/diagnostics.d.ts +18 -0
  96. package/dist/core/diagnostics.d.ts.map +1 -0
  97. package/dist/core/diagnostics.js +2 -0
  98. package/dist/core/diagnostics.js.map +1 -0
  99. package/dist/core/event-bus.d.ts +9 -0
  100. package/dist/core/event-bus.d.ts.map +1 -0
  101. package/dist/core/event-bus.js +25 -0
  102. package/dist/core/event-bus.js.map +1 -0
  103. package/dist/core/exec.d.ts +29 -0
  104. package/dist/core/exec.d.ts.map +1 -0
  105. package/dist/core/exec.js +75 -0
  106. package/dist/core/exec.js.map +1 -0
  107. package/dist/core/export-html/ansi-to-html.d.ts +22 -0
  108. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -0
  109. package/dist/core/export-html/ansi-to-html.js +245 -0
  110. package/dist/core/export-html/ansi-to-html.js.map +1 -0
  111. package/dist/core/export-html/index.d.ts +21 -0
  112. package/dist/core/export-html/index.d.ts.map +1 -0
  113. package/dist/core/export-html/index.js +230 -0
  114. package/dist/core/export-html/index.js.map +1 -0
  115. package/dist/core/export-html/template.css +1066 -0
  116. package/dist/core/export-html/template.html +55 -0
  117. package/dist/core/export-html/template.js +1864 -0
  118. package/dist/core/export-html/tool-renderer.d.ts +32 -0
  119. package/dist/core/export-html/tool-renderer.d.ts.map +1 -0
  120. package/dist/core/export-html/tool-renderer.js +108 -0
  121. package/dist/core/export-html/tool-renderer.js.map +1 -0
  122. package/dist/core/export-html/vendor/highlight.min.js +1213 -0
  123. package/dist/core/export-html/vendor/marked.min.js +78 -0
  124. package/dist/core/extensions/loader.d.ts +24 -0
  125. package/dist/core/extensions/loader.d.ts.map +1 -0
  126. package/dist/core/extensions/loader.js +613 -0
  127. package/dist/core/extensions/loader.js.map +1 -0
  128. package/dist/core/extensions/runner.d.ts +160 -0
  129. package/dist/core/extensions/runner.d.ts.map +1 -0
  130. package/dist/core/extensions/runner.js +962 -0
  131. package/dist/core/extensions/runner.js.map +1 -0
  132. package/dist/core/extensions/types.d.ts +1311 -0
  133. package/dist/core/extensions/types.d.ts.map +1 -0
  134. package/dist/core/extensions/types.js +51 -0
  135. package/dist/core/extensions/types.js.map +1 -0
  136. package/dist/core/extensions/wrapper.d.ts +20 -0
  137. package/dist/core/extensions/wrapper.d.ts.map +1 -0
  138. package/dist/core/extensions/wrapper.js +22 -0
  139. package/dist/core/extensions/wrapper.js.map +1 -0
  140. package/dist/core/footer-data-provider.d.ts +52 -0
  141. package/dist/core/footer-data-provider.d.ts.map +1 -0
  142. package/dist/core/footer-data-provider.js +318 -0
  143. package/dist/core/footer-data-provider.js.map +1 -0
  144. package/dist/core/grip-agent.d.ts +240 -0
  145. package/dist/core/grip-agent.d.ts.map +1 -0
  146. package/dist/core/grip-agent.js +1243 -0
  147. package/dist/core/grip-agent.js.map +1 -0
  148. package/dist/core/grip-manifest.d.ts +9 -0
  149. package/dist/core/grip-manifest.d.ts.map +1 -0
  150. package/dist/core/grip-manifest.js +25 -0
  151. package/dist/core/grip-manifest.js.map +1 -0
  152. package/dist/core/hooks/aggregate.d.ts +5 -0
  153. package/dist/core/hooks/aggregate.d.ts.map +1 -0
  154. package/dist/core/hooks/aggregate.js +226 -0
  155. package/dist/core/hooks/aggregate.js.map +1 -0
  156. package/dist/core/hooks/config.d.ts +14 -0
  157. package/dist/core/hooks/config.d.ts.map +1 -0
  158. package/dist/core/hooks/config.js +372 -0
  159. package/dist/core/hooks/config.js.map +1 -0
  160. package/dist/core/hooks/executor.d.ts +12 -0
  161. package/dist/core/hooks/executor.d.ts.map +1 -0
  162. package/dist/core/hooks/executor.js +708 -0
  163. package/dist/core/hooks/executor.js.map +1 -0
  164. package/dist/core/hooks/index.d.ts +9 -0
  165. package/dist/core/hooks/index.d.ts.map +1 -0
  166. package/dist/core/hooks/index.js +14 -0
  167. package/dist/core/hooks/index.js.map +1 -0
  168. package/dist/core/hooks/matcher.d.ts +10 -0
  169. package/dist/core/hooks/matcher.d.ts.map +1 -0
  170. package/dist/core/hooks/matcher.js +70 -0
  171. package/dist/core/hooks/matcher.js.map +1 -0
  172. package/dist/core/hooks/trust-store.d.ts +38 -0
  173. package/dist/core/hooks/trust-store.d.ts.map +1 -0
  174. package/dist/core/hooks/trust-store.js +167 -0
  175. package/dist/core/hooks/trust-store.js.map +1 -0
  176. package/dist/core/hooks/types.d.ts +234 -0
  177. package/dist/core/hooks/types.d.ts.map +1 -0
  178. package/dist/core/hooks/types.js +52 -0
  179. package/dist/core/hooks/types.js.map +1 -0
  180. package/dist/core/http-dispatcher.d.ts +21 -0
  181. package/dist/core/http-dispatcher.d.ts.map +1 -0
  182. package/dist/core/http-dispatcher.js +82 -0
  183. package/dist/core/http-dispatcher.js.map +1 -0
  184. package/dist/core/instruction-resource-loader.d.ts +81 -0
  185. package/dist/core/instruction-resource-loader.d.ts.map +1 -0
  186. package/dist/core/instruction-resource-loader.js +574 -0
  187. package/dist/core/instruction-resource-loader.js.map +1 -0
  188. package/dist/core/keybindings.d.ts +399 -0
  189. package/dist/core/keybindings.d.ts.map +1 -0
  190. package/dist/core/keybindings.js +299 -0
  191. package/dist/core/keybindings.js.map +1 -0
  192. package/dist/core/lsp/abort.d.ts +3 -0
  193. package/dist/core/lsp/abort.d.ts.map +1 -0
  194. package/dist/core/lsp/abort.js +28 -0
  195. package/dist/core/lsp/abort.js.map +1 -0
  196. package/dist/core/lsp/client.d.ts +108 -0
  197. package/dist/core/lsp/client.d.ts.map +1 -0
  198. package/dist/core/lsp/client.js +586 -0
  199. package/dist/core/lsp/client.js.map +1 -0
  200. package/dist/core/lsp/config-loader.d.ts +44 -0
  201. package/dist/core/lsp/config-loader.d.ts.map +1 -0
  202. package/dist/core/lsp/config-loader.js +223 -0
  203. package/dist/core/lsp/config-loader.js.map +1 -0
  204. package/dist/core/lsp/config.d.ts +134 -0
  205. package/dist/core/lsp/config.d.ts.map +1 -0
  206. package/dist/core/lsp/config.js +682 -0
  207. package/dist/core/lsp/config.js.map +1 -0
  208. package/dist/core/lsp/diagnostics.d.ts +18 -0
  209. package/dist/core/lsp/diagnostics.d.ts.map +1 -0
  210. package/dist/core/lsp/diagnostics.js +311 -0
  211. package/dist/core/lsp/diagnostics.js.map +1 -0
  212. package/dist/core/lsp/file-sync.d.ts +58 -0
  213. package/dist/core/lsp/file-sync.d.ts.map +1 -0
  214. package/dist/core/lsp/file-sync.js +432 -0
  215. package/dist/core/lsp/file-sync.js.map +1 -0
  216. package/dist/core/lsp/integration.d.ts +62 -0
  217. package/dist/core/lsp/integration.d.ts.map +1 -0
  218. package/dist/core/lsp/integration.js +145 -0
  219. package/dist/core/lsp/integration.js.map +1 -0
  220. package/dist/core/lsp/language-map.d.ts +54 -0
  221. package/dist/core/lsp/language-map.d.ts.map +1 -0
  222. package/dist/core/lsp/language-map.js +300 -0
  223. package/dist/core/lsp/language-map.js.map +1 -0
  224. package/dist/core/lsp/manager.d.ts +120 -0
  225. package/dist/core/lsp/manager.d.ts.map +1 -0
  226. package/dist/core/lsp/manager.js +636 -0
  227. package/dist/core/lsp/manager.js.map +1 -0
  228. package/dist/core/lsp/navigation.d.ts +32 -0
  229. package/dist/core/lsp/navigation.d.ts.map +1 -0
  230. package/dist/core/lsp/navigation.js +327 -0
  231. package/dist/core/lsp/navigation.js.map +1 -0
  232. package/dist/core/lsp/portable-path.d.ts +18 -0
  233. package/dist/core/lsp/portable-path.d.ts.map +1 -0
  234. package/dist/core/lsp/portable-path.js +83 -0
  235. package/dist/core/lsp/portable-path.js.map +1 -0
  236. package/dist/core/lsp/refactor.d.ts +32 -0
  237. package/dist/core/lsp/refactor.d.ts.map +1 -0
  238. package/dist/core/lsp/refactor.js +519 -0
  239. package/dist/core/lsp/refactor.js.map +1 -0
  240. package/dist/core/lsp/transport.d.ts +39 -0
  241. package/dist/core/lsp/transport.d.ts.map +1 -0
  242. package/dist/core/lsp/transport.js +261 -0
  243. package/dist/core/lsp/transport.js.map +1 -0
  244. package/dist/core/messages.d.ts +34 -0
  245. package/dist/core/messages.d.ts.map +1 -0
  246. package/dist/core/messages.js +140 -0
  247. package/dist/core/messages.js.map +1 -0
  248. package/dist/core/model-registry.d.ts +148 -0
  249. package/dist/core/model-registry.d.ts.map +1 -0
  250. package/dist/core/model-registry.js +812 -0
  251. package/dist/core/model-registry.js.map +1 -0
  252. package/dist/core/model-resolver.d.ts +115 -0
  253. package/dist/core/model-resolver.d.ts.map +1 -0
  254. package/dist/core/model-resolver.js +498 -0
  255. package/dist/core/model-resolver.js.map +1 -0
  256. package/dist/core/output-guard.d.ts +7 -0
  257. package/dist/core/output-guard.d.ts.map +1 -0
  258. package/dist/core/output-guard.js +89 -0
  259. package/dist/core/output-guard.js.map +1 -0
  260. package/dist/core/package-manager.d.ts +209 -0
  261. package/dist/core/package-manager.d.ts.map +1 -0
  262. package/dist/core/package-manager.js +2341 -0
  263. package/dist/core/package-manager.js.map +1 -0
  264. package/dist/core/prompt-templates.d.ts +57 -0
  265. package/dist/core/prompt-templates.d.ts.map +1 -0
  266. package/dist/core/prompt-templates.js +353 -0
  267. package/dist/core/prompt-templates.js.map +1 -0
  268. package/dist/core/provider-display-names.d.ts +2 -0
  269. package/dist/core/provider-display-names.d.ts.map +1 -0
  270. package/dist/core/provider-display-names.js +33 -0
  271. package/dist/core/provider-display-names.js.map +1 -0
  272. package/dist/core/remote-workspace-protocol/contract.d.ts +465 -0
  273. package/dist/core/remote-workspace-protocol/contract.d.ts.map +1 -0
  274. package/dist/core/remote-workspace-protocol/contract.js +825 -0
  275. package/dist/core/remote-workspace-protocol/contract.js.map +1 -0
  276. package/dist/core/remote-workspace-protocol/guest-shared-client.d.ts +16 -0
  277. package/dist/core/remote-workspace-protocol/guest-shared-client.d.ts.map +1 -0
  278. package/dist/core/remote-workspace-protocol/guest-shared-client.js +54 -0
  279. package/dist/core/remote-workspace-protocol/guest-shared-client.js.map +1 -0
  280. package/dist/core/remote-workspace-protocol/guest-shared-outbound-scheduler.d.ts +23 -0
  281. package/dist/core/remote-workspace-protocol/guest-shared-outbound-scheduler.d.ts.map +1 -0
  282. package/dist/core/remote-workspace-protocol/guest-shared-outbound-scheduler.js +112 -0
  283. package/dist/core/remote-workspace-protocol/guest-shared-outbound-scheduler.js.map +1 -0
  284. package/dist/core/remote-workspace-protocol/guest-shared-uplink.d.ts +30 -0
  285. package/dist/core/remote-workspace-protocol/guest-shared-uplink.d.ts.map +1 -0
  286. package/dist/core/remote-workspace-protocol/guest-shared-uplink.js +243 -0
  287. package/dist/core/remote-workspace-protocol/guest-shared-uplink.js.map +1 -0
  288. package/dist/core/remote-workspace-protocol/lima-owner-directory.d.ts +3 -0
  289. package/dist/core/remote-workspace-protocol/lima-owner-directory.d.ts.map +1 -0
  290. package/dist/core/remote-workspace-protocol/lima-owner-directory.js +31 -0
  291. package/dist/core/remote-workspace-protocol/lima-owner-directory.js.map +1 -0
  292. package/dist/core/remote-workspace-protocol/lima-owner-lock.d.ts +9 -0
  293. package/dist/core/remote-workspace-protocol/lima-owner-lock.d.ts.map +1 -0
  294. package/dist/core/remote-workspace-protocol/lima-owner-lock.js +89 -0
  295. package/dist/core/remote-workspace-protocol/lima-owner-lock.js.map +1 -0
  296. package/dist/core/remote-workspace-protocol/session.d.ts +249 -0
  297. package/dist/core/remote-workspace-protocol/session.d.ts.map +1 -0
  298. package/dist/core/remote-workspace-protocol/session.js +1842 -0
  299. package/dist/core/remote-workspace-protocol/session.js.map +1 -0
  300. package/dist/core/remote-workspace-protocol/shared-transport.d.ts +71 -0
  301. package/dist/core/remote-workspace-protocol/shared-transport.d.ts.map +1 -0
  302. package/dist/core/remote-workspace-protocol/shared-transport.js +68 -0
  303. package/dist/core/remote-workspace-protocol/shared-transport.js.map +1 -0
  304. package/dist/core/resolve-config-value.d.ts +32 -0
  305. package/dist/core/resolve-config-value.d.ts.map +1 -0
  306. package/dist/core/resolve-config-value.js +257 -0
  307. package/dist/core/resolve-config-value.js.map +1 -0
  308. package/dist/core/resource-loader.d.ts +200 -0
  309. package/dist/core/resource-loader.d.ts.map +1 -0
  310. package/dist/core/resource-loader.js +1209 -0
  311. package/dist/core/resource-loader.js.map +1 -0
  312. package/dist/core/rules.d.ts +40 -0
  313. package/dist/core/rules.d.ts.map +1 -0
  314. package/dist/core/rules.js +57 -0
  315. package/dist/core/rules.js.map +1 -0
  316. package/dist/core/sandbox/command.d.ts +25 -0
  317. package/dist/core/sandbox/command.d.ts.map +1 -0
  318. package/dist/core/sandbox/command.js +102 -0
  319. package/dist/core/sandbox/command.js.map +1 -0
  320. package/dist/core/sandbox/config.d.ts +91 -0
  321. package/dist/core/sandbox/config.d.ts.map +1 -0
  322. package/dist/core/sandbox/config.js +88 -0
  323. package/dist/core/sandbox/config.js.map +1 -0
  324. package/dist/core/sandbox/lima-guest-binary.d.ts +11 -0
  325. package/dist/core/sandbox/lima-guest-binary.d.ts.map +1 -0
  326. package/dist/core/sandbox/lima-guest-binary.js +140 -0
  327. package/dist/core/sandbox/lima-guest-binary.js.map +1 -0
  328. package/dist/core/sandbox/lima.d.ts +57 -0
  329. package/dist/core/sandbox/lima.d.ts.map +1 -0
  330. package/dist/core/sandbox/lima.js +716 -0
  331. package/dist/core/sandbox/lima.js.map +1 -0
  332. package/dist/core/sandbox/shared-lima-roots.d.ts +11 -0
  333. package/dist/core/sandbox/shared-lima-roots.d.ts.map +1 -0
  334. package/dist/core/sandbox/shared-lima-roots.js +25 -0
  335. package/dist/core/sandbox/shared-lima-roots.js.map +1 -0
  336. package/dist/core/sandbox/update-shared-guest-binary.d.ts +8 -0
  337. package/dist/core/sandbox/update-shared-guest-binary.d.ts.map +1 -0
  338. package/dist/core/sandbox/update-shared-guest-binary.js +100 -0
  339. package/dist/core/sandbox/update-shared-guest-binary.js.map +1 -0
  340. package/dist/core/session/constants.d.ts +2 -0
  341. package/dist/core/session/constants.d.ts.map +1 -0
  342. package/dist/core/session/constants.js +2 -0
  343. package/dist/core/session/constants.js.map +1 -0
  344. package/dist/core/session/context-metadata.d.ts +5 -0
  345. package/dist/core/session/context-metadata.d.ts.map +1 -0
  346. package/dist/core/session/context-metadata.js +55 -0
  347. package/dist/core/session/context-metadata.js.map +1 -0
  348. package/dist/core/session/context.d.ts +14 -0
  349. package/dist/core/session/context.d.ts.map +1 -0
  350. package/dist/core/session/context.js +117 -0
  351. package/dist/core/session/context.js.map +1 -0
  352. package/dist/core/session/ids.d.ts +9 -0
  353. package/dist/core/session/ids.d.ts.map +1 -0
  354. package/dist/core/session/ids.js +21 -0
  355. package/dist/core/session/ids.js.map +1 -0
  356. package/dist/core/session/in-memory-session-manager.d.ts +17 -0
  357. package/dist/core/session/in-memory-session-manager.d.ts.map +1 -0
  358. package/dist/core/session/in-memory-session-manager.js +40 -0
  359. package/dist/core/session/in-memory-session-manager.js.map +1 -0
  360. package/dist/core/session/in-memory-session.d.ts +7 -0
  361. package/dist/core/session/in-memory-session.d.ts.map +1 -0
  362. package/dist/core/session/in-memory-session.js +11 -0
  363. package/dist/core/session/in-memory-session.js.map +1 -0
  364. package/dist/core/session/jsonl-errors.d.ts +36 -0
  365. package/dist/core/session/jsonl-errors.d.ts.map +1 -0
  366. package/dist/core/session/jsonl-errors.js +49 -0
  367. package/dist/core/session/jsonl-errors.js.map +1 -0
  368. package/dist/core/session/jsonl-helpers.d.ts +20 -0
  369. package/dist/core/session/jsonl-helpers.d.ts.map +1 -0
  370. package/dist/core/session/jsonl-helpers.js +21 -0
  371. package/dist/core/session/jsonl-helpers.js.map +1 -0
  372. package/dist/core/session/local-session-manager.d.ts +30 -0
  373. package/dist/core/session/local-session-manager.d.ts.map +1 -0
  374. package/dist/core/session/local-session-manager.js +205 -0
  375. package/dist/core/session/local-session-manager.js.map +1 -0
  376. package/dist/core/session/local-session.d.ts +9 -0
  377. package/dist/core/session/local-session.d.ts.map +1 -0
  378. package/dist/core/session/local-session.js +15 -0
  379. package/dist/core/session/local-session.js.map +1 -0
  380. package/dist/core/session/migrations.d.ts +11 -0
  381. package/dist/core/session/migrations.d.ts.map +1 -0
  382. package/dist/core/session/migrations.js +78 -0
  383. package/dist/core/session/migrations.js.map +1 -0
  384. package/dist/core/session/remote-session-client.d.ts +83 -0
  385. package/dist/core/session/remote-session-client.d.ts.map +1 -0
  386. package/dist/core/session/remote-session-client.js +224 -0
  387. package/dist/core/session/remote-session-client.js.map +1 -0
  388. package/dist/core/session/remote-session-manager.d.ts +32 -0
  389. package/dist/core/session/remote-session-manager.d.ts.map +1 -0
  390. package/dist/core/session/remote-session-manager.js +124 -0
  391. package/dist/core/session/remote-session-manager.js.map +1 -0
  392. package/dist/core/session/remote-session.d.ts +20 -0
  393. package/dist/core/session/remote-session.d.ts.map +1 -0
  394. package/dist/core/session/remote-session.js +33 -0
  395. package/dist/core/session/remote-session.js.map +1 -0
  396. package/dist/core/session/session-manager.d.ts +18 -0
  397. package/dist/core/session/session-manager.d.ts.map +1 -0
  398. package/dist/core/session/session-manager.js +2 -0
  399. package/dist/core/session/session-manager.js.map +1 -0
  400. package/dist/core/session/session.d.ts +140 -0
  401. package/dist/core/session/session.d.ts.map +1 -0
  402. package/dist/core/session/session.js +461 -0
  403. package/dist/core/session/session.js.map +1 -0
  404. package/dist/core/session/stores/in-memory-session-store.d.ts +39 -0
  405. package/dist/core/session/stores/in-memory-session-store.d.ts.map +1 -0
  406. package/dist/core/session/stores/in-memory-session-store.js +168 -0
  407. package/dist/core/session/stores/in-memory-session-store.js.map +1 -0
  408. package/dist/core/session/stores/jsonl-session-store.d.ts +97 -0
  409. package/dist/core/session/stores/jsonl-session-store.d.ts.map +1 -0
  410. package/dist/core/session/stores/jsonl-session-store.js +1140 -0
  411. package/dist/core/session/stores/jsonl-session-store.js.map +1 -0
  412. package/dist/core/session/stores/remote-session-store.d.ts +44 -0
  413. package/dist/core/session/stores/remote-session-store.d.ts.map +1 -0
  414. package/dist/core/session/stores/remote-session-store.js +159 -0
  415. package/dist/core/session/stores/remote-session-store.js.map +1 -0
  416. package/dist/core/session/stores/session-store.d.ts +42 -0
  417. package/dist/core/session/stores/session-store.d.ts.map +1 -0
  418. package/dist/core/session/stores/session-store.js +2 -0
  419. package/dist/core/session/stores/session-store.js.map +1 -0
  420. package/dist/core/session/types.d.ts +141 -0
  421. package/dist/core/session/types.d.ts.map +1 -0
  422. package/dist/core/session/types.js +2 -0
  423. package/dist/core/session/types.js.map +1 -0
  424. package/dist/core/session/usage-ledger.d.ts +18 -0
  425. package/dist/core/session/usage-ledger.d.ts.map +1 -0
  426. package/dist/core/session/usage-ledger.js +68 -0
  427. package/dist/core/session/usage-ledger.js.map +1 -0
  428. package/dist/core/session-cwd.d.ts +19 -0
  429. package/dist/core/session-cwd.d.ts.map +1 -0
  430. package/dist/core/session-cwd.js +38 -0
  431. package/dist/core/session-cwd.js.map +1 -0
  432. package/dist/core/settings-manager.d.ts +314 -0
  433. package/dist/core/settings-manager.d.ts.map +1 -0
  434. package/dist/core/settings-manager.js +991 -0
  435. package/dist/core/settings-manager.js.map +1 -0
  436. package/dist/core/skills.d.ts +40 -0
  437. package/dist/core/skills.d.ts.map +1 -0
  438. package/dist/core/skills.js +57 -0
  439. package/dist/core/skills.js.map +1 -0
  440. package/dist/core/slash-commands.d.ts +15 -0
  441. package/dist/core/slash-commands.d.ts.map +1 -0
  442. package/dist/core/slash-commands.js +36 -0
  443. package/dist/core/slash-commands.js.map +1 -0
  444. package/dist/core/source-info.d.ts +26 -0
  445. package/dist/core/source-info.d.ts.map +1 -0
  446. package/dist/core/source-info.js +27 -0
  447. package/dist/core/source-info.js.map +1 -0
  448. package/dist/core/system-prompt.d.ts +32 -0
  449. package/dist/core/system-prompt.d.ts.map +1 -0
  450. package/dist/core/system-prompt.js +131 -0
  451. package/dist/core/system-prompt.js.map +1 -0
  452. package/dist/core/telemetry.d.ts +3 -0
  453. package/dist/core/telemetry.d.ts.map +1 -0
  454. package/dist/core/telemetry.js +9 -0
  455. package/dist/core/telemetry.js.map +1 -0
  456. package/dist/core/timings.d.ts +10 -0
  457. package/dist/core/timings.d.ts.map +1 -0
  458. package/dist/core/timings.js +41 -0
  459. package/dist/core/timings.js.map +1 -0
  460. package/dist/core/tools/bash.d.ts +51 -0
  461. package/dist/core/tools/bash.d.ts.map +1 -0
  462. package/dist/core/tools/bash.js +321 -0
  463. package/dist/core/tools/bash.js.map +1 -0
  464. package/dist/core/tools/compress-context.d.ts +27 -0
  465. package/dist/core/tools/compress-context.d.ts.map +1 -0
  466. package/dist/core/tools/compress-context.js +142 -0
  467. package/dist/core/tools/compress-context.js.map +1 -0
  468. package/dist/core/tools/edit-diff.d.ts +82 -0
  469. package/dist/core/tools/edit-diff.d.ts.map +1 -0
  470. package/dist/core/tools/edit-diff.js +327 -0
  471. package/dist/core/tools/edit-diff.js.map +1 -0
  472. package/dist/core/tools/edit.d.ts +50 -0
  473. package/dist/core/tools/edit.d.ts.map +1 -0
  474. package/dist/core/tools/edit.js +324 -0
  475. package/dist/core/tools/edit.js.map +1 -0
  476. package/dist/core/tools/file-mutation-queue.d.ts +8 -0
  477. package/dist/core/tools/file-mutation-queue.d.ts.map +1 -0
  478. package/dist/core/tools/file-mutation-queue.js +69 -0
  479. package/dist/core/tools/file-mutation-queue.js.map +1 -0
  480. package/dist/core/tools/find.d.ts +22 -0
  481. package/dist/core/tools/find.d.ts.map +1 -0
  482. package/dist/core/tools/find.js +268 -0
  483. package/dist/core/tools/find.js.map +1 -0
  484. package/dist/core/tools/grep.d.ts +27 -0
  485. package/dist/core/tools/grep.d.ts.map +1 -0
  486. package/dist/core/tools/grep.js +332 -0
  487. package/dist/core/tools/grep.js.map +1 -0
  488. package/dist/core/tools/hash-store.d.ts +12 -0
  489. package/dist/core/tools/hash-store.d.ts.map +1 -0
  490. package/dist/core/tools/hash-store.js +48 -0
  491. package/dist/core/tools/hash-store.js.map +1 -0
  492. package/dist/core/tools/hashline/apply.d.ts +40 -0
  493. package/dist/core/tools/hashline/apply.d.ts.map +1 -0
  494. package/dist/core/tools/hashline/apply.js +261 -0
  495. package/dist/core/tools/hashline/apply.js.map +1 -0
  496. package/dist/core/tools/hashline/hash.d.ts +56 -0
  497. package/dist/core/tools/hashline/hash.d.ts.map +1 -0
  498. package/dist/core/tools/hashline/hash.js +196 -0
  499. package/dist/core/tools/hashline/hash.js.map +1 -0
  500. package/dist/core/tools/hashline/parse.d.ts +8 -0
  501. package/dist/core/tools/hashline/parse.d.ts.map +1 -0
  502. package/dist/core/tools/hashline/parse.js +41 -0
  503. package/dist/core/tools/hashline/parse.js.map +1 -0
  504. package/dist/core/tools/hashline/resolve.d.ts +51 -0
  505. package/dist/core/tools/hashline/resolve.d.ts.map +1 -0
  506. package/dist/core/tools/hashline/resolve.js +187 -0
  507. package/dist/core/tools/hashline/resolve.js.map +1 -0
  508. package/dist/core/tools/hashline-utils.d.ts +6 -0
  509. package/dist/core/tools/hashline-utils.d.ts.map +1 -0
  510. package/dist/core/tools/hashline-utils.js +23 -0
  511. package/dist/core/tools/hashline-utils.js.map +1 -0
  512. package/dist/core/tools/index.d.ts +36 -0
  513. package/dist/core/tools/index.d.ts.map +1 -0
  514. package/dist/core/tools/index.js +141 -0
  515. package/dist/core/tools/index.js.map +1 -0
  516. package/dist/core/tools/ls.d.ts +21 -0
  517. package/dist/core/tools/ls.d.ts.map +1 -0
  518. package/dist/core/tools/ls.js +156 -0
  519. package/dist/core/tools/ls.js.map +1 -0
  520. package/dist/core/tools/operations.d.ts +212 -0
  521. package/dist/core/tools/operations.d.ts.map +1 -0
  522. package/dist/core/tools/operations.js +793 -0
  523. package/dist/core/tools/operations.js.map +1 -0
  524. package/dist/core/tools/output-accumulator.d.ts +54 -0
  525. package/dist/core/tools/output-accumulator.d.ts.map +1 -0
  526. package/dist/core/tools/output-accumulator.js +184 -0
  527. package/dist/core/tools/output-accumulator.js.map +1 -0
  528. package/dist/core/tools/path-utils.d.ts +9 -0
  529. package/dist/core/tools/path-utils.d.ts.map +1 -0
  530. package/dist/core/tools/path-utils.js +99 -0
  531. package/dist/core/tools/path-utils.js.map +1 -0
  532. package/dist/core/tools/read.d.ts +32 -0
  533. package/dist/core/tools/read.d.ts.map +1 -0
  534. package/dist/core/tools/read.js +318 -0
  535. package/dist/core/tools/read.js.map +1 -0
  536. package/dist/core/tools/render-utils.d.ts +33 -0
  537. package/dist/core/tools/render-utils.d.ts.map +1 -0
  538. package/dist/core/tools/render-utils.js +61 -0
  539. package/dist/core/tools/render-utils.js.map +1 -0
  540. package/dist/core/tools/replace-diff.d.ts +16 -0
  541. package/dist/core/tools/replace-diff.d.ts.map +1 -0
  542. package/dist/core/tools/replace-diff.js +117 -0
  543. package/dist/core/tools/replace-diff.js.map +1 -0
  544. package/dist/core/tools/replace-normalize.d.ts +2 -0
  545. package/dist/core/tools/replace-normalize.d.ts.map +1 -0
  546. package/dist/core/tools/replace-normalize.js +73 -0
  547. package/dist/core/tools/replace-normalize.js.map +1 -0
  548. package/dist/core/tools/replace-render.d.ts +51 -0
  549. package/dist/core/tools/replace-render.d.ts.map +1 -0
  550. package/dist/core/tools/replace-render.js +162 -0
  551. package/dist/core/tools/replace-render.js.map +1 -0
  552. package/dist/core/tools/runtime.d.ts +2 -0
  553. package/dist/core/tools/runtime.d.ts.map +1 -0
  554. package/dist/core/tools/runtime.js +6 -0
  555. package/dist/core/tools/runtime.js.map +1 -0
  556. package/dist/core/tools/session-history.d.ts +55 -0
  557. package/dist/core/tools/session-history.d.ts.map +1 -0
  558. package/dist/core/tools/session-history.js +649 -0
  559. package/dist/core/tools/session-history.js.map +1 -0
  560. package/dist/core/tools/subagent-agents.d.ts +29 -0
  561. package/dist/core/tools/subagent-agents.d.ts.map +1 -0
  562. package/dist/core/tools/subagent-agents.js +223 -0
  563. package/dist/core/tools/subagent-agents.js.map +1 -0
  564. package/dist/core/tools/subagent.d.ts +185 -0
  565. package/dist/core/tools/subagent.d.ts.map +1 -0
  566. package/dist/core/tools/subagent.js +1309 -0
  567. package/dist/core/tools/subagent.js.map +1 -0
  568. package/dist/core/tools/tool-definition-wrapper.d.ts +14 -0
  569. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -0
  570. package/dist/core/tools/tool-definition-wrapper.js +34 -0
  571. package/dist/core/tools/tool-definition-wrapper.js.map +1 -0
  572. package/dist/core/tools/truncate.d.ts +39 -0
  573. package/dist/core/tools/truncate.d.ts.map +1 -0
  574. package/dist/core/tools/truncate.js +215 -0
  575. package/dist/core/tools/truncate.js.map +1 -0
  576. package/dist/core/tools/websearch.d.ts +33 -0
  577. package/dist/core/tools/websearch.d.ts.map +1 -0
  578. package/dist/core/tools/websearch.js +341 -0
  579. package/dist/core/tools/websearch.js.map +1 -0
  580. package/dist/core/tools/workspace-tool-host.d.ts +102 -0
  581. package/dist/core/tools/workspace-tool-host.d.ts.map +1 -0
  582. package/dist/core/tools/workspace-tool-host.js +348 -0
  583. package/dist/core/tools/workspace-tool-host.js.map +1 -0
  584. package/dist/core/tools/write.d.ts +16 -0
  585. package/dist/core/tools/write.d.ts.map +1 -0
  586. package/dist/core/tools/write.js +204 -0
  587. package/dist/core/tools/write.js.map +1 -0
  588. package/dist/core/workspace-identity.d.ts +7 -0
  589. package/dist/core/workspace-identity.d.ts.map +1 -0
  590. package/dist/core/workspace-identity.js +2 -0
  591. package/dist/core/workspace-identity.js.map +1 -0
  592. package/dist/daemon/activity-budget.d.ts +10 -0
  593. package/dist/daemon/activity-budget.d.ts.map +1 -0
  594. package/dist/daemon/activity-budget.js +34 -0
  595. package/dist/daemon/activity-budget.js.map +1 -0
  596. package/dist/daemon/command.d.ts +6 -0
  597. package/dist/daemon/command.d.ts.map +1 -0
  598. package/dist/daemon/command.js +58 -0
  599. package/dist/daemon/command.js.map +1 -0
  600. package/dist/daemon/config.d.ts +45 -0
  601. package/dist/daemon/config.d.ts.map +1 -0
  602. package/dist/daemon/config.js +319 -0
  603. package/dist/daemon/config.js.map +1 -0
  604. package/dist/daemon/help.d.ts +2 -0
  605. package/dist/daemon/help.d.ts.map +1 -0
  606. package/dist/daemon/help.js +42 -0
  607. package/dist/daemon/help.js.map +1 -0
  608. package/dist/daemon/lsp-config.d.ts +4 -0
  609. package/dist/daemon/lsp-config.d.ts.map +1 -0
  610. package/dist/daemon/lsp-config.js +155 -0
  611. package/dist/daemon/lsp-config.js.map +1 -0
  612. package/dist/daemon/outbound-budget.d.ts +10 -0
  613. package/dist/daemon/outbound-budget.d.ts.map +1 -0
  614. package/dist/daemon/outbound-budget.js +30 -0
  615. package/dist/daemon/outbound-budget.js.map +1 -0
  616. package/dist/daemon/security.d.ts +19 -0
  617. package/dist/daemon/security.d.ts.map +1 -0
  618. package/dist/daemon/security.js +177 -0
  619. package/dist/daemon/security.js.map +1 -0
  620. package/dist/daemon/server.d.ts +20 -0
  621. package/dist/daemon/server.d.ts.map +1 -0
  622. package/dist/daemon/server.js +480 -0
  623. package/dist/daemon/server.js.map +1 -0
  624. package/dist/daemon/shared-connection.d.ts +33 -0
  625. package/dist/daemon/shared-connection.d.ts.map +1 -0
  626. package/dist/daemon/shared-connection.js +271 -0
  627. package/dist/daemon/shared-connection.js.map +1 -0
  628. package/dist/daemon/shared-revision.d.ts +5 -0
  629. package/dist/daemon/shared-revision.d.ts.map +1 -0
  630. package/dist/daemon/shared-revision.js +61 -0
  631. package/dist/daemon/shared-revision.js.map +1 -0
  632. package/dist/daemon/shared-roots.d.ts +9 -0
  633. package/dist/daemon/shared-roots.d.ts.map +1 -0
  634. package/dist/daemon/shared-roots.js +33 -0
  635. package/dist/daemon/shared-roots.js.map +1 -0
  636. package/dist/daemon/workspace-runtime.d.ts +46 -0
  637. package/dist/daemon/workspace-runtime.d.ts.map +1 -0
  638. package/dist/daemon/workspace-runtime.js +705 -0
  639. package/dist/daemon/workspace-runtime.js.map +1 -0
  640. package/dist/index.d.ts +109 -0
  641. package/dist/index.d.ts.map +1 -0
  642. package/dist/index.js +107 -0
  643. package/dist/index.js.map +1 -0
  644. package/dist/main.d.ts +39 -0
  645. package/dist/main.d.ts.map +1 -0
  646. package/dist/main.js +765 -0
  647. package/dist/main.js.map +1 -0
  648. package/dist/migrations.d.ts +35 -0
  649. package/dist/migrations.d.ts.map +1 -0
  650. package/dist/migrations.js +412 -0
  651. package/dist/migrations.js.map +1 -0
  652. package/dist/modes/interactive/components/assistant-message.d.ts +30 -0
  653. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -0
  654. package/dist/modes/interactive/components/assistant-message.js +159 -0
  655. package/dist/modes/interactive/components/assistant-message.js.map +1 -0
  656. package/dist/modes/interactive/components/bash-execution.d.ts +36 -0
  657. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -0
  658. package/dist/modes/interactive/components/bash-execution.js +173 -0
  659. package/dist/modes/interactive/components/bash-execution.js.map +1 -0
  660. package/dist/modes/interactive/components/bordered-loader.d.ts +18 -0
  661. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -0
  662. package/dist/modes/interactive/components/bordered-loader.js +54 -0
  663. package/dist/modes/interactive/components/bordered-loader.js.map +1 -0
  664. package/dist/modes/interactive/components/branch-summary-message.d.ts +17 -0
  665. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -0
  666. package/dist/modes/interactive/components/branch-summary-message.js +45 -0
  667. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -0
  668. package/dist/modes/interactive/components/compaction-summary-message.d.ts +17 -0
  669. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -0
  670. package/dist/modes/interactive/components/compaction-summary-message.js +46 -0
  671. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -0
  672. package/dist/modes/interactive/components/config-selector.d.ts +74 -0
  673. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -0
  674. package/dist/modes/interactive/components/config-selector.js +514 -0
  675. package/dist/modes/interactive/components/config-selector.js.map +1 -0
  676. package/dist/modes/interactive/components/countdown-timer.d.ts +14 -0
  677. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -0
  678. package/dist/modes/interactive/components/countdown-timer.js +33 -0
  679. package/dist/modes/interactive/components/countdown-timer.js.map +1 -0
  680. package/dist/modes/interactive/components/custom-editor.d.ts +25 -0
  681. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -0
  682. package/dist/modes/interactive/components/custom-editor.js +85 -0
  683. package/dist/modes/interactive/components/custom-editor.js.map +1 -0
  684. package/dist/modes/interactive/components/custom-message.d.ts +20 -0
  685. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -0
  686. package/dist/modes/interactive/components/custom-message.js +81 -0
  687. package/dist/modes/interactive/components/custom-message.js.map +1 -0
  688. package/dist/modes/interactive/components/diff.d.ts +12 -0
  689. package/dist/modes/interactive/components/diff.d.ts.map +1 -0
  690. package/dist/modes/interactive/components/diff.js +118 -0
  691. package/dist/modes/interactive/components/diff.js.map +1 -0
  692. package/dist/modes/interactive/components/dynamic-border.d.ts +15 -0
  693. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -0
  694. package/dist/modes/interactive/components/dynamic-border.js +21 -0
  695. package/dist/modes/interactive/components/dynamic-border.js.map +1 -0
  696. package/dist/modes/interactive/components/extension-editor.d.ts +22 -0
  697. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -0
  698. package/dist/modes/interactive/components/extension-editor.js +128 -0
  699. package/dist/modes/interactive/components/extension-editor.js.map +1 -0
  700. package/dist/modes/interactive/components/extension-input.d.ts +23 -0
  701. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -0
  702. package/dist/modes/interactive/components/extension-input.js +61 -0
  703. package/dist/modes/interactive/components/extension-input.js.map +1 -0
  704. package/dist/modes/interactive/components/extension-selector.d.ts +26 -0
  705. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -0
  706. package/dist/modes/interactive/components/extension-selector.js +83 -0
  707. package/dist/modes/interactive/components/extension-selector.js.map +1 -0
  708. package/dist/modes/interactive/components/footer.d.ts +36 -0
  709. package/dist/modes/interactive/components/footer.d.ts.map +1 -0
  710. package/dist/modes/interactive/components/footer.js +227 -0
  711. package/dist/modes/interactive/components/footer.js.map +1 -0
  712. package/dist/modes/interactive/components/hook-execution.d.ts +19 -0
  713. package/dist/modes/interactive/components/hook-execution.d.ts.map +1 -0
  714. package/dist/modes/interactive/components/hook-execution.js +185 -0
  715. package/dist/modes/interactive/components/hook-execution.js.map +1 -0
  716. package/dist/modes/interactive/components/keybinding-hints.d.ts +13 -0
  717. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -0
  718. package/dist/modes/interactive/components/keybinding-hints.js +36 -0
  719. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -0
  720. package/dist/modes/interactive/components/login-dialog.d.ts +55 -0
  721. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -0
  722. package/dist/modes/interactive/components/login-dialog.js +176 -0
  723. package/dist/modes/interactive/components/login-dialog.js.map +1 -0
  724. package/dist/modes/interactive/components/markdown-transform.d.ts +4 -0
  725. package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -0
  726. package/dist/modes/interactive/components/markdown-transform.js +19 -0
  727. package/dist/modes/interactive/components/markdown-transform.js.map +1 -0
  728. package/dist/modes/interactive/components/mermaid.d.ts +14 -0
  729. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -0
  730. package/dist/modes/interactive/components/mermaid.js +228 -0
  731. package/dist/modes/interactive/components/mermaid.js.map +1 -0
  732. package/dist/modes/interactive/components/message-card.d.ts +9 -0
  733. package/dist/modes/interactive/components/message-card.d.ts.map +1 -0
  734. package/dist/modes/interactive/components/message-card.js +24 -0
  735. package/dist/modes/interactive/components/message-card.js.map +1 -0
  736. package/dist/modes/interactive/components/model-selector.d.ts +52 -0
  737. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -0
  738. package/dist/modes/interactive/components/model-selector.js +296 -0
  739. package/dist/modes/interactive/components/model-selector.js.map +1 -0
  740. package/dist/modes/interactive/components/oauth-selector.d.ts +33 -0
  741. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -0
  742. package/dist/modes/interactive/components/oauth-selector.js +165 -0
  743. package/dist/modes/interactive/components/oauth-selector.js.map +1 -0
  744. package/dist/modes/interactive/components/scoped-models-selector.d.ts +50 -0
  745. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -0
  746. package/dist/modes/interactive/components/scoped-models-selector.js +300 -0
  747. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -0
  748. package/dist/modes/interactive/components/session-selector-search.d.ts +22 -0
  749. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -0
  750. package/dist/modes/interactive/components/session-selector-search.js +144 -0
  751. package/dist/modes/interactive/components/session-selector-search.js.map +1 -0
  752. package/dist/modes/interactive/components/session-selector.d.ts +108 -0
  753. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -0
  754. package/dist/modes/interactive/components/session-selector.js +835 -0
  755. package/dist/modes/interactive/components/session-selector.js.map +1 -0
  756. package/dist/modes/interactive/components/settings-selector.d.ts +81 -0
  757. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -0
  758. package/dist/modes/interactive/components/settings-selector.js +455 -0
  759. package/dist/modes/interactive/components/settings-selector.js.map +1 -0
  760. package/dist/modes/interactive/components/show-images-selector.d.ts +10 -0
  761. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -0
  762. package/dist/modes/interactive/components/show-images-selector.js +39 -0
  763. package/dist/modes/interactive/components/show-images-selector.js.map +1 -0
  764. package/dist/modes/interactive/components/skill-invocation-message.d.ts +18 -0
  765. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -0
  766. package/dist/modes/interactive/components/skill-invocation-message.js +48 -0
  767. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -0
  768. package/dist/modes/interactive/components/theme-selector.d.ts +11 -0
  769. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -0
  770. package/dist/modes/interactive/components/theme-selector.js +50 -0
  771. package/dist/modes/interactive/components/theme-selector.js.map +1 -0
  772. package/dist/modes/interactive/components/thinking-selector.d.ts +11 -0
  773. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -0
  774. package/dist/modes/interactive/components/thinking-selector.js +51 -0
  775. package/dist/modes/interactive/components/thinking-selector.js.map +1 -0
  776. package/dist/modes/interactive/components/tool-execution.d.ts +67 -0
  777. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -0
  778. package/dist/modes/interactive/components/tool-execution.js +312 -0
  779. package/dist/modes/interactive/components/tool-execution.js.map +1 -0
  780. package/dist/modes/interactive/components/tree-selector.d.ts +127 -0
  781. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -0
  782. package/dist/modes/interactive/components/tree-selector.js +1098 -0
  783. package/dist/modes/interactive/components/tree-selector.js.map +1 -0
  784. package/dist/modes/interactive/components/user-message-selector.d.ts +30 -0
  785. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -0
  786. package/dist/modes/interactive/components/user-message-selector.js +114 -0
  787. package/dist/modes/interactive/components/user-message-selector.js.map +1 -0
  788. package/dist/modes/interactive/components/user-message.d.ts +16 -0
  789. package/dist/modes/interactive/components/user-message.d.ts.map +1 -0
  790. package/dist/modes/interactive/components/user-message.js +50 -0
  791. package/dist/modes/interactive/components/user-message.js.map +1 -0
  792. package/dist/modes/interactive/components/visual-truncate.d.ts +24 -0
  793. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -0
  794. package/dist/modes/interactive/components/visual-truncate.js +33 -0
  795. package/dist/modes/interactive/components/visual-truncate.js.map +1 -0
  796. package/dist/modes/interactive/interactive-mode.d.ts +554 -0
  797. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -0
  798. package/dist/modes/interactive/interactive-mode.js +5870 -0
  799. package/dist/modes/interactive/interactive-mode.js.map +1 -0
  800. package/dist/modes/interactive/theme/dark.json +86 -0
  801. package/dist/modes/interactive/theme/light.json +85 -0
  802. package/dist/modes/interactive/theme/theme-schema.json +335 -0
  803. package/dist/modes/interactive/theme/theme.d.ts +109 -0
  804. package/dist/modes/interactive/theme/theme.d.ts.map +1 -0
  805. package/dist/modes/interactive/theme/theme.js +1040 -0
  806. package/dist/modes/interactive/theme/theme.js.map +1 -0
  807. package/dist/modes/json-event.d.ts +28 -0
  808. package/dist/modes/json-event.d.ts.map +1 -0
  809. package/dist/modes/json-event.js +12 -0
  810. package/dist/modes/json-event.js.map +1 -0
  811. package/dist/modes/print-mode.d.ts +29 -0
  812. package/dist/modes/print-mode.d.ts.map +1 -0
  813. package/dist/modes/print-mode.js +142 -0
  814. package/dist/modes/print-mode.js.map +1 -0
  815. package/dist/modes/rpc/jsonl.d.ts +17 -0
  816. package/dist/modes/rpc/jsonl.d.ts.map +1 -0
  817. package/dist/modes/rpc/jsonl.js +49 -0
  818. package/dist/modes/rpc/jsonl.js.map +1 -0
  819. package/dist/modes/rpc/rpc-client.d.ts +321 -0
  820. package/dist/modes/rpc/rpc-client.d.ts.map +1 -0
  821. package/dist/modes/rpc/rpc-client.js +755 -0
  822. package/dist/modes/rpc/rpc-client.js.map +1 -0
  823. package/dist/modes/rpc/rpc-mode.d.ts +20 -0
  824. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -0
  825. package/dist/modes/rpc/rpc-mode.js +963 -0
  826. package/dist/modes/rpc/rpc-mode.js.map +1 -0
  827. package/dist/modes/rpc/rpc-types.d.ts +652 -0
  828. package/dist/modes/rpc/rpc-types.d.ts.map +1 -0
  829. package/dist/modes/rpc/rpc-types.js +8 -0
  830. package/dist/modes/rpc/rpc-types.js.map +1 -0
  831. package/dist/package-manager-cli.d.ts +4 -0
  832. package/dist/package-manager-cli.d.ts.map +1 -0
  833. package/dist/package-manager-cli.js +488 -0
  834. package/dist/package-manager-cli.js.map +1 -0
  835. package/dist/utils/ansi.d.ts +2 -0
  836. package/dist/utils/ansi.d.ts.map +1 -0
  837. package/dist/utils/ansi.js +25 -0
  838. package/dist/utils/ansi.js.map +1 -0
  839. package/dist/utils/changelog.d.ts +23 -0
  840. package/dist/utils/changelog.d.ts.map +1 -0
  841. package/dist/utils/changelog.js +74 -0
  842. package/dist/utils/changelog.js.map +1 -0
  843. package/dist/utils/child-process.d.ts +15 -0
  844. package/dist/utils/child-process.d.ts.map +1 -0
  845. package/dist/utils/child-process.js +88 -0
  846. package/dist/utils/child-process.js.map +1 -0
  847. package/dist/utils/clipboard-image.d.ts +13 -0
  848. package/dist/utils/clipboard-image.d.ts.map +1 -0
  849. package/dist/utils/clipboard-image.js +248 -0
  850. package/dist/utils/clipboard-image.js.map +1 -0
  851. package/dist/utils/clipboard-native.d.ts +11 -0
  852. package/dist/utils/clipboard-native.d.ts.map +1 -0
  853. package/dist/utils/clipboard-native.js +20 -0
  854. package/dist/utils/clipboard-native.js.map +1 -0
  855. package/dist/utils/clipboard.d.ts +4 -0
  856. package/dist/utils/clipboard.d.ts.map +1 -0
  857. package/dist/utils/clipboard.js +171 -0
  858. package/dist/utils/clipboard.js.map +1 -0
  859. package/dist/utils/deprecation.d.ts +4 -0
  860. package/dist/utils/deprecation.d.ts.map +1 -0
  861. package/dist/utils/deprecation.js +13 -0
  862. package/dist/utils/deprecation.js.map +1 -0
  863. package/dist/utils/directory-completions.d.ts +5 -0
  864. package/dist/utils/directory-completions.d.ts.map +1 -0
  865. package/dist/utils/directory-completions.js +64 -0
  866. package/dist/utils/directory-completions.js.map +1 -0
  867. package/dist/utils/exif-orientation.d.ts +6 -0
  868. package/dist/utils/exif-orientation.d.ts.map +1 -0
  869. package/dist/utils/exif-orientation.js +166 -0
  870. package/dist/utils/exif-orientation.js.map +1 -0
  871. package/dist/utils/frontmatter.d.ts +8 -0
  872. package/dist/utils/frontmatter.d.ts.map +1 -0
  873. package/dist/utils/frontmatter.js +26 -0
  874. package/dist/utils/frontmatter.js.map +1 -0
  875. package/dist/utils/fs-watch.d.ts +5 -0
  876. package/dist/utils/fs-watch.d.ts.map +1 -0
  877. package/dist/utils/fs-watch.js +25 -0
  878. package/dist/utils/fs-watch.js.map +1 -0
  879. package/dist/utils/git.d.ts +27 -0
  880. package/dist/utils/git.d.ts.map +1 -0
  881. package/dist/utils/git.js +237 -0
  882. package/dist/utils/git.js.map +1 -0
  883. package/dist/utils/grip-user-agent.d.ts +2 -0
  884. package/dist/utils/grip-user-agent.d.ts.map +1 -0
  885. package/dist/utils/grip-user-agent.js +5 -0
  886. package/dist/utils/grip-user-agent.js.map +1 -0
  887. package/dist/utils/html.d.ts +7 -0
  888. package/dist/utils/html.d.ts.map +1 -0
  889. package/dist/utils/html.js +40 -0
  890. package/dist/utils/html.js.map +1 -0
  891. package/dist/utils/image-convert.d.ts +12 -0
  892. package/dist/utils/image-convert.d.ts.map +1 -0
  893. package/dist/utils/image-convert.js +43 -0
  894. package/dist/utils/image-convert.js.map +1 -0
  895. package/dist/utils/image-process.d.ts +18 -0
  896. package/dist/utils/image-process.d.ts.map +1 -0
  897. package/dist/utils/image-process.js +83 -0
  898. package/dist/utils/image-process.js.map +1 -0
  899. package/dist/utils/image-resize-core.d.ts +30 -0
  900. package/dist/utils/image-resize-core.d.ts.map +1 -0
  901. package/dist/utils/image-resize-core.js +133 -0
  902. package/dist/utils/image-resize-core.js.map +1 -0
  903. package/dist/utils/image-resize-worker.d.ts +2 -0
  904. package/dist/utils/image-resize-worker.d.ts.map +1 -0
  905. package/dist/utils/image-resize-worker.js +31 -0
  906. package/dist/utils/image-resize-worker.js.map +1 -0
  907. package/dist/utils/image-resize.d.ts +19 -0
  908. package/dist/utils/image-resize.d.ts.map +1 -0
  909. package/dist/utils/image-resize.js +86 -0
  910. package/dist/utils/image-resize.js.map +1 -0
  911. package/dist/utils/json.d.ts +3 -0
  912. package/dist/utils/json.d.ts.map +1 -0
  913. package/dist/utils/json.js +7 -0
  914. package/dist/utils/json.js.map +1 -0
  915. package/dist/utils/mime.d.ts +3 -0
  916. package/dist/utils/mime.d.ts.map +1 -0
  917. package/dist/utils/mime.js +110 -0
  918. package/dist/utils/mime.js.map +1 -0
  919. package/dist/utils/open-browser.d.ts +9 -0
  920. package/dist/utils/open-browser.d.ts.map +1 -0
  921. package/dist/utils/open-browser.js +22 -0
  922. package/dist/utils/open-browser.js.map +1 -0
  923. package/dist/utils/paths.d.ts +31 -0
  924. package/dist/utils/paths.d.ts.map +1 -0
  925. package/dist/utils/paths.js +87 -0
  926. package/dist/utils/paths.js.map +1 -0
  927. package/dist/utils/photon.d.ts +22 -0
  928. package/dist/utils/photon.d.ts.map +1 -0
  929. package/dist/utils/photon.js +126 -0
  930. package/dist/utils/photon.js.map +1 -0
  931. package/dist/utils/shell.d.ts +28 -0
  932. package/dist/utils/shell.d.ts.map +1 -0
  933. package/dist/utils/shell.js +188 -0
  934. package/dist/utils/shell.js.map +1 -0
  935. package/dist/utils/sleep.d.ts +5 -0
  936. package/dist/utils/sleep.d.ts.map +1 -0
  937. package/dist/utils/sleep.js +17 -0
  938. package/dist/utils/sleep.js.map +1 -0
  939. package/dist/utils/syntax-highlight.d.ts +12 -0
  940. package/dist/utils/syntax-highlight.d.ts.map +1 -0
  941. package/dist/utils/syntax-highlight.js +125 -0
  942. package/dist/utils/syntax-highlight.js.map +1 -0
  943. package/dist/utils/tools-manager.d.ts +5 -0
  944. package/dist/utils/tools-manager.d.ts.map +1 -0
  945. package/dist/utils/tools-manager.js +329 -0
  946. package/dist/utils/tools-manager.js.map +1 -0
  947. package/dist/utils/version-check.d.ts +14 -0
  948. package/dist/utils/version-check.d.ts.map +1 -0
  949. package/dist/utils/version-check.js +91 -0
  950. package/dist/utils/version-check.js.map +1 -0
  951. package/dist/utils/windows-self-update.d.ts +3 -0
  952. package/dist/utils/windows-self-update.d.ts.map +1 -0
  953. package/dist/utils/windows-self-update.js +77 -0
  954. package/dist/utils/windows-self-update.js.map +1 -0
  955. package/docs/compaction.md +408 -0
  956. package/docs/custom-provider.md +714 -0
  957. package/docs/daemon-architecture.md +399 -0
  958. package/docs/daemon.md +112 -0
  959. package/docs/development.md +72 -0
  960. package/docs/docs.json +164 -0
  961. package/docs/extensions.md +2745 -0
  962. package/docs/hooks.md +85 -0
  963. package/docs/images/doom-extension.png +0 -0
  964. package/docs/images/exy.png +0 -0
  965. package/docs/images/interactive-mode.png +0 -0
  966. package/docs/images/tree-view.png +0 -0
  967. package/docs/index.md +77 -0
  968. package/docs/json.md +89 -0
  969. package/docs/keybindings.md +230 -0
  970. package/docs/lsp.md +499 -0
  971. package/docs/migrating-to-grip.md +18 -0
  972. package/docs/models.md +496 -0
  973. package/docs/packages.md +228 -0
  974. package/docs/prompt-templates.md +88 -0
  975. package/docs/providers.md +251 -0
  976. package/docs/quickstart.md +159 -0
  977. package/docs/rpc.md +1492 -0
  978. package/docs/rules.md +117 -0
  979. package/docs/sandbox.md +104 -0
  980. package/docs/sdk.md +360 -0
  981. package/docs/session-format.md +414 -0
  982. package/docs/sessions.md +137 -0
  983. package/docs/settings.md +372 -0
  984. package/docs/shell-aliases.md +13 -0
  985. package/docs/skills.md +246 -0
  986. package/docs/terminal-setup.md +112 -0
  987. package/docs/termux.md +112 -0
  988. package/docs/themes.md +295 -0
  989. package/docs/tmux.md +61 -0
  990. package/docs/tui.md +918 -0
  991. package/docs/usage.md +304 -0
  992. package/docs/windows.md +17 -0
  993. package/examples/README.md +29 -0
  994. package/examples/daemon-docker/Dockerfile +43 -0
  995. package/examples/daemon-docker/README.md +45 -0
  996. package/examples/extensions/README.md +208 -0
  997. package/examples/extensions/auto-commit-on-exit.ts +46 -0
  998. package/examples/extensions/bash-spawn-hook.ts +30 -0
  999. package/examples/extensions/bookmark.ts +50 -0
  1000. package/examples/extensions/border-status-editor.ts +145 -0
  1001. package/examples/extensions/built-in-tool-renderer.ts +259 -0
  1002. package/examples/extensions/claude-rules.ts +86 -0
  1003. package/examples/extensions/commands.ts +82 -0
  1004. package/examples/extensions/confirm-destructive.ts +59 -0
  1005. package/examples/extensions/custom-compaction.ts +131 -0
  1006. package/examples/extensions/custom-footer.ts +79 -0
  1007. package/examples/extensions/custom-header.ts +73 -0
  1008. package/examples/extensions/custom-provider-anthropic/index.ts +707 -0
  1009. package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
  1010. package/examples/extensions/custom-provider-anthropic/package.json +19 -0
  1011. package/examples/extensions/custom-provider-gitlab-duo/index.ts +402 -0
  1012. package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
  1013. package/examples/extensions/custom-provider-gitlab-duo/test.ts +104 -0
  1014. package/examples/extensions/dirty-repo-guard.ts +59 -0
  1015. package/examples/extensions/doom-overlay/README.md +46 -0
  1016. package/examples/extensions/doom-overlay/doom/build/doom.js +21 -0
  1017. package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
  1018. package/examples/extensions/doom-overlay/doom/build.sh +152 -0
  1019. package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -0
  1020. package/examples/extensions/doom-overlay/doom-component.ts +133 -0
  1021. package/examples/extensions/doom-overlay/doom-engine.ts +173 -0
  1022. package/examples/extensions/doom-overlay/doom-keys.ts +104 -0
  1023. package/examples/extensions/doom-overlay/index.ts +74 -0
  1024. package/examples/extensions/doom-overlay/wad-finder.ts +51 -0
  1025. package/examples/extensions/dynamic-resources/RULES.md +8 -0
  1026. package/examples/extensions/dynamic-resources/SKILL.md +8 -0
  1027. package/examples/extensions/dynamic-resources/dynamic.json +79 -0
  1028. package/examples/extensions/dynamic-resources/dynamic.md +5 -0
  1029. package/examples/extensions/dynamic-resources/index.ts +16 -0
  1030. package/examples/extensions/dynamic-tools.ts +74 -0
  1031. package/examples/extensions/event-bus.ts +43 -0
  1032. package/examples/extensions/file-trigger.ts +41 -0
  1033. package/examples/extensions/git-checkpoint.ts +53 -0
  1034. package/examples/extensions/git-merge-and-resolve.ts +125 -0
  1035. package/examples/extensions/github-issue-autocomplete.ts +191 -0
  1036. package/examples/extensions/handoff.ts +191 -0
  1037. package/examples/extensions/hello.ts +26 -0
  1038. package/examples/extensions/hidden-thinking-label.ts +53 -0
  1039. package/examples/extensions/inline-bash.ts +104 -0
  1040. package/examples/extensions/input-transform.ts +43 -0
  1041. package/examples/extensions/interactive-shell.ts +194 -0
  1042. package/examples/extensions/mac-system-theme.ts +47 -0
  1043. package/examples/extensions/message-renderer.ts +59 -0
  1044. package/examples/extensions/minimal-mode.ts +428 -0
  1045. package/examples/extensions/modal-editor.ts +86 -0
  1046. package/examples/extensions/model-status.ts +31 -0
  1047. package/examples/extensions/notify.ts +55 -0
  1048. package/examples/extensions/overlay-qa-tests.ts +1374 -0
  1049. package/examples/extensions/overlay-test.ts +171 -0
  1050. package/examples/extensions/permission-gate.ts +34 -0
  1051. package/examples/extensions/pirate.ts +47 -0
  1052. package/examples/extensions/plan-mode/README.md +65 -0
  1053. package/examples/extensions/plan-mode/index.ts +346 -0
  1054. package/examples/extensions/plan-mode/utils.ts +172 -0
  1055. package/examples/extensions/preset.ts +426 -0
  1056. package/examples/extensions/prompt-customizer.ts +97 -0
  1057. package/examples/extensions/protected-paths.ts +29 -0
  1058. package/examples/extensions/provider-payload.ts +18 -0
  1059. package/examples/extensions/qna.ts +125 -0
  1060. package/examples/extensions/question.ts +294 -0
  1061. package/examples/extensions/questionnaire.ts +459 -0
  1062. package/examples/extensions/rainbow-editor.ts +88 -0
  1063. package/examples/extensions/reload-runtime.ts +37 -0
  1064. package/examples/extensions/rpc-demo.ts +118 -0
  1065. package/examples/extensions/sandbox/index.ts +320 -0
  1066. package/examples/extensions/sandbox/package-lock.json +92 -0
  1067. package/examples/extensions/sandbox/package.json +19 -0
  1068. package/examples/extensions/send-user-message.ts +97 -0
  1069. package/examples/extensions/session-name.ts +27 -0
  1070. package/examples/extensions/shutdown-command.ts +63 -0
  1071. package/examples/extensions/snake.ts +381 -0
  1072. package/examples/extensions/space-invaders.ts +597 -0
  1073. package/examples/extensions/status-line.ts +32 -0
  1074. package/examples/extensions/structured-output.ts +65 -0
  1075. package/examples/extensions/subagent/README.md +175 -0
  1076. package/examples/extensions/subagent/agents/planner.md +37 -0
  1077. package/examples/extensions/subagent/agents/reviewer.md +35 -0
  1078. package/examples/extensions/subagent/agents/scout.md +50 -0
  1079. package/examples/extensions/subagent/agents/worker.md +24 -0
  1080. package/examples/extensions/subagent/agents.ts +126 -0
  1081. package/examples/extensions/subagent/index.ts +1083 -0
  1082. package/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
  1083. package/examples/extensions/subagent/prompts/implement.md +10 -0
  1084. package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
  1085. package/examples/extensions/summarize.ts +186 -0
  1086. package/examples/extensions/system-prompt-header.ts +17 -0
  1087. package/examples/extensions/tic-tac-toe.ts +1091 -0
  1088. package/examples/extensions/timed-confirm.ts +70 -0
  1089. package/examples/extensions/titlebar-spinner.ts +58 -0
  1090. package/examples/extensions/todo.ts +306 -0
  1091. package/examples/extensions/tool-override.ts +144 -0
  1092. package/examples/extensions/tools.ts +141 -0
  1093. package/examples/extensions/trigger-compact.ts +50 -0
  1094. package/examples/extensions/truncated-tool.ts +200 -0
  1095. package/examples/extensions/widget-placement.ts +9 -0
  1096. package/examples/extensions/with-deps/index.ts +32 -0
  1097. package/examples/extensions/with-deps/package-lock.json +31 -0
  1098. package/examples/extensions/with-deps/package.json +22 -0
  1099. package/examples/extensions/working-indicator.ts +123 -0
  1100. package/examples/extensions/working-message-test.ts +25 -0
  1101. package/examples/remote-session-server/README.md +71 -0
  1102. package/examples/remote-session-server/server.ts +353 -0
  1103. package/examples/rpc-extension-ui.ts +642 -0
  1104. package/examples/sdk/01-minimal.ts +27 -0
  1105. package/examples/sdk/02-custom-model.ts +54 -0
  1106. package/examples/sdk/03-custom-prompt.ts +76 -0
  1107. package/examples/sdk/04-skills.ts +60 -0
  1108. package/examples/sdk/05-tools.ts +55 -0
  1109. package/examples/sdk/06-extensions.ts +94 -0
  1110. package/examples/sdk/07-context-files.ts +47 -0
  1111. package/examples/sdk/08-prompt-templates.ts +56 -0
  1112. package/examples/sdk/09-api-keys-and-oauth.ts +50 -0
  1113. package/examples/sdk/10-settings.ts +58 -0
  1114. package/examples/sdk/11-sessions.ts +54 -0
  1115. package/examples/sdk/12-full-control.ts +79 -0
  1116. package/examples/sdk/13-session-runtime.ts +49 -0
  1117. package/examples/sdk/README.md +94 -0
  1118. package/npm-shrinkwrap.json +1878 -0
  1119. package/package.json +101 -5
@@ -0,0 +1,271 @@
1
+ import { createHash, randomBytes } from "node:crypto";
2
+ import { VERSION } from "../config.js";
3
+ import { RemoteWorkspaceServerProtocol, } from "../core/remote-workspace-protocol/session.js";
4
+ import { parseSharedWorkspaceClientEnvelope, } from "../core/remote-workspace-protocol/shared-transport.js";
5
+ import { DaemonActivityBudget } from "./activity-budget.js";
6
+ import { withSharedRevisionGuard } from "./shared-revision.js";
7
+ import { createDaemonWorkspaceRuntime } from "./workspace-runtime.js";
8
+ /** One authenticated v2 WebSocket. No state (including request IDs) is shared between channels. */
9
+ export class SharedDaemonConnection {
10
+ channels = new Map();
11
+ channelDisposals = new WeakMap();
12
+ pendingDisposals = new Set();
13
+ usedControlIds = new Set();
14
+ epoch = randomBytes(18).toString("base64url");
15
+ hello = false;
16
+ closed = false;
17
+ queue = Promise.resolve();
18
+ pendingInboundMessages = 0;
19
+ pendingInboundBytes = 0;
20
+ budget;
21
+ configuration;
22
+ roots;
23
+ send;
24
+ closeSocket;
25
+ constructor(configuration, roots, send, closeSocket, budget = new DaemonActivityBudget(configuration)) {
26
+ this.configuration = configuration;
27
+ this.roots = roots;
28
+ this.send = send;
29
+ this.closeSocket = closeSocket;
30
+ this.budget = budget;
31
+ }
32
+ receive(payload) {
33
+ if (this.closed)
34
+ return Promise.resolve();
35
+ const limits = this.configuration.protocolLimits;
36
+ if (payload.byteLength > limits.maxMessageBytes ||
37
+ this.pendingInboundMessages >= limits.maxPendingInboundMessages ||
38
+ this.pendingInboundBytes + payload.byteLength > limits.maxPendingInboundBytes) {
39
+ this.closed = true;
40
+ this.closeSocket(1009, "Shared workspace inbound queue exceeds limits");
41
+ return Promise.resolve();
42
+ }
43
+ // Copy before queuing: WebSocket buffers need not remain stable after the callback returns.
44
+ const queuedPayload = Uint8Array.from(payload);
45
+ this.pendingInboundMessages++;
46
+ this.pendingInboundBytes += queuedPayload.byteLength;
47
+ let complete;
48
+ const finished = new Promise((resolve) => {
49
+ complete = resolve;
50
+ });
51
+ let channelPending = false;
52
+ const settle = () => {
53
+ this.pendingInboundMessages--;
54
+ this.pendingInboundBytes -= queuedPayload.byteLength;
55
+ complete();
56
+ };
57
+ const fail = () => {
58
+ if (!this.closed) {
59
+ this.closed = true;
60
+ this.closeSocket(1002, "Invalid shared workspace frame");
61
+ }
62
+ };
63
+ const scheduled = this.queue.then(() => {
64
+ if (this.closed)
65
+ return;
66
+ const frame = parseSharedWorkspaceClientEnvelope(queuedPayload, limits);
67
+ if (frame.type === "channel") {
68
+ // Validate the channel before letting the control queue advance. Its own
69
+ // protocol preserves per-channel receive order and bounds queued frames.
70
+ if (!this.channels.has(frame.channelId))
71
+ throw new Error("Unknown shared workspace channel");
72
+ channelPending = true;
73
+ void this.dispatch(frame).catch(fail).finally(settle);
74
+ return;
75
+ }
76
+ // Hello, opens, closes and reloads remain serialized in control order.
77
+ return this.dispatch(frame);
78
+ });
79
+ this.queue = scheduled.catch(fail).finally(() => {
80
+ if (!channelPending)
81
+ settle();
82
+ });
83
+ return finished;
84
+ }
85
+ get handshakeComplete() {
86
+ return this.hello;
87
+ }
88
+ async beginDrain() {
89
+ await Promise.allSettled([...this.channels.values()].map((channel) => channel.protocol.beginDrain()));
90
+ }
91
+ createChannelRuntime(root) {
92
+ return createDaemonWorkspaceRuntime({
93
+ ...this.configuration,
94
+ workspaceRoot: root,
95
+ // Operator-wide resource files and the v1 temporary root are not channel-scoped.
96
+ // Keep them available on v1, but never expose them through a child channel.
97
+ temporaryRoot: undefined,
98
+ sandboxInstructionsPath: undefined,
99
+ userAgentsPath: undefined,
100
+ });
101
+ }
102
+ reload() {
103
+ const operation = this.queue.then(async () => {
104
+ if (this.closed)
105
+ throw new Error("Shared workspace connection is closed");
106
+ for (const channel of this.channels.values()) {
107
+ const previous = channel.runtime;
108
+ const previousHandler = channel.handler;
109
+ const candidate = this.createChannelRuntime(channel.workspace.root);
110
+ const candidateHandler = candidate.createHandler(channel.workspace, true);
111
+ channel.runtime = candidate;
112
+ channel.handler = candidateHandler;
113
+ try {
114
+ await channel.protocol.publishCatalog({ ...candidate.catalog, generation: channel.generation + 1 });
115
+ channel.generation++;
116
+ }
117
+ catch (error) {
118
+ channel.runtime = previous;
119
+ channel.handler = previousHandler;
120
+ await candidate.dispose();
121
+ throw error;
122
+ }
123
+ await previous.retire();
124
+ }
125
+ });
126
+ this.queue = operation.catch(() => undefined);
127
+ return operation;
128
+ }
129
+ async dispatch(frame) {
130
+ if (frame.type === "hello") {
131
+ if (this.hello)
132
+ throw new Error("Duplicate v2 hello");
133
+ this.hello = true;
134
+ this.usedControlIds.add(frame.id);
135
+ await this.send({ type: "hello_ack", id: frame.id, version: 2, epoch: this.epoch, daemonVersion: VERSION });
136
+ return;
137
+ }
138
+ if (!this.hello)
139
+ throw new Error("V2 hello required before opening channels");
140
+ if (frame.type === "open") {
141
+ if (this.usedControlIds.has(frame.id))
142
+ throw new Error("Duplicate v2 control ID");
143
+ if (this.usedControlIds.size >= 65_536)
144
+ throw new Error("V2 control ID budget exhausted");
145
+ this.usedControlIds.add(frame.id);
146
+ if (this.channels.size >= Math.min(this.configuration.maxConnections, 32)) {
147
+ await this.send({
148
+ type: "control_error",
149
+ id: frame.id,
150
+ code: "limit_exceeded",
151
+ message: "Channel limit reached",
152
+ });
153
+ return;
154
+ }
155
+ let root;
156
+ try {
157
+ root = await this.roots.bind(frame.root);
158
+ }
159
+ catch {
160
+ await this.send({
161
+ type: "control_error",
162
+ id: frame.id,
163
+ code: "invalid_root",
164
+ message: "Workspace root is not an existing directory under the shared parent",
165
+ });
166
+ return;
167
+ }
168
+ await this.open(frame.id, root);
169
+ return;
170
+ }
171
+ const channel = this.channels.get(frame.channelId);
172
+ if (!channel)
173
+ throw new Error("Unknown shared workspace channel");
174
+ if (frame.type === "close") {
175
+ // Do not wait on a channel's in-flight requests while blocking the socket receive queue.
176
+ this.channels.delete(frame.channelId);
177
+ // Begin cancellation before acknowledging detach; track it for physical shutdown.
178
+ void this.disposeChannel(channel);
179
+ await this.send({ type: "closed", channelId: frame.channelId });
180
+ return;
181
+ }
182
+ await channel.protocol.receive(Buffer.from(JSON.stringify(frame.payload)));
183
+ }
184
+ async open(id, root) {
185
+ const channelId = randomBytes(24).toString("base64url");
186
+ const workspace = Object.freeze({
187
+ id: randomBytes(18).toString("base64url"),
188
+ root,
189
+ pathFlavor: "posix",
190
+ });
191
+ let runtime;
192
+ try {
193
+ runtime = this.createChannelRuntime(root);
194
+ }
195
+ catch {
196
+ // A bad child project configuration is an open failure, not a corrupt
197
+ // physical envelope. Keep already bound sibling channels usable.
198
+ await this.send({
199
+ type: "control_error",
200
+ id,
201
+ code: "invalid_request",
202
+ message: "Unable to initialize shared workspace channel",
203
+ });
204
+ return;
205
+ }
206
+ const handler = runtime.createHandler(workspace, true);
207
+ let channel;
208
+ const protocol = new RemoteWorkspaceServerProtocol({
209
+ send: (payload) => this.channels.has(channelId) && !this.closed
210
+ ? this.send({ type: "channel", channelId, payload })
211
+ : Promise.reject(new Error("Shared workspace channel is closed")),
212
+ close: async (reason) => {
213
+ const channel = this.channels.get(channelId);
214
+ if (channel) {
215
+ this.channels.delete(channelId);
216
+ void this.disposeChannel(channel);
217
+ if (!this.closed)
218
+ await this.send({ type: "closed", channelId, reason });
219
+ }
220
+ },
221
+ }, {
222
+ validateToolArguments: (toolName, value) => channel.handler.validateToolArguments(toolName, value),
223
+ handleRequest: (request, context) => this.budget.run(request.method, async () => {
224
+ const result = await withSharedRevisionGuard(request, workspace.root, channel.runtime.operations, context, () => channel.handler.handleRequest(request, context));
225
+ if (request.method !== "workspace.read")
226
+ return result;
227
+ const read = result;
228
+ return {
229
+ ...read,
230
+ revision: createHash("sha256").update(Buffer.from(read.contentBase64, "base64")).digest("hex"),
231
+ };
232
+ }),
233
+ }, {
234
+ workspace,
235
+ catalog: runtime.catalog,
236
+ capabilities: runtime.capabilities,
237
+ limits: this.configuration.protocolLimits,
238
+ backendLabel: "grip-shared-workspace-daemon",
239
+ });
240
+ channel = { runtime, handler, protocol, workspace, generation: runtime.catalog.generation };
241
+ this.channels.set(channelId, channel);
242
+ try {
243
+ await this.send({ type: "opened", id, channelId });
244
+ }
245
+ catch (error) {
246
+ this.channels.delete(channelId);
247
+ void this.disposeChannel(channel);
248
+ throw error;
249
+ }
250
+ }
251
+ disposeChannel(channel) {
252
+ const existing = this.channelDisposals.get(channel);
253
+ if (existing)
254
+ return existing;
255
+ const disposal = (async () => {
256
+ await channel.protocol.disconnect().catch(() => undefined);
257
+ await channel.runtime.dispose().catch(() => undefined);
258
+ })();
259
+ this.channelDisposals.set(channel, disposal);
260
+ this.pendingDisposals.add(disposal);
261
+ void disposal.then(() => this.pendingDisposals.delete(disposal), () => this.pendingDisposals.delete(disposal));
262
+ return disposal;
263
+ }
264
+ async disconnect() {
265
+ this.closed = true;
266
+ const channels = [...this.channels.values()];
267
+ this.channels.clear();
268
+ await Promise.allSettled([...channels.map((channel) => this.disposeChannel(channel)), ...this.pendingDisposals]);
269
+ }
270
+ }
271
+ //# sourceMappingURL=shared-connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-connection.js","sourceRoot":"","sources":["../../src/daemon/shared-connection.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomBytes } from \"node:crypto\";\nimport { VERSION } from \"../config.ts\";\nimport type {\n\tRemoteWorkspaceIdentity,\n\tRemoteWorkspaceServerMessage,\n} from \"../core/remote-workspace-protocol/contract.ts\";\nimport {\n\ttype RemoteWorkspaceServerHandler,\n\tRemoteWorkspaceServerProtocol,\n} from \"../core/remote-workspace-protocol/session.ts\";\nimport {\n\tparseSharedWorkspaceClientEnvelope,\n\ttype SharedWorkspaceClientEnvelope,\n\ttype SharedWorkspaceServerFrame,\n} from \"../core/remote-workspace-protocol/shared-transport.ts\";\nimport { DaemonActivityBudget } from \"./activity-budget.ts\";\nimport type { DaemonConfiguration } from \"./config.ts\";\nimport { withSharedRevisionGuard } from \"./shared-revision.ts\";\nimport type { SharedWorkspaceRoots } from \"./shared-roots.ts\";\nimport { createDaemonWorkspaceRuntime, type DaemonWorkspaceRuntime } from \"./workspace-runtime.ts\";\n\ninterface Channel {\n\treadonly protocol: RemoteWorkspaceServerProtocol;\n\truntime: DaemonWorkspaceRuntime;\n\thandler: RemoteWorkspaceServerHandler;\n\treadonly workspace: RemoteWorkspaceIdentity;\n\tgeneration: number;\n}\n\n/** One authenticated v2 WebSocket. No state (including request IDs) is shared between channels. */\nexport class SharedDaemonConnection {\n\tprivate readonly channels = new Map<string, Channel>();\n\tprivate readonly channelDisposals = new WeakMap<Channel, Promise<void>>();\n\tprivate readonly pendingDisposals = new Set<Promise<void>>();\n\tprivate readonly usedControlIds = new Set<string>();\n\tprivate readonly epoch = randomBytes(18).toString(\"base64url\");\n\tprivate hello = false;\n\tprivate closed = false;\n\tprivate queue: Promise<void> = Promise.resolve();\n\tprivate pendingInboundMessages = 0;\n\tprivate pendingInboundBytes = 0;\n\tprivate readonly budget: DaemonActivityBudget;\n\n\tprivate readonly configuration: DaemonConfiguration;\n\tprivate readonly roots: SharedWorkspaceRoots;\n\tprivate readonly send: (message: SharedWorkspaceServerFrame) => Promise<void>;\n\tprivate readonly closeSocket: (code: number, message: string) => void;\n\n\tconstructor(\n\t\tconfiguration: DaemonConfiguration,\n\t\troots: SharedWorkspaceRoots,\n\t\tsend: (message: SharedWorkspaceServerFrame) => Promise<void>,\n\t\tcloseSocket: (code: number, message: string) => void,\n\t\tbudget: DaemonActivityBudget = new DaemonActivityBudget(configuration),\n\t) {\n\t\tthis.configuration = configuration;\n\t\tthis.roots = roots;\n\t\tthis.send = send;\n\t\tthis.closeSocket = closeSocket;\n\t\tthis.budget = budget;\n\t}\n\n\treceive(payload: Uint8Array): Promise<void> {\n\t\tif (this.closed) return Promise.resolve();\n\t\tconst limits = this.configuration.protocolLimits;\n\t\tif (\n\t\t\tpayload.byteLength > limits.maxMessageBytes ||\n\t\t\tthis.pendingInboundMessages >= limits.maxPendingInboundMessages ||\n\t\t\tthis.pendingInboundBytes + payload.byteLength > limits.maxPendingInboundBytes\n\t\t) {\n\t\t\tthis.closed = true;\n\t\t\tthis.closeSocket(1009, \"Shared workspace inbound queue exceeds limits\");\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\t// Copy before queuing: WebSocket buffers need not remain stable after the callback returns.\n\t\tconst queuedPayload = Uint8Array.from(payload);\n\t\tthis.pendingInboundMessages++;\n\t\tthis.pendingInboundBytes += queuedPayload.byteLength;\n\t\tlet complete!: () => void;\n\t\tconst finished = new Promise<void>((resolve) => {\n\t\t\tcomplete = resolve;\n\t\t});\n\t\tlet channelPending = false;\n\t\tconst settle = () => {\n\t\t\tthis.pendingInboundMessages--;\n\t\t\tthis.pendingInboundBytes -= queuedPayload.byteLength;\n\t\t\tcomplete();\n\t\t};\n\t\tconst fail = () => {\n\t\t\tif (!this.closed) {\n\t\t\t\tthis.closed = true;\n\t\t\t\tthis.closeSocket(1002, \"Invalid shared workspace frame\");\n\t\t\t}\n\t\t};\n\t\tconst scheduled = this.queue.then(() => {\n\t\t\tif (this.closed) return;\n\t\t\tconst frame = parseSharedWorkspaceClientEnvelope(queuedPayload, limits);\n\t\t\tif (frame.type === \"channel\") {\n\t\t\t\t// Validate the channel before letting the control queue advance. Its own\n\t\t\t\t// protocol preserves per-channel receive order and bounds queued frames.\n\t\t\t\tif (!this.channels.has(frame.channelId)) throw new Error(\"Unknown shared workspace channel\");\n\t\t\t\tchannelPending = true;\n\t\t\t\tvoid this.dispatch(frame).catch(fail).finally(settle);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Hello, opens, closes and reloads remain serialized in control order.\n\t\t\treturn this.dispatch(frame);\n\t\t});\n\t\tthis.queue = scheduled.catch(fail).finally(() => {\n\t\t\tif (!channelPending) settle();\n\t\t});\n\t\treturn finished;\n\t}\n\n\tget handshakeComplete(): boolean {\n\t\treturn this.hello;\n\t}\n\n\tasync beginDrain(): Promise<void> {\n\t\tawait Promise.allSettled([...this.channels.values()].map((channel) => channel.protocol.beginDrain()));\n\t}\n\n\tprivate createChannelRuntime(root: string): DaemonWorkspaceRuntime {\n\t\treturn createDaemonWorkspaceRuntime({\n\t\t\t...this.configuration,\n\t\t\tworkspaceRoot: root,\n\t\t\t// Operator-wide resource files and the v1 temporary root are not channel-scoped.\n\t\t\t// Keep them available on v1, but never expose them through a child channel.\n\t\t\ttemporaryRoot: undefined,\n\t\t\tsandboxInstructionsPath: undefined,\n\t\t\tuserAgentsPath: undefined,\n\t\t});\n\t}\n\n\treload(): Promise<void> {\n\t\tconst operation = this.queue.then(async () => {\n\t\t\tif (this.closed) throw new Error(\"Shared workspace connection is closed\");\n\t\t\tfor (const channel of this.channels.values()) {\n\t\t\t\tconst previous = channel.runtime;\n\t\t\t\tconst previousHandler = channel.handler;\n\t\t\t\tconst candidate = this.createChannelRuntime(channel.workspace.root);\n\t\t\t\tconst candidateHandler = candidate.createHandler(channel.workspace, true);\n\t\t\t\tchannel.runtime = candidate;\n\t\t\t\tchannel.handler = candidateHandler;\n\t\t\t\ttry {\n\t\t\t\t\tawait channel.protocol.publishCatalog({ ...candidate.catalog, generation: channel.generation + 1 });\n\t\t\t\t\tchannel.generation++;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tchannel.runtime = previous;\n\t\t\t\t\tchannel.handler = previousHandler;\n\t\t\t\t\tawait candidate.dispose();\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tawait previous.retire();\n\t\t\t}\n\t\t});\n\t\tthis.queue = operation.catch(() => undefined);\n\t\treturn operation;\n\t}\n\n\tprivate async dispatch(frame: SharedWorkspaceClientEnvelope): Promise<void> {\n\t\tif (frame.type === \"hello\") {\n\t\t\tif (this.hello) throw new Error(\"Duplicate v2 hello\");\n\t\t\tthis.hello = true;\n\t\t\tthis.usedControlIds.add(frame.id);\n\t\t\tawait this.send({ type: \"hello_ack\", id: frame.id, version: 2, epoch: this.epoch, daemonVersion: VERSION });\n\t\t\treturn;\n\t\t}\n\t\tif (!this.hello) throw new Error(\"V2 hello required before opening channels\");\n\t\tif (frame.type === \"open\") {\n\t\t\tif (this.usedControlIds.has(frame.id)) throw new Error(\"Duplicate v2 control ID\");\n\t\t\tif (this.usedControlIds.size >= 65_536) throw new Error(\"V2 control ID budget exhausted\");\n\t\t\tthis.usedControlIds.add(frame.id);\n\t\t\tif (this.channels.size >= Math.min(this.configuration.maxConnections, 32)) {\n\t\t\t\tawait this.send({\n\t\t\t\t\ttype: \"control_error\",\n\t\t\t\t\tid: frame.id,\n\t\t\t\t\tcode: \"limit_exceeded\",\n\t\t\t\t\tmessage: \"Channel limit reached\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet root: string;\n\t\t\ttry {\n\t\t\t\troot = await this.roots.bind(frame.root);\n\t\t\t} catch {\n\t\t\t\tawait this.send({\n\t\t\t\t\ttype: \"control_error\",\n\t\t\t\t\tid: frame.id,\n\t\t\t\t\tcode: \"invalid_root\",\n\t\t\t\t\tmessage: \"Workspace root is not an existing directory under the shared parent\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait this.open(frame.id, root);\n\t\t\treturn;\n\t\t}\n\t\tconst channel = this.channels.get(frame.channelId);\n\t\tif (!channel) throw new Error(\"Unknown shared workspace channel\");\n\t\tif (frame.type === \"close\") {\n\t\t\t// Do not wait on a channel's in-flight requests while blocking the socket receive queue.\n\t\t\tthis.channels.delete(frame.channelId);\n\t\t\t// Begin cancellation before acknowledging detach; track it for physical shutdown.\n\t\t\tvoid this.disposeChannel(channel);\n\t\t\tawait this.send({ type: \"closed\", channelId: frame.channelId });\n\t\t\treturn;\n\t\t}\n\t\tawait channel.protocol.receive(Buffer.from(JSON.stringify(frame.payload)));\n\t}\n\n\tprivate async open(id: string, root: string): Promise<void> {\n\t\tconst channelId = randomBytes(24).toString(\"base64url\");\n\t\tconst workspace = Object.freeze({\n\t\t\tid: randomBytes(18).toString(\"base64url\"),\n\t\t\troot,\n\t\t\tpathFlavor: \"posix\" as const,\n\t\t});\n\t\tlet runtime: DaemonWorkspaceRuntime;\n\t\ttry {\n\t\t\truntime = this.createChannelRuntime(root);\n\t\t} catch {\n\t\t\t// A bad child project configuration is an open failure, not a corrupt\n\t\t\t// physical envelope. Keep already bound sibling channels usable.\n\t\t\tawait this.send({\n\t\t\t\ttype: \"control_error\",\n\t\t\t\tid,\n\t\t\t\tcode: \"invalid_request\",\n\t\t\t\tmessage: \"Unable to initialize shared workspace channel\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tconst handler = runtime.createHandler(workspace, true);\n\t\tlet channel!: Channel;\n\t\tconst protocol = new RemoteWorkspaceServerProtocol(\n\t\t\t{\n\t\t\t\tsend: (payload: RemoteWorkspaceServerMessage) =>\n\t\t\t\t\tthis.channels.has(channelId) && !this.closed\n\t\t\t\t\t\t? this.send({ type: \"channel\", channelId, payload })\n\t\t\t\t\t\t: Promise.reject(new Error(\"Shared workspace channel is closed\")),\n\t\t\t\tclose: async (reason) => {\n\t\t\t\t\tconst channel = this.channels.get(channelId);\n\t\t\t\t\tif (channel) {\n\t\t\t\t\t\tthis.channels.delete(channelId);\n\t\t\t\t\t\tvoid this.disposeChannel(channel);\n\t\t\t\t\t\tif (!this.closed) await this.send({ type: \"closed\", channelId, reason });\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tvalidateToolArguments: (toolName, value) => channel.handler.validateToolArguments(toolName, value),\n\t\t\t\thandleRequest: (request, context) =>\n\t\t\t\t\tthis.budget.run(request.method, async () => {\n\t\t\t\t\t\tconst result = await withSharedRevisionGuard(\n\t\t\t\t\t\t\trequest,\n\t\t\t\t\t\t\tworkspace.root,\n\t\t\t\t\t\t\tchannel.runtime.operations,\n\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\t() => channel.handler.handleRequest(request, context),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (request.method !== \"workspace.read\") return result;\n\t\t\t\t\t\tconst read = result as { contentBase64: string };\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...read,\n\t\t\t\t\t\t\trevision: createHash(\"sha256\").update(Buffer.from(read.contentBase64, \"base64\")).digest(\"hex\"),\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\t\t\t},\n\t\t\t{\n\t\t\t\tworkspace,\n\t\t\t\tcatalog: runtime.catalog,\n\t\t\t\tcapabilities: runtime.capabilities,\n\t\t\t\tlimits: this.configuration.protocolLimits,\n\t\t\t\tbackendLabel: \"grip-shared-workspace-daemon\",\n\t\t\t},\n\t\t);\n\t\tchannel = { runtime, handler, protocol, workspace, generation: runtime.catalog.generation };\n\t\tthis.channels.set(channelId, channel);\n\t\ttry {\n\t\t\tawait this.send({ type: \"opened\", id, channelId });\n\t\t} catch (error) {\n\t\t\tthis.channels.delete(channelId);\n\t\t\tvoid this.disposeChannel(channel);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate disposeChannel(channel: Channel): Promise<void> {\n\t\tconst existing = this.channelDisposals.get(channel);\n\t\tif (existing) return existing;\n\t\tconst disposal = (async () => {\n\t\t\tawait channel.protocol.disconnect().catch(() => undefined);\n\t\t\tawait channel.runtime.dispose().catch(() => undefined);\n\t\t})();\n\t\tthis.channelDisposals.set(channel, disposal);\n\t\tthis.pendingDisposals.add(disposal);\n\t\tvoid disposal.then(\n\t\t\t() => this.pendingDisposals.delete(disposal),\n\t\t\t() => this.pendingDisposals.delete(disposal),\n\t\t);\n\t\treturn disposal;\n\t}\n\n\tasync disconnect(): Promise<void> {\n\t\tthis.closed = true;\n\t\tconst channels = [...this.channels.values()];\n\t\tthis.channels.clear();\n\t\tawait Promise.allSettled([...channels.map((channel) => this.disposeChannel(channel)), ...this.pendingDisposals]);\n\t}\n}\n"]}
@@ -0,0 +1,5 @@
1
+ import { type RemoteWorkspaceServerRequestContext, type RemoteWorkspaceTypedRequest } from "../core/remote-workspace-protocol/session.ts";
2
+ import type { ConfinedDaemonToolOperations } from "./workspace-runtime.ts";
3
+ /** v2-only CAS checked inside the same process-wide per-file queue as edit/write. */
4
+ export declare function withSharedRevisionGuard<T>(request: RemoteWorkspaceTypedRequest, root: string, operations: ConfinedDaemonToolOperations, context: RemoteWorkspaceServerRequestContext, action: () => Promise<T>): Promise<T>;
5
+ //# sourceMappingURL=shared-revision.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-revision.d.ts","sourceRoot":"","sources":["../../src/daemon/shared-revision.ts"],"names":[],"mappings":"AAGA,OAAO,EAEN,KAAK,mCAAmC,EACxC,KAAK,2BAA2B,EAChC,MAAM,8CAA8C,CAAC;AAEtD,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAmD3E,qFAAqF;AACrF,wBAAgB,uBAAuB,CAAC,CAAC,EACxC,OAAO,EAAE,2BAA2B,EACpC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,4BAA4B,EACxC,OAAO,EAAE,mCAAmC,EAC5C,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACtB,OAAO,CAAC,CAAC,CAAC,CAgBZ","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { resolve } from \"node:path\";\nimport type { ExpectedWorkspaceRevision } from \"../core/remote-workspace-protocol/contract.ts\";\nimport {\n\tRemoteWorkspaceRequestError,\n\ttype RemoteWorkspaceServerRequestContext,\n\ttype RemoteWorkspaceTypedRequest,\n} from \"../core/remote-workspace-protocol/session.ts\";\nimport { withFileMutationGuard } from \"../core/tools/file-mutation-queue.ts\";\nimport type { ConfinedDaemonToolOperations } from \"./workspace-runtime.ts\";\n\ntype SharedRevisionErrorCode = \"invalid_request\" | \"conflict\";\n\nfunction revisionError(code: SharedRevisionErrorCode, message: string): RemoteWorkspaceRequestError {\n\treturn new RemoteWorkspaceRequestError({ code, message, executionState: \"not_started\", retryable: false });\n}\nfunction requireActiveMutation(context: RemoteWorkspaceServerRequestContext): void {\n\tif (context.signal.aborted)\n\t\tthrow new RemoteWorkspaceRequestError({\n\t\t\tcode: \"cancelled\",\n\t\t\tmessage: \"Shared mutation was cancelled before starting\",\n\t\t\texecutionState: \"not_started\",\n\t\t\tretryable: false,\n\t\t});\n}\n\nfunction missing(error: unknown): boolean {\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\t\"code\" in error &&\n\t\t(error.code === \"ENOENT\" || error.code === \"ENOTDIR\")\n\t);\n}\n\nasync function checkRevision(\n\tfilePath: string,\n\ttarget: string,\n\trevision: ExpectedWorkspaceRevision,\n\toperations: ConfinedDaemonToolOperations,\n\tcontext: RemoteWorkspaceServerRequestContext,\n): Promise<void> {\n\trequireActiveMutation(context);\n\tif (resolve(filePath) !== target)\n\t\tthrow revisionError(\"invalid_request\", \"Shared mutation path does not match its revision precondition\");\n\tif (\"sha256\" in revision || \"absent\" in revision) {\n\t\tlet actual: Buffer | undefined;\n\t\ttry {\n\t\t\tactual = await operations.readFile(target);\n\t\t} catch (error) {\n\t\t\tif (!missing(error)) throw error;\n\t\t}\n\t\tif (\"sha256\" in revision && (!actual || createHash(\"sha256\").update(actual).digest(\"hex\") !== revision.sha256)) {\n\t\t\tthrow revisionError(\"conflict\", \"Workspace file changed since the expected revision\");\n\t\t}\n\t\tif (\"absent\" in revision && actual) throw revisionError(\"conflict\", \"Workspace file already exists\");\n\t}\n\trequireActiveMutation(context);\n\tcontext.markSideEffectStarted();\n}\n/** v2-only CAS checked inside the same process-wide per-file queue as edit/write. */\nexport function withSharedRevisionGuard<T>(\n\trequest: RemoteWorkspaceTypedRequest,\n\troot: string,\n\toperations: ConfinedDaemonToolOperations,\n\tcontext: RemoteWorkspaceServerRequestContext,\n\taction: () => Promise<T>,\n): Promise<T> {\n\tconst params = request.params as Record<string, unknown>;\n\tconst toolName = request.method === \"tool.invoke\" ? params.toolName : undefined;\n\tif (request.method !== \"workspace.write\" && toolName !== \"edit\" && toolName !== \"write\") return action();\n\tconst args = toolName ? (params.arguments as { path?: unknown }) : params;\n\tif (typeof args?.path !== \"string\" || !args.path)\n\t\tthrow revisionError(\"invalid_request\", \"Shared mutation requires a file path\");\n\tconst revision = params.expectedRevision as ExpectedWorkspaceRevision | undefined;\n\tif (!revision || (toolName === \"edit\" && !(\"sha256\" in revision))) {\n\t\tthrow revisionError(\n\t\t\t\"invalid_request\",\n\t\t\t\"Shared edit requires expected SHA-256; shared write requires expected SHA-256, expected absence or explicit unsafeOverwrite\",\n\t\t);\n\t}\n\tconst target = resolve(root, args.path);\n\treturn withFileMutationGuard((filePath) => checkRevision(filePath, target, revision, operations, context), action);\n}\n"]}
@@ -0,0 +1,61 @@
1
+ import { createHash } from "node:crypto";
2
+ import { resolve } from "node:path";
3
+ import { RemoteWorkspaceRequestError, } from "../core/remote-workspace-protocol/session.js";
4
+ import { withFileMutationGuard } from "../core/tools/file-mutation-queue.js";
5
+ function revisionError(code, message) {
6
+ return new RemoteWorkspaceRequestError({ code, message, executionState: "not_started", retryable: false });
7
+ }
8
+ function requireActiveMutation(context) {
9
+ if (context.signal.aborted)
10
+ throw new RemoteWorkspaceRequestError({
11
+ code: "cancelled",
12
+ message: "Shared mutation was cancelled before starting",
13
+ executionState: "not_started",
14
+ retryable: false,
15
+ });
16
+ }
17
+ function missing(error) {
18
+ return (typeof error === "object" &&
19
+ error !== null &&
20
+ "code" in error &&
21
+ (error.code === "ENOENT" || error.code === "ENOTDIR"));
22
+ }
23
+ async function checkRevision(filePath, target, revision, operations, context) {
24
+ requireActiveMutation(context);
25
+ if (resolve(filePath) !== target)
26
+ throw revisionError("invalid_request", "Shared mutation path does not match its revision precondition");
27
+ if ("sha256" in revision || "absent" in revision) {
28
+ let actual;
29
+ try {
30
+ actual = await operations.readFile(target);
31
+ }
32
+ catch (error) {
33
+ if (!missing(error))
34
+ throw error;
35
+ }
36
+ if ("sha256" in revision && (!actual || createHash("sha256").update(actual).digest("hex") !== revision.sha256)) {
37
+ throw revisionError("conflict", "Workspace file changed since the expected revision");
38
+ }
39
+ if ("absent" in revision && actual)
40
+ throw revisionError("conflict", "Workspace file already exists");
41
+ }
42
+ requireActiveMutation(context);
43
+ context.markSideEffectStarted();
44
+ }
45
+ /** v2-only CAS checked inside the same process-wide per-file queue as edit/write. */
46
+ export function withSharedRevisionGuard(request, root, operations, context, action) {
47
+ const params = request.params;
48
+ const toolName = request.method === "tool.invoke" ? params.toolName : undefined;
49
+ if (request.method !== "workspace.write" && toolName !== "edit" && toolName !== "write")
50
+ return action();
51
+ const args = toolName ? params.arguments : params;
52
+ if (typeof args?.path !== "string" || !args.path)
53
+ throw revisionError("invalid_request", "Shared mutation requires a file path");
54
+ const revision = params.expectedRevision;
55
+ if (!revision || (toolName === "edit" && !("sha256" in revision))) {
56
+ throw revisionError("invalid_request", "Shared edit requires expected SHA-256; shared write requires expected SHA-256, expected absence or explicit unsafeOverwrite");
57
+ }
58
+ const target = resolve(root, args.path);
59
+ return withFileMutationGuard((filePath) => checkRevision(filePath, target, revision, operations, context), action);
60
+ }
61
+ //# sourceMappingURL=shared-revision.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-revision.js","sourceRoot":"","sources":["../../src/daemon/shared-revision.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { resolve } from \"node:path\";\nimport type { ExpectedWorkspaceRevision } from \"../core/remote-workspace-protocol/contract.ts\";\nimport {\n\tRemoteWorkspaceRequestError,\n\ttype RemoteWorkspaceServerRequestContext,\n\ttype RemoteWorkspaceTypedRequest,\n} from \"../core/remote-workspace-protocol/session.ts\";\nimport { withFileMutationGuard } from \"../core/tools/file-mutation-queue.ts\";\nimport type { ConfinedDaemonToolOperations } from \"./workspace-runtime.ts\";\n\ntype SharedRevisionErrorCode = \"invalid_request\" | \"conflict\";\n\nfunction revisionError(code: SharedRevisionErrorCode, message: string): RemoteWorkspaceRequestError {\n\treturn new RemoteWorkspaceRequestError({ code, message, executionState: \"not_started\", retryable: false });\n}\nfunction requireActiveMutation(context: RemoteWorkspaceServerRequestContext): void {\n\tif (context.signal.aborted)\n\t\tthrow new RemoteWorkspaceRequestError({\n\t\t\tcode: \"cancelled\",\n\t\t\tmessage: \"Shared mutation was cancelled before starting\",\n\t\t\texecutionState: \"not_started\",\n\t\t\tretryable: false,\n\t\t});\n}\n\nfunction missing(error: unknown): boolean {\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\t\"code\" in error &&\n\t\t(error.code === \"ENOENT\" || error.code === \"ENOTDIR\")\n\t);\n}\n\nasync function checkRevision(\n\tfilePath: string,\n\ttarget: string,\n\trevision: ExpectedWorkspaceRevision,\n\toperations: ConfinedDaemonToolOperations,\n\tcontext: RemoteWorkspaceServerRequestContext,\n): Promise<void> {\n\trequireActiveMutation(context);\n\tif (resolve(filePath) !== target)\n\t\tthrow revisionError(\"invalid_request\", \"Shared mutation path does not match its revision precondition\");\n\tif (\"sha256\" in revision || \"absent\" in revision) {\n\t\tlet actual: Buffer | undefined;\n\t\ttry {\n\t\t\tactual = await operations.readFile(target);\n\t\t} catch (error) {\n\t\t\tif (!missing(error)) throw error;\n\t\t}\n\t\tif (\"sha256\" in revision && (!actual || createHash(\"sha256\").update(actual).digest(\"hex\") !== revision.sha256)) {\n\t\t\tthrow revisionError(\"conflict\", \"Workspace file changed since the expected revision\");\n\t\t}\n\t\tif (\"absent\" in revision && actual) throw revisionError(\"conflict\", \"Workspace file already exists\");\n\t}\n\trequireActiveMutation(context);\n\tcontext.markSideEffectStarted();\n}\n/** v2-only CAS checked inside the same process-wide per-file queue as edit/write. */\nexport function withSharedRevisionGuard<T>(\n\trequest: RemoteWorkspaceTypedRequest,\n\troot: string,\n\toperations: ConfinedDaemonToolOperations,\n\tcontext: RemoteWorkspaceServerRequestContext,\n\taction: () => Promise<T>,\n): Promise<T> {\n\tconst params = request.params as Record<string, unknown>;\n\tconst toolName = request.method === \"tool.invoke\" ? params.toolName : undefined;\n\tif (request.method !== \"workspace.write\" && toolName !== \"edit\" && toolName !== \"write\") return action();\n\tconst args = toolName ? (params.arguments as { path?: unknown }) : params;\n\tif (typeof args?.path !== \"string\" || !args.path)\n\t\tthrow revisionError(\"invalid_request\", \"Shared mutation requires a file path\");\n\tconst revision = params.expectedRevision as ExpectedWorkspaceRevision | undefined;\n\tif (!revision || (toolName === \"edit\" && !(\"sha256\" in revision))) {\n\t\tthrow revisionError(\n\t\t\t\"invalid_request\",\n\t\t\t\"Shared edit requires expected SHA-256; shared write requires expected SHA-256, expected absence or explicit unsafeOverwrite\",\n\t\t);\n\t}\n\tconst target = resolve(root, args.path);\n\treturn withFileMutationGuard((filePath) => checkRevision(filePath, target, revision, operations, context), action);\n}\n"]}
@@ -0,0 +1,9 @@
1
+ /** The parent mount is fixed; children can be created at any time. */
2
+ export declare class SharedWorkspaceRoots {
3
+ readonly parent: string;
4
+ private constructor();
5
+ static fromParent(parent: string): Promise<SharedWorkspaceRoots>;
6
+ bind(requested: string): Promise<string>;
7
+ private assertWithin;
8
+ }
9
+ //# sourceMappingURL=shared-roots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-roots.d.ts","sourceRoot":"","sources":["../../src/daemon/shared-roots.ts"],"names":[],"mappings":"AAGA,sEAAsE;AACtE,qBAAa,oBAAoB;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,OAAO,eAEN;IAED,OAAa,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAIrE;IAEK,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAS7C;IAED,OAAO,CAAC,YAAY;CAMpB","sourcesContent":["import { realpath, stat } from \"node:fs/promises\";\nimport { isAbsolute, relative, resolve, sep } from \"node:path\";\n\n/** The parent mount is fixed; children can be created at any time. */\nexport class SharedWorkspaceRoots {\n\treadonly parent: string;\n\tprivate constructor(parent: string) {\n\t\tthis.parent = parent;\n\t}\n\n\tstatic async fromParent(parent: string): Promise<SharedWorkspaceRoots> {\n\t\tconst canonical = await realpath(parent);\n\t\tif (!(await stat(canonical)).isDirectory()) throw new Error(\"Shared workspace parent is not a directory\");\n\t\treturn new SharedWorkspaceRoots(canonical);\n\t}\n\n\tasync bind(requested: string): Promise<string> {\n\t\tif (!isAbsolute(requested) || requested.includes(\"\\0\"))\n\t\t\tthrow new Error(\"Shared workspace root must be an absolute path\");\n\t\tconst candidate = resolve(requested);\n\t\tthis.assertWithin(candidate);\n\t\tconst canonical = await realpath(candidate);\n\t\tthis.assertWithin(canonical);\n\t\tif (!(await stat(canonical)).isDirectory()) throw new Error(\"Shared workspace root is not a directory\");\n\t\treturn canonical;\n\t}\n\n\tprivate assertWithin(path: string): void {\n\t\tconst suffix = relative(this.parent, path);\n\t\tif (suffix === \"..\" || suffix.startsWith(`..${sep}`) || isAbsolute(suffix)) {\n\t\t\tthrow new Error(\"Shared workspace root escapes the parent mount\");\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,33 @@
1
+ import { realpath, stat } from "node:fs/promises";
2
+ import { isAbsolute, relative, resolve, sep } from "node:path";
3
+ /** The parent mount is fixed; children can be created at any time. */
4
+ export class SharedWorkspaceRoots {
5
+ parent;
6
+ constructor(parent) {
7
+ this.parent = parent;
8
+ }
9
+ static async fromParent(parent) {
10
+ const canonical = await realpath(parent);
11
+ if (!(await stat(canonical)).isDirectory())
12
+ throw new Error("Shared workspace parent is not a directory");
13
+ return new SharedWorkspaceRoots(canonical);
14
+ }
15
+ async bind(requested) {
16
+ if (!isAbsolute(requested) || requested.includes("\0"))
17
+ throw new Error("Shared workspace root must be an absolute path");
18
+ const candidate = resolve(requested);
19
+ this.assertWithin(candidate);
20
+ const canonical = await realpath(candidate);
21
+ this.assertWithin(canonical);
22
+ if (!(await stat(canonical)).isDirectory())
23
+ throw new Error("Shared workspace root is not a directory");
24
+ return canonical;
25
+ }
26
+ assertWithin(path) {
27
+ const suffix = relative(this.parent, path);
28
+ if (suffix === ".." || suffix.startsWith(`..${sep}`) || isAbsolute(suffix)) {
29
+ throw new Error("Shared workspace root escapes the parent mount");
30
+ }
31
+ }
32
+ }
33
+ //# sourceMappingURL=shared-roots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-roots.js","sourceRoot":"","sources":["../../src/daemon/shared-roots.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAE/D,sEAAsE;AACtE,MAAM,OAAO,oBAAoB;IACvB,MAAM,CAAS;IACxB,YAAoB,MAAc,EAAE;QACnC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IAAA,CACrB;IAED,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAc,EAAiC;QACtE,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAC1G,OAAO,IAAI,oBAAoB,CAAC,SAAS,CAAC,CAAC;IAAA,CAC3C;IAED,KAAK,CAAC,IAAI,CAAC,SAAiB,EAAmB;QAC9C,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC;YACrD,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACnE,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;QACrC,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QAC7B,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC5C,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QAC7B,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QACxG,OAAO,SAAS,CAAC;IAAA,CACjB;IAEO,YAAY,CAAC,IAAY,EAAQ;QACxC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC3C,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5E,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACnE,CAAC;IAAA,CACD;CACD","sourcesContent":["import { realpath, stat } from \"node:fs/promises\";\nimport { isAbsolute, relative, resolve, sep } from \"node:path\";\n\n/** The parent mount is fixed; children can be created at any time. */\nexport class SharedWorkspaceRoots {\n\treadonly parent: string;\n\tprivate constructor(parent: string) {\n\t\tthis.parent = parent;\n\t}\n\n\tstatic async fromParent(parent: string): Promise<SharedWorkspaceRoots> {\n\t\tconst canonical = await realpath(parent);\n\t\tif (!(await stat(canonical)).isDirectory()) throw new Error(\"Shared workspace parent is not a directory\");\n\t\treturn new SharedWorkspaceRoots(canonical);\n\t}\n\n\tasync bind(requested: string): Promise<string> {\n\t\tif (!isAbsolute(requested) || requested.includes(\"\\0\"))\n\t\t\tthrow new Error(\"Shared workspace root must be an absolute path\");\n\t\tconst candidate = resolve(requested);\n\t\tthis.assertWithin(candidate);\n\t\tconst canonical = await realpath(candidate);\n\t\tthis.assertWithin(canonical);\n\t\tif (!(await stat(canonical)).isDirectory()) throw new Error(\"Shared workspace root is not a directory\");\n\t\treturn canonical;\n\t}\n\n\tprivate assertWithin(path: string): void {\n\t\tconst suffix = relative(this.parent, path);\n\t\tif (suffix === \"..\" || suffix.startsWith(`..${sep}`) || isAbsolute(suffix)) {\n\t\t\tthrow new Error(\"Shared workspace root escapes the parent mount\");\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,46 @@
1
+ import { type LspRuntimeState } from "../core/lsp/integration.ts";
2
+ import { type RemoteWorkspaceCapability, type RemoteWorkspaceCatalog, type RemoteWorkspaceIdentity } from "../core/remote-workspace-protocol/contract.ts";
3
+ import { type RemoteWorkspaceServerHandler } from "../core/remote-workspace-protocol/session.ts";
4
+ import { type ToolAccessMode, type ToolBackendInfo, type ToolExecOptions, type ToolExecResult, type ToolFileStat, type ToolGlobOptions, type ToolGrepOptions, type ToolGrepResult, type ToolMkdirOptions, type ToolOperations } from "../core/tools/operations.ts";
5
+ import { WorkspaceToolHost } from "../core/tools/workspace-tool-host.ts";
6
+ import type { DaemonConfiguration } from "./config.ts";
7
+ export declare class ConfinedDaemonToolOperations implements ToolOperations {
8
+ readonly cwd: string;
9
+ private readonly local;
10
+ private readonly allowedRoots;
11
+ private readonly allowProcessExec;
12
+ private readonly environment;
13
+ private readonly maxBufferedOutputBytes;
14
+ constructor(configuration: DaemonConfiguration);
15
+ createChildEnvironment(extra?: Record<string, string>): Record<string, string>;
16
+ private isWithinAllowedRoot;
17
+ private lexicalPath;
18
+ private existingPath;
19
+ private existingWritablePath;
20
+ private ensureConfinedWritableParent;
21
+ private writablePath;
22
+ private atomicWriteFile;
23
+ exec(command: string, options: ToolExecOptions): Promise<ToolExecResult>;
24
+ access(path: string, mode?: ToolAccessMode): Promise<void>;
25
+ readFile(path: string): Promise<Buffer>;
26
+ writeFile(path: string, content: string | Buffer): Promise<void>;
27
+ mkdir(path: string, options?: ToolMkdirOptions): Promise<void>;
28
+ stat(path: string): Promise<ToolFileStat>;
29
+ readdir(path: string): Promise<string[]>;
30
+ glob(pattern: string, cwd: string, options: ToolGlobOptions): Promise<string[]>;
31
+ grep(options: ToolGrepOptions): Promise<ToolGrepResult>;
32
+ detectImageMimeType(path: string): Promise<string | null | undefined>;
33
+ getBackendInfo(): ToolBackendInfo;
34
+ }
35
+ export interface DaemonWorkspaceRuntime {
36
+ readonly operations: ConfinedDaemonToolOperations;
37
+ readonly host: WorkspaceToolHost;
38
+ readonly lspRuntime?: LspRuntimeState;
39
+ readonly catalog: RemoteWorkspaceCatalog;
40
+ readonly capabilities: readonly RemoteWorkspaceCapability[];
41
+ createHandler(workspace: RemoteWorkspaceIdentity, sharedMode?: boolean): RemoteWorkspaceServerHandler;
42
+ retire(): Promise<void>;
43
+ dispose(): Promise<void>;
44
+ }
45
+ export declare function createDaemonWorkspaceRuntime(configuration: DaemonConfiguration): DaemonWorkspaceRuntime;
46
+ //# sourceMappingURL=workspace-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-runtime.d.ts","sourceRoot":"","sources":["../../src/daemon/workspace-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { mkdir as fsMkdir, lstat, open, readFile, realpath, rename, rm } from \"node:fs/promises\";\nimport { basename, isAbsolute, relative, resolve, sep } from \"node:path\";\nimport type { AgentToolResult } from \"@greppleai/grip-agent-core\";\nimport { createLspRuntimeState, createLspToolDefinitions, type LspRuntimeState } from \"../core/lsp/integration.ts\";\nimport type { LspServerStatus } from \"../core/lsp/manager.ts\";\nimport { createManagedStdioConnectionFactory, resolveLspConnectionFactory } from \"../core/lsp/transport.ts\";\nimport {\n\thashRemoteWorkspaceJson,\n\ttype RemoteWorkspaceCapability,\n\ttype RemoteWorkspaceCatalog,\n\ttype RemoteWorkspaceIdentity,\n\ttype RemoteWorkspaceMethod,\n\ttype RemoteWorkspaceOperationKind,\n} from \"../core/remote-workspace-protocol/contract.ts\";\nimport {\n\tRemoteWorkspaceRequestError,\n\ttype RemoteWorkspaceServerHandler,\n\ttype RemoteWorkspaceServerRequestContext,\n\ttype RemoteWorkspaceTypedRequest,\n} from \"../core/remote-workspace-protocol/session.ts\";\nimport { withFileMutationQueue } from \"../core/tools/file-mutation-queue.ts\";\nimport {\n\tGRIP_SESSION_ENVIRONMENT_NAMES,\n\tLocalToolOperations,\n\ttype ToolAccessMode,\n\ttype ToolBackendInfo,\n\ttype ToolExecOptions,\n\ttype ToolExecResult,\n\ttype ToolFileStat,\n\ttype ToolGlobOptions,\n\ttype ToolGrepMatch,\n\ttype ToolGrepOptions,\n\ttype ToolGrepResult,\n\ttype ToolMkdirOptions,\n\ttype ToolOperations,\n\ttype WorkspaceToolExecutionOptions,\n} from \"../core/tools/operations.ts\";\nimport { WorkspaceToolHost, type WorkspaceToolName } from \"../core/tools/workspace-tool-host.ts\";\nimport type { DaemonConfiguration } from \"./config.ts\";\nimport { loadDaemonLspConfiguration } from \"./lsp-config.ts\";\nimport { redactDaemonText } from \"./security.ts\";\n\nconst PRIMITIVE_OPERATIONS: RemoteWorkspaceMethod[] = [\n\t\"workspace.access\",\n\t\"workspace.read\",\n\t\"workspace.write\",\n\t\"workspace.mkdir\",\n\t\"workspace.stat\",\n\t\"workspace.readdir\",\n\t\"workspace.glob\",\n\t\"workspace.grep\",\n\t\"workspace.detect_image_mime\",\n\t\"workspace.exec\",\n];\n\nconst SECRET_ENVIRONMENT_SUFFIX = /_(?:API_KEY|TOKEN|SECRET|PASSWORD|PRIVATE_KEY|CREDENTIALS)$/iu;\nconst BASELINE_ENVIRONMENT =\n\tprocess.platform === \"win32\"\n\t\t? [\"PATH\", \"PATHEXT\", \"SYSTEMROOT\", \"COMSPEC\", \"TEMP\", \"TMP\", \"USER\", \"USERNAME\"]\n\t\t: [\"PATH\", \"HOME\", \"USER\", \"LOGNAME\", \"SHELL\", \"LANG\", \"TERM\", \"COLORTERM\", \"NO_COLOR\", \"TMPDIR\"];\n\nfunction isSecretEnvironmentName(name: string): boolean {\n\tconst upper = name.toUpperCase();\n\treturn (\n\t\tupper === \"GRIP_DAEMON_TOKEN\" ||\n\t\tupper === \"PI_DAEMON_TOKEN\" ||\n\t\tupper === \"GRIP_REMOTE_TOKEN\" ||\n\t\tupper.startsWith(\"GRIP_DAEMON_TLS_\") ||\n\t\tupper.startsWith(\"PI_DAEMON_TLS_\") ||\n\t\tSECRET_ENVIRONMENT_SUFFIX.test(upper)\n\t);\n}\nprocess.platform === \"win32\"\n\t? [\"PATH\", \"PATHEXT\", \"SYSTEMROOT\", \"TEMP\", \"TMP\"]\n\t: [\"PATH\", \"HOME\", \"LANG\", \"LC_ALL\", \"TERM\", \"TMPDIR\"];\n\nfunction isMissingPath(error: unknown): boolean {\n\treturn error instanceof Error && \"code\" in error && error.code === \"ENOENT\";\n}\n\nfunction sanitizeLspStatus(\n\tstatus: LspServerStatus,\n\tconfiguration: DaemonConfiguration,\n): Omit<LspServerStatus, \"capabilities\"> {\n\tconst { capabilities: _capabilities, ...safe } = status;\n\tconst secrets = [configuration.token, configuration.tls?.passphrase];\n\tconst redact = (value: string | undefined) => (value ? redactDaemonText(value, secrets) : undefined);\n\treturn {\n\t\t...safe,\n\t\tserverId: redact(safe.serverId)!,\n\t\tlanguageIds: safe.languageIds.map((value) => redact(value)!),\n\t\ttransport: redact(safe.transport)!,\n\t\t...(safe.instanceKey ? { instanceKey: redact(safe.instanceKey) } : {}),\n\t\t...(safe.workspaceRoot ? { workspaceRoot: redact(safe.workspaceRoot) } : {}),\n\t\t...(safe.rootUri ? { rootUri: redact(safe.rootUri) } : {}),\n\t\t...(safe.endpoint ? { endpoint: redact(safe.endpoint) } : {}),\n\t\t...(safe.lastError ? { lastError: redact(safe.lastError) } : {}),\n\t\t...(safe.lastRequestError ? { lastRequestError: redact(safe.lastRequestError) } : {}),\n\t\t...(safe.stderr ? { stderr: redact(safe.stderr) } : {}),\n\t\t...(safe.synchronizationError ? { synchronizationError: redact(safe.synchronizationError) } : {}),\n\t};\n}\n\nfunction portableToolResult(result: AgentToolResult<unknown>): AgentToolResult<unknown> {\n\tconst clone = JSON.parse(JSON.stringify(result)) as AgentToolResult<unknown>;\n\tconst details = clone.details;\n\tif (!details || typeof details !== \"object\" || !(\"fullOutputPath\" in details)) return clone;\n\tconst fullOutputPath = (details as { fullOutputPath?: unknown }).fullOutputPath;\n\tif (typeof fullOutputPath !== \"string\") return clone;\n\tdelete (details as { fullOutputPath?: unknown }).fullOutputPath;\n\tfor (const content of clone.content) {\n\t\tif (content.type === \"text\") {\n\t\t\tcontent.text = content.text.replaceAll(fullOutputPath, \"[remote full output is not transferable]\");\n\t\t}\n\t}\n\treturn clone;\n}\n\nfunction operationKind(name: string): RemoteWorkspaceOperationKind {\n\tif (name.startsWith(\"lsp_\")) return \"service\";\n\tswitch (name) {\n\t\tcase \"read\":\n\t\tcase \"grep\":\n\t\tcase \"find\":\n\t\tcase \"ls\":\n\t\t\treturn \"read\";\n\t\tcase \"edit\":\n\t\tcase \"write\":\n\t\t\treturn \"mutation\";\n\t\tcase \"bash\":\n\t\t\treturn \"process\";\n\t}\n\tthrow new Error(`Unknown daemon tool: ${name}`);\n}\n\nfunction runCommand(\n\tcommand: string,\n\targs: string[],\n\tenvironment: NodeJS.ProcessEnv,\n\tmaxBufferedBytes: number,\n): Promise<Buffer> {\n\treturn new Promise((resolvePromise, reject) => {\n\t\tconst child = spawn(command, args, { stdio: [\"ignore\", \"pipe\", \"pipe\"], windowsHide: true, env: environment });\n\t\tconst stdout: Buffer[] = [];\n\t\tconst stderr: Buffer[] = [];\n\t\tlet bufferedBytes = 0;\n\t\tlet settled = false;\n\t\tconst append = (target: Buffer[], chunk: Buffer) => {\n\t\t\tif (settled) return;\n\t\t\tbufferedBytes += chunk.byteLength;\n\t\t\tif (bufferedBytes > maxBufferedBytes) {\n\t\t\t\tsettled = true;\n\t\t\t\tchild.kill();\n\t\t\t\treject(new Error(`${command} output exceeded the daemon buffered-output limit`));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttarget.push(Buffer.from(chunk));\n\t\t};\n\t\tchild.stdout.on(\"data\", (chunk: Buffer) => append(stdout, chunk));\n\t\tchild.stderr.on(\"data\", (chunk: Buffer) => append(stderr, chunk));\n\t\tchild.once(\"error\", (error) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\treject(error);\n\t\t});\n\t\tchild.once(\"close\", (code) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tif (code === 0 || (command === \"rg\" && code === 1)) {\n\t\t\t\tresolvePromise(Buffer.concat(stdout));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\treject(new Error(Buffer.concat(stderr).toString(\"utf8\").trim() || `${command} exited with code ${code}`));\n\t\t});\n\t});\n}\n\nfunction isUnknownRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction nestedText(record: Record<string, unknown> | undefined, key: string): string | undefined {\n\tconst nested = record?.[key];\n\treturn isUnknownRecord(nested) && typeof nested.text === \"string\" ? nested.text : undefined;\n}\n\nfunction parseDaemonGrepMatch(line: string): ToolGrepMatch | undefined {\n\tif (!line) return undefined;\n\tlet event: unknown;\n\ttry {\n\t\tevent = JSON.parse(line) as unknown;\n\t} catch {\n\t\treturn undefined;\n\t}\n\tconst eventRecord = isUnknownRecord(event) ? event : undefined;\n\tif (eventRecord?.type !== \"match\") return undefined;\n\tconst data = isUnknownRecord(eventRecord.data) ? eventRecord.data : undefined;\n\tconst filePath = nestedText(data, \"path\");\n\tconst lineNumber = data?.line_number;\n\tif (!filePath || typeof lineNumber !== \"number\") return undefined;\n\tconst lineText = nestedText(data, \"lines\");\n\treturn { filePath, lineNumber, ...(lineText === undefined ? {} : { lineText }) };\n}\n\nexport class ConfinedDaemonToolOperations implements ToolOperations {\n\treadonly cwd: string;\n\tprivate readonly local: LocalToolOperations;\n\tprivate readonly allowedRoots: readonly string[];\n\tprivate readonly allowProcessExec: boolean;\n\tprivate readonly environment: NodeJS.ProcessEnv;\n\tprivate readonly maxBufferedOutputBytes: number;\n\n\tconstructor(configuration: DaemonConfiguration) {\n\t\tthis.cwd = configuration.workspaceRoot;\n\t\tthis.local = new LocalToolOperations(this.cwd);\n\t\tthis.allowedRoots = Object.freeze([\n\t\t\tthis.cwd,\n\t\t\t...(configuration.temporaryRoot ? [configuration.temporaryRoot] : []),\n\t\t]);\n\t\tthis.allowProcessExec = configuration.allowProcessExec;\n\t\tthis.maxBufferedOutputBytes = configuration.maxBufferedOutputBytes;\n\t\tconst localeNames = Object.keys(process.env).filter((name) => /^LC_/iu.test(name));\n\t\tconst names = new Set([...BASELINE_ENVIRONMENT, ...localeNames, ...configuration.forwardedEnvironment]);\n\t\tthis.environment = {};\n\t\tfor (const name of names) {\n\t\t\tif (isSecretEnvironmentName(name)) continue;\n\t\t\tconst value = process.env[name];\n\t\t\tif (value !== undefined) this.environment[name] = value;\n\t\t}\n\t}\n\n\tcreateChildEnvironment(extra: Record<string, string> = {}): Record<string, string> {\n\t\tconst environment: Record<string, string> = {};\n\t\tfor (const [name, value] of Object.entries(this.environment)) {\n\t\t\tif (value !== undefined) environment[name] = value;\n\t\t}\n\t\tObject.assign(environment, extra);\n\t\tfor (const name of Object.keys(environment)) {\n\t\t\tif (isSecretEnvironmentName(name)) delete environment[name];\n\t\t}\n\t\treturn environment;\n\t}\n\tprivate isWithinAllowedRoot(candidate: string, root: string): boolean {\n\t\tconst pathRelative = relative(root, candidate);\n\t\treturn pathRelative !== \"..\" && !pathRelative.startsWith(`..${sep}`) && !isAbsolute(pathRelative);\n\t}\n\n\tprivate lexicalPath(path: string): string {\n\t\tconst candidate = resolve(this.cwd, path);\n\t\tif (!this.allowedRoots.some((root) => this.isWithinAllowedRoot(candidate, root))) {\n\t\t\tthrow new Error(`Path escapes the daemon workspace and allowed temporary root: ${path}`);\n\t\t}\n\t\treturn candidate;\n\t}\n\n\tprivate async existingPath(path: string): Promise<string> {\n\t\tconst candidate = this.lexicalPath(path);\n\t\tconst canonical = await realpath(candidate);\n\t\treturn this.lexicalPath(canonical);\n\t}\n\n\tprivate async existingWritablePath(candidate: string, path: string): Promise<string | undefined> {\n\t\ttry {\n\t\t\tconst stat = await lstat(candidate);\n\t\t\tif (stat.isSymbolicLink()) {\n\t\t\t\ttry {\n\t\t\t\t\tthis.lexicalPath(await realpath(candidate));\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (isMissingPath(error)) throw new Error(`Writable path uses a broken symbolic link: ${path}`);\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tthrow new Error(`Writable path uses a symbolic link: ${path}`);\n\t\t\t}\n\t\t\tconst canonical = await realpath(candidate);\n\t\t\tthis.lexicalPath(canonical);\n\t\t\treturn this.lexicalPath(canonical);\n\t\t} catch (error) {\n\t\t\tif (isMissingPath(error)) return undefined;\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate async ensureConfinedWritableParent(candidate: string, path: string): Promise<void> {\n\t\tlet parent = resolve(candidate, \"..\");\n\t\twhile (true) {\n\t\t\ttry {\n\t\t\t\tconst parentStat = await lstat(parent);\n\t\t\t\tif (parentStat.isSymbolicLink()) {\n\t\t\t\t\tthis.lexicalPath(await realpath(parent));\n\t\t\t\t\tthrow new Error(`Writable parent uses a symbolic link: ${path}`);\n\t\t\t\t}\n\t\t\t\tconst canonicalParent = await realpath(parent);\n\t\t\t\tthis.lexicalPath(canonicalParent);\n\t\t\t\treturn;\n\t\t\t} catch (error) {\n\t\t\t\tif (!isMissingPath(error)) throw error;\n\t\t\t\tconst next = resolve(parent, \"..\");\n\t\t\t\tif (next === parent) throw new Error(`No confined parent exists for path: ${path}`);\n\t\t\t\tparent = next;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async writablePath(path: string): Promise<string> {\n\t\tconst candidate = this.lexicalPath(path);\n\t\tconst existing = await this.existingWritablePath(candidate, path);\n\t\tif (existing) return existing;\n\t\tawait this.ensureConfinedWritableParent(candidate, path);\n\t\treturn candidate;\n\t}\n\n\tprivate async atomicWriteFile(path: string, content: string | Buffer): Promise<void> {\n\t\tconst target = await this.writablePath(path);\n\t\tconst parent = resolve(target, \"..\");\n\t\tconst temporary = resolve(parent, `.grip-remote-write-${process.pid}-${randomUUID()}-${basename(target)}.tmp`);\n\t\tthis.lexicalPath(temporary);\n\t\tlet wroteTemporary = false;\n\t\ttry {\n\t\t\tconst handle = await open(temporary, \"wx\", 0o600);\n\t\t\ttry {\n\t\t\t\tawait handle.writeFile(content, typeof content === \"string\" ? \"utf8\" : undefined);\n\t\t\t} finally {\n\t\t\t\tawait handle.close();\n\t\t\t}\n\t\t\twroteTemporary = true;\n\t\t\tthis.lexicalPath(await realpath(temporary));\n\t\t\ttry {\n\t\t\t\tif ((await lstat(target)).isSymbolicLink()) throw new Error(`Writable path uses a symbolic link: ${path}`);\n\t\t\t} catch (error) {\n\t\t\t\tif (!isMissingPath(error)) throw error;\n\t\t\t}\n\t\t\tawait rename(temporary, target);\n\t\t\twroteTemporary = false;\n\t\t\tthis.lexicalPath(await realpath(target));\n\t\t} finally {\n\t\t\tif (wroteTemporary) await rm(temporary, { force: true });\n\t\t}\n\t}\n\n\tasync exec(command: string, options: ToolExecOptions): Promise<ToolExecResult> {\n\t\tif (!this.allowProcessExec) throw new Error(\"Process execution is disabled by daemon policy\");\n\t\tconst cwd = await this.existingPath(options.cwd ?? this.cwd);\n\t\tconst environment = { ...this.environment };\n\t\tfor (const name of GRIP_SESSION_ENVIRONMENT_NAMES) {\n\t\t\tconst value = options.env?.[name];\n\t\t\tif (value !== undefined) environment[name] = value;\n\t\t}\n\t\treturn this.local.exec(command, { ...options, cwd, env: environment });\n\t}\n\n\tasync access(path: string, mode?: ToolAccessMode): Promise<void> {\n\t\tawait this.local.access(await this.existingPath(path), mode);\n\t}\n\n\tasync readFile(path: string): Promise<Buffer> {\n\t\treturn this.local.readFile(await this.existingPath(path));\n\t}\n\n\tasync writeFile(path: string, content: string | Buffer): Promise<void> {\n\t\tawait this.atomicWriteFile(path, content);\n\t}\n\n\tasync mkdir(path: string, options?: ToolMkdirOptions): Promise<void> {\n\t\tawait fsMkdir(await this.writablePath(path), options);\n\t}\n\n\tasync stat(path: string): Promise<ToolFileStat> {\n\t\treturn this.local.stat(await this.existingPath(path));\n\t}\n\n\tasync readdir(path: string): Promise<string[]> {\n\t\treturn this.local.readdir(await this.existingPath(path));\n\t}\n\n\tasync glob(pattern: string, cwd: string, options: ToolGlobOptions): Promise<string[]> {\n\t\tconst searchRoot = await this.existingPath(cwd);\n\t\tconst args = [\"--glob\", \"--color=never\", \"--hidden\", \"--no-require-git\", \"--max-results\", String(options.limit)];\n\t\tfor (const ignored of options.ignore) args.push(\"--exclude\", ignored);\n\t\tlet effectivePattern = pattern;\n\t\tif (pattern.includes(\"/\")) {\n\t\t\targs.push(\"--full-path\");\n\t\t\tif (!pattern.startsWith(\"/\") && !pattern.startsWith(\"**/\") && pattern !== \"**\")\n\t\t\t\teffectivePattern = `**/${pattern}`;\n\t\t}\n\t\targs.push(\"--\", effectivePattern, searchRoot);\n\t\tconst output = await runCommand(\"fd\", args, this.environment, this.maxBufferedOutputBytes);\n\t\tconst results: string[] = [];\n\t\tfor (const entry of output.toString(\"utf8\").split(\"\\n\")) {\n\t\t\tif (!entry) continue;\n\t\t\ttry {\n\t\t\t\tresults.push(await this.existingPath(entry));\n\t\t\t} catch {\n\t\t\t\t// Symlinks escaping the workspace are deliberately omitted.\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t}\n\n\tasync grep(options: ToolGrepOptions): Promise<ToolGrepResult> {\n\t\tconst searchPath = await this.existingPath(options.path);\n\t\tconst isDirectory = (await this.local.stat(searchPath)).isDirectory();\n\t\tconst args = [\"--json\", \"--line-number\", \"--color=never\", \"--hidden\"];\n\t\tif (options.ignoreCase) args.push(\"--ignore-case\");\n\t\tif (options.literal) args.push(\"--fixed-strings\");\n\t\tif (options.glob) args.push(\"--glob\", options.glob);\n\t\targs.push(\"--\", options.pattern, searchPath);\n\t\tconst output = await runCommand(\"rg\", args, this.environment, this.maxBufferedOutputBytes);\n\t\tconst matches: ToolGrepMatch[] = [];\n\t\tfor (const line of output.toString(\"utf8\").split(\"\\n\")) {\n\t\t\tif (matches.length >= options.limit) continue;\n\t\t\tconst match = parseDaemonGrepMatch(line);\n\t\t\tif (!match) continue;\n\t\t\ttry {\n\t\t\t\tawait this.existingPath(match.filePath);\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tmatches.push(match);\n\t\t}\n\t\treturn { isDirectory, matches };\n\t}\n\n\tasync detectImageMimeType(path: string): Promise<string | null | undefined> {\n\t\treturn this.local.detectImageMimeType(await this.existingPath(path));\n\t}\n\n\tgetBackendInfo(): ToolBackendInfo {\n\t\treturn { type: \"local\", cwd: this.cwd };\n\t}\n}\n\nexport interface DaemonWorkspaceRuntime {\n\treadonly operations: ConfinedDaemonToolOperations;\n\treadonly host: WorkspaceToolHost;\n\treadonly lspRuntime?: LspRuntimeState;\n\treadonly catalog: RemoteWorkspaceCatalog;\n\treadonly capabilities: readonly RemoteWorkspaceCapability[];\n\tcreateHandler(workspace: RemoteWorkspaceIdentity, sharedMode?: boolean): RemoteWorkspaceServerHandler;\n\tretire(): Promise<void>;\n\tdispose(): Promise<void>;\n}\n\ntype DaemonRequestInterruptionCode = \"cancelled\" | \"deadline_exceeded\";\ntype DaemonInterruptedExecutionState = \"not_started\" | \"indeterminate\";\n\nfunction requestError(code: DaemonRequestInterruptionCode, message: string, state: DaemonInterruptedExecutionState) {\n\treturn new RemoteWorkspaceRequestError({ code, message, executionState: state, retryable: false });\n}\ninterface DaemonRequestRuntime {\n\tconfiguration: DaemonConfiguration;\n\toperations: ConfinedDaemonToolOperations;\n\thost: WorkspaceToolHost;\n\tlspRuntime: LspRuntimeState | undefined;\n\tworkspace: RemoteWorkspaceIdentity;\n\tsharedMode: boolean;\n}\n\nfunction withDaemonWorkspace<T extends Record<string, unknown>>(result: T, workspace: RemoteWorkspaceIdentity) {\n\treturn { ...result, workspace };\n}\n\nasync function synchronizeDaemonToolFile(\n\ttoolName: string,\n\tinvocationArguments: unknown,\n\truntime: DaemonRequestRuntime,\n): Promise<void> {\n\tif (!runtime.lspRuntime) return;\n\tconst args = invocationArguments as { path?: unknown };\n\tif (typeof args.path !== \"string\") return;\n\ttry {\n\t\tif (toolName === \"read\") {\n\t\t\tawait runtime.lspRuntime.fileSync.handleFileRead(args.path, runtime.operations);\n\t\t} else if (toolName === \"write\" || toolName === \"edit\") {\n\t\t\tawait runtime.lspRuntime.fileSync.handleFileWrite(args.path, runtime.operations);\n\t\t}\n\t} catch {\n\t\t// Synchronization remains best-effort, matching local AgentSession behavior.\n\t}\n}\n\nfunction marksToolSideEffect(kind: RemoteWorkspaceOperationKind, toolName: string, sharedMode: boolean): boolean {\n\treturn kind !== \"read\" && !(sharedMode && (toolName === \"edit\" || toolName === \"write\"));\n}\n\nasync function invokeDaemonTool(\n\trequest: RemoteWorkspaceTypedRequest,\n\tparams: Record<string, unknown>,\n\tcontext: RemoteWorkspaceServerRequestContext,\n\truntime: DaemonRequestRuntime,\n): Promise<AgentToolResult<unknown>> {\n\tconst toolName = params.toolName as string;\n\tconst kind = operationKind(toolName);\n\tif (marksToolSideEffect(kind, toolName, runtime.sharedMode)) context.markSideEffectStarted();\n\tlet updateQueue = Promise.resolve();\n\ttry {\n\t\tconst result = await runtime.host.executePrepared(toolName, {\n\t\t\ttoolCallId: request.id,\n\t\t\targuments: params.arguments,\n\t\t\tsignal: context.signal,\n\t\t\texecutionOptions: params.executionOptions as WorkspaceToolExecutionOptions,\n\t\t\tonUpdate: (update) => {\n\t\t\t\tupdateQueue = updateQueue.then(() => context.sendUpdate(portableToolResult(update)));\n\t\t\t},\n\t\t});\n\t\tawait updateQueue;\n\t\tawait synchronizeDaemonToolFile(toolName, params.arguments, runtime);\n\t\tif (kind !== \"read\") context.markCommitted();\n\t\treturn portableToolResult(result);\n\t} catch (error) {\n\t\tawait updateQueue.catch(() => undefined);\n\t\tif (context.signal.aborted) {\n\t\t\tthrow requestError(\n\t\t\t\t\"cancelled\",\n\t\t\t\t\"Remote workspace tool invocation was cancelled\",\n\t\t\t\tkind === \"read\" ? \"not_started\" : \"indeterminate\",\n\t\t\t);\n\t\t}\n\t\tif (error instanceof RemoteWorkspaceRequestError) throw error;\n\t\tthrow new RemoteWorkspaceRequestError({\n\t\t\tcode: \"internal_error\",\n\t\t\tmessage: error instanceof Error ? error.message.slice(0, 4096) : \"Workspace tool failed\",\n\t\t\texecutionState: kind === \"read\" ? \"not_started\" : \"indeterminate\",\n\t\t\tretryable: false,\n\t\t});\n\t}\n}\n\nasync function executeDaemonWorkspaceProcess(\n\tparams: Record<string, unknown>,\n\tcontext: RemoteWorkspaceServerRequestContext,\n\truntime: DaemonRequestRuntime,\n): Promise<ToolExecResult> {\n\tcontext.markSideEffectStarted();\n\tlet updateQueue = Promise.resolve();\n\tlet pendingOutputBytes = 0;\n\tlet outputLimitExceeded = false;\n\tconst outputController = new AbortController();\n\tconst signal = AbortSignal.any([context.signal, outputController.signal]);\n\tlet result: ToolExecResult;\n\ttry {\n\t\tresult = await runtime.operations.exec(params.command as string, {\n\t\t\tcwd: params.cwd as string,\n\t\t\tsignal,\n\t\t\tonData: (data) => {\n\t\t\t\tif (outputLimitExceeded) return;\n\t\t\t\tconst chunk = Buffer.from(data);\n\t\t\t\tpendingOutputBytes += chunk.byteLength;\n\t\t\t\tif (pendingOutputBytes > runtime.configuration.maxBufferedOutputBytes) {\n\t\t\t\t\toutputLimitExceeded = true;\n\t\t\t\t\toutputController.abort();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tupdateQueue = updateQueue\n\t\t\t\t\t.then(() => context.sendUpdate({ dataBase64: chunk.toString(\"base64\") }))\n\t\t\t\t\t.finally(() => {\n\t\t\t\t\t\tpendingOutputBytes -= chunk.byteLength;\n\t\t\t\t\t});\n\t\t\t\t// The process may run after an update fails; observe rejection until the final await.\n\t\t\t\tvoid updateQueue.catch(() => undefined);\n\t\t\t},\n\t\t});\n\t} catch (error) {\n\t\tif (outputLimitExceeded) throw new Error(\"Process output exceeded the daemon buffered-output limit\");\n\t\tthrow error;\n\t}\n\tawait updateQueue;\n\tcontext.markCommitted();\n\treturn result;\n}\n\nasync function readDaemonResource(\n\tparams: Record<string, unknown>,\n\truntime: DaemonRequestRuntime,\n): Promise<Record<string, unknown>> {\n\tconst path = params.path as string;\n\tconst resourcePath =\n\t\tpath === \"SANDBOX.md\"\n\t\t\t? runtime.configuration.sandboxInstructionsPath\n\t\t\t: path === \"AGENTS.md\"\n\t\t\t\t? runtime.configuration.userAgentsPath\n\t\t\t\t: undefined;\n\tif (!resourcePath) {\n\t\tthrow new RemoteWorkspaceRequestError({\n\t\t\tcode: \"not_available\",\n\t\t\tmessage: \"Requested daemon resource is not available\",\n\t\t\texecutionState: \"not_started\",\n\t\t\tretryable: false,\n\t\t});\n\t}\n\treturn withDaemonWorkspace({ contentBase64: (await readFile(resourcePath)).toString(\"base64\") }, runtime.workspace);\n}\n\nfunction getDaemonLspStatus(runtime: DaemonRequestRuntime): Record<string, unknown> {\n\tif (!runtime.lspRuntime) {\n\t\tthrow new RemoteWorkspaceRequestError({\n\t\t\tcode: \"not_available\",\n\t\t\tmessage: \"Daemon LSP is not configured\",\n\t\t\texecutionState: \"not_started\",\n\t\t\tretryable: false,\n\t\t});\n\t}\n\treturn {\n\t\tenabled: true,\n\t\tservers: runtime.lspRuntime.manager.getStatus().map((status) => sanitizeLspStatus(status, runtime.configuration)),\n\t};\n}\nasync function statDaemonWorkspace(path: string, runtime: DaemonRequestRuntime): Promise<unknown> {\n\ttry {\n\t\tconst value = await runtime.operations.stat(path);\n\t\treturn withDaemonWorkspace(\n\t\t\t{ kind: value.isDirectory() ? \"directory\" : value.isFile() ? \"file\" : \"other\" },\n\t\t\truntime.workspace,\n\t\t);\n\t} catch (error) {\n\t\tif (!runtime.sharedMode || !isMissingPath(error)) throw error;\n\t\treturn withDaemonWorkspace({ kind: \"absent\" }, runtime.workspace);\n\t}\n}\n\nasync function dispatchDaemonWorkspaceRequest(\n\trequest: RemoteWorkspaceTypedRequest,\n\tcontext: RemoteWorkspaceServerRequestContext,\n\truntime: DaemonRequestRuntime,\n): Promise<unknown> {\n\tconst params = request.params as Record<string, unknown>;\n\tswitch (request.method) {\n\t\tcase \"tool.invoke\":\n\t\t\treturn invokeDaemonTool(request, params, context, runtime);\n\t\tcase \"workspace.access\":\n\t\t\tawait runtime.operations.access(params.path as string, params.mode as ToolAccessMode | undefined);\n\t\t\treturn {};\n\t\tcase \"workspace.read\":\n\t\t\treturn withDaemonWorkspace(\n\t\t\t\t{ contentBase64: (await runtime.operations.readFile(params.path as string)).toString(\"base64\") },\n\t\t\t\truntime.workspace,\n\t\t\t);\n\t\tcase \"workspace.write\":\n\t\t\tif (!runtime.sharedMode) context.markSideEffectStarted();\n\t\t\tawait withFileMutationQueue(resolve(runtime.configuration.workspaceRoot, params.path as string), () =>\n\t\t\t\truntime.operations.writeFile(params.path as string, Buffer.from(params.contentBase64 as string, \"base64\")),\n\t\t\t);\n\t\t\tcontext.markCommitted();\n\t\t\treturn {};\n\t\tcase \"workspace.mkdir\":\n\t\t\tif (!runtime.sharedMode) context.markSideEffectStarted();\n\t\t\tawait withFileMutationQueue(resolve(runtime.configuration.workspaceRoot, params.path as string), () => {\n\t\t\t\tif (runtime.sharedMode) {\n\t\t\t\t\tif (context.signal.aborted)\n\t\t\t\t\t\tthrow requestError(\n\t\t\t\t\t\t\t\"cancelled\",\n\t\t\t\t\t\t\t\"Shared directory creation was cancelled before starting\",\n\t\t\t\t\t\t\t\"not_started\",\n\t\t\t\t\t\t);\n\t\t\t\t\tcontext.markSideEffectStarted();\n\t\t\t\t}\n\t\t\t\treturn runtime.operations.mkdir(params.path as string, { recursive: params.recursive === true });\n\t\t\t});\n\t\t\tcontext.markCommitted();\n\t\t\treturn {};\n\t\tcase \"workspace.stat\":\n\t\t\treturn statDaemonWorkspace(params.path as string, runtime);\n\t\tcase \"workspace.readdir\":\n\t\t\treturn withDaemonWorkspace(\n\t\t\t\t{ entries: await runtime.operations.readdir(params.path as string) },\n\t\t\t\truntime.workspace,\n\t\t\t);\n\t\tcase \"workspace.glob\":\n\t\t\treturn withDaemonWorkspace(\n\t\t\t\t{\n\t\t\t\t\tmatches: await runtime.operations.glob(params.pattern as string, params.cwd as string, {\n\t\t\t\t\t\tignore: params.ignore as string[],\n\t\t\t\t\t\tlimit: params.limit as number,\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t\truntime.workspace,\n\t\t\t);\n\t\tcase \"workspace.grep\": {\n\t\t\tconst result = await runtime.operations.grep(params as unknown as ToolGrepOptions);\n\t\t\treturn withDaemonWorkspace(result as unknown as Record<string, unknown>, runtime.workspace);\n\t\t}\n\t\tcase \"workspace.detect_image_mime\":\n\t\t\treturn withDaemonWorkspace(\n\t\t\t\t{ mimeType: (await runtime.operations.detectImageMimeType(params.path as string)) ?? null },\n\t\t\t\truntime.workspace,\n\t\t\t);\n\t\tcase \"workspace.exec\":\n\t\t\treturn executeDaemonWorkspaceProcess(params, context, runtime);\n\t\tcase \"resource.read\":\n\t\t\treturn readDaemonResource(params, runtime);\n\t\tcase \"lsp.status\":\n\t\t\treturn getDaemonLspStatus(runtime);\n\t\tdefault:\n\t\t\tthrow new RemoteWorkspaceRequestError({\n\t\t\t\tcode: \"method_not_supported\",\n\t\t\t\tmessage: `Workspace operation is not implemented: ${request.method}`,\n\t\t\t\texecutionState: \"not_started\",\n\t\t\t\tretryable: false,\n\t\t\t});\n\t}\n}\n\nexport function createDaemonWorkspaceRuntime(configuration: DaemonConfiguration): DaemonWorkspaceRuntime {\n\tconst operations = new ConfinedDaemonToolOperations(configuration);\n\tconst toolNames: WorkspaceToolName[] = [\"read\", \"edit\", \"write\", \"grep\", \"find\", \"ls\"];\n\tif (configuration.allowProcessExec) toolNames.splice(1, 0, \"bash\");\n\tconst lspConfiguration = loadDaemonLspConfiguration(configuration);\n\tconst lspRuntime = lspConfiguration.enabled\n\t\t? createLspRuntimeState(configuration.workspaceRoot, {\n\t\t\t\tconfiguration: lspConfiguration,\n\t\t\t\tgetToolBackendInfo: () => operations.getBackendInfo(),\n\t\t\t\tgetToolOperations: () => operations,\n\t\t\t\tresolveConnectionFactory: (transport) =>\n\t\t\t\t\ttransport.type === \"spawn\"\n\t\t\t\t\t\t? createManagedStdioConnectionFactory({\n\t\t\t\t\t\t\t\t...transport,\n\t\t\t\t\t\t\t\tenv: operations.createChildEnvironment(transport.env),\n\t\t\t\t\t\t\t\tinheritEnvironment: false,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t: resolveLspConnectionFactory(transport),\n\t\t\t})\n\t\t: undefined;\n\tconst host = new WorkspaceToolHost({\n\t\tcwd: configuration.workspaceRoot,\n\t\toperations,\n\t\ttoolNames,\n\t\tadditionalDefinitions: lspRuntime\n\t\t\t? createLspToolDefinitions(\n\t\t\t\t\t() => lspRuntime,\n\t\t\t\t\t() => operations,\n\t\t\t\t)\n\t\t\t: undefined,\n\t\tdisposeTimeoutMs: Math.min(configuration.shutdownTimeoutMs, 60_000),\n\t});\n\tconst catalog: RemoteWorkspaceCatalog = {\n\t\tgeneration: 1,\n\t\ttools: host.getCatalog().map((entry) => ({\n\t\t\tname: entry.name,\n\t\t\texecutionMode: operationKind(entry.name),\n\t\t\tparameterSchema: structuredClone(entry.parameters) as Record<string, unknown>,\n\t\t\tschemaHash: hashRemoteWorkspaceJson(entry.parameters),\n\t\t\tfeatureFlags: [],\n\t\t})),\n\t\toperations: [\n\t\t\t...PRIMITIVE_OPERATIONS.filter((method) => method !== \"workspace.exec\" || configuration.allowProcessExec),\n\t\t\t...(configuration.sandboxInstructionsPath || configuration.userAgentsPath ? ([\"resource.read\"] as const) : []),\n\t\t\t...(lspRuntime ? ([\"lsp.status\"] as const) : []),\n\t\t],\n\t};\n\tconst capabilities: RemoteWorkspaceCapability[] = [\n\t\t\"catalog_refresh\",\n\t\t\"primitive_operations\",\n\t\t\"tool_updates\",\n\t\t...(lspRuntime ? ([\"lsp_status\"] as const) : []),\n\t];\n\tlet activeRequests = 0;\n\n\treturn {\n\t\toperations,\n\t\thost,\n\t\tlspRuntime,\n\t\tcatalog,\n\t\tcapabilities,\n\t\tcreateHandler(workspace, sharedMode = false) {\n\t\t\tconst requestRuntime: DaemonRequestRuntime = {\n\t\t\t\tconfiguration,\n\t\t\t\toperations,\n\t\t\t\thost,\n\t\t\t\tlspRuntime,\n\t\t\t\tworkspace,\n\t\t\t\tsharedMode,\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tvalidateToolArguments: (toolName, value) => host.validatePreparedArguments(toolName, value),\n\t\t\t\tasync handleRequest(request, context) {\n\t\t\t\t\tif (activeRequests >= configuration.maxGlobalRequests) {\n\t\t\t\t\t\tthrow new RemoteWorkspaceRequestError({\n\t\t\t\t\t\t\tcode: \"limit_exceeded\",\n\t\t\t\t\t\t\tmessage: \"Daemon global active request limit reached\",\n\t\t\t\t\t\t\texecutionState: \"not_started\",\n\t\t\t\t\t\t\tretryable: true,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tactiveRequests++;\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn await dispatchDaemonWorkspaceRequest(request, context, requestRuntime);\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tactiveRequests--;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\tretire: async () => {\n\t\t\tawait host.waitForIdle(configuration.shutdownTimeoutMs);\n\t\t\tawait lspRuntime?.manager.shutdownAll();\n\t\t\tawait host.dispose();\n\t\t},\n\t\tdispose: async () => {\n\t\t\tawait Promise.all([lspRuntime?.manager.shutdownAll(), host.dispose()]);\n\t\t},\n\t};\n}\n"]}