@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,155 @@
1
+ import { lstatSync, readFileSync, realpathSync } from "node:fs";
2
+ import { dirname, isAbsolute, relative, resolve } from "node:path";
3
+ import { parseLspConfiguration, resolveLspConfiguration, } from "../core/lsp/config.js";
4
+ import { resolveLspConfigurationLayerPaths } from "../core/lsp/config-loader.js";
5
+ import { relativeWithin } from "../core/lsp/portable-path.js";
6
+ import { DaemonConfigurationError } from "./config.js";
7
+ const DISABLED_LSP_CONFIGURATION = { enabled: false, servers: [] };
8
+ function readJson(path, optional = false) {
9
+ try {
10
+ return JSON.parse(readFileSync(path, "utf8"));
11
+ }
12
+ catch (error) {
13
+ if (optional && error instanceof Error && "code" in error && error.code === "ENOENT")
14
+ return undefined;
15
+ throw new DaemonConfigurationError(`Unable to load daemon LSP configuration ${path}: ${error instanceof Error ? error.message : String(error)}`);
16
+ }
17
+ }
18
+ function parseLayer(value, source, baseDir) {
19
+ const parsed = parseLspConfiguration(value);
20
+ if (!parsed.configuration) {
21
+ throw new DaemonConfigurationError(`Invalid daemon LSP configuration ${source}: ${parsed.diagnostics.map((item) => `${item.path}: ${item.message}`).join("; ")}`);
22
+ }
23
+ const resolved = parseLspConfiguration(resolveLspConfigurationLayerPaths(parsed.configuration, baseDir));
24
+ if (!resolved.configuration) {
25
+ throw new DaemonConfigurationError(`Invalid resolved daemon LSP configuration ${source}: ${resolved.diagnostics.map((item) => `${item.path}: ${item.message}`).join("; ")}`);
26
+ }
27
+ return resolved.configuration;
28
+ }
29
+ function isMissingPathError(error) {
30
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
31
+ }
32
+ function validateExistingLspPath(path, requestedPath, label) {
33
+ let isSymbolicLink;
34
+ try {
35
+ isSymbolicLink = lstatSync(path).isSymbolicLink();
36
+ }
37
+ catch (error) {
38
+ if (isMissingPathError(error))
39
+ return false;
40
+ throw error;
41
+ }
42
+ if (!isSymbolicLink)
43
+ return true;
44
+ try {
45
+ realpathSync(path);
46
+ }
47
+ catch {
48
+ throw new DaemonConfigurationError(`${label} uses a broken symbolic link: ${requestedPath}`);
49
+ }
50
+ return true;
51
+ }
52
+ function findExistingLspPathAncestor(path, label) {
53
+ let existing = path;
54
+ while (!validateExistingLspPath(existing, path, label)) {
55
+ const parent = dirname(existing);
56
+ if (parent === existing)
57
+ break;
58
+ existing = parent;
59
+ }
60
+ return existing;
61
+ }
62
+ function requireConfinedPath(path, configuration, label) {
63
+ const existing = findExistingLspPathAncestor(path, label);
64
+ const canonicalExisting = realpathSync(existing);
65
+ if (relativeWithin(configuration.workspaceRoot, canonicalExisting) === undefined) {
66
+ throw new DaemonConfigurationError(`${label} escapes the daemon workspace: ${path}`);
67
+ }
68
+ if (existing === path)
69
+ return canonicalExisting;
70
+ return resolve(canonicalExisting, relative(existing, path));
71
+ }
72
+ function canonicalizeDaemonLspServer(server, configuration, transport, workspace) {
73
+ return {
74
+ ...server,
75
+ transport,
76
+ workspace,
77
+ ...(server.pathMappings
78
+ ? {
79
+ pathMappings: server.pathMappings.map((mapping) => ({
80
+ ...mapping,
81
+ agentRoot: requireConfinedPath(mapping.agentRoot, configuration, `LSP path mapping for ${server.id}`),
82
+ })),
83
+ }
84
+ : {}),
85
+ };
86
+ }
87
+ function canonicalizeDaemonLspTransport(server, configuration) {
88
+ if (server.transport.type === "connection") {
89
+ throw new DaemonConfigurationError(`Daemon LSP server ${JSON.stringify(server.id)} cannot use a host-provided connection transport`);
90
+ }
91
+ if (server.transport.type === "spawn") {
92
+ if (!configuration.allowProcessExec) {
93
+ throw new DaemonConfigurationError(`Daemon LSP server ${JSON.stringify(server.id)} requires --daemon-allow-process-exec`);
94
+ }
95
+ return {
96
+ ...server.transport,
97
+ ...(server.transport.cwd
98
+ ? { cwd: requireConfinedPath(server.transport.cwd, configuration, `LSP cwd for ${server.id}`) }
99
+ : {}),
100
+ ...(isAbsolute(server.transport.command)
101
+ ? {
102
+ command: requireConfinedPath(server.transport.command, configuration, `LSP command for ${server.id}`),
103
+ }
104
+ : {}),
105
+ };
106
+ }
107
+ if (server.transport.type === "unix") {
108
+ return {
109
+ ...server.transport,
110
+ path: requireConfinedPath(server.transport.path, configuration, `LSP socket for ${server.id}`),
111
+ };
112
+ }
113
+ return server.transport;
114
+ }
115
+ function canonicalizeDaemonLspWorkspace(server, configuration) {
116
+ if (server.workspace.type === "fixed") {
117
+ return {
118
+ ...server.workspace,
119
+ path: requireConfinedPath(server.workspace.path, configuration, `LSP workspace for ${server.id}`),
120
+ };
121
+ }
122
+ if (server.workspace.type === "markers" && server.workspace.stopAt) {
123
+ return {
124
+ ...server.workspace,
125
+ stopAt: requireConfinedPath(server.workspace.stopAt, configuration, `LSP marker boundary for ${server.id}`),
126
+ };
127
+ }
128
+ return server.workspace;
129
+ }
130
+ function canonicalizeDaemonPolicy(configuration, resolved) {
131
+ const servers = resolved.servers.map((server) => canonicalizeDaemonLspServer(server, configuration, canonicalizeDaemonLspTransport(server, configuration), canonicalizeDaemonLspWorkspace(server, configuration)));
132
+ return { enabled: resolved.enabled, servers };
133
+ }
134
+ export function loadDaemonLspConfiguration(configuration) {
135
+ const layers = [];
136
+ if (configuration.trustProjectLsp) {
137
+ const projectSettingsPath = resolve(configuration.workspaceRoot, ".grip", "settings.json");
138
+ const settings = readJson(projectSettingsPath, true);
139
+ if (settings !== undefined) {
140
+ if (typeof settings !== "object" || settings === null || Array.isArray(settings)) {
141
+ throw new DaemonConfigurationError(`Invalid project settings for daemon LSP: ${projectSettingsPath}`);
142
+ }
143
+ const lsp = settings.lsp;
144
+ if (lsp !== undefined)
145
+ layers.push(parseLayer(lsp, projectSettingsPath, resolve(configuration.workspaceRoot, ".grip")));
146
+ }
147
+ }
148
+ if (configuration.lspConfigPath) {
149
+ const value = readJson(configuration.lspConfigPath);
150
+ layers.push(parseLayer(value, configuration.lspConfigPath, resolve(configuration.lspConfigPath, "..")));
151
+ }
152
+ const resolved = layers.length === 0 ? DISABLED_LSP_CONFIGURATION : resolveLspConfiguration(layers);
153
+ return canonicalizeDaemonPolicy(configuration, resolved);
154
+ }
155
+ //# sourceMappingURL=lsp-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lsp-config.js","sourceRoot":"","sources":["../../src/daemon/lsp-config.ts"],"names":[],"mappings":"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","sourcesContent":["import { lstatSync, readFileSync, realpathSync } from \"node:fs\";\nimport { dirname, isAbsolute, relative, resolve } from \"node:path\";\nimport {\n\ttype LspConfigurationLayer,\n\ttype LspConfiguredServer,\n\ttype LspTransport,\n\ttype LspWorkspaceRoot,\n\tparseLspConfiguration,\n\ttype ResolvedLspConfiguration,\n\tresolveLspConfiguration,\n} from \"../core/lsp/config.ts\";\nimport { resolveLspConfigurationLayerPaths } from \"../core/lsp/config-loader.ts\";\nimport { relativeWithin } from \"../core/lsp/portable-path.ts\";\nimport { type DaemonConfiguration, DaemonConfigurationError } from \"./config.ts\";\n\nconst DISABLED_LSP_CONFIGURATION: ResolvedLspConfiguration = { enabled: false, servers: [] };\n\nfunction readJson(path: string, optional = false): unknown | undefined {\n\ttry {\n\t\treturn JSON.parse(readFileSync(path, \"utf8\")) as unknown;\n\t} catch (error) {\n\t\tif (optional && error instanceof Error && \"code\" in error && error.code === \"ENOENT\") return undefined;\n\t\tthrow new DaemonConfigurationError(\n\t\t\t`Unable to load daemon LSP configuration ${path}: ${error instanceof Error ? error.message : String(error)}`,\n\t\t);\n\t}\n}\n\nfunction parseLayer(value: unknown, source: string, baseDir: string): LspConfigurationLayer {\n\tconst parsed = parseLspConfiguration(value);\n\tif (!parsed.configuration) {\n\t\tthrow new DaemonConfigurationError(\n\t\t\t`Invalid daemon LSP configuration ${source}: ${parsed.diagnostics.map((item) => `${item.path}: ${item.message}`).join(\"; \")}`,\n\t\t);\n\t}\n\tconst resolved = parseLspConfiguration(resolveLspConfigurationLayerPaths(parsed.configuration, baseDir));\n\tif (!resolved.configuration) {\n\t\tthrow new DaemonConfigurationError(\n\t\t\t`Invalid resolved daemon LSP configuration ${source}: ${resolved.diagnostics.map((item) => `${item.path}: ${item.message}`).join(\"; \")}`,\n\t\t);\n\t}\n\treturn resolved.configuration;\n}\n\nfunction isMissingPathError(error: unknown): boolean {\n\treturn error instanceof Error && \"code\" in error && error.code === \"ENOENT\";\n}\n\nfunction validateExistingLspPath(path: string, requestedPath: string, label: string): boolean {\n\tlet isSymbolicLink: boolean;\n\ttry {\n\t\tisSymbolicLink = lstatSync(path).isSymbolicLink();\n\t} catch (error) {\n\t\tif (isMissingPathError(error)) return false;\n\t\tthrow error;\n\t}\n\tif (!isSymbolicLink) return true;\n\ttry {\n\t\trealpathSync(path);\n\t} catch {\n\t\tthrow new DaemonConfigurationError(`${label} uses a broken symbolic link: ${requestedPath}`);\n\t}\n\treturn true;\n}\n\nfunction findExistingLspPathAncestor(path: string, label: string): string {\n\tlet existing = path;\n\twhile (!validateExistingLspPath(existing, path, label)) {\n\t\tconst parent = dirname(existing);\n\t\tif (parent === existing) break;\n\t\texisting = parent;\n\t}\n\treturn existing;\n}\n\nfunction requireConfinedPath(path: string, configuration: DaemonConfiguration, label: string): string {\n\tconst existing = findExistingLspPathAncestor(path, label);\n\tconst canonicalExisting = realpathSync(existing);\n\tif (relativeWithin(configuration.workspaceRoot, canonicalExisting) === undefined) {\n\t\tthrow new DaemonConfigurationError(`${label} escapes the daemon workspace: ${path}`);\n\t}\n\tif (existing === path) return canonicalExisting;\n\treturn resolve(canonicalExisting, relative(existing, path));\n}\n\nfunction canonicalizeDaemonLspServer(\n\tserver: LspConfiguredServer,\n\tconfiguration: DaemonConfiguration,\n\ttransport: LspTransport,\n\tworkspace: LspWorkspaceRoot,\n): LspConfiguredServer {\n\treturn {\n\t\t...server,\n\t\ttransport,\n\t\tworkspace,\n\t\t...(server.pathMappings\n\t\t\t? {\n\t\t\t\t\tpathMappings: server.pathMappings.map((mapping) => ({\n\t\t\t\t\t\t...mapping,\n\t\t\t\t\t\tagentRoot: requireConfinedPath(mapping.agentRoot, configuration, `LSP path mapping for ${server.id}`),\n\t\t\t\t\t})),\n\t\t\t\t}\n\t\t\t: {}),\n\t};\n}\nfunction canonicalizeDaemonLspTransport(server: LspConfiguredServer, configuration: DaemonConfiguration): LspTransport {\n\tif (server.transport.type === \"connection\") {\n\t\tthrow new DaemonConfigurationError(\n\t\t\t`Daemon LSP server ${JSON.stringify(server.id)} cannot use a host-provided connection transport`,\n\t\t);\n\t}\n\tif (server.transport.type === \"spawn\") {\n\t\tif (!configuration.allowProcessExec) {\n\t\t\tthrow new DaemonConfigurationError(\n\t\t\t\t`Daemon LSP server ${JSON.stringify(server.id)} requires --daemon-allow-process-exec`,\n\t\t\t);\n\t\t}\n\t\treturn {\n\t\t\t...server.transport,\n\t\t\t...(server.transport.cwd\n\t\t\t\t? { cwd: requireConfinedPath(server.transport.cwd, configuration, `LSP cwd for ${server.id}`) }\n\t\t\t\t: {}),\n\t\t\t...(isAbsolute(server.transport.command)\n\t\t\t\t? {\n\t\t\t\t\t\tcommand: requireConfinedPath(server.transport.command, configuration, `LSP command for ${server.id}`),\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t};\n\t}\n\tif (server.transport.type === \"unix\") {\n\t\treturn {\n\t\t\t...server.transport,\n\t\t\tpath: requireConfinedPath(server.transport.path, configuration, `LSP socket for ${server.id}`),\n\t\t};\n\t}\n\treturn server.transport;\n}\n\nfunction canonicalizeDaemonLspWorkspace(\n\tserver: LspConfiguredServer,\n\tconfiguration: DaemonConfiguration,\n): LspWorkspaceRoot {\n\tif (server.workspace.type === \"fixed\") {\n\t\treturn {\n\t\t\t...server.workspace,\n\t\t\tpath: requireConfinedPath(server.workspace.path, configuration, `LSP workspace for ${server.id}`),\n\t\t};\n\t}\n\tif (server.workspace.type === \"markers\" && server.workspace.stopAt) {\n\t\treturn {\n\t\t\t...server.workspace,\n\t\t\tstopAt: requireConfinedPath(server.workspace.stopAt, configuration, `LSP marker boundary for ${server.id}`),\n\t\t};\n\t}\n\treturn server.workspace;\n}\n\nfunction canonicalizeDaemonPolicy(\n\tconfiguration: DaemonConfiguration,\n\tresolved: ResolvedLspConfiguration,\n): ResolvedLspConfiguration {\n\tconst servers = resolved.servers.map((server) =>\n\t\tcanonicalizeDaemonLspServer(\n\t\t\tserver,\n\t\t\tconfiguration,\n\t\t\tcanonicalizeDaemonLspTransport(server, configuration),\n\t\t\tcanonicalizeDaemonLspWorkspace(server, configuration),\n\t\t),\n\t);\n\treturn { enabled: resolved.enabled, servers };\n}\n\nexport function loadDaemonLspConfiguration(configuration: DaemonConfiguration): ResolvedLspConfiguration {\n\tconst layers: LspConfigurationLayer[] = [];\n\tif (configuration.trustProjectLsp) {\n\t\tconst projectSettingsPath = resolve(configuration.workspaceRoot, \".grip\", \"settings.json\");\n\t\tconst settings = readJson(projectSettingsPath, true);\n\t\tif (settings !== undefined) {\n\t\t\tif (typeof settings !== \"object\" || settings === null || Array.isArray(settings)) {\n\t\t\t\tthrow new DaemonConfigurationError(`Invalid project settings for daemon LSP: ${projectSettingsPath}`);\n\t\t\t}\n\t\t\tconst lsp = (settings as { lsp?: unknown }).lsp;\n\t\t\tif (lsp !== undefined)\n\t\t\t\tlayers.push(parseLayer(lsp, projectSettingsPath, resolve(configuration.workspaceRoot, \".grip\")));\n\t\t}\n\t}\n\tif (configuration.lspConfigPath) {\n\t\tconst value = readJson(configuration.lspConfigPath);\n\t\tlayers.push(parseLayer(value, configuration.lspConfigPath, resolve(configuration.lspConfigPath, \"..\")));\n\t}\n\tconst resolved = layers.length === 0 ? DISABLED_LSP_CONFIGURATION : resolveLspConfiguration(layers);\n\treturn canonicalizeDaemonPolicy(configuration, resolved);\n}\n"]}
@@ -0,0 +1,10 @@
1
+ /** Aggregate outstanding sends on one physical WebSocket (v1 or v2). */
2
+ export declare class DaemonOutboundBudget {
3
+ private pendingBytes;
4
+ private pendingMessages;
5
+ private readonly maxBytes;
6
+ private readonly maxMessages;
7
+ constructor(maxBytes: number, maxMessages: number);
8
+ reserve(bytes: number, bufferedAmount: number): () => void;
9
+ }
10
+ //# sourceMappingURL=outbound-budget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbound-budget.d.ts","sourceRoot":"","sources":["../../src/daemon/outbound-budget.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,qBAAa,oBAAoB;IAChC,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IAErC,YAAY,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAGhD;IAED,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,IAAI,CAkBzD;CACD","sourcesContent":["/** Aggregate outstanding sends on one physical WebSocket (v1 or v2). */\nexport class DaemonOutboundBudget {\n\tprivate pendingBytes = 0;\n\tprivate pendingMessages = 0;\n\tprivate readonly maxBytes: number;\n\tprivate readonly maxMessages: number;\n\n\tconstructor(maxBytes: number, maxMessages: number) {\n\t\tthis.maxBytes = maxBytes;\n\t\tthis.maxMessages = maxMessages;\n\t}\n\n\treserve(bytes: number, bufferedAmount: number): () => void {\n\t\t// ws.bufferedAmount measures socket-queued data; a callback can also stall after\n\t\t// the socket accepts data. Bound both views without double-counting overlap.\n\t\tif (\n\t\t\tthis.pendingMessages >= this.maxMessages ||\n\t\t\tMath.max(this.pendingBytes, bufferedAmount) + bytes > this.maxBytes\n\t\t) {\n\t\t\tthrow new Error(\"WebSocket outbound buffer exceeds daemon limits\");\n\t\t}\n\t\tthis.pendingMessages++;\n\t\tthis.pendingBytes += bytes;\n\t\tlet released = false;\n\t\treturn () => {\n\t\t\tif (released) return;\n\t\t\treleased = true;\n\t\t\tthis.pendingMessages--;\n\t\t\tthis.pendingBytes -= bytes;\n\t\t};\n\t}\n}\n"]}
@@ -0,0 +1,30 @@
1
+ /** Aggregate outstanding sends on one physical WebSocket (v1 or v2). */
2
+ export class DaemonOutboundBudget {
3
+ pendingBytes = 0;
4
+ pendingMessages = 0;
5
+ maxBytes;
6
+ maxMessages;
7
+ constructor(maxBytes, maxMessages) {
8
+ this.maxBytes = maxBytes;
9
+ this.maxMessages = maxMessages;
10
+ }
11
+ reserve(bytes, bufferedAmount) {
12
+ // ws.bufferedAmount measures socket-queued data; a callback can also stall after
13
+ // the socket accepts data. Bound both views without double-counting overlap.
14
+ if (this.pendingMessages >= this.maxMessages ||
15
+ Math.max(this.pendingBytes, bufferedAmount) + bytes > this.maxBytes) {
16
+ throw new Error("WebSocket outbound buffer exceeds daemon limits");
17
+ }
18
+ this.pendingMessages++;
19
+ this.pendingBytes += bytes;
20
+ let released = false;
21
+ return () => {
22
+ if (released)
23
+ return;
24
+ released = true;
25
+ this.pendingMessages--;
26
+ this.pendingBytes -= bytes;
27
+ };
28
+ }
29
+ }
30
+ //# sourceMappingURL=outbound-budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbound-budget.js","sourceRoot":"","sources":["../../src/daemon/outbound-budget.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,MAAM,OAAO,oBAAoB;IACxB,YAAY,GAAG,CAAC,CAAC;IACjB,eAAe,GAAG,CAAC,CAAC;IACX,QAAQ,CAAS;IACjB,WAAW,CAAS;IAErC,YAAY,QAAgB,EAAE,WAAmB,EAAE;QAClD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IAAA,CAC/B;IAED,OAAO,CAAC,KAAa,EAAE,cAAsB,EAAc;QAC1D,iFAAiF;QACjF,6EAA6E;QAC7E,IACC,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,WAAW;YACxC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,cAAc,CAAC,GAAG,KAAK,GAAG,IAAI,CAAC,QAAQ,EAClE,CAAC;YACF,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACpE,CAAC;QACD,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,IAAI,CAAC,YAAY,IAAI,KAAK,CAAC;QAC3B,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,OAAO,GAAG,EAAE,CAAC;YACZ,IAAI,QAAQ;gBAAE,OAAO;YACrB,QAAQ,GAAG,IAAI,CAAC;YAChB,IAAI,CAAC,eAAe,EAAE,CAAC;YACvB,IAAI,CAAC,YAAY,IAAI,KAAK,CAAC;QAAA,CAC3B,CAAC;IAAA,CACF;CACD","sourcesContent":["/** Aggregate outstanding sends on one physical WebSocket (v1 or v2). */\nexport class DaemonOutboundBudget {\n\tprivate pendingBytes = 0;\n\tprivate pendingMessages = 0;\n\tprivate readonly maxBytes: number;\n\tprivate readonly maxMessages: number;\n\n\tconstructor(maxBytes: number, maxMessages: number) {\n\t\tthis.maxBytes = maxBytes;\n\t\tthis.maxMessages = maxMessages;\n\t}\n\n\treserve(bytes: number, bufferedAmount: number): () => void {\n\t\t// ws.bufferedAmount measures socket-queued data; a callback can also stall after\n\t\t// the socket accepts data. Bound both views without double-counting overlap.\n\t\tif (\n\t\t\tthis.pendingMessages >= this.maxMessages ||\n\t\t\tMath.max(this.pendingBytes, bufferedAmount) + bytes > this.maxBytes\n\t\t) {\n\t\t\tthrow new Error(\"WebSocket outbound buffer exceeds daemon limits\");\n\t\t}\n\t\tthis.pendingMessages++;\n\t\tthis.pendingBytes += bytes;\n\t\tlet released = false;\n\t\treturn () => {\n\t\t\tif (released) return;\n\t\t\treleased = true;\n\t\t\tthis.pendingMessages--;\n\t\t\tthis.pendingBytes -= bytes;\n\t\t};\n\t}\n}\n"]}
@@ -0,0 +1,19 @@
1
+ import type { IncomingMessage } from "node:http";
2
+ import type { Duplex } from "node:stream";
3
+ import { type DaemonConfiguration } from "./config.ts";
4
+ export interface DaemonAuthorization {
5
+ readonly configuredBytes: number;
6
+ readonly digest: Buffer;
7
+ }
8
+ export interface DaemonUpgradeDecision {
9
+ readonly accepted: boolean;
10
+ readonly status: number;
11
+ readonly message: string;
12
+ }
13
+ export declare function isLoopbackBind(host: string): boolean;
14
+ export declare function validateDaemonNetworkPolicy(configuration: DaemonConfiguration): void;
15
+ export declare function createDaemonAuthorization(token: string | undefined): DaemonAuthorization | undefined;
16
+ export declare function validateDaemonUpgrade(request: IncomingMessage, configuration: DaemonConfiguration, authorization: DaemonAuthorization | undefined): DaemonUpgradeDecision;
17
+ export declare function rejectDaemonUpgrade(socket: Duplex, decision: DaemonUpgradeDecision): void;
18
+ export declare function redactDaemonText(value: string, secrets: readonly (string | undefined)[]): string;
19
+ //# sourceMappingURL=security.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../src/daemon/security.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAGN,KAAK,mBAAmB,EAExB,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AA2BD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMpD;AA6ED,wBAAgB,2BAA2B,CAAC,aAAa,EAAE,mBAAmB,GAAG,IAAI,CAMpF;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,mBAAmB,GAAG,SAAS,CAIpG;AAaD,wBAAgB,qBAAqB,CACpC,OAAO,EAAE,eAAe,EACxB,aAAa,EAAE,mBAAmB,EAClC,aAAa,EAAE,mBAAmB,GAAG,SAAS,GAC5C,qBAAqB,CA+BvB;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,qBAAqB,GAAG,IAAI,CAazF;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,GAAG,MAAM,CAOhG","sourcesContent":["import { createHash, timingSafeEqual } from \"node:crypto\";\nimport type { IncomingMessage } from \"node:http\";\nimport { isIP } from \"node:net\";\nimport type { Duplex } from \"node:stream\";\nimport { SHARED_WORKSPACE_WEBSOCKET_PROTOCOL } from \"../core/remote-workspace-protocol/shared-transport.ts\";\nimport {\n\tDAEMON_WEBSOCKET_PATH,\n\tDAEMON_WEBSOCKET_PROTOCOL,\n\ttype DaemonConfiguration,\n\tDaemonConfigurationError,\n} from \"./config.ts\";\n\nexport interface DaemonAuthorization {\n\treadonly configuredBytes: number;\n\treadonly digest: Buffer;\n}\n\nexport interface DaemonUpgradeDecision {\n\treadonly accepted: boolean;\n\treadonly status: number;\n\treadonly message: string;\n}\n\nfunction headerValues(request: IncomingMessage, name: string): string[] {\n\tconst values: string[] = [];\n\tfor (let index = 0; index < request.rawHeaders.length; index += 2) {\n\t\tif (request.rawHeaders[index]?.toLowerCase() === name) values.push(request.rawHeaders[index + 1] ?? \"\");\n\t}\n\treturn values;\n}\n\nfunction singleHeader(request: IncomingMessage, name: string): string | undefined {\n\tconst values = headerValues(request, name);\n\treturn values.length === 1 ? values[0] : undefined;\n}\n\nfunction hasToken(value: string, token: string): boolean {\n\treturn value\n\t\t.split(\",\")\n\t\t.map((entry) => entry.trim().toLowerCase())\n\t\t.includes(token);\n}\n\nfunction isValidWebSocketKey(value: string): boolean {\n\tif (!/^[A-Za-z0-9+/]{22}==$/.test(value)) return false;\n\treturn Buffer.from(value, \"base64\").byteLength === 16;\n}\n\nexport function isLoopbackBind(host: string): boolean {\n\tconst normalized = host.startsWith(\"[\") && host.endsWith(\"]\") ? host.slice(1, -1) : host;\n\tif (isIP(normalized) === 4) return normalized.split(\".\")[0] === \"127\";\n\tif (isIP(normalized) !== 6) return false;\n\tconst lower = normalized.toLowerCase();\n\treturn lower === \"::1\" || /^::ffff:127(?:\\.[0-9]{1,3}){3}$/.test(lower);\n}\nfunction validateDaemonRuntimeLimits(configuration: DaemonConfiguration): void {\n\tif (!Number.isSafeInteger(configuration.port) || configuration.port < 0 || configuration.port > 65535) {\n\t\tthrow new DaemonConfigurationError(\"Daemon server port must be an integer from 0 to 65535\");\n\t}\n\tif (!Number.isSafeInteger(configuration.maxConnections) || configuration.maxConnections < 1) {\n\t\tthrow new DaemonConfigurationError(\"Daemon maxConnections must be a positive integer\");\n\t}\n\tif (!Number.isSafeInteger(configuration.maxPendingConnections) || configuration.maxPendingConnections < 1) {\n\t\tthrow new DaemonConfigurationError(\"Daemon maxPendingConnections must be a positive integer\");\n\t}\n\tif (\n\t\t!Number.isSafeInteger(configuration.handshakeTimeoutMs) ||\n\t\tconfiguration.handshakeTimeoutMs < 100 ||\n\t\tconfiguration.handshakeTimeoutMs > 5 * 60_000\n\t) {\n\t\tthrow new DaemonConfigurationError(\"Daemon handshakeTimeoutMs must be an integer from 100 to 300000\");\n\t}\n\tif (\n\t\t!Number.isSafeInteger(configuration.shutdownTimeoutMs) ||\n\t\tconfiguration.shutdownTimeoutMs < 100 ||\n\t\tconfiguration.shutdownTimeoutMs > 5 * 60_000\n\t) {\n\t\tthrow new DaemonConfigurationError(\"Daemon shutdownTimeoutMs must be an integer from 100 to 300000\");\n\t}\n}\n\nfunction validateDaemonCredentials(configuration: DaemonConfiguration): void {\n\tif (process.platform !== \"win32\" && process.getuid?.() === 0 && !configuration.allowRoot) {\n\t\tthrow new DaemonConfigurationError(\"Refusing to run the workspace daemon as root without allowRoot\");\n\t}\n\tif (configuration.token === undefined) return;\n\tconst tokenBytes = Buffer.byteLength(configuration.token, \"utf8\");\n\tif (\n\t\ttokenBytes < 32 ||\n\t\ttokenBytes > 1024 ||\n\t\t!/\\S/u.test(configuration.token) ||\n\t\t/[\\r\\n]/u.test(configuration.token)\n\t) {\n\t\tthrow new DaemonConfigurationError(\"Daemon token must contain 32 to 1024 UTF-8 bytes and no line breaks\");\n\t}\n}\n\nfunction validateDaemonOrigins(origins: readonly string[]): void {\n\tfor (const origin of origins) {\n\t\tlet parsed: URL;\n\t\ttry {\n\t\t\tparsed = new URL(origin);\n\t\t} catch {\n\t\t\tthrow new DaemonConfigurationError(`Invalid daemon Origin: ${origin}`);\n\t\t}\n\t\tif ((parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") || origin !== parsed.origin) {\n\t\t\tthrow new DaemonConfigurationError(`Invalid daemon Origin: ${origin}`);\n\t\t}\n\t}\n}\n\nfunction validateDaemonTls(configuration: DaemonConfiguration): void {\n\tif (configuration.tls && (configuration.tls.cert.byteLength === 0 || configuration.tls.key.byteLength === 0)) {\n\t\tthrow new DaemonConfigurationError(\"Daemon TLS certificate and private key must not be empty\");\n\t}\n}\n\nfunction validateDaemonBindExposure(configuration: DaemonConfiguration): void {\n\tif (isIP(configuration.host.replace(/^\\[|\\]$/g, \"\")) === 0) {\n\t\tthrow new DaemonConfigurationError(\"Daemon host must be a literal IPv4 or IPv6 address\");\n\t}\n\tif (isLoopbackBind(configuration.host)) return;\n\tif (!configuration.token)\n\t\tthrow new DaemonConfigurationError(\"A non-loopback daemon bind requires GRIP_DAEMON_TOKEN\");\n\tif (!configuration.tls && !configuration.allowInsecureTransport) {\n\t\tthrow new DaemonConfigurationError(\n\t\t\t\"A non-loopback daemon bind requires TLS or explicit --daemon-allow-insecure-transport acknowledgement\",\n\t\t);\n\t}\n}\n\nexport function validateDaemonNetworkPolicy(configuration: DaemonConfiguration): void {\n\tvalidateDaemonRuntimeLimits(configuration);\n\tvalidateDaemonCredentials(configuration);\n\tvalidateDaemonOrigins(configuration.allowedOrigins);\n\tvalidateDaemonTls(configuration);\n\tvalidateDaemonBindExposure(configuration);\n}\n\nexport function createDaemonAuthorization(token: string | undefined): DaemonAuthorization | undefined {\n\tif (token === undefined) return undefined;\n\tconst bytes = Buffer.from(token, \"utf8\");\n\treturn Object.freeze({ configuredBytes: bytes.byteLength, digest: createHash(\"sha256\").update(bytes).digest() });\n}\n\nfunction authenticateAuthorizationHeader(\n\tvalue: string | undefined,\n\tauthorization: DaemonAuthorization | undefined,\n): boolean {\n\tif (!authorization) return value === undefined;\n\tif (!value?.startsWith(\"Bearer \")) return false;\n\tconst presented = Buffer.from(value.slice(\"Bearer \".length), \"utf8\");\n\tconst digest = createHash(\"sha256\").update(presented).digest();\n\treturn presented.byteLength === authorization.configuredBytes && timingSafeEqual(digest, authorization.digest);\n}\n\nexport function validateDaemonUpgrade(\n\trequest: IncomingMessage,\n\tconfiguration: DaemonConfiguration,\n\tauthorization: DaemonAuthorization | undefined,\n): DaemonUpgradeDecision {\n\tif (request.method !== \"GET\" || request.url !== DAEMON_WEBSOCKET_PATH) {\n\t\treturn { accepted: false, status: 404, message: \"Not found\" };\n\t}\n\tconst upgrade = singleHeader(request, \"upgrade\");\n\tconst connection = singleHeader(request, \"connection\");\n\tconst version = singleHeader(request, \"sec-websocket-version\");\n\tconst key = singleHeader(request, \"sec-websocket-key\");\n\tconst protocol = singleHeader(request, \"sec-websocket-protocol\");\n\tif (\n\t\tupgrade?.toLowerCase() !== \"websocket\" ||\n\t\t!connection ||\n\t\t!hasToken(connection, \"upgrade\") ||\n\t\tversion !== \"13\" ||\n\t\t!key ||\n\t\t!isValidWebSocketKey(key) ||\n\t\t(protocol !== DAEMON_WEBSOCKET_PROTOCOL &&\n\t\t\t(protocol !== SHARED_WORKSPACE_WEBSOCKET_PROTOCOL || !configuration.sharedParentRoot))\n\t) {\n\t\treturn { accepted: false, status: 400, message: \"Invalid WebSocket upgrade\" };\n\t}\n\tconst originValues = headerValues(request, \"origin\");\n\tif (originValues.length > 1) return { accepted: false, status: 403, message: \"Origin not allowed\" };\n\tif (originValues.length === 1 && !configuration.allowedOrigins.includes(originValues[0])) {\n\t\treturn { accepted: false, status: 403, message: \"Origin not allowed\" };\n\t}\n\tconst authorizationValues = headerValues(request, \"authorization\");\n\tif (authorizationValues.length > 1 || !authenticateAuthorizationHeader(authorizationValues[0], authorization)) {\n\t\treturn { accepted: false, status: 401, message: \"Unauthorized\" };\n\t}\n\treturn { accepted: true, status: 101, message: \"Switching Protocols\" };\n}\n\nexport function rejectDaemonUpgrade(socket: Duplex, decision: DaemonUpgradeDecision): void {\n\tconst statusText =\n\t\tnew Map([\n\t\t\t[400, \"Bad Request\"],\n\t\t\t[401, \"Unauthorized\"],\n\t\t\t[403, \"Forbidden\"],\n\t\t\t[404, \"Not Found\"],\n\t\t\t[503, \"Service Unavailable\"],\n\t\t]).get(decision.status) ?? \"Rejected\";\n\tconst body = `${decision.message}\\n`;\n\tsocket.end(\n\t\t`HTTP/1.1 ${decision.status} ${statusText}\\r\\nConnection: close\\r\\nContent-Type: text/plain\\r\\nContent-Length: ${Buffer.byteLength(body)}\\r\\n\\r\\n${body}`,\n\t);\n}\n\nexport function redactDaemonText(value: string, secrets: readonly (string | undefined)[]): string {\n\tlet result = value\n\t\t.replace(/(authorization\\s*:\\s*bearer\\s+)[^\\s,;]+/giu, \"$1[REDACTED]\")\n\t\t.replace(/([?&](?:token|key|secret|password|credential)=)[^&#\\s]*/giu, \"$1[REDACTED]\")\n\t\t.replace(/(\\/\\/)[^/@\\s]+:[^/@\\s]+@/gu, \"$1[REDACTED]@\");\n\tfor (const secret of secrets) if (secret) result = result.split(secret).join(\"[REDACTED]\");\n\treturn result;\n}\n"]}
@@ -0,0 +1,177 @@
1
+ import { createHash, timingSafeEqual } from "node:crypto";
2
+ import { isIP } from "node:net";
3
+ import { SHARED_WORKSPACE_WEBSOCKET_PROTOCOL } from "../core/remote-workspace-protocol/shared-transport.js";
4
+ import { DAEMON_WEBSOCKET_PATH, DAEMON_WEBSOCKET_PROTOCOL, DaemonConfigurationError, } from "./config.js";
5
+ function headerValues(request, name) {
6
+ const values = [];
7
+ for (let index = 0; index < request.rawHeaders.length; index += 2) {
8
+ if (request.rawHeaders[index]?.toLowerCase() === name)
9
+ values.push(request.rawHeaders[index + 1] ?? "");
10
+ }
11
+ return values;
12
+ }
13
+ function singleHeader(request, name) {
14
+ const values = headerValues(request, name);
15
+ return values.length === 1 ? values[0] : undefined;
16
+ }
17
+ function hasToken(value, token) {
18
+ return value
19
+ .split(",")
20
+ .map((entry) => entry.trim().toLowerCase())
21
+ .includes(token);
22
+ }
23
+ function isValidWebSocketKey(value) {
24
+ if (!/^[A-Za-z0-9+/]{22}==$/.test(value))
25
+ return false;
26
+ return Buffer.from(value, "base64").byteLength === 16;
27
+ }
28
+ export function isLoopbackBind(host) {
29
+ const normalized = host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host;
30
+ if (isIP(normalized) === 4)
31
+ return normalized.split(".")[0] === "127";
32
+ if (isIP(normalized) !== 6)
33
+ return false;
34
+ const lower = normalized.toLowerCase();
35
+ return lower === "::1" || /^::ffff:127(?:\.[0-9]{1,3}){3}$/.test(lower);
36
+ }
37
+ function validateDaemonRuntimeLimits(configuration) {
38
+ if (!Number.isSafeInteger(configuration.port) || configuration.port < 0 || configuration.port > 65535) {
39
+ throw new DaemonConfigurationError("Daemon server port must be an integer from 0 to 65535");
40
+ }
41
+ if (!Number.isSafeInteger(configuration.maxConnections) || configuration.maxConnections < 1) {
42
+ throw new DaemonConfigurationError("Daemon maxConnections must be a positive integer");
43
+ }
44
+ if (!Number.isSafeInteger(configuration.maxPendingConnections) || configuration.maxPendingConnections < 1) {
45
+ throw new DaemonConfigurationError("Daemon maxPendingConnections must be a positive integer");
46
+ }
47
+ if (!Number.isSafeInteger(configuration.handshakeTimeoutMs) ||
48
+ configuration.handshakeTimeoutMs < 100 ||
49
+ configuration.handshakeTimeoutMs > 5 * 60_000) {
50
+ throw new DaemonConfigurationError("Daemon handshakeTimeoutMs must be an integer from 100 to 300000");
51
+ }
52
+ if (!Number.isSafeInteger(configuration.shutdownTimeoutMs) ||
53
+ configuration.shutdownTimeoutMs < 100 ||
54
+ configuration.shutdownTimeoutMs > 5 * 60_000) {
55
+ throw new DaemonConfigurationError("Daemon shutdownTimeoutMs must be an integer from 100 to 300000");
56
+ }
57
+ }
58
+ function validateDaemonCredentials(configuration) {
59
+ if (process.platform !== "win32" && process.getuid?.() === 0 && !configuration.allowRoot) {
60
+ throw new DaemonConfigurationError("Refusing to run the workspace daemon as root without allowRoot");
61
+ }
62
+ if (configuration.token === undefined)
63
+ return;
64
+ const tokenBytes = Buffer.byteLength(configuration.token, "utf8");
65
+ if (tokenBytes < 32 ||
66
+ tokenBytes > 1024 ||
67
+ !/\S/u.test(configuration.token) ||
68
+ /[\r\n]/u.test(configuration.token)) {
69
+ throw new DaemonConfigurationError("Daemon token must contain 32 to 1024 UTF-8 bytes and no line breaks");
70
+ }
71
+ }
72
+ function validateDaemonOrigins(origins) {
73
+ for (const origin of origins) {
74
+ let parsed;
75
+ try {
76
+ parsed = new URL(origin);
77
+ }
78
+ catch {
79
+ throw new DaemonConfigurationError(`Invalid daemon Origin: ${origin}`);
80
+ }
81
+ if ((parsed.protocol !== "http:" && parsed.protocol !== "https:") || origin !== parsed.origin) {
82
+ throw new DaemonConfigurationError(`Invalid daemon Origin: ${origin}`);
83
+ }
84
+ }
85
+ }
86
+ function validateDaemonTls(configuration) {
87
+ if (configuration.tls && (configuration.tls.cert.byteLength === 0 || configuration.tls.key.byteLength === 0)) {
88
+ throw new DaemonConfigurationError("Daemon TLS certificate and private key must not be empty");
89
+ }
90
+ }
91
+ function validateDaemonBindExposure(configuration) {
92
+ if (isIP(configuration.host.replace(/^\[|\]$/g, "")) === 0) {
93
+ throw new DaemonConfigurationError("Daemon host must be a literal IPv4 or IPv6 address");
94
+ }
95
+ if (isLoopbackBind(configuration.host))
96
+ return;
97
+ if (!configuration.token)
98
+ throw new DaemonConfigurationError("A non-loopback daemon bind requires GRIP_DAEMON_TOKEN");
99
+ if (!configuration.tls && !configuration.allowInsecureTransport) {
100
+ throw new DaemonConfigurationError("A non-loopback daemon bind requires TLS or explicit --daemon-allow-insecure-transport acknowledgement");
101
+ }
102
+ }
103
+ export function validateDaemonNetworkPolicy(configuration) {
104
+ validateDaemonRuntimeLimits(configuration);
105
+ validateDaemonCredentials(configuration);
106
+ validateDaemonOrigins(configuration.allowedOrigins);
107
+ validateDaemonTls(configuration);
108
+ validateDaemonBindExposure(configuration);
109
+ }
110
+ export function createDaemonAuthorization(token) {
111
+ if (token === undefined)
112
+ return undefined;
113
+ const bytes = Buffer.from(token, "utf8");
114
+ return Object.freeze({ configuredBytes: bytes.byteLength, digest: createHash("sha256").update(bytes).digest() });
115
+ }
116
+ function authenticateAuthorizationHeader(value, authorization) {
117
+ if (!authorization)
118
+ return value === undefined;
119
+ if (!value?.startsWith("Bearer "))
120
+ return false;
121
+ const presented = Buffer.from(value.slice("Bearer ".length), "utf8");
122
+ const digest = createHash("sha256").update(presented).digest();
123
+ return presented.byteLength === authorization.configuredBytes && timingSafeEqual(digest, authorization.digest);
124
+ }
125
+ export function validateDaemonUpgrade(request, configuration, authorization) {
126
+ if (request.method !== "GET" || request.url !== DAEMON_WEBSOCKET_PATH) {
127
+ return { accepted: false, status: 404, message: "Not found" };
128
+ }
129
+ const upgrade = singleHeader(request, "upgrade");
130
+ const connection = singleHeader(request, "connection");
131
+ const version = singleHeader(request, "sec-websocket-version");
132
+ const key = singleHeader(request, "sec-websocket-key");
133
+ const protocol = singleHeader(request, "sec-websocket-protocol");
134
+ if (upgrade?.toLowerCase() !== "websocket" ||
135
+ !connection ||
136
+ !hasToken(connection, "upgrade") ||
137
+ version !== "13" ||
138
+ !key ||
139
+ !isValidWebSocketKey(key) ||
140
+ (protocol !== DAEMON_WEBSOCKET_PROTOCOL &&
141
+ (protocol !== SHARED_WORKSPACE_WEBSOCKET_PROTOCOL || !configuration.sharedParentRoot))) {
142
+ return { accepted: false, status: 400, message: "Invalid WebSocket upgrade" };
143
+ }
144
+ const originValues = headerValues(request, "origin");
145
+ if (originValues.length > 1)
146
+ return { accepted: false, status: 403, message: "Origin not allowed" };
147
+ if (originValues.length === 1 && !configuration.allowedOrigins.includes(originValues[0])) {
148
+ return { accepted: false, status: 403, message: "Origin not allowed" };
149
+ }
150
+ const authorizationValues = headerValues(request, "authorization");
151
+ if (authorizationValues.length > 1 || !authenticateAuthorizationHeader(authorizationValues[0], authorization)) {
152
+ return { accepted: false, status: 401, message: "Unauthorized" };
153
+ }
154
+ return { accepted: true, status: 101, message: "Switching Protocols" };
155
+ }
156
+ export function rejectDaemonUpgrade(socket, decision) {
157
+ const statusText = new Map([
158
+ [400, "Bad Request"],
159
+ [401, "Unauthorized"],
160
+ [403, "Forbidden"],
161
+ [404, "Not Found"],
162
+ [503, "Service Unavailable"],
163
+ ]).get(decision.status) ?? "Rejected";
164
+ const body = `${decision.message}\n`;
165
+ socket.end(`HTTP/1.1 ${decision.status} ${statusText}\r\nConnection: close\r\nContent-Type: text/plain\r\nContent-Length: ${Buffer.byteLength(body)}\r\n\r\n${body}`);
166
+ }
167
+ export function redactDaemonText(value, secrets) {
168
+ let result = value
169
+ .replace(/(authorization\s*:\s*bearer\s+)[^\s,;]+/giu, "$1[REDACTED]")
170
+ .replace(/([?&](?:token|key|secret|password|credential)=)[^&#\s]*/giu, "$1[REDACTED]")
171
+ .replace(/(\/\/)[^/@\s]+:[^/@\s]+@/gu, "$1[REDACTED]@");
172
+ for (const secret of secrets)
173
+ if (secret)
174
+ result = result.split(secret).join("[REDACTED]");
175
+ return result;
176
+ }
177
+ //# sourceMappingURL=security.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/daemon/security.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, timingSafeEqual } from \"node:crypto\";\nimport type { IncomingMessage } from \"node:http\";\nimport { isIP } from \"node:net\";\nimport type { Duplex } from \"node:stream\";\nimport { SHARED_WORKSPACE_WEBSOCKET_PROTOCOL } from \"../core/remote-workspace-protocol/shared-transport.ts\";\nimport {\n\tDAEMON_WEBSOCKET_PATH,\n\tDAEMON_WEBSOCKET_PROTOCOL,\n\ttype DaemonConfiguration,\n\tDaemonConfigurationError,\n} from \"./config.ts\";\n\nexport interface DaemonAuthorization {\n\treadonly configuredBytes: number;\n\treadonly digest: Buffer;\n}\n\nexport interface DaemonUpgradeDecision {\n\treadonly accepted: boolean;\n\treadonly status: number;\n\treadonly message: string;\n}\n\nfunction headerValues(request: IncomingMessage, name: string): string[] {\n\tconst values: string[] = [];\n\tfor (let index = 0; index < request.rawHeaders.length; index += 2) {\n\t\tif (request.rawHeaders[index]?.toLowerCase() === name) values.push(request.rawHeaders[index + 1] ?? \"\");\n\t}\n\treturn values;\n}\n\nfunction singleHeader(request: IncomingMessage, name: string): string | undefined {\n\tconst values = headerValues(request, name);\n\treturn values.length === 1 ? values[0] : undefined;\n}\n\nfunction hasToken(value: string, token: string): boolean {\n\treturn value\n\t\t.split(\",\")\n\t\t.map((entry) => entry.trim().toLowerCase())\n\t\t.includes(token);\n}\n\nfunction isValidWebSocketKey(value: string): boolean {\n\tif (!/^[A-Za-z0-9+/]{22}==$/.test(value)) return false;\n\treturn Buffer.from(value, \"base64\").byteLength === 16;\n}\n\nexport function isLoopbackBind(host: string): boolean {\n\tconst normalized = host.startsWith(\"[\") && host.endsWith(\"]\") ? host.slice(1, -1) : host;\n\tif (isIP(normalized) === 4) return normalized.split(\".\")[0] === \"127\";\n\tif (isIP(normalized) !== 6) return false;\n\tconst lower = normalized.toLowerCase();\n\treturn lower === \"::1\" || /^::ffff:127(?:\\.[0-9]{1,3}){3}$/.test(lower);\n}\nfunction validateDaemonRuntimeLimits(configuration: DaemonConfiguration): void {\n\tif (!Number.isSafeInteger(configuration.port) || configuration.port < 0 || configuration.port > 65535) {\n\t\tthrow new DaemonConfigurationError(\"Daemon server port must be an integer from 0 to 65535\");\n\t}\n\tif (!Number.isSafeInteger(configuration.maxConnections) || configuration.maxConnections < 1) {\n\t\tthrow new DaemonConfigurationError(\"Daemon maxConnections must be a positive integer\");\n\t}\n\tif (!Number.isSafeInteger(configuration.maxPendingConnections) || configuration.maxPendingConnections < 1) {\n\t\tthrow new DaemonConfigurationError(\"Daemon maxPendingConnections must be a positive integer\");\n\t}\n\tif (\n\t\t!Number.isSafeInteger(configuration.handshakeTimeoutMs) ||\n\t\tconfiguration.handshakeTimeoutMs < 100 ||\n\t\tconfiguration.handshakeTimeoutMs > 5 * 60_000\n\t) {\n\t\tthrow new DaemonConfigurationError(\"Daemon handshakeTimeoutMs must be an integer from 100 to 300000\");\n\t}\n\tif (\n\t\t!Number.isSafeInteger(configuration.shutdownTimeoutMs) ||\n\t\tconfiguration.shutdownTimeoutMs < 100 ||\n\t\tconfiguration.shutdownTimeoutMs > 5 * 60_000\n\t) {\n\t\tthrow new DaemonConfigurationError(\"Daemon shutdownTimeoutMs must be an integer from 100 to 300000\");\n\t}\n}\n\nfunction validateDaemonCredentials(configuration: DaemonConfiguration): void {\n\tif (process.platform !== \"win32\" && process.getuid?.() === 0 && !configuration.allowRoot) {\n\t\tthrow new DaemonConfigurationError(\"Refusing to run the workspace daemon as root without allowRoot\");\n\t}\n\tif (configuration.token === undefined) return;\n\tconst tokenBytes = Buffer.byteLength(configuration.token, \"utf8\");\n\tif (\n\t\ttokenBytes < 32 ||\n\t\ttokenBytes > 1024 ||\n\t\t!/\\S/u.test(configuration.token) ||\n\t\t/[\\r\\n]/u.test(configuration.token)\n\t) {\n\t\tthrow new DaemonConfigurationError(\"Daemon token must contain 32 to 1024 UTF-8 bytes and no line breaks\");\n\t}\n}\n\nfunction validateDaemonOrigins(origins: readonly string[]): void {\n\tfor (const origin of origins) {\n\t\tlet parsed: URL;\n\t\ttry {\n\t\t\tparsed = new URL(origin);\n\t\t} catch {\n\t\t\tthrow new DaemonConfigurationError(`Invalid daemon Origin: ${origin}`);\n\t\t}\n\t\tif ((parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") || origin !== parsed.origin) {\n\t\t\tthrow new DaemonConfigurationError(`Invalid daemon Origin: ${origin}`);\n\t\t}\n\t}\n}\n\nfunction validateDaemonTls(configuration: DaemonConfiguration): void {\n\tif (configuration.tls && (configuration.tls.cert.byteLength === 0 || configuration.tls.key.byteLength === 0)) {\n\t\tthrow new DaemonConfigurationError(\"Daemon TLS certificate and private key must not be empty\");\n\t}\n}\n\nfunction validateDaemonBindExposure(configuration: DaemonConfiguration): void {\n\tif (isIP(configuration.host.replace(/^\\[|\\]$/g, \"\")) === 0) {\n\t\tthrow new DaemonConfigurationError(\"Daemon host must be a literal IPv4 or IPv6 address\");\n\t}\n\tif (isLoopbackBind(configuration.host)) return;\n\tif (!configuration.token)\n\t\tthrow new DaemonConfigurationError(\"A non-loopback daemon bind requires GRIP_DAEMON_TOKEN\");\n\tif (!configuration.tls && !configuration.allowInsecureTransport) {\n\t\tthrow new DaemonConfigurationError(\n\t\t\t\"A non-loopback daemon bind requires TLS or explicit --daemon-allow-insecure-transport acknowledgement\",\n\t\t);\n\t}\n}\n\nexport function validateDaemonNetworkPolicy(configuration: DaemonConfiguration): void {\n\tvalidateDaemonRuntimeLimits(configuration);\n\tvalidateDaemonCredentials(configuration);\n\tvalidateDaemonOrigins(configuration.allowedOrigins);\n\tvalidateDaemonTls(configuration);\n\tvalidateDaemonBindExposure(configuration);\n}\n\nexport function createDaemonAuthorization(token: string | undefined): DaemonAuthorization | undefined {\n\tif (token === undefined) return undefined;\n\tconst bytes = Buffer.from(token, \"utf8\");\n\treturn Object.freeze({ configuredBytes: bytes.byteLength, digest: createHash(\"sha256\").update(bytes).digest() });\n}\n\nfunction authenticateAuthorizationHeader(\n\tvalue: string | undefined,\n\tauthorization: DaemonAuthorization | undefined,\n): boolean {\n\tif (!authorization) return value === undefined;\n\tif (!value?.startsWith(\"Bearer \")) return false;\n\tconst presented = Buffer.from(value.slice(\"Bearer \".length), \"utf8\");\n\tconst digest = createHash(\"sha256\").update(presented).digest();\n\treturn presented.byteLength === authorization.configuredBytes && timingSafeEqual(digest, authorization.digest);\n}\n\nexport function validateDaemonUpgrade(\n\trequest: IncomingMessage,\n\tconfiguration: DaemonConfiguration,\n\tauthorization: DaemonAuthorization | undefined,\n): DaemonUpgradeDecision {\n\tif (request.method !== \"GET\" || request.url !== DAEMON_WEBSOCKET_PATH) {\n\t\treturn { accepted: false, status: 404, message: \"Not found\" };\n\t}\n\tconst upgrade = singleHeader(request, \"upgrade\");\n\tconst connection = singleHeader(request, \"connection\");\n\tconst version = singleHeader(request, \"sec-websocket-version\");\n\tconst key = singleHeader(request, \"sec-websocket-key\");\n\tconst protocol = singleHeader(request, \"sec-websocket-protocol\");\n\tif (\n\t\tupgrade?.toLowerCase() !== \"websocket\" ||\n\t\t!connection ||\n\t\t!hasToken(connection, \"upgrade\") ||\n\t\tversion !== \"13\" ||\n\t\t!key ||\n\t\t!isValidWebSocketKey(key) ||\n\t\t(protocol !== DAEMON_WEBSOCKET_PROTOCOL &&\n\t\t\t(protocol !== SHARED_WORKSPACE_WEBSOCKET_PROTOCOL || !configuration.sharedParentRoot))\n\t) {\n\t\treturn { accepted: false, status: 400, message: \"Invalid WebSocket upgrade\" };\n\t}\n\tconst originValues = headerValues(request, \"origin\");\n\tif (originValues.length > 1) return { accepted: false, status: 403, message: \"Origin not allowed\" };\n\tif (originValues.length === 1 && !configuration.allowedOrigins.includes(originValues[0])) {\n\t\treturn { accepted: false, status: 403, message: \"Origin not allowed\" };\n\t}\n\tconst authorizationValues = headerValues(request, \"authorization\");\n\tif (authorizationValues.length > 1 || !authenticateAuthorizationHeader(authorizationValues[0], authorization)) {\n\t\treturn { accepted: false, status: 401, message: \"Unauthorized\" };\n\t}\n\treturn { accepted: true, status: 101, message: \"Switching Protocols\" };\n}\n\nexport function rejectDaemonUpgrade(socket: Duplex, decision: DaemonUpgradeDecision): void {\n\tconst statusText =\n\t\tnew Map([\n\t\t\t[400, \"Bad Request\"],\n\t\t\t[401, \"Unauthorized\"],\n\t\t\t[403, \"Forbidden\"],\n\t\t\t[404, \"Not Found\"],\n\t\t\t[503, \"Service Unavailable\"],\n\t\t]).get(decision.status) ?? \"Rejected\";\n\tconst body = `${decision.message}\\n`;\n\tsocket.end(\n\t\t`HTTP/1.1 ${decision.status} ${statusText}\\r\\nConnection: close\\r\\nContent-Type: text/plain\\r\\nContent-Length: ${Buffer.byteLength(body)}\\r\\n\\r\\n${body}`,\n\t);\n}\n\nexport function redactDaemonText(value: string, secrets: readonly (string | undefined)[]): string {\n\tlet result = value\n\t\t.replace(/(authorization\\s*:\\s*bearer\\s+)[^\\s,;]+/giu, \"$1[REDACTED]\")\n\t\t.replace(/([?&](?:token|key|secret|password|credential)=)[^&#\\s]*/giu, \"$1[REDACTED]\")\n\t\t.replace(/(\\/\\/)[^/@\\s]+:[^/@\\s]+@/gu, \"$1[REDACTED]@\");\n\tfor (const secret of secrets) if (secret) result = result.split(secret).join(\"[REDACTED]\");\n\treturn result;\n}\n"]}
@@ -0,0 +1,20 @@
1
+ import { type DaemonConfiguration } from "./config.ts";
2
+ export interface DaemonServerAddress {
3
+ readonly host: string;
4
+ readonly port: number;
5
+ readonly secure: boolean;
6
+ readonly url: string;
7
+ readonly workspaceRoot: string;
8
+ readonly workspaceId: string;
9
+ }
10
+ export type DaemonServerState = "created" | "listening" | "closing" | "closed";
11
+ export interface DaemonServer {
12
+ listen(): Promise<DaemonServerAddress>;
13
+ address(): DaemonServerAddress | undefined;
14
+ state(): DaemonServerState;
15
+ reload(): Promise<void>;
16
+ close(): Promise<void>;
17
+ forceClose(): Promise<void>;
18
+ }
19
+ export declare function createDaemonServer(configuration: DaemonConfiguration): DaemonServer;
20
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/daemon/server.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAyB,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAY9E,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE/E,MAAM,WAAW,YAAY;IAC5B,MAAM,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACvC,OAAO,IAAI,mBAAmB,GAAG,SAAS,CAAC;IAC3C,KAAK,IAAI,iBAAiB,CAAC;IAC3B,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AA2FD,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,mBAAmB,GAAG,YAAY,CA4YnF","sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport {\n\tcreateServer as createHttpServer,\n\ttype Server as HttpServer,\n\ttype IncomingMessage,\n\ttype ServerResponse,\n} from \"node:http\";\nimport { createServer as createHttpsServer } from \"node:https\";\nimport type { AddressInfo, Socket } from \"node:net\";\nimport WebSocket, { type RawData, WebSocketServer } from \"ws\";\nimport type { RemoteWorkspaceServerMessage } from \"../core/remote-workspace-protocol/contract.ts\";\nimport {\n\ttype RemoteWorkspaceProtocolCloseCode,\n\ttype RemoteWorkspaceProtocolCloseReason,\n\tRemoteWorkspaceRequestError,\n\ttype RemoteWorkspaceServerHandler,\n\tRemoteWorkspaceServerProtocol,\n} from \"../core/remote-workspace-protocol/session.ts\";\nimport {\n\tSHARED_WORKSPACE_WEBSOCKET_PROTOCOL,\n\ttype SharedWorkspaceServerFrame,\n} from \"../core/remote-workspace-protocol/shared-transport.ts\";\nimport { DaemonActivityBudget } from \"./activity-budget.ts\";\nimport { DAEMON_WEBSOCKET_PATH, type DaemonConfiguration } from \"./config.ts\";\nimport { DaemonOutboundBudget } from \"./outbound-budget.ts\";\nimport {\n\tcreateDaemonAuthorization,\n\trejectDaemonUpgrade,\n\tvalidateDaemonNetworkPolicy,\n\tvalidateDaemonUpgrade,\n} from \"./security.ts\";\nimport { SharedDaemonConnection } from \"./shared-connection.ts\";\nimport { SharedWorkspaceRoots } from \"./shared-roots.ts\";\nimport { createDaemonWorkspaceRuntime } from \"./workspace-runtime.ts\";\n\nexport interface DaemonServerAddress {\n\treadonly host: string;\n\treadonly port: number;\n\treadonly secure: boolean;\n\treadonly url: string;\n\treadonly workspaceRoot: string;\n\treadonly workspaceId: string;\n}\n\nexport type DaemonServerState = \"created\" | \"listening\" | \"closing\" | \"closed\";\n\nexport interface DaemonServer {\n\tlisten(): Promise<DaemonServerAddress>;\n\taddress(): DaemonServerAddress | undefined;\n\tstate(): DaemonServerState;\n\treload(): Promise<void>;\n\tclose(): Promise<void>;\n\tforceClose(): Promise<void>;\n}\n\ninterface DaemonConnection {\n\treadonly websocket: WebSocket;\n\treadonly protocol: RemoteWorkspaceServerProtocol | SharedDaemonConnection;\n\tclosed: Promise<void>;\n}\n\nfunction websocketPayload(data: RawData): Uint8Array {\n\tif (Buffer.isBuffer(data)) return Uint8Array.from(data);\n\tif (Array.isArray(data)) return Uint8Array.from(Buffer.concat(data));\n\treturn Uint8Array.from(new Uint8Array(data));\n}\n\nfunction websocketCloseCode(code: RemoteWorkspaceProtocolCloseCode): number {\n\tswitch (code) {\n\t\tcase \"normal\":\n\t\t\treturn 1000;\n\t\tcase \"protocol_error\":\n\t\t\treturn 1002;\n\t\tcase \"invalid_payload\":\n\t\t\treturn 1007;\n\t\tcase \"policy_violation\":\n\t\t\treturn 1008;\n\t\tcase \"message_too_large\":\n\t\t\treturn 1009;\n\t}\n}\n\nfunction waitForWebSocketClose(websocket: WebSocket): Promise<void> {\n\tif (websocket.readyState === WebSocket.CLOSED) return Promise.resolve();\n\treturn new Promise((resolve) => websocket.once(\"close\", () => resolve()));\n}\n\nfunction waitWithin(promise: Promise<unknown>, timeoutMs: number, forceSignal: AbortSignal): Promise<boolean> {\n\tif (forceSignal.aborted) return Promise.resolve(false);\n\treturn new Promise((resolve) => {\n\t\tlet settled = false;\n\t\tconst finish = (value: boolean) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tclearTimeout(timer);\n\t\t\tforceSignal.removeEventListener(\"abort\", onForce);\n\t\t\tresolve(value);\n\t\t};\n\t\tconst timer = setTimeout(() => finish(false), timeoutMs);\n\t\tconst onForce = () => finish(false);\n\t\tforceSignal.addEventListener(\"abort\", onForce, { once: true });\n\t\tpromise.then(\n\t\t\t() => finish(true),\n\t\t\t() => finish(false),\n\t\t);\n\t});\n}\nfunction terminateDaemonConnections(connections: Iterable<DaemonConnection>): void {\n\tfor (const connection of connections) connection.websocket.terminate();\n}\n\nfunction beginDaemonConnectionDrain(\n\tconnections: readonly DaemonConnection[],\n\thostDisposal: Promise<void>,\n): Promise<void> {\n\treturn Promise.allSettled([...connections.map((connection) => connection.protocol.beginDrain()), hostDisposal]).then(\n\t\t() => undefined,\n\t);\n}\n\nfunction disconnectDaemonConnections(connections: readonly DaemonConnection[]): Promise<void> {\n\treturn Promise.allSettled(connections.map((connection) => connection.protocol.disconnect())).then(() => undefined);\n}\n\nfunction requestDaemonConnectionClose(connections: readonly DaemonConnection[]): void {\n\tfor (const connection of connections) {\n\t\tif (connection.websocket.readyState === WebSocket.OPEN) {\n\t\t\tconnection.websocket.close(1001, \"Daemon shutting down\");\n\t\t}\n\t}\n}\n\nfunction waitForDaemonConnectionsClosed(connections: readonly DaemonConnection[]): Promise<void> {\n\treturn Promise.allSettled(connections.map((connection) => connection.closed)).then(() => undefined);\n}\n\nfunction destroyDaemonSockets(sockets: ReadonlySet<Socket>): void {\n\tfor (const socket of sockets) socket.destroy();\n}\n\nfunction formatHostForUrl(host: string): string {\n\treturn host.includes(\":\") && !host.startsWith(\"[\") ? `[${host}]` : host;\n}\n\nexport function createDaemonServer(configuration: DaemonConfiguration): DaemonServer {\n\tvalidateDaemonNetworkPolicy(configuration);\n\tconst authorization = createDaemonAuthorization(configuration.token);\n\tconst activityBudget = new DaemonActivityBudget(configuration);\n\tconst workspaceId = randomBytes(18).toString(\"base64url\");\n\tconst workspace = Object.freeze({\n\t\tid: workspaceId,\n\t\troot: configuration.workspaceRoot,\n\t\tpathFlavor: process.platform === \"win32\" ? (\"windows\" as const) : (\"posix\" as const),\n\t});\n\tlet runtime = createDaemonWorkspaceRuntime(configuration);\n\tlet runtimeHandler = runtime.createHandler(workspace);\n\tconst handler: RemoteWorkspaceServerHandler = {\n\t\thandleRequest: (request, context) => {\n\t\t\tif (typeof request.params === \"object\" && request.params !== null && \"expectedRevision\" in request.params) {\n\t\t\t\tthrow new RemoteWorkspaceRequestError({\n\t\t\t\t\tcode: \"invalid_request\",\n\t\t\t\t\tmessage: \"Revision preconditions require the v2 shared workspace protocol\",\n\t\t\t\t\texecutionState: \"not_started\",\n\t\t\t\t\tretryable: false,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn activityBudget.run(request.method, () => runtimeHandler.handleRequest(request, context));\n\t\t},\n\t\tvalidateToolArguments: (toolName, value) => runtimeHandler.validateToolArguments(toolName, value),\n\t};\n\tconst requestListener = (_request: IncomingMessage, response: ServerResponse) => {\n\t\tresponse.writeHead(404, { \"content-type\": \"text/plain\" });\n\t\tresponse.end(\"Not found\\n\");\n\t};\n\tconst server: HttpServer = configuration.tls\n\t\t? createHttpsServer(\n\t\t\t\t{\n\t\t\t\t\tcert: configuration.tls.cert,\n\t\t\t\t\tkey: configuration.tls.key,\n\t\t\t\t\tpassphrase: configuration.tls.passphrase,\n\t\t\t\t\tminVersion: \"TLSv1.2\",\n\t\t\t\t},\n\t\t\t\trequestListener,\n\t\t\t)\n\t\t: createHttpServer(requestListener);\n\tconst websocketServer = new WebSocketServer({\n\t\tnoServer: true,\n\t\tclientTracking: false,\n\t\tmaxPayload: configuration.protocolLimits.maxMessageBytes,\n\t\tperMessageDeflate: false,\n\t\tallowSynchronousEvents: false,\n\t\tskipUTF8Validation: false,\n\t});\n\tconst sockets = new Set<Socket>();\n\tconst pendingSockets = new Set<Socket>();\n\tconst pendingSocketTimers = new Map<Socket, NodeJS.Timeout>();\n\tconst pendingSocketDeadlines = new Map<Socket, number>();\n\tconst connections = new Set<DaemonConnection>();\n\tlet sharedRoots: SharedWorkspaceRoots | undefined;\n\tlet catalog = runtime.catalog;\n\tlet reloadQueue: Promise<void> = Promise.resolve();\n\tconst forceController = new AbortController();\n\tlet currentAddress: DaemonServerAddress | undefined;\n\tlet listenPromise: Promise<DaemonServerAddress> | undefined;\n\tlet rejectListen: ((error: Error) => void) | undefined;\n\tlet closePromise: Promise<void> | undefined;\n\tlet serverState: DaemonServerState = \"created\";\n\n\tconst stopListener = (): Promise<void> => {\n\t\tif (!server.listening && !listenPromise) return Promise.resolve();\n\t\treturn new Promise((resolve) => {\n\t\t\tlet settled = false;\n\t\t\tconst cleanup = () => {\n\t\t\t\tserver.off(\"listening\", onListening);\n\t\t\t\tserver.off(\"error\", onError);\n\t\t\t\tserver.off(\"close\", onClose);\n\t\t\t};\n\t\t\tconst finish = () => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tcleanup();\n\t\t\t\tresolve();\n\t\t\t};\n\t\t\tconst closeListener = () => server.close(() => finish());\n\t\t\tconst onListening = () => closeListener();\n\t\t\tconst onError = () => finish();\n\t\t\tconst onClose = () => finish();\n\t\t\tserver.once(\"error\", onError);\n\t\t\tserver.once(\"close\", onClose);\n\t\t\tif (server.listening) closeListener();\n\t\t\telse server.once(\"listening\", onListening);\n\t\t});\n\t};\n\n\tserver.on(\"connection\", (socket: Socket) => {\n\t\tif (serverState !== \"listening\" || pendingSockets.size >= configuration.maxPendingConnections) {\n\t\t\tsocket.destroy();\n\t\t\treturn;\n\t\t}\n\t\tsockets.add(socket);\n\t\tpendingSockets.add(socket);\n\t\tconst pendingTimer = setTimeout(() => socket.destroy(), configuration.handshakeTimeoutMs);\n\t\tpendingTimer.unref?.();\n\t\tpendingSocketTimers.set(socket, pendingTimer);\n\t\tpendingSocketDeadlines.set(socket, performance.now() + configuration.handshakeTimeoutMs);\n\t\tsocket.once(\"close\", () => {\n\t\t\tsockets.delete(socket);\n\t\t\tpendingSockets.delete(socket);\n\t\t\tconst timer = pendingSocketTimers.get(socket);\n\t\t\tif (timer) clearTimeout(timer);\n\t\t\tpendingSocketTimers.delete(socket);\n\t\t\tpendingSocketDeadlines.delete(socket);\n\t\t});\n\t});\n\n\tserver.on(\"upgrade\", (request, socket, head) => {\n\t\tconst netSocket = socket as Socket;\n\t\tconst decision = validateDaemonUpgrade(request, configuration, authorization);\n\t\tif (!decision.accepted) {\n\t\t\trejectDaemonUpgrade(netSocket, decision);\n\t\t\treturn;\n\t\t}\n\t\tif (serverState !== \"listening\" || connections.size >= configuration.maxConnections) {\n\t\t\trejectDaemonUpgrade(netSocket, { accepted: false, status: 503, message: \"Service unavailable\" });\n\t\t\treturn;\n\t\t}\n\t\tconst handshakeDeadline = pendingSocketDeadlines.get(netSocket) ?? performance.now();\n\t\tpendingSockets.delete(netSocket);\n\t\tconst pendingTimer = pendingSocketTimers.get(netSocket);\n\t\tif (pendingTimer) clearTimeout(pendingTimer);\n\t\tpendingSocketTimers.delete(netSocket);\n\t\tpendingSocketDeadlines.delete(netSocket);\n\t\twebsocketServer.handleUpgrade(request, socket, head, (websocket) => {\n\t\t\tif (serverState !== \"listening\") {\n\t\t\t\twebsocket.terminate();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst remainingHandshakeMs = Math.max(0, handshakeDeadline - performance.now());\n\t\t\tconst handshakeTimer = setTimeout(() => {\n\t\t\t\twebsocket.terminate();\n\t\t\t}, remainingHandshakeMs);\n\t\t\thandshakeTimer.unref?.();\n\t\t\tlet protocol: RemoteWorkspaceServerProtocol;\n\t\t\tconst outboundBudget = new DaemonOutboundBudget(\n\t\t\t\tconfiguration.protocolLimits.maxPendingOutboundBytes,\n\t\t\t\tconfiguration.protocolLimits.maxPendingOutboundMessages,\n\t\t\t);\n\t\t\tconst transport = {\n\t\t\t\tsend(message: RemoteWorkspaceServerMessage | SharedWorkspaceServerFrame): Promise<void> {\n\t\t\t\t\tif (websocket.readyState !== WebSocket.OPEN) return Promise.reject(new Error(\"WebSocket is not open\"));\n\t\t\t\t\tconst serialized = JSON.stringify(message);\n\t\t\t\t\tconst bytes = Buffer.byteLength(serialized, \"utf8\");\n\t\t\t\t\tlet release: () => void;\n\t\t\t\t\ttry {\n\t\t\t\t\t\trelease = outboundBudget.reserve(bytes, websocket.bufferedAmount);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t// No channel can safely continue after a physical send is dropped.\n\t\t\t\t\t\twebsocket.terminate();\n\t\t\t\t\t\treturn Promise.reject(error);\n\t\t\t\t\t}\n\t\t\t\t\treturn new Promise<void>((resolve, reject) => {\n\t\t\t\t\t\t// A stalled callback must not pin physical reservations indefinitely. A\n\t\t\t\t\t\t// timed-out send makes the entire uplink uncertain, not just its channel.\n\t\t\t\t\t\tconst deadline = setTimeout(() => {\n\t\t\t\t\t\t\twebsocket.terminate();\n\t\t\t\t\t\t\treject(new Error(\"WebSocket outbound send timed out\"));\n\t\t\t\t\t\t}, configuration.protocolLimits.maxTransportSendMs);\n\t\t\t\t\t\tdeadline.unref?.();\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\twebsocket.send(serialized, { binary: false, compress: false }, (error) => {\n\t\t\t\t\t\t\t\tclearTimeout(deadline);\n\t\t\t\t\t\t\t\tif (error) {\n\t\t\t\t\t\t\t\t\twebsocket.terminate();\n\t\t\t\t\t\t\t\t\treject(error);\n\t\t\t\t\t\t\t\t} else resolve();\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tclearTimeout(deadline);\n\t\t\t\t\t\t\twebsocket.terminate();\n\t\t\t\t\t\t\treject(error);\n\t\t\t\t\t\t}\n\t\t\t\t\t}).finally(release);\n\t\t\t\t},\n\t\t\t\tclose(reason: RemoteWorkspaceProtocolCloseReason): Promise<void> {\n\t\t\t\t\tif (websocket.readyState === WebSocket.CLOSED) return Promise.resolve();\n\t\t\t\t\twebsocket.close(websocketCloseCode(reason.code), reason.message);\n\t\t\t\t\treturn waitForWebSocketClose(websocket);\n\t\t\t\t},\n\t\t\t};\n\t\t\tif (websocket.protocol === SHARED_WORKSPACE_WEBSOCKET_PROTOCOL) {\n\t\t\t\tif (!sharedRoots) {\n\t\t\t\t\twebsocket.close(1008, \"Shared parent unavailable\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst shared = new SharedDaemonConnection(\n\t\t\t\t\tconfiguration,\n\t\t\t\t\tsharedRoots,\n\t\t\t\t\ttransport.send,\n\t\t\t\t\t(code, reason) => {\n\t\t\t\t\t\tif (websocket.readyState === WebSocket.OPEN) websocket.close(code, reason);\n\t\t\t\t\t},\n\t\t\t\t\tactivityBudget,\n\t\t\t\t);\n\t\t\t\tconst connection: DaemonConnection = { websocket, protocol: shared, closed: Promise.resolve() };\n\t\t\t\tconnection.closed = waitForWebSocketClose(websocket).then(async () => {\n\t\t\t\t\tclearTimeout(handshakeTimer);\n\t\t\t\t\tconnections.delete(connection);\n\t\t\t\t\tawait shared.disconnect().catch(() => undefined);\n\t\t\t\t});\n\t\t\t\tconnections.add(connection);\n\t\t\t\twebsocket.on(\"message\", (data, isBinary) => {\n\t\t\t\t\tif (isBinary) {\n\t\t\t\t\t\twebsocket.close(1003, \"Text protocol required\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tvoid shared.receive(websocketPayload(data)).then(() => {\n\t\t\t\t\t\tif (shared.handshakeComplete) clearTimeout(handshakeTimer);\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\twebsocket.on(\"error\", () => undefined);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tprotocol = new RemoteWorkspaceServerProtocol(transport, handler, {\n\t\t\t\tworkspace,\n\t\t\t\tcatalog,\n\t\t\t\tcapabilities: runtime.capabilities,\n\t\t\t\tlimits: configuration.protocolLimits,\n\t\t\t\tbackendLabel: \"grip-workspace-daemon\",\n\t\t\t});\n\t\t\tconst connection: DaemonConnection = {\n\t\t\t\twebsocket,\n\t\t\t\tprotocol,\n\t\t\t\tclosed: Promise.resolve(),\n\t\t\t};\n\t\t\tconnection.closed = waitForWebSocketClose(websocket).then(async () => {\n\t\t\t\tclearTimeout(handshakeTimer);\n\t\t\t\tconnections.delete(connection);\n\t\t\t\tawait protocol.disconnect().catch(() => undefined);\n\t\t\t});\n\t\t\tconnections.add(connection);\n\t\t\twebsocket.on(\"message\", (data, isBinary) => {\n\t\t\t\tif (isBinary) {\n\t\t\t\t\twebsocket.close(1003, \"Text protocol required\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tvoid protocol\n\t\t\t\t\t.receive(websocketPayload(data))\n\t\t\t\t\t.then(() => {\n\t\t\t\t\t\tif (protocol.handshakeComplete) clearTimeout(handshakeTimer);\n\t\t\t\t\t})\n\t\t\t\t\t.catch(() => undefined);\n\t\t\t});\n\t\t\twebsocket.on(\"error\", () => undefined);\n\t\t});\n\t});\n\n\tconst api: DaemonServer = {\n\t\tlisten(): Promise<DaemonServerAddress> {\n\t\t\tif (serverState === \"closing\" || serverState === \"closed\")\n\t\t\t\treturn Promise.reject(new Error(\"Daemon server is closing\"));\n\t\t\tif (currentAddress) return Promise.resolve(currentAddress);\n\t\t\tif (listenPromise) return listenPromise;\n\t\t\tif (configuration.sharedParentRoot && !sharedRoots) {\n\t\t\t\treturn SharedWorkspaceRoots.fromParent(configuration.sharedParentRoot).then((roots) => {\n\t\t\t\t\tsharedRoots = roots;\n\t\t\t\t\treturn api.listen();\n\t\t\t\t});\n\t\t\t}\n\t\t\tlistenPromise = new Promise((resolve, reject) => {\n\t\t\t\trejectListen = reject;\n\t\t\t\tconst onError = (error: Error) => {\n\t\t\t\t\tserver.off(\"listening\", onListening);\n\t\t\t\t\tlistenPromise = undefined;\n\t\t\t\t\trejectListen = undefined;\n\t\t\t\t\treject(error);\n\t\t\t\t};\n\t\t\t\tconst onListening = () => {\n\t\t\t\t\tserver.off(\"error\", onError);\n\t\t\t\t\tif (serverState !== \"created\") {\n\t\t\t\t\t\trejectListen = undefined;\n\t\t\t\t\t\treject(new Error(\"Daemon server closed before listening completed\"));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst address = server.address();\n\t\t\t\t\tif (!address || typeof address === \"string\") {\n\t\t\t\t\t\trejectListen = undefined;\n\t\t\t\t\t\treject(new Error(\"Daemon listener did not return a TCP address\"));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tserverState = \"listening\";\n\t\t\t\t\tconst port = (address as AddressInfo).port;\n\t\t\t\t\tcurrentAddress = Object.freeze({\n\t\t\t\t\t\thost: configuration.host,\n\t\t\t\t\t\tport,\n\t\t\t\t\t\tsecure: configuration.tls !== undefined,\n\t\t\t\t\t\turl: `${configuration.tls ? \"wss\" : \"ws\"}://${formatHostForUrl(configuration.host)}:${port}${DAEMON_WEBSOCKET_PATH}`,\n\t\t\t\t\t\tworkspaceRoot: configuration.workspaceRoot,\n\t\t\t\t\t\tworkspaceId,\n\t\t\t\t\t});\n\t\t\t\t\trejectListen = undefined;\n\t\t\t\t\tresolve(currentAddress);\n\t\t\t\t};\n\t\t\t\tserver.once(\"error\", onError);\n\t\t\t\tserver.once(\"listening\", onListening);\n\t\t\t\tserver.listen(configuration.port, configuration.host);\n\t\t\t});\n\t\t\treturn listenPromise;\n\t\t},\n\t\taddress(): DaemonServerAddress | undefined {\n\t\t\treturn currentAddress ? { ...currentAddress } : undefined;\n\t\t},\n\t\tstate(): DaemonServerState {\n\t\t\treturn serverState;\n\t\t},\n\t\treload(): Promise<void> {\n\t\t\tif (serverState !== \"listening\") return Promise.reject(new Error(\"Daemon server is not listening\"));\n\t\t\treloadQueue = reloadQueue\n\t\t\t\t.catch(() => undefined)\n\t\t\t\t.then(async () => {\n\t\t\t\t\tif (serverState !== \"listening\") throw new Error(\"Daemon server is not listening\");\n\t\t\t\t\tconst candidate = createDaemonWorkspaceRuntime(configuration);\n\t\t\t\t\tconst candidateCatalog = { ...candidate.catalog, generation: catalog.generation + 1 };\n\t\t\t\t\tconst previous = runtime;\n\t\t\t\t\truntime = candidate;\n\t\t\t\t\truntimeHandler = candidate.createHandler(workspace);\n\t\t\t\t\tcatalog = candidateCatalog;\n\t\t\t\t\tconst snapshot = [...connections];\n\t\t\t\t\tconst outcomes = await Promise.allSettled(\n\t\t\t\t\t\tsnapshot.map(async (connection) => {\n\t\t\t\t\t\t\tif (connection.protocol instanceof SharedDaemonConnection) await connection.protocol.reload();\n\t\t\t\t\t\t\telse await connection.protocol.publishCatalog(catalog);\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\tconst failed = snapshot.filter((_connection, index) => outcomes[index]?.status === \"rejected\");\n\t\t\t\t\t// A failed publication may have been sent already. Do not roll back successful peers\n\t\t\t\t\t// to an older generation: close only transports whose catalog is uncertain.\n\t\t\t\t\tfor (const connection of failed) connection.websocket.terminate();\n\t\t\t\t\tawait previous.retire();\n\t\t\t\t\tif (failed.length > 0)\n\t\t\t\t\t\tthrow new Error(`Daemon catalog reload failed for ${failed.length} connection(s)`);\n\t\t\t\t});\n\t\t\treturn reloadQueue;\n\t\t},\n\t\tclose(): Promise<void> {\n\t\t\tif (closePromise) return closePromise;\n\t\t\tserverState = \"closing\";\n\t\t\trejectListen?.(new Error(\"Daemon server closed before listening completed\"));\n\t\t\trejectListen = undefined;\n\t\t\tconst deadline = performance.now() + configuration.shutdownTimeoutMs;\n\t\t\tconst remainingMs = () => Math.max(0, deadline - performance.now());\n\t\t\tclosePromise = (async () => {\n\t\t\t\tconst listenerClose = stopListener();\n\t\t\t\tconst snapshot = [...connections];\n\t\t\t\tawait waitWithin(\n\t\t\t\t\treloadQueue.catch(() => undefined),\n\t\t\t\t\tremainingMs(),\n\t\t\t\t\tforceController.signal,\n\t\t\t\t);\n\t\t\t\tconst hostDisposal = runtime.dispose();\n\t\t\t\tconst drained = await waitWithin(\n\t\t\t\t\tbeginDaemonConnectionDrain(snapshot, hostDisposal),\n\t\t\t\t\tremainingMs(),\n\t\t\t\t\tforceController.signal,\n\t\t\t\t);\n\t\t\t\tif (!drained) terminateDaemonConnections(snapshot);\n\t\t\t\tawait waitWithin(disconnectDaemonConnections(snapshot), remainingMs(), forceController.signal);\n\t\t\t\trequestDaemonConnectionClose(snapshot);\n\t\t\t\tconst socketsClosed = await waitWithin(\n\t\t\t\t\twaitForDaemonConnectionsClosed(snapshot),\n\t\t\t\t\tremainingMs(),\n\t\t\t\t\tforceController.signal,\n\t\t\t\t);\n\t\t\t\tif (!socketsClosed) terminateDaemonConnections(snapshot);\n\t\t\t\tdestroyDaemonSockets(sockets);\n\t\t\t\tawait listenerClose;\n\t\t\t\tconnections.clear();\n\t\t\t})().finally(() => {\n\t\t\t\tterminateDaemonConnections(connections);\n\t\t\t\tdestroyDaemonSockets(sockets);\n\t\t\t\tfor (const timer of pendingSocketTimers.values()) clearTimeout(timer);\n\t\t\t\tpendingSocketTimers.clear();\n\t\t\t\tpendingSocketDeadlines.clear();\n\t\t\t\tpendingSockets.clear();\n\t\t\t\tconnections.clear();\n\t\t\t\tcurrentAddress = undefined;\n\t\t\t\tserverState = \"closed\";\n\t\t\t});\n\t\t\treturn closePromise;\n\t\t},\n\t\tforceClose(): Promise<void> {\n\t\t\tif (serverState === \"closed\") return closePromise ?? Promise.resolve();\n\t\t\tserverState = \"closing\";\n\t\t\tforceController.abort();\n\t\t\tcurrentAddress = undefined;\n\t\t\tterminateDaemonConnections(connections);\n\t\t\tdestroyDaemonSockets(sockets);\n\t\t\treturn api.close();\n\t\t},\n\t};\n\treturn api;\n}\n"]}