windows-development-sandbox 0.0.0-stage → 1.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 (426) hide show
  1. package/.sandbox-config.example.json +14 -0
  2. package/LICENSE +21 -0
  3. package/README.md +94 -2
  4. package/config.example.json +349 -0
  5. package/dist/api.d.ts +31 -0
  6. package/dist/api.js +31 -0
  7. package/dist/bin/agent-sandbox.d.ts +2 -0
  8. package/dist/bin/agent-sandbox.js +3 -0
  9. package/dist/bin/claude-host.d.ts +2 -0
  10. package/dist/bin/claude-host.js +5 -0
  11. package/dist/bin/claude-sbx.d.ts +2 -0
  12. package/dist/bin/claude-sbx.js +3 -0
  13. package/dist/bin/codex-sbx.d.ts +2 -0
  14. package/dist/bin/codex-sbx.js +3 -0
  15. package/dist/bin/gemini-sbx.d.ts +2 -0
  16. package/dist/bin/gemini-sbx.js +3 -0
  17. package/dist/bin/sandbox.d.ts +2 -0
  18. package/dist/bin/sandbox.js +4 -0
  19. package/dist/bin/sbx-hide.d.ts +2 -0
  20. package/dist/bin/sbx-hide.js +3 -0
  21. package/dist/bin/sbx-show.d.ts +2 -0
  22. package/dist/bin/sbx-show.js +3 -0
  23. package/dist/cli/args.d.ts +52 -0
  24. package/dist/cli/args.js +143 -0
  25. package/dist/cli/colors.d.ts +24 -0
  26. package/dist/cli/colors.js +42 -0
  27. package/dist/cli/commands/accounts.d.ts +2 -0
  28. package/dist/cli/commands/accounts.js +52 -0
  29. package/dist/cli/commands/agent-commands.d.ts +6 -0
  30. package/dist/cli/commands/agent-commands.js +61 -0
  31. package/dist/cli/commands/context.d.ts +23 -0
  32. package/dist/cli/commands/context.js +57 -0
  33. package/dist/cli/commands/data/clean.d.ts +15 -0
  34. package/dist/cli/commands/data/clean.js +101 -0
  35. package/dist/cli/commands/data/collect.d.ts +11 -0
  36. package/dist/cli/commands/data/collect.js +54 -0
  37. package/dist/cli/commands/data/index.d.ts +4 -0
  38. package/dist/cli/commands/data/index.js +45 -0
  39. package/dist/cli/commands/data/remove.d.ts +2 -0
  40. package/dist/cli/commands/data/remove.js +30 -0
  41. package/dist/cli/commands/index.d.ts +10 -0
  42. package/dist/cli/commands/index.js +10 -0
  43. package/dist/cli/commands/launch.d.ts +29 -0
  44. package/dist/cli/commands/launch.js +333 -0
  45. package/dist/cli/commands/maintenance.d.ts +8 -0
  46. package/dist/cli/commands/maintenance.js +154 -0
  47. package/dist/cli/commands/project.d.ts +29 -0
  48. package/dist/cli/commands/project.js +63 -0
  49. package/dist/cli/commands/projects.d.ts +14 -0
  50. package/dist/cli/commands/projects.js +146 -0
  51. package/dist/cli/commands/repair/checks.d.ts +2 -0
  52. package/dist/cli/commands/repair/checks.js +170 -0
  53. package/dist/cli/commands/repair/finders.d.ts +30 -0
  54. package/dist/cli/commands/repair/finders.js +108 -0
  55. package/dist/cli/commands/repair/index.d.ts +12 -0
  56. package/dist/cli/commands/repair/index.js +61 -0
  57. package/dist/cli/commands/repair/types.d.ts +26 -0
  58. package/dist/cli/commands/repair/types.js +3 -0
  59. package/dist/cli/commands/restart.d.ts +6 -0
  60. package/dist/cli/commands/restart.js +85 -0
  61. package/dist/cli/commands/sessions.d.ts +12 -0
  62. package/dist/cli/commands/sessions.js +257 -0
  63. package/dist/cli/commands/setup/checks.d.ts +13 -0
  64. package/dist/cli/commands/setup/checks.js +71 -0
  65. package/dist/cli/commands/setup/facts.d.ts +31 -0
  66. package/dist/cli/commands/setup/facts.js +60 -0
  67. package/dist/cli/commands/setup/index.d.ts +2 -0
  68. package/dist/cli/commands/setup/index.js +43 -0
  69. package/dist/cli/commands/user-config.d.ts +8 -0
  70. package/dist/cli/commands/user-config.js +41 -0
  71. package/dist/cli/history.d.ts +11 -0
  72. package/dist/cli/history.js +21 -0
  73. package/dist/cli/index.d.ts +20 -0
  74. package/dist/cli/index.js +121 -0
  75. package/dist/cli/manifest.d.ts +103 -0
  76. package/dist/cli/manifest.js +107 -0
  77. package/dist/cli/menu-multi.d.ts +12 -0
  78. package/dist/cli/menu-multi.js +82 -0
  79. package/dist/cli/menu.d.ts +14 -0
  80. package/dist/cli/menu.js +290 -0
  81. package/dist/cli/progress.d.ts +9 -0
  82. package/dist/cli/progress.js +49 -0
  83. package/dist/cli/settings/edit.d.ts +13 -0
  84. package/dist/cli/settings/edit.js +19 -0
  85. package/dist/cli/settings/index.d.ts +8 -0
  86. package/dist/cli/settings/index.js +131 -0
  87. package/dist/cli/settings/prompts.d.ts +7 -0
  88. package/dist/cli/settings/prompts.js +48 -0
  89. package/dist/cli/settings/schema.d.ts +33 -0
  90. package/dist/cli/settings/schema.js +29 -0
  91. package/dist/cli/validate.d.ts +17 -0
  92. package/dist/cli/validate.js +89 -0
  93. package/dist/core/config.d.ts +17 -0
  94. package/dist/core/config.js +106 -0
  95. package/dist/core/detect-databases.d.ts +15 -0
  96. package/dist/core/detect-databases.js +147 -0
  97. package/dist/core/detect-pwsh.d.ts +18 -0
  98. package/dist/core/detect-pwsh.js +111 -0
  99. package/dist/core/detect-toolchains.d.ts +30 -0
  100. package/dist/core/detect-toolchains.js +58 -0
  101. package/dist/core/disk.d.ts +16 -0
  102. package/dist/core/disk.js +55 -0
  103. package/dist/core/local-config.d.ts +20 -0
  104. package/dist/core/local-config.js +77 -0
  105. package/dist/core/project-policy.d.ts +15 -0
  106. package/dist/core/project-policy.js +35 -0
  107. package/dist/core/prompt.d.ts +4 -0
  108. package/dist/core/prompt.js +15 -0
  109. package/dist/core/safe-paths.d.ts +4 -0
  110. package/dist/core/safe-paths.js +37 -0
  111. package/dist/core/schema/common.d.ts +17 -0
  112. package/dist/core/schema/common.js +15 -0
  113. package/dist/core/schema/config.d.ts +594 -0
  114. package/dist/core/schema/config.js +63 -0
  115. package/dist/core/schema/databases.d.ts +33 -0
  116. package/dist/core/schema/databases.js +35 -0
  117. package/dist/core/schema/harness.d.ts +12 -0
  118. package/dist/core/schema/harness.js +17 -0
  119. package/dist/core/schema/json-schema.d.ts +5 -0
  120. package/dist/core/schema/json-schema.js +25 -0
  121. package/dist/core/schema/profile.d.ts +27 -0
  122. package/dist/core/schema/profile.js +29 -0
  123. package/dist/core/schema/projects.d.ts +9 -0
  124. package/dist/core/schema/projects.js +11 -0
  125. package/dist/core/schema/sandbox.d.ts +50 -0
  126. package/dist/core/schema/sandbox.js +36 -0
  127. package/dist/core/schema/toolchains.d.ts +93 -0
  128. package/dist/core/schema/toolchains.js +83 -0
  129. package/dist/core/schema.d.ts +6 -0
  130. package/dist/core/schema.js +8 -0
  131. package/dist/core/types.d.ts +190 -0
  132. package/dist/core/types.js +1 -0
  133. package/dist/core/util.d.ts +60 -0
  134. package/dist/core/util.js +154 -0
  135. package/dist/core/workspace.d.ts +18 -0
  136. package/dist/core/workspace.js +128 -0
  137. package/dist/guest/boot-env.d.ts +4 -0
  138. package/dist/guest/boot-env.js +25 -0
  139. package/dist/guest/cmdline.d.ts +12 -0
  140. package/dist/guest/cmdline.js +23 -0
  141. package/dist/guest/daemon/exec.d.ts +5 -0
  142. package/dist/guest/daemon/exec.js +32 -0
  143. package/dist/guest/daemon/project.d.ts +14 -0
  144. package/dist/guest/daemon/project.js +132 -0
  145. package/dist/guest/daemon/session.d.ts +13 -0
  146. package/dist/guest/daemon/session.js +139 -0
  147. package/dist/guest/daemon/shutdown.d.ts +1 -0
  148. package/dist/guest/daemon/shutdown.js +21 -0
  149. package/dist/guest/daemon/state.d.ts +17 -0
  150. package/dist/guest/daemon/state.js +31 -0
  151. package/dist/guest/daemon.d.ts +1 -0
  152. package/dist/guest/daemon.js +53 -0
  153. package/dist/guest/db.d.ts +1 -0
  154. package/dist/guest/db.js +75 -0
  155. package/dist/guest/env.d.ts +51 -0
  156. package/dist/guest/env.js +101 -0
  157. package/dist/guest/gitguard.d.ts +7 -0
  158. package/dist/guest/gitguard.js +60 -0
  159. package/dist/guest/gitrules.d.ts +2 -0
  160. package/dist/guest/gitrules.js +11 -0
  161. package/dist/guest/guide.d.ts +16 -0
  162. package/dist/guest/guide.js +69 -0
  163. package/dist/guest/helpers.d.ts +3 -0
  164. package/dist/guest/helpers.js +26 -0
  165. package/dist/guest/main.d.ts +1 -0
  166. package/dist/guest/main.js +130 -0
  167. package/dist/guest/ports.d.ts +6 -0
  168. package/dist/guest/ports.js +22 -0
  169. package/dist/guest/project-context.d.ts +7 -0
  170. package/dist/guest/project-context.js +10 -0
  171. package/dist/guest/project-env.d.ts +20 -0
  172. package/dist/guest/project-env.js +20 -0
  173. package/dist/guest/project-status.d.ts +5 -0
  174. package/dist/guest/project-status.js +17 -0
  175. package/dist/guest/ptyhost.d.ts +22 -0
  176. package/dist/guest/ptyhost.js +36 -0
  177. package/dist/guest/setup/agents.d.ts +11 -0
  178. package/dist/guest/setup/agents.js +87 -0
  179. package/dist/guest/setup/claude.d.ts +21 -0
  180. package/dist/guest/setup/claude.js +146 -0
  181. package/dist/guest/setup/environment.d.ts +16 -0
  182. package/dist/guest/setup/environment.js +69 -0
  183. package/dist/guest/setup/hooks.d.ts +9 -0
  184. package/dist/guest/setup/hooks.js +50 -0
  185. package/dist/guest/setup/network.d.ts +10 -0
  186. package/dist/guest/setup/network.js +99 -0
  187. package/dist/guest/setup/policy.d.ts +3 -0
  188. package/dist/guest/setup/policy.js +18 -0
  189. package/dist/guest/setup/user.d.ts +7 -0
  190. package/dist/guest/setup/user.js +47 -0
  191. package/dist/guest/toolchains/catalogue.d.ts +55 -0
  192. package/dist/guest/toolchains/catalogue.js +31 -0
  193. package/dist/guest/toolchains/cli.d.ts +10 -0
  194. package/dist/guest/toolchains/cli.js +72 -0
  195. package/dist/guest/toolchains/common.d.ts +54 -0
  196. package/dist/guest/toolchains/common.js +147 -0
  197. package/dist/guest/toolchains/databases/dynamodb.d.ts +8 -0
  198. package/dist/guest/toolchains/databases/dynamodb.js +52 -0
  199. package/dist/guest/toolchains/databases/index.d.ts +6 -0
  200. package/dist/guest/toolchains/databases/index.js +62 -0
  201. package/dist/guest/toolchains/databases/mongodb.d.ts +3 -0
  202. package/dist/guest/toolchains/databases/mongodb.js +31 -0
  203. package/dist/guest/toolchains/databases/mysql.d.ts +3 -0
  204. package/dist/guest/toolchains/databases/mysql.js +38 -0
  205. package/dist/guest/toolchains/databases/postgres.d.ts +5 -0
  206. package/dist/guest/toolchains/databases/postgres.js +38 -0
  207. package/dist/guest/toolchains/databases/redis.d.ts +3 -0
  208. package/dist/guest/toolchains/databases/redis.js +16 -0
  209. package/dist/guest/toolchains/databases/server.d.ts +14 -0
  210. package/dist/guest/toolchains/databases/server.js +52 -0
  211. package/dist/guest/toolchains/git.d.ts +3 -0
  212. package/dist/guest/toolchains/git.js +121 -0
  213. package/dist/guest/toolchains/go.d.ts +3 -0
  214. package/dist/guest/toolchains/go.js +33 -0
  215. package/dist/guest/toolchains/index.d.ts +17 -0
  216. package/dist/guest/toolchains/index.js +80 -0
  217. package/dist/guest/toolchains/java.d.ts +8 -0
  218. package/dist/guest/toolchains/java.js +96 -0
  219. package/dist/guest/toolchains/leftovers.d.ts +2 -0
  220. package/dist/guest/toolchains/leftovers.js +26 -0
  221. package/dist/guest/toolchains/managers.d.ts +16 -0
  222. package/dist/guest/toolchains/managers.js +84 -0
  223. package/dist/guest/toolchains/native/binstall.d.ts +7 -0
  224. package/dist/guest/toolchains/native/binstall.js +52 -0
  225. package/dist/guest/toolchains/native/cpp.d.ts +4 -0
  226. package/dist/guest/toolchains/native/cpp.js +38 -0
  227. package/dist/guest/toolchains/native/dotnet.d.ts +4 -0
  228. package/dist/guest/toolchains/native/dotnet.js +103 -0
  229. package/dist/guest/toolchains/native/mesa.d.ts +7 -0
  230. package/dist/guest/toolchains/native/mesa.js +46 -0
  231. package/dist/guest/toolchains/native/msvc/environment.d.ts +16 -0
  232. package/dist/guest/toolchains/native/msvc/environment.js +57 -0
  233. package/dist/guest/toolchains/native/msvc/index.d.ts +6 -0
  234. package/dist/guest/toolchains/native/msvc/index.js +48 -0
  235. package/dist/guest/toolchains/native/msvc/packages.d.ts +6 -0
  236. package/dist/guest/toolchains/native/msvc/packages.js +156 -0
  237. package/dist/guest/toolchains/native/msvc/tree.d.ts +15 -0
  238. package/dist/guest/toolchains/native/msvc/tree.js +21 -0
  239. package/dist/guest/toolchains/native/rust.d.ts +3 -0
  240. package/dist/guest/toolchains/native/rust.js +45 -0
  241. package/dist/guest/toolchains/node.d.ts +3 -0
  242. package/dist/guest/toolchains/node.js +152 -0
  243. package/dist/guest/toolchains/plan.d.ts +22 -0
  244. package/dist/guest/toolchains/plan.js +96 -0
  245. package/dist/guest/toolchains/pwsh.d.ts +4 -0
  246. package/dist/guest/toolchains/pwsh.js +14 -0
  247. package/dist/guest/toolchains/python.d.ts +3 -0
  248. package/dist/guest/toolchains/python.js +54 -0
  249. package/dist/guest/toolchains/runtimes.d.ts +19 -0
  250. package/dist/guest/toolchains/runtimes.js +38 -0
  251. package/dist/guest/toolchains/scripting/php.d.ts +3 -0
  252. package/dist/guest/toolchains/scripting/php.js +71 -0
  253. package/dist/guest/toolchains/scripting/ruby.d.ts +3 -0
  254. package/dist/guest/toolchains/scripting/ruby.js +47 -0
  255. package/dist/guest/toolchains/scripting/vcruntime.d.ts +7 -0
  256. package/dist/guest/toolchains/scripting/vcruntime.js +45 -0
  257. package/dist/guest/toolchains/versions.d.ts +47 -0
  258. package/dist/guest/toolchains/versions.js +77 -0
  259. package/dist/guest/toolchains/vscode.d.ts +2 -0
  260. package/dist/guest/toolchains/vscode.js +53 -0
  261. package/dist/guest/view.d.ts +1 -0
  262. package/dist/guest/view.js +42 -0
  263. package/dist/host/accounts.d.ts +32 -0
  264. package/dist/host/accounts.js +128 -0
  265. package/dist/host/agent-commands.d.ts +25 -0
  266. package/dist/host/agent-commands.js +145 -0
  267. package/dist/host/attach.d.ts +17 -0
  268. package/dist/host/attach.js +69 -0
  269. package/dist/host/channel.d.ts +38 -0
  270. package/dist/host/channel.js +162 -0
  271. package/dist/host/claude-profile.d.ts +15 -0
  272. package/dist/host/claude-profile.js +107 -0
  273. package/dist/host/cleanup.d.ts +23 -0
  274. package/dist/host/cleanup.js +57 -0
  275. package/dist/host/database-plan.d.ts +12 -0
  276. package/dist/host/database-plan.js +52 -0
  277. package/dist/host/generate.d.ts +7 -0
  278. package/dist/host/generate.js +98 -0
  279. package/dist/host/join.d.ts +28 -0
  280. package/dist/host/join.js +76 -0
  281. package/dist/host/launch/mappings.d.ts +3 -0
  282. package/dist/host/launch/mappings.js +50 -0
  283. package/dist/host/launch/projects.d.ts +15 -0
  284. package/dist/host/launch/projects.js +56 -0
  285. package/dist/host/launch/stage.d.ts +11 -0
  286. package/dist/host/launch/stage.js +66 -0
  287. package/dist/host/launch/wsb.d.ts +10 -0
  288. package/dist/host/launch/wsb.js +34 -0
  289. package/dist/host/pc-scan.d.ts +6 -0
  290. package/dist/host/pc-scan.js +37 -0
  291. package/dist/host/personalize.d.ts +10 -0
  292. package/dist/host/personalize.js +97 -0
  293. package/dist/host/platform.d.ts +19 -0
  294. package/dist/host/platform.js +126 -0
  295. package/dist/host/project-scan.d.ts +7 -0
  296. package/dist/host/project-scan.js +89 -0
  297. package/dist/host/projects.d.ts +100 -0
  298. package/dist/host/projects.js +147 -0
  299. package/dist/host/repo-guard.d.ts +36 -0
  300. package/dist/host/repo-guard.js +219 -0
  301. package/dist/host/secrets.d.ts +14 -0
  302. package/dist/host/secrets.js +133 -0
  303. package/dist/host/terminal.d.ts +32 -0
  304. package/dist/host/terminal.js +130 -0
  305. package/dist/host/test-guard.d.ts +6 -0
  306. package/dist/host/test-guard.js +15 -0
  307. package/dist/host/window.d.ts +4 -0
  308. package/dist/host/window.js +72 -0
  309. package/dist/host/wsb.d.ts +37 -0
  310. package/dist/host/wsb.js +101 -0
  311. package/dist/runtime/daemon.js +28494 -0
  312. package/dist/runtime/db.js +26387 -0
  313. package/dist/runtime/gitguard.js +84 -0
  314. package/dist/runtime/main.js +28622 -0
  315. package/dist/runtime/view.js +25841 -0
  316. package/dist/selftest/accounts.test.d.ts +2 -0
  317. package/dist/selftest/accounts.test.js +44 -0
  318. package/dist/selftest/agent-commands.test.d.ts +2 -0
  319. package/dist/selftest/agent-commands.test.js +47 -0
  320. package/dist/selftest/channel.test.d.ts +2 -0
  321. package/dist/selftest/channel.test.js +37 -0
  322. package/dist/selftest/cli.test.d.ts +2 -0
  323. package/dist/selftest/cli.test.js +118 -0
  324. package/dist/selftest/cmdline.test.d.ts +2 -0
  325. package/dist/selftest/cmdline.test.js +45 -0
  326. package/dist/selftest/config.test.d.ts +2 -0
  327. package/dist/selftest/config.test.js +38 -0
  328. package/dist/selftest/data.test.d.ts +2 -0
  329. package/dist/selftest/data.test.js +80 -0
  330. package/dist/selftest/detect.test.d.ts +2 -0
  331. package/dist/selftest/detect.test.js +58 -0
  332. package/dist/selftest/fixtures.d.ts +272 -0
  333. package/dist/selftest/fixtures.js +80 -0
  334. package/dist/selftest/generate.test.d.ts +2 -0
  335. package/dist/selftest/generate.test.js +63 -0
  336. package/dist/selftest/git-access.test.d.ts +2 -0
  337. package/dist/selftest/git-access.test.js +26 -0
  338. package/dist/selftest/guest-boot.test.d.ts +2 -0
  339. package/dist/selftest/guest-boot.test.js +76 -0
  340. package/dist/selftest/harness.d.ts +51 -0
  341. package/dist/selftest/harness.js +77 -0
  342. package/dist/selftest/host-sim.test.d.ts +2 -0
  343. package/dist/selftest/host-sim.test.js +93 -0
  344. package/dist/selftest/hostile-input.test.d.ts +2 -0
  345. package/dist/selftest/hostile-input.test.js +54 -0
  346. package/dist/selftest/index.d.ts +8 -0
  347. package/dist/selftest/index.js +155 -0
  348. package/dist/selftest/links.test.d.ts +2 -0
  349. package/dist/selftest/links.test.js +50 -0
  350. package/dist/selftest/live-daemon.test.d.ts +2 -0
  351. package/dist/selftest/live-daemon.test.js +91 -0
  352. package/dist/selftest/live-git.test.d.ts +2 -0
  353. package/dist/selftest/live-git.test.js +60 -0
  354. package/dist/selftest/live-projects.test.d.ts +2 -0
  355. package/dist/selftest/live-projects.test.js +127 -0
  356. package/dist/selftest/live.d.ts +65 -0
  357. package/dist/selftest/live.js +109 -0
  358. package/dist/selftest/local-config.test.d.ts +2 -0
  359. package/dist/selftest/local-config.test.js +107 -0
  360. package/dist/selftest/mirror.test.d.ts +2 -0
  361. package/dist/selftest/mirror.test.js +101 -0
  362. package/dist/selftest/network.test.d.ts +2 -0
  363. package/dist/selftest/network.test.js +28 -0
  364. package/dist/selftest/personalization.test.d.ts +2 -0
  365. package/dist/selftest/personalization.test.js +53 -0
  366. package/dist/selftest/projects.test.d.ts +2 -0
  367. package/dist/selftest/projects.test.js +254 -0
  368. package/dist/selftest/repair.test.d.ts +2 -0
  369. package/dist/selftest/repair.test.js +42 -0
  370. package/dist/selftest/repo-guard.test.d.ts +2 -0
  371. package/dist/selftest/repo-guard.test.js +63 -0
  372. package/dist/selftest/secrets.test.d.ts +2 -0
  373. package/dist/selftest/secrets.test.js +71 -0
  374. package/dist/selftest/setup.test.d.ts +2 -0
  375. package/dist/selftest/setup.test.js +46 -0
  376. package/dist/selftest/suite.d.ts +13 -0
  377. package/dist/selftest/suite.js +1 -0
  378. package/dist/selftest/sync.test.d.ts +2 -0
  379. package/dist/selftest/sync.test.js +94 -0
  380. package/dist/selftest/test-guard.test.d.ts +2 -0
  381. package/dist/selftest/test-guard.test.js +49 -0
  382. package/dist/selftest/toolchains.test.d.ts +2 -0
  383. package/dist/selftest/toolchains.test.js +103 -0
  384. package/dist/selftest/workspace.test.d.ts +2 -0
  385. package/dist/selftest/workspace.test.js +53 -0
  386. package/dist/shared/download.d.ts +60 -0
  387. package/dist/shared/download.js +215 -0
  388. package/dist/shared/guest-paths.d.ts +30 -0
  389. package/dist/shared/guest-paths.js +61 -0
  390. package/dist/shared/netrules.d.ts +18 -0
  391. package/dist/shared/netrules.js +98 -0
  392. package/dist/shared/paths.d.ts +14 -0
  393. package/dist/shared/paths.js +28 -0
  394. package/dist/shared/projects.d.ts +53 -0
  395. package/dist/shared/projects.js +67 -0
  396. package/dist/shared/pty-client.d.ts +86 -0
  397. package/dist/shared/pty-client.js +227 -0
  398. package/dist/shared/rundir.d.ts +39 -0
  399. package/dist/shared/rundir.js +94 -0
  400. package/dist/shared/safe-remove.d.ts +10 -0
  401. package/dist/shared/safe-remove.js +66 -0
  402. package/dist/shared/schema.d.ts +527 -0
  403. package/dist/shared/schema.js +90 -0
  404. package/dist/shared/system.d.ts +15 -0
  405. package/dist/shared/system.js +19 -0
  406. package/dist/shared/test-guard.d.ts +4 -0
  407. package/dist/shared/test-guard.js +37 -0
  408. package/dist/sync/claude-mem.d.ts +8 -0
  409. package/dist/sync/claude-mem.js +79 -0
  410. package/dist/sync/history.d.ts +41 -0
  411. package/dist/sync/history.js +161 -0
  412. package/dist/sync/watcher.d.ts +21 -0
  413. package/dist/sync/watcher.js +135 -0
  414. package/hooks/post-agent/README.txt +1 -0
  415. package/hooks/pre-provision/README.txt +1 -0
  416. package/package.json +91 -4
  417. package/sandbox/bootstrap.ps1 +258 -0
  418. package/sandbox/cpucap.ps1 +51 -0
  419. package/sandbox/gitshim.cs +35 -0
  420. package/sandbox/logon.cmd +18 -0
  421. package/sandbox/openssl.cs +42 -0
  422. package/sandbox/ptyhost.cs +614 -0
  423. package/sandbox/trust.cmd +35 -0
  424. package/sandbox/vswhere.cs +83 -0
  425. package/schemas/config.schema.json +1161 -0
  426. package/schemas/sandbox-config.schema.json +968 -0
