parasor 0.1.0

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 (633) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +208 -0
  3. package/THIRD-PARTY-NOTICES.md +138 -0
  4. package/bin/parasor.mjs +3 -0
  5. package/node_modules/@parasor/shared/dist/client.d.ts +8 -0
  6. package/node_modules/@parasor/shared/dist/client.d.ts.map +1 -0
  7. package/node_modules/@parasor/shared/dist/client.js +2 -0
  8. package/node_modules/@parasor/shared/dist/client.js.map +1 -0
  9. package/node_modules/@parasor/shared/dist/drops.d.ts +24 -0
  10. package/node_modules/@parasor/shared/dist/drops.d.ts.map +1 -0
  11. package/node_modules/@parasor/shared/dist/drops.js +2 -0
  12. package/node_modules/@parasor/shared/dist/drops.js.map +1 -0
  13. package/node_modules/@parasor/shared/dist/file-uploads.d.ts +56 -0
  14. package/node_modules/@parasor/shared/dist/file-uploads.d.ts.map +1 -0
  15. package/node_modules/@parasor/shared/dist/file-uploads.js +13 -0
  16. package/node_modules/@parasor/shared/dist/file-uploads.js.map +1 -0
  17. package/node_modules/@parasor/shared/dist/ide-commands.d.ts +8 -0
  18. package/node_modules/@parasor/shared/dist/ide-commands.d.ts.map +1 -0
  19. package/node_modules/@parasor/shared/dist/ide-commands.js +59 -0
  20. package/node_modules/@parasor/shared/dist/ide-commands.js.map +1 -0
  21. package/node_modules/@parasor/shared/dist/pane-commands.d.ts +7 -0
  22. package/node_modules/@parasor/shared/dist/pane-commands.d.ts.map +1 -0
  23. package/node_modules/@parasor/shared/dist/pane-commands.js +47 -0
  24. package/node_modules/@parasor/shared/dist/pane-commands.js.map +1 -0
  25. package/node_modules/@parasor/shared/dist/pane-model.d.ts +63 -0
  26. package/node_modules/@parasor/shared/dist/pane-model.d.ts.map +1 -0
  27. package/node_modules/@parasor/shared/dist/pane-model.js +89 -0
  28. package/node_modules/@parasor/shared/dist/pane-model.js.map +1 -0
  29. package/node_modules/@parasor/shared/dist/panes.d.ts +33 -0
  30. package/node_modules/@parasor/shared/dist/panes.d.ts.map +1 -0
  31. package/node_modules/@parasor/shared/dist/panes.js +2 -0
  32. package/node_modules/@parasor/shared/dist/panes.js.map +1 -0
  33. package/node_modules/@parasor/shared/dist/runtime.d.ts +180 -0
  34. package/node_modules/@parasor/shared/dist/runtime.d.ts.map +1 -0
  35. package/node_modules/@parasor/shared/dist/runtime.js +2 -0
  36. package/node_modules/@parasor/shared/dist/runtime.js.map +1 -0
  37. package/node_modules/@parasor/shared/dist/state.d.ts +192 -0
  38. package/node_modules/@parasor/shared/dist/state.d.ts.map +1 -0
  39. package/node_modules/@parasor/shared/dist/state.js +10 -0
  40. package/node_modules/@parasor/shared/dist/state.js.map +1 -0
  41. package/node_modules/@parasor/shared/dist/terminal.d.ts +191 -0
  42. package/node_modules/@parasor/shared/dist/terminal.d.ts.map +1 -0
  43. package/node_modules/@parasor/shared/dist/terminal.js +174 -0
  44. package/node_modules/@parasor/shared/dist/terminal.js.map +1 -0
  45. package/node_modules/@parasor/shared/dist/types.d.ts +13 -0
  46. package/node_modules/@parasor/shared/dist/types.d.ts.map +1 -0
  47. package/node_modules/@parasor/shared/dist/types.js +13 -0
  48. package/node_modules/@parasor/shared/dist/types.js.map +1 -0
  49. package/node_modules/@parasor/shared/dist/worktree-local-files.d.ts +14 -0
  50. package/node_modules/@parasor/shared/dist/worktree-local-files.d.ts.map +1 -0
  51. package/node_modules/@parasor/shared/dist/worktree-local-files.js +41 -0
  52. package/node_modules/@parasor/shared/dist/worktree-local-files.js.map +1 -0
  53. package/node_modules/@parasor/shared/dist/ws-events.d.ts +152 -0
  54. package/node_modules/@parasor/shared/dist/ws-events.d.ts.map +1 -0
  55. package/node_modules/@parasor/shared/dist/ws-events.js +2 -0
  56. package/node_modules/@parasor/shared/dist/ws-events.js.map +1 -0
  57. package/node_modules/@parasor/shared/package.json +13 -0
  58. package/package.json +61 -0
  59. package/server/agent-detector/agent-state-store.d.ts +23 -0
  60. package/server/agent-detector/agent-state-store.d.ts.map +1 -0
  61. package/server/agent-detector/agent-state-store.js +110 -0
  62. package/server/agent-detector/agent-state-store.js.map +1 -0
  63. package/server/agent-detector/detector.d.ts +80 -0
  64. package/server/agent-detector/detector.d.ts.map +1 -0
  65. package/server/agent-detector/detector.js +219 -0
  66. package/server/agent-detector/detector.js.map +1 -0
  67. package/server/agent-detector/event-map.d.ts +25 -0
  68. package/server/agent-detector/event-map.d.ts.map +1 -0
  69. package/server/agent-detector/event-map.js +136 -0
  70. package/server/agent-detector/event-map.js.map +1 -0
  71. package/server/agent-detector/manual-agent-tracker.d.ts +19 -0
  72. package/server/agent-detector/manual-agent-tracker.d.ts.map +1 -0
  73. package/server/agent-detector/manual-agent-tracker.js +123 -0
  74. package/server/agent-detector/manual-agent-tracker.js.map +1 -0
  75. package/server/agent-detector/output-eligibility.d.ts +3 -0
  76. package/server/agent-detector/output-eligibility.d.ts.map +1 -0
  77. package/server/agent-detector/output-eligibility.js +39 -0
  78. package/server/agent-detector/output-eligibility.js.map +1 -0
  79. package/server/application/files/errors.d.ts +28 -0
  80. package/server/application/files/errors.d.ts.map +1 -0
  81. package/server/application/files/errors.js +55 -0
  82. package/server/application/files/errors.js.map +1 -0
  83. package/server/application/files/local-filesystem.d.ts +36 -0
  84. package/server/application/files/local-filesystem.d.ts.map +1 -0
  85. package/server/application/files/local-filesystem.js +171 -0
  86. package/server/application/files/local-filesystem.js.map +1 -0
  87. package/server/application/files/project-file-queries.d.ts +16 -0
  88. package/server/application/files/project-file-queries.d.ts.map +1 -0
  89. package/server/application/files/project-file-queries.js +126 -0
  90. package/server/application/files/project-file-queries.js.map +1 -0
  91. package/server/application/integrations/errors.d.ts +16 -0
  92. package/server/application/integrations/errors.d.ts.map +1 -0
  93. package/server/application/integrations/errors.js +31 -0
  94. package/server/application/integrations/errors.js.map +1 -0
  95. package/server/application/integrations/hook-notify.d.ts +32 -0
  96. package/server/application/integrations/hook-notify.d.ts.map +1 -0
  97. package/server/application/integrations/hook-notify.js +118 -0
  98. package/server/application/integrations/hook-notify.js.map +1 -0
  99. package/server/application/integrations/open-url.d.ts +11 -0
  100. package/server/application/integrations/open-url.d.ts.map +1 -0
  101. package/server/application/integrations/open-url.js +23 -0
  102. package/server/application/integrations/open-url.js.map +1 -0
  103. package/server/application/ports.d.ts +11 -0
  104. package/server/application/ports.d.ts.map +1 -0
  105. package/server/application/ports.js +2 -0
  106. package/server/application/ports.js.map +1 -0
  107. package/server/application/workspace/errors.d.ts +21 -0
  108. package/server/application/workspace/errors.d.ts.map +1 -0
  109. package/server/application/workspace/errors.js +21 -0
  110. package/server/application/workspace/errors.js.map +1 -0
  111. package/server/application/workspace/pane-commands.d.ts +47 -0
  112. package/server/application/workspace/pane-commands.d.ts.map +1 -0
  113. package/server/application/workspace/pane-commands.js +193 -0
  114. package/server/application/workspace/pane-commands.js.map +1 -0
  115. package/server/application/workspace/project-commands.d.ts +34 -0
  116. package/server/application/workspace/project-commands.d.ts.map +1 -0
  117. package/server/application/workspace/project-commands.js +81 -0
  118. package/server/application/workspace/project-commands.js.map +1 -0
  119. package/server/application/workspace/project-queries.d.ts +21 -0
  120. package/server/application/workspace/project-queries.d.ts.map +1 -0
  121. package/server/application/workspace/project-queries.js +216 -0
  122. package/server/application/workspace/project-queries.js.map +1 -0
  123. package/server/application/workspace/session-commands.d.ts +24 -0
  124. package/server/application/workspace/session-commands.d.ts.map +1 -0
  125. package/server/application/workspace/session-commands.js +123 -0
  126. package/server/application/workspace/session-commands.js.map +1 -0
  127. package/server/application/workspace/session-queries.d.ts +14 -0
  128. package/server/application/workspace/session-queries.d.ts.map +1 -0
  129. package/server/application/workspace/session-queries.js +47 -0
  130. package/server/application/workspace/session-queries.js.map +1 -0
  131. package/server/application/workspace/worktree-commands.d.ts +98 -0
  132. package/server/application/workspace/worktree-commands.d.ts.map +1 -0
  133. package/server/application/workspace/worktree-commands.js +323 -0
  134. package/server/application/workspace/worktree-commands.js.map +1 -0
  135. package/server/application/workspace/worktree-local-files.d.ts +11 -0
  136. package/server/application/workspace/worktree-local-files.d.ts.map +1 -0
  137. package/server/application/workspace/worktree-local-files.js +223 -0
  138. package/server/application/workspace/worktree-local-files.js.map +1 -0
  139. package/server/application/workspace/worktree-reconcile.d.ts +21 -0
  140. package/server/application/workspace/worktree-reconcile.d.ts.map +1 -0
  141. package/server/application/workspace/worktree-reconcile.js +49 -0
  142. package/server/application/workspace/worktree-reconcile.js.map +1 -0
  143. package/server/auth/origin.d.ts +17 -0
  144. package/server/auth/origin.d.ts.map +1 -0
  145. package/server/auth/origin.js +93 -0
  146. package/server/auth/origin.js.map +1 -0
  147. package/server/auth/pairing-token.d.ts +28 -0
  148. package/server/auth/pairing-token.d.ts.map +1 -0
  149. package/server/auth/pairing-token.js +46 -0
  150. package/server/auth/pairing-token.js.map +1 -0
  151. package/server/auth/token-exchange.d.ts +11 -0
  152. package/server/auth/token-exchange.d.ts.map +1 -0
  153. package/server/auth/token-exchange.js +27 -0
  154. package/server/auth/token-exchange.js.map +1 -0
  155. package/server/auth/token.d.ts +18 -0
  156. package/server/auth/token.d.ts.map +1 -0
  157. package/server/auth/token.js +115 -0
  158. package/server/auth/token.js.map +1 -0
  159. package/server/bootstrap/create-app-server.d.ts +49 -0
  160. package/server/bootstrap/create-app-server.d.ts.map +1 -0
  161. package/server/bootstrap/create-app-server.js +154 -0
  162. package/server/bootstrap/create-app-server.js.map +1 -0
  163. package/server/bootstrap/project-runtime.d.ts +29 -0
  164. package/server/bootstrap/project-runtime.d.ts.map +1 -0
  165. package/server/bootstrap/project-runtime.js +253 -0
  166. package/server/bootstrap/project-runtime.js.map +1 -0
  167. package/server/bootstrap/pty-env.d.ts +3 -0
  168. package/server/bootstrap/pty-env.d.ts.map +1 -0
  169. package/server/bootstrap/pty-env.js +15 -0
  170. package/server/bootstrap/pty-env.js.map +1 -0
  171. package/server/bootstrap/reconcile-state.d.ts +16 -0
  172. package/server/bootstrap/reconcile-state.d.ts.map +1 -0
  173. package/server/bootstrap/reconcile-state.js +73 -0
  174. package/server/bootstrap/reconcile-state.js.map +1 -0
  175. package/server/bootstrap/runtime-loops.d.ts +51 -0
  176. package/server/bootstrap/runtime-loops.d.ts.map +1 -0
  177. package/server/bootstrap/runtime-loops.js +189 -0
  178. package/server/bootstrap/runtime-loops.js.map +1 -0
  179. package/server/bootstrap/runtime-port.d.ts +4 -0
  180. package/server/bootstrap/runtime-port.d.ts.map +1 -0
  181. package/server/bootstrap/runtime-port.js +52 -0
  182. package/server/bootstrap/runtime-port.js.map +1 -0
  183. package/server/bootstrap/safety-gate.d.ts +22 -0
  184. package/server/bootstrap/safety-gate.d.ts.map +1 -0
  185. package/server/bootstrap/safety-gate.js +43 -0
  186. package/server/bootstrap/safety-gate.js.map +1 -0
  187. package/server/bootstrap/shutdown-marker.d.ts +35 -0
  188. package/server/bootstrap/shutdown-marker.d.ts.map +1 -0
  189. package/server/bootstrap/shutdown-marker.js +100 -0
  190. package/server/bootstrap/shutdown-marker.js.map +1 -0
  191. package/server/bootstrap/shutdown-runtime.d.ts +62 -0
  192. package/server/bootstrap/shutdown-runtime.d.ts.map +1 -0
  193. package/server/bootstrap/shutdown-runtime.js +66 -0
  194. package/server/bootstrap/shutdown-runtime.js.map +1 -0
  195. package/server/bootstrap/startup-banner.d.ts +34 -0
  196. package/server/bootstrap/startup-banner.d.ts.map +1 -0
  197. package/server/bootstrap/startup-banner.js +114 -0
  198. package/server/bootstrap/startup-banner.js.map +1 -0
  199. package/server/bootstrap/wire-runtime.d.ts +42 -0
  200. package/server/bootstrap/wire-runtime.d.ts.map +1 -0
  201. package/server/bootstrap/wire-runtime.js +205 -0
  202. package/server/bootstrap/wire-runtime.js.map +1 -0
  203. package/server/cli/help.d.ts +3 -0
  204. package/server/cli/help.d.ts.map +1 -0
  205. package/server/cli/help.js +39 -0
  206. package/server/cli/help.js.map +1 -0
  207. package/server/cli/hook-client.d.ts +12 -0
  208. package/server/cli/hook-client.d.ts.map +1 -0
  209. package/server/cli/hook-client.js +81 -0
  210. package/server/cli/hook-client.js.map +1 -0
  211. package/server/cli/hook.d.ts +3 -0
  212. package/server/cli/hook.d.ts.map +1 -0
  213. package/server/cli/hook.js +152 -0
  214. package/server/cli/hook.js.map +1 -0
  215. package/server/cli/main.d.ts +2 -0
  216. package/server/cli/main.d.ts.map +1 -0
  217. package/server/cli/main.js +133 -0
  218. package/server/cli/main.js.map +1 -0
  219. package/server/cli/notify.d.ts +19 -0
  220. package/server/cli/notify.d.ts.map +1 -0
  221. package/server/cli/notify.js +77 -0
  222. package/server/cli/notify.js.map +1 -0
  223. package/server/cli/open.d.ts +2 -0
  224. package/server/cli/open.d.ts.map +1 -0
  225. package/server/cli/open.js +47 -0
  226. package/server/cli/open.js.map +1 -0
  227. package/server/cli/probe-daemon-version.d.ts +46 -0
  228. package/server/cli/probe-daemon-version.d.ts.map +1 -0
  229. package/server/cli/probe-daemon-version.js +167 -0
  230. package/server/cli/probe-daemon-version.js.map +1 -0
  231. package/server/cli/pty-host.d.ts +36 -0
  232. package/server/cli/pty-host.d.ts.map +1 -0
  233. package/server/cli/pty-host.js +390 -0
  234. package/server/cli/pty-host.js.map +1 -0
  235. package/server/cli/qr.d.ts +2 -0
  236. package/server/cli/qr.d.ts.map +1 -0
  237. package/server/cli/qr.js +70 -0
  238. package/server/cli/qr.js.map +1 -0
  239. package/server/cli/restart-confirm.d.ts +33 -0
  240. package/server/cli/restart-confirm.d.ts.map +1 -0
  241. package/server/cli/restart-confirm.js +107 -0
  242. package/server/cli/restart-confirm.js.map +1 -0
  243. package/server/cli/restart.d.ts +17 -0
  244. package/server/cli/restart.d.ts.map +1 -0
  245. package/server/cli/restart.js +145 -0
  246. package/server/cli/restart.js.map +1 -0
  247. package/server/cli/service-darwin.d.ts +70 -0
  248. package/server/cli/service-darwin.d.ts.map +1 -0
  249. package/server/cli/service-darwin.js +562 -0
  250. package/server/cli/service-darwin.js.map +1 -0
  251. package/server/cli/service-linux.d.ts +81 -0
  252. package/server/cli/service-linux.d.ts.map +1 -0
  253. package/server/cli/service-linux.js +412 -0
  254. package/server/cli/service-linux.js.map +1 -0
  255. package/server/cli/service.d.ts +33 -0
  256. package/server/cli/service.d.ts.map +1 -0
  257. package/server/cli/service.js +133 -0
  258. package/server/cli/service.js.map +1 -0
  259. package/server/cli/shim-installer.d.ts +35 -0
  260. package/server/cli/shim-installer.d.ts.map +1 -0
  261. package/server/cli/shim-installer.js +662 -0
  262. package/server/cli/shim-installer.js.map +1 -0
  263. package/server/cli/shim-open.d.ts +2 -0
  264. package/server/cli/shim-open.d.ts.map +1 -0
  265. package/server/cli/shim-open.js +128 -0
  266. package/server/cli/shim-open.js.map +1 -0
  267. package/server/cli/shutdown-deps.d.ts +41 -0
  268. package/server/cli/shutdown-deps.d.ts.map +1 -0
  269. package/server/cli/shutdown-deps.js +158 -0
  270. package/server/cli/shutdown-deps.js.map +1 -0
  271. package/server/cli/stop.d.ts +11 -0
  272. package/server/cli/stop.d.ts.map +1 -0
  273. package/server/cli/stop.js +123 -0
  274. package/server/cli/stop.js.map +1 -0
  275. package/server/cli/unknown-command.d.ts +8 -0
  276. package/server/cli/unknown-command.d.ts.map +1 -0
  277. package/server/cli/unknown-command.js +14 -0
  278. package/server/cli/unknown-command.js.map +1 -0
  279. package/server/debug/agent-status-recorder.d.ts +57 -0
  280. package/server/debug/agent-status-recorder.d.ts.map +1 -0
  281. package/server/debug/agent-status-recorder.js +209 -0
  282. package/server/debug/agent-status-recorder.js.map +1 -0
  283. package/server/debug/terminal-trace-recorder.d.ts +41 -0
  284. package/server/debug/terminal-trace-recorder.d.ts.map +1 -0
  285. package/server/debug/terminal-trace-recorder.js +112 -0
  286. package/server/debug/terminal-trace-recorder.js.map +1 -0
  287. package/server/fonts/catalog.d.ts +35 -0
  288. package/server/fonts/catalog.d.ts.map +1 -0
  289. package/server/fonts/catalog.js +76 -0
  290. package/server/fonts/catalog.js.map +1 -0
  291. package/server/fonts/installer.d.ts +45 -0
  292. package/server/fonts/installer.d.ts.map +1 -0
  293. package/server/fonts/installer.js +201 -0
  294. package/server/fonts/installer.js.map +1 -0
  295. package/server/fonts/routes.d.ts +4 -0
  296. package/server/fonts/routes.d.ts.map +1 -0
  297. package/server/fonts/routes.js +91 -0
  298. package/server/fonts/routes.js.map +1 -0
  299. package/server/fs/drops.d.ts +50 -0
  300. package/server/fs/drops.d.ts.map +1 -0
  301. package/server/fs/drops.js +137 -0
  302. package/server/fs/drops.js.map +1 -0
  303. package/server/fs/file-uploads.d.ts +57 -0
  304. package/server/fs/file-uploads.d.ts.map +1 -0
  305. package/server/fs/file-uploads.js +214 -0
  306. package/server/fs/file-uploads.js.map +1 -0
  307. package/server/fs/file-watcher.d.ts +22 -0
  308. package/server/fs/file-watcher.d.ts.map +1 -0
  309. package/server/fs/file-watcher.js +105 -0
  310. package/server/fs/file-watcher.js.map +1 -0
  311. package/server/fs/git-watcher.d.ts +76 -0
  312. package/server/fs/git-watcher.d.ts.map +1 -0
  313. package/server/fs/git-watcher.js +356 -0
  314. package/server/fs/git-watcher.js.map +1 -0
  315. package/server/fs/media.d.ts +35 -0
  316. package/server/fs/media.d.ts.map +1 -0
  317. package/server/fs/media.js +271 -0
  318. package/server/fs/media.js.map +1 -0
  319. package/server/fs/service.d.ts +97 -0
  320. package/server/fs/service.d.ts.map +1 -0
  321. package/server/fs/service.js +306 -0
  322. package/server/fs/service.js.map +1 -0
  323. package/server/fs/upload-staging.d.ts +76 -0
  324. package/server/fs/upload-staging.d.ts.map +1 -0
  325. package/server/fs/upload-staging.js +283 -0
  326. package/server/fs/upload-staging.js.map +1 -0
  327. package/server/fs/watcher-lifecycle.d.ts +24 -0
  328. package/server/fs/watcher-lifecycle.d.ts.map +1 -0
  329. package/server/fs/watcher-lifecycle.js +105 -0
  330. package/server/fs/watcher-lifecycle.js.map +1 -0
  331. package/server/index.d.ts +17 -0
  332. package/server/index.d.ts.map +1 -0
  333. package/server/index.js +510 -0
  334. package/server/index.js.map +1 -0
  335. package/server/ipc/socket-server.d.ts +28 -0
  336. package/server/ipc/socket-server.d.ts.map +1 -0
  337. package/server/ipc/socket-server.js +206 -0
  338. package/server/ipc/socket-server.js.map +1 -0
  339. package/server/lib/git-exec.d.ts +38 -0
  340. package/server/lib/git-exec.d.ts.map +1 -0
  341. package/server/lib/git-exec.js +96 -0
  342. package/server/lib/git-exec.js.map +1 -0
  343. package/server/lib/open-in-ide.d.ts +22 -0
  344. package/server/lib/open-in-ide.d.ts.map +1 -0
  345. package/server/lib/open-in-ide.js +90 -0
  346. package/server/lib/open-in-ide.js.map +1 -0
  347. package/server/lib/open-in-os.d.ts +20 -0
  348. package/server/lib/open-in-os.d.ts.map +1 -0
  349. package/server/lib/open-in-os.js +51 -0
  350. package/server/lib/open-in-os.js.map +1 -0
  351. package/server/lib/path.d.ts +2 -0
  352. package/server/lib/path.d.ts.map +1 -0
  353. package/server/lib/path.js +10 -0
  354. package/server/lib/path.js.map +1 -0
  355. package/server/lib/promise-mutex.d.ts +7 -0
  356. package/server/lib/promise-mutex.d.ts.map +1 -0
  357. package/server/lib/promise-mutex.js +26 -0
  358. package/server/lib/promise-mutex.js.map +1 -0
  359. package/server/lib/sd-notify.d.ts +8 -0
  360. package/server/lib/sd-notify.d.ts.map +1 -0
  361. package/server/lib/sd-notify.js +27 -0
  362. package/server/lib/sd-notify.js.map +1 -0
  363. package/server/net/local-machine.d.ts +7 -0
  364. package/server/net/local-machine.d.ts.map +1 -0
  365. package/server/net/local-machine.js +79 -0
  366. package/server/net/local-machine.js.map +1 -0
  367. package/server/net/reachable-host.d.ts +12 -0
  368. package/server/net/reachable-host.d.ts.map +1 -0
  369. package/server/net/reachable-host.js +25 -0
  370. package/server/net/reachable-host.js.map +1 -0
  371. package/server/network/endpoints.d.ts +14 -0
  372. package/server/network/endpoints.d.ts.map +1 -0
  373. package/server/network/endpoints.js +104 -0
  374. package/server/network/endpoints.js.map +1 -0
  375. package/server/network/qr.d.ts +16 -0
  376. package/server/network/qr.d.ts.map +1 -0
  377. package/server/network/qr.js +89 -0
  378. package/server/network/qr.js.map +1 -0
  379. package/server/port-forwarder/forwarder.d.ts +47 -0
  380. package/server/port-forwarder/forwarder.d.ts.map +1 -0
  381. package/server/port-forwarder/forwarder.js +159 -0
  382. package/server/port-forwarder/forwarder.js.map +1 -0
  383. package/server/port-scanner/scanner.d.ts +24 -0
  384. package/server/port-scanner/scanner.d.ts.map +1 -0
  385. package/server/port-scanner/scanner.js +193 -0
  386. package/server/port-scanner/scanner.js.map +1 -0
  387. package/server/pty/connection-lifecycle.d.ts +50 -0
  388. package/server/pty/connection-lifecycle.d.ts.map +1 -0
  389. package/server/pty/connection-lifecycle.js +113 -0
  390. package/server/pty/connection-lifecycle.js.map +1 -0
  391. package/server/pty/daemon-connect.d.ts +52 -0
  392. package/server/pty/daemon-connect.d.ts.map +1 -0
  393. package/server/pty/daemon-connect.js +62 -0
  394. package/server/pty/daemon-connect.js.map +1 -0
  395. package/server/pty/handshake-timeout-race.d.ts +22 -0
  396. package/server/pty/handshake-timeout-race.d.ts.map +1 -0
  397. package/server/pty/handshake-timeout-race.js +23 -0
  398. package/server/pty/handshake-timeout-race.js.map +1 -0
  399. package/server/pty/headless-replay-snapshot.d.ts +28 -0
  400. package/server/pty/headless-replay-snapshot.d.ts.map +1 -0
  401. package/server/pty/headless-replay-snapshot.js +285 -0
  402. package/server/pty/headless-replay-snapshot.js.map +1 -0
  403. package/server/pty/headless-terminal-state-cache.d.ts +31 -0
  404. package/server/pty/headless-terminal-state-cache.d.ts.map +1 -0
  405. package/server/pty/headless-terminal-state-cache.js +119 -0
  406. package/server/pty/headless-terminal-state-cache.js.map +1 -0
  407. package/server/pty/hello-ack-validator.d.ts +15 -0
  408. package/server/pty/hello-ack-validator.d.ts.map +1 -0
  409. package/server/pty/hello-ack-validator.js +30 -0
  410. package/server/pty/hello-ack-validator.js.map +1 -0
  411. package/server/pty/host-daemon/bootstrap.d.ts +100 -0
  412. package/server/pty/host-daemon/bootstrap.d.ts.map +1 -0
  413. package/server/pty/host-daemon/bootstrap.js +611 -0
  414. package/server/pty/host-daemon/bootstrap.js.map +1 -0
  415. package/server/pty/host-daemon/daemon.d.ts +111 -0
  416. package/server/pty/host-daemon/daemon.d.ts.map +1 -0
  417. package/server/pty/host-daemon/daemon.js +648 -0
  418. package/server/pty/host-daemon/daemon.js.map +1 -0
  419. package/server/pty/host-daemon/entry.d.ts +3 -0
  420. package/server/pty/host-daemon/entry.d.ts.map +1 -0
  421. package/server/pty/host-daemon/entry.js +72 -0
  422. package/server/pty/host-daemon/entry.js.map +1 -0
  423. package/server/pty/host-daemon/lockfile.d.ts +12 -0
  424. package/server/pty/host-daemon/lockfile.d.ts.map +1 -0
  425. package/server/pty/host-daemon/lockfile.js +120 -0
  426. package/server/pty/host-daemon/lockfile.js.map +1 -0
  427. package/server/pty/host-daemon/mode-marker.d.ts +77 -0
  428. package/server/pty/host-daemon/mode-marker.d.ts.map +1 -0
  429. package/server/pty/host-daemon/mode-marker.js +228 -0
  430. package/server/pty/host-daemon/mode-marker.js.map +1 -0
  431. package/server/pty/host-daemon/orphan-cleanup.d.ts +42 -0
  432. package/server/pty/host-daemon/orphan-cleanup.d.ts.map +1 -0
  433. package/server/pty/host-daemon/orphan-cleanup.js +84 -0
  434. package/server/pty/host-daemon/orphan-cleanup.js.map +1 -0
  435. package/server/pty/host-daemon/paths.d.ts +10 -0
  436. package/server/pty/host-daemon/paths.d.ts.map +1 -0
  437. package/server/pty/host-daemon/paths.js +56 -0
  438. package/server/pty/host-daemon/paths.js.map +1 -0
  439. package/server/pty/host-daemon/server-connection.d.ts +44 -0
  440. package/server/pty/host-daemon/server-connection.d.ts.map +1 -0
  441. package/server/pty/host-daemon/server-connection.js +100 -0
  442. package/server/pty/host-daemon/server-connection.js.map +1 -0
  443. package/server/pty/host-daemon/service-detection.d.ts +24 -0
  444. package/server/pty/host-daemon/service-detection.d.ts.map +1 -0
  445. package/server/pty/host-daemon/service-detection.js +16 -0
  446. package/server/pty/host-daemon/service-detection.js.map +1 -0
  447. package/server/pty/host-daemon/socket-ready.d.ts +22 -0
  448. package/server/pty/host-daemon/socket-ready.d.ts.map +1 -0
  449. package/server/pty/host-daemon/socket-ready.js +33 -0
  450. package/server/pty/host-daemon/socket-ready.js.map +1 -0
  451. package/server/pty/host-daemon/spawn-daemon.d.ts +45 -0
  452. package/server/pty/host-daemon/spawn-daemon.d.ts.map +1 -0
  453. package/server/pty/host-daemon/spawn-daemon.js +155 -0
  454. package/server/pty/host-daemon/spawn-daemon.js.map +1 -0
  455. package/server/pty/host-daemon/terminate-daemon.d.ts +16 -0
  456. package/server/pty/host-daemon/terminate-daemon.d.ts.map +1 -0
  457. package/server/pty/host-daemon/terminate-daemon.js +128 -0
  458. package/server/pty/host-daemon/terminate-daemon.js.map +1 -0
  459. package/server/pty/host-protocol/frames.d.ts +110 -0
  460. package/server/pty/host-protocol/frames.d.ts.map +1 -0
  461. package/server/pty/host-protocol/frames.js +255 -0
  462. package/server/pty/host-protocol/frames.js.map +1 -0
  463. package/server/pty/host-protocol/messages.d.ts +140 -0
  464. package/server/pty/host-protocol/messages.d.ts.map +1 -0
  465. package/server/pty/host-protocol/messages.js +117 -0
  466. package/server/pty/host-protocol/messages.js.map +1 -0
  467. package/server/pty/host.d.ts +273 -0
  468. package/server/pty/host.d.ts.map +1 -0
  469. package/server/pty/host.js +184 -0
  470. package/server/pty/host.js.map +1 -0
  471. package/server/pty/in-process-host.d.ts +224 -0
  472. package/server/pty/in-process-host.d.ts.map +1 -0
  473. package/server/pty/in-process-host.js +1183 -0
  474. package/server/pty/in-process-host.js.map +1 -0
  475. package/server/pty/osc7-lifecycle.d.ts +8 -0
  476. package/server/pty/osc7-lifecycle.d.ts.map +1 -0
  477. package/server/pty/osc7-lifecycle.js +22 -0
  478. package/server/pty/osc7-lifecycle.js.map +1 -0
  479. package/server/pty/osc7-parser.d.ts +23 -0
  480. package/server/pty/osc7-parser.d.ts.map +1 -0
  481. package/server/pty/osc7-parser.js +91 -0
  482. package/server/pty/osc7-parser.js.map +1 -0
  483. package/server/pty/remote-host.d.ts +188 -0
  484. package/server/pty/remote-host.d.ts.map +1 -0
  485. package/server/pty/remote-host.js +810 -0
  486. package/server/pty/remote-host.js.map +1 -0
  487. package/server/pty/request-correlator.d.ts +59 -0
  488. package/server/pty/request-correlator.d.ts.map +1 -0
  489. package/server/pty/request-correlator.js +75 -0
  490. package/server/pty/request-correlator.js.map +1 -0
  491. package/server/pty/scrollback-log.d.ts +130 -0
  492. package/server/pty/scrollback-log.d.ts.map +1 -0
  493. package/server/pty/scrollback-log.js +344 -0
  494. package/server/pty/scrollback-log.js.map +1 -0
  495. package/server/pty/scrollback-sanitize.d.ts +2 -0
  496. package/server/pty/scrollback-sanitize.d.ts.map +1 -0
  497. package/server/pty/scrollback-sanitize.js +54 -0
  498. package/server/pty/scrollback-sanitize.js.map +1 -0
  499. package/server/pty/session-mirror.d.ts +67 -0
  500. package/server/pty/session-mirror.d.ts.map +1 -0
  501. package/server/pty/session-mirror.js +112 -0
  502. package/server/pty/session-mirror.js.map +1 -0
  503. package/server/pty/session-policy.d.ts +85 -0
  504. package/server/pty/session-policy.d.ts.map +1 -0
  505. package/server/pty/session-policy.js +186 -0
  506. package/server/pty/session-policy.js.map +1 -0
  507. package/server/pty/version-mismatch-recovery.d.ts +71 -0
  508. package/server/pty/version-mismatch-recovery.d.ts.map +1 -0
  509. package/server/pty/version-mismatch-recovery.js +63 -0
  510. package/server/pty/version-mismatch-recovery.js.map +1 -0
  511. package/server/routes/debug-agent-status.d.ts +5 -0
  512. package/server/routes/debug-agent-status.d.ts.map +1 -0
  513. package/server/routes/debug-agent-status.js +22 -0
  514. package/server/routes/debug-agent-status.js.map +1 -0
  515. package/server/routes/debug-diagnostics.d.ts +8 -0
  516. package/server/routes/debug-diagnostics.d.ts.map +1 -0
  517. package/server/routes/debug-diagnostics.js +34 -0
  518. package/server/routes/debug-diagnostics.js.map +1 -0
  519. package/server/routes/debug-terminal-trace.d.ts +16 -0
  520. package/server/routes/debug-terminal-trace.d.ts.map +1 -0
  521. package/server/routes/debug-terminal-trace.js +545 -0
  522. package/server/routes/debug-terminal-trace.js.map +1 -0
  523. package/server/routes/drops.d.ts +13 -0
  524. package/server/routes/drops.d.ts.map +1 -0
  525. package/server/routes/drops.js +126 -0
  526. package/server/routes/drops.js.map +1 -0
  527. package/server/routes/file-uploads.d.ts +9 -0
  528. package/server/routes/file-uploads.d.ts.map +1 -0
  529. package/server/routes/file-uploads.js +119 -0
  530. package/server/routes/file-uploads.js.map +1 -0
  531. package/server/routes/files.d.ts +9 -0
  532. package/server/routes/files.d.ts.map +1 -0
  533. package/server/routes/files.js +441 -0
  534. package/server/routes/files.js.map +1 -0
  535. package/server/routes/filesystem.d.ts +6 -0
  536. package/server/routes/filesystem.d.ts.map +1 -0
  537. package/server/routes/filesystem.js +76 -0
  538. package/server/routes/filesystem.js.map +1 -0
  539. package/server/routes/git.d.ts +38 -0
  540. package/server/routes/git.d.ts.map +1 -0
  541. package/server/routes/git.js +585 -0
  542. package/server/routes/git.js.map +1 -0
  543. package/server/routes/healthz.d.ts +8 -0
  544. package/server/routes/healthz.d.ts.map +1 -0
  545. package/server/routes/healthz.js +24 -0
  546. package/server/routes/healthz.js.map +1 -0
  547. package/server/routes/hook.d.ts +14 -0
  548. package/server/routes/hook.d.ts.map +1 -0
  549. package/server/routes/hook.js +86 -0
  550. package/server/routes/hook.js.map +1 -0
  551. package/server/routes/ide-commands.d.ts +9 -0
  552. package/server/routes/ide-commands.d.ts.map +1 -0
  553. package/server/routes/ide-commands.js +23 -0
  554. package/server/routes/ide-commands.js.map +1 -0
  555. package/server/routes/lib/resolve-worktree.d.ts +30 -0
  556. package/server/routes/lib/resolve-worktree.d.ts.map +1 -0
  557. package/server/routes/lib/resolve-worktree.js +35 -0
  558. package/server/routes/lib/resolve-worktree.js.map +1 -0
  559. package/server/routes/open.d.ts +4 -0
  560. package/server/routes/open.d.ts.map +1 -0
  561. package/server/routes/open.js +21 -0
  562. package/server/routes/open.js.map +1 -0
  563. package/server/routes/pane-commands.d.ts +9 -0
  564. package/server/routes/pane-commands.d.ts.map +1 -0
  565. package/server/routes/pane-commands.js +23 -0
  566. package/server/routes/pane-commands.js.map +1 -0
  567. package/server/routes/projects.d.ts +15 -0
  568. package/server/routes/projects.d.ts.map +1 -0
  569. package/server/routes/projects.js +363 -0
  570. package/server/routes/projects.js.map +1 -0
  571. package/server/routes/server-notices.d.ts +4 -0
  572. package/server/routes/server-notices.d.ts.map +1 -0
  573. package/server/routes/server-notices.js +29 -0
  574. package/server/routes/server-notices.js.map +1 -0
  575. package/server/routes/service-config.d.ts +11 -0
  576. package/server/routes/service-config.d.ts.map +1 -0
  577. package/server/routes/service-config.js +64 -0
  578. package/server/routes/service-config.js.map +1 -0
  579. package/server/routes/sessions.d.ts +7 -0
  580. package/server/routes/sessions.d.ts.map +1 -0
  581. package/server/routes/sessions.js +218 -0
  582. package/server/routes/sessions.js.map +1 -0
  583. package/server/service/caffeinate.d.ts +33 -0
  584. package/server/service/caffeinate.d.ts.map +1 -0
  585. package/server/service/caffeinate.js +72 -0
  586. package/server/service/caffeinate.js.map +1 -0
  587. package/server/state/app-state.d.ts +167 -0
  588. package/server/state/app-state.d.ts.map +1 -0
  589. package/server/state/app-state.js +335 -0
  590. package/server/state/app-state.js.map +1 -0
  591. package/server/state/project-manager.d.ts +30 -0
  592. package/server/state/project-manager.d.ts.map +1 -0
  593. package/server/state/project-manager.js +128 -0
  594. package/server/state/project-manager.js.map +1 -0
  595. package/server/state/server-notices.d.ts +12 -0
  596. package/server/state/server-notices.d.ts.map +1 -0
  597. package/server/state/server-notices.js +32 -0
  598. package/server/state/server-notices.js.map +1 -0
  599. package/server/state/worktree-cache.d.ts +25 -0
  600. package/server/state/worktree-cache.d.ts.map +1 -0
  601. package/server/state/worktree-cache.js +53 -0
  602. package/server/state/worktree-cache.js.map +1 -0
  603. package/server/ws/events.d.ts +45 -0
  604. package/server/ws/events.d.ts.map +1 -0
  605. package/server/ws/events.js +134 -0
  606. package/server/ws/events.js.map +1 -0
  607. package/server/ws/keepalive.d.ts +27 -0
  608. package/server/ws/keepalive.d.ts.map +1 -0
  609. package/server/ws/keepalive.js +63 -0
  610. package/server/ws/keepalive.js.map +1 -0
  611. package/server/ws/terminal-attach.d.ts +13 -0
  612. package/server/ws/terminal-attach.d.ts.map +1 -0
  613. package/server/ws/terminal-attach.js +233 -0
  614. package/server/ws/terminal-attach.js.map +1 -0
  615. package/server/ws/terminal-flow.d.ts +17 -0
  616. package/server/ws/terminal-flow.d.ts.map +1 -0
  617. package/server/ws/terminal-flow.js +64 -0
  618. package/server/ws/terminal-flow.js.map +1 -0
  619. package/server/ws/terminal.d.ts +69 -0
  620. package/server/ws/terminal.d.ts.map +1 -0
  621. package/server/ws/terminal.js +311 -0
  622. package/server/ws/terminal.js.map +1 -0
  623. package/web/assets/EditorPane-CzzT3iYY.js +123 -0
  624. package/web/assets/SymbolsNerdFontMono-Regular-CwEZqMeU.woff2 +0 -0
  625. package/web/assets/TerminalPane-CjbYzePr.js +68 -0
  626. package/web/assets/TerminalPane-DkTCHfhq.css +1 -0
  627. package/web/assets/file-icons-JBi09j0r.js +6 -0
  628. package/web/assets/index-CTTkRpnn.css +2 -0
  629. package/web/assets/index-CmhewzMp.js +34 -0
  630. package/web/assets/session-resume-7f-tB-ZU.js +2 -0
  631. package/web/assets/terminal-trace-PuuFRybC.js +2803 -0
  632. package/web/assets/useVirtualKeyboard-DgJb9u9d.js +1 -0
  633. package/web/index.html +52 -0
