apex-code 0.0.1-alpha.0 → 0.0.1-alpha.10

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 (739) hide show
  1. package/CHANGELOG.md +471 -0
  2. package/README.md +74 -680
  3. package/dist/cli/args.d.ts +21 -1
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +119 -15
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/auth-command.d.ts.map +1 -1
  8. package/dist/cli/auth-command.js +3 -3
  9. package/dist/cli/auth-command.js.map +1 -1
  10. package/dist/cli/concurrent-session.d.ts +3 -0
  11. package/dist/cli/concurrent-session.d.ts.map +1 -0
  12. package/dist/cli/concurrent-session.js +13 -0
  13. package/dist/cli/concurrent-session.js.map +1 -0
  14. package/dist/cli/cost-command.d.ts +19 -0
  15. package/dist/cli/cost-command.d.ts.map +1 -0
  16. package/dist/cli/cost-command.js +107 -0
  17. package/dist/cli/cost-command.js.map +1 -0
  18. package/dist/cli/file-processor.d.ts.map +1 -1
  19. package/dist/cli/file-processor.js +2 -1
  20. package/dist/cli/file-processor.js.map +1 -1
  21. package/dist/cli/startup-ui.d.ts +1 -1
  22. package/dist/cli/startup-ui.d.ts.map +1 -1
  23. package/dist/cli/startup-ui.js +1 -2
  24. package/dist/cli/startup-ui.js.map +1 -1
  25. package/dist/cli.d.ts.map +1 -1
  26. package/dist/cli.js +99 -16
  27. package/dist/cli.js.map +1 -1
  28. package/dist/config.d.ts +5 -4
  29. package/dist/config.d.ts.map +1 -1
  30. package/dist/config.js +35 -20
  31. package/dist/config.js.map +1 -1
  32. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  33. package/dist/core/agent-session-runtime.js +2 -0
  34. package/dist/core/agent-session-runtime.js.map +1 -1
  35. package/dist/core/agent-session-services.d.ts +28 -0
  36. package/dist/core/agent-session-services.d.ts.map +1 -1
  37. package/dist/core/agent-session-services.js +140 -4
  38. package/dist/core/agent-session-services.js.map +1 -1
  39. package/dist/core/agent-session.d.ts +121 -9
  40. package/dist/core/agent-session.d.ts.map +1 -1
  41. package/dist/core/agent-session.js +364 -123
  42. package/dist/core/agent-session.js.map +1 -1
  43. package/dist/core/auth-storage.d.ts +4 -1
  44. package/dist/core/auth-storage.d.ts.map +1 -1
  45. package/dist/core/auth-storage.js +17 -14
  46. package/dist/core/auth-storage.js.map +1 -1
  47. package/dist/core/bash-executor.d.ts.map +1 -1
  48. package/dist/core/bash-executor.js +11 -10
  49. package/dist/core/bash-executor.js.map +1 -1
  50. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  51. package/dist/core/compaction/branch-summarization.js +3 -0
  52. package/dist/core/compaction/branch-summarization.js.map +1 -1
  53. package/dist/core/compaction/compaction.d.ts +4 -3
  54. package/dist/core/compaction/compaction.d.ts.map +1 -1
  55. package/dist/core/compaction/compaction.js +41 -32
  56. package/dist/core/compaction/compaction.js.map +1 -1
  57. package/dist/core/context/deferred-schemas.d.ts +92 -0
  58. package/dist/core/context/deferred-schemas.d.ts.map +1 -0
  59. package/dist/core/context/deferred-schemas.js +74 -0
  60. package/dist/core/context/deferred-schemas.js.map +1 -0
  61. package/dist/core/context/eviction.d.ts +47 -0
  62. package/dist/core/context/eviction.d.ts.map +1 -0
  63. package/dist/core/context/eviction.js +83 -0
  64. package/dist/core/context/eviction.js.map +1 -0
  65. package/dist/core/context/pipeline.d.ts +90 -0
  66. package/dist/core/context/pipeline.d.ts.map +1 -0
  67. package/dist/core/context/pipeline.js +109 -0
  68. package/dist/core/context/pipeline.js.map +1 -0
  69. package/dist/core/credential-failover.d.ts +30 -0
  70. package/dist/core/credential-failover.d.ts.map +1 -0
  71. package/dist/core/credential-failover.js +46 -0
  72. package/dist/core/credential-failover.js.map +1 -0
  73. package/dist/core/credential-pool.d.ts +60 -0
  74. package/dist/core/credential-pool.d.ts.map +1 -0
  75. package/dist/core/credential-pool.js +84 -0
  76. package/dist/core/credential-pool.js.map +1 -0
  77. package/dist/core/defaults.d.ts +1 -0
  78. package/dist/core/defaults.d.ts.map +1 -1
  79. package/dist/core/defaults.js +9 -0
  80. package/dist/core/defaults.js.map +1 -1
  81. package/dist/core/delegation/agents.d.ts +15 -0
  82. package/dist/core/delegation/agents.d.ts.map +1 -0
  83. package/dist/core/delegation/agents.js +55 -0
  84. package/dist/core/delegation/agents.js.map +1 -0
  85. package/dist/core/delegation/ceiling.d.ts +29 -0
  86. package/dist/core/delegation/ceiling.d.ts.map +1 -0
  87. package/dist/core/delegation/ceiling.js +34 -0
  88. package/dist/core/delegation/ceiling.js.map +1 -0
  89. package/dist/core/delegation/runtime.d.ts +94 -0
  90. package/dist/core/delegation/runtime.d.ts.map +1 -0
  91. package/dist/core/delegation/runtime.js +117 -0
  92. package/dist/core/delegation/runtime.js.map +1 -0
  93. package/dist/core/durable-state/daemon.d.ts +37 -0
  94. package/dist/core/durable-state/daemon.d.ts.map +1 -0
  95. package/dist/core/durable-state/daemon.js +62 -0
  96. package/dist/core/durable-state/daemon.js.map +1 -0
  97. package/dist/core/durable-state/provenance.d.ts +7 -0
  98. package/dist/core/durable-state/provenance.d.ts.map +1 -0
  99. package/dist/core/durable-state/provenance.js +24 -0
  100. package/dist/core/durable-state/provenance.js.map +1 -0
  101. package/dist/core/durable-state/sqlite.d.ts +84 -0
  102. package/dist/core/durable-state/sqlite.d.ts.map +1 -0
  103. package/dist/core/durable-state/sqlite.js +355 -0
  104. package/dist/core/durable-state/sqlite.js.map +1 -0
  105. package/dist/core/environment.d.ts +12 -0
  106. package/dist/core/environment.d.ts.map +1 -0
  107. package/dist/core/environment.js +69 -0
  108. package/dist/core/environment.js.map +1 -0
  109. package/dist/core/evidence-policy.d.ts +17 -0
  110. package/dist/core/evidence-policy.d.ts.map +1 -0
  111. package/dist/core/evidence-policy.js +25 -0
  112. package/dist/core/evidence-policy.js.map +1 -0
  113. package/dist/core/evidence.d.ts +16 -0
  114. package/dist/core/evidence.d.ts.map +1 -0
  115. package/dist/core/evidence.js +51 -0
  116. package/dist/core/evidence.js.map +1 -0
  117. package/dist/core/experimental.d.ts +4 -0
  118. package/dist/core/experimental.d.ts.map +1 -1
  119. package/dist/core/experimental.js +6 -1
  120. package/dist/core/experimental.js.map +1 -1
  121. package/dist/core/extensions/index.d.ts +2 -2
  122. package/dist/core/extensions/index.d.ts.map +1 -1
  123. package/dist/core/extensions/index.js +1 -1
  124. package/dist/core/extensions/index.js.map +1 -1
  125. package/dist/core/extensions/loader.d.ts.map +1 -1
  126. package/dist/core/extensions/loader.js +115 -48
  127. package/dist/core/extensions/loader.js.map +1 -1
  128. package/dist/core/extensions/types.d.ts +44 -9
  129. package/dist/core/extensions/types.d.ts.map +1 -1
  130. package/dist/core/extensions/types.js +3 -0
  131. package/dist/core/extensions/types.js.map +1 -1
  132. package/dist/core/footer-data-provider.d.ts +1 -1
  133. package/dist/core/footer-data-provider.d.ts.map +1 -1
  134. package/dist/core/footer-data-provider.js +1 -1
  135. package/dist/core/footer-data-provider.js.map +1 -1
  136. package/dist/core/http-dispatcher.d.ts +1 -2
  137. package/dist/core/http-dispatcher.d.ts.map +1 -1
  138. package/dist/core/http-dispatcher.js +2 -17
  139. package/dist/core/http-dispatcher.js.map +1 -1
  140. package/dist/core/http-idle-timeout.d.ts +12 -0
  141. package/dist/core/http-idle-timeout.d.ts.map +1 -0
  142. package/dist/core/http-idle-timeout.js +27 -0
  143. package/dist/core/http-idle-timeout.js.map +1 -0
  144. package/dist/core/index.d.ts +1 -0
  145. package/dist/core/index.d.ts.map +1 -1
  146. package/dist/core/index.js +1 -0
  147. package/dist/core/index.js.map +1 -1
  148. package/dist/core/keybindings.d.ts +38 -13
  149. package/dist/core/keybindings.d.ts.map +1 -1
  150. package/dist/core/keybindings.js +26 -5
  151. package/dist/core/keybindings.js.map +1 -1
  152. package/dist/core/lsp/client.d.ts +78 -0
  153. package/dist/core/lsp/client.d.ts.map +1 -0
  154. package/dist/core/lsp/client.js +494 -0
  155. package/dist/core/lsp/client.js.map +1 -0
  156. package/dist/core/lsp/diagnostics.d.ts +47 -0
  157. package/dist/core/lsp/diagnostics.d.ts.map +1 -0
  158. package/dist/core/lsp/diagnostics.js +224 -0
  159. package/dist/core/lsp/diagnostics.js.map +1 -0
  160. package/dist/core/lsp/pool.d.ts +48 -0
  161. package/dist/core/lsp/pool.d.ts.map +1 -0
  162. package/dist/core/lsp/pool.js +150 -0
  163. package/dist/core/lsp/pool.js.map +1 -0
  164. package/dist/core/lsp/registry.d.ts +49 -0
  165. package/dist/core/lsp/registry.d.ts.map +1 -0
  166. package/dist/core/lsp/registry.js +215 -0
  167. package/dist/core/lsp/registry.js.map +1 -0
  168. package/dist/core/lsp/status.d.ts +23 -0
  169. package/dist/core/lsp/status.d.ts.map +1 -0
  170. package/dist/core/lsp/status.js +35 -0
  171. package/dist/core/lsp/status.js.map +1 -0
  172. package/dist/core/lsp/sync.d.ts +13 -0
  173. package/dist/core/lsp/sync.d.ts.map +1 -0
  174. package/dist/core/lsp/sync.js +71 -0
  175. package/dist/core/lsp/sync.js.map +1 -0
  176. package/dist/core/model-config.d.ts +18 -0
  177. package/dist/core/model-config.d.ts.map +1 -1
  178. package/dist/core/model-config.js +25 -6
  179. package/dist/core/model-config.js.map +1 -1
  180. package/dist/core/model-resolver.d.ts +21 -0
  181. package/dist/core/model-resolver.d.ts.map +1 -1
  182. package/dist/core/model-resolver.js +73 -8
  183. package/dist/core/model-resolver.js.map +1 -1
  184. package/dist/core/model-runtime.d.ts +73 -0
  185. package/dist/core/model-runtime.d.ts.map +1 -1
  186. package/dist/core/model-runtime.js +225 -8
  187. package/dist/core/model-runtime.js.map +1 -1
  188. package/dist/core/models-store.d.ts.map +1 -1
  189. package/dist/core/models-store.js +2 -1
  190. package/dist/core/models-store.js.map +1 -1
  191. package/dist/core/observability/aggregate.d.ts +21 -0
  192. package/dist/core/observability/aggregate.d.ts.map +1 -0
  193. package/dist/core/observability/aggregate.js +36 -0
  194. package/dist/core/observability/aggregate.js.map +1 -0
  195. package/dist/core/observability/otlp.d.ts +66 -0
  196. package/dist/core/observability/otlp.d.ts.map +1 -0
  197. package/dist/core/observability/otlp.js +95 -0
  198. package/dist/core/observability/otlp.js.map +1 -0
  199. package/dist/core/package-manager.d.ts.map +1 -1
  200. package/dist/core/package-manager.js +40 -16
  201. package/dist/core/package-manager.js.map +1 -1
  202. package/dist/core/permissions/gate.d.ts +42 -0
  203. package/dist/core/permissions/gate.d.ts.map +1 -0
  204. package/dist/core/permissions/gate.js +72 -0
  205. package/dist/core/permissions/gate.js.map +1 -0
  206. package/dist/core/permissions/modes.d.ts +18 -0
  207. package/dist/core/permissions/modes.d.ts.map +1 -0
  208. package/dist/core/permissions/modes.js +57 -0
  209. package/dist/core/permissions/modes.js.map +1 -0
  210. package/dist/core/permissions/responder.d.ts +30 -0
  211. package/dist/core/permissions/responder.d.ts.map +1 -0
  212. package/dist/core/permissions/responder.js +32 -0
  213. package/dist/core/permissions/responder.js.map +1 -0
  214. package/dist/core/permissions/rules.d.ts +34 -0
  215. package/dist/core/permissions/rules.d.ts.map +1 -0
  216. package/dist/core/permissions/rules.js +74 -0
  217. package/dist/core/permissions/rules.js.map +1 -0
  218. package/dist/core/permissions/startup.d.ts +45 -0
  219. package/dist/core/permissions/startup.d.ts.map +1 -0
  220. package/dist/core/permissions/startup.js +63 -0
  221. package/dist/core/permissions/startup.js.map +1 -0
  222. package/dist/core/permissions/store.d.ts +114 -0
  223. package/dist/core/permissions/store.d.ts.map +1 -0
  224. package/dist/core/permissions/store.js +229 -0
  225. package/dist/core/permissions/store.js.map +1 -0
  226. package/dist/core/pi-manifest.d.ts.map +1 -1
  227. package/dist/core/pi-manifest.js +2 -1
  228. package/dist/core/pi-manifest.js.map +1 -1
  229. package/dist/core/project-trust.d.ts.map +1 -1
  230. package/dist/core/project-trust.js +1 -1
  231. package/dist/core/project-trust.js.map +1 -1
  232. package/dist/core/provider-attribution.d.ts.map +1 -1
  233. package/dist/core/provider-attribution.js +6 -7
  234. package/dist/core/provider-attribution.js.map +1 -1
  235. package/dist/core/remote-catalog-provider.d.ts +2 -2
  236. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  237. package/dist/core/remote-catalog-provider.js +22 -17
  238. package/dist/core/remote-catalog-provider.js.map +1 -1
  239. package/dist/core/resource-loader.d.ts.map +1 -1
  240. package/dist/core/resource-loader.js +3 -2
  241. package/dist/core/resource-loader.js.map +1 -1
  242. package/dist/core/sandbox/bwrap-arguments.d.ts +52 -0
  243. package/dist/core/sandbox/bwrap-arguments.d.ts.map +1 -0
  244. package/dist/core/sandbox/bwrap-arguments.js +86 -0
  245. package/dist/core/sandbox/bwrap-arguments.js.map +1 -0
  246. package/dist/core/sandbox/child-entry.d.ts +2 -0
  247. package/dist/core/sandbox/child-entry.d.ts.map +1 -0
  248. package/dist/core/sandbox/child-entry.js +22 -0
  249. package/dist/core/sandbox/child-entry.js.map +1 -0
  250. package/dist/core/sandbox/cli-launch.d.ts +88 -0
  251. package/dist/core/sandbox/cli-launch.d.ts.map +1 -0
  252. package/dist/core/sandbox/cli-launch.js +272 -0
  253. package/dist/core/sandbox/cli-launch.js.map +1 -0
  254. package/dist/core/sandbox/cli-supervisor.d.ts +30 -0
  255. package/dist/core/sandbox/cli-supervisor.d.ts.map +1 -0
  256. package/dist/core/sandbox/cli-supervisor.js +123 -0
  257. package/dist/core/sandbox/cli-supervisor.js.map +1 -0
  258. package/dist/core/sandbox/default-hosts.d.ts +28 -0
  259. package/dist/core/sandbox/default-hosts.d.ts.map +1 -0
  260. package/dist/core/sandbox/default-hosts.js +69 -0
  261. package/dist/core/sandbox/default-hosts.js.map +1 -0
  262. package/dist/core/sandbox/full-access.d.ts +28 -0
  263. package/dist/core/sandbox/full-access.d.ts.map +1 -0
  264. package/dist/core/sandbox/full-access.js +63 -0
  265. package/dist/core/sandbox/full-access.js.map +1 -0
  266. package/dist/core/sandbox/git-identity.d.ts +57 -0
  267. package/dist/core/sandbox/git-identity.d.ts.map +1 -0
  268. package/dist/core/sandbox/git-identity.js +78 -0
  269. package/dist/core/sandbox/git-identity.js.map +1 -0
  270. package/dist/core/sandbox/host-approval.d.ts +42 -0
  271. package/dist/core/sandbox/host-approval.d.ts.map +1 -0
  272. package/dist/core/sandbox/host-approval.js +99 -0
  273. package/dist/core/sandbox/host-approval.js.map +1 -0
  274. package/dist/core/sandbox/linux-backend.d.ts +46 -0
  275. package/dist/core/sandbox/linux-backend.d.ts.map +1 -0
  276. package/dist/core/sandbox/linux-backend.js +304 -0
  277. package/dist/core/sandbox/linux-backend.js.map +1 -0
  278. package/dist/core/sandbox/macos-backend.d.ts +28 -0
  279. package/dist/core/sandbox/macos-backend.d.ts.map +1 -0
  280. package/dist/core/sandbox/macos-backend.js +313 -0
  281. package/dist/core/sandbox/macos-backend.js.map +1 -0
  282. package/dist/core/sandbox/network-proxy.d.ts +38 -0
  283. package/dist/core/sandbox/network-proxy.d.ts.map +1 -0
  284. package/dist/core/sandbox/network-proxy.js +153 -0
  285. package/dist/core/sandbox/network-proxy.js.map +1 -0
  286. package/dist/core/sandbox/network-refusal.d.ts +24 -0
  287. package/dist/core/sandbox/network-refusal.d.ts.map +1 -0
  288. package/dist/core/sandbox/network-refusal.js +72 -0
  289. package/dist/core/sandbox/network-refusal.js.map +1 -0
  290. package/dist/core/sandbox/policy.d.ts +40 -0
  291. package/dist/core/sandbox/policy.d.ts.map +1 -0
  292. package/dist/core/sandbox/policy.js +55 -0
  293. package/dist/core/sandbox/policy.js.map +1 -0
  294. package/dist/core/sandbox/profiles.d.ts +25 -0
  295. package/dist/core/sandbox/profiles.d.ts.map +1 -0
  296. package/dist/core/sandbox/profiles.js +23 -0
  297. package/dist/core/sandbox/profiles.js.map +1 -0
  298. package/dist/core/sandbox/rpc/command-client.d.ts +28 -0
  299. package/dist/core/sandbox/rpc/command-client.d.ts.map +1 -0
  300. package/dist/core/sandbox/rpc/command-client.js +86 -0
  301. package/dist/core/sandbox/rpc/command-client.js.map +1 -0
  302. package/dist/core/sandbox/rpc/command-proxy.d.ts +48 -0
  303. package/dist/core/sandbox/rpc/command-proxy.d.ts.map +1 -0
  304. package/dist/core/sandbox/rpc/command-proxy.js +120 -0
  305. package/dist/core/sandbox/rpc/command-proxy.js.map +1 -0
  306. package/dist/core/sandbox/rpc/credential-client.d.ts +20 -0
  307. package/dist/core/sandbox/rpc/credential-client.d.ts.map +1 -0
  308. package/dist/core/sandbox/rpc/credential-client.js +170 -0
  309. package/dist/core/sandbox/rpc/credential-client.js.map +1 -0
  310. package/dist/core/sandbox/rpc/credential-proxy.d.ts +44 -0
  311. package/dist/core/sandbox/rpc/credential-proxy.d.ts.map +1 -0
  312. package/dist/core/sandbox/rpc/credential-proxy.js +287 -0
  313. package/dist/core/sandbox/rpc/credential-proxy.js.map +1 -0
  314. package/dist/core/sandbox/rpc/framing.d.ts +35 -0
  315. package/dist/core/sandbox/rpc/framing.d.ts.map +1 -0
  316. package/dist/core/sandbox/rpc/framing.js +114 -0
  317. package/dist/core/sandbox/rpc/framing.js.map +1 -0
  318. package/dist/core/sandbox/rpc/git-credential-helper.d.ts +40 -0
  319. package/dist/core/sandbox/rpc/git-credential-helper.d.ts.map +1 -0
  320. package/dist/core/sandbox/rpc/git-credential-helper.js +152 -0
  321. package/dist/core/sandbox/rpc/git-credential-helper.js.map +1 -0
  322. package/dist/core/sandbox/rpc/git-credential-proxy.d.ts +48 -0
  323. package/dist/core/sandbox/rpc/git-credential-proxy.d.ts.map +1 -0
  324. package/dist/core/sandbox/rpc/git-credential-proxy.js +142 -0
  325. package/dist/core/sandbox/rpc/git-credential-proxy.js.map +1 -0
  326. package/dist/core/sandbox/supervisor-temp.d.ts +18 -0
  327. package/dist/core/sandbox/supervisor-temp.d.ts.map +1 -0
  328. package/dist/core/sandbox/supervisor-temp.js +21 -0
  329. package/dist/core/sandbox/supervisor-temp.js.map +1 -0
  330. package/dist/core/sandbox/supervisor.d.ts +51 -0
  331. package/dist/core/sandbox/supervisor.d.ts.map +1 -0
  332. package/dist/core/sandbox/supervisor.js +18 -0
  333. package/dist/core/sandbox/supervisor.js.map +1 -0
  334. package/dist/core/sandbox/terminal-handoff.d.ts +45 -0
  335. package/dist/core/sandbox/terminal-handoff.d.ts.map +1 -0
  336. package/dist/core/sandbox/terminal-handoff.js +176 -0
  337. package/dist/core/sandbox/terminal-handoff.js.map +1 -0
  338. package/dist/core/sandbox/terminal-size.d.ts +40 -0
  339. package/dist/core/sandbox/terminal-size.d.ts.map +1 -0
  340. package/dist/core/sandbox/terminal-size.js +105 -0
  341. package/dist/core/sandbox/terminal-size.js.map +1 -0
  342. package/dist/core/sandbox/violations.d.ts +23 -0
  343. package/dist/core/sandbox/violations.d.ts.map +1 -0
  344. package/dist/core/sandbox/violations.js +30 -0
  345. package/dist/core/sandbox/violations.js.map +1 -0
  346. package/dist/core/sdk.d.ts +32 -41
  347. package/dist/core/sdk.d.ts.map +1 -1
  348. package/dist/core/sdk.js +161 -6
  349. package/dist/core/sdk.js.map +1 -1
  350. package/dist/core/session-export.d.ts +4 -0
  351. package/dist/core/session-export.d.ts.map +1 -0
  352. package/dist/core/session-export.js +32 -0
  353. package/dist/core/session-export.js.map +1 -0
  354. package/dist/core/session-lease.d.ts +31 -0
  355. package/dist/core/session-lease.d.ts.map +1 -0
  356. package/dist/core/session-lease.js +138 -0
  357. package/dist/core/session-lease.js.map +1 -0
  358. package/dist/core/session-manager.d.ts +46 -2
  359. package/dist/core/session-manager.d.ts.map +1 -1
  360. package/dist/core/session-manager.js +62 -4
  361. package/dist/core/session-manager.js.map +1 -1
  362. package/dist/core/session-share.d.ts +31 -0
  363. package/dist/core/session-share.d.ts.map +1 -0
  364. package/dist/core/session-share.js +45 -0
  365. package/dist/core/session-share.js.map +1 -0
  366. package/dist/core/settings-diagnostics.d.ts +9 -0
  367. package/dist/core/settings-diagnostics.d.ts.map +1 -0
  368. package/dist/core/settings-diagnostics.js +21 -0
  369. package/dist/core/settings-diagnostics.js.map +1 -0
  370. package/dist/core/settings-manager.d.ts +92 -9
  371. package/dist/core/settings-manager.d.ts.map +1 -1
  372. package/dist/core/settings-manager.js +138 -36
  373. package/dist/core/settings-manager.js.map +1 -1
  374. package/dist/core/skills.d.ts +19 -7
  375. package/dist/core/skills.d.ts.map +1 -1
  376. package/dist/core/skills.js +128 -52
  377. package/dist/core/skills.js.map +1 -1
  378. package/dist/core/slash-commands.d.ts.map +1 -1
  379. package/dist/core/slash-commands.js +5 -2
  380. package/dist/core/slash-commands.js.map +1 -1
  381. package/dist/core/system-prompt.d.ts +2 -2
  382. package/dist/core/system-prompt.d.ts.map +1 -1
  383. package/dist/core/system-prompt.js +59 -68
  384. package/dist/core/system-prompt.js.map +1 -1
  385. package/dist/core/timings.d.ts +1 -1
  386. package/dist/core/timings.d.ts.map +1 -1
  387. package/dist/core/timings.js +3 -2
  388. package/dist/core/timings.js.map +1 -1
  389. package/dist/core/tools/ask-user.d.ts +25 -0
  390. package/dist/core/tools/ask-user.d.ts.map +1 -0
  391. package/dist/core/tools/ask-user.js +49 -0
  392. package/dist/core/tools/ask-user.js.map +1 -0
  393. package/dist/core/tools/bash-command-segments.d.ts +22 -0
  394. package/dist/core/tools/bash-command-segments.d.ts.map +1 -0
  395. package/dist/core/tools/bash-command-segments.js +128 -0
  396. package/dist/core/tools/bash-command-segments.js.map +1 -0
  397. package/dist/core/tools/bash.d.ts +40 -4
  398. package/dist/core/tools/bash.d.ts.map +1 -1
  399. package/dist/core/tools/bash.js +183 -32
  400. package/dist/core/tools/bash.js.map +1 -1
  401. package/dist/core/tools/contract.d.ts +183 -0
  402. package/dist/core/tools/contract.d.ts.map +1 -0
  403. package/dist/core/tools/contract.js +48 -0
  404. package/dist/core/tools/contract.js.map +1 -0
  405. package/dist/core/tools/delegate.d.ts +38 -0
  406. package/dist/core/tools/delegate.d.ts.map +1 -0
  407. package/dist/core/tools/delegate.js +90 -0
  408. package/dist/core/tools/delegate.js.map +1 -0
  409. package/dist/core/tools/diagnostics.d.ts +39 -0
  410. package/dist/core/tools/diagnostics.d.ts.map +1 -0
  411. package/dist/core/tools/diagnostics.js +62 -0
  412. package/dist/core/tools/diagnostics.js.map +1 -0
  413. package/dist/core/tools/edit-diff.d.ts +0 -5
  414. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  415. package/dist/core/tools/edit-diff.js +2 -5
  416. package/dist/core/tools/edit-diff.js.map +1 -1
  417. package/dist/core/tools/edit.d.ts +12 -2
  418. package/dist/core/tools/edit.d.ts.map +1 -1
  419. package/dist/core/tools/edit.js +61 -10
  420. package/dist/core/tools/edit.js.map +1 -1
  421. package/dist/core/tools/find.d.ts +2 -2
  422. package/dist/core/tools/find.d.ts.map +1 -1
  423. package/dist/core/tools/find.js +13 -1
  424. package/dist/core/tools/find.js.map +1 -1
  425. package/dist/core/tools/grep.d.ts +4 -2
  426. package/dist/core/tools/grep.d.ts.map +1 -1
  427. package/dist/core/tools/grep.js +47 -10
  428. package/dist/core/tools/grep.js.map +1 -1
  429. package/dist/core/tools/index.d.ts +51 -6
  430. package/dist/core/tools/index.d.ts.map +1 -1
  431. package/dist/core/tools/index.js +145 -2
  432. package/dist/core/tools/index.js.map +1 -1
  433. package/dist/core/tools/ls.d.ts +4 -2
  434. package/dist/core/tools/ls.d.ts.map +1 -1
  435. package/dist/core/tools/ls.js +17 -1
  436. package/dist/core/tools/ls.js.map +1 -1
  437. package/dist/core/tools/lsp.d.ts +62 -0
  438. package/dist/core/tools/lsp.d.ts.map +1 -0
  439. package/dist/core/tools/lsp.js +216 -0
  440. package/dist/core/tools/lsp.js.map +1 -0
  441. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  442. package/dist/core/tools/output-accumulator.js +1 -1
  443. package/dist/core/tools/output-accumulator.js.map +1 -1
  444. package/dist/core/tools/path-permission.d.ts +18 -0
  445. package/dist/core/tools/path-permission.d.ts.map +1 -0
  446. package/dist/core/tools/path-permission.js +28 -0
  447. package/dist/core/tools/path-permission.js.map +1 -0
  448. package/dist/core/tools/plan-present.d.ts +27 -0
  449. package/dist/core/tools/plan-present.d.ts.map +1 -0
  450. package/dist/core/tools/plan-present.js +55 -0
  451. package/dist/core/tools/plan-present.js.map +1 -0
  452. package/dist/core/tools/powershell.d.ts +16 -0
  453. package/dist/core/tools/powershell.d.ts.map +1 -0
  454. package/dist/core/tools/powershell.js +39 -0
  455. package/dist/core/tools/powershell.js.map +1 -0
  456. package/dist/core/tools/read.d.ts +2 -2
  457. package/dist/core/tools/read.d.ts.map +1 -1
  458. package/dist/core/tools/read.js +14 -0
  459. package/dist/core/tools/read.js.map +1 -1
  460. package/dist/core/tools/skill-search.d.ts +32 -0
  461. package/dist/core/tools/skill-search.d.ts.map +1 -0
  462. package/dist/core/tools/skill-search.js +56 -0
  463. package/dist/core/tools/skill-search.js.map +1 -0
  464. package/dist/core/tools/test.d.ts +34 -0
  465. package/dist/core/tools/test.d.ts.map +1 -0
  466. package/dist/core/tools/test.js +75 -0
  467. package/dist/core/tools/test.js.map +1 -0
  468. package/dist/core/tools/todo-write.d.ts +31 -0
  469. package/dist/core/tools/todo-write.d.ts.map +1 -0
  470. package/dist/core/tools/todo-write.js +51 -0
  471. package/dist/core/tools/todo-write.js.map +1 -0
  472. package/dist/core/tools/tool-definition-wrapper.d.ts +13 -2
  473. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  474. package/dist/core/tools/tool-definition-wrapper.js +11 -1
  475. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  476. package/dist/core/tools/tool-schema.d.ts +22 -0
  477. package/dist/core/tools/tool-schema.d.ts.map +1 -0
  478. package/dist/core/tools/tool-schema.js +45 -0
  479. package/dist/core/tools/tool-schema.js.map +1 -0
  480. package/dist/core/tools/web-fetch.d.ts +26 -0
  481. package/dist/core/tools/web-fetch.d.ts.map +1 -0
  482. package/dist/core/tools/web-fetch.js +62 -0
  483. package/dist/core/tools/web-fetch.js.map +1 -0
  484. package/dist/core/tools/web-search-exa.d.ts +33 -0
  485. package/dist/core/tools/web-search-exa.d.ts.map +1 -0
  486. package/dist/core/tools/web-search-exa.js +128 -0
  487. package/dist/core/tools/web-search-exa.js.map +1 -0
  488. package/dist/core/tools/web-search.d.ts +26 -0
  489. package/dist/core/tools/web-search.d.ts.map +1 -0
  490. package/dist/core/tools/web-search.js +53 -0
  491. package/dist/core/tools/web-search.js.map +1 -0
  492. package/dist/core/tools/write.d.ts +16 -2
  493. package/dist/core/tools/write.d.ts.map +1 -1
  494. package/dist/core/tools/write.js +48 -2
  495. package/dist/core/tools/write.js.map +1 -1
  496. package/dist/core/trust-manager.d.ts.map +1 -1
  497. package/dist/core/trust-manager.js +2 -1
  498. package/dist/core/trust-manager.js.map +1 -1
  499. package/dist/core/usage-performance-store.d.ts +56 -0
  500. package/dist/core/usage-performance-store.d.ts.map +1 -0
  501. package/dist/core/usage-performance-store.js +85 -0
  502. package/dist/core/usage-performance-store.js.map +1 -0
  503. package/dist/core/web-search-provider.d.ts +64 -0
  504. package/dist/core/web-search-provider.d.ts.map +1 -0
  505. package/dist/core/web-search-provider.js +149 -0
  506. package/dist/core/web-search-provider.js.map +1 -0
  507. package/dist/extensions/llama/index.d.ts.map +1 -1
  508. package/dist/extensions/llama/index.js +2 -0
  509. package/dist/extensions/llama/index.js.map +1 -1
  510. package/dist/extensions/llama/provider.d.ts.map +1 -1
  511. package/dist/extensions/llama/provider.js +6 -2
  512. package/dist/extensions/llama/provider.js.map +1 -1
  513. package/dist/index.d.ts +7 -6
  514. package/dist/index.d.ts.map +1 -1
  515. package/dist/index.js +5 -4
  516. package/dist/index.js.map +1 -1
  517. package/dist/main.d.ts +5 -0
  518. package/dist/main.d.ts.map +1 -1
  519. package/dist/main.js +87 -22
  520. package/dist/main.js.map +1 -1
  521. package/dist/migrations.d.ts.map +1 -1
  522. package/dist/migrations.js +6 -5
  523. package/dist/migrations.js.map +1 -1
  524. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  525. package/dist/modes/interactive/components/config-selector.js +9 -6
  526. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  527. package/dist/modes/interactive/components/custom-editor.d.ts +72 -1
  528. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  529. package/dist/modes/interactive/components/custom-editor.js +338 -1
  530. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  531. package/dist/modes/interactive/components/dynamic-border.d.ts +7 -1
  532. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  533. package/dist/modes/interactive/components/dynamic-border.js +11 -2
  534. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  535. package/dist/modes/interactive/components/extension-selector.d.ts +4 -0
  536. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  537. package/dist/modes/interactive/components/extension-selector.js +24 -6
  538. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  539. package/dist/modes/interactive/components/first-time-setup.d.ts +1 -4
  540. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  541. package/dist/modes/interactive/components/first-time-setup.js +17 -41
  542. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  543. package/dist/modes/interactive/components/first-use-hints.d.ts +8 -0
  544. package/dist/modes/interactive/components/first-use-hints.d.ts.map +1 -0
  545. package/dist/modes/interactive/components/first-use-hints.js +22 -0
  546. package/dist/modes/interactive/components/first-use-hints.js.map +1 -0
  547. package/dist/modes/interactive/components/footer.d.ts +23 -1
  548. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  549. package/dist/modes/interactive/components/footer.js +182 -21
  550. package/dist/modes/interactive/components/footer.js.map +1 -1
  551. package/dist/modes/interactive/components/index.d.ts +2 -0
  552. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  553. package/dist/modes/interactive/components/index.js +2 -0
  554. package/dist/modes/interactive/components/index.js.map +1 -1
  555. package/dist/modes/interactive/components/model-selector.d.ts +31 -9
  556. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  557. package/dist/modes/interactive/components/model-selector.js +236 -96
  558. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  559. package/dist/modes/interactive/components/settings-selector.d.ts +25 -5
  560. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  561. package/dist/modes/interactive/components/settings-selector.js +226 -58
  562. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  563. package/dist/modes/interactive/components/settings-submenu.d.ts +72 -0
  564. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -0
  565. package/dist/modes/interactive/components/settings-submenu.js +165 -0
  566. package/dist/modes/interactive/components/settings-submenu.js.map +1 -0
  567. package/dist/modes/interactive/components/splash-header.d.ts +66 -0
  568. package/dist/modes/interactive/components/splash-header.d.ts.map +1 -0
  569. package/dist/modes/interactive/components/splash-header.js +180 -0
  570. package/dist/modes/interactive/components/splash-header.js.map +1 -0
  571. package/dist/modes/interactive/components/thinking-selector.d.ts +15 -3
  572. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  573. package/dist/modes/interactive/components/thinking-selector.js +74 -17
  574. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  575. package/dist/modes/interactive/components/tool-execution.d.ts +16 -1
  576. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  577. package/dist/modes/interactive/components/tool-execution.js +113 -35
  578. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  579. package/dist/modes/interactive/components/tool-panel.d.ts +30 -0
  580. package/dist/modes/interactive/components/tool-panel.d.ts.map +1 -0
  581. package/dist/modes/interactive/components/tool-panel.js +130 -0
  582. package/dist/modes/interactive/components/tool-panel.js.map +1 -0
  583. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  584. package/dist/modes/interactive/external-editor.js +60 -10
  585. package/dist/modes/interactive/external-editor.js.map +1 -1
  586. package/dist/modes/interactive/interactive-mode.d.ts +61 -5
  587. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  588. package/dist/modes/interactive/interactive-mode.js +642 -203
  589. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  590. package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
  591. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
  592. package/dist/modes/interactive/model-catalog-refresh.js +34 -0
  593. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
  594. package/dist/modes/interactive/theme/apex.json +93 -0
  595. package/dist/modes/interactive/theme/dark.json +2 -0
  596. package/dist/modes/interactive/theme/light.json +3 -1
  597. package/dist/modes/interactive/theme/theme-controller.d.ts +10 -2
  598. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  599. package/dist/modes/interactive/theme/theme-controller.js +25 -11
  600. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  601. package/dist/modes/interactive/theme/theme-schema.json +11 -3
  602. package/dist/modes/interactive/theme/theme.d.ts +14 -3
  603. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  604. package/dist/modes/interactive/theme/theme.js +65 -10
  605. package/dist/modes/interactive/theme/theme.js.map +1 -1
  606. package/dist/modes/json-event.d.ts +18 -12
  607. package/dist/modes/json-event.d.ts.map +1 -1
  608. package/dist/modes/json-event.js +22 -5
  609. package/dist/modes/json-event.js.map +1 -1
  610. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  611. package/dist/modes/rpc/rpc-mode.js +2 -1
  612. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  613. package/dist/package-manager-cli.d.ts +1 -0
  614. package/dist/package-manager-cli.d.ts.map +1 -1
  615. package/dist/package-manager-cli.js +211 -14
  616. package/dist/package-manager-cli.js.map +1 -1
  617. package/dist/rpc-entry.d.ts.map +1 -1
  618. package/dist/rpc-entry.js +2 -1
  619. package/dist/rpc-entry.js.map +1 -1
  620. package/dist/server/create-harness.d.ts +1 -1
  621. package/dist/server/create-harness.d.ts.map +1 -1
  622. package/dist/server/create-harness.js +8 -5
  623. package/dist/server/create-harness.js.map +1 -1
  624. package/dist/testing/replay/metrics.d.ts +24 -0
  625. package/dist/testing/replay/metrics.d.ts.map +1 -0
  626. package/dist/testing/replay/metrics.js +35 -0
  627. package/dist/testing/replay/metrics.js.map +1 -0
  628. package/dist/testing/replay/recorded-provider.d.ts +10 -0
  629. package/dist/testing/replay/recorded-provider.d.ts.map +1 -0
  630. package/dist/testing/replay/recorded-provider.js +108 -0
  631. package/dist/testing/replay/recorded-provider.js.map +1 -0
  632. package/dist/testing/replay/runner.d.ts +56 -0
  633. package/dist/testing/replay/runner.d.ts.map +1 -0
  634. package/dist/testing/replay/runner.js +406 -0
  635. package/dist/testing/replay/runner.js.map +1 -0
  636. package/dist/themes/apex-logo.d.ts +41 -0
  637. package/dist/themes/apex-logo.d.ts.map +1 -0
  638. package/dist/themes/apex-logo.js +35 -0
  639. package/dist/themes/apex-logo.js.map +1 -0
  640. package/dist/utils/apex-code-user-agent.d.ts +2 -0
  641. package/dist/utils/apex-code-user-agent.d.ts.map +1 -0
  642. package/dist/utils/apex-code-user-agent.js +5 -0
  643. package/dist/utils/apex-code-user-agent.js.map +1 -0
  644. package/dist/utils/changelog.d.ts +7 -2
  645. package/dist/utils/changelog.d.ts.map +1 -1
  646. package/dist/utils/changelog.js +82 -13
  647. package/dist/utils/changelog.js.map +1 -1
  648. package/dist/utils/clipboard-image.d.ts.map +1 -1
  649. package/dist/utils/clipboard-image.js +1 -1
  650. package/dist/utils/clipboard-image.js.map +1 -1
  651. package/dist/utils/frontmatter.d.ts.map +1 -1
  652. package/dist/utils/frontmatter.js +2 -1
  653. package/dist/utils/frontmatter.js.map +1 -1
  654. package/dist/utils/management-http.d.ts +5 -3
  655. package/dist/utils/management-http.d.ts.map +1 -1
  656. package/dist/utils/management-http.js +14 -10
  657. package/dist/utils/management-http.js.map +1 -1
  658. package/dist/utils/shell.d.ts +3 -0
  659. package/dist/utils/shell.d.ts.map +1 -1
  660. package/dist/utils/shell.js +17 -5
  661. package/dist/utils/shell.js.map +1 -1
  662. package/dist/utils/syntax-highlight.d.ts +1 -0
  663. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  664. package/dist/utils/syntax-highlight.js +60 -1
  665. package/dist/utils/syntax-highlight.js.map +1 -1
  666. package/dist/utils/text.d.ts +8 -0
  667. package/dist/utils/text.d.ts.map +1 -0
  668. package/dist/utils/text.js +9 -0
  669. package/dist/utils/text.js.map +1 -0
  670. package/dist/utils/tools-manager.d.ts +70 -2
  671. package/dist/utils/tools-manager.d.ts.map +1 -1
  672. package/dist/utils/tools-manager.js +280 -124
  673. package/dist/utils/tools-manager.js.map +1 -1
  674. package/dist/utils/version-check.d.ts +7 -5
  675. package/dist/utils/version-check.d.ts.map +1 -1
  676. package/dist/utils/version-check.js +25 -14
  677. package/dist/utils/version-check.js.map +1 -1
  678. package/dist/utils/windows-self-update.d.ts.map +1 -1
  679. package/dist/utils/windows-self-update.js +1 -1
  680. package/dist/utils/windows-self-update.js.map +1 -1
  681. package/docs/compaction.md +39 -24
  682. package/docs/containerization.md +24 -21
  683. package/docs/custom-provider.md +15 -12
  684. package/docs/development.md +11 -11
  685. package/docs/environment-variables.md +37 -77
  686. package/docs/extensions.md +68 -54
  687. package/docs/index.md +12 -24
  688. package/docs/json.md +18 -11
  689. package/docs/keybindings.md +18 -12
  690. package/docs/llama-cpp.md +9 -7
  691. package/docs/models.md +17 -11
  692. package/docs/packages.md +47 -43
  693. package/docs/prompt-templates.md +3 -3
  694. package/docs/providers.md +10 -10
  695. package/docs/quickstart.md +49 -32
  696. package/docs/rpc.md +35 -18
  697. package/docs/sdk.md +20 -6
  698. package/docs/security.md +18 -18
  699. package/docs/session-format.md +9 -9
  700. package/docs/sessions.md +13 -13
  701. package/docs/settings.md +83 -16
  702. package/docs/shell-aliases.md +1 -1
  703. package/docs/skills.md +66 -15
  704. package/docs/terminal-setup.md +44 -19
  705. package/docs/termux.md +4 -4
  706. package/docs/themes.md +32 -11
  707. package/docs/tmux.md +4 -4
  708. package/docs/tui.md +5 -5
  709. package/docs/usage.md +61 -53
  710. package/docs/windows.md +24 -2
  711. package/examples/extensions/border-status-editor.ts +1 -1
  712. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  713. package/examples/extensions/custom-provider-anthropic/package.json +2 -2
  714. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  715. package/examples/extensions/git-checkpoint.ts +2 -2
  716. package/examples/extensions/gondolin/package-lock.json +2 -2
  717. package/examples/extensions/gondolin/package.json +1 -1
  718. package/examples/extensions/notify.ts +3 -1
  719. package/examples/extensions/sandbox/package-lock.json +2 -2
  720. package/examples/extensions/sandbox/package.json +1 -1
  721. package/examples/extensions/subagent/README.md +3 -1
  722. package/examples/extensions/subagent/agents.ts +40 -9
  723. package/examples/extensions/subagent/index.ts +27 -4
  724. package/examples/extensions/titlebar-spinner.ts +1 -1
  725. package/examples/extensions/with-deps/package-lock.json +2 -2
  726. package/examples/extensions/with-deps/package.json +1 -1
  727. package/examples/rpc-extension-ui.ts +1 -1
  728. package/examples/sdk/06-extensions.ts +1 -1
  729. package/examples/sdk/README.md +1 -1
  730. package/npm-shrinkwrap.json +280 -445
  731. package/package.json +9 -12
  732. package/dist/core/telemetry.d.ts +0 -3
  733. package/dist/core/telemetry.d.ts.map +0 -1
  734. package/dist/core/telemetry.js +0 -9
  735. package/dist/core/telemetry.js.map +0 -1
  736. package/dist/utils/pi-user-agent.d.ts +0 -2
  737. package/dist/utils/pi-user-agent.d.ts.map +0 -1
  738. package/dist/utils/pi-user-agent.js +0 -5
  739. package/dist/utils/pi-user-agent.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-supervisor.js","sourceRoot":"","sources":["../../../src/core/sandbox/cli-supervisor.ts"],"names":[],"mappings":"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","sourcesContent":["import { rmSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { parseArgs } from \"../../cli/args.ts\";\nimport { reportConcurrentSessionRefusal } from \"../../cli/concurrent-session.ts\";\nimport type { HostToolBinary } from \"../../utils/tools-manager.ts\";\nimport { acquireSessionLease, readLiveSessionLeases } from \"../session-lease.ts\";\nimport { buildSandboxedCliLaunch, getSandboxSessionDirectory, type HostSkillPaths } from \"./cli-launch.ts\";\nimport { createProjectedGitConfig, resolveHostGitIdentity } from \"./git-identity.ts\";\nimport { createLinuxSandboxBackend } from \"./linux-backend.ts\";\nimport { createMacosSandboxBackend } from \"./macos-backend.ts\";\nimport { createSandboxPolicy } from \"./policy.ts\";\nimport { createCredentialProxy, resolveCredentialChannelPaths } from \"./rpc/credential-proxy.ts\";\nimport { gitCredentialHelperCommand } from \"./rpc/git-credential-helper.ts\";\nimport { createSandboxSupervisor, type SandboxBackend, type SandboxLaunch } from \"./supervisor.ts\";\nimport { SandboxViolationStore } from \"./violations.ts\";\n\nexport interface CliSandboxDependencies {\n\tcreateBackend: (options: { violationStore: SandboxViolationStore }) => SandboxBackend;\n\tstderr: { write(message: string): boolean };\n}\n\n/** Routes to the platform adapter for the running OS; each adapter self-reports\n * `unavailable` on any other platform, so this only needs to pick the one whose\n * enforcement is actually reachable here. */\nfunction createDefaultSandboxBackend(options: { violationStore: SandboxViolationStore }): SandboxBackend {\n\tif (process.platform === \"darwin\") return createMacosSandboxBackend(options);\n\treturn createLinuxSandboxBackend(options);\n}\n\nconst defaultDependencies: CliSandboxDependencies = {\n\tcreateBackend: createDefaultSandboxBackend,\n\tstderr: process.stderr,\n};\n\n/**\n * Start a normal CLI runtime beneath the whole-process boundary. The caller returns\n * the result directly so the outer process never continues into `main()` afterward.\n */\nexport async function launchSandboxedCli(options: {\n\tcommand: string;\n\targs: readonly string[];\n\tenvironment: NodeJS.ProcessEnv;\n\tworkspace: string;\n\tallowedHosts?: readonly string[];\n\tadditionalWritableRoots?: readonly string[];\n\treadOnlyPaths?: readonly string[];\n\tauthPath?: string;\n\ttoolBinaries?: readonly HostToolBinary[];\n\tskillPaths?: HostSkillPaths;\n\tdependencies?: Partial<CliSandboxDependencies>;\n}): Promise<number> {\n\tconst dependencies = { ...defaultDependencies, ...options.dependencies };\n\tconst policyResult = createSandboxPolicy({\n\t\tworkspace: options.workspace,\n\t\tallowedHosts: options.allowedHosts,\n\t\tadditionalWritableRoots: options.additionalWritableRoots,\n\t});\n\tif (policyResult.kind === \"invalid\") {\n\t\tdependencies.stderr.write(`Error: OS sandbox is not enforcing this agent session: ${policyResult.reason}\\n`);\n\t\treturn 1;\n\t}\n\tconst violationStore = new SandboxViolationStore();\n\tconst backend = dependencies.createBackend({ violationStore });\n\n\tconst supervisor = createSandboxSupervisor({ backend, policy: policyResult.policy });\n\tlet credentialProxy: Awaited<ReturnType<typeof createCredentialProxy>> | undefined;\n\tlet lease: ReturnType<typeof acquireSessionLease> | undefined;\n\tlet projectedGitConfig: ReturnType<typeof createProjectedGitConfig> | undefined;\n\ttry {\n\t\tconst parsed = parseArgs(options.args);\n\t\tconst wantsPersistentSession = !parsed.noSession && !parsed.help && parsed.listModels === undefined;\n\t\tconst sessionDirectory = getSandboxSessionDirectory(policyResult.policy.workspace);\n\t\tif (wantsPersistentSession && !parsed.allowConcurrent) {\n\t\t\tconst liveSessions = readLiveSessionLeases(sessionDirectory, policyResult.policy.workspace);\n\t\t\tif (liveSessions.length > 0) {\n\t\t\t\treportConcurrentSessionRefusal(liveSessions, policyResult.policy.workspace);\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t}\n\t\tlease = wantsPersistentSession\n\t\t\t? acquireSessionLease(sessionDirectory, policyResult.policy.workspace, `supervisor-${process.pid}`)\n\t\t\t: undefined;\n\n\t\t// Open the host-owned credential channel only after startup checks that can\n\t\t// return early. AuthStorage creates a missing canonical file as 0600, so a\n\t\t// first-run credential writes get the same channel and read-only projection as later runs.\n\t\tlet credentialChannel: SandboxLaunch[\"credentialChannel\"];\n\t\tif (options.authPath && backend.status.kind === \"enforced\") {\n\t\t\tconst paths = resolveCredentialChannelPaths();\n\t\t\tcredentialProxy = await createCredentialProxy({\n\t\t\t\tauthPath: options.authPath,\n\t\t\t\tviolationStore,\n\t\t\t\tsocketPath: paths.hostSocketPath,\n\t\t\t\tcleanupDirectory: paths.hostSocketDirectory,\n\t\t\t});\n\t\t\tcredentialChannel = paths;\n\t\t}\n\n\t\t// Resolved here rather than in the caller because this function owns the teardown\n\t\t// that removes the directory again. The supervisor is unsandboxed, so the host home\n\t\t// is still visible at this point; inside the child it is not.\n\t\tconst identity = resolveHostGitIdentity({ environment: options.environment });\n\t\t// The helper command is derived from the state directory rather than handed back by\n\t\t// the backend, because the config has to name it before any backend exists. Both\n\t\t// sides derive the same path, so the config never names a file nothing created.\n\t\tprojectedGitConfig = identity\n\t\t\t? createProjectedGitConfig(identity, {\n\t\t\t\t\tcredentialHelper: gitCredentialHelperCommand(\n\t\t\t\t\t\tjoin(policyResult.policy.workspace, \".apex-code\", \"sandbox-state\"),\n\t\t\t\t\t),\n\t\t\t\t})\n\t\t\t: undefined;\n\n\t\tconst launch = buildSandboxedCliLaunch({\n\t\t\tworkspace: policyResult.policy.workspace,\n\t\t\tcommand: options.command,\n\t\t\targs: options.args,\n\t\t\tenvironment: options.environment,\n\t\t\tallowedHosts: options.allowedHosts,\n\t\t\treadOnlyPaths: options.readOnlyPaths,\n\t\t\tauthPath: options.authPath,\n\t\t\tgitConfigPath: projectedGitConfig?.path,\n\t\t\ttoolBinaries: options.toolBinaries,\n\t\t\tskillPaths: options.skillPaths,\n\t\t\tcredentialChannel,\n\t\t});\n\t\treturn await supervisor.launch(launch);\n\t} catch (error: unknown) {\n\t\tconst message = error instanceof Error ? error.message : \"Failed to start OS sandbox.\";\n\t\tdependencies.stderr.write(`Error: ${message}\\n`);\n\t\treturn 1;\n\t} finally {\n\t\tlease?.release();\n\t\tif (projectedGitConfig) rmSync(projectedGitConfig.directory, { force: true, recursive: true });\n\t\tconst cleanupResults = await Promise.allSettled([supervisor.close(), credentialProxy?.close()]);\n\t\tfor (const violation of violationStore.list()) {\n\t\t\tdependencies.stderr.write(\n\t\t\t\t`Sandbox violation (${violation.kind}): ${violation.command} — ${violation.detail}\\n`,\n\t\t\t);\n\t\t}\n\t\tfor (const result of cleanupResults) {\n\t\t\tif (result.status === \"rejected\") {\n\t\t\t\tdependencies.stderr.write(\"Warning: sandbox cleanup did not complete cleanly.\\n\");\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Model-provider API hosts permitted by default inside the sandbox.
3
+ *
4
+ * The boundary shipped denying every host, which meant a fresh install could not reach
5
+ * any model at all: the first request failed, and the user had no way to discover that
6
+ * `generativelanguage.googleapis.com` was the missing entry — the endpoint is an
7
+ * implementation detail of the provider, not something a user knows. Denying by default
8
+ * only protects anyone if the working configuration is reachable without it.
9
+ *
10
+ * This list is a materialised copy of what `builtinProviders()` declares. It is not
11
+ * derived at runtime because importing the provider registry costs roughly 190ms, and
12
+ * the supervisor pays that on every launch before the child even starts.
13
+ * `test/sandbox/default-hosts.test.ts` recomputes the set from the registry and fails if
14
+ * this copy drifts, so adding a provider upstream cannot silently leave it unreachable.
15
+ *
16
+ * Providers whose `baseUrl` is absent or templated — Bedrock, Azure, Cloudflare, Vertex,
17
+ * and the self-hosted ones — resolve their endpoint from account or environment
18
+ * configuration the supervisor cannot see, so they are not here. Those still require an
19
+ * explicit `network.allowedHosts` entry, and the refusal message now names the host.
20
+ */
21
+ export declare const DEFAULT_PROVIDER_HOSTS: readonly string[];
22
+ /**
23
+ * Hosts allowed before any user configuration: every statically known model provider,
24
+ * plus the update check, which is Apex Code's own outbound request and otherwise records
25
+ * a policy violation on every single run.
26
+ */
27
+ export declare function resolveDefaultAllowedHosts(): string[];
28
+ //# sourceMappingURL=default-hosts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-hosts.d.ts","sourceRoot":"","sources":["../../../src/core/sandbox/default-hosts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,sBAAsB,EAAE,SAAS,MAAM,EAgCnD,CAAC;AAUF;;;;GAIG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,EAAE,CAErD","sourcesContent":["/**\n * Model-provider API hosts permitted by default inside the sandbox.\n *\n * The boundary shipped denying every host, which meant a fresh install could not reach\n * any model at all: the first request failed, and the user had no way to discover that\n * `generativelanguage.googleapis.com` was the missing entry — the endpoint is an\n * implementation detail of the provider, not something a user knows. Denying by default\n * only protects anyone if the working configuration is reachable without it.\n *\n * This list is a materialised copy of what `builtinProviders()` declares. It is not\n * derived at runtime because importing the provider registry costs roughly 190ms, and\n * the supervisor pays that on every launch before the child even starts.\n * `test/sandbox/default-hosts.test.ts` recomputes the set from the registry and fails if\n * this copy drifts, so adding a provider upstream cannot silently leave it unreachable.\n *\n * Providers whose `baseUrl` is absent or templated — Bedrock, Azure, Cloudflare, Vertex,\n * and the self-hosted ones — resolve their endpoint from account or environment\n * configuration the supervisor cannot see, so they are not here. Those still require an\n * explicit `network.allowedHosts` entry, and the refusal message now names the host.\n */\nexport const DEFAULT_PROVIDER_HOSTS: readonly string[] = [\n\t\"ai-gateway.vercel.sh\",\n\t\"api.ant-ling.com\",\n\t\"api.anthropic.com\",\n\t\"api.cerebras.ai\",\n\t\"api.deepseek.com\",\n\t\"api.fireworks.ai\",\n\t\"api.groq.com\",\n\t\"api.individual.githubcopilot.com\",\n\t\"api.kimi.com\",\n\t\"api.minimax.io\",\n\t\"api.minimaxi.com\",\n\t\"api.mistral.ai\",\n\t\"api.moonshot.ai\",\n\t\"api.moonshot.cn\",\n\t\"api.openai.com\",\n\t\"api.together.ai\",\n\t\"api.x.ai\",\n\t\"api.xiaomimimo.com\",\n\t\"api.z.ai\",\n\t\"chatgpt.com\",\n\t\"generativelanguage.googleapis.com\",\n\t\"inference.baseten.co\",\n\t\"integrate.api.nvidia.com\",\n\t\"open.bigmodel.cn\",\n\t\"openrouter.ai\",\n\t\"router.huggingface.co\",\n\t\"token-plan-ams.xiaomimimo.com\",\n\t\"token-plan-cn.xiaomimimo.com\",\n\t\"token-plan-sgp.xiaomimimo.com\",\n\t\"token-plan.ap-southeast-1.maas.aliyuncs.com\",\n\t\"token-plan.cn-beijing.maas.aliyuncs.com\",\n];\n\n/**\n * Host of Apex Code's own update check. Duplicated from `version-check.ts` rather than\n * imported: this module is loaded by the supervisor on every launch, and pulling in that\n * module's dependency chain costs roughly 40ms to obtain a single string.\n * `test/sandbox/default-hosts.test.ts` asserts the two agree.\n */\nconst UPDATE_CHECK_HOST = \"registry.npmjs.org\";\n\n/**\n * Hosts allowed before any user configuration: every statically known model provider,\n * plus the update check, which is Apex Code's own outbound request and otherwise records\n * a policy violation on every single run.\n */\nexport function resolveDefaultAllowedHosts(): string[] {\n\treturn [...new Set([...DEFAULT_PROVIDER_HOSTS, UPDATE_CHECK_HOST])];\n}\n"]}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Model-provider API hosts permitted by default inside the sandbox.
3
+ *
4
+ * The boundary shipped denying every host, which meant a fresh install could not reach
5
+ * any model at all: the first request failed, and the user had no way to discover that
6
+ * `generativelanguage.googleapis.com` was the missing entry — the endpoint is an
7
+ * implementation detail of the provider, not something a user knows. Denying by default
8
+ * only protects anyone if the working configuration is reachable without it.
9
+ *
10
+ * This list is a materialised copy of what `builtinProviders()` declares. It is not
11
+ * derived at runtime because importing the provider registry costs roughly 190ms, and
12
+ * the supervisor pays that on every launch before the child even starts.
13
+ * `test/sandbox/default-hosts.test.ts` recomputes the set from the registry and fails if
14
+ * this copy drifts, so adding a provider upstream cannot silently leave it unreachable.
15
+ *
16
+ * Providers whose `baseUrl` is absent or templated — Bedrock, Azure, Cloudflare, Vertex,
17
+ * and the self-hosted ones — resolve their endpoint from account or environment
18
+ * configuration the supervisor cannot see, so they are not here. Those still require an
19
+ * explicit `network.allowedHosts` entry, and the refusal message now names the host.
20
+ */
21
+ export const DEFAULT_PROVIDER_HOSTS = [
22
+ "ai-gateway.vercel.sh",
23
+ "api.ant-ling.com",
24
+ "api.anthropic.com",
25
+ "api.cerebras.ai",
26
+ "api.deepseek.com",
27
+ "api.fireworks.ai",
28
+ "api.groq.com",
29
+ "api.individual.githubcopilot.com",
30
+ "api.kimi.com",
31
+ "api.minimax.io",
32
+ "api.minimaxi.com",
33
+ "api.mistral.ai",
34
+ "api.moonshot.ai",
35
+ "api.moonshot.cn",
36
+ "api.openai.com",
37
+ "api.together.ai",
38
+ "api.x.ai",
39
+ "api.xiaomimimo.com",
40
+ "api.z.ai",
41
+ "chatgpt.com",
42
+ "generativelanguage.googleapis.com",
43
+ "inference.baseten.co",
44
+ "integrate.api.nvidia.com",
45
+ "open.bigmodel.cn",
46
+ "openrouter.ai",
47
+ "router.huggingface.co",
48
+ "token-plan-ams.xiaomimimo.com",
49
+ "token-plan-cn.xiaomimimo.com",
50
+ "token-plan-sgp.xiaomimimo.com",
51
+ "token-plan.ap-southeast-1.maas.aliyuncs.com",
52
+ "token-plan.cn-beijing.maas.aliyuncs.com",
53
+ ];
54
+ /**
55
+ * Host of Apex Code's own update check. Duplicated from `version-check.ts` rather than
56
+ * imported: this module is loaded by the supervisor on every launch, and pulling in that
57
+ * module's dependency chain costs roughly 40ms to obtain a single string.
58
+ * `test/sandbox/default-hosts.test.ts` asserts the two agree.
59
+ */
60
+ const UPDATE_CHECK_HOST = "registry.npmjs.org";
61
+ /**
62
+ * Hosts allowed before any user configuration: every statically known model provider,
63
+ * plus the update check, which is Apex Code's own outbound request and otherwise records
64
+ * a policy violation on every single run.
65
+ */
66
+ export function resolveDefaultAllowedHosts() {
67
+ return [...new Set([...DEFAULT_PROVIDER_HOSTS, UPDATE_CHECK_HOST])];
68
+ }
69
+ //# sourceMappingURL=default-hosts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-hosts.js","sourceRoot":"","sources":["../../../src/core/sandbox/default-hosts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAsB;IACxD,sBAAsB;IACtB,kBAAkB;IAClB,mBAAmB;IACnB,iBAAiB;IACjB,kBAAkB;IAClB,kBAAkB;IAClB,cAAc;IACd,kCAAkC;IAClC,cAAc;IACd,gBAAgB;IAChB,kBAAkB;IAClB,gBAAgB;IAChB,iBAAiB;IACjB,iBAAiB;IACjB,gBAAgB;IAChB,iBAAiB;IACjB,UAAU;IACV,oBAAoB;IACpB,UAAU;IACV,aAAa;IACb,mCAAmC;IACnC,sBAAsB;IACtB,0BAA0B;IAC1B,kBAAkB;IAClB,eAAe;IACf,uBAAuB;IACvB,+BAA+B;IAC/B,8BAA8B;IAC9B,+BAA+B;IAC/B,6CAA6C;IAC7C,yCAAyC;CACzC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,iBAAiB,GAAG,oBAAoB,CAAC;AAE/C;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,GAAa;IACtD,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,sBAAsB,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;AAAA,CACpE","sourcesContent":["/**\n * Model-provider API hosts permitted by default inside the sandbox.\n *\n * The boundary shipped denying every host, which meant a fresh install could not reach\n * any model at all: the first request failed, and the user had no way to discover that\n * `generativelanguage.googleapis.com` was the missing entry — the endpoint is an\n * implementation detail of the provider, not something a user knows. Denying by default\n * only protects anyone if the working configuration is reachable without it.\n *\n * This list is a materialised copy of what `builtinProviders()` declares. It is not\n * derived at runtime because importing the provider registry costs roughly 190ms, and\n * the supervisor pays that on every launch before the child even starts.\n * `test/sandbox/default-hosts.test.ts` recomputes the set from the registry and fails if\n * this copy drifts, so adding a provider upstream cannot silently leave it unreachable.\n *\n * Providers whose `baseUrl` is absent or templated — Bedrock, Azure, Cloudflare, Vertex,\n * and the self-hosted ones — resolve their endpoint from account or environment\n * configuration the supervisor cannot see, so they are not here. Those still require an\n * explicit `network.allowedHosts` entry, and the refusal message now names the host.\n */\nexport const DEFAULT_PROVIDER_HOSTS: readonly string[] = [\n\t\"ai-gateway.vercel.sh\",\n\t\"api.ant-ling.com\",\n\t\"api.anthropic.com\",\n\t\"api.cerebras.ai\",\n\t\"api.deepseek.com\",\n\t\"api.fireworks.ai\",\n\t\"api.groq.com\",\n\t\"api.individual.githubcopilot.com\",\n\t\"api.kimi.com\",\n\t\"api.minimax.io\",\n\t\"api.minimaxi.com\",\n\t\"api.mistral.ai\",\n\t\"api.moonshot.ai\",\n\t\"api.moonshot.cn\",\n\t\"api.openai.com\",\n\t\"api.together.ai\",\n\t\"api.x.ai\",\n\t\"api.xiaomimimo.com\",\n\t\"api.z.ai\",\n\t\"chatgpt.com\",\n\t\"generativelanguage.googleapis.com\",\n\t\"inference.baseten.co\",\n\t\"integrate.api.nvidia.com\",\n\t\"open.bigmodel.cn\",\n\t\"openrouter.ai\",\n\t\"router.huggingface.co\",\n\t\"token-plan-ams.xiaomimimo.com\",\n\t\"token-plan-cn.xiaomimimo.com\",\n\t\"token-plan-sgp.xiaomimimo.com\",\n\t\"token-plan.ap-southeast-1.maas.aliyuncs.com\",\n\t\"token-plan.cn-beijing.maas.aliyuncs.com\",\n];\n\n/**\n * Host of Apex Code's own update check. Duplicated from `version-check.ts` rather than\n * imported: this module is loaded by the supervisor on every launch, and pulling in that\n * module's dependency chain costs roughly 40ms to obtain a single string.\n * `test/sandbox/default-hosts.test.ts` asserts the two agree.\n */\nconst UPDATE_CHECK_HOST = \"registry.npmjs.org\";\n\n/**\n * Hosts allowed before any user configuration: every statically known model provider,\n * plus the update check, which is Apex Code's own outbound request and otherwise records\n * a policy violation on every single run.\n */\nexport function resolveDefaultAllowedHosts(): string[] {\n\treturn [...new Set([...DEFAULT_PROVIDER_HOSTS, UPDATE_CHECK_HOST])];\n}\n"]}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * The explicit opt-out from OS containment.
3
+ *
4
+ * ADR 0005 shipped without one on purpose, and its 2026-08-28 amendment records why that
5
+ * is now a flag rather than an absence: the delegation work removed the reasons people
6
+ * were reaching for an escape hatch, so the hatch can exist without becoming the default
7
+ * route around a boundary that could not otherwise be worked with.
8
+ *
9
+ * Two rules keep it honest. It is spelled out in full on the command line, never inferred
10
+ * from settings, so no repository and no saved configuration can turn the boundary off.
11
+ * And it always announces itself, because a session that silently ran unconfined is
12
+ * indistinguishable afterwards from one that did not.
13
+ */
14
+ export declare function writeFullAccessBanner(stderr: {
15
+ write(message: string): boolean;
16
+ }): void;
17
+ /**
18
+ * Confirm the opt-out interactively, or accept it unprompted where no human could answer.
19
+ *
20
+ * A non-interactive session is the case the flag legitimately exists for -- CI that is
21
+ * already externally sandboxed -- and there is nobody there to type. Prompting anyway
22
+ * would hang the run rather than protect anything, so the banner carries the weight.
23
+ */
24
+ export declare function confirmFullAccess(options: {
25
+ input?: NodeJS.ReadStream;
26
+ output?: NodeJS.WriteStream;
27
+ }): Promise<boolean>;
28
+ //# sourceMappingURL=full-access.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"full-access.d.ts","sourceRoot":"","sources":["../../../src/core/sandbox/full-access.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAYH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE;IAAE,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GAAG,IAAI,CAEvF;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC,WAAW,CAAC;CAC5B,GAAG,OAAO,CAAC,OAAO,CAAC,CA4BnB","sourcesContent":["/**\n * The explicit opt-out from OS containment.\n *\n * ADR 0005 shipped without one on purpose, and its 2026-08-28 amendment records why that\n * is now a flag rather than an absence: the delegation work removed the reasons people\n * were reaching for an escape hatch, so the hatch can exist without becoming the default\n * route around a boundary that could not otherwise be worked with.\n *\n * Two rules keep it honest. It is spelled out in full on the command line, never inferred\n * from settings, so no repository and no saved configuration can turn the boundary off.\n * And it always announces itself, because a session that silently ran unconfined is\n * indistinguishable afterwards from one that did not.\n */\n\nconst BANNER = [\n\t\"\",\n\t\" ! OS sandbox disabled for this session (--sandbox danger-full-access).\",\n\t\"\",\n\t\" Tool calls and every process they spawn run with your full account authority:\",\n\t\" your home directory, your credentials, and unrestricted network access.\",\n\t\" The permission gate still applies. It is not a containment boundary.\",\n\t\"\",\n].join(\"\\n\");\n\nexport function writeFullAccessBanner(stderr: { write(message: string): boolean }): void {\n\tstderr.write(`${BANNER}\\n`);\n}\n\n/**\n * Confirm the opt-out interactively, or accept it unprompted where no human could answer.\n *\n * A non-interactive session is the case the flag legitimately exists for -- CI that is\n * already externally sandboxed -- and there is nobody there to type. Prompting anyway\n * would hang the run rather than protect anything, so the banner carries the weight.\n */\nexport function confirmFullAccess(options: {\n\tinput?: NodeJS.ReadStream;\n\toutput?: NodeJS.WriteStream;\n}): Promise<boolean> {\n\tconst input = options.input ?? process.stdin;\n\tconst output = options.output ?? process.stdout;\n\tif (!input.isTTY || !output.isTTY) return Promise.resolve(true);\n\n\toutput.write(\"Run this session with no OS sandbox? [y/N] \");\n\treturn new Promise((resolve) => {\n\t\tlet buffer = \"\";\n\t\tconst finish = (value: string) => {\n\t\t\tinput.off(\"data\", onData);\n\t\t\tinput.off(\"error\", onError);\n\t\t\tinput.pause();\n\t\t\tconst answer = value.trim().toLowerCase();\n\t\t\toutput.write(\"\\n\");\n\t\t\tresolve(answer === \"y\" || answer === \"yes\");\n\t\t};\n\t\tconst onData = (chunk: Buffer | string) => {\n\t\t\tbuffer += chunk.toString();\n\t\t\tconst newline = buffer.indexOf(\"\\n\");\n\t\t\tif (newline >= 0) finish(buffer.slice(0, newline));\n\t\t};\n\t\t// Anything unreadable declines, because an unanswerable prompt must not be the way\n\t\t// containment gets switched off.\n\t\tconst onError = () => finish(\"\");\n\t\tinput.on(\"data\", onData);\n\t\tinput.on(\"error\", onError);\n\t\tinput.resume();\n\t});\n}\n"]}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * The explicit opt-out from OS containment.
3
+ *
4
+ * ADR 0005 shipped without one on purpose, and its 2026-08-28 amendment records why that
5
+ * is now a flag rather than an absence: the delegation work removed the reasons people
6
+ * were reaching for an escape hatch, so the hatch can exist without becoming the default
7
+ * route around a boundary that could not otherwise be worked with.
8
+ *
9
+ * Two rules keep it honest. It is spelled out in full on the command line, never inferred
10
+ * from settings, so no repository and no saved configuration can turn the boundary off.
11
+ * And it always announces itself, because a session that silently ran unconfined is
12
+ * indistinguishable afterwards from one that did not.
13
+ */
14
+ const BANNER = [
15
+ "",
16
+ " ! OS sandbox disabled for this session (--sandbox danger-full-access).",
17
+ "",
18
+ " Tool calls and every process they spawn run with your full account authority:",
19
+ " your home directory, your credentials, and unrestricted network access.",
20
+ " The permission gate still applies. It is not a containment boundary.",
21
+ "",
22
+ ].join("\n");
23
+ export function writeFullAccessBanner(stderr) {
24
+ stderr.write(`${BANNER}\n`);
25
+ }
26
+ /**
27
+ * Confirm the opt-out interactively, or accept it unprompted where no human could answer.
28
+ *
29
+ * A non-interactive session is the case the flag legitimately exists for -- CI that is
30
+ * already externally sandboxed -- and there is nobody there to type. Prompting anyway
31
+ * would hang the run rather than protect anything, so the banner carries the weight.
32
+ */
33
+ export function confirmFullAccess(options) {
34
+ const input = options.input ?? process.stdin;
35
+ const output = options.output ?? process.stdout;
36
+ if (!input.isTTY || !output.isTTY)
37
+ return Promise.resolve(true);
38
+ output.write("Run this session with no OS sandbox? [y/N] ");
39
+ return new Promise((resolve) => {
40
+ let buffer = "";
41
+ const finish = (value) => {
42
+ input.off("data", onData);
43
+ input.off("error", onError);
44
+ input.pause();
45
+ const answer = value.trim().toLowerCase();
46
+ output.write("\n");
47
+ resolve(answer === "y" || answer === "yes");
48
+ };
49
+ const onData = (chunk) => {
50
+ buffer += chunk.toString();
51
+ const newline = buffer.indexOf("\n");
52
+ if (newline >= 0)
53
+ finish(buffer.slice(0, newline));
54
+ };
55
+ // Anything unreadable declines, because an unanswerable prompt must not be the way
56
+ // containment gets switched off.
57
+ const onError = () => finish("");
58
+ input.on("data", onData);
59
+ input.on("error", onError);
60
+ input.resume();
61
+ });
62
+ }
63
+ //# sourceMappingURL=full-access.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"full-access.js","sourceRoot":"","sources":["../../../src/core/sandbox/full-access.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,MAAM,GAAG;IACd,EAAE;IACF,0EAA0E;IAC1E,EAAE;IACF,mFAAmF;IACnF,6EAA6E;IAC7E,0EAA0E;IAC1E,EAAE;CACF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,UAAU,qBAAqB,CAAC,MAA2C,EAAQ;IACxF,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,CAAC;AAAA,CAC5B;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAGjC,EAAoB;IACpB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC;IAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAChD,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,KAAK;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhE,MAAM,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;IAC5D,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;QAC/B,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,MAAM,MAAM,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC;YACjC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAC1B,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC5B,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YAC1C,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACnB,OAAO,CAAC,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,KAAK,CAAC,CAAC;QAAA,CAC5C,CAAC;QACF,MAAM,MAAM,GAAG,CAAC,KAAsB,EAAE,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC3B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACrC,IAAI,OAAO,IAAI,CAAC;gBAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QAAA,CACnD,CAAC;QACF,mFAAmF;QACnF,iCAAiC;QACjC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACjC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACzB,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC3B,KAAK,CAAC,MAAM,EAAE,CAAC;IAAA,CACf,CAAC,CAAC;AAAA,CACH","sourcesContent":["/**\n * The explicit opt-out from OS containment.\n *\n * ADR 0005 shipped without one on purpose, and its 2026-08-28 amendment records why that\n * is now a flag rather than an absence: the delegation work removed the reasons people\n * were reaching for an escape hatch, so the hatch can exist without becoming the default\n * route around a boundary that could not otherwise be worked with.\n *\n * Two rules keep it honest. It is spelled out in full on the command line, never inferred\n * from settings, so no repository and no saved configuration can turn the boundary off.\n * And it always announces itself, because a session that silently ran unconfined is\n * indistinguishable afterwards from one that did not.\n */\n\nconst BANNER = [\n\t\"\",\n\t\" ! OS sandbox disabled for this session (--sandbox danger-full-access).\",\n\t\"\",\n\t\" Tool calls and every process they spawn run with your full account authority:\",\n\t\" your home directory, your credentials, and unrestricted network access.\",\n\t\" The permission gate still applies. It is not a containment boundary.\",\n\t\"\",\n].join(\"\\n\");\n\nexport function writeFullAccessBanner(stderr: { write(message: string): boolean }): void {\n\tstderr.write(`${BANNER}\\n`);\n}\n\n/**\n * Confirm the opt-out interactively, or accept it unprompted where no human could answer.\n *\n * A non-interactive session is the case the flag legitimately exists for -- CI that is\n * already externally sandboxed -- and there is nobody there to type. Prompting anyway\n * would hang the run rather than protect anything, so the banner carries the weight.\n */\nexport function confirmFullAccess(options: {\n\tinput?: NodeJS.ReadStream;\n\toutput?: NodeJS.WriteStream;\n}): Promise<boolean> {\n\tconst input = options.input ?? process.stdin;\n\tconst output = options.output ?? process.stdout;\n\tif (!input.isTTY || !output.isTTY) return Promise.resolve(true);\n\n\toutput.write(\"Run this session with no OS sandbox? [y/N] \");\n\treturn new Promise((resolve) => {\n\t\tlet buffer = \"\";\n\t\tconst finish = (value: string) => {\n\t\t\tinput.off(\"data\", onData);\n\t\t\tinput.off(\"error\", onError);\n\t\t\tinput.pause();\n\t\t\tconst answer = value.trim().toLowerCase();\n\t\t\toutput.write(\"\\n\");\n\t\t\tresolve(answer === \"y\" || answer === \"yes\");\n\t\t};\n\t\tconst onData = (chunk: Buffer | string) => {\n\t\t\tbuffer += chunk.toString();\n\t\t\tconst newline = buffer.indexOf(\"\\n\");\n\t\t\tif (newline >= 0) finish(buffer.slice(0, newline));\n\t\t};\n\t\t// Anything unreadable declines, because an unanswerable prompt must not be the way\n\t\t// containment gets switched off.\n\t\tconst onError = () => finish(\"\");\n\t\tinput.on(\"data\", onData);\n\t\tinput.on(\"error\", onError);\n\t\tinput.resume();\n\t});\n}\n"]}
@@ -0,0 +1,57 @@
1
+ export interface HostGitIdentity {
2
+ readonly name: string;
3
+ readonly email: string;
4
+ }
5
+ export interface ProjectedGitConfig {
6
+ readonly directory: string;
7
+ readonly path: string;
8
+ }
9
+ /**
10
+ * Read the host's git identity before the sandbox exists to hide it.
11
+ *
12
+ * `--global` rather than a plain lookup, because the scope flag is what excludes the
13
+ * workspace's own `.git/config` by construction rather than by choosing a lucky working
14
+ * directory. A repository must not be able to decide what the supervisor projects, the
15
+ * same rule ADR 0016 applies to the network allowlist. Repository scope still works
16
+ * normally inside the child: the workspace is bind-mounted read-write, so git reads
17
+ * `.git/config` there itself and it wins over this projection, exactly as it would on the
18
+ * host.
19
+ *
20
+ * System scope (`/etc/gitconfig`) is deliberately not consulted. A machine-wide commit
21
+ * identity is not a real configuration, and a second `spawnSync` to find one would cost
22
+ * every launch what it saves nobody.
23
+ *
24
+ * Returns undefined unless both keys are present. A name without an email still fails to
25
+ * author a commit, so projecting half an identity would replace one confusing error with
26
+ * another.
27
+ */
28
+ export declare function resolveHostGitIdentity(options?: {
29
+ /** Injectable only for tests; production uses the supervisor's own environment. */
30
+ environment?: NodeJS.ProcessEnv;
31
+ /**
32
+ * Injectable only for tests, so one can prove repository scope stays excluded even
33
+ * when the lookup runs from inside a repository.
34
+ */
35
+ cwd?: string;
36
+ }): HostGitIdentity | undefined;
37
+ /**
38
+ * Write a two-key config the child can be pointed at through `GIT_CONFIG_GLOBAL`.
39
+ *
40
+ * Synthesized rather than copied. A real `~/.gitconfig` can carry a `credential.helper`
41
+ * that runs a command, or an `insteadOf` rule rewriting a remote to one carrying a token;
42
+ * projecting the host file would hand both to the child along with the name we wanted.
43
+ * Building the file from a resolved identity means it cannot contain anything else.
44
+ *
45
+ * The directory is its own, not shared with the credential projection, and `0700` for the
46
+ * same reason `resolveCredentialChannelPaths` uses one. TMPDIR is deliberately not
47
+ * honoured: it can point inside the workspace on macOS, which the sandbox may write.
48
+ */
49
+ export declare function createProjectedGitConfig(identity: HostGitIdentity, options?: {
50
+ /**
51
+ * A `credential.helper` value for the child. It names the supervisor-mediated
52
+ * helper, never a host one: the point is that the child asks over the channel
53
+ * rather than reading any store itself.
54
+ */
55
+ credentialHelper?: string;
56
+ }): ProjectedGitConfig;
57
+ //# sourceMappingURL=git-identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-identity.d.ts","sourceRoot":"","sources":["../../../src/core/sandbox/git-identity.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACtB;AAKD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE;IAChD,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAChC;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACb,GAAG,eAAe,GAAG,SAAS,CAoB9B;AAOD;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CACvC,QAAQ,EAAE,eAAe,EACzB,OAAO,CAAC,EAAE;IACT;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B,GACC,kBAAkB,CAUpB","sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport { chmodSync, mkdtempSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { supervisorTempDirectory } from \"./supervisor-temp.ts\";\n\nexport interface HostGitIdentity {\n\treadonly name: string;\n\treadonly email: string;\n}\n\nexport interface ProjectedGitConfig {\n\treadonly directory: string;\n\treadonly path: string;\n}\n\n/** Long enough for a cold `git` on a slow disk, short enough not to stall every launch. */\nconst RESOLUTION_TIMEOUT_MILLISECONDS = 2_000;\n\n/**\n * Read the host's git identity before the sandbox exists to hide it.\n *\n * `--global` rather than a plain lookup, because the scope flag is what excludes the\n * workspace's own `.git/config` by construction rather than by choosing a lucky working\n * directory. A repository must not be able to decide what the supervisor projects, the\n * same rule ADR 0016 applies to the network allowlist. Repository scope still works\n * normally inside the child: the workspace is bind-mounted read-write, so git reads\n * `.git/config` there itself and it wins over this projection, exactly as it would on the\n * host.\n *\n * System scope (`/etc/gitconfig`) is deliberately not consulted. A machine-wide commit\n * identity is not a real configuration, and a second `spawnSync` to find one would cost\n * every launch what it saves nobody.\n *\n * Returns undefined unless both keys are present. A name without an email still fails to\n * author a commit, so projecting half an identity would replace one confusing error with\n * another.\n */\nexport function resolveHostGitIdentity(options?: {\n\t/** Injectable only for tests; production uses the supervisor's own environment. */\n\tenvironment?: NodeJS.ProcessEnv;\n\t/**\n\t * Injectable only for tests, so one can prove repository scope stays excluded even\n\t * when the lookup runs from inside a repository.\n\t */\n\tcwd?: string;\n}): HostGitIdentity | undefined {\n\tconst result = spawnSync(\"git\", [\"config\", \"--global\", \"--get-regexp\", \"^user\\\\.(name|email)$\"], {\n\t\tcwd: options?.cwd,\n\t\tencoding: \"utf8\",\n\t\tenv: options?.environment ?? process.env,\n\t\ttimeout: RESOLUTION_TIMEOUT_MILLISECONDS,\n\t});\n\tif (result.status !== 0 || typeof result.stdout !== \"string\") return undefined;\n\n\tlet name: string | undefined;\n\tlet email: string | undefined;\n\tfor (const line of result.stdout.split(\"\\n\")) {\n\t\tconst separator = line.indexOf(\" \");\n\t\tif (separator < 0) continue;\n\t\tconst value = line.slice(separator + 1).trim();\n\t\tif (value.length === 0) continue;\n\t\tif (line.slice(0, separator) === \"user.name\") name = value;\n\t\tif (line.slice(0, separator) === \"user.email\") email = value;\n\t}\n\treturn name && email ? { name, email } : undefined;\n}\n\n/** Escape a value for git's config syntax, which reads a quoted string with backslash escapes. */\nfunction quote(value: string): string {\n\treturn `\"${value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n}\n\n/**\n * Write a two-key config the child can be pointed at through `GIT_CONFIG_GLOBAL`.\n *\n * Synthesized rather than copied. A real `~/.gitconfig` can carry a `credential.helper`\n * that runs a command, or an `insteadOf` rule rewriting a remote to one carrying a token;\n * projecting the host file would hand both to the child along with the name we wanted.\n * Building the file from a resolved identity means it cannot contain anything else.\n *\n * The directory is its own, not shared with the credential projection, and `0700` for the\n * same reason `resolveCredentialChannelPaths` uses one. TMPDIR is deliberately not\n * honoured: it can point inside the workspace on macOS, which the sandbox may write.\n */\nexport function createProjectedGitConfig(\n\tidentity: HostGitIdentity,\n\toptions?: {\n\t\t/**\n\t\t * A `credential.helper` value for the child. It names the supervisor-mediated\n\t\t * helper, never a host one: the point is that the child asks over the channel\n\t\t * rather than reading any store itself.\n\t\t */\n\t\tcredentialHelper?: string;\n\t},\n): ProjectedGitConfig {\n\tconst directory = mkdtempSync(join(supervisorTempDirectory(), `apex-git-${process.pid}-`), { encoding: \"utf8\" });\n\tchmodSync(directory, 0o700);\n\tconst path = join(directory, \"config\");\n\tconst sections = [`[user]\\n\\tname = ${quote(identity.name)}\\n\\temail = ${quote(identity.email)}\\n`];\n\tif (options?.credentialHelper) {\n\t\tsections.push(`[credential]\\n\\thelper = ${quote(options.credentialHelper)}\\n`);\n\t}\n\twriteFileSync(path, sections.join(\"\"), { mode: 0o600 });\n\treturn { directory, path };\n}\n"]}
@@ -0,0 +1,78 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { chmodSync, mkdtempSync, writeFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { supervisorTempDirectory } from "./supervisor-temp.js";
5
+ /** Long enough for a cold `git` on a slow disk, short enough not to stall every launch. */
6
+ const RESOLUTION_TIMEOUT_MILLISECONDS = 2_000;
7
+ /**
8
+ * Read the host's git identity before the sandbox exists to hide it.
9
+ *
10
+ * `--global` rather than a plain lookup, because the scope flag is what excludes the
11
+ * workspace's own `.git/config` by construction rather than by choosing a lucky working
12
+ * directory. A repository must not be able to decide what the supervisor projects, the
13
+ * same rule ADR 0016 applies to the network allowlist. Repository scope still works
14
+ * normally inside the child: the workspace is bind-mounted read-write, so git reads
15
+ * `.git/config` there itself and it wins over this projection, exactly as it would on the
16
+ * host.
17
+ *
18
+ * System scope (`/etc/gitconfig`) is deliberately not consulted. A machine-wide commit
19
+ * identity is not a real configuration, and a second `spawnSync` to find one would cost
20
+ * every launch what it saves nobody.
21
+ *
22
+ * Returns undefined unless both keys are present. A name without an email still fails to
23
+ * author a commit, so projecting half an identity would replace one confusing error with
24
+ * another.
25
+ */
26
+ export function resolveHostGitIdentity(options) {
27
+ const result = spawnSync("git", ["config", "--global", "--get-regexp", "^user\\.(name|email)$"], {
28
+ cwd: options?.cwd,
29
+ encoding: "utf8",
30
+ env: options?.environment ?? process.env,
31
+ timeout: RESOLUTION_TIMEOUT_MILLISECONDS,
32
+ });
33
+ if (result.status !== 0 || typeof result.stdout !== "string")
34
+ return undefined;
35
+ let name;
36
+ let email;
37
+ for (const line of result.stdout.split("\n")) {
38
+ const separator = line.indexOf(" ");
39
+ if (separator < 0)
40
+ continue;
41
+ const value = line.slice(separator + 1).trim();
42
+ if (value.length === 0)
43
+ continue;
44
+ if (line.slice(0, separator) === "user.name")
45
+ name = value;
46
+ if (line.slice(0, separator) === "user.email")
47
+ email = value;
48
+ }
49
+ return name && email ? { name, email } : undefined;
50
+ }
51
+ /** Escape a value for git's config syntax, which reads a quoted string with backslash escapes. */
52
+ function quote(value) {
53
+ return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
54
+ }
55
+ /**
56
+ * Write a two-key config the child can be pointed at through `GIT_CONFIG_GLOBAL`.
57
+ *
58
+ * Synthesized rather than copied. A real `~/.gitconfig` can carry a `credential.helper`
59
+ * that runs a command, or an `insteadOf` rule rewriting a remote to one carrying a token;
60
+ * projecting the host file would hand both to the child along with the name we wanted.
61
+ * Building the file from a resolved identity means it cannot contain anything else.
62
+ *
63
+ * The directory is its own, not shared with the credential projection, and `0700` for the
64
+ * same reason `resolveCredentialChannelPaths` uses one. TMPDIR is deliberately not
65
+ * honoured: it can point inside the workspace on macOS, which the sandbox may write.
66
+ */
67
+ export function createProjectedGitConfig(identity, options) {
68
+ const directory = mkdtempSync(join(supervisorTempDirectory(), `apex-git-${process.pid}-`), { encoding: "utf8" });
69
+ chmodSync(directory, 0o700);
70
+ const path = join(directory, "config");
71
+ const sections = [`[user]\n\tname = ${quote(identity.name)}\n\temail = ${quote(identity.email)}\n`];
72
+ if (options?.credentialHelper) {
73
+ sections.push(`[credential]\n\thelper = ${quote(options.credentialHelper)}\n`);
74
+ }
75
+ writeFileSync(path, sections.join(""), { mode: 0o600 });
76
+ return { directory, path };
77
+ }
78
+ //# sourceMappingURL=git-identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-identity.js","sourceRoot":"","sources":["../../../src/core/sandbox/git-identity.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport { chmodSync, mkdtempSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { supervisorTempDirectory } from \"./supervisor-temp.ts\";\n\nexport interface HostGitIdentity {\n\treadonly name: string;\n\treadonly email: string;\n}\n\nexport interface ProjectedGitConfig {\n\treadonly directory: string;\n\treadonly path: string;\n}\n\n/** Long enough for a cold `git` on a slow disk, short enough not to stall every launch. */\nconst RESOLUTION_TIMEOUT_MILLISECONDS = 2_000;\n\n/**\n * Read the host's git identity before the sandbox exists to hide it.\n *\n * `--global` rather than a plain lookup, because the scope flag is what excludes the\n * workspace's own `.git/config` by construction rather than by choosing a lucky working\n * directory. A repository must not be able to decide what the supervisor projects, the\n * same rule ADR 0016 applies to the network allowlist. Repository scope still works\n * normally inside the child: the workspace is bind-mounted read-write, so git reads\n * `.git/config` there itself and it wins over this projection, exactly as it would on the\n * host.\n *\n * System scope (`/etc/gitconfig`) is deliberately not consulted. A machine-wide commit\n * identity is not a real configuration, and a second `spawnSync` to find one would cost\n * every launch what it saves nobody.\n *\n * Returns undefined unless both keys are present. A name without an email still fails to\n * author a commit, so projecting half an identity would replace one confusing error with\n * another.\n */\nexport function resolveHostGitIdentity(options?: {\n\t/** Injectable only for tests; production uses the supervisor's own environment. */\n\tenvironment?: NodeJS.ProcessEnv;\n\t/**\n\t * Injectable only for tests, so one can prove repository scope stays excluded even\n\t * when the lookup runs from inside a repository.\n\t */\n\tcwd?: string;\n}): HostGitIdentity | undefined {\n\tconst result = spawnSync(\"git\", [\"config\", \"--global\", \"--get-regexp\", \"^user\\\\.(name|email)$\"], {\n\t\tcwd: options?.cwd,\n\t\tencoding: \"utf8\",\n\t\tenv: options?.environment ?? process.env,\n\t\ttimeout: RESOLUTION_TIMEOUT_MILLISECONDS,\n\t});\n\tif (result.status !== 0 || typeof result.stdout !== \"string\") return undefined;\n\n\tlet name: string | undefined;\n\tlet email: string | undefined;\n\tfor (const line of result.stdout.split(\"\\n\")) {\n\t\tconst separator = line.indexOf(\" \");\n\t\tif (separator < 0) continue;\n\t\tconst value = line.slice(separator + 1).trim();\n\t\tif (value.length === 0) continue;\n\t\tif (line.slice(0, separator) === \"user.name\") name = value;\n\t\tif (line.slice(0, separator) === \"user.email\") email = value;\n\t}\n\treturn name && email ? { name, email } : undefined;\n}\n\n/** Escape a value for git's config syntax, which reads a quoted string with backslash escapes. */\nfunction quote(value: string): string {\n\treturn `\"${value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n}\n\n/**\n * Write a two-key config the child can be pointed at through `GIT_CONFIG_GLOBAL`.\n *\n * Synthesized rather than copied. A real `~/.gitconfig` can carry a `credential.helper`\n * that runs a command, or an `insteadOf` rule rewriting a remote to one carrying a token;\n * projecting the host file would hand both to the child along with the name we wanted.\n * Building the file from a resolved identity means it cannot contain anything else.\n *\n * The directory is its own, not shared with the credential projection, and `0700` for the\n * same reason `resolveCredentialChannelPaths` uses one. TMPDIR is deliberately not\n * honoured: it can point inside the workspace on macOS, which the sandbox may write.\n */\nexport function createProjectedGitConfig(\n\tidentity: HostGitIdentity,\n\toptions?: {\n\t\t/**\n\t\t * A `credential.helper` value for the child. It names the supervisor-mediated\n\t\t * helper, never a host one: the point is that the child asks over the channel\n\t\t * rather than reading any store itself.\n\t\t */\n\t\tcredentialHelper?: string;\n\t},\n): ProjectedGitConfig {\n\tconst directory = mkdtempSync(join(supervisorTempDirectory(), `apex-git-${process.pid}-`), { encoding: \"utf8\" });\n\tchmodSync(directory, 0o700);\n\tconst path = join(directory, \"config\");\n\tconst sections = [`[user]\\n\\tname = ${quote(identity.name)}\\n\\temail = ${quote(identity.email)}\\n`];\n\tif (options?.credentialHelper) {\n\t\tsections.push(`[credential]\\n\\thelper = ${quote(options.credentialHelper)}\\n`);\n\t}\n\twriteFileSync(path, sections.join(\"\"), { mode: 0o600 });\n\treturn { directory, path };\n}\n"]}
@@ -0,0 +1,42 @@
1
+ import type { TerminalHandoff } from "./terminal-handoff.ts";
2
+ /**
3
+ * The supervisor's own approval prompt for one refused host.
4
+ *
5
+ * ADR 0023 puts the decision here rather than in the child. An approval asserted from
6
+ * inside the boundary is indistinguishable, at the supervisor, from one forged by a
7
+ * postinstall script or a git hook -- the code the boundary exists to contain -- so the
8
+ * human's answer is read by the side that owns the decision, on a terminal borrowed back
9
+ * from the child for the duration.
10
+ *
11
+ * Returning undefined when there is no terminal is the mechanism, not a fallback. The
12
+ * proxy's own deny-without-asking path then runs unchanged, so ADR 0005's headless, print,
13
+ * JSON, and RPC behaviour holds by construction rather than by a mode check that a later
14
+ * change could forget to make.
15
+ */
16
+ export interface TerminalPromptOptions {
17
+ handoff: TerminalHandoff;
18
+ input?: NodeJS.ReadStream;
19
+ output?: NodeJS.WriteStream;
20
+ }
21
+ /** Approve one refused host for the rest of the session. */
22
+ export declare function createHostApprover(options: TerminalPromptOptions): ((hostname: string, port: number) => Promise<boolean>) | undefined;
23
+ /**
24
+ * Release the host's own git credential for one host, for the rest of the session.
25
+ *
26
+ * Separate from the host approval above even though both are yes/no, because they are
27
+ * different grants and conflating them would let approving a push also release a token to
28
+ * everything else the session later contacts.
29
+ */
30
+ export declare function createCredentialReleaser(options: TerminalPromptOptions): ((host: string) => Promise<boolean>) | undefined;
31
+ /**
32
+ * Approve one command to run in a separate child with one extra writable root.
33
+ *
34
+ * Unlike a host or a credential, nothing is remembered. A command is not a stable subject
35
+ * to grant against, and a remembered approval would silently cover the next command that
36
+ * happened to name the same root.
37
+ */
38
+ export declare function createCommandEscalationApprover(options: TerminalPromptOptions): ((request: {
39
+ command: string;
40
+ writableRoot: string;
41
+ }) => Promise<boolean>) | undefined;
42
+ //# sourceMappingURL=host-approval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-approval.d.ts","sourceRoot":"","sources":["../../../src/core/sandbox/host-approval.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,qBAAqB;IACrC,OAAO,EAAE,eAAe,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC,WAAW,CAAC;CAC5B;AAyDD,4DAA4D;AAC5D,wBAAgB,kBAAkB,CACjC,OAAO,EAAE,qBAAqB,GAC5B,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,SAAS,CAUpE;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACvC,OAAO,EAAE,qBAAqB,GAC5B,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,SAAS,CASlD;AAED;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAC9C,OAAO,EAAE,qBAAqB,GAC5B,CAAC,CAAC,OAAO,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,SAAS,CAYxF","sourcesContent":["import type { TerminalHandoff } from \"./terminal-handoff.ts\";\n\n/**\n * The supervisor's own approval prompt for one refused host.\n *\n * ADR 0023 puts the decision here rather than in the child. An approval asserted from\n * inside the boundary is indistinguishable, at the supervisor, from one forged by a\n * postinstall script or a git hook -- the code the boundary exists to contain -- so the\n * human's answer is read by the side that owns the decision, on a terminal borrowed back\n * from the child for the duration.\n *\n * Returning undefined when there is no terminal is the mechanism, not a fallback. The\n * proxy's own deny-without-asking path then runs unchanged, so ADR 0005's headless, print,\n * JSON, and RPC behaviour holds by construction rather than by a mode check that a later\n * change could forget to make.\n */\nexport interface TerminalPromptOptions {\n\thandoff: TerminalHandoff;\n\tinput?: NodeJS.ReadStream;\n\toutput?: NodeJS.WriteStream;\n}\n\n/**\n * Build a yes/no prompt the supervisor owns, or nothing at all when there is no terminal.\n *\n * Both sandbox escalations ask the same shape of question and must fail closed the same\n * way, so they share one implementation. Returning undefined rather than a\n * function-that-says-no is deliberate: the caller's own refuse path then runs untouched,\n * which is how ADR 0005's headless behaviour stays correct without a mode check.\n */\nfunction createTerminalPrompt(\n\toptions: TerminalPromptOptions,\n\tcompose: (subject: string) => { question: string; granted: string; refused: string },\n): ((subject: string) => Promise<boolean>) | undefined {\n\tconst input = options.input ?? process.stdin;\n\tconst output = options.output ?? process.stdout;\n\tif (!input.isTTY || !output.isTTY) return undefined;\n\n\tfunction readAnswer(): Promise<string> {\n\t\treturn new Promise((resolve) => {\n\t\t\tlet buffer = \"\";\n\t\t\tconst finish = (value: string) => {\n\t\t\t\tinput.off(\"data\", onData);\n\t\t\t\tinput.off(\"error\", onError);\n\t\t\t\tinput.off(\"end\", onEnd);\n\t\t\t\t// The child had stdin in raw mode and takes it back on resume, so the\n\t\t\t\t// supervisor leaves the stream paused rather than owning it past the answer.\n\t\t\t\tinput.pause();\n\t\t\t\tresolve(value);\n\t\t\t};\n\t\t\tconst onData = (chunk: Buffer | string) => {\n\t\t\t\tbuffer += chunk.toString();\n\t\t\t\tconst newline = buffer.indexOf(\"\\n\");\n\t\t\t\tif (newline >= 0) finish(buffer.slice(0, newline));\n\t\t\t};\n\t\t\t// Anything unreadable declines. Treating an unanswerable prompt as consent would\n\t\t\t// hand the grant to whatever broke the terminal.\n\t\t\tconst onError = () => finish(\"\");\n\t\t\tconst onEnd = () => finish(buffer);\n\t\t\tinput.on(\"data\", onData);\n\t\t\tinput.on(\"error\", onError);\n\t\t\tinput.on(\"end\", onEnd);\n\t\t\tinput.resume();\n\t\t});\n\t}\n\n\treturn (subject: string): Promise<boolean> =>\n\t\toptions.handoff.borrowTerminal(async () => {\n\t\t\tconst text = compose(subject);\n\t\t\toutput.write(`\\n${text.question}`);\n\t\t\tconst answer = (await readAnswer()).trim().toLowerCase();\n\t\t\tconst approved = answer === \"y\" || answer === \"yes\";\n\t\t\toutput.write(`${approved ? text.granted : text.refused}\\n\\n`);\n\t\t\treturn approved;\n\t\t});\n}\n\n/** Approve one refused host for the rest of the session. */\nexport function createHostApprover(\n\toptions: TerminalPromptOptions,\n): ((hostname: string, port: number) => Promise<boolean>) | undefined {\n\tconst prompt = createTerminalPrompt(options, (subject) => ({\n\t\tquestion:\n\t\t\t`The sandboxed session asked to reach ${subject}, which is not on the network allowlist.\\n` +\n\t\t\t`Allow it for this session only? [y/N] `,\n\t\tgranted: `Allowed ${subject} for this session. Add it to \"network.allowedHosts\" in your global settings to make it permanent.`,\n\t\trefused: `Refused ${subject}.`,\n\t}));\n\tif (!prompt) return undefined;\n\treturn (hostname: string, port: number) => prompt(`${hostname}:${port}`);\n}\n\n/**\n * Release the host's own git credential for one host, for the rest of the session.\n *\n * Separate from the host approval above even though both are yes/no, because they are\n * different grants and conflating them would let approving a push also release a token to\n * everything else the session later contacts.\n */\nexport function createCredentialReleaser(\n\toptions: TerminalPromptOptions,\n): ((host: string) => Promise<boolean>) | undefined {\n\treturn createTerminalPrompt(options, (subject) => ({\n\t\tquestion:\n\t\t\t`The sandboxed session asked for your git credential for ${subject}.\\n` +\n\t\t\t`It is read from your host credential store and never written into the workspace.\\n` +\n\t\t\t`Release it for this session only? [y/N] `,\n\t\tgranted: `Released the ${subject} credential for this session.`,\n\t\trefused: `Refused the ${subject} credential.`,\n\t}));\n}\n\n/**\n * Approve one command to run in a separate child with one extra writable root.\n *\n * Unlike a host or a credential, nothing is remembered. A command is not a stable subject\n * to grant against, and a remembered approval would silently cover the next command that\n * happened to name the same root.\n */\nexport function createCommandEscalationApprover(\n\toptions: TerminalPromptOptions,\n): ((request: { command: string; writableRoot: string }) => Promise<boolean>) | undefined {\n\tconst prompt = createTerminalPrompt(options, (subject) => ({\n\t\tquestion:\n\t\t\t`The sandboxed session asked to run a command with write access outside its workspace.\\n\\n` +\n\t\t\t` ${subject}\\n\\n` +\n\t\t\t`It runs once, in a separate sandbox. The session's own boundary does not change.\\n` +\n\t\t\t`Allow it? [y/N] `,\n\t\tgranted: \"Ran the command once with that root writable.\",\n\t\trefused: \"Refused.\",\n\t}));\n\tif (!prompt) return undefined;\n\treturn (request) => prompt(`${request.command}\\n (writable: ${request.writableRoot})`);\n}\n"]}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Build a yes/no prompt the supervisor owns, or nothing at all when there is no terminal.
3
+ *
4
+ * Both sandbox escalations ask the same shape of question and must fail closed the same
5
+ * way, so they share one implementation. Returning undefined rather than a
6
+ * function-that-says-no is deliberate: the caller's own refuse path then runs untouched,
7
+ * which is how ADR 0005's headless behaviour stays correct without a mode check.
8
+ */
9
+ function createTerminalPrompt(options, compose) {
10
+ const input = options.input ?? process.stdin;
11
+ const output = options.output ?? process.stdout;
12
+ if (!input.isTTY || !output.isTTY)
13
+ return undefined;
14
+ function readAnswer() {
15
+ return new Promise((resolve) => {
16
+ let buffer = "";
17
+ const finish = (value) => {
18
+ input.off("data", onData);
19
+ input.off("error", onError);
20
+ input.off("end", onEnd);
21
+ // The child had stdin in raw mode and takes it back on resume, so the
22
+ // supervisor leaves the stream paused rather than owning it past the answer.
23
+ input.pause();
24
+ resolve(value);
25
+ };
26
+ const onData = (chunk) => {
27
+ buffer += chunk.toString();
28
+ const newline = buffer.indexOf("\n");
29
+ if (newline >= 0)
30
+ finish(buffer.slice(0, newline));
31
+ };
32
+ // Anything unreadable declines. Treating an unanswerable prompt as consent would
33
+ // hand the grant to whatever broke the terminal.
34
+ const onError = () => finish("");
35
+ const onEnd = () => finish(buffer);
36
+ input.on("data", onData);
37
+ input.on("error", onError);
38
+ input.on("end", onEnd);
39
+ input.resume();
40
+ });
41
+ }
42
+ return (subject) => options.handoff.borrowTerminal(async () => {
43
+ const text = compose(subject);
44
+ output.write(`\n${text.question}`);
45
+ const answer = (await readAnswer()).trim().toLowerCase();
46
+ const approved = answer === "y" || answer === "yes";
47
+ output.write(`${approved ? text.granted : text.refused}\n\n`);
48
+ return approved;
49
+ });
50
+ }
51
+ /** Approve one refused host for the rest of the session. */
52
+ export function createHostApprover(options) {
53
+ const prompt = createTerminalPrompt(options, (subject) => ({
54
+ question: `The sandboxed session asked to reach ${subject}, which is not on the network allowlist.\n` +
55
+ `Allow it for this session only? [y/N] `,
56
+ granted: `Allowed ${subject} for this session. Add it to "network.allowedHosts" in your global settings to make it permanent.`,
57
+ refused: `Refused ${subject}.`,
58
+ }));
59
+ if (!prompt)
60
+ return undefined;
61
+ return (hostname, port) => prompt(`${hostname}:${port}`);
62
+ }
63
+ /**
64
+ * Release the host's own git credential for one host, for the rest of the session.
65
+ *
66
+ * Separate from the host approval above even though both are yes/no, because they are
67
+ * different grants and conflating them would let approving a push also release a token to
68
+ * everything else the session later contacts.
69
+ */
70
+ export function createCredentialReleaser(options) {
71
+ return createTerminalPrompt(options, (subject) => ({
72
+ question: `The sandboxed session asked for your git credential for ${subject}.\n` +
73
+ `It is read from your host credential store and never written into the workspace.\n` +
74
+ `Release it for this session only? [y/N] `,
75
+ granted: `Released the ${subject} credential for this session.`,
76
+ refused: `Refused the ${subject} credential.`,
77
+ }));
78
+ }
79
+ /**
80
+ * Approve one command to run in a separate child with one extra writable root.
81
+ *
82
+ * Unlike a host or a credential, nothing is remembered. A command is not a stable subject
83
+ * to grant against, and a remembered approval would silently cover the next command that
84
+ * happened to name the same root.
85
+ */
86
+ export function createCommandEscalationApprover(options) {
87
+ const prompt = createTerminalPrompt(options, (subject) => ({
88
+ question: `The sandboxed session asked to run a command with write access outside its workspace.\n\n` +
89
+ ` ${subject}\n\n` +
90
+ `It runs once, in a separate sandbox. The session's own boundary does not change.\n` +
91
+ `Allow it? [y/N] `,
92
+ granted: "Ran the command once with that root writable.",
93
+ refused: "Refused.",
94
+ }));
95
+ if (!prompt)
96
+ return undefined;
97
+ return (request) => prompt(`${request.command}\n (writable: ${request.writableRoot})`);
98
+ }
99
+ //# sourceMappingURL=host-approval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-approval.js","sourceRoot":"","sources":["../../../src/core/sandbox/host-approval.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TerminalHandoff } from \"./terminal-handoff.ts\";\n\n/**\n * The supervisor's own approval prompt for one refused host.\n *\n * ADR 0023 puts the decision here rather than in the child. An approval asserted from\n * inside the boundary is indistinguishable, at the supervisor, from one forged by a\n * postinstall script or a git hook -- the code the boundary exists to contain -- so the\n * human's answer is read by the side that owns the decision, on a terminal borrowed back\n * from the child for the duration.\n *\n * Returning undefined when there is no terminal is the mechanism, not a fallback. The\n * proxy's own deny-without-asking path then runs unchanged, so ADR 0005's headless, print,\n * JSON, and RPC behaviour holds by construction rather than by a mode check that a later\n * change could forget to make.\n */\nexport interface TerminalPromptOptions {\n\thandoff: TerminalHandoff;\n\tinput?: NodeJS.ReadStream;\n\toutput?: NodeJS.WriteStream;\n}\n\n/**\n * Build a yes/no prompt the supervisor owns, or nothing at all when there is no terminal.\n *\n * Both sandbox escalations ask the same shape of question and must fail closed the same\n * way, so they share one implementation. Returning undefined rather than a\n * function-that-says-no is deliberate: the caller's own refuse path then runs untouched,\n * which is how ADR 0005's headless behaviour stays correct without a mode check.\n */\nfunction createTerminalPrompt(\n\toptions: TerminalPromptOptions,\n\tcompose: (subject: string) => { question: string; granted: string; refused: string },\n): ((subject: string) => Promise<boolean>) | undefined {\n\tconst input = options.input ?? process.stdin;\n\tconst output = options.output ?? process.stdout;\n\tif (!input.isTTY || !output.isTTY) return undefined;\n\n\tfunction readAnswer(): Promise<string> {\n\t\treturn new Promise((resolve) => {\n\t\t\tlet buffer = \"\";\n\t\t\tconst finish = (value: string) => {\n\t\t\t\tinput.off(\"data\", onData);\n\t\t\t\tinput.off(\"error\", onError);\n\t\t\t\tinput.off(\"end\", onEnd);\n\t\t\t\t// The child had stdin in raw mode and takes it back on resume, so the\n\t\t\t\t// supervisor leaves the stream paused rather than owning it past the answer.\n\t\t\t\tinput.pause();\n\t\t\t\tresolve(value);\n\t\t\t};\n\t\t\tconst onData = (chunk: Buffer | string) => {\n\t\t\t\tbuffer += chunk.toString();\n\t\t\t\tconst newline = buffer.indexOf(\"\\n\");\n\t\t\t\tif (newline >= 0) finish(buffer.slice(0, newline));\n\t\t\t};\n\t\t\t// Anything unreadable declines. Treating an unanswerable prompt as consent would\n\t\t\t// hand the grant to whatever broke the terminal.\n\t\t\tconst onError = () => finish(\"\");\n\t\t\tconst onEnd = () => finish(buffer);\n\t\t\tinput.on(\"data\", onData);\n\t\t\tinput.on(\"error\", onError);\n\t\t\tinput.on(\"end\", onEnd);\n\t\t\tinput.resume();\n\t\t});\n\t}\n\n\treturn (subject: string): Promise<boolean> =>\n\t\toptions.handoff.borrowTerminal(async () => {\n\t\t\tconst text = compose(subject);\n\t\t\toutput.write(`\\n${text.question}`);\n\t\t\tconst answer = (await readAnswer()).trim().toLowerCase();\n\t\t\tconst approved = answer === \"y\" || answer === \"yes\";\n\t\t\toutput.write(`${approved ? text.granted : text.refused}\\n\\n`);\n\t\t\treturn approved;\n\t\t});\n}\n\n/** Approve one refused host for the rest of the session. */\nexport function createHostApprover(\n\toptions: TerminalPromptOptions,\n): ((hostname: string, port: number) => Promise<boolean>) | undefined {\n\tconst prompt = createTerminalPrompt(options, (subject) => ({\n\t\tquestion:\n\t\t\t`The sandboxed session asked to reach ${subject}, which is not on the network allowlist.\\n` +\n\t\t\t`Allow it for this session only? [y/N] `,\n\t\tgranted: `Allowed ${subject} for this session. Add it to \"network.allowedHosts\" in your global settings to make it permanent.`,\n\t\trefused: `Refused ${subject}.`,\n\t}));\n\tif (!prompt) return undefined;\n\treturn (hostname: string, port: number) => prompt(`${hostname}:${port}`);\n}\n\n/**\n * Release the host's own git credential for one host, for the rest of the session.\n *\n * Separate from the host approval above even though both are yes/no, because they are\n * different grants and conflating them would let approving a push also release a token to\n * everything else the session later contacts.\n */\nexport function createCredentialReleaser(\n\toptions: TerminalPromptOptions,\n): ((host: string) => Promise<boolean>) | undefined {\n\treturn createTerminalPrompt(options, (subject) => ({\n\t\tquestion:\n\t\t\t`The sandboxed session asked for your git credential for ${subject}.\\n` +\n\t\t\t`It is read from your host credential store and never written into the workspace.\\n` +\n\t\t\t`Release it for this session only? [y/N] `,\n\t\tgranted: `Released the ${subject} credential for this session.`,\n\t\trefused: `Refused the ${subject} credential.`,\n\t}));\n}\n\n/**\n * Approve one command to run in a separate child with one extra writable root.\n *\n * Unlike a host or a credential, nothing is remembered. A command is not a stable subject\n * to grant against, and a remembered approval would silently cover the next command that\n * happened to name the same root.\n */\nexport function createCommandEscalationApprover(\n\toptions: TerminalPromptOptions,\n): ((request: { command: string; writableRoot: string }) => Promise<boolean>) | undefined {\n\tconst prompt = createTerminalPrompt(options, (subject) => ({\n\t\tquestion:\n\t\t\t`The sandboxed session asked to run a command with write access outside its workspace.\\n\\n` +\n\t\t\t` ${subject}\\n\\n` +\n\t\t\t`It runs once, in a separate sandbox. The session's own boundary does not change.\\n` +\n\t\t\t`Allow it? [y/N] `,\n\t\tgranted: \"Ran the command once with that root writable.\",\n\t\trefused: \"Refused.\",\n\t}));\n\tif (!prompt) return undefined;\n\treturn (request) => prompt(`${request.command}\\n (writable: ${request.writableRoot})`);\n}\n"]}