windows-development-sandbox 1.10.0 → 1.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (378) hide show
  1. package/README.md +64 -17
  2. package/config.example.json +5 -1
  3. package/dist/app/features/accounts/accounts.def.d.ts +122 -0
  4. package/dist/app/features/accounts/accounts.def.js +243 -0
  5. package/dist/app/features/accounts/accounts.run.d.ts +51 -0
  6. package/dist/app/features/accounts/accounts.run.js +125 -0
  7. package/dist/app/features/accounts/index.d.ts +2 -0
  8. package/dist/app/features/accounts/index.js +3 -0
  9. package/dist/app/features/agents/agent-entry.d.ts +17 -0
  10. package/dist/app/features/agents/agent-entry.js +50 -0
  11. package/dist/app/features/agents/agents.def.d.ts +65 -0
  12. package/dist/app/features/agents/agents.def.js +142 -0
  13. package/dist/app/features/agents/agents.run.d.ts +31 -0
  14. package/dist/app/features/agents/agents.run.js +189 -0
  15. package/dist/app/features/agents/index.d.ts +3 -0
  16. package/dist/app/features/agents/index.js +4 -0
  17. package/dist/app/features/apps/apps-rows.d.ts +31 -0
  18. package/dist/app/features/apps/apps-rows.js +73 -0
  19. package/dist/app/features/apps/apps.def.d.ts +181 -0
  20. package/dist/app/features/apps/apps.def.js +264 -0
  21. package/dist/app/features/apps/apps.run.d.ts +58 -0
  22. package/dist/app/features/apps/apps.run.js +76 -0
  23. package/dist/app/features/apps/index.d.ts +3 -0
  24. package/dist/app/features/apps/index.js +4 -0
  25. package/dist/app/features/data/data.def.d.ts +154 -0
  26. package/dist/app/features/data/data.def.js +201 -0
  27. package/dist/app/features/data/data.run.d.ts +46 -0
  28. package/dist/app/features/data/data.run.js +141 -0
  29. package/dist/app/features/data/index.d.ts +2 -0
  30. package/dist/app/features/data/index.js +3 -0
  31. package/dist/app/features/defs.d.ts +952 -4
  32. package/dist/app/features/defs.js +147 -10
  33. package/dist/app/features/engine/engine.def.d.ts +228 -0
  34. package/dist/app/features/engine/engine.def.js +194 -0
  35. package/dist/app/features/engine/engine.run.d.ts +72 -0
  36. package/dist/app/features/engine/engine.run.js +77 -0
  37. package/dist/app/features/engine/index.d.ts +2 -0
  38. package/dist/app/features/engine/index.js +4 -0
  39. package/dist/app/features/files/files.def.d.ts +51 -0
  40. package/dist/app/features/files/files.def.js +38 -0
  41. package/dist/app/features/files/files.run.d.ts +20 -0
  42. package/dist/app/features/files/files.run.js +59 -0
  43. package/dist/app/features/files/index.d.ts +2 -0
  44. package/dist/app/features/files/index.js +3 -0
  45. package/dist/app/features/github/github.def.d.ts +80 -0
  46. package/dist/app/features/github/github.def.js +142 -0
  47. package/dist/app/features/github/github.run.d.ts +36 -0
  48. package/dist/app/features/github/github.run.js +59 -0
  49. package/dist/app/features/github/index.d.ts +2 -0
  50. package/dist/app/features/github/index.js +3 -0
  51. package/dist/app/features/health/health.def.d.ts +275 -0
  52. package/dist/app/features/health/health.def.js +281 -0
  53. package/dist/app/features/health/health.run.d.ts +125 -0
  54. package/dist/app/features/health/health.run.js +204 -0
  55. package/dist/app/features/health/index.d.ts +2 -0
  56. package/dist/app/features/health/index.js +3 -0
  57. package/dist/app/features/logs/index.d.ts +2 -0
  58. package/dist/app/features/logs/index.js +3 -0
  59. package/dist/app/features/logs/logs.def.d.ts +78 -0
  60. package/dist/app/features/logs/logs.def.js +115 -0
  61. package/dist/app/features/logs/logs.run.d.ts +20 -0
  62. package/dist/app/features/logs/logs.run.js +42 -0
  63. package/dist/app/features/projects/index.d.ts +2 -0
  64. package/dist/app/features/projects/index.js +3 -0
  65. package/dist/app/features/projects/projects.def.d.ts +101 -0
  66. package/dist/app/features/projects/projects.def.js +208 -0
  67. package/dist/app/features/projects/projects.run.d.ts +56 -0
  68. package/dist/app/features/projects/projects.run.js +155 -0
  69. package/dist/app/features/sandbox/sandbox.def.js +11 -5
  70. package/dist/app/features/sessions/sessions.def.js +3 -0
  71. package/dist/app/features/settings/categories.def.js +3 -2
  72. package/dist/{cli/menu/settings/share.d.ts → app/features/settings/settings-share.d.ts} +1 -1
  73. package/dist/{cli/menu/settings/share.js → app/features/settings/settings-share.js} +3 -2
  74. package/dist/app/features/settings/settings.def.d.ts +22 -5
  75. package/dist/app/features/settings/settings.def.js +81 -6
  76. package/dist/app/features/settings/settings.run.d.ts +17 -0
  77. package/dist/app/features/settings/settings.run.js +89 -4
  78. package/dist/app/features/storage/index.d.ts +2 -0
  79. package/dist/app/features/storage/index.js +3 -0
  80. package/dist/app/features/storage/storage.def.d.ts +133 -0
  81. package/dist/app/features/storage/storage.def.js +225 -0
  82. package/dist/app/features/storage/storage.run.d.ts +62 -0
  83. package/dist/app/features/storage/storage.run.js +370 -0
  84. package/dist/app/features/updates/index.d.ts +3 -0
  85. package/dist/app/features/updates/index.js +4 -0
  86. package/dist/app/features/updates/update-lines.d.ts +13 -0
  87. package/dist/app/features/updates/update-lines.js +61 -0
  88. package/dist/app/features/updates/updates.def.d.ts +89 -0
  89. package/dist/app/features/updates/updates.def.js +225 -0
  90. package/dist/app/features/updates/updates.run.d.ts +48 -0
  91. package/dist/app/features/updates/updates.run.js +154 -0
  92. package/dist/app/features/vpn/index.d.ts +2 -0
  93. package/dist/app/features/vpn/index.js +3 -0
  94. package/dist/app/features/vpn/vpn.def.d.ts +112 -0
  95. package/dist/app/features/vpn/vpn.def.js +174 -0
  96. package/dist/app/features/vpn/vpn.run.d.ts +37 -0
  97. package/dist/app/features/vpn/vpn.run.js +54 -0
  98. package/dist/app/features/web/index.d.ts +2 -0
  99. package/dist/app/features/web/index.js +3 -0
  100. package/dist/app/features/web/web.def.d.ts +33 -0
  101. package/dist/app/features/web/web.def.js +90 -0
  102. package/dist/app/features/web/web.run.d.ts +24 -0
  103. package/dist/app/features/web/web.run.js +93 -0
  104. package/dist/app/kernel/define.d.ts +10 -1
  105. package/dist/app/kernel/io.d.ts +34 -0
  106. package/dist/app/kernel/io.js +9 -0
  107. package/dist/app/kernel/rpc.d.ts +17 -0
  108. package/dist/app/kernel/text.d.ts +2 -0
  109. package/dist/app/kernel/text.js +7 -0
  110. package/dist/app/kernel/view.d.ts +24 -1
  111. package/dist/app/kernel/view.js +1 -1
  112. package/dist/app/registry.js +74 -1
  113. package/dist/cli/args.js +1 -1
  114. package/dist/cli/commands/context.d.ts +7 -0
  115. package/dist/cli/commands/context.js +29 -2
  116. package/dist/cli/commands/engine.js +5 -58
  117. package/dist/cli/commands/github.d.ts +2 -0
  118. package/dist/cli/commands/github.js +11 -0
  119. package/dist/cli/commands/index.d.ts +3 -5
  120. package/dist/cli/commands/index.js +3 -5
  121. package/dist/cli/commands/launch/launch.js +21 -4
  122. package/dist/cli/commands/launch/running.js +4 -1
  123. package/dist/cli/commands/maintenance/config.js +1 -6
  124. package/dist/cli/commands/maintenance/index.d.ts +0 -1
  125. package/dist/cli/commands/maintenance/index.js +1 -2
  126. package/dist/cli/commands/maintenance/logs.js +27 -32
  127. package/dist/cli/commands/maintenance/migrate.d.ts +0 -8
  128. package/dist/cli/commands/maintenance/migrate.js +2 -44
  129. package/dist/cli/commands/maintenance/update.d.ts +0 -19
  130. package/dist/cli/commands/maintenance/update.js +1 -99
  131. package/dist/cli/commands/projects/index.d.ts +0 -1
  132. package/dist/cli/commands/projects/index.js +0 -1
  133. package/dist/cli/commands/registry.d.ts +1 -1
  134. package/dist/cli/commands/registry.js +29 -11
  135. package/dist/cli/commands/repair/checks/data.js +1 -1
  136. package/dist/cli/commands/repair/checks/hcs.js +28 -1
  137. package/dist/cli/commands/repair/checks/sandbox.js +1 -1
  138. package/dist/cli/commands/repair/health-run.d.ts +30 -0
  139. package/dist/cli/commands/repair/health-run.js +32 -0
  140. package/dist/cli/commands/repair/printer.d.ts +2 -2
  141. package/dist/cli/commands/repair/printer.js +2 -11
  142. package/dist/cli/commands/repair/run.d.ts +1 -21
  143. package/dist/cli/commands/repair/run.js +13 -70
  144. package/dist/cli/commands/storage/index.d.ts +0 -1
  145. package/dist/cli/commands/storage/index.js +0 -1
  146. package/dist/cli/commands/storage/offer.js +6 -2
  147. package/dist/cli/commands/vpn.d.ts +1 -3
  148. package/dist/cli/commands/vpn.js +8 -89
  149. package/dist/cli/commands/web.d.ts +2 -1
  150. package/dist/cli/commands/web.js +14 -78
  151. package/dist/cli/index.js +3 -2
  152. package/dist/cli/manifest.d.ts +16 -153
  153. package/dist/cli/manifest.js +20 -50
  154. package/dist/cli/menu/command-form.js +1 -2
  155. package/dist/cli/menu/io-menu.d.ts +2 -2
  156. package/dist/cli/menu/io-menu.js +6 -4
  157. package/dist/cli/menu/menu.js +1 -1
  158. package/dist/cli/menu/pages/accounts-page.d.ts +5 -17
  159. package/dist/cli/menu/pages/accounts-page.js +28 -170
  160. package/dist/cli/menu/pages/agents-page.d.ts +17 -18
  161. package/dist/cli/menu/pages/agents-page.js +67 -124
  162. package/dist/cli/menu/pages/apps-page.d.ts +15 -8
  163. package/dist/cli/menu/pages/apps-page.js +121 -29
  164. package/dist/cli/menu/pages/list-page.js +10 -1
  165. package/dist/cli/menu/pages/maintenance-page.d.ts +51 -52
  166. package/dist/cli/menu/pages/maintenance-page.js +246 -427
  167. package/dist/cli/menu/pages/sandbox-page.d.ts +3 -5
  168. package/dist/cli/menu/pages/sandbox-page.js +34 -112
  169. package/dist/cli/menu/pages/settings-page.d.ts +21 -3
  170. package/dist/cli/menu/pages/settings-page.js +89 -17
  171. package/dist/cli/menu/render-view.js +2 -1
  172. package/dist/cli/menu/settings/index.d.ts +0 -1
  173. package/dist/cli/menu/settings/index.js +3 -3
  174. package/dist/cli/menu/views.js +28 -0
  175. package/dist/cli/operations/handler.js +7 -3
  176. package/dist/cli/operations/input.d.ts +1 -1
  177. package/dist/cli/operations/input.js +29 -5
  178. package/dist/cli/operations/io-cli.js +9 -1
  179. package/dist/cli/operations/spec.js +8 -2
  180. package/dist/cli/output/render-view.js +2 -0
  181. package/dist/cli/{commands/data/collect.js → services/data-collect.js} +2 -2
  182. package/dist/cli/{commands/data/remove.js → services/data-remove.js} +2 -2
  183. package/dist/cli/services/data-service.d.ts +1 -1
  184. package/dist/cli/services/data-service.js +2 -2
  185. package/dist/cli/services/databases-service.d.ts +5 -0
  186. package/dist/cli/services/databases-service.js +15 -0
  187. package/dist/cli/services/health-service.d.ts +8 -4
  188. package/dist/cli/services/health-service.js +10 -8
  189. package/dist/cli/services/index.d.ts +4 -1
  190. package/dist/cli/services/index.js +4 -1
  191. package/dist/cli/services/logs-service.d.ts +7 -0
  192. package/dist/cli/services/logs-service.js +13 -0
  193. package/dist/cli/services/storage-service.d.ts +19 -0
  194. package/dist/cli/services/storage-service.js +71 -0
  195. package/dist/cli/services/vpn-service.d.ts +6 -4
  196. package/dist/cli/services/vpn-service.js +5 -11
  197. package/dist/cli/services/web-service.d.ts +4 -3
  198. package/dist/cli/services/web-service.js +12 -32
  199. package/dist/core/config/defaults.js +2 -1
  200. package/dist/core/schema/config.d.ts +5 -0
  201. package/dist/core/schema/config.js +2 -0
  202. package/dist/core/schema/github.d.ts +4 -0
  203. package/dist/core/schema/github.js +7 -0
  204. package/dist/core/schema/index.d.ts +1 -0
  205. package/dist/core/schema/index.js +1 -0
  206. package/dist/core/schema/profile.d.ts +1 -0
  207. package/dist/core/schema/profile.js +3 -0
  208. package/dist/core/schema/sandbox.js +3 -3
  209. package/dist/core/schema/toolchains.js +2 -2
  210. package/dist/core/types.d.ts +6 -3
  211. package/dist/guest/boot/boot.js +8 -0
  212. package/dist/guest/daemon/daemon.js +1 -1
  213. package/dist/guest/daemon/sessions.d.ts +3 -2
  214. package/dist/guest/daemon/sessions.js +38 -7
  215. package/dist/guest/governor/core.d.ts +44 -0
  216. package/dist/guest/governor/core.js +124 -0
  217. package/dist/guest/governor/decide.d.ts +46 -18
  218. package/dist/guest/governor/decide.js +136 -82
  219. package/dist/guest/governor/governor.d.ts +2 -38
  220. package/dist/guest/governor/governor.js +33 -113
  221. package/dist/guest/governor/index.d.ts +1 -0
  222. package/dist/guest/governor/index.js +1 -0
  223. package/dist/guest/network/firewall.d.ts +2 -0
  224. package/dist/guest/network/firewall.js +3 -3
  225. package/dist/guest/sessions/viewer.js +5 -1
  226. package/dist/guest/setup/github-token.d.ts +7 -0
  227. package/dist/guest/setup/github-token.js +65 -0
  228. package/dist/guest/toolchains/languages/node.js +11 -1
  229. package/dist/guest/toolchains/native/rust-extras.js +2 -2
  230. package/dist/guest/toolchains/tools/cli.d.ts +8 -0
  231. package/dist/guest/toolchains/tools/cli.js +16 -2
  232. package/dist/guest/vpn/openvpn.d.ts +5 -0
  233. package/dist/guest/vpn/openvpn.js +14 -1
  234. package/dist/guest/vpn/vpn.js +55 -16
  235. package/dist/guest/vpn/wireguard.js +2 -0
  236. package/dist/host/channel/attach.d.ts +1 -0
  237. package/dist/host/channel/attach.js +1 -0
  238. package/dist/host/channel/channel.d.ts +1 -1
  239. package/dist/host/channel/channel.js +2 -2
  240. package/dist/host/engines/hcs/check.d.ts +1 -0
  241. package/dist/host/engines/hcs/check.js +1 -1
  242. package/dist/host/engines/hcs/engine.d.ts +1 -1
  243. package/dist/host/engines/hcs/engine.js +6 -4
  244. package/dist/host/engines/hcs/helper.d.ts +11 -0
  245. package/dist/host/engines/hcs/helper.js +31 -2
  246. package/dist/host/engines/hcs/leftovers.d.ts +42 -0
  247. package/dist/host/engines/hcs/leftovers.js +101 -0
  248. package/dist/host/engines/index.d.ts +1 -0
  249. package/dist/host/engines/index.js +1 -0
  250. package/dist/host/github/deliver.d.ts +13 -0
  251. package/dist/host/github/deliver.js +51 -0
  252. package/dist/host/github/index.d.ts +2 -0
  253. package/dist/host/github/index.js +3 -0
  254. package/dist/host/github/token.d.ts +21 -0
  255. package/dist/host/github/token.js +74 -0
  256. package/dist/host/launch/generate.js +11 -5
  257. package/dist/host/launch/index.d.ts +1 -1
  258. package/dist/host/launch/index.js +1 -1
  259. package/dist/host/launch/session-file.js +1 -2
  260. package/dist/host/launch/wsb-file.d.ts +11 -7
  261. package/dist/host/launch/wsb-file.js +30 -12
  262. package/dist/host/life/watchdog.d.ts +9 -0
  263. package/dist/host/life/watchdog.js +17 -1
  264. package/dist/host/sandbox/tasklist.d.ts +6 -0
  265. package/dist/host/sandbox/tasklist.js +37 -0
  266. package/dist/host/secrets/launch-secrets.d.ts +2 -1
  267. package/dist/host/secrets/launch-secrets.js +4 -2
  268. package/dist/host/vpn/status.js +13 -3
  269. package/dist/host/web/backend.d.ts +1 -3
  270. package/dist/host/web/index.d.ts +2 -1
  271. package/dist/host/web/index.js +2 -1
  272. package/dist/host/web/live.d.ts +23 -0
  273. package/dist/host/web/live.js +107 -0
  274. package/dist/host/web/rpc.d.ts +6 -1
  275. package/dist/host/web/rpc.js +23 -31
  276. package/dist/host/web/runner.d.ts +4 -0
  277. package/dist/host/web/runner.js +12 -1
  278. package/dist/host/web/server.d.ts +30 -2
  279. package/dist/host/web/server.js +87 -29
  280. package/dist/host/web/state.d.ts +1 -0
  281. package/dist/host/web/state.js +2 -0
  282. package/dist/runtime/agent.js +30 -6
  283. package/dist/runtime/daemon.js +323 -176
  284. package/dist/runtime/db.js +30 -6
  285. package/dist/runtime/main.js +375 -76
  286. package/dist/runtime/netproxy.js +30 -6
  287. package/dist/runtime/view.js +495 -146
  288. package/dist/selftest/app.test.js +620 -12
  289. package/dist/selftest/channel.test.js +18 -1
  290. package/dist/selftest/cli.test.js +1 -1
  291. package/dist/selftest/config.test.js +1 -1
  292. package/dist/selftest/contained.test.js +1 -1
  293. package/dist/selftest/data.test.js +1 -2
  294. package/dist/selftest/engine.test.js +3 -1
  295. package/dist/selftest/github.test.d.ts +2 -0
  296. package/dist/selftest/github.test.js +243 -0
  297. package/dist/selftest/hcs.test.js +105 -8
  298. package/dist/selftest/health.test.js +71 -0
  299. package/dist/selftest/heavy-load.test.js +132 -72
  300. package/dist/selftest/index.js +4 -0
  301. package/dist/selftest/layout.test.js +8 -0
  302. package/dist/selftest/live-terminal.test.js +74 -0
  303. package/dist/selftest/menu-screens.js +171 -56
  304. package/dist/selftest/menu.test.js +54 -37
  305. package/dist/selftest/migrate.test.js +14 -12
  306. package/dist/selftest/powershell-variables.test.d.ts +2 -0
  307. package/dist/selftest/powershell-variables.test.js +61 -0
  308. package/dist/selftest/support/engine-golden.js +1 -0
  309. package/dist/selftest/support/fixtures.d.ts +4 -0
  310. package/dist/selftest/support/web-preview.d.ts +1 -0
  311. package/dist/selftest/support/web-preview.js +856 -0
  312. package/dist/selftest/update-service.test.js +15 -8
  313. package/dist/selftest/vpn.test.js +86 -2
  314. package/dist/selftest/web.test.js +58 -11
  315. package/dist/shared/channel/run-dir.d.ts +2 -0
  316. package/dist/shared/channel/run-dir.js +3 -0
  317. package/dist/shared/channel/schema.d.ts +7 -0
  318. package/dist/shared/channel/schema.js +9 -1
  319. package/dist/shared/channel/secrets.d.ts +1 -0
  320. package/dist/shared/channel/secrets.js +3 -0
  321. package/dist/shared/github/index.d.ts +1 -0
  322. package/dist/shared/github/index.js +2 -0
  323. package/dist/shared/github/token.d.ts +29 -0
  324. package/dist/shared/github/token.js +89 -0
  325. package/dist/shared/memory/policy.d.ts +33 -12
  326. package/dist/shared/memory/policy.js +50 -19
  327. package/dist/shared/pty/ctrl-c.d.ts +18 -0
  328. package/dist/shared/pty/ctrl-c.js +36 -0
  329. package/dist/shared/pty/index.d.ts +1 -0
  330. package/dist/shared/pty/index.js +1 -0
  331. package/dist/shared/pty/terminal.d.ts +2 -0
  332. package/dist/shared/pty/terminal.js +21 -2
  333. package/dist/shared/vpn/kill-switch.d.ts +13 -2
  334. package/dist/shared/vpn/kill-switch.js +88 -8
  335. package/dist/shared/web/protocol.d.ts +0 -4
  336. package/dist/sync/watcher.js +1 -1
  337. package/dist/web/index.html +2 -2
  338. package/dist/web/{main-T5DMCHYV.css → main-6JF3ASB5.css} +1 -1
  339. package/dist/web/main-Z645W45E.js +219 -0
  340. package/native/csharp/HcsHost/AssemblyInfo.cs +3 -3
  341. package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
  342. package/package.json +10 -3
  343. package/sandbox/csharp/MemGov.cs +240 -38
  344. package/sandbox/csharp/PtyHost.cs +104 -15
  345. package/sandbox/csharp/SandboxTools/CpuCap.cs +50 -1
  346. package/sandbox/csharp/SandboxTools/Program.cs +1 -1
  347. package/sandbox/scripts/repair-wmi-services.ps1 +26 -0
  348. package/schemas/config.schema.json +19 -5
  349. package/schemas/sandbox-config.schema.json +7 -3
  350. package/dist/cli/commands/accounts.d.ts +0 -2
  351. package/dist/cli/commands/accounts.js +0 -96
  352. package/dist/cli/commands/data/clean.d.ts +0 -3
  353. package/dist/cli/commands/data/clean.js +0 -60
  354. package/dist/cli/commands/data/index.d.ts +0 -4
  355. package/dist/cli/commands/data/index.js +0 -62
  356. package/dist/cli/commands/maintenance/clean.d.ts +0 -2
  357. package/dist/cli/commands/maintenance/clean.js +0 -24
  358. package/dist/cli/commands/maintenance/config-share.d.ts +0 -12
  359. package/dist/cli/commands/maintenance/config-share.js +0 -80
  360. package/dist/cli/commands/projects/projects.d.ts +0 -2
  361. package/dist/cli/commands/projects/projects.js +0 -162
  362. package/dist/cli/commands/storage/contained.d.ts +0 -3
  363. package/dist/cli/commands/storage/contained.js +0 -179
  364. package/dist/cli/commands/storage/storage.d.ts +0 -8
  365. package/dist/cli/commands/storage/storage.js +0 -179
  366. package/dist/cli/menu/add-agent.d.ts +0 -47
  367. package/dist/cli/menu/add-agent.js +0 -168
  368. package/dist/cli/menu/apps.d.ts +0 -69
  369. package/dist/cli/menu/apps.js +0 -214
  370. package/dist/cli/menu/data-folder.d.ts +0 -18
  371. package/dist/cli/menu/data-folder.js +0 -99
  372. package/dist/cli/menu/share-settings.d.ts +0 -21
  373. package/dist/cli/menu/share-settings.js +0 -112
  374. package/dist/cli/menu/vpn-login.d.ts +0 -16
  375. package/dist/cli/menu/vpn-login.js +0 -74
  376. package/dist/web/main-NRRS5O6Z.js +0 -157
  377. /package/dist/cli/{commands/data/collect.d.ts → services/data-collect.d.ts} +0 -0
  378. /package/dist/cli/{commands/data/remove.d.ts → services/data-remove.d.ts} +0 -0