@@ -0,0 +1,306 @@
1
+ import { Buffer } from "node:buffer";
2
+ import { existsSync, constants as fsConstants, readFileSync, realpathSync, } from "node:fs";
3
+ import { cp as fsCp, mkdir as fsMkdir, open as fsOpen, readFile as fsReadFile, realpath as fsRealpath, writeFile as fsWriteFile, readdir, stat, } from "node:fs/promises";
4
+ import { join, relative, resolve, sep } from "node:path";
5
+ import ignore from "ignore";
6
+ const HARD_EXCLUDES = new Set([".git", ".DS_Store", "Thumbs.db"]);
7
+ const BUILTIN_IGNORES = [
8
+ "node_modules",
9
+ "dist",
10
+ "build",
11
+ ".next",
12
+ ".nuxt",
13
+ ".venv",
14
+ "venv",
15
+ "__pycache__",
16
+ ".pytest_cache",
17
+ "target",
18
+ ".turbo",
19
+ ];
20
+ const MAX_FILE_SIZE = 1024 * 1024; // 1 MB
21
+ export class PathTraversalError extends Error {
22
+ constructor() {
23
+ super("Path traversal denied");
24
+ this.name = "PathTraversalError";
25
+ }
26
+ }
27
+ export class CopySourceNotFoundError extends Error {
28
+ constructor() {
29
+ super("Copy source not found");
30
+ this.name = "CopySourceNotFoundError";
31
+ }
32
+ }
33
+ export class CopyDestinationExistsError extends Error {
34
+ constructor() {
35
+ super("Copy destination already exists");
36
+ this.name = "CopyDestinationExistsError";
37
+ }
38
+ }
39
+ export class FilesystemService {
40
+ projectRoot;
41
+ ignoreInstance;
42
+ constructor(projectRoot) {
43
+ const resolved = resolve(projectRoot);
44
+ try {
45
+ this.projectRoot = realpathSync(resolved);
46
+ }
47
+ catch {
48
+ this.projectRoot = resolved;
49
+ }
50
+ this.ignoreInstance = this.loadIgnore();
51
+ }
52
+ async listDir(relPath) {
53
+ const absPath = this.resolve(relPath);
54
+ const ig = this.ignoreInstance;
55
+ const entries = [];
56
+ const dirEntries = await readdir(absPath, { withFileTypes: true });
57
+ for (const dirent of dirEntries) {
58
+ if (HARD_EXCLUDES.has(dirent.name))
59
+ continue;
60
+ const entryRelPath = relative(this.projectRoot, join(absPath, dirent.name));
61
+ const isDir = dirent.isDirectory();
62
+ const isGitignored = this.isIgnoredWith(ig, entryRelPath, isDir);
63
+ const isHidden = dirent.name.startsWith(".");
64
+ entries.push({
65
+ name: dirent.name,
66
+ path: entryRelPath,
67
+ type: isDir ? "directory" : "file",
68
+ ...(isGitignored && { isGitignored: true }),
69
+ ...(isHidden && { isHidden: true }),
70
+ });
71
+ }
72
+ entries.sort((a, b) => {
73
+ if (a.type !== b.type)
74
+ return a.type === "directory" ? -1 : 1;
75
+ return a.name.localeCompare(b.name);
76
+ });
77
+ return entries;
78
+ }
79
+ async readFile(relPath, maxBytes) {
80
+ const absPath = this.resolve(relPath);
81
+ const limit = maxBytes ?? MAX_FILE_SIZE;
82
+ try {
83
+ const stats = await stat(absPath);
84
+ if (stats.size > limit) {
85
+ throw new Error("File too large");
86
+ }
87
+ const content = await fsReadFile(absPath, "utf-8");
88
+ return content;
89
+ }
90
+ catch (err) {
91
+ if (err instanceof Error && err.message === "File too large")
92
+ throw err;
93
+ if (isNodeError(err) && err.code === "ENOENT")
94
+ return null;
95
+ throw err;
96
+ }
97
+ }
98
+ /**
99
+ * Stat a single file, returning `null` when missing. Wraps node `stat()`
100
+ * to surface `PathTraversalError` consistently and never leak ENOENT
101
+ * details to the route layer.
102
+ */
103
+ async statFile(relPath) {
104
+ const absPath = this.resolve(relPath);
105
+ try {
106
+ return await stat(absPath);
107
+ }
108
+ catch (err) {
109
+ if (isNodeError(err) && err.code === "ENOENT")
110
+ return null;
111
+ throw err;
112
+ }
113
+ }
114
+ /**
115
+ * Open a regular file inside the project root for inline media serving.
116
+ * The leaf is opened with `O_NOFOLLOW` so a symlink swapped in between
117
+ * the parent-directory resolve and this open cannot redirect to a target
118
+ * outside the project tree. The returned `FileHandle` is the single
119
+ * authoritative reference: callers do `fstat`, magic-number sniff via
120
+ * `read`, and stream creation through the same handle so size limits and
121
+ * content-type detection apply to the exact bytes about to be served.
122
+ * The caller MUST `close()` the handle (or pass it to `createReadStream`
123
+ * with `autoClose: true`).
124
+ *
125
+ * `O_NONBLOCK` keeps `open()` from blocking when the path happens to be a
126
+ * FIFO/socket/character device (a `*.mp4` FIFO in a cloned repo would
127
+ * otherwise pin a libuv worker until a writer connects); the post-open
128
+ * `isFile()` check then rejects everything that isn't a regular file.
129
+ *
130
+ * `O_NOFOLLOW` only protects the leaf -- an attacker with FS write access
131
+ * can still swap a parent directory to a symlink between `resolve()`'s
132
+ * realpath check and this `open()`. We close that gap by re-resolving the
133
+ * path *after* open and comparing the canonical result's inode to the
134
+ * fd's inode. A mid-open swap leaves the fd bound to a file outside the
135
+ * project tree while the second realpath resolves to the legitimate
136
+ * (or missing) in-tree entry, so the inodes diverge and we reject.
137
+ *
138
+ * Returns `null` for ENOENT so missing files surface as 404 rather than
139
+ * leaking the absolute path. ELOOP (the leaf was a symlink) raises a
140
+ * `PathTraversalError` because following symlinks at the leaf is exactly
141
+ * what we are refusing.
142
+ */
143
+ async openInlineFile(relPath) {
144
+ const absPath = this.resolve(relPath);
145
+ const NONBLOCK = fsConstants.O_NONBLOCK ?? 0;
146
+ let handle;
147
+ try {
148
+ handle = await fsOpen(absPath, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW | NONBLOCK);
149
+ }
150
+ catch (err) {
151
+ if (isNodeError(err) && err.code === "ENOENT")
152
+ return null;
153
+ if (isNodeError(err) && err.code === "ELOOP") {
154
+ throw new PathTraversalError();
155
+ }
156
+ throw err;
157
+ }
158
+ try {
159
+ const stats = await handle.stat();
160
+ if (!stats.isFile()) {
161
+ await handle.close();
162
+ return null;
163
+ }
164
+ let real;
165
+ try {
166
+ real = await fsRealpath(absPath);
167
+ }
168
+ catch (err) {
169
+ if (isNodeError(err) && err.code === "ENOENT") {
170
+ await handle.close();
171
+ return null;
172
+ }
173
+ throw err;
174
+ }
175
+ if (real !== this.projectRoot &&
176
+ !real.startsWith(this.projectRoot + sep)) {
177
+ await handle.close();
178
+ throw new PathTraversalError();
179
+ }
180
+ const pathStats = await stat(real);
181
+ if (pathStats.ino !== stats.ino || pathStats.dev !== stats.dev) {
182
+ await handle.close();
183
+ throw new PathTraversalError();
184
+ }
185
+ return { handle, stats };
186
+ }
187
+ catch (err) {
188
+ await handle.close().catch(() => { });
189
+ throw err;
190
+ }
191
+ }
192
+ /**
193
+ * Build a read stream from an already-open `FileHandle`, optionally clamped
194
+ * to a byte range. Uses `FileHandle.createReadStream` with `autoClose: true`
195
+ * so stream ownership of the handle is explicit -- closing the stream
196
+ * releases the underlying fd through the FileHandle, avoiding the
197
+ * double-close hazard of passing the raw `handle.fd` to `createReadStream`
198
+ * (where the FileHandle's own GC finalizer could close an fd the stream
199
+ * already returned to the OS). Pairs with `openInlineFile` -- callers must
200
+ * not reuse the handle after this call returns.
201
+ */
202
+ createStreamFromHandle(handle, size, range) {
203
+ let start = 0;
204
+ let end = size === 0 ? 0 : size - 1;
205
+ if (range) {
206
+ start = range.start;
207
+ end = range.end;
208
+ }
209
+ const stream = size === 0
210
+ ? handle.createReadStream({ autoClose: true })
211
+ : handle.createReadStream({ autoClose: true, start, end });
212
+ return { stream, start, end };
213
+ }
214
+ async writeFile(relPath, content) {
215
+ const byteLength = Buffer.byteLength(content, "utf-8");
216
+ if (byteLength > MAX_FILE_SIZE) {
217
+ throw new Error("File too large");
218
+ }
219
+ const absPath = this.resolve(relPath);
220
+ await fsWriteFile(absPath, content, "utf-8");
221
+ }
222
+ async mkdir(relPath) {
223
+ const absPath = this.resolve(relPath);
224
+ await fsMkdir(absPath, { recursive: true });
225
+ }
226
+ /**
227
+ * Recursive copy of a file or directory inside the project root. Both
228
+ * sides are routed through `resolve()` so symlink-escape and `..` traversal
229
+ * remain blocked. Refuses to overwrite an existing destination -- callers
230
+ * pick a unique name (Finder-style "<n> copy", "<n> copy 2") before invoking.
231
+ */
232
+ async cp(srcRelPath, destRelPath) {
233
+ const srcAbs = this.resolve(srcRelPath);
234
+ const destAbs = this.resolve(destRelPath);
235
+ try {
236
+ await stat(srcAbs);
237
+ }
238
+ catch (err) {
239
+ if (isNodeError(err) && err.code === "ENOENT") {
240
+ throw new CopySourceNotFoundError();
241
+ }
242
+ throw err;
243
+ }
244
+ if (existsSync(destAbs)) {
245
+ throw new CopyDestinationExistsError();
246
+ }
247
+ await fsCp(srcAbs, destAbs, {
248
+ recursive: true,
249
+ errorOnExist: true,
250
+ force: false,
251
+ });
252
+ }
253
+ reloadIgnore() {
254
+ this.ignoreInstance = this.loadIgnore();
255
+ }
256
+ isIgnored(relPath, isDir) {
257
+ if (!relPath || relPath === "." || relPath === "")
258
+ return false;
259
+ return this.isIgnoredWith(this.ignoreInstance, relPath, isDir);
260
+ }
261
+ resolve(relPath) {
262
+ // Normalize resolved path against canonical projectRoot
263
+ const resolved = resolve(this.projectRoot, relPath);
264
+ if (resolved !== this.projectRoot &&
265
+ !resolved.startsWith(this.projectRoot + sep)) {
266
+ throw new PathTraversalError();
267
+ }
268
+ // Symlink check: resolve real path if it exists
269
+ try {
270
+ const real = realpathSync(resolved);
271
+ if (real !== this.projectRoot &&
272
+ !real.startsWith(this.projectRoot + sep)) {
273
+ throw new PathTraversalError();
274
+ }
275
+ }
276
+ catch (err) {
277
+ if (err instanceof PathTraversalError)
278
+ throw err;
279
+ // ENOENT or other -- path doesn't exist yet, allow (ENOENT handled in callers)
280
+ }
281
+ return resolved;
282
+ }
283
+ loadIgnore() {
284
+ const ig = ignore();
285
+ ig.add(BUILTIN_IGNORES);
286
+ const gitignorePath = join(this.projectRoot, ".gitignore");
287
+ if (existsSync(gitignorePath)) {
288
+ try {
289
+ const content = readFileSync(gitignorePath, "utf-8");
290
+ ig.add(content);
291
+ }
292
+ catch {
293
+ // ignore read failures
294
+ }
295
+ }
296
+ return ig;
297
+ }
298
+ isIgnoredWith(ig, relPath, isDir) {
299
+ const testPath = isDir ? `${relPath}/` : relPath;
300
+ return ig.ignores(testPath);
301
+ }
302
+ }
303
+ function isNodeError(err) {
304
+ return err instanceof Error && "code" in err;
305
+ }
306
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/fs/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Validation failure for a sessionId that does not match the strict
3
+ * format. Carries the raw value as a property so log sinks can decide
4
+ * whether to record it; the human-readable `message` stays a fixed
5
+ * literal so journald / file logs cannot be ANSI/newline-injected by an
6
+ * attacker who controls the query string (reviewed for correctness).
7
+ */
8
+ export declare class InvalidSessionIdError extends Error {
9
+ readonly reason: "empty" | "format";
10
+ /** Raw value as received. Not embedded in `message`. */
11
+ readonly value: string;
12
+ constructor(reason: "empty" | "format", value: string);
13
+ }
14
+ export interface UploadStagingOptions {
15
+ /**
16
+ * Base directory. Resolved through `realpath()` once at construction
17
+ * (macOS `/tmp` -> `/private/tmp`) so every later `startsWith(rootDir)`
18
+ * fence compares canonical paths. Defaults to `${tmpdir()}/parasor`.
19
+ */
20
+ rootDir?: string;
21
+ /**
22
+ * Entries older than this in `sweepStale()` are removed. Default 24h.
23
+ */
24
+ ttlMs?: number;
25
+ /**
26
+ * Test injection point. Defaults to `Date.now`.
27
+ */
28
+ clock?: () => number;
29
+ }
30
+ export declare class UploadStaging {
31
+ /** Canonical absolute path of `<rootDir>/uploads`. */
32
+ readonly uploadsDir: string;
33
+ private readonly ttlMs;
34
+ private readonly clock;
35
+ constructor(options?: UploadStagingOptions);
36
+ /**
37
+ * Acquire (or re-use) a session-scoped upload directory. The directory
38
+ * name is `{sessionId}` -- opaque per-PTY, no timestamp suffix. Multiple
39
+ * concurrent callers for the same sessionId race-safely converge on the
40
+ * same directory because `mkdir({recursive:true})` is idempotent
41
+ * (prior `recursive:false` would 500 on EEXIST).
42
+ */
43
+ acquire(sessionId: string): Promise<string>;
44
+ /**
45
+ * L1 cleanup. Removes the session's directory tree if any. Best-effort:
46
+ * a failure here is logged by the caller but never breaks shutdown.
47
+ */
48
+ releaseSession(sessionId: string): Promise<void>;
49
+ /**
50
+ * L2 / L3 cleanup. Walks `uploadsDir` and removes every entry whose
51
+ * mtime is older than `ttlMs`. We stat instead of parsing the entry
52
+ * name so a future-dated suffix cannot keep an entry alive forever
53
+ * (reviewed for correctness). Returns the removed paths so callers can log
54
+ * a single-line summary.
55
+ */
56
+ sweepStale(now?: number): Promise<{
57
+ swept: string[];
58
+ }>;
59
+ }
60
+ /**
61
+ * Best-effort removal of the legacy `.parasor/drops/` directory inside a
62
+ * project root. Upload staging isolation retires the in-tree drop layout entirely; on
63
+ * server boot the upload route's old dirs are deleted from every known
64
+ * project so the surface area for "stale screenshot in repo" goes to
65
+ * zero. Errors are swallowed (logged by caller) -- the legacy dir is
66
+ * already `.gitignore`d, so failure to delete is non-fatal.
67
+ *
68
+ * target is narrowed to `.parasor/drops/`. The
69
+ * parent `.parasor/` namespace is removed only when it ends up empty,
70
+ * so future code writing other entries under `.parasor/<other>` is
71
+ * not nuked by every server boot.
72
+ */
73
+ export declare function removeLegacyDropsDir(projectRoot: string): Promise<{
74
+ removed: boolean;
75
+ }>;
76
+ //# sourceMappingURL=upload-staging.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload-staging.d.ts","sourceRoot":"","sources":["../../src/fs/upload-staging.ts"],"names":[],"mappings":"AAoCA;;;;;;GAMG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,QAAQ,CAAC;IACpC,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBACX,MAAM,EAAE,OAAO,GAAG,QAAQ,EAAE,KAAK,EAAE,MAAM;CAUtD;AAoBD,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;CACtB;AAED,qBAAa,aAAa;IACxB,sDAAsD;IACtD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;gBAEzB,OAAO,GAAE,oBAAyB;IAwB9C;;;;;;OAMG;IACG,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgBjD;;;OAGG;IACG,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOtD;;;;;;OAMG;IACG,UAAU,CAAC,GAAG,GAAE,MAAqB,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAqC3E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CA2D/B"}
@@ -0,0 +1,283 @@
1
+ import { lstatSync, mkdirSync, realpathSync } from "node:fs";
2
+ import { lstat, mkdir, readdir, realpath, rm, rmdir, stat, } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join, resolve, sep } from "node:path";
5
+ /**
6
+ * Image / file drops attached from the chat composer land here, NOT inside
7
+ * the user's project tree. The directory layout is:
8
+ *
9
+ * {rootDir}/uploads/{sessionId}/<filename>
10
+ *
11
+ * `{sessionId}` is opaque per-PTY (UUID). The directory is owned by the
12
+ * server process and exposed to the live PTY child via the per-session
13
+ * env var `PARASOR_UPLOAD_DIR` (set in `InProcessPtyHost.buildSessionEnv`)
14
+ * -- never as a shared root -- so the Claude wrapper's `--add-dir` only
15
+ * widens that PTY's allowlist to its own subdir, not its siblings'.
16
+ *
17
+ * Three-layer GC (upload staging isolation):
18
+ * L1 -- `releaseSession()` on PTY exit (immediate, in-process)
19
+ * L2 -- `sweepStale()` at server boot (handles SIGKILL leftovers)
20
+ * L3 -- `sweepStale()` on a 60-min interval (handles long-lived servers)
21
+ */
22
+ const DEFAULT_TTL_MS = 24 * 60 * 60 * 1000;
23
+ const UPLOADS_SUBDIR = "uploads";
24
+ /** Owner-only -- drop dir contents may include unredacted screenshots. */
25
+ const DIR_MODE = 0o700;
26
+ /**
27
+ * Validation failure for a sessionId that does not match the strict
28
+ * format. Carries the raw value as a property so log sinks can decide
29
+ * whether to record it; the human-readable `message` stays a fixed
30
+ * literal so journald / file logs cannot be ANSI/newline-injected by an
31
+ * attacker who controls the query string (reviewed for correctness).
32
+ */
33
+ export class InvalidSessionIdError extends Error {
34
+ reason;
35
+ /** Raw value as received. Not embedded in `message`. */
36
+ value;
37
+ constructor(reason, value) {
38
+ super(reason === "empty"
39
+ ? "uploadStaging: empty sessionId"
40
+ : "uploadStaging: invalid sessionId format");
41
+ this.reason = reason;
42
+ this.value = value;
43
+ this.name = "InvalidSessionIdError";
44
+ }
45
+ }
46
+ /** Reject session-id strings that could escape the upload root. */
47
+ function assertSafeSessionId(sessionId) {
48
+ if (sessionId.length === 0) {
49
+ throw new InvalidSessionIdError("empty", sessionId);
50
+ }
51
+ if (!/^[A-Za-z0-9_-]+$/.test(sessionId)) {
52
+ throw new InvalidSessionIdError("format", sessionId);
53
+ }
54
+ }
55
+ function isNodeErrorWithCode(err, code) {
56
+ return (err instanceof Error &&
57
+ "code" in err &&
58
+ err.code === code);
59
+ }
60
+ export class UploadStaging {
61
+ /** Canonical absolute path of `<rootDir>/uploads`. */
62
+ uploadsDir;
63
+ ttlMs;
64
+ clock;
65
+ constructor(options = {}) {
66
+ const baseRaw = options.rootDir ?? join(tmpdir(), "parasor");
67
+ // mkdirSync runs before realpath because realpath() throws ENOENT on
68
+ // a missing path. The constructor is sync to keep `index.ts` boot
69
+ // ordering simple -- every subsequent operation is async.
70
+ mkdirSync(baseRaw, { recursive: true, mode: DIR_MODE });
71
+ const uploadsRaw = join(baseRaw, UPLOADS_SUBDIR);
72
+ mkdirSync(uploadsRaw, { recursive: true, mode: DIR_MODE });
73
+ // Reject if an attacker pre-planted a symlink at our root: realpath()
74
+ // would happily follow the link and we'd write under their target.
75
+ // lstat *before* realpath so the symlink itself is the thing we
76
+ // inspect (reviewed for correctness). uid is checked against geteuid()
77
+ // -- owning user only, no group/other writers.
78
+ assertOwnedRealDir(baseRaw);
79
+ assertOwnedRealDir(uploadsRaw);
80
+ // realpath resolves symlinks (notably macOS /tmp -> /private/tmp).
81
+ // Sync resolution keeps the public `uploadsDir` available for the
82
+ // `--add-dir` env injection without forcing the constructor to be
83
+ // async.
84
+ this.uploadsDir = realpathSync(uploadsRaw);
85
+ this.ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;
86
+ this.clock = options.clock ?? (() => Date.now());
87
+ }
88
+ /**
89
+ * Acquire (or re-use) a session-scoped upload directory. The directory
90
+ * name is `{sessionId}` -- opaque per-PTY, no timestamp suffix. Multiple
91
+ * concurrent callers for the same sessionId race-safely converge on the
92
+ * same directory because `mkdir({recursive:true})` is idempotent
93
+ * (prior `recursive:false` would 500 on EEXIST).
94
+ */
95
+ async acquire(sessionId) {
96
+ assertSafeSessionId(sessionId);
97
+ const target = join(this.uploadsDir, sessionId);
98
+ // Defence in depth -- the sanitizer above already proves `sessionId`
99
+ // contains no separators, but the realpath-based fence catches a
100
+ // future regression of the validator.
101
+ if (!target.startsWith(this.uploadsDir + sep)) {
102
+ throw new Error("uploadStaging: target escaped uploadsDir");
103
+ }
104
+ // recursive:true converts EEXIST into a no-op success. The caller
105
+ // never sees an error if a sibling acquire() raced ahead, so two
106
+ // PTYs requesting the same sessionId both get the same dir back.
107
+ await mkdir(target, { recursive: true, mode: DIR_MODE });
108
+ return target;
109
+ }
110
+ /**
111
+ * L1 cleanup. Removes the session's directory tree if any. Best-effort:
112
+ * a failure here is logged by the caller but never breaks shutdown.
113
+ */
114
+ async releaseSession(sessionId) {
115
+ assertSafeSessionId(sessionId);
116
+ const target = join(this.uploadsDir, sessionId);
117
+ if (!target.startsWith(this.uploadsDir + sep))
118
+ return;
119
+ await rm(target, { recursive: true, force: true });
120
+ }
121
+ /**
122
+ * L2 / L3 cleanup. Walks `uploadsDir` and removes every entry whose
123
+ * mtime is older than `ttlMs`. We stat instead of parsing the entry
124
+ * name so a future-dated suffix cannot keep an entry alive forever
125
+ * (reviewed for correctness). Returns the removed paths so callers can log
126
+ * a single-line summary.
127
+ */
128
+ async sweepStale(now = this.clock()) {
129
+ const cutoff = now - this.ttlMs;
130
+ const swept = [];
131
+ let entries;
132
+ try {
133
+ entries = await readdir(this.uploadsDir);
134
+ }
135
+ catch (err) {
136
+ if (isNodeErrorWithCode(err, "ENOENT"))
137
+ return { swept };
138
+ throw err;
139
+ }
140
+ for (const name of entries) {
141
+ const full = join(this.uploadsDir, name);
142
+ // Same fence as acquire: never act outside uploadsDir.
143
+ if (!full.startsWith(this.uploadsDir + sep))
144
+ continue;
145
+ try {
146
+ const st = await stat(full);
147
+ // Both birthtime (creation) and mtime (last write) must be old
148
+ // enough to retire -- a stale dir whose user keeps appending
149
+ // files stays alive while it's still in use.
150
+ const ageRef = Math.max(st.mtimeMs, st.birthtimeMs || 0);
151
+ if (ageRef > cutoff)
152
+ continue;
153
+ }
154
+ catch (err) {
155
+ if (isNodeErrorWithCode(err, "ENOENT"))
156
+ continue;
157
+ throw err;
158
+ }
159
+ try {
160
+ await rm(full, { recursive: true, force: true });
161
+ swept.push(full);
162
+ }
163
+ catch (err) {
164
+ if (isNodeErrorWithCode(err, "ENOENT"))
165
+ continue;
166
+ // Log + continue: a stuck entry must not block the rest of the
167
+ // sweep. Caller has no actionable response.
168
+ console.error("[upload-staging] sweep rm failed:", full, err);
169
+ }
170
+ }
171
+ return { swept };
172
+ }
173
+ }
174
+ /**
175
+ * Best-effort removal of the legacy `.parasor/drops/` directory inside a
176
+ * project root. Upload staging isolation retires the in-tree drop layout entirely; on
177
+ * server boot the upload route's old dirs are deleted from every known
178
+ * project so the surface area for "stale screenshot in repo" goes to
179
+ * zero. Errors are swallowed (logged by caller) -- the legacy dir is
180
+ * already `.gitignore`d, so failure to delete is non-fatal.
181
+ *
182
+ * target is narrowed to `.parasor/drops/`. The
183
+ * parent `.parasor/` namespace is removed only when it ends up empty,
184
+ * so future code writing other entries under `.parasor/<other>` is
185
+ * not nuked by every server boot.
186
+ */
187
+ export async function removeLegacyDropsDir(projectRoot) {
188
+ // Realpath the project root first so a project pointer like
189
+ // `~/projects/foo` (already expanded by caller) is canonicalized
190
+ // before the startsWith fence below.
191
+ let realProject;
192
+ try {
193
+ realProject = await realpath(projectRoot);
194
+ }
195
+ catch (err) {
196
+ if (isNodeErrorWithCode(err, "ENOENT"))
197
+ return { removed: false };
198
+ throw err;
199
+ }
200
+ const parasorDir = resolve(realProject, ".parasor");
201
+ const dropsDir = resolve(parasorDir, "drops");
202
+ // Reject if `.parasor` itself is a symlink -- refuse to follow into
203
+ // arbitrary territory. Using lstat (not stat) so the symlink itself
204
+ // is the thing we inspect.
205
+ try {
206
+ const parasorLst = await lstat(parasorDir);
207
+ if (parasorLst.isSymbolicLink())
208
+ return { removed: false };
209
+ }
210
+ catch (err) {
211
+ if (isNodeErrorWithCode(err, "ENOENT"))
212
+ return { removed: false };
213
+ throw err;
214
+ }
215
+ // Defence in depth: re-canonicalize and verify the drops path stays
216
+ // inside the project root. Catches a `.parasor/drops -> /etc` symlink
217
+ // even after the parent-dir lstat above passed.
218
+ let realDrops;
219
+ try {
220
+ realDrops = await realpath(dropsDir);
221
+ }
222
+ catch (err) {
223
+ if (isNodeErrorWithCode(err, "ENOENT"))
224
+ return { removed: false };
225
+ throw err;
226
+ }
227
+ if (realDrops !== resolve(realProject, ".parasor", "drops") ||
228
+ !realDrops.startsWith(realProject + sep)) {
229
+ return { removed: false };
230
+ }
231
+ await rm(realDrops, { recursive: true, force: true });
232
+ // Best-effort: clean the now-orphaned `.parasor/` shell, but only if
233
+ // empty. Other tooling that legitimately writes to `.parasor/<other>`
234
+ // (future features, user scripts) keeps its data.
235
+ try {
236
+ await rmdir(parasorDir);
237
+ }
238
+ catch (err) {
239
+ // ENOTEMPTY = other entries present (future namespace neighbours);
240
+ // ENOENT = removed concurrently. Both fine.
241
+ if (!isNodeErrorWithCode(err, "ENOTEMPTY") &&
242
+ !isNodeErrorWithCode(err, "ENOENT") &&
243
+ // Some platforms return EEXIST instead of ENOTEMPTY for non-empty
244
+ // rmdir (POSIX permits either).
245
+ !isNodeErrorWithCode(err, "EEXIST")) {
246
+ throw err;
247
+ }
248
+ }
249
+ return { removed: true };
250
+ }
251
+ /**
252
+ * Refuse to use `path` if its `lstat` reports it as a symlink, or its
253
+ * owner uid does not match the running process's effective uid. The
254
+ * latter check is skipped on Windows where `geteuid` is unavailable;
255
+ * elsewhere it ensures an attacker who pre-created the dir under a
256
+ * different user cannot trick us into writing secrets they can read.
257
+ */
258
+ function assertOwnedRealDir(path) {
259
+ let st;
260
+ try {
261
+ st = lstatSync(path);
262
+ }
263
+ catch {
264
+ // Constructor only calls this after a successful mkdirSync so
265
+ // ENOENT here would be a TOCTOU race -- refuse to continue.
266
+ throw new Error(`uploadStaging: cannot lstat ${path}`);
267
+ }
268
+ if (st.isSymbolicLink()) {
269
+ throw new Error(`uploadStaging: refusing symlink at ${path}`);
270
+ }
271
+ if (!st.isDirectory()) {
272
+ throw new Error(`uploadStaging: not a directory: ${path}`);
273
+ }
274
+ // process.geteuid is undefined on Windows; skip the uid check there.
275
+ const geteuid = process.geteuid;
276
+ if (geteuid) {
277
+ const me = geteuid();
278
+ if (st.uid !== me) {
279
+ throw new Error(`uploadStaging: ${path} is owned by uid ${st.uid}, expected ${me}`);
280
+ }
281
+ }
282
+ }
283
+ //# sourceMappingURL=upload-staging.js.map