@@ -0,0 +1,227 @@
1
+ // Client side of the ptyhost protocol (see sandbox/ptyhost.cs). Used by the window inside the sandbox and by
2
+ // `--terminal` / `attach` on the host, so it only depends on Node built-ins.
3
+ import net from 'node:net';
4
+ export const FrameType = { Hello: 1, Input: 2, Resize: 3, Restart: 4, Ping: 5, Output: 16, Exit: 17, Error: 18, Restarting: 19, Status: 20 };
5
+ /** HELLO flags: control-only connections get no output and never size the console; a query only asks for STATUS. */
6
+ export const HelloFlag = { ControlOnly: 1, Query: 2 };
7
+ /** Viewers ping this often; ptyhost counts a viewer as gone after 15 s of silence (e.g. its terminal tab was closed). */
8
+ export const PING_INTERVAL_MS = 5000;
9
+ /** Ctrl+] — the same detach key telnet uses; Claude Code does not bind it. */
10
+ export const DETACH_KEY = 0x1d;
11
+ export const encodeFrame = (type, payload = Buffer.alloc(0)) => {
12
+ const header = Buffer.alloc(5);
13
+ header.writeUInt8(type, 0);
14
+ header.writeUInt32LE(payload.length, 1);
15
+ return Buffer.concat([header, payload]);
16
+ };
17
+ export const helloFrame = (token, cols, rows, flags = 0) => {
18
+ const head = Buffer.alloc(5);
19
+ head.writeInt16LE(cols, 0);
20
+ head.writeInt16LE(rows, 2);
21
+ head.writeUInt8(flags, 4);
22
+ return encodeFrame(FrameType.Hello, Buffer.concat([head, Buffer.from(token, 'utf8')]));
23
+ };
24
+ export const resizeFrame = (cols, rows) => {
25
+ const payload = Buffer.alloc(4);
26
+ payload.writeInt16LE(cols, 0);
27
+ payload.writeInt16LE(rows, 2);
28
+ return encodeFrame(FrameType.Resize, payload);
29
+ };
30
+ /** Same limit as ptyhost.cs; a peer announcing more is broken or hostile. */
31
+ export const MAX_FRAME_BYTES = 1 << 20;
32
+ /** Splits a TCP byte stream back into frames. */
33
+ export class FrameReader {
34
+ pending = Buffer.alloc(0);
35
+ push(chunk) {
36
+ this.pending = Buffer.concat([this.pending, chunk]);
37
+ const frames = [];
38
+ while (this.pending.length >= 5) {
39
+ const length = this.pending.readUInt32LE(1);
40
+ if (length > MAX_FRAME_BYTES)
41
+ throw new Error('frame too large (' + length + ' bytes)');
42
+ if (this.pending.length < 5 + length)
43
+ break;
44
+ frames.push({ type: this.pending[0], payload: this.pending.subarray(5, 5 + length) });
45
+ this.pending = this.pending.subarray(5 + length);
46
+ }
47
+ return frames;
48
+ }
49
+ }
50
+ /**
51
+ * Removes OSC 52 (clipboard write) from the sandbox's output before it reaches your terminal: an untrusted program
52
+ * must not be able to silently put text into your clipboard. Everything else (colours, titles, links) passes.
53
+ * Stateful, so a sequence split across chunks is still caught.
54
+ */
55
+ export class OutputFilter {
56
+ carry = '';
57
+ push(chunk) {
58
+ let text = (this.carry + chunk.toString('latin1')).replace(/\x1b\]52;[^\x07\x1b]*(\x07|\x1b\\)/g, '');
59
+ this.carry = '';
60
+ const open = text.lastIndexOf('\x1b');
61
+ const tail = open === -1 ? '' : text.slice(open);
62
+ if (tail.length < 1 << 16 && /^\x1b(\](5(2(;[^\x07\x1b]*)?)?)?)?$/.test(tail)) {
63
+ this.carry = tail;
64
+ text = text.slice(0, open);
65
+ }
66
+ return Buffer.from(text, 'latin1');
67
+ }
68
+ }
69
+ const connectOnce = (host, port, timeoutMs) => {
70
+ return new Promise((resolve, reject) => {
71
+ const socket = net.connect({ host, port });
72
+ const timer = setTimeout(() => { socket.destroy(); reject(new Error('timed out connecting to ' + host + ':' + port)); }, timeoutMs);
73
+ socket.once('connect', () => { clearTimeout(timer); socket.setNoDelay(true); resolve(socket); });
74
+ socket.once('error', (e) => { clearTimeout(timer); reject(e); });
75
+ });
76
+ };
77
+ /** Tries every address the sandbox published and returns the first one that answers. */
78
+ export const connect = async (endpoint, timeoutMs = 3000) => {
79
+ const errors = [];
80
+ for (const address of endpoint.addresses) {
81
+ try {
82
+ return await connectOnce(address, endpoint.port, timeoutMs);
83
+ }
84
+ catch (e) {
85
+ errors.push(address + ': ' + (e instanceof Error ? e.message : String(e)));
86
+ }
87
+ }
88
+ throw new Error('Could not reach the sandbox session (' + errors.join('; ') + ')');
89
+ };
90
+ /** Sends one control frame (e.g. RESTART) without taking over the screen. */
91
+ export const sendControl = async (endpoint, type) => {
92
+ const socket = await connect(endpoint);
93
+ await new Promise((resolve) => socket.end(Buffer.concat([helloFrame(endpoint.token, 80, 24, HelloFlag.ControlOnly), encodeFrame(type)]), resolve));
94
+ };
95
+ /**
96
+ * Asks a session's ptyhost who is attached. Only viewers heard from in the last few seconds count, so a terminal that
97
+ * was closed (or a PC that went to sleep) is not reported. null when the session does not answer: an older ptyhost
98
+ * treats the query as a silent control connection, so the caller must not assume anything.
99
+ */
100
+ export const queryViewers = async (endpoint, timeoutMs = 2000) => {
101
+ let socket;
102
+ try {
103
+ socket = await connect(endpoint, timeoutMs);
104
+ }
105
+ catch {
106
+ return null;
107
+ }
108
+ return new Promise((resolve) => {
109
+ const reader = new FrameReader();
110
+ const done = (value) => { clearTimeout(timer); socket.destroy(); resolve(value); };
111
+ const timer = setTimeout(() => done(null), timeoutMs);
112
+ socket.on('data', (chunk) => {
113
+ let frames;
114
+ try {
115
+ frames = reader.push(chunk);
116
+ }
117
+ catch {
118
+ done(null);
119
+ return;
120
+ }
121
+ const status = frames.find((f) => f.type === FrameType.Status && f.payload.length >= 4);
122
+ if (status)
123
+ done({ viewers: status.payload.readInt16LE(0), remote: status.payload.readInt16LE(2) });
124
+ else if (frames.some((f) => f.type === FrameType.Error))
125
+ done(null);
126
+ });
127
+ socket.on('error', () => done(null));
128
+ socket.on('close', () => done(null));
129
+ socket.write(helloFrame(endpoint.token, 80, 24, HelloFlag.Query));
130
+ });
131
+ };
132
+ /**
133
+ * Node on Windows reads keys through the console API, where Backspace is ^H and Ctrl+Backspace is DEL: the reverse of
134
+ * what terminals send. ConPTY reads ^H as Ctrl+Backspace (delete a word), so swap them back.
135
+ */
136
+ export const fixWindowsKeys = (chunk) => {
137
+ if (!chunk.includes(0x08) && !chunk.includes(0x7f))
138
+ return chunk;
139
+ return Buffer.from(chunk.map((b) => (b === 0x08 ? 0x7f : b === 0x7f ? 0x08 : b)));
140
+ };
141
+ /**
142
+ * Bridges this process's terminal to the remote program until it exits, the connection drops, or the user presses
143
+ * the detach key. Restores the terminal before resolving.
144
+ */
145
+ export const runTerminalClient = (socket, token, options = {}) => {
146
+ const stdin = process.stdin;
147
+ const stdout = process.stdout;
148
+ // getWindowSize asks the console every time; columns/rows only change when Node noticed a resize.
149
+ const size = () => { const [c, r] = stdout.isTTY ? stdout.getWindowSize() : [0, 0]; return [c || 120, r || 30]; };
150
+ const swapKeys = process.platform === 'win32' && stdin.isTTY;
151
+ return new Promise((resolve) => {
152
+ let done = false;
153
+ const reader = new FrameReader();
154
+ const filter = new OutputFilter();
155
+ let sent = size();
156
+ let resizeTimer;
157
+ const finish = (result) => {
158
+ if (done)
159
+ return;
160
+ done = true;
161
+ stdin.off('data', onInput);
162
+ stdout.off('resize', onResize);
163
+ clearTimeout(resizeTimer);
164
+ clearInterval(heartbeat);
165
+ clearInterval(sizeWatch);
166
+ if (stdin.isTTY)
167
+ stdin.setRawMode(false);
168
+ stdin.pause();
169
+ socket.destroy();
170
+ stdout.write('\x1b[0m\x1b[?25h\r\n');
171
+ resolve(result);
172
+ };
173
+ const onInput = (chunk) => {
174
+ if (options.detachKey !== undefined && chunk.includes(options.detachKey)) {
175
+ finish({ reason: 'detach' });
176
+ return;
177
+ }
178
+ socket.write(encodeFrame(FrameType.Input, swapKeys ? fixWindowsKeys(chunk) : chunk));
179
+ };
180
+ // Dragging a window edge fires dozens of resizes; each one makes ConPTY reflow and repaint, and repaints racing each
181
+ // other are what left the screen garbled. Wait until the size settles, clear what this terminal reflowed on its own,
182
+ // then let ptyhost repaint everything once at the new size.
183
+ const sendSize = () => {
184
+ const [c, r] = size();
185
+ if (c === sent[0] && r === sent[1])
186
+ return;
187
+ sent = [c, r];
188
+ stdout.write('\x1b[H\x1b[J');
189
+ socket.write(resizeFrame(c, r));
190
+ };
191
+ const onResize = () => { clearTimeout(resizeTimer); resizeTimer = setTimeout(() => { resizeTimer = undefined; sendSize(); }, 120); };
192
+ const heartbeat = setInterval(() => socket.write(encodeFrame(FrameType.Ping)), PING_INTERVAL_MS);
193
+ // Windows does not always report a resize in raw mode, so the size is also checked twice a second.
194
+ const sizeWatch = setInterval(() => { if (!resizeTimer)
195
+ sendSize(); }, 500);
196
+ socket.on('data', (chunk) => {
197
+ let frames;
198
+ try {
199
+ frames = reader.push(chunk);
200
+ }
201
+ catch {
202
+ finish({ reason: 'error', message: 'invalid data from the sandbox' });
203
+ return;
204
+ }
205
+ for (const frame of frames) {
206
+ if (frame.type === FrameType.Output)
207
+ stdout.write(filter.push(frame.payload));
208
+ else if (frame.type === FrameType.Restarting)
209
+ stdout.write('\x1b[2J\x1b[3J\x1b[H');
210
+ else if (frame.type === FrameType.Exit)
211
+ finish({ reason: 'exit', exitCode: frame.payload.length >= 4 ? frame.payload.readInt32LE(0) : 1 });
212
+ else if (frame.type === FrameType.Error)
213
+ finish({ reason: 'error', message: frame.payload.toString('utf8').slice(0, 500).replace(/[\x00-\x1f\x7f]/g, ' ') });
214
+ }
215
+ });
216
+ socket.on('close', () => finish({ reason: 'closed' }));
217
+ socket.on('error', () => finish({ reason: 'closed' }));
218
+ const [c, r] = size();
219
+ stdout.write('\x1b[2J\x1b[3J\x1b[H');
220
+ socket.write(helloFrame(token, c, r));
221
+ if (stdin.isTTY)
222
+ stdin.setRawMode(true);
223
+ stdin.on('data', onInput);
224
+ stdin.resume();
225
+ stdout.on('resize', onResize);
226
+ });
227
+ };
@@ -0,0 +1,39 @@
1
+ import type { z } from 'zod';
2
+ import type { GuestRequestT, GuestResponseT, ProjectStatusT, SandboxStatusT, SessionStatusT } from './schema.js';
3
+ /** Anything bigger than this from the other side is ignored (a compromised sandbox must not exhaust the host). */
4
+ export declare const MAX_MESSAGE_BYTES: number;
5
+ /** Ids become file names, so only a strict alphabet is allowed (no separators, no dots). */
6
+ export declare const safeId: (id: string) => string;
7
+ export declare const runPaths: (dataDir: string) => {
8
+ run: string;
9
+ sandbox: string;
10
+ requests: string;
11
+ responses: string;
12
+ sessions: string;
13
+ projects: string;
14
+ request: (id: string) => string;
15
+ response: (id: string) => string;
16
+ session: (id: string) => string;
17
+ project: (id: string) => string;
18
+ };
19
+ export declare const readJsonFile: <T>(file: string) => T | null;
20
+ /** Reads and validates; a missing, oversized or malformed file is simply absent. */
21
+ export declare const readValid: <S extends z.ZodType>(schema: S, file: string) => z.output<S> | null;
22
+ /**
23
+ * Write to a uniquely named temp file and rename, so a reader on the other side of the mapped folder never sees half a
24
+ * file. The rename is retried briefly: antivirus or the other side's reader can hold the target for a moment.
25
+ */
26
+ export declare const writeJsonAtomic: (file: string, value: unknown) => void;
27
+ /** Same for any text file (two commands at once, or a watcher and a command, never leave a half-written file). */
28
+ export declare const writeFileAtomic: (file: string, text: string) => void;
29
+ export declare const readSandboxStatus: (dataDir: string) => SandboxStatusT | null;
30
+ export declare const readSession: (dataDir: string, id: string) => SessionStatusT | null;
31
+ export declare const readResponse: (dataDir: string, id: string) => GuestResponseT | null;
32
+ export declare const listSessions: (dataDir: string) => SessionStatusT[];
33
+ export declare const readProjectStatus: (dataDir: string, name: string) => ProjectStatusT | null;
34
+ export declare const listProjectStatus: (dataDir: string) => ProjectStatusT[];
35
+ export declare const scanRequests: (dataDir: string) => {
36
+ valid: GuestRequestT[];
37
+ invalid: string[];
38
+ };
39
+ export declare const now: () => string;
@@ -0,0 +1,94 @@
1
+ // The run folder (<data>\run on the host, C:\AgentData\run in the sandbox) is the host <-> sandbox channel. No
2
+ // network needed: boot status, requests (host -> guest) and responses/status (guest -> host) are small JSON files,
3
+ // written atomically and parsed with the channel schemas on read. Anything that does not parse is ignored.
4
+ import fs from 'node:fs';
5
+ import path from 'node:path';
6
+ import { GuestRequest, GuestResponse, Id, ProjectStatus, SandboxStatus, SessionStatus } from './schema.js';
7
+ import { assertTestWritable } from './test-guard.js';
8
+ /** Anything bigger than this from the other side is ignored (a compromised sandbox must not exhaust the host). */
9
+ export const MAX_MESSAGE_BYTES = 8 * 1024 * 1024;
10
+ /** Ids become file names, so only a strict alphabet is allowed (no separators, no dots). */
11
+ export const safeId = (id) => Id.parse(id);
12
+ export const runPaths = (dataDir) => {
13
+ const run = path.join(dataDir, 'run');
14
+ const file = (dir) => (id) => path.join(run, dir, safeId(id) + '.json');
15
+ return {
16
+ run,
17
+ sandbox: path.join(run, 'sandbox.json'),
18
+ requests: path.join(run, 'requests'),
19
+ responses: path.join(run, 'responses'),
20
+ sessions: path.join(run, 'sessions'),
21
+ projects: path.join(run, 'projects'),
22
+ request: file('requests'),
23
+ response: file('responses'),
24
+ session: file('sessions'),
25
+ project: file('projects'),
26
+ };
27
+ };
28
+ export const readJsonFile = (file) => {
29
+ try {
30
+ if (fs.statSync(file).size > MAX_MESSAGE_BYTES)
31
+ return null;
32
+ return JSON.parse(fs.readFileSync(file, 'utf8').replace(/^\uFEFF/, ''));
33
+ }
34
+ catch {
35
+ return null;
36
+ }
37
+ };
38
+ /** Reads and validates; a missing, oversized or malformed file is simply absent. */
39
+ export const readValid = (schema, file) => {
40
+ const parsed = schema.safeParse(readJsonFile(file));
41
+ return parsed.success ? parsed.data : null;
42
+ };
43
+ const pause = (ms) => { Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms); };
44
+ /**
45
+ * Write to a uniquely named temp file and rename, so a reader on the other side of the mapped folder never sees half a
46
+ * file. The rename is retried briefly: antivirus or the other side's reader can hold the target for a moment.
47
+ */
48
+ export const writeJsonAtomic = (file, value) => writeFileAtomic(file, JSON.stringify(value, null, 2) + '\n');
49
+ /** Same for any text file (two commands at once, or a watcher and a command, never leave a half-written file). */
50
+ export const writeFileAtomic = (file, text) => {
51
+ assertTestWritable(file);
52
+ fs.mkdirSync(path.dirname(file), { recursive: true });
53
+ const temp = file + '.' + process.pid + '-' + Math.random().toString(36).slice(2) + '.tmp';
54
+ fs.writeFileSync(temp, text, { encoding: 'utf8', flag: 'wx' });
55
+ for (let attempt = 1;; attempt++) {
56
+ try {
57
+ fs.renameSync(temp, file);
58
+ return;
59
+ }
60
+ catch (e) {
61
+ const code = e.code;
62
+ if (attempt >= 8 || (code !== 'EPERM' && code !== 'EBUSY' && code !== 'EACCES')) {
63
+ fs.rmSync(temp, { force: true });
64
+ throw e;
65
+ }
66
+ pause(50 * attempt);
67
+ }
68
+ }
69
+ };
70
+ /** Message files in a folder (strict names only), validated; invalid ones are reported separately for deletion. */
71
+ const scan = (schema, dir) => {
72
+ if (!fs.existsSync(dir))
73
+ return { valid: [], invalid: [] };
74
+ const valid = [];
75
+ const invalid = [];
76
+ for (const name of fs.readdirSync(dir)) {
77
+ if (name.endsWith('.tmp'))
78
+ continue;
79
+ const message = /^[A-Za-z0-9_-]{1,64}\.json$/.test(name) ? readValid(schema, path.join(dir, name)) : null;
80
+ if (message)
81
+ valid.push(message);
82
+ else
83
+ invalid.push(path.join(dir, name));
84
+ }
85
+ return { valid, invalid };
86
+ };
87
+ export const readSandboxStatus = (dataDir) => readValid(SandboxStatus, runPaths(dataDir).sandbox);
88
+ export const readSession = (dataDir, id) => readValid(SessionStatus, runPaths(dataDir).session(id));
89
+ export const readResponse = (dataDir, id) => readValid(GuestResponse, runPaths(dataDir).response(id));
90
+ export const listSessions = (dataDir) => scan(SessionStatus, runPaths(dataDir).sessions).valid.sort((a, b) => a.startedAt.localeCompare(b.startedAt));
91
+ export const readProjectStatus = (dataDir, name) => readValid(ProjectStatus, runPaths(dataDir).project(name));
92
+ export const listProjectStatus = (dataDir) => scan(ProjectStatus, runPaths(dataDir).projects).valid.slice(0, 64);
93
+ export const scanRequests = (dataDir) => scan(GuestRequest, runPaths(dataDir).requests);
94
+ export const now = () => new Date().toISOString();
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Why `target` may not be deleted, or null when it may. Refused: a relative path, a drive root, a protected folder or
3
+ * any folder that contains one, and anything that is not strictly inside `root`.
4
+ */
5
+ export declare const removeRefusal: (target: string, root: string) => string | null;
6
+ /**
7
+ * Deletes `target` (a folder tree or file) only when it is strictly inside `root` and nothing protected; a link is
8
+ * removed itself, never followed. Throws instead of deleting anything else.
9
+ */
10
+ export declare const safeRemove: (target: string, root: string) => void;
@@ -0,0 +1,66 @@
1
+ // The one way this tool deletes a folder tree. A recursive delete that resolved to the wrong place (an empty
2
+ // variable, a relative path, a planted link) must never be able to take a user profile, a drive or Windows with it.
3
+ import fs from 'node:fs';
4
+ import os from 'node:os';
5
+ import path from 'node:path';
6
+ import { assertTestWritable } from './test-guard.js';
7
+ const norm = (p) => path.resolve(p).replace(/[\\/]+$/, '').toLowerCase();
8
+ const isAncestorOrSame = (parent, child) => { const a = norm(parent); const b = norm(child); return a === b || b.startsWith(a + path.sep); };
9
+ /** Folders no delete may ever reach, or contain: profiles, Windows, program folders. */
10
+ const protectedFolders = () => [
11
+ os.homedir(), process.env.USERPROFILE, process.env.APPDATA, process.env.LOCALAPPDATA, path.join(os.homedir(), 'Documents'), path.join(os.homedir(), 'Desktop'),
12
+ process.env.SystemRoot, process.env.WINDIR, process.env.ProgramFiles, process.env['ProgramFiles(x86)'], process.env.ProgramData, 'C:\\Users', 'C:\\Windows',
13
+ ].filter((p) => typeof p === 'string' && p.trim() !== '');
14
+ /** Folders nothing of ours lives in, so nothing below them may be deleted either. */
15
+ const systemFolders = () => [process.env.SystemRoot, process.env.WINDIR, process.env.ProgramFiles, process.env['ProgramFiles(x86)'], 'C:\\Windows', 'C:\\Program Files', 'C:\\Program Files (x86)']
16
+ .filter((p) => typeof p === 'string' && p.trim() !== '');
17
+ /**
18
+ * Why `target` may not be deleted, or null when it may. Refused: a relative path, a drive root, a protected folder or
19
+ * any folder that contains one, and anything that is not strictly inside `root`.
20
+ */
21
+ export const removeRefusal = (target, root) => {
22
+ if (!target || !path.isAbsolute(target) || !root || !path.isAbsolute(root))
23
+ return 'not an absolute path';
24
+ // \\?\C:\Users and \\.\ spell the same folders in a way the checks below would not recognise.
25
+ if (/^[\\/]{2}[?.][\\/]/.test(target) || /^[\\/]{2}[?.][\\/]/.test(root))
26
+ return 'a device path (\\\\?\\ or \\\\.\\)';
27
+ const t = norm(target);
28
+ if (t === norm(path.parse(t).root))
29
+ return 'a drive root';
30
+ const hit = protectedFolders().find((p) => isAncestorOrSame(t, p));
31
+ if (hit)
32
+ return 'it is, or contains, ' + hit;
33
+ const system = systemFolders().find((p) => isAncestorOrSame(p, t));
34
+ if (system)
35
+ return 'it is inside ' + system;
36
+ if (!t.startsWith(norm(root) + path.sep))
37
+ return 'it is not inside ' + root;
38
+ return null;
39
+ };
40
+ /**
41
+ * Deletes `target` (a folder tree or file) only when it is strictly inside `root` and nothing protected; a link is
42
+ * removed itself, never followed. Throws instead of deleting anything else.
43
+ */
44
+ export const safeRemove = (target, root) => {
45
+ const refusal = removeRefusal(target, root);
46
+ if (refusal)
47
+ throw new Error('Refusing to delete ' + target + ': ' + refusal);
48
+ assertTestWritable(target);
49
+ let stat;
50
+ try {
51
+ stat = fs.lstatSync(target);
52
+ }
53
+ catch {
54
+ return;
55
+ }
56
+ if (stat.isSymbolicLink()) {
57
+ try {
58
+ fs.unlinkSync(target);
59
+ }
60
+ catch {
61
+ fs.rmdirSync(target);
62
+ }
63
+ return;
64
+ }
65
+ fs.rmSync(target, { recursive: true, force: true, maxRetries: 2 });
66
+ };