@@ -1363,11 +1363,11 @@ var require_lodash = __commonJS({
1363
1363
  return isFunction(object2[key]);
1364
1364
  });
1365
1365
  }
1366
- function baseGet(object2, path5) {
1367
- path5 = castPath(path5, object2);
1368
- var index = 0, length = path5.length;
1366
+ function baseGet(object2, path10) {
1367
+ path10 = castPath(path10, object2);
1368
+ var index = 0, length = path10.length;
1369
1369
  while (object2 != null && index < length) {
1370
- object2 = object2[toKey(path5[index++])];
1370
+ object2 = object2[toKey(path10[index++])];
1371
1371
  }
1372
1372
  return index && index == length ? object2 : undefined2;
1373
1373
  }
@@ -1431,10 +1431,10 @@ var require_lodash = __commonJS({
1431
1431
  });
1432
1432
  return accumulator;
1433
1433
  }
1434
- function baseInvoke(object2, path5, args) {
1435
- path5 = castPath(path5, object2);
1436
- object2 = parent(object2, path5);
1437
- var func = object2 == null ? object2 : object2[toKey(last(path5))];
1434
+ function baseInvoke(object2, path10, args) {
1435
+ path10 = castPath(path10, object2);
1436
+ object2 = parent(object2, path10);
1437
+ var func = object2 == null ? object2 : object2[toKey(last(path10))];
1438
1438
  return func == null ? undefined2 : apply(func, object2, args);
1439
1439
  }
1440
1440
  function baseIsArguments(value) {
@@ -1590,13 +1590,13 @@ var require_lodash = __commonJS({
1590
1590
  return object2 === source || baseIsMatch(object2, source, matchData);
1591
1591
  };
1592
1592
  }
1593
- function baseMatchesProperty(path5, srcValue) {
1594
- if (isKey(path5) && isStrictComparable(srcValue)) {
1595
- return matchesStrictComparable(toKey(path5), srcValue);
1593
+ function baseMatchesProperty(path10, srcValue) {
1594
+ if (isKey(path10) && isStrictComparable(srcValue)) {
1595
+ return matchesStrictComparable(toKey(path10), srcValue);
1596
1596
  }
1597
1597
  return function(object2) {
1598
- var objValue = get(object2, path5);
1599
- return objValue === undefined2 && objValue === srcValue ? hasIn(object2, path5) : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
1598
+ var objValue = get(object2, path10);
1599
+ return objValue === undefined2 && objValue === srcValue ? hasIn(object2, path10) : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
1600
1600
  };
1601
1601
  }
1602
1602
  function baseMerge(object2, source, srcIndex, customizer, stack) {
@@ -1693,23 +1693,23 @@ var require_lodash = __commonJS({
1693
1693
  });
1694
1694
  }
1695
1695
  function basePick(object2, paths) {
1696
- return basePickBy(object2, paths, function(value, path5) {
1697
- return hasIn(object2, path5);
1696
+ return basePickBy(object2, paths, function(value, path10) {
1697
+ return hasIn(object2, path10);
1698
1698
  });
1699
1699
  }
1700
1700
  function basePickBy(object2, paths, predicate) {
1701
1701
  var index = -1, length = paths.length, result2 = {};
1702
1702
  while (++index < length) {
1703
- var path5 = paths[index], value = baseGet(object2, path5);
1704
- if (predicate(value, path5)) {
1705
- baseSet(result2, castPath(path5, object2), value);
1703
+ var path10 = paths[index], value = baseGet(object2, path10);
1704
+ if (predicate(value, path10)) {
1705
+ baseSet(result2, castPath(path10, object2), value);
1706
1706
  }
1707
1707
  }
1708
1708
  return result2;
1709
1709
  }
1710
- function basePropertyDeep(path5) {
1710
+ function basePropertyDeep(path10) {
1711
1711
  return function(object2) {
1712
- return baseGet(object2, path5);
1712
+ return baseGet(object2, path10);
1713
1713
  };
1714
1714
  }
1715
1715
  function basePullAll(array2, values2, iteratee2, comparator) {
@@ -1783,14 +1783,14 @@ var require_lodash = __commonJS({
1783
1783
  var array2 = values(collection);
1784
1784
  return shuffleSelf(array2, baseClamp(n, 0, array2.length));
1785
1785
  }
1786
- function baseSet(object2, path5, value, customizer) {
1786
+ function baseSet(object2, path10, value, customizer) {
1787
1787
  if (!isObject2(object2)) {
1788
1788
  return object2;
1789
1789
  }
1790
- path5 = castPath(path5, object2);
1791
- var index = -1, length = path5.length, lastIndex = length - 1, nested = object2;
1790
+ path10 = castPath(path10, object2);
1791
+ var index = -1, length = path10.length, lastIndex = length - 1, nested = object2;
1792
1792
  while (nested != null && ++index < length) {
1793
- var key = toKey(path5[index]), newValue = value;
1793
+ var key = toKey(path10[index]), newValue = value;
1794
1794
  if (key === "__proto__" || key === "constructor" || key === "prototype") {
1795
1795
  return object2;
1796
1796
  }
@@ -1798,7 +1798,7 @@ var require_lodash = __commonJS({
1798
1798
  var objValue = nested[key];
1799
1799
  newValue = customizer ? customizer(objValue, key, nested) : undefined2;
1800
1800
  if (newValue === undefined2) {
1801
- newValue = isObject2(objValue) ? objValue : isIndex(path5[index + 1]) ? [] : {};
1801
+ newValue = isObject2(objValue) ? objValue : isIndex(path10[index + 1]) ? [] : {};
1802
1802
  }
1803
1803
  }
1804
1804
  assignValue(nested, key, newValue);
@@ -1964,14 +1964,14 @@ var require_lodash = __commonJS({
1964
1964
  }
1965
1965
  return result2;
1966
1966
  }
1967
- function baseUnset(object2, path5) {
1968
- path5 = castPath(path5, object2);
1969
- var index = -1, length = path5.length;
1967
+ function baseUnset(object2, path10) {
1968
+ path10 = castPath(path10, object2);
1969
+ var index = -1, length = path10.length;
1970
1970
  if (!length) {
1971
1971
  return true;
1972
1972
  }
1973
1973
  while (++index < length) {
1974
- var key = toKey(path5[index]);
1974
+ var key = toKey(path10[index]);
1975
1975
  if (key === "__proto__" && !hasOwnProperty.call(object2, "__proto__")) {
1976
1976
  return false;
1977
1977
  }
@@ -1979,11 +1979,11 @@ var require_lodash = __commonJS({
1979
1979
  return false;
1980
1980
  }
1981
1981
  }
1982
- var obj = parent(object2, path5);
1983
- return obj == null || delete obj[toKey(last(path5))];
1982
+ var obj = parent(object2, path10);
1983
+ return obj == null || delete obj[toKey(last(path10))];
1984
1984
  }
1985
- function baseUpdate(object2, path5, updater, customizer) {
1986
- return baseSet(object2, path5, updater(baseGet(object2, path5)), customizer);
1985
+ function baseUpdate(object2, path10, updater, customizer) {
1986
+ return baseSet(object2, path10, updater(baseGet(object2, path10)), customizer);
1987
1987
  }
1988
1988
  function baseWhile(array2, predicate, isDrop, fromRight) {
1989
1989
  var length = array2.length, index = fromRight ? length : -1;
@@ -2866,11 +2866,11 @@ var require_lodash = __commonJS({
2866
2866
  var match = source.match(reWrapDetails);
2867
2867
  return match ? match[1].split(reSplitDetails) : [];
2868
2868
  }
2869
- function hasPath(object2, path5, hasFunc) {
2870
- path5 = castPath(path5, object2);
2871
- var index = -1, length = path5.length, result2 = false;
2869
+ function hasPath(object2, path10, hasFunc) {
2870
+ path10 = castPath(path10, object2);
2871
+ var index = -1, length = path10.length, result2 = false;
2872
2872
  while (++index < length) {
2873
- var key = toKey(path5[index]);
2873
+ var key = toKey(path10[index]);
2874
2874
  if (!(result2 = object2 != null && hasFunc(object2, key))) {
2875
2875
  break;
2876
2876
  }
@@ -3072,8 +3072,8 @@ var require_lodash = __commonJS({
3072
3072
  return apply(func, this, otherArgs);
3073
3073
  };
3074
3074
  }
3075
- function parent(object2, path5) {
3076
- return path5.length < 2 ? object2 : baseGet(object2, baseSlice(path5, 0, -1));
3075
+ function parent(object2, path10) {
3076
+ return path10.length < 2 ? object2 : baseGet(object2, baseSlice(path10, 0, -1));
3077
3077
  }
3078
3078
  function reorder(array2, indexes) {
3079
3079
  var arrLength = array2.length, length = nativeMin(indexes.length, arrLength), oldArray = copyArray(array2);
@@ -3708,10 +3708,10 @@ var require_lodash = __commonJS({
3708
3708
  }
3709
3709
  return isString(collection) ? fromIndex <= length && collection.indexOf(value, fromIndex) > -1 : !!length && baseIndexOf(collection, value, fromIndex) > -1;
3710
3710
  }
3711
- var invokeMap = baseRest(function(collection, path5, args) {
3712
- var index = -1, isFunc = typeof path5 == "function", result2 = isArrayLike(collection) ? Array2(collection.length) : [];
3711
+ var invokeMap = baseRest(function(collection, path10, args) {
3712
+ var index = -1, isFunc = typeof path10 == "function", result2 = isArrayLike(collection) ? Array2(collection.length) : [];
3713
3713
  baseEach(collection, function(value) {
3714
- result2[++index] = isFunc ? apply(path5, value, args) : baseInvoke(value, path5, args);
3714
+ result2[++index] = isFunc ? apply(path10, value, args) : baseInvoke(value, path10, args);
3715
3715
  });
3716
3716
  return result2;
3717
3717
  });
@@ -4363,15 +4363,15 @@ var require_lodash = __commonJS({
4363
4363
  function functionsIn(object2) {
4364
4364
  return object2 == null ? [] : baseFunctions(object2, keysIn(object2));
4365
4365
  }
4366
- function get(object2, path5, defaultValue) {
4367
- var result2 = object2 == null ? undefined2 : baseGet(object2, path5);
4366
+ function get(object2, path10, defaultValue) {
4367
+ var result2 = object2 == null ? undefined2 : baseGet(object2, path10);
4368
4368
  return result2 === undefined2 ? defaultValue : result2;
4369
4369
  }
4370
- function has(object2, path5) {
4371
- return object2 != null && hasPath(object2, path5, baseHas);
4370
+ function has(object2, path10) {
4371
+ return object2 != null && hasPath(object2, path10, baseHas);
4372
4372
  }
4373
- function hasIn(object2, path5) {
4374
- return object2 != null && hasPath(object2, path5, baseHasIn);
4373
+ function hasIn(object2, path10) {
4374
+ return object2 != null && hasPath(object2, path10, baseHasIn);
4375
4375
  }
4376
4376
  var invert = createInverter(function(result2, value, key) {
4377
4377
  if (value != null && typeof value.toString != "function") {
@@ -4424,10 +4424,10 @@ var require_lodash = __commonJS({
4424
4424
  return result2;
4425
4425
  }
4426
4426
  var isDeep = false;
4427
- paths = arrayMap(paths, function(path5) {
4428
- path5 = castPath(path5, object2);
4429
- isDeep || (isDeep = path5.length > 1);
4430
- return path5;
4427
+ paths = arrayMap(paths, function(path10) {
4428
+ path10 = castPath(path10, object2);
4429
+ isDeep || (isDeep = path10.length > 1);
4430
+ return path10;
4431
4431
  });
4432
4432
  copyObject(object2, getAllKeysIn(object2), result2);
4433
4433
  if (isDeep) {
@@ -4453,19 +4453,19 @@ var require_lodash = __commonJS({
4453
4453
  return [prop];
4454
4454
  });
4455
4455
  predicate = getIteratee(predicate);
4456
- return basePickBy(object2, props, function(value, path5) {
4457
- return predicate(value, path5[0]);
4456
+ return basePickBy(object2, props, function(value, path10) {
4457
+ return predicate(value, path10[0]);
4458
4458
  });
4459
4459
  }
4460
- function result(object2, path5, defaultValue) {
4461
- path5 = castPath(path5, object2);
4462
- var index = -1, length = path5.length;
4460
+ function result(object2, path10, defaultValue) {
4461
+ path10 = castPath(path10, object2);
4462
+ var index = -1, length = path10.length;
4463
4463
  if (!length) {
4464
4464
  length = 1;
4465
4465
  object2 = undefined2;
4466
4466
  }
4467
4467
  while (++index < length) {
4468
- var value = object2 == null ? undefined2 : object2[toKey(path5[index])];
4468
+ var value = object2 == null ? undefined2 : object2[toKey(path10[index])];
4469
4469
  if (value === undefined2) {
4470
4470
  index = length;
4471
4471
  value = defaultValue;
@@ -4474,12 +4474,12 @@ var require_lodash = __commonJS({
4474
4474
  }
4475
4475
  return object2;
4476
4476
  }
4477
- function set2(object2, path5, value) {
4478
- return object2 == null ? object2 : baseSet(object2, path5, value);
4477
+ function set2(object2, path10, value) {
4478
+ return object2 == null ? object2 : baseSet(object2, path10, value);
4479
4479
  }
4480
- function setWith(object2, path5, value, customizer) {
4480
+ function setWith(object2, path10, value, customizer) {
4481
4481
  customizer = typeof customizer == "function" ? customizer : undefined2;
4482
- return object2 == null ? object2 : baseSet(object2, path5, value, customizer);
4482
+ return object2 == null ? object2 : baseSet(object2, path10, value, customizer);
4483
4483
  }
4484
4484
  var toPairs = createToPairs(keys);
4485
4485
  var toPairsIn = createToPairs(keysIn);
@@ -4501,15 +4501,15 @@ var require_lodash = __commonJS({
4501
4501
  });
4502
4502
  return accumulator;
4503
4503
  }
4504
- function unset(object2, path5) {
4505
- return object2 == null ? true : baseUnset(object2, path5);
4504
+ function unset(object2, path10) {
4505
+ return object2 == null ? true : baseUnset(object2, path10);
4506
4506
  }
4507
- function update(object2, path5, updater) {
4508
- return object2 == null ? object2 : baseUpdate(object2, path5, castFunction(updater));
4507
+ function update(object2, path10, updater) {
4508
+ return object2 == null ? object2 : baseUpdate(object2, path10, castFunction(updater));
4509
4509
  }
4510
- function updateWith(object2, path5, updater, customizer) {
4510
+ function updateWith(object2, path10, updater, customizer) {
4511
4511
  customizer = typeof customizer == "function" ? customizer : undefined2;
4512
- return object2 == null ? object2 : baseUpdate(object2, path5, castFunction(updater), customizer);
4512
+ return object2 == null ? object2 : baseUpdate(object2, path10, castFunction(updater), customizer);
4513
4513
  }
4514
4514
  function values(object2) {
4515
4515
  return object2 == null ? [] : baseValues(object2, keys(object2));
@@ -4895,17 +4895,17 @@ var require_lodash = __commonJS({
4895
4895
  function matches(source) {
4896
4896
  return baseMatches(baseClone(source, CLONE_DEEP_FLAG));
4897
4897
  }
4898
- function matchesProperty(path5, srcValue) {
4899
- return baseMatchesProperty(path5, baseClone(srcValue, CLONE_DEEP_FLAG));
4898
+ function matchesProperty(path10, srcValue) {
4899
+ return baseMatchesProperty(path10, baseClone(srcValue, CLONE_DEEP_FLAG));
4900
4900
  }
4901
- var method = baseRest(function(path5, args) {
4901
+ var method = baseRest(function(path10, args) {
4902
4902
  return function(object2) {
4903
- return baseInvoke(object2, path5, args);
4903
+ return baseInvoke(object2, path10, args);
4904
4904
  };
4905
4905
  });
4906
4906
  var methodOf = baseRest(function(object2, args) {
4907
- return function(path5) {
4908
- return baseInvoke(object2, path5, args);
4907
+ return function(path10) {
4908
+ return baseInvoke(object2, path10, args);
4909
4909
  };
4910
4910
  });
4911
4911
  function mixin(object2, source, options) {
@@ -4952,12 +4952,12 @@ var require_lodash = __commonJS({
4952
4952
  var over = createOver(arrayMap);
4953
4953
  var overEvery = createOver(arrayEvery);
4954
4954
  var overSome = createOver(arraySome);
4955
- function property(path5) {
4956
- return isKey(path5) ? baseProperty(toKey(path5)) : basePropertyDeep(path5);
4955
+ function property(path10) {
4956
+ return isKey(path10) ? baseProperty(toKey(path10)) : basePropertyDeep(path10);
4957
4957
  }
4958
4958
  function propertyOf(object2) {
4959
- return function(path5) {
4960
- return object2 == null ? undefined2 : baseGet(object2, path5);
4959
+ return function(path10) {
4960
+ return object2 == null ? undefined2 : baseGet(object2, path10);
4961
4961
  };
4962
4962
  }
4963
4963
  var range = createRange();
@@ -5410,12 +5410,12 @@ var require_lodash = __commonJS({
5410
5410
  LazyWrapper.prototype.findLast = function(predicate) {
5411
5411
  return this.reverse().find(predicate);
5412
5412
  };
5413
- LazyWrapper.prototype.invokeMap = baseRest(function(path5, args) {
5414
- if (typeof path5 == "function") {
5413
+ LazyWrapper.prototype.invokeMap = baseRest(function(path10, args) {
5414
+ if (typeof path10 == "function") {
5415
5415
  return new LazyWrapper(this);
5416
5416
  }
5417
5417
  return this.map(function(value) {
5418
- return baseInvoke(value, path5, args);
5418
+ return baseInvoke(value, path10, args);
5419
5419
  });
5420
5420
  });
5421
5421
  LazyWrapper.prototype.reject = function(predicate) {
@@ -5858,6 +5858,36 @@ function unfinishedSequence(data) {
5858
5858
  return data.length;
5859
5859
  }
5860
5860
 
5861
+ // src/shared/pty/ctrl-c.ts
5862
+ var CTRL_C_CONFIRM_MS = 1500;
5863
+ var CTRL_C_HINT = "Ctrl+C again to send it to the program (Esc stops an agent)";
5864
+ var OSC_TITLE = /\x1b\][02];([^\x07\x1b]{0,256})(?:\x07|\x1b\\)/g;
5865
+ var CtrlCGuard = class {
5866
+ armedAt = Number.NEGATIVE_INFINITY;
5867
+ lastTitle = "";
5868
+ /** What to send for one read from the keyboard: a lone Ctrl+C only when another came just before. */
5869
+ push(chunk, nowMs) {
5870
+ if (chunk.length !== 1 || chunk[0] !== 3) return { send: chunk, held: false };
5871
+ if (nowMs - this.armedAt <= CTRL_C_CONFIRM_MS) {
5872
+ this.armedAt = Number.NEGATIVE_INFINITY;
5873
+ return { send: chunk, held: false };
5874
+ }
5875
+ this.armedAt = nowMs;
5876
+ return { send: Buffer.alloc(0), held: true };
5877
+ }
5878
+ /** Remembers the title the program last set (from its output), to put it back after the hint. */
5879
+ watchOutput(text) {
5880
+ for (const m of text.matchAll(OSC_TITLE)) this.lastTitle = m[1];
5881
+ }
5882
+ /** The escape sequence that shows the hint, and the one that puts the program's title back. */
5883
+ hintTitle() {
5884
+ return "\x1B]0;" + CTRL_C_HINT + "\x07";
5885
+ }
5886
+ restoreTitle() {
5887
+ return "\x1B]0;" + this.lastTitle.replace(/[\x00-\x1f\x7f]/g, "") + "\x07";
5888
+ }
5889
+ };
5890
+
5861
5891
  // src/shared/pty/terminal.ts
5862
5892
  var MOUSE_OFF = "\x1B[?1000l\x1B[?1002l\x1B[?1003l\x1B[?1005l\x1B[?1006l\x1B[?1015l";
5863
5893
  function fixWindowsKeys(chunk) {
@@ -5888,6 +5918,7 @@ function runTerminalClient(socket, token, options = {}) {
5888
5918
  clearInterval(heartbeat);
5889
5919
  clearInterval(sizeWatch);
5890
5920
  clearTimeout(joinTimer);
5921
+ clearTimeout(hintTimer);
5891
5922
  socket.destroy();
5892
5923
  stdout.write("\x1B[0m\x1B[?25h" + MOUSE_OFF + "\r\n");
5893
5924
  void (vtInput?.stop() ?? Promise.resolve()).then(() => {
@@ -5901,11 +5932,23 @@ function runTerminalClient(socket, token, options = {}) {
5901
5932
  const sendInput = (data) => {
5902
5933
  if (data.length && !done) socket.write(encodeFrame(FrameType.Input, swapKeys ? fixWindowsKeys(data) : data));
5903
5934
  };
5935
+ const guard = options.confirmCtrlC ? new CtrlCGuard() : null;
5936
+ let hintTimer;
5904
5937
  const onInput = (chunk) => {
5905
5938
  if (options.detachKey !== void 0 && chunk.includes(options.detachKey)) {
5906
5939
  finish({ reason: "detach" });
5907
5940
  return;
5908
5941
  }
5942
+ if (guard) {
5943
+ const decided = guard.push(chunk, Date.now());
5944
+ clearTimeout(hintTimer);
5945
+ if (decided.held) {
5946
+ stdout.write(guard.hintTitle());
5947
+ hintTimer = setTimeout(() => stdout.write(guard.restoreTitle()), CTRL_C_CONFIRM_MS);
5948
+ return;
5949
+ }
5950
+ if (decided.send.length === 1 && decided.send[0] === 3) stdout.write(guard.restoreTitle());
5951
+ }
5909
5952
  clearTimeout(joinTimer);
5910
5953
  sendInput(joiner.push(chunk));
5911
5954
  if (joiner.holding()) joinTimer = setTimeout(() => sendInput(joiner.flush()), JOIN_MS);
@@ -5938,8 +5981,11 @@ function runTerminalClient(socket, token, options = {}) {
5938
5981
  return;
5939
5982
  }
5940
5983
  for (const frame of frames) {
5941
- if (frame.type === FrameType.Output) stdout.write(filter.push(frame.payload));
5942
- else if (frame.type === FrameType.Console) passthrough = frame.payload.toString("latin1") === "conpty.dll";
5984
+ if (frame.type === FrameType.Output) {
5985
+ const out = filter.push(frame.payload);
5986
+ guard?.watchOutput(out.toString("latin1"));
5987
+ stdout.write(out);
5988
+ } else if (frame.type === FrameType.Console) passthrough = frame.payload.toString("latin1") === "conpty.dll";
5943
5989
  else if (frame.type === FrameType.Restarting) stdout.write(MOUSE_OFF + "\x1B[2J\x1B[3J\x1B[H");
5944
5990
  else if (frame.type === FrameType.Exit)
5945
5991
  finish({ reason: "exit", exitCode: frame.payload.length >= 4 ? frame.payload.readInt32LE(0) : 1 });
@@ -5967,11 +6013,11 @@ function runTerminalClient(socket, token, options = {}) {
5967
6013
  }
5968
6014
 
5969
6015
  // src/guest/runtime/paths.ts
5970
- import path4 from "node:path";
6016
+ import path6 from "node:path";
5971
6017
 
5972
6018
  // src/shared/channel/run-dir.ts
5973
- import fs3 from "node:fs";
5974
- import path3 from "node:path";
6019
+ import fs5 from "node:fs";
6020
+ import path5 from "node:path";
5975
6021
 
5976
6022
  // node_modules/zod/v4/classic/external.js
5977
6023
  var external_exports = {};
@@ -6789,10 +6835,10 @@ function mergeDefs(...defs) {
6789
6835
  function cloneDef(schema) {
6790
6836
  return mergeDefs(schema._zod.def);
6791
6837
  }
6792
- function getElementAtPath(obj, path5) {
6793
- if (!path5)
6838
+ function getElementAtPath(obj, path10) {
6839
+ if (!path10)
6794
6840
  return obj;
6795
- return path5.reduce((acc, key) => acc?.[key], obj);
6841
+ return path10.reduce((acc, key) => acc?.[key], obj);
6796
6842
  }
6797
6843
  function promiseAllObject(promisesObj) {
6798
6844
  const keys = Object.keys(promisesObj);
@@ -7132,11 +7178,11 @@ function explicitlyAborted(x, startIndex = 0) {
7132
7178
  }
7133
7179
  return false;
7134
7180
  }
7135
- function prefixIssues(path5, issues) {
7181
+ function prefixIssues(path10, issues) {
7136
7182
  return issues.map((iss) => {
7137
7183
  var _a3;
7138
7184
  (_a3 = iss).path ?? (_a3.path = []);
7139
- iss.path.unshift(path5);
7185
+ iss.path.unshift(path10);
7140
7186
  return iss;
7141
7187
  });
7142
7188
  }
@@ -7586,16 +7632,16 @@ function flattenError(error62, mapper = (issue2) => issue2.message) {
7586
7632
  }
7587
7633
  function formatError(error62, mapper = (issue2) => issue2.message) {
7588
7634
  const fieldErrors = { _errors: [] };
7589
- const processError = (error63, path5 = []) => {
7635
+ const processError = (error63, path10 = []) => {
7590
7636
  for (const issue2 of error63.issues) {
7591
7637
  if (issue2.code === "invalid_union" && issue2.errors.length) {
7592
- issue2.errors.map((issues) => processError({ issues }, [...path5, ...issue2.path]));
7638
+ issue2.errors.map((issues) => processError({ issues }, [...path10, ...issue2.path]));
7593
7639
  } else if (issue2.code === "invalid_key") {
7594
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
7640
+ processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
7595
7641
  } else if (issue2.code === "invalid_element") {
7596
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
7642
+ processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
7597
7643
  } else {
7598
- const fullpath = [...path5, ...issue2.path];
7644
+ const fullpath = [...path10, ...issue2.path];
7599
7645
  if (fullpath.length === 0) {
7600
7646
  fieldErrors._errors.push(mapper(issue2));
7601
7647
  } else {
@@ -7634,17 +7680,17 @@ function formatError(error62, mapper = (issue2) => issue2.message) {
7634
7680
  }
7635
7681
  function treeifyError(error62, mapper = (issue2) => issue2.message) {
7636
7682
  const result = { errors: [] };
7637
- const processError = (error63, path5 = []) => {
7683
+ const processError = (error63, path10 = []) => {
7638
7684
  var _a3;
7639
7685
  for (const issue2 of error63.issues) {
7640
7686
  if (issue2.code === "invalid_union" && issue2.errors.length) {
7641
- issue2.errors.map((issues) => processError({ issues }, [...path5, ...issue2.path]));
7687
+ issue2.errors.map((issues) => processError({ issues }, [...path10, ...issue2.path]));
7642
7688
  } else if (issue2.code === "invalid_key") {
7643
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
7689
+ processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
7644
7690
  } else if (issue2.code === "invalid_element") {
7645
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
7691
+ processError({ issues: issue2.issues }, [...path10, ...issue2.path]);
7646
7692
  } else {
7647
- const fullpath = [...path5, ...issue2.path];
7693
+ const fullpath = [...path10, ...issue2.path];
7648
7694
  if (fullpath.length === 0) {
7649
7695
  result.errors.push(mapper(issue2));
7650
7696
  continue;
@@ -7683,8 +7729,8 @@ function treeifyError(error62, mapper = (issue2) => issue2.message) {
7683
7729
  }
7684
7730
  function toDotPath(_path) {
7685
7731
  const segs = [];
7686
- const path5 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
7687
- for (const seg of path5) {
7732
+ const path10 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
7733
+ for (const seg of path10) {
7688
7734
  if (typeof seg === "number")
7689
7735
  segs.push(`[${seg}]`);
7690
7736
  else if (typeof seg === "symbol")
@@ -21387,13 +21433,13 @@ function _promise(Class2, innerType) {
21387
21433
  }
21388
21434
  // @__NO_SIDE_EFFECTS__
21389
21435
  function _custom(Class2, fn, _params) {
21390
- const norm = normalizeParams(_params);
21391
- norm.abort ?? (norm.abort = true);
21436
+ const norm2 = normalizeParams(_params);
21437
+ norm2.abort ?? (norm2.abort = true);
21392
21438
  const schema = new Class2({
21393
21439
  type: "custom",
21394
21440
  check: "custom",
21395
21441
  fn,
21396
- ...norm
21442
+ ...norm2
21397
21443
  });
21398
21444
  return schema;
21399
21445
  }
@@ -24786,13 +24832,13 @@ function resolveRef(ref, ctx) {
24786
24832
  if (!ref.startsWith("#")) {
24787
24833
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
24788
24834
  }
24789
- const path5 = ref.slice(1).split("/").filter(Boolean);
24790
- if (path5.length === 0) {
24835
+ const path10 = ref.slice(1).split("/").filter(Boolean);
24836
+ if (path10.length === 0) {
24791
24837
  return ctx.rootSchema;
24792
24838
  }
24793
24839
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
24794
- if (path5[0] === defsKey) {
24795
- const key = path5[1] === void 0 ? void 0 : decodeJSONPointerSegment(path5[1]);
24840
+ if (path10[0] === defsKey) {
24841
+ const key = path10[1] === void 0 ? void 0 : decodeJSONPointerSegment(path10[1]);
24796
24842
  if (!key || !ctx.defs[key]) {
24797
24843
  throw new Error(`Reference not found: ${ref}`);
24798
24844
  }
@@ -25798,6 +25844,9 @@ var AttachSchema = external_exports.strictObject({
25798
25844
  ),
25799
25845
  autoHide: external_exports.boolean().describe(
25800
25846
  "Hide the Windows Sandbox window whenever this terminal attaches; it keeps running (sandbox show brings it back)."
25847
+ ),
25848
+ confirmCtrlC: external_exports.boolean().describe(
25849
+ 'In an attached terminal and the sandbox window, a single Ctrl+C is held back (the title says so) and only a second one within 1.5 seconds reaches the agent: a Ctrl+C meant as "copy" no longer stops it. Esc still stops an agent.'
25801
25850
  )
25802
25851
  });
25803
25852
  var AgentCommandsSchema = external_exports.strictObject({
@@ -25842,7 +25891,9 @@ var SandboxSchema = external_exports.strictObject({
25842
25891
  engine: external_exports.enum(["windows-sandbox", "hcs"]).describe(
25843
25892
  '(alpha) What runs the sandbox. "windows-sandbox" = Windows Sandbox (the default: desktop, Windows Terminal, GPU, clipboard, audio, printers). "hcs" = a headless Hyper-V isolated Server Core container for agents (no desktop, GPU or clipboard); it needs Windows features and an image on this PC (sandbox engine check hcs lists what is missing), and starting it is not enabled yet in this alpha. sandbox engine shows what each engine can do. Yours only: a project file (.sandbox-config.json) cannot set it.'
25844
25893
  ),
25845
- memoryMb: external_exports.union([external_exports.literal("auto"), external_exports.number().int().min(2048)]).describe('Sandbox RAM in MB (>= 2048), or "auto": free RAM minus reserveHostMb, capped at maxMemoryMb.'),
25894
+ memoryMb: external_exports.union([external_exports.literal("auto"), external_exports.number().int().min(2048)]).describe(
25895
+ 'Sandbox RAM in MB (>= 2048), or "auto": free RAM minus reserveHostMb, capped at maxMemoryMb. Never more than this PC can keep in RAM for it (its RAM minus the larger of reserveHostMb and 25 %, 2 GB more with vGPU): a bigger value is lowered.'
25896
+ ),
25846
25897
  maxMemoryMb: external_exports.number().int().positive().describe('Upper limit for memoryMb "auto".'),
25847
25898
  maxMemoryPercent: external_exports.number().int().min(10).max(100).describe(`memoryMb "auto" never takes more than this share of this PC's total RAM (percent).`),
25848
25899
  cpuLimit: external_exports.union([external_exports.literal("none"), external_exports.number().int().min(5).max(100)]).describe(
@@ -25855,10 +25906,10 @@ var SandboxSchema = external_exports.strictObject({
25855
25906
  'Memory always left for this PC when memoryMb is "auto": the sandbox gets at most (free RAM, and RAM plus paging file still unused) minus this.'
25856
25907
  ),
25857
25908
  agentMemoryHeadroomMb: external_exports.union([external_exports.literal("auto"), external_exports.literal("none"), external_exports.number().int().min(0)]).describe(
25858
- 'Memory kept out of the agents reach inside the sandbox, in MB: everything the agents start (their builds, tests, tools) together may use at most the sandbox memory minus this; a runaway parallel build then gets out-of-memory errors in its own session instead of freezing or crashing the whole sandbox. "auto" = the larger of 2048 MB and 10 % of the sandbox memory; "none" = no limit. Yours only: a project file cannot change it.'
25909
+ 'The last resort that keeps the sandbox up, in MB below its commit limit (RAM plus paging file): builds are slowed down long before (sandbox.pressureResponse); only if everything the agents start together would take the sandbox to the very edge of its memory, where Windows inside it would start failing, is a build refused memory instead of Windows. "auto" = the larger of 1536 MB and 3 % of the commit limit; "none" = no backstop. Yours only: a project file cannot change it.'
25859
25910
  ),
25860
25911
  pressureResponse: external_exports.boolean().describe(
25861
- "When the sandbox (or this PC) runs low on memory, slow the heaviest build programs down (lower priority) and, if that is not enough, pause the biggest compiler for a few seconds at a time, so heavy parallel builds slow down instead of closing the sandbox. Never touches the agents themselves. Yours only: a project file cannot change it."
25912
+ "When the sandbox (or this PC) runs low on memory, slow builds down in steps, like a PC that gets slower instead of failing: build programs get lower CPU and memory priority, then less CPU, then compilers take turns (the waiting ones briefly suspended and trimmed to the paging file). Nothing is stopped or killed, and the agents themselves are never touched. Yours only: a project file cannot change it."
25862
25913
  ),
25863
25914
  vGpu: external_exports.boolean().describe(
25864
25915
  "Virtual GPU. Off by default: Microsoft notes it widens the sandbox attack surface. The sandbox then uses this PC's graphics card, and with some graphics drivers heavy use can freeze the whole PC: turn it on only when a program in the sandbox needs the GPU (the mesa toolchain gives software OpenGL without it)."
@@ -26004,7 +26055,7 @@ var ToolchainsSchema = external_exports.strictObject({
26004
26055
  `GNU host: "lld" links with Rust's own lld through MinGW's gcc (much less memory than GNU ld), "gnu" with GNU ld.`
26005
26056
  ),
26006
26057
  linkSlots: external_exports.union([external_exports.literal("auto"), external_exports.number().int().min(1).max(32)]).describe(
26007
- 'GNU host: how many programs may link at the same time in the whole sandbox (other links wait). "auto" = one per 8 GB of sandbox memory, 2 to 4. Several agents linking big programs at once can take Windows down.'
26058
+ 'GNU host: how many programs may link at the same time in the whole sandbox (other links wait). "auto" = one per 3 GB of sandbox memory after 6 GB, 2 to 8 (the memory governor slows links down too when memory runs short).'
26008
26059
  )
26009
26060
  }),
26010
26061
  msvc: external_exports.strictObject({
@@ -26079,7 +26130,7 @@ var ToolchainsSchema = external_exports.strictObject({
26079
26130
  }),
26080
26131
  cli: external_exports.strictObject({
26081
26132
  gh: EnabledSchema.describe(
26082
- 'GitHub CLI (gh). Only with provisioning.git.access "full": gh can push and merge through the GitHub API, past a read-only git. Your PC\'s gh login is never copied; `gh auth login` inside persists (GH_CONFIG_DIR). "auto" = when the project has a .github folder.'
26133
+ 'GitHub CLI (gh). Only with provisioning.git.access "full": gh can push and merge through the GitHub API, past a read-only git. Your PC\'s gh login is never copied; `gh auth login` inside persists (GH_CONFIG_DIR), unless a token you saved for sandboxes is handed over (github.shareToken). "auto" = when the project has a .github folder.'
26083
26134
  ),
26084
26135
  zstd: EnabledSchema.describe('Zstandard (zstd). "auto" = off; set true to get it.'),
26085
26136
  openssl: EnabledSchema.describe(
@@ -26967,6 +27018,13 @@ var VpnSchema = external_exports.strictObject({
26967
27018
  )
26968
27019
  });
26969
27020
 
27021
+ // src/core/schema/github.ts
27022
+ var GithubSchema = external_exports.strictObject({
27023
+ shareToken: external_exports.boolean().describe(
27024
+ 'Give each sandbox the GitHub token you saved with `sandbox github login` (best a fine-grained token limited to some repositories and permissions), so gh and https git work there without logging in. Only with provisioning.git.access "full". The agent in the sandbox can read the token and use it for whatever it allows. A project file (.sandbox-config.json) cannot turn this on.'
27025
+ )
27026
+ });
27027
+
26970
27028
  // src/core/schema/config.ts
26971
27029
  var ConfigSchema = external_exports.strictObject({
26972
27030
  $schema: SchemaRefSchema.optional(),
@@ -26997,6 +27055,7 @@ var ConfigSchema = external_exports.strictObject({
26997
27055
  }),
26998
27056
  network: NetworkSchema,
26999
27057
  vpn: VpnSchema,
27058
+ github: GithubSchema,
27000
27059
  provisioning: ProvisioningSchema,
27001
27060
  downloads: DownloadsSchema,
27002
27061
  toolchains: ToolchainsSchema,
@@ -27159,19 +27218,25 @@ var GuestRequestSchema = external_exports.discriminatedUnion("kind", [
27159
27218
  id: IdSchema,
27160
27219
  reason: Text(300),
27161
27220
  seconds: external_exports.number().int().min(10).max(300),
27221
+ /** "severe": the PC is nearly out of memory; builds go to the governor's last step at once. */
27222
+ level: external_exports.enum(["slow", "severe"]).optional(),
27162
27223
  createdAt: TimeSchema
27163
27224
  })
27164
27225
  ]);
27165
27226
  var PressureStatusSchema = external_exports.object({
27166
27227
  level: external_exports.enum(["ok", "throttled", "suspending"]),
27228
+ /** The governor's dial, 0 (nothing wrong) to 4 (one compiler at a time). */
27229
+ step: external_exports.number().int().min(0).max(4).optional(),
27167
27230
  profile: external_exports.enum(["normal", "gentle"]),
27168
27231
  /** Share of the sandbox's RAM still free and of its commit limit in use (percent). */
27169
27232
  ramFreePercent: external_exports.number().int().min(0).max(100),
27170
27233
  commitPercent: external_exports.number().int().min(0).max(100),
27171
27234
  /** Programs running at lower priority because of it. */
27172
27235
  lowered: external_exports.number().int().min(0).max(1024),
27173
- /** Programs paused right now (name, process id, seconds left). */
27236
+ /** Compilers waiting their turn right now (name, process id, seconds until they may go on). */
27174
27237
  paused: external_exports.array(external_exports.object({ name: Text(64), pid: external_exports.number().int(), seconds: external_exports.number().int().min(0).max(60) })).max(8),
27238
+ /** The CPU share the compilers get together (percent; 100 = no cap). */
27239
+ cpuPercent: external_exports.number().int().min(0).max(100).optional(),
27175
27240
  /** The PC itself asked for slowing down (its memory or CPU is low). */
27176
27241
  pcLow: external_exports.boolean(),
27177
27242
  lastAction: Text(300),
@@ -27215,6 +27280,8 @@ var VpnStatusSchema = external_exports.object({
27215
27280
  state: external_exports.enum(["off", "starting", "up", "failed"]),
27216
27281
  message: Text(2e3),
27217
27282
  killSwitch: external_exports.boolean(),
27283
+ /** A direct connection was tried after the kill switch was applied: false = it still got out. */
27284
+ killSwitchHeld: external_exports.boolean().optional(),
27218
27285
  /** The server's name, e.g. uk2201.nordvpn.com. */
27219
27286
  server: Text(128).optional(),
27220
27287
  /** What the sandbox's traffic looks like from outside, once the tunnel is up. */
@@ -27223,12 +27290,46 @@ var VpnStatusSchema = external_exports.object({
27223
27290
  });
27224
27291
 
27225
27292
  // src/shared/io/json.ts
27293
+ import fs3 from "node:fs";
27294
+
27295
+ // src/shared/test-guard.ts
27226
27296
  import fs2 from "node:fs";
27297
+ import os from "node:os";
27298
+ import path3 from "node:path";
27299
+ function selfTestRunning() {
27300
+ return process.env.AGENT_SANDBOX_SELFTEST === "1";
27301
+ }
27302
+ var canonical = (p) => {
27303
+ let rest = "";
27304
+ let current = path3.resolve(p);
27305
+ for (; ; ) {
27306
+ try {
27307
+ return path3.join(fs2.realpathSync.native(current), rest).toLowerCase();
27308
+ } catch {
27309
+ const parent = path3.dirname(current);
27310
+ if (parent === current) return path3.resolve(p).toLowerCase();
27311
+ rest = path3.join(path3.basename(current), rest);
27312
+ current = parent;
27313
+ }
27314
+ }
27315
+ };
27316
+ function testWriteRefusal(target) {
27317
+ if (!selfTestRunning()) return null;
27318
+ const temp = canonical(os.tmpdir());
27319
+ const t = canonical(target);
27320
+ return t === temp || t.startsWith(temp + path3.sep) ? null : "The self-test refused to change " + target + ": it only works in temp folders, so it can never change this PC.";
27321
+ }
27322
+ function assertTestWritable(target) {
27323
+ const refusal = testWriteRefusal(target);
27324
+ if (refusal) throw new Error(refusal);
27325
+ }
27326
+
27327
+ // src/shared/io/json.ts
27227
27328
  var MAX_MESSAGE_BYTES = 8 * 1024 * 1024;
27228
27329
  function readJsonFile(file2) {
27229
27330
  try {
27230
- if (fs2.statSync(file2).size > MAX_MESSAGE_BYTES) return null;
27231
- return JSON.parse(fs2.readFileSync(file2, "utf8").replace(/^\uFEFF/, ""));
27331
+ if (fs3.statSync(file2).size > MAX_MESSAGE_BYTES) return null;
27332
+ return JSON.parse(fs3.readFileSync(file2, "utf8").replace(/^\uFEFF/, ""));
27232
27333
  } catch {
27233
27334
  return null;
27234
27335
  }
@@ -27238,19 +27339,83 @@ function readValid(schema, file2) {
27238
27339
  return parsed.success ? parsed.data : null;
27239
27340
  }
27240
27341
 
27342
+ // src/shared/io/safe-remove.ts
27343
+ import fs4 from "node:fs";
27344
+ import os2 from "node:os";
27345
+ import path4 from "node:path";
27346
+ var norm = (p) => path4.resolve(p).replace(/[\\/]+$/, "").toLowerCase();
27347
+ var isAncestorOrSame = (parent, child) => {
27348
+ const a = norm(parent);
27349
+ const b = norm(child);
27350
+ return a === b || b.startsWith(a + path4.sep);
27351
+ };
27352
+ var depthBelow = (parent, child) => path4.relative(norm(parent), norm(child)).split(path4.sep).filter(Boolean).length;
27353
+ var protectedFolders = () => [
27354
+ os2.homedir(),
27355
+ process.env.USERPROFILE,
27356
+ process.env.APPDATA,
27357
+ process.env.LOCALAPPDATA,
27358
+ path4.join(os2.homedir(), "Documents"),
27359
+ path4.join(os2.homedir(), "Desktop"),
27360
+ process.env.SystemRoot,
27361
+ process.env.WINDIR,
27362
+ process.env.ProgramFiles,
27363
+ process.env["ProgramFiles(x86)"],
27364
+ process.env.ProgramData,
27365
+ "C:\\Users",
27366
+ "C:\\Windows"
27367
+ ].filter((p) => typeof p === "string" && p.trim() !== "");
27368
+ var present = (paths) => paths.filter((p) => typeof p === "string" && p.trim() !== "");
27369
+ var windowsFolders = () => present([process.env.SystemRoot, process.env.WINDIR, "C:\\Windows"]);
27370
+ var programFolders = () => present([process.env.ProgramFiles, process.env["ProgramFiles(x86)"], "C:\\Program Files", "C:\\Program Files (x86)"]);
27371
+ function removeRefusal(target, root) {
27372
+ if (!target || !path4.isAbsolute(target) || !root || !path4.isAbsolute(root)) return "not an absolute path";
27373
+ if (/^[\\/]{2}[?.][\\/]/.test(target) || /^[\\/]{2}[?.][\\/]/.test(root)) return "a device path (\\\\?\\ or \\\\.\\)";
27374
+ const t = norm(target);
27375
+ if (t === norm(path4.parse(t).root)) return "a drive root";
27376
+ const hit = protectedFolders().find((p) => isAncestorOrSame(t, p));
27377
+ if (hit) return "it is, or contains, " + hit;
27378
+ const windows = windowsFolders().find((p) => isAncestorOrSame(p, t));
27379
+ if (windows) return "it is inside " + windows;
27380
+ const program = programFolders().find((p) => isAncestorOrSame(p, t));
27381
+ if (program && !(isAncestorOrSame(program, root) && depthBelow(program, root) >= 2)) return "it is inside " + program;
27382
+ if (!t.startsWith(norm(root) + path4.sep)) return "it is not inside " + root;
27383
+ return null;
27384
+ }
27385
+ function safeRemove(target, root) {
27386
+ const refusal = removeRefusal(target, root);
27387
+ if (refusal) throw new Error("Refusing to delete " + target + ": " + refusal);
27388
+ assertTestWritable(target);
27389
+ let stat;
27390
+ try {
27391
+ stat = fs4.lstatSync(target);
27392
+ } catch {
27393
+ return;
27394
+ }
27395
+ if (stat.isSymbolicLink()) {
27396
+ try {
27397
+ fs4.unlinkSync(target);
27398
+ } catch {
27399
+ fs4.rmdirSync(target);
27400
+ }
27401
+ return;
27402
+ }
27403
+ fs4.rmSync(target, { recursive: true, force: true, maxRetries: 2 });
27404
+ }
27405
+
27241
27406
  // src/shared/channel/run-dir.ts
27242
27407
  function safeId(id) {
27243
27408
  return IdSchema.parse(id);
27244
27409
  }
27245
27410
  var scan = (schema, dir) => {
27246
- if (!fs3.existsSync(dir)) return { valid: [], invalid: [] };
27411
+ if (!fs5.existsSync(dir)) return { valid: [], invalid: [] };
27247
27412
  const valid = [];
27248
27413
  const invalid = [];
27249
- for (const name of fs3.readdirSync(dir)) {
27414
+ for (const name of fs5.readdirSync(dir)) {
27250
27415
  if (name.endsWith(".tmp")) continue;
27251
- const message = /^[A-Za-z0-9_-]{1,64}\.json$/.test(name) ? readValid(schema, path3.join(dir, name)) : null;
27416
+ const message = /^[A-Za-z0-9_-]{1,64}\.json$/.test(name) ? readValid(schema, path5.join(dir, name)) : null;
27252
27417
  if (message) valid.push(message);
27253
- else invalid.push(path3.join(dir, name));
27418
+ else invalid.push(path5.join(dir, name));
27254
27419
  }
27255
27420
  return { valid, invalid };
27256
27421
  };
@@ -27260,6 +27425,8 @@ var RunDir = class {
27260
27425
  vpnFile;
27261
27426
  /** What the memory governor in the sandbox is doing (pressure.json). */
27262
27427
  pressureFile;
27428
+ /** What the sandbox's programs may really use (budget.json): processors, memory, build jobs, link slots. */
27429
+ budgetFile;
27263
27430
  requestsDir;
27264
27431
  responsesDir;
27265
27432
  sessionsDir;
@@ -27269,31 +27436,32 @@ var RunDir = class {
27269
27436
  /** One-shot secrets the host hands over (see secrets.ts). Next to run, not in it: shared-use users can change run. */
27270
27437
  secretsDir;
27271
27438
  constructor(dataDir2) {
27272
- this.root = path3.join(dataDir2, "run");
27273
- this.sandboxFile = path3.join(this.root, "sandbox.json");
27274
- this.vpnFile = path3.join(this.root, "vpn.json");
27275
- this.pressureFile = path3.join(this.root, "pressure.json");
27276
- this.requestsDir = path3.join(this.root, "requests");
27277
- this.responsesDir = path3.join(this.root, "responses");
27278
- this.sessionsDir = path3.join(this.root, "sessions");
27279
- this.projectsDir = path3.join(this.root, "projects");
27280
- this.auditDir = path3.join(this.root, "audit");
27281
- this.secretsDir = path3.join(dataDir2, "secrets");
27439
+ this.root = path5.join(dataDir2, "run");
27440
+ this.sandboxFile = path5.join(this.root, "sandbox.json");
27441
+ this.vpnFile = path5.join(this.root, "vpn.json");
27442
+ this.pressureFile = path5.join(this.root, "pressure.json");
27443
+ this.budgetFile = path5.join(this.root, "budget.json");
27444
+ this.requestsDir = path5.join(this.root, "requests");
27445
+ this.responsesDir = path5.join(this.root, "responses");
27446
+ this.sessionsDir = path5.join(this.root, "sessions");
27447
+ this.projectsDir = path5.join(this.root, "projects");
27448
+ this.auditDir = path5.join(this.root, "audit");
27449
+ this.secretsDir = path5.join(dataDir2, "secrets");
27282
27450
  }
27283
27451
  requestFile(id) {
27284
- return path3.join(this.requestsDir, safeId(id) + ".json");
27452
+ return path5.join(this.requestsDir, safeId(id) + ".json");
27285
27453
  }
27286
27454
  responseFile(id) {
27287
- return path3.join(this.responsesDir, safeId(id) + ".json");
27455
+ return path5.join(this.responsesDir, safeId(id) + ".json");
27288
27456
  }
27289
27457
  sessionFile(id) {
27290
- return path3.join(this.sessionsDir, safeId(id) + ".json");
27458
+ return path5.join(this.sessionsDir, safeId(id) + ".json");
27291
27459
  }
27292
27460
  projectFile(name) {
27293
- return path3.join(this.projectsDir, safeId(name) + ".json");
27461
+ return path5.join(this.projectsDir, safeId(name) + ".json");
27294
27462
  }
27295
27463
  secretFile(id) {
27296
- return path3.join(this.secretsDir, safeId(id) + ".json");
27464
+ return path5.join(this.secretsDir, safeId(id) + ".json");
27297
27465
  }
27298
27466
  readSandboxStatus() {
27299
27467
  return readValid(SandboxStatusSchema, this.sandboxFile);
@@ -27332,10 +27500,188 @@ var launchDir = process.env.AGENT_LAUNCH_DIR ?? "C:\\AgentLaunch";
27332
27500
  var dataDir = process.env.AGENT_DATA_DIR ?? "C:\\AgentData";
27333
27501
  var hostToolsDir = process.env.AGENT_HOST_TOOLS_DIR ?? "C:\\HostTools";
27334
27502
  var localDir = process.env.AGENT_LOCAL_DIR ?? "C:\\nvm";
27335
- var toolsDir = path4.join(dataDir, "tools");
27336
- var logsDir = path4.join(dataDir, "logs");
27503
+ var toolsDir = path6.join(dataDir, "tools");
27504
+ var logsDir = path6.join(dataDir, "logs");
27337
27505
  var run = new RunDir(dataDir);
27338
27506
 
27507
+ // src/guest/runtime/session.ts
27508
+ import fs8 from "node:fs";
27509
+ import path9 from "node:path";
27510
+
27511
+ // src/shared/download/http.ts
27512
+ var USER_AGENT = "windows-development-sandbox";
27513
+ async function fetchRetry(url2, init = {}, attempts = 5, timeoutMs = 6e4) {
27514
+ let last;
27515
+ for (let i = 1; i <= attempts; i++) {
27516
+ try {
27517
+ const response = await fetch(url2, {
27518
+ ...init,
27519
+ signal: AbortSignal.timeout(timeoutMs),
27520
+ headers: { "User-Agent": USER_AGENT, ...init.headers ?? {} }
27521
+ });
27522
+ if (response.ok) return response;
27523
+ last = new Error("HTTP " + response.status + " for " + url2);
27524
+ if (response.status === 404) break;
27525
+ } catch (e) {
27526
+ last = e;
27527
+ }
27528
+ if (i < attempts) await new Promise((r) => setTimeout(r, 3e3));
27529
+ }
27530
+ throw last instanceof Error ? last : new Error(String(last));
27531
+ }
27532
+
27533
+ // src/shared/download/archive.ts
27534
+ import fs6 from "node:fs";
27535
+ import path7 from "node:path";
27536
+ import crypto from "node:crypto";
27537
+
27538
+ // src/shared/download/spawn.ts
27539
+ import { spawn as spawn2 } from "node:child_process";
27540
+ function spawnAsync(file2, args, options = {}) {
27541
+ return new Promise((resolve, reject) => {
27542
+ const child = spawn2(file2, args, { stdio: "ignore", windowsHide: true, ...options });
27543
+ child.once("error", reject);
27544
+ child.once("close", (code) => resolve(code ?? -1));
27545
+ });
27546
+ }
27547
+
27548
+ // src/shared/download/archive.ts
27549
+ function stagingFolder(destination) {
27550
+ return destination + ".staging-" + crypto.randomBytes(3).toString("hex");
27551
+ }
27552
+ function moveIntoPlace(work, destination) {
27553
+ safeRemove(destination, path7.dirname(destination));
27554
+ fs6.mkdirSync(path7.dirname(destination), { recursive: true });
27555
+ fs6.renameSync(work, destination);
27556
+ }
27557
+ async function extractArchive(archive, destination, members2 = []) {
27558
+ fs6.mkdirSync(destination, { recursive: true });
27559
+ let status = await spawnAsync(SYSTEM.tar(), ["-xf", archive, "-C", destination, ...members2]);
27560
+ if (status !== 0 && /\.(zip|nupkg)$/i.test(archive)) {
27561
+ const zip = archive.endsWith(".zip") ? archive : archive + ".zip";
27562
+ if (zip !== archive) fs6.copyFileSync(archive, zip);
27563
+ status = await spawnAsync(
27564
+ SYSTEM.powershell(),
27565
+ scriptArgs("expand-archive.ps1", ["-Archive", zip, "-Destination", destination])
27566
+ );
27567
+ }
27568
+ if (status !== 0) throw new Error("Could not extract " + archive);
27569
+ }
27570
+ function findFile(root, name, maxDepth = 4) {
27571
+ if (maxDepth < 0 || !fs6.existsSync(root)) return null;
27572
+ const entries = fs6.readdirSync(root, { withFileTypes: true });
27573
+ for (const entry of entries)
27574
+ if (entry.isFile() && entry.name.toLowerCase() === name.toLowerCase()) return path7.join(root, entry.name);
27575
+ for (const entry of entries)
27576
+ if (entry.isDirectory()) {
27577
+ const found = findFile(path7.join(root, entry.name), name, maxDepth - 1);
27578
+ if (found) return found;
27579
+ }
27580
+ return null;
27581
+ }
27582
+
27583
+ // src/shared/download/downloader.ts
27584
+ import fs7 from "node:fs";
27585
+ import path8 from "node:path";
27586
+ import crypto2 from "node:crypto";
27587
+ import { Readable, Transform } from "node:stream";
27588
+ import { pipeline } from "node:stream/promises";
27589
+ var Downloader = class {
27590
+ /** downloads.requireChecksum: refuse anything without an expected hash. The guest sets it from session.json. */
27591
+ requireChecksum = false;
27592
+ watcher = null;
27593
+ /** Reports coarse progress of the downloads that start from now on to `watcher` (null: stop). */
27594
+ watch(watcher) {
27595
+ this.watcher = watcher;
27596
+ }
27597
+ /**
27598
+ * Streams a download to disk, hashing as it goes: big archives (PostgreSQL is ~330 MB) never sit in memory, and the
27599
+ * event loop stays free so other toolchains keep downloading meanwhile. A mismatch (or any failure) leaves no file
27600
+ * behind.
27601
+ */
27602
+ async file(url2, destination, expected = null) {
27603
+ const sums = typeof expected === "string" || expected === null ? { sha256: expected } : expected;
27604
+ if (this.requireChecksum && !sums.sha256?.trim() && !sums.sha512?.trim()) {
27605
+ throw new Error(
27606
+ "Refusing to download " + path8.basename(destination) + " (" + url2 + "): no checksum is published for it, and downloads.requireChecksum is on. Turn that setting off to allow downloads that cannot be verified."
27607
+ );
27608
+ }
27609
+ const response = await fetchRetry(url2, {}, 3, 20 * 60 * 1e3);
27610
+ if (!response.body) throw new Error("Empty response for " + url2);
27611
+ fs7.mkdirSync(path8.dirname(destination), { recursive: true });
27612
+ const checks = ["sha256", "sha512"].flatMap((kind) => {
27613
+ const want = sums[kind]?.trim().toLowerCase();
27614
+ return want ? [{ want, hash: crypto2.createHash(kind) }] : [];
27615
+ });
27616
+ const size = Number(response.headers.get("content-length")) || 0;
27617
+ const report = size > 0 ? this.watcher?.() ?? null : null;
27618
+ let received = 0;
27619
+ let tenth = 0;
27620
+ let reportedAt = Date.now();
27621
+ const tap = new Transform({
27622
+ transform(chunk, _encoding, done) {
27623
+ for (const c of checks) c.hash.update(chunk);
27624
+ if (report) {
27625
+ received += chunk.length;
27626
+ const now = Math.floor(received * 10 / size);
27627
+ if (now !== tenth || Date.now() - reportedAt > 5e3) {
27628
+ tenth = now;
27629
+ reportedAt = Date.now();
27630
+ try {
27631
+ report(Math.min(1, received / size));
27632
+ } catch {
27633
+ }
27634
+ }
27635
+ }
27636
+ done(null, chunk);
27637
+ }
27638
+ });
27639
+ const partial2 = destination + ".part";
27640
+ try {
27641
+ await pipeline(Readable.fromWeb(response.body), tap, fs7.createWriteStream(partial2));
27642
+ if (checks.some((c) => c.hash.digest("hex") !== c.want)) throw new Error("Checksum mismatch for " + url2);
27643
+ fs7.rmSync(destination, { force: true });
27644
+ fs7.renameSync(partial2, destination);
27645
+ } finally {
27646
+ fs7.rmSync(partial2, { force: true });
27647
+ }
27648
+ }
27649
+ /**
27650
+ * Downloads + extracts into `destination` atomically (staging folder, then rename). With `locate`, only the folder
27651
+ * holding that file is kept (`up` folders above it, e.g. locate ruby.exe with up 1 keeps the folder around bin).
27652
+ */
27653
+ async archive(url2, destination, options = {}) {
27654
+ const work = stagingFolder(destination);
27655
+ try {
27656
+ const archive = path8.join(work, options.fileName ?? path8.basename(new URL(url2).pathname));
27657
+ await this.file(url2, archive, { sha256: options.sha256, sha512: options.sha512 });
27658
+ const extracted = path8.join(work, "x");
27659
+ await extractArchive(archive, extracted, options.members);
27660
+ let root = extracted;
27661
+ if (options.locate) {
27662
+ const found = findFile(extracted, options.locate);
27663
+ if (!found) throw new Error(options.locate + " not found in " + url2);
27664
+ root = path8.dirname(found);
27665
+ for (let i = 0; i < (options.up ?? 0) && path8.dirname(root).startsWith(extracted); i++)
27666
+ root = path8.dirname(root);
27667
+ }
27668
+ moveIntoPlace(root, destination);
27669
+ } finally {
27670
+ safeRemove(work, path8.dirname(work));
27671
+ }
27672
+ }
27673
+ };
27674
+ var downloader = new Downloader();
27675
+
27676
+ // src/guest/runtime/session.ts
27677
+ var session = JSON.parse(
27678
+ fs8.readFileSync(path9.join(launchDir, "session.json"), "utf8").replace(/^\uFEFF/, "")
27679
+ );
27680
+ downloader.requireChecksum = session.downloads?.requireChecksum === true;
27681
+ var workspace = process.env.AGENT_WORKSPACE ?? session.workspace;
27682
+ var stateDir = path9.join(dataDir, session.persistAgentState ? "state" : "state-session");
27683
+ var claudeDir = path9.join(stateDir, "claude");
27684
+
27339
27685
  // src/guest/sessions/viewer.ts
27340
27686
  var waitUntilStarted = async (id) => {
27341
27687
  let last = "";
@@ -27351,19 +27697,22 @@ var waitUntilStarted = async (id) => {
27351
27697
  return run.readSession(id);
27352
27698
  };
27353
27699
  async function viewSession(id) {
27354
- const session = await waitUntilStarted(id);
27355
- if (session?.phase === "failed") {
27356
- console.error("Session " + id + " could not start: " + session.message);
27700
+ const session2 = await waitUntilStarted(id);
27701
+ if (session2?.phase === "failed") {
27702
+ console.error("Session " + id + " could not start: " + session2.message);
27357
27703
  await new Promise((r) => setTimeout(r, 3e4));
27358
27704
  return 1;
27359
27705
  }
27360
- if (!session?.attach) {
27706
+ if (!session2?.attach) {
27361
27707
  console.error("Session " + id + " is not running.");
27362
27708
  return 1;
27363
27709
  }
27364
- const socket = await connect({ ...session.attach, addresses: ["127.0.0.1"] });
27365
- const result = await runTerminalClient(socket, session.attach.token, { clipboardWrites: true });
27366
- if (result.reason === "exit") console.log(session.harness + " exited with code " + result.exitCode + ".");
27710
+ const socket = await connect({ ...session2.attach, addresses: ["127.0.0.1"] });
27711
+ const result = await runTerminalClient(socket, session2.attach.token, {
27712
+ clipboardWrites: true,
27713
+ confirmCtrlC: session.attach.confirmCtrlC !== false
27714
+ });
27715
+ if (result.reason === "exit") console.log(session2.harness + " exited with code " + result.exitCode + ".");
27367
27716
  else if (result.reason === "error") console.log("Session error: " + result.message);
27368
27717
  return result.reason === "exit" ? result.exitCode : 1;
27369
27718
  }