@geminixiang/mikan 1.0.0-beta.2 → 1.0.0-beta.20

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 (412) hide show
  1. package/CHANGELOG.md +354 -0
  2. package/README.md +42 -16
  3. package/dist/adapter.d.ts +1 -1
  4. package/dist/adapter.d.ts.map +1 -1
  5. package/dist/adapter.js.map +1 -1
  6. package/dist/adapters/discord/bot.d.ts +1 -0
  7. package/dist/adapters/discord/bot.d.ts.map +1 -1
  8. package/dist/adapters/discord/bot.js +36 -67
  9. package/dist/adapters/discord/bot.js.map +1 -1
  10. package/dist/adapters/discord/context.d.ts.map +1 -1
  11. package/dist/adapters/discord/context.js +17 -42
  12. package/dist/adapters/discord/context.js.map +1 -1
  13. package/dist/adapters/github/bot.d.ts +148 -0
  14. package/dist/adapters/github/bot.d.ts.map +1 -0
  15. package/dist/adapters/github/bot.js +1031 -0
  16. package/dist/adapters/github/bot.js.map +1 -0
  17. package/dist/adapters/github/client.d.ts +118 -0
  18. package/dist/adapters/github/client.d.ts.map +1 -0
  19. package/dist/adapters/github/client.js +309 -0
  20. package/dist/adapters/github/client.js.map +1 -0
  21. package/dist/adapters/github/cloudbuild.d.ts +24 -0
  22. package/dist/adapters/github/cloudbuild.d.ts.map +1 -0
  23. package/dist/adapters/github/cloudbuild.js +71 -0
  24. package/dist/adapters/github/cloudbuild.js.map +1 -0
  25. package/dist/adapters/github/context.d.ts +9 -0
  26. package/dist/adapters/github/context.d.ts.map +1 -0
  27. package/dist/adapters/github/context.js +175 -0
  28. package/dist/adapters/github/context.js.map +1 -0
  29. package/dist/adapters/github/gcp-auth.d.ts +31 -0
  30. package/dist/adapters/github/gcp-auth.d.ts.map +1 -0
  31. package/dist/adapters/github/gcp-auth.js +196 -0
  32. package/dist/adapters/github/gcp-auth.js.map +1 -0
  33. package/dist/adapters/github/ids.d.ts +34 -0
  34. package/dist/adapters/github/ids.d.ts.map +1 -0
  35. package/dist/adapters/github/ids.js +53 -0
  36. package/dist/adapters/github/ids.js.map +1 -0
  37. package/dist/adapters/github/repo.d.ts +30 -0
  38. package/dist/adapters/github/repo.d.ts.map +1 -0
  39. package/dist/adapters/github/repo.js +136 -0
  40. package/dist/adapters/github/repo.js.map +1 -0
  41. package/dist/adapters/github/tool-pack.d.ts +14 -0
  42. package/dist/adapters/github/tool-pack.d.ts.map +1 -0
  43. package/dist/adapters/github/tool-pack.js +56 -0
  44. package/dist/adapters/github/tool-pack.js.map +1 -0
  45. package/dist/adapters/github/tools/checks.d.ts +24 -0
  46. package/dist/adapters/github/tools/checks.d.ts.map +1 -0
  47. package/dist/adapters/github/tools/checks.js +116 -0
  48. package/dist/adapters/github/tools/checks.js.map +1 -0
  49. package/dist/adapters/github/tools/issue.d.ts +22 -0
  50. package/dist/adapters/github/tools/issue.d.ts.map +1 -0
  51. package/dist/adapters/github/tools/issue.js +59 -0
  52. package/dist/adapters/github/tools/issue.js.map +1 -0
  53. package/dist/adapters/github/tools/pr.d.ts +22 -0
  54. package/dist/adapters/github/tools/pr.d.ts.map +1 -0
  55. package/dist/adapters/github/tools/pr.js +59 -0
  56. package/dist/adapters/github/tools/pr.js.map +1 -0
  57. package/dist/adapters/github/tools/read.d.ts +22 -0
  58. package/dist/adapters/github/tools/read.d.ts.map +1 -0
  59. package/dist/adapters/github/tools/read.js +152 -0
  60. package/dist/adapters/github/tools/read.js.map +1 -0
  61. package/dist/adapters/github/tools/review-reply.d.ts +19 -0
  62. package/dist/adapters/github/tools/review-reply.d.ts.map +1 -0
  63. package/dist/adapters/github/tools/review-reply.js +49 -0
  64. package/dist/adapters/github/tools/review-reply.js.map +1 -0
  65. package/dist/adapters/github/tools/sync.d.ts +17 -0
  66. package/dist/adapters/github/tools/sync.d.ts.map +1 -0
  67. package/dist/adapters/github/tools/sync.js +45 -0
  68. package/dist/adapters/github/tools/sync.js.map +1 -0
  69. package/dist/adapters/github/types.d.ts +350 -0
  70. package/dist/adapters/github/types.d.ts.map +1 -0
  71. package/dist/adapters/github/types.js +2 -0
  72. package/dist/adapters/github/types.js.map +1 -0
  73. package/dist/adapters/intake.d.ts +16 -5
  74. package/dist/adapters/intake.d.ts.map +1 -1
  75. package/dist/adapters/intake.js +79 -22
  76. package/dist/adapters/intake.js.map +1 -1
  77. package/dist/adapters/slack/bot.d.ts +8 -6
  78. package/dist/adapters/slack/bot.d.ts.map +1 -1
  79. package/dist/adapters/slack/bot.js +81 -133
  80. package/dist/adapters/slack/bot.js.map +1 -1
  81. package/dist/adapters/slack/context.d.ts.map +1 -1
  82. package/dist/adapters/slack/context.js +3 -14
  83. package/dist/adapters/slack/context.js.map +1 -1
  84. package/dist/adapters/slack/response-lifecycle.d.ts.map +1 -1
  85. package/dist/adapters/slack/response-lifecycle.js +14 -17
  86. package/dist/adapters/slack/response-lifecycle.js.map +1 -1
  87. package/dist/adapters/slack/session.d.ts.map +1 -1
  88. package/dist/adapters/slack/session.js +5 -8
  89. package/dist/adapters/slack/session.js.map +1 -1
  90. package/dist/adapters/streaming.d.ts +4 -0
  91. package/dist/adapters/streaming.d.ts.map +1 -1
  92. package/dist/adapters/streaming.js +11 -0
  93. package/dist/adapters/streaming.js.map +1 -1
  94. package/dist/adapters/telegram/bot.d.ts +1 -2
  95. package/dist/adapters/telegram/bot.d.ts.map +1 -1
  96. package/dist/adapters/telegram/bot.js +27 -62
  97. package/dist/adapters/telegram/bot.js.map +1 -1
  98. package/dist/adapters/telegram/context.d.ts.map +1 -1
  99. package/dist/adapters/telegram/context.js +8 -27
  100. package/dist/adapters/telegram/context.js.map +1 -1
  101. package/dist/adapters/types.d.ts +28 -2
  102. package/dist/adapters/types.d.ts.map +1 -1
  103. package/dist/adapters/types.js.map +1 -1
  104. package/dist/agent.d.ts +38 -14
  105. package/dist/agent.d.ts.map +1 -1
  106. package/dist/agent.js +358 -224
  107. package/dist/agent.js.map +1 -1
  108. package/dist/cli/download.d.ts.map +1 -0
  109. package/dist/cli/download.js.map +1 -0
  110. package/dist/cli/ext-git.d.ts +22 -0
  111. package/dist/cli/ext-git.d.ts.map +1 -0
  112. package/dist/cli/ext-git.js +76 -0
  113. package/dist/cli/ext-git.js.map +1 -0
  114. package/dist/cli/ext.d.ts +2 -0
  115. package/dist/cli/ext.d.ts.map +1 -0
  116. package/dist/cli/ext.js +217 -0
  117. package/dist/cli/ext.js.map +1 -0
  118. package/dist/commands/admin.d.ts.map +1 -1
  119. package/dist/commands/admin.js +2 -1
  120. package/dist/commands/admin.js.map +1 -1
  121. package/dist/commands/auto-reply.d.ts.map +1 -1
  122. package/dist/commands/auto-reply.js +2 -6
  123. package/dist/commands/auto-reply.js.map +1 -1
  124. package/dist/commands/extensions.d.ts.map +1 -1
  125. package/dist/commands/extensions.js +16 -6
  126. package/dist/commands/extensions.js.map +1 -1
  127. package/dist/commands/login.d.ts +2 -1
  128. package/dist/commands/login.d.ts.map +1 -1
  129. package/dist/commands/login.js +30 -1
  130. package/dist/commands/login.js.map +1 -1
  131. package/dist/commands/manifest.d.ts +72 -0
  132. package/dist/commands/manifest.d.ts.map +1 -0
  133. package/dist/commands/manifest.js +121 -0
  134. package/dist/commands/manifest.js.map +1 -0
  135. package/dist/commands/model.d.ts.map +1 -1
  136. package/dist/commands/model.js +3 -1
  137. package/dist/commands/model.js.map +1 -1
  138. package/dist/commands/new.d.ts.map +1 -1
  139. package/dist/commands/new.js +2 -1
  140. package/dist/commands/new.js.map +1 -1
  141. package/dist/commands/sandbox.d.ts.map +1 -1
  142. package/dist/commands/sandbox.js +16 -12
  143. package/dist/commands/sandbox.js.map +1 -1
  144. package/dist/commands/text.d.ts +2 -0
  145. package/dist/commands/text.d.ts.map +1 -0
  146. package/dist/commands/text.js +16 -0
  147. package/dist/commands/text.js.map +1 -0
  148. package/dist/commands/types.d.ts +14 -1
  149. package/dist/commands/types.d.ts.map +1 -1
  150. package/dist/commands/types.js.map +1 -1
  151. package/dist/config.d.ts +1 -1
  152. package/dist/config.d.ts.map +1 -1
  153. package/dist/config.js +90 -54
  154. package/dist/config.js.map +1 -1
  155. package/dist/events.d.ts +10 -0
  156. package/dist/events.d.ts.map +1 -1
  157. package/dist/events.js +14 -5
  158. package/dist/events.js.map +1 -1
  159. package/dist/execution-resolver.d.ts +3 -2
  160. package/dist/execution-resolver.d.ts.map +1 -1
  161. package/dist/execution-resolver.js +28 -12
  162. package/dist/execution-resolver.js.map +1 -1
  163. package/dist/harness/extensions/loader.d.ts +39 -9
  164. package/dist/harness/extensions/loader.d.ts.map +1 -1
  165. package/dist/harness/extensions/loader.js +258 -54
  166. package/dist/harness/extensions/loader.js.map +1 -1
  167. package/dist/harness/extensions/registry.d.ts +48 -1
  168. package/dist/harness/extensions/registry.d.ts.map +1 -1
  169. package/dist/harness/extensions/registry.js +146 -0
  170. package/dist/harness/extensions/registry.js.map +1 -1
  171. package/dist/harness/extensions/types.d.ts +161 -14
  172. package/dist/harness/extensions/types.d.ts.map +1 -1
  173. package/dist/harness/extensions/types.js.map +1 -1
  174. package/dist/harness/index.d.ts +5 -5
  175. package/dist/harness/index.d.ts.map +1 -1
  176. package/dist/harness/index.js +2 -2
  177. package/dist/harness/index.js.map +1 -1
  178. package/dist/harness/models.d.ts +5 -0
  179. package/dist/harness/models.d.ts.map +1 -1
  180. package/dist/harness/models.js +10 -0
  181. package/dist/harness/models.js.map +1 -1
  182. package/dist/harness/runner.d.ts +21 -2
  183. package/dist/harness/runner.d.ts.map +1 -1
  184. package/dist/harness/runner.js +80 -22
  185. package/dist/harness/runner.js.map +1 -1
  186. package/dist/harness/session-store.d.ts +4 -1
  187. package/dist/harness/session-store.d.ts.map +1 -1
  188. package/dist/harness/session-store.js +11 -2
  189. package/dist/harness/session-store.js.map +1 -1
  190. package/dist/harness/subagent-runner.d.ts +17 -0
  191. package/dist/harness/subagent-runner.d.ts.map +1 -0
  192. package/dist/harness/subagent-runner.js +307 -0
  193. package/dist/harness/subagent-runner.js.map +1 -0
  194. package/dist/harness/types.d.ts +53 -0
  195. package/dist/harness/types.d.ts.map +1 -1
  196. package/dist/harness/types.js.map +1 -1
  197. package/dist/index.d.ts +1 -1
  198. package/dist/index.d.ts.map +1 -1
  199. package/dist/index.js.map +1 -1
  200. package/dist/main.js +232 -29
  201. package/dist/main.js.map +1 -1
  202. package/dist/provisioner.d.ts.map +1 -1
  203. package/dist/provisioner.js +2 -5
  204. package/dist/provisioner.js.map +1 -1
  205. package/dist/runtime/conversation-runtime.d.ts +1 -1
  206. package/dist/runtime/conversation-runtime.d.ts.map +1 -1
  207. package/dist/runtime/conversation-runtime.js +264 -41
  208. package/dist/runtime/conversation-runtime.js.map +1 -1
  209. package/dist/runtime/types.d.ts +32 -5
  210. package/dist/runtime/types.d.ts.map +1 -1
  211. package/dist/runtime/types.js.map +1 -1
  212. package/dist/sandbox/cloudflare.d.ts +2 -0
  213. package/dist/sandbox/cloudflare.d.ts.map +1 -1
  214. package/dist/sandbox/cloudflare.js +7 -0
  215. package/dist/sandbox/cloudflare.js.map +1 -1
  216. package/dist/sandbox/container.d.ts +3 -0
  217. package/dist/sandbox/container.d.ts.map +1 -1
  218. package/dist/sandbox/container.js +8 -2
  219. package/dist/sandbox/container.js.map +1 -1
  220. package/dist/sandbox/firecracker.d.ts +2 -0
  221. package/dist/sandbox/firecracker.d.ts.map +1 -1
  222. package/dist/sandbox/firecracker.js +7 -1
  223. package/dist/sandbox/firecracker.js.map +1 -1
  224. package/dist/sandbox/gondolin-fleet.d.ts +104 -0
  225. package/dist/sandbox/gondolin-fleet.d.ts.map +1 -0
  226. package/dist/sandbox/gondolin-fleet.js +330 -0
  227. package/dist/sandbox/gondolin-fleet.js.map +1 -0
  228. package/dist/sandbox/gondolin-gateway.d.ts +85 -0
  229. package/dist/sandbox/gondolin-gateway.d.ts.map +1 -0
  230. package/dist/sandbox/gondolin-gateway.js +400 -0
  231. package/dist/sandbox/gondolin-gateway.js.map +1 -0
  232. package/dist/sandbox/gondolin-inventory.d.ts +89 -0
  233. package/dist/sandbox/gondolin-inventory.d.ts.map +1 -0
  234. package/dist/sandbox/gondolin-inventory.js +267 -0
  235. package/dist/sandbox/gondolin-inventory.js.map +1 -0
  236. package/dist/sandbox/gondolin-join.d.ts +62 -0
  237. package/dist/sandbox/gondolin-join.d.ts.map +1 -0
  238. package/dist/sandbox/gondolin-join.js +261 -0
  239. package/dist/sandbox/gondolin-join.js.map +1 -0
  240. package/dist/sandbox/gondolin-nfs-advisory.d.ts +15 -0
  241. package/dist/sandbox/gondolin-nfs-advisory.d.ts.map +1 -0
  242. package/dist/sandbox/gondolin-nfs-advisory.js +60 -0
  243. package/dist/sandbox/gondolin-nfs-advisory.js.map +1 -0
  244. package/dist/sandbox/gondolin-placement.d.ts +32 -0
  245. package/dist/sandbox/gondolin-placement.d.ts.map +1 -0
  246. package/dist/sandbox/gondolin-placement.js +83 -0
  247. package/dist/sandbox/gondolin-placement.js.map +1 -0
  248. package/dist/sandbox/gondolin-remote.d.ts +73 -0
  249. package/dist/sandbox/gondolin-remote.d.ts.map +1 -0
  250. package/dist/sandbox/gondolin-remote.js +352 -0
  251. package/dist/sandbox/gondolin-remote.js.map +1 -0
  252. package/dist/sandbox/gondolin-worker-client.d.ts +139 -0
  253. package/dist/sandbox/gondolin-worker-client.d.ts.map +1 -0
  254. package/dist/sandbox/gondolin-worker-client.js +325 -0
  255. package/dist/sandbox/gondolin-worker-client.js.map +1 -0
  256. package/dist/sandbox/gondolin-worker-main.d.ts +2 -0
  257. package/dist/sandbox/gondolin-worker-main.d.ts.map +1 -0
  258. package/dist/sandbox/gondolin-worker-main.js +22 -0
  259. package/dist/sandbox/gondolin-worker-main.js.map +1 -0
  260. package/dist/sandbox/gondolin-worker.d.ts +55 -0
  261. package/dist/sandbox/gondolin-worker.d.ts.map +1 -0
  262. package/dist/sandbox/gondolin-worker.js +201 -0
  263. package/dist/sandbox/gondolin-worker.js.map +1 -0
  264. package/dist/sandbox/gondolin.d.ts +52 -0
  265. package/dist/sandbox/gondolin.d.ts.map +1 -0
  266. package/dist/sandbox/gondolin.js +425 -0
  267. package/dist/sandbox/gondolin.js.map +1 -0
  268. package/dist/sandbox/host.d.ts +2 -0
  269. package/dist/sandbox/host.d.ts.map +1 -1
  270. package/dist/sandbox/host.js +11 -0
  271. package/dist/sandbox/host.js.map +1 -1
  272. package/dist/sandbox/identity.d.ts +21 -0
  273. package/dist/sandbox/identity.d.ts.map +1 -0
  274. package/dist/sandbox/identity.js +36 -0
  275. package/dist/sandbox/identity.js.map +1 -0
  276. package/dist/sandbox/index.d.ts +4 -3
  277. package/dist/sandbox/index.d.ts.map +1 -1
  278. package/dist/sandbox/index.js +5 -3
  279. package/dist/sandbox/index.js.map +1 -1
  280. package/dist/sandbox/types.d.ts +26 -1
  281. package/dist/sandbox/types.d.ts.map +1 -1
  282. package/dist/sandbox/types.js.map +1 -1
  283. package/dist/sandbox/utils.d.ts +11 -0
  284. package/dist/sandbox/utils.d.ts.map +1 -1
  285. package/dist/sandbox/utils.js +35 -0
  286. package/dist/sandbox/utils.js.map +1 -1
  287. package/dist/sessions/agent-memory-file-manager.d.ts.map +1 -1
  288. package/dist/sessions/agent-memory-file-manager.js +16 -30
  289. package/dist/sessions/agent-memory-file-manager.js.map +1 -1
  290. package/dist/sessions/history-line.d.ts +20 -0
  291. package/dist/sessions/history-line.d.ts.map +1 -0
  292. package/dist/sessions/history-line.js +24 -0
  293. package/dist/sessions/history-line.js.map +1 -0
  294. package/dist/sessions/policy.d.ts.map +1 -1
  295. package/dist/sessions/policy.js +5 -3
  296. package/dist/sessions/policy.js.map +1 -1
  297. package/dist/sessions/session-key.d.ts +31 -0
  298. package/dist/sessions/session-key.d.ts.map +1 -0
  299. package/dist/sessions/session-key.js +44 -0
  300. package/dist/sessions/session-key.js.map +1 -0
  301. package/dist/sessions/store.d.ts.map +1 -1
  302. package/dist/sessions/store.js +2 -2
  303. package/dist/sessions/store.js.map +1 -1
  304. package/dist/tools/bash.d.ts +3 -1
  305. package/dist/tools/bash.d.ts.map +1 -1
  306. package/dist/tools/bash.js +24 -17
  307. package/dist/tools/bash.js.map +1 -1
  308. package/dist/tools/edit.d.ts.map +1 -1
  309. package/dist/tools/edit.js +9 -12
  310. package/dist/tools/edit.js.map +1 -1
  311. package/dist/tools/event.d.ts +1 -1
  312. package/dist/tools/event.d.ts.map +1 -1
  313. package/dist/tools/event.js +33 -4
  314. package/dist/tools/event.js.map +1 -1
  315. package/dist/tools/generate-image.d.ts +17 -0
  316. package/dist/tools/generate-image.d.ts.map +1 -0
  317. package/dist/tools/generate-image.js +63 -0
  318. package/dist/tools/generate-image.js.map +1 -0
  319. package/dist/tools/index.d.ts +16 -2
  320. package/dist/tools/index.d.ts.map +1 -1
  321. package/dist/tools/index.js +27 -3
  322. package/dist/tools/index.js.map +1 -1
  323. package/dist/tools/react.d.ts +15 -0
  324. package/dist/tools/react.d.ts.map +1 -0
  325. package/dist/tools/react.js +40 -0
  326. package/dist/tools/react.js.map +1 -0
  327. package/dist/tools/sandbox.d.ts +2 -2
  328. package/dist/tools/sandbox.d.ts.map +1 -1
  329. package/dist/tools/sandbox.js +8 -7
  330. package/dist/tools/sandbox.js.map +1 -1
  331. package/dist/tools/subagent.d.ts +69 -0
  332. package/dist/tools/subagent.d.ts.map +1 -0
  333. package/dist/tools/subagent.js +286 -0
  334. package/dist/tools/subagent.js.map +1 -0
  335. package/dist/tools/types.d.ts +34 -1
  336. package/dist/tools/types.d.ts.map +1 -1
  337. package/dist/tools/types.js.map +1 -1
  338. package/dist/tools/write.d.ts.map +1 -1
  339. package/dist/tools/write.js +1 -8
  340. package/dist/tools/write.js.map +1 -1
  341. package/dist/trigger.d.ts.map +1 -1
  342. package/dist/trigger.js +1 -2
  343. package/dist/trigger.js.map +1 -1
  344. package/dist/types.d.ts +139 -7
  345. package/dist/types.d.ts.map +1 -1
  346. package/dist/types.js.map +1 -1
  347. package/dist/vault/disabled.d.ts +9 -0
  348. package/dist/vault/disabled.d.ts.map +1 -0
  349. package/dist/vault/disabled.js +23 -0
  350. package/dist/vault/disabled.js.map +1 -0
  351. package/dist/vault/index.d.ts.map +1 -1
  352. package/dist/vault/index.js +3 -24
  353. package/dist/vault/index.js.map +1 -1
  354. package/dist/vault/policy.d.ts +20 -0
  355. package/dist/vault/policy.d.ts.map +1 -0
  356. package/dist/vault/policy.js +20 -0
  357. package/dist/vault/policy.js.map +1 -0
  358. package/dist/vault/routing.d.ts +1 -0
  359. package/dist/vault/routing.d.ts.map +1 -1
  360. package/dist/vault/routing.js +3 -10
  361. package/dist/vault/routing.js.map +1 -1
  362. package/dist/web/admin/portal.d.ts +27 -0
  363. package/dist/web/admin/portal.d.ts.map +1 -1
  364. package/dist/web/admin/portal.js +91 -130
  365. package/dist/web/admin/portal.js.map +1 -1
  366. package/dist/web/admin/types.d.ts +3 -0
  367. package/dist/web/admin/types.d.ts.map +1 -1
  368. package/dist/web/admin/types.js.map +1 -1
  369. package/dist/web/login/oauth.d.ts +2 -3
  370. package/dist/web/login/oauth.d.ts.map +1 -1
  371. package/dist/web/login/oauth.js +0 -31
  372. package/dist/web/login/oauth.js.map +1 -1
  373. package/dist/web/login/portal.js +1 -1
  374. package/dist/web/login/portal.js.map +1 -1
  375. package/dist/web/login/types.d.ts +0 -11
  376. package/dist/web/login/types.d.ts.map +1 -1
  377. package/dist/web/login/types.js.map +1 -1
  378. package/dist/web/portal-shell.d.ts +4 -0
  379. package/dist/web/portal-shell.d.ts.map +1 -0
  380. package/dist/{portal-shell.js → web/portal-shell.js} +2 -2
  381. package/dist/web/portal-shell.js.map +1 -0
  382. package/dist/web/server.d.ts.map +1 -1
  383. package/dist/web/server.js +7 -0
  384. package/dist/web/server.js.map +1 -1
  385. package/dist/web/session-view/command.d.ts.map +1 -1
  386. package/dist/web/session-view/command.js +4 -1
  387. package/dist/web/session-view/command.js.map +1 -1
  388. package/dist/web/session-view/portal.d.ts.map +1 -1
  389. package/dist/web/session-view/portal.js +4 -3
  390. package/dist/web/session-view/portal.js.map +1 -1
  391. package/dist/web/session-view/service.d.ts.map +1 -1
  392. package/dist/web/session-view/service.js +2 -1
  393. package/dist/web/session-view/service.js.map +1 -1
  394. package/dist/web/session-view/types.d.ts +2 -1
  395. package/dist/web/session-view/types.d.ts.map +1 -1
  396. package/dist/web/session-view/types.js.map +1 -1
  397. package/package.json +7 -4
  398. package/dist/download.d.ts.map +0 -1
  399. package/dist/download.js.map +0 -1
  400. package/dist/model-registry.d.ts +0 -4
  401. package/dist/model-registry.d.ts.map +0 -1
  402. package/dist/model-registry.js +0 -7
  403. package/dist/model-registry.js.map +0 -1
  404. package/dist/portal-shell.d.ts +0 -4
  405. package/dist/portal-shell.d.ts.map +0 -1
  406. package/dist/portal-shell.js.map +0 -1
  407. package/dist/runtime/agent-run-controller.d.ts +0 -31
  408. package/dist/runtime/agent-run-controller.d.ts.map +0 -1
  409. package/dist/runtime/agent-run-controller.js +0 -195
  410. package/dist/runtime/agent-run-controller.js.map +0 -1
  411. /package/dist/{download.d.ts → cli/download.d.ts} +0 -0
  412. /package/dist/{download.js → cli/download.js} +0 -0
@@ -0,0 +1,425 @@
1
+ import { createHash } from "node:crypto";
2
+ import { readFileSync, statSync } from "node:fs";
3
+ import * as log from "../log.js";
4
+ import { SandboxError } from "./errors.js";
5
+ import { gondolinInventory } from "./gondolin-inventory.js";
6
+ import { GondolinRuntimeGoneError, GondolinRuntimeInterruptedError, gondolinWorkers, } from "./gondolin-worker-client.js";
7
+ import { gondolinFleet } from "./gondolin-fleet.js";
8
+ import { gondolinGateway } from "./gondolin-gateway.js";
9
+ import { createMountedRuntimePathContext } from "./path-context.js";
10
+ import { withRuntimeBootstrap } from "./container.js";
11
+ import { execReadFile, execWriteFile } from "./utils.js";
12
+ const MINIMUM_NODE_VERSION = [23, 6, 0];
13
+ const MIKAN_IMAGE = "mikan-sandbox:latest";
14
+ const sessions = new Map();
15
+ const transitions = new Map();
16
+ let activeShutdowns = 0;
17
+ let shutdownGeneration = 0;
18
+ class GondolinResourceManager {
19
+ constructor() {
20
+ this.boostedKeys = new Set();
21
+ this.overrideLimits = new Map();
22
+ }
23
+ configure(defaultLimits, boostLimits) {
24
+ this.defaultLimits = defaultLimits;
25
+ this.boostLimits = boostLimits;
26
+ this.boostedKeys.clear();
27
+ this.overrideLimits.clear();
28
+ }
29
+ async boost(key) {
30
+ if (this.boostLimits?.cpus || this.boostLimits?.memory) {
31
+ this.overrideLimits.delete(key);
32
+ this.boostedKeys.add(key);
33
+ }
34
+ return this.getLimitStatus(key);
35
+ }
36
+ async setLimits(key, limits) {
37
+ this.boostedKeys.delete(key);
38
+ this.overrideLimits.set(key, { ...this.defaultLimits, ...limits });
39
+ return this.getLimitStatus(key);
40
+ }
41
+ getLimitStatus(key) {
42
+ return { limits: this.effectiveLimits(key), boosted: this.boostedKeys.has(key) };
43
+ }
44
+ getDefaultLimits() {
45
+ return this.defaultLimits;
46
+ }
47
+ getBoostLimits() {
48
+ return this.boostLimits;
49
+ }
50
+ clear(key) {
51
+ this.boostedKeys.delete(key);
52
+ this.overrideLimits.delete(key);
53
+ }
54
+ effectiveLimits(key) {
55
+ const override = this.overrideLimits.get(key);
56
+ if (override)
57
+ return override;
58
+ if (!this.boostedKeys.has(key))
59
+ return this.defaultLimits;
60
+ return { ...this.defaultLimits, ...this.boostLimits };
61
+ }
62
+ }
63
+ export const gondolinResources = new GondolinResourceManager();
64
+ function parseGondolinSandboxArg(value) {
65
+ if (!value.startsWith("gondolin:"))
66
+ return undefined;
67
+ const profile = value.slice("gondolin:".length);
68
+ if (!profile) {
69
+ throw new SandboxError("Error: gondolin sandbox requires a profile (e.g., gondolin:default)");
70
+ }
71
+ if (profile !== "default" && profile !== "remote") {
72
+ throw new SandboxError(`Error: unsupported gondolin profile '${profile}'. Use 'gondolin:default' or 'gondolin:remote'`);
73
+ }
74
+ return { type: "gondolin", profile };
75
+ }
76
+ function assertSupportedNodeVersion() {
77
+ const [major = 0, minor = 0] = process.versions.node.split(".").map(Number);
78
+ if (major < MINIMUM_NODE_VERSION[0] || (major === MINIMUM_NODE_VERSION[0] && minor < 6)) {
79
+ throw new SandboxError(`Error: gondolin:default requires Node.js >=23.6.0 (current: ${process.versions.node}). Other sandbox modes remain available on Node.js >=22.19.0.`);
80
+ }
81
+ }
82
+ async function validateGondolinSandbox(config) {
83
+ if (config?.profile === "remote") {
84
+ // The remote transports are configured from settings later in startup, so
85
+ // "is a worker source configured?" is checked there (assertRemoteConfigured),
86
+ // not here where nothing has been wired yet.
87
+ console.log(" Gondolin microVM enabled. Profile: remote");
88
+ return;
89
+ }
90
+ assertSupportedNodeVersion();
91
+ console.log(" Gondolin microVM enabled. Profile: default");
92
+ }
93
+ /**
94
+ * Fail fast when `gondolin:remote` is selected but no worker source is
95
+ * configured. Call after the fleet and gateway have been configured.
96
+ */
97
+ export function assertRemoteConfigured() {
98
+ if (!gondolinFleet.isConfigured() && !gondolinGateway.isConfigured()) {
99
+ throw new SandboxError("Error: gondolin:remote requires sandbox.gondolin.remote settings (workers[]/url, or gateway for dial-home workers)");
100
+ }
101
+ // Without a workspaceRoot, mount sources cannot be translated to the worker's
102
+ // filesystem and every runtime is rejected with "escapes the workspace root".
103
+ const missing = gondolinFleet.workersMissingWorkspaceRoot();
104
+ if (missing.length > 0) {
105
+ throw new SandboxError(`Error: gondolin:remote worker(s) [${missing.join(", ")}] have no workspaceRoot; ` +
106
+ `set sandbox.gondolin.remote.workspaceRoot (or gateway.workspaceRoot) to the worker-side shared workspace path`);
107
+ }
108
+ }
109
+ function transportFor(config) {
110
+ return config.profile === "remote" ? gondolinFleet : gondolinWorkers;
111
+ }
112
+ async function resolveDesiredRuntime(config) {
113
+ let image;
114
+ let imageIdentity;
115
+ if (config.profile === "remote") {
116
+ // image assets live on the worker host; the selector is the identity
117
+ image = gondolinFleet.imageSelector() ?? config.image ?? MIKAN_IMAGE;
118
+ imageIdentity = image;
119
+ }
120
+ else {
121
+ const selector = config.image ?? MIKAN_IMAGE;
122
+ const { ensureImageSelector } = (await import("@earendil-works/gondolin"));
123
+ const resolvedImage = await ensureImageSelector(selector);
124
+ image = resolvedImage.assetDir;
125
+ imageIdentity = resolvedImage.buildId ?? resolvedImage.assetDir;
126
+ }
127
+ const mounts = (config.mounts ?? [{ source: config.workspacePath ?? process.cwd(), target: "/workspace" }]).toSorted((left, right) => left.target.localeCompare(right.target));
128
+ return {
129
+ image,
130
+ imageIdentity,
131
+ mounts,
132
+ credentialIdentity: credentialIdentity(mounts),
133
+ limits: config.resourceKey
134
+ ? gondolinResources.getLimitStatus(config.resourceKey).limits
135
+ : undefined,
136
+ };
137
+ }
138
+ /**
139
+ * Content hashes of credential file mounts (files projected outside
140
+ * /workspace). Rotating a credential on the host changes the fingerprint, so
141
+ * the next command recreates the runtime with a fresh projection instead of
142
+ * serving the stale copy for the rest of the VM's life. Workspace files are
143
+ * excluded: the guest writes them back, which would drift the runtime it runs
144
+ * in.
145
+ */
146
+ function credentialIdentity(mounts) {
147
+ const identity = {};
148
+ for (const mount of mounts) {
149
+ if (mount.target.startsWith("/workspace/") || mount.target === "/workspace")
150
+ continue;
151
+ try {
152
+ if (!statSync(mount.source).isFile())
153
+ continue;
154
+ identity[mount.target] = createHash("sha256")
155
+ .update(readFileSync(mount.source))
156
+ .digest("hex");
157
+ }
158
+ catch {
159
+ // missing source: the worker skips it too, so it has no runtime identity
160
+ }
161
+ }
162
+ return identity;
163
+ }
164
+ function runtimeFingerprint(desired) {
165
+ return createHash("sha256")
166
+ .update(JSON.stringify({
167
+ image: desired.imageIdentity,
168
+ mounts: desired.mounts,
169
+ credentials: desired.credentialIdentity,
170
+ limits: desired.limits,
171
+ }))
172
+ .digest("hex");
173
+ }
174
+ function gondolinCpuCount(cpus) {
175
+ if (cpus === undefined)
176
+ return undefined;
177
+ const parsed = Number(cpus);
178
+ if (!Number.isFinite(parsed) || parsed <= 0) {
179
+ throw new SandboxError(`Error: invalid Gondolin CPU limit '${cpus}'`);
180
+ }
181
+ // ponytail: Gondolin exposes whole vCPUs; add host cgroup quotas if fractional enforcement matters.
182
+ return Math.ceil(parsed);
183
+ }
184
+ function createSession(key, config, desired, fingerprint) {
185
+ const transport = transportFor(config);
186
+ let session;
187
+ const runtime = transport
188
+ .ensure(key, {
189
+ image: desired.image,
190
+ mounts: desired.mounts,
191
+ cpus: desired.limits?.cpus,
192
+ vmCpus: gondolinCpuCount(desired.limits?.cpus),
193
+ memory: desired.limits?.memory,
194
+ fingerprint,
195
+ workspacePath: config.workspacePath,
196
+ })
197
+ .catch((error) => {
198
+ if (sessions.get(key) === session)
199
+ sessions.delete(key);
200
+ throw error;
201
+ });
202
+ session = {
203
+ runtime,
204
+ transport,
205
+ fingerprint,
206
+ resourceKey: config.resourceKey,
207
+ activeOperations: 0,
208
+ lastUsed: Date.now(),
209
+ idleWaiters: [],
210
+ };
211
+ return session;
212
+ }
213
+ async function acquireSession(key, config, generation = shutdownGeneration) {
214
+ if (activeShutdowns > 0 || generation !== shutdownGeneration) {
215
+ throw new SandboxError("Error: Gondolin runtime is shutting down");
216
+ }
217
+ const pending = transitions.get(key);
218
+ if (pending) {
219
+ await pending;
220
+ return acquireSession(key, config, generation);
221
+ }
222
+ const desired = await resolveDesiredRuntime(config);
223
+ if (activeShutdowns > 0 || generation !== shutdownGeneration) {
224
+ throw new SandboxError("Error: Gondolin runtime is shutting down");
225
+ }
226
+ const concurrentTransition = transitions.get(key);
227
+ if (concurrentTransition) {
228
+ await concurrentTransition;
229
+ return acquireSession(key, config, generation);
230
+ }
231
+ const fingerprint = runtimeFingerprint(desired);
232
+ const existing = sessions.get(key);
233
+ if (existing?.fingerprint === fingerprint) {
234
+ existing.activeOperations += 1;
235
+ return existing;
236
+ }
237
+ const transition = replaceSession(key, config, desired, fingerprint, existing);
238
+ transitions.set(key, transition);
239
+ try {
240
+ await transition;
241
+ }
242
+ finally {
243
+ if (transitions.get(key) === transition)
244
+ transitions.delete(key);
245
+ }
246
+ return acquireSession(key, config, generation);
247
+ }
248
+ async function replaceSession(key, config, desired, fingerprint, existing) {
249
+ if (existing) {
250
+ await closeSession(key, existing, {
251
+ waitForActiveOperations: true,
252
+ resetResources: false,
253
+ throwOnError: true,
254
+ });
255
+ }
256
+ const replacement = createSession(key, config, desired, fingerprint);
257
+ sessions.set(key, replacement);
258
+ await replacement.runtime;
259
+ }
260
+ function discardDeadSession(key, session) {
261
+ if (sessions.get(key) !== session)
262
+ return;
263
+ sessions.delete(key);
264
+ log.logWarning(`Gondolin runtime for '${key}' died; the session will be recreated`);
265
+ }
266
+ async function withRuntime(key, config, operation) {
267
+ for (let attempt = 0;; attempt += 1) {
268
+ const session = await acquireSession(key, config);
269
+ let handle;
270
+ try {
271
+ handle = await session.runtime;
272
+ return await operation(handle);
273
+ }
274
+ catch (error) {
275
+ const gone = error instanceof GondolinRuntimeGoneError;
276
+ const interrupted = error instanceof GondolinRuntimeInterruptedError;
277
+ if (gone || (interrupted && handle && !(await session.transport.isRuntimeAlive(handle)))) {
278
+ discardDeadSession(key, session);
279
+ }
280
+ // Nothing reached a gone runtime, so recreating and retrying is safe;
281
+ // an interrupted command may have side effects and must surface.
282
+ if (gone && attempt === 0)
283
+ continue;
284
+ if (gone || interrupted) {
285
+ throw new SandboxError(`Error: Gondolin runtime for '${key}' died (${error.message}); it is recreated on the next command`);
286
+ }
287
+ throw error;
288
+ }
289
+ finally {
290
+ session.activeOperations -= 1;
291
+ session.lastUsed = Date.now();
292
+ if (session.activeOperations === 0) {
293
+ for (const resolve of session.idleWaiters.splice(0))
294
+ resolve();
295
+ }
296
+ }
297
+ }
298
+ }
299
+ function waitForIdle(session) {
300
+ if (session.activeOperations === 0)
301
+ return Promise.resolve();
302
+ return new Promise((resolve) => session.idleWaiters.push(resolve));
303
+ }
304
+ async function closeSession(key, session, options = {}) {
305
+ if (sessions.get(key) !== session)
306
+ return;
307
+ sessions.delete(key);
308
+ try {
309
+ if (options.waitForActiveOperations)
310
+ await waitForIdle(session);
311
+ const handle = await session.runtime;
312
+ if (options.stopRuntime !== false)
313
+ await session.transport.stop(handle);
314
+ if (options.resetResources !== false &&
315
+ session.resourceKey &&
316
+ !Array.from(sessions.values()).some(({ resourceKey }) => resourceKey === session.resourceKey)) {
317
+ gondolinResources.clear(session.resourceKey);
318
+ }
319
+ }
320
+ catch (error) {
321
+ session.fingerprint = "";
322
+ // Re-track for a retried close, unless a replacement already claimed the
323
+ // key — then the failed runtime stays for the reconcile paths and
324
+ // clobbering the replacement would leak it too.
325
+ if (!sessions.has(key))
326
+ sessions.set(key, session);
327
+ if (options.throwOnError)
328
+ throw error;
329
+ log.logWarning(`Failed to close Gondolin session '${key}'`, error instanceof Error ? error.message : String(error));
330
+ }
331
+ }
332
+ export async function stopIdleGondolinVms(maxIdleMs, now = Date.now()) {
333
+ const idle = Array.from(sessions.entries()).filter(([key, session]) => !transitions.has(key) &&
334
+ session.activeOperations === 0 &&
335
+ now - session.lastUsed >= maxIdleMs);
336
+ await Promise.all(idle.map(([key, session]) => {
337
+ // Register the close as a transition so a concurrent acquire waits for
338
+ // it instead of racing the shared session slot.
339
+ const transition = closeSession(key, session).finally(() => {
340
+ if (transitions.get(key) === transition)
341
+ transitions.delete(key);
342
+ });
343
+ transitions.set(key, transition);
344
+ return transition;
345
+ }));
346
+ }
347
+ /**
348
+ * Stop workers surviving from a previous mikan that no conversation has
349
+ * adopted — without this, a runtime whose conversation went quiet before the
350
+ * restart would idle forever (its worker only self-stops when every mikan is
351
+ * gone, and the in-memory idle sweep only tracks acquired sessions).
352
+ */
353
+ export async function sweepUnadoptedGondolinWorkers() {
354
+ for (const record of gondolinInventory.listWorkerRecords()) {
355
+ if (sessions.has(record.instanceId) || transitions.has(record.instanceId))
356
+ continue;
357
+ log.logInfo(`Stopping unadopted Gondolin worker ${record.ownerPid} (instance '${record.instanceId}')`);
358
+ await gondolinWorkers.stop({ workerPid: record.ownerPid, sessionId: record.sessionId });
359
+ }
360
+ }
361
+ /**
362
+ * Forget every session without stopping the workers: runtimes deliberately
363
+ * outlive the mikan process so the next one adopts them instead of paying a
364
+ * VM boot per conversation on every deploy.
365
+ */
366
+ export async function disconnectAllGondolinRuntimes() {
367
+ shutdownGeneration += 1;
368
+ activeShutdowns += 1;
369
+ try {
370
+ await Promise.allSettled(transitions.values());
371
+ const current = Array.from(sessions.entries());
372
+ await Promise.all(current.map(([key, session]) => closeSession(key, session, { waitForActiveOperations: true, stopRuntime: false })));
373
+ }
374
+ finally {
375
+ activeShutdowns -= 1;
376
+ }
377
+ }
378
+ function executionSignal(options) {
379
+ const signals = [options?.signal];
380
+ if (options?.timeout && options.timeout > 0) {
381
+ signals.push(AbortSignal.timeout(options.timeout * 1000));
382
+ }
383
+ const active = signals.filter((signal) => signal !== undefined);
384
+ return active.length > 0 ? AbortSignal.any(active) : undefined;
385
+ }
386
+ export class GondolinExecutor {
387
+ constructor(config, env) {
388
+ this.config = config;
389
+ this.env = env;
390
+ // remote runtimes never load gondolin in this process, so the mikan host
391
+ // may stay on the supported Node floor
392
+ if (config.profile !== "remote")
393
+ assertSupportedNodeVersion();
394
+ this.workspacePath = config.workspacePath ?? process.cwd();
395
+ this.instanceId = config.instanceId ?? this.workspacePath;
396
+ }
397
+ async exec(command, options) {
398
+ return withRuntime(this.instanceId, this.config, (handle) => transportFor(this.config).exec(handle, withRuntimeBootstrap(command, this.env), {
399
+ env: this.env,
400
+ signal: executionSignal(options),
401
+ }));
402
+ }
403
+ async readFile(path) {
404
+ return execReadFile(this, path);
405
+ }
406
+ async writeFile(path, content) {
407
+ return execWriteFile(this, path, content);
408
+ }
409
+ getWorkspacePath() {
410
+ return "/workspace";
411
+ }
412
+ getPathContext(hostWorkspaceRoot) {
413
+ return createMountedRuntimePathContext(hostWorkspaceRoot, "/workspace");
414
+ }
415
+ getSandboxConfig() {
416
+ return this.config;
417
+ }
418
+ }
419
+ export const gondolinSandboxAdapter = {
420
+ type: "gondolin",
421
+ parse: parseGondolinSandboxArg,
422
+ validate: validateGondolinSandbox,
423
+ createExecutor: (config, env) => new GondolinExecutor(config, env),
424
+ };
425
+ //# sourceMappingURL=gondolin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gondolin.js","sourceRoot":"","sources":["../../src/sandbox/gondolin.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { readFileSync, statSync } from \"node:fs\";\nimport * as log from \"../log.js\";\nimport type { ResourceLimits, SandboxLimitStatus, SandboxResourceController } from \"../types.js\";\nimport { SandboxError } from \"./errors.js\";\nimport { gondolinInventory } from \"./gondolin-inventory.js\";\nimport {\n GondolinRuntimeGoneError,\n GondolinRuntimeInterruptedError,\n gondolinWorkers,\n type GondolinRuntimeHandle,\n type GondolinRuntimeTransport,\n} from \"./gondolin-worker-client.js\";\nimport { gondolinFleet } from \"./gondolin-fleet.js\";\nimport { gondolinGateway } from \"./gondolin-gateway.js\";\nimport { createMountedRuntimePathContext } from \"./path-context.js\";\nimport { withRuntimeBootstrap } from \"./container.js\";\nimport { execReadFile, execWriteFile } from \"./utils.js\";\nimport type {\n ExecOptions,\n ExecResult,\n Executor,\n GondolinSandboxConfig,\n RuntimePathContext,\n SandboxAdapter,\n} from \"./types.js\";\n\ntype GondolinModule = typeof import(\"@earendil-works/gondolin\");\n\ninterface GondolinSession {\n runtime: Promise<GondolinRuntimeHandle>;\n transport: GondolinRuntimeTransport;\n fingerprint: string;\n resourceKey?: string;\n activeOperations: number;\n lastUsed: number;\n idleWaiters: Array<() => void>;\n}\n\ninterface GondolinDesiredRuntime {\n image: string;\n imageIdentity: string;\n mounts: Array<{ source: string; target: string }>;\n /** Content identity of projected credential files (rotation → drift). */\n credentialIdentity: Record<string, string>;\n limits?: ResourceLimits;\n}\n\nconst MINIMUM_NODE_VERSION = [23, 6, 0] as const;\nconst MIKAN_IMAGE = \"mikan-sandbox:latest\";\nconst sessions = new Map<string, GondolinSession>();\nconst transitions = new Map<string, Promise<void>>();\nlet activeShutdowns = 0;\nlet shutdownGeneration = 0;\n\nclass GondolinResourceManager implements SandboxResourceController {\n private defaultLimits?: ResourceLimits;\n private boostLimits?: ResourceLimits;\n private readonly boostedKeys = new Set<string>();\n private readonly overrideLimits = new Map<string, ResourceLimits>();\n\n configure(defaultLimits?: ResourceLimits, boostLimits?: ResourceLimits): void {\n this.defaultLimits = defaultLimits;\n this.boostLimits = boostLimits;\n this.boostedKeys.clear();\n this.overrideLimits.clear();\n }\n\n async boost(key: string): Promise<SandboxLimitStatus> {\n if (this.boostLimits?.cpus || this.boostLimits?.memory) {\n this.overrideLimits.delete(key);\n this.boostedKeys.add(key);\n }\n return this.getLimitStatus(key);\n }\n\n async setLimits(key: string, limits: ResourceLimits): Promise<SandboxLimitStatus> {\n this.boostedKeys.delete(key);\n this.overrideLimits.set(key, { ...this.defaultLimits, ...limits });\n return this.getLimitStatus(key);\n }\n\n getLimitStatus(key: string): SandboxLimitStatus {\n return { limits: this.effectiveLimits(key), boosted: this.boostedKeys.has(key) };\n }\n\n getDefaultLimits(): ResourceLimits | undefined {\n return this.defaultLimits;\n }\n\n getBoostLimits(): ResourceLimits | undefined {\n return this.boostLimits;\n }\n\n clear(key: string): void {\n this.boostedKeys.delete(key);\n this.overrideLimits.delete(key);\n }\n\n private effectiveLimits(key: string): ResourceLimits | undefined {\n const override = this.overrideLimits.get(key);\n if (override) return override;\n if (!this.boostedKeys.has(key)) return this.defaultLimits;\n return { ...this.defaultLimits, ...this.boostLimits };\n }\n}\n\nexport const gondolinResources = new GondolinResourceManager();\n\nfunction parseGondolinSandboxArg(value: string): GondolinSandboxConfig | undefined {\n if (!value.startsWith(\"gondolin:\")) return undefined;\n\n const profile = value.slice(\"gondolin:\".length);\n if (!profile) {\n throw new SandboxError(\"Error: gondolin sandbox requires a profile (e.g., gondolin:default)\");\n }\n if (profile !== \"default\" && profile !== \"remote\") {\n throw new SandboxError(\n `Error: unsupported gondolin profile '${profile}'. Use 'gondolin:default' or 'gondolin:remote'`,\n );\n }\n return { type: \"gondolin\", profile };\n}\n\nfunction assertSupportedNodeVersion(): void {\n const [major = 0, minor = 0] = process.versions.node.split(\".\").map(Number);\n if (major < MINIMUM_NODE_VERSION[0] || (major === MINIMUM_NODE_VERSION[0] && minor < 6)) {\n throw new SandboxError(\n `Error: gondolin:default requires Node.js >=23.6.0 (current: ${process.versions.node}). Other sandbox modes remain available on Node.js >=22.19.0.`,\n );\n }\n}\n\nasync function validateGondolinSandbox(config?: GondolinSandboxConfig): Promise<void> {\n if (config?.profile === \"remote\") {\n // The remote transports are configured from settings later in startup, so\n // \"is a worker source configured?\" is checked there (assertRemoteConfigured),\n // not here where nothing has been wired yet.\n console.log(\" Gondolin microVM enabled. Profile: remote\");\n return;\n }\n assertSupportedNodeVersion();\n console.log(\" Gondolin microVM enabled. Profile: default\");\n}\n\n/**\n * Fail fast when `gondolin:remote` is selected but no worker source is\n * configured. Call after the fleet and gateway have been configured.\n */\nexport function assertRemoteConfigured(): void {\n if (!gondolinFleet.isConfigured() && !gondolinGateway.isConfigured()) {\n throw new SandboxError(\n \"Error: gondolin:remote requires sandbox.gondolin.remote settings (workers[]/url, or gateway for dial-home workers)\",\n );\n }\n // Without a workspaceRoot, mount sources cannot be translated to the worker's\n // filesystem and every runtime is rejected with \"escapes the workspace root\".\n const missing = gondolinFleet.workersMissingWorkspaceRoot();\n if (missing.length > 0) {\n throw new SandboxError(\n `Error: gondolin:remote worker(s) [${missing.join(\", \")}] have no workspaceRoot; ` +\n `set sandbox.gondolin.remote.workspaceRoot (or gateway.workspaceRoot) to the worker-side shared workspace path`,\n );\n }\n}\n\nfunction transportFor(config: GondolinSandboxConfig): GondolinRuntimeTransport {\n return config.profile === \"remote\" ? gondolinFleet : gondolinWorkers;\n}\n\nasync function resolveDesiredRuntime(\n config: GondolinSandboxConfig,\n): Promise<GondolinDesiredRuntime> {\n let image: string;\n let imageIdentity: string;\n if (config.profile === \"remote\") {\n // image assets live on the worker host; the selector is the identity\n image = gondolinFleet.imageSelector() ?? config.image ?? MIKAN_IMAGE;\n imageIdentity = image;\n } else {\n const selector = config.image ?? MIKAN_IMAGE;\n const { ensureImageSelector } = (await import(\"@earendil-works/gondolin\")) as GondolinModule;\n const resolvedImage = await ensureImageSelector(selector);\n image = resolvedImage.assetDir;\n imageIdentity = resolvedImage.buildId ?? resolvedImage.assetDir;\n }\n const mounts = (\n config.mounts ?? [{ source: config.workspacePath ?? process.cwd(), target: \"/workspace\" }]\n ).toSorted((left, right) => left.target.localeCompare(right.target));\n return {\n image,\n imageIdentity,\n mounts,\n credentialIdentity: credentialIdentity(mounts),\n limits: config.resourceKey\n ? gondolinResources.getLimitStatus(config.resourceKey).limits\n : undefined,\n };\n}\n\n/**\n * Content hashes of credential file mounts (files projected outside\n * /workspace). Rotating a credential on the host changes the fingerprint, so\n * the next command recreates the runtime with a fresh projection instead of\n * serving the stale copy for the rest of the VM's life. Workspace files are\n * excluded: the guest writes them back, which would drift the runtime it runs\n * in.\n */\nfunction credentialIdentity(\n mounts: Array<{ source: string; target: string }>,\n): Record<string, string> {\n const identity: Record<string, string> = {};\n for (const mount of mounts) {\n if (mount.target.startsWith(\"/workspace/\") || mount.target === \"/workspace\") continue;\n try {\n if (!statSync(mount.source).isFile()) continue;\n identity[mount.target] = createHash(\"sha256\")\n .update(readFileSync(mount.source))\n .digest(\"hex\");\n } catch {\n // missing source: the worker skips it too, so it has no runtime identity\n }\n }\n return identity;\n}\n\nfunction runtimeFingerprint(desired: GondolinDesiredRuntime): string {\n return createHash(\"sha256\")\n .update(\n JSON.stringify({\n image: desired.imageIdentity,\n mounts: desired.mounts,\n credentials: desired.credentialIdentity,\n limits: desired.limits,\n }),\n )\n .digest(\"hex\");\n}\n\nfunction gondolinCpuCount(cpus: string | undefined): number | undefined {\n if (cpus === undefined) return undefined;\n const parsed = Number(cpus);\n if (!Number.isFinite(parsed) || parsed <= 0) {\n throw new SandboxError(`Error: invalid Gondolin CPU limit '${cpus}'`);\n }\n // ponytail: Gondolin exposes whole vCPUs; add host cgroup quotas if fractional enforcement matters.\n return Math.ceil(parsed);\n}\n\nfunction createSession(\n key: string,\n config: GondolinSandboxConfig,\n desired: GondolinDesiredRuntime,\n fingerprint: string,\n): GondolinSession {\n const transport = transportFor(config);\n let session: GondolinSession;\n const runtime = transport\n .ensure(key, {\n image: desired.image,\n mounts: desired.mounts,\n cpus: desired.limits?.cpus,\n vmCpus: gondolinCpuCount(desired.limits?.cpus),\n memory: desired.limits?.memory,\n fingerprint,\n workspacePath: config.workspacePath,\n })\n .catch((error) => {\n if (sessions.get(key) === session) sessions.delete(key);\n throw error;\n });\n session = {\n runtime,\n transport,\n fingerprint,\n resourceKey: config.resourceKey,\n activeOperations: 0,\n lastUsed: Date.now(),\n idleWaiters: [],\n };\n return session;\n}\n\nasync function acquireSession(\n key: string,\n config: GondolinSandboxConfig,\n generation = shutdownGeneration,\n): Promise<GondolinSession> {\n if (activeShutdowns > 0 || generation !== shutdownGeneration) {\n throw new SandboxError(\"Error: Gondolin runtime is shutting down\");\n }\n\n const pending = transitions.get(key);\n if (pending) {\n await pending;\n return acquireSession(key, config, generation);\n }\n\n const desired = await resolveDesiredRuntime(config);\n if (activeShutdowns > 0 || generation !== shutdownGeneration) {\n throw new SandboxError(\"Error: Gondolin runtime is shutting down\");\n }\n const concurrentTransition = transitions.get(key);\n if (concurrentTransition) {\n await concurrentTransition;\n return acquireSession(key, config, generation);\n }\n\n const fingerprint = runtimeFingerprint(desired);\n const existing = sessions.get(key);\n if (existing?.fingerprint === fingerprint) {\n existing.activeOperations += 1;\n return existing;\n }\n\n const transition = replaceSession(key, config, desired, fingerprint, existing);\n transitions.set(key, transition);\n try {\n await transition;\n } finally {\n if (transitions.get(key) === transition) transitions.delete(key);\n }\n return acquireSession(key, config, generation);\n}\n\nasync function replaceSession(\n key: string,\n config: GondolinSandboxConfig,\n desired: GondolinDesiredRuntime,\n fingerprint: string,\n existing: GondolinSession | undefined,\n): Promise<void> {\n if (existing) {\n await closeSession(key, existing, {\n waitForActiveOperations: true,\n resetResources: false,\n throwOnError: true,\n });\n }\n const replacement = createSession(key, config, desired, fingerprint);\n sessions.set(key, replacement);\n await replacement.runtime;\n}\n\nfunction discardDeadSession(key: string, session: GondolinSession): void {\n if (sessions.get(key) !== session) return;\n sessions.delete(key);\n log.logWarning(`Gondolin runtime for '${key}' died; the session will be recreated`);\n}\n\nasync function withRuntime<T>(\n key: string,\n config: GondolinSandboxConfig,\n operation: (handle: GondolinRuntimeHandle) => Promise<T>,\n): Promise<T> {\n for (let attempt = 0; ; attempt += 1) {\n const session = await acquireSession(key, config);\n let handle: GondolinRuntimeHandle | undefined;\n try {\n handle = await session.runtime;\n return await operation(handle);\n } catch (error) {\n const gone = error instanceof GondolinRuntimeGoneError;\n const interrupted = error instanceof GondolinRuntimeInterruptedError;\n if (gone || (interrupted && handle && !(await session.transport.isRuntimeAlive(handle)))) {\n discardDeadSession(key, session);\n }\n // Nothing reached a gone runtime, so recreating and retrying is safe;\n // an interrupted command may have side effects and must surface.\n if (gone && attempt === 0) continue;\n if (gone || interrupted) {\n throw new SandboxError(\n `Error: Gondolin runtime for '${key}' died (${(error as Error).message}); it is recreated on the next command`,\n );\n }\n throw error;\n } finally {\n session.activeOperations -= 1;\n session.lastUsed = Date.now();\n if (session.activeOperations === 0) {\n for (const resolve of session.idleWaiters.splice(0)) resolve();\n }\n }\n }\n}\n\nfunction waitForIdle(session: GondolinSession): Promise<void> {\n if (session.activeOperations === 0) return Promise.resolve();\n return new Promise((resolve) => session.idleWaiters.push(resolve));\n}\n\nasync function closeSession(\n key: string,\n session: GondolinSession,\n options: {\n waitForActiveOperations?: boolean;\n resetResources?: boolean;\n throwOnError?: boolean;\n stopRuntime?: boolean;\n } = {},\n): Promise<void> {\n if (sessions.get(key) !== session) return;\n sessions.delete(key);\n try {\n if (options.waitForActiveOperations) await waitForIdle(session);\n const handle = await session.runtime;\n if (options.stopRuntime !== false) await session.transport.stop(handle);\n if (\n options.resetResources !== false &&\n session.resourceKey &&\n !Array.from(sessions.values()).some(({ resourceKey }) => resourceKey === session.resourceKey)\n ) {\n gondolinResources.clear(session.resourceKey);\n }\n } catch (error) {\n session.fingerprint = \"\";\n // Re-track for a retried close, unless a replacement already claimed the\n // key — then the failed runtime stays for the reconcile paths and\n // clobbering the replacement would leak it too.\n if (!sessions.has(key)) sessions.set(key, session);\n if (options.throwOnError) throw error;\n log.logWarning(\n `Failed to close Gondolin session '${key}'`,\n error instanceof Error ? error.message : String(error),\n );\n }\n}\n\nexport async function stopIdleGondolinVms(maxIdleMs: number, now = Date.now()): Promise<void> {\n const idle = Array.from(sessions.entries()).filter(\n ([key, session]) =>\n !transitions.has(key) &&\n session.activeOperations === 0 &&\n now - session.lastUsed >= maxIdleMs,\n );\n await Promise.all(\n idle.map(([key, session]) => {\n // Register the close as a transition so a concurrent acquire waits for\n // it instead of racing the shared session slot.\n const transition = closeSession(key, session).finally(() => {\n if (transitions.get(key) === transition) transitions.delete(key);\n });\n transitions.set(key, transition);\n return transition;\n }),\n );\n}\n\n/**\n * Stop workers surviving from a previous mikan that no conversation has\n * adopted — without this, a runtime whose conversation went quiet before the\n * restart would idle forever (its worker only self-stops when every mikan is\n * gone, and the in-memory idle sweep only tracks acquired sessions).\n */\nexport async function sweepUnadoptedGondolinWorkers(): Promise<void> {\n for (const record of gondolinInventory.listWorkerRecords()) {\n if (sessions.has(record.instanceId) || transitions.has(record.instanceId)) continue;\n log.logInfo(\n `Stopping unadopted Gondolin worker ${record.ownerPid} (instance '${record.instanceId}')`,\n );\n await gondolinWorkers.stop({ workerPid: record.ownerPid, sessionId: record.sessionId });\n }\n}\n\n/**\n * Forget every session without stopping the workers: runtimes deliberately\n * outlive the mikan process so the next one adopts them instead of paying a\n * VM boot per conversation on every deploy.\n */\nexport async function disconnectAllGondolinRuntimes(): Promise<void> {\n shutdownGeneration += 1;\n activeShutdowns += 1;\n try {\n await Promise.allSettled(transitions.values());\n const current = Array.from(sessions.entries());\n await Promise.all(\n current.map(([key, session]) =>\n closeSession(key, session, { waitForActiveOperations: true, stopRuntime: false }),\n ),\n );\n } finally {\n activeShutdowns -= 1;\n }\n}\n\nfunction executionSignal(options?: ExecOptions): AbortSignal | undefined {\n const signals = [options?.signal];\n if (options?.timeout && options.timeout > 0) {\n signals.push(AbortSignal.timeout(options.timeout * 1000));\n }\n const active = signals.filter((signal): signal is AbortSignal => signal !== undefined);\n return active.length > 0 ? AbortSignal.any(active) : undefined;\n}\n\nexport class GondolinExecutor implements Executor {\n private readonly workspacePath: string;\n private readonly instanceId: string;\n\n constructor(\n private readonly config: GondolinSandboxConfig,\n private readonly env?: Record<string, string>,\n ) {\n // remote runtimes never load gondolin in this process, so the mikan host\n // may stay on the supported Node floor\n if (config.profile !== \"remote\") assertSupportedNodeVersion();\n this.workspacePath = config.workspacePath ?? process.cwd();\n this.instanceId = config.instanceId ?? this.workspacePath;\n }\n\n async exec(command: string, options?: ExecOptions): Promise<ExecResult> {\n return withRuntime(this.instanceId, this.config, (handle) =>\n transportFor(this.config).exec(handle, withRuntimeBootstrap(command, this.env), {\n env: this.env,\n signal: executionSignal(options),\n }),\n );\n }\n\n async readFile(path: string): Promise<string> {\n return execReadFile(this, path);\n }\n\n async writeFile(path: string, content: string): Promise<void> {\n return execWriteFile(this, path, content);\n }\n\n getWorkspacePath(): string {\n return \"/workspace\";\n }\n\n getPathContext(hostWorkspaceRoot: string): RuntimePathContext {\n return createMountedRuntimePathContext(hostWorkspaceRoot, \"/workspace\");\n }\n\n getSandboxConfig(): GondolinSandboxConfig {\n return this.config;\n }\n}\n\nexport const gondolinSandboxAdapter: SandboxAdapter<GondolinSandboxConfig> = {\n type: \"gondolin\",\n parse: parseGondolinSandboxArg,\n validate: validateGondolinSandbox,\n createExecutor: (config, env) => new GondolinExecutor(config, env),\n};\n"]}
@@ -1,6 +1,8 @@
1
1
  import type { ExecOptions, ExecResult, Executor, HostSandboxConfig, RuntimePathContext, SandboxAdapter } from "./types.js";
2
2
  export declare class HostExecutor implements Executor {
3
3
  exec(command: string, options?: ExecOptions): Promise<ExecResult>;
4
+ readFile(path: string): Promise<string>;
5
+ writeFile(path: string, content: string): Promise<void>;
4
6
  getWorkspacePath(hostPath: string): string;
5
7
  getPathContext(hostWorkspaceRoot: string): RuntimePathContext;
6
8
  getSandboxConfig(): HostSandboxConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/sandbox/host.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,QAAQ,EACR,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACf,MAAM,YAAY,CAAC;AAWpB,qBAAa,YAAa,YAAW,QAAQ;IACrC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAuEtE;IAED,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEzC;IAED,cAAc,CAAC,iBAAiB,EAAE,MAAM,GAAG,kBAAkB,CAE5D;IAED,gBAAgB,IAAI,iBAAiB,CAEpC;CACF;AAED,eAAO,MAAM,kBAAkB,EAAE,cAAc,CAAC,iBAAiB,CAIhE,CAAC"}
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/sandbox/host.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,QAAQ,EACR,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACf,MAAM,YAAY,CAAC;AAWpB,qBAAa,YAAa,YAAW,QAAQ;IACrC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAuEtE;IAEK,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE5C;IAEK,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK5D;IAED,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEzC;IAED,cAAc,CAAC,iBAAiB,EAAE,MAAM,GAAG,kBAAkB,CAE5D;IAED,gBAAgB,IAAI,iBAAiB,CAEpC;CACF;AAED,eAAO,MAAM,kBAAkB,EAAE,cAAc,CAAC,iBAAiB,CAIhE,CAAC"}
@@ -1,4 +1,6 @@
1
1
  import { spawn } from "child_process";
2
+ import { mkdir, readFile, rename, writeFile } from "fs/promises";
3
+ import { dirname } from "path";
2
4
  import { killProcessTree } from "./utils.js";
3
5
  import { createMountedRuntimePathContext } from "./path-context.js";
4
6
  function parseHostSandboxArg(value) {
@@ -67,6 +69,15 @@ export class HostExecutor {
67
69
  });
68
70
  });
69
71
  }
72
+ async readFile(path) {
73
+ return readFile(path, "utf-8");
74
+ }
75
+ async writeFile(path, content) {
76
+ await mkdir(dirname(path), { recursive: true });
77
+ const stage = `${path}.mikan-stage`;
78
+ await writeFile(stage, content, "utf-8");
79
+ await rename(stage, path);
80
+ }
70
81
  getWorkspacePath(hostPath) {
71
82
  return hostPath;
72
83
  }
@@ -1 +1 @@
1
- {"version":3,"file":"host.js","sourceRoot":"","sources":["../../src/sandbox/host.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"child_process\";\nimport type {\n ExecOptions,\n ExecResult,\n Executor,\n HostSandboxConfig,\n RuntimePathContext,\n SandboxAdapter,\n} from \"./types.js\";\nimport { killProcessTree } from \"./utils.js\";\nimport { createMountedRuntimePathContext } from \"./path-context.js\";\n\nfunction parseHostSandboxArg(value: string): HostSandboxConfig | undefined {\n if (value === \"host\") {\n return { type: \"host\" };\n }\n return undefined;\n}\n\nexport class HostExecutor implements Executor {\n async exec(command: string, options?: ExecOptions): Promise<ExecResult> {\n return new Promise((resolve, reject) => {\n const shell = process.platform === \"win32\" ? \"cmd\" : \"sh\";\n const shellArgs = process.platform === \"win32\" ? [\"/c\"] : [\"-c\"];\n\n const child = spawn(shell, [...shellArgs, command], {\n detached: true,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n\n let stdout = \"\";\n let stderr = \"\";\n let timedOut = false;\n\n const timeoutHandle =\n options?.timeout && options.timeout > 0\n ? setTimeout(() => {\n timedOut = true;\n killProcessTree(child.pid!);\n }, options.timeout * 1000)\n : undefined;\n\n const onAbort = () => {\n if (child.pid) killProcessTree(child.pid);\n };\n\n if (options?.signal) {\n if (options.signal.aborted) {\n onAbort();\n } else {\n options.signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n }\n\n child.stdout?.on(\"data\", (data) => {\n stdout += data.toString();\n if (stdout.length > 10 * 1024 * 1024) {\n stdout = stdout.slice(0, 10 * 1024 * 1024);\n }\n });\n\n child.stderr?.on(\"data\", (data) => {\n stderr += data.toString();\n if (stderr.length > 10 * 1024 * 1024) {\n stderr = stderr.slice(0, 10 * 1024 * 1024);\n }\n });\n\n child.on(\"close\", (code) => {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n if (options?.signal) {\n options.signal.removeEventListener(\"abort\", onAbort);\n }\n\n if (options?.signal?.aborted) {\n reject(new Error(`${stdout}\\n${stderr}\\nCommand aborted`.trim()));\n return;\n }\n\n if (timedOut) {\n reject(\n new Error(\n `${stdout}\\n${stderr}\\nCommand timed out after ${options?.timeout} seconds`.trim(),\n ),\n );\n return;\n }\n\n resolve({ stdout, stderr, code: code ?? 0 });\n });\n });\n }\n\n getWorkspacePath(hostPath: string): string {\n return hostPath;\n }\n\n getPathContext(hostWorkspaceRoot: string): RuntimePathContext {\n return createMountedRuntimePathContext(hostWorkspaceRoot, hostWorkspaceRoot);\n }\n\n getSandboxConfig(): HostSandboxConfig {\n return { type: \"host\" };\n }\n}\n\nexport const hostSandboxAdapter: SandboxAdapter<HostSandboxConfig> = {\n type: \"host\",\n parse: parseHostSandboxArg,\n createExecutor: () => new HostExecutor(),\n};\n"]}
1
+ {"version":3,"file":"host.js","sourceRoot":"","sources":["../../src/sandbox/host.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"child_process\";\nimport { mkdir, readFile, rename, writeFile } from \"fs/promises\";\nimport { dirname } from \"path\";\nimport type {\n ExecOptions,\n ExecResult,\n Executor,\n HostSandboxConfig,\n RuntimePathContext,\n SandboxAdapter,\n} from \"./types.js\";\nimport { killProcessTree } from \"./utils.js\";\nimport { createMountedRuntimePathContext } from \"./path-context.js\";\n\nfunction parseHostSandboxArg(value: string): HostSandboxConfig | undefined {\n if (value === \"host\") {\n return { type: \"host\" };\n }\n return undefined;\n}\n\nexport class HostExecutor implements Executor {\n async exec(command: string, options?: ExecOptions): Promise<ExecResult> {\n return new Promise((resolve, reject) => {\n const shell = process.platform === \"win32\" ? \"cmd\" : \"sh\";\n const shellArgs = process.platform === \"win32\" ? [\"/c\"] : [\"-c\"];\n\n const child = spawn(shell, [...shellArgs, command], {\n detached: true,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n\n let stdout = \"\";\n let stderr = \"\";\n let timedOut = false;\n\n const timeoutHandle =\n options?.timeout && options.timeout > 0\n ? setTimeout(() => {\n timedOut = true;\n killProcessTree(child.pid!);\n }, options.timeout * 1000)\n : undefined;\n\n const onAbort = () => {\n if (child.pid) killProcessTree(child.pid);\n };\n\n if (options?.signal) {\n if (options.signal.aborted) {\n onAbort();\n } else {\n options.signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n }\n\n child.stdout?.on(\"data\", (data) => {\n stdout += data.toString();\n if (stdout.length > 10 * 1024 * 1024) {\n stdout = stdout.slice(0, 10 * 1024 * 1024);\n }\n });\n\n child.stderr?.on(\"data\", (data) => {\n stderr += data.toString();\n if (stderr.length > 10 * 1024 * 1024) {\n stderr = stderr.slice(0, 10 * 1024 * 1024);\n }\n });\n\n child.on(\"close\", (code) => {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n if (options?.signal) {\n options.signal.removeEventListener(\"abort\", onAbort);\n }\n\n if (options?.signal?.aborted) {\n reject(new Error(`${stdout}\\n${stderr}\\nCommand aborted`.trim()));\n return;\n }\n\n if (timedOut) {\n reject(\n new Error(\n `${stdout}\\n${stderr}\\nCommand timed out after ${options?.timeout} seconds`.trim(),\n ),\n );\n return;\n }\n\n resolve({ stdout, stderr, code: code ?? 0 });\n });\n });\n }\n\n async readFile(path: string): Promise<string> {\n return readFile(path, \"utf-8\");\n }\n\n async writeFile(path: string, content: string): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n const stage = `${path}.mikan-stage`;\n await writeFile(stage, content, \"utf-8\");\n await rename(stage, path);\n }\n\n getWorkspacePath(hostPath: string): string {\n return hostPath;\n }\n\n getPathContext(hostWorkspaceRoot: string): RuntimePathContext {\n return createMountedRuntimePathContext(hostWorkspaceRoot, hostWorkspaceRoot);\n }\n\n getSandboxConfig(): HostSandboxConfig {\n return { type: \"host\" };\n }\n}\n\nexport const hostSandboxAdapter: SandboxAdapter<HostSandboxConfig> = {\n type: \"host\",\n parse: parseHostSandboxArg,\n createExecutor: () => new HostExecutor(),\n};\n"]}
@@ -0,0 +1,21 @@
1
+ import type { SandboxConfig } from "./types.js";
2
+ /**
3
+ * Runtime actor identity: the one key that names a conversation's vault dir,
4
+ * docker container and network, and cloudflare sandbox suffix. Everything
5
+ * that needs such a name consumes actorKey(); nothing may re-derive or
6
+ * re-sanitize it — two sanitizers with divergent outputs used to make a
7
+ * container/vault mismatch a silent wrong-identity bug rather than an error.
8
+ */
9
+ export declare function sanitizeIdentitySegment(value: string): string;
10
+ /**
11
+ * The actor key for a sandbox config: per-conversation for managed sandboxes
12
+ * (image/gondolin/cloudflare/firecracker), the fixed container name for a shared
13
+ * container, and the platform user id on the host.
14
+ */
15
+ export declare function actorKey(baseConfig: SandboxConfig, ids: {
16
+ userId: string;
17
+ conversationId: string;
18
+ }): string;
19
+ /** Scope a base cloudflare sandbox id to one actor key. */
20
+ export declare function scopeCloudflareSandboxId(baseId: string, actorVaultKey: string): string;
21
+ //# sourceMappingURL=identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/sandbox/identity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM7D;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CACtB,UAAU,EAAE,aAAa,EACzB,GAAG,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GAC9C,MAAM,CAaR;AAED,2DAA2D;AAC3D,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAEtF"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Runtime actor identity: the one key that names a conversation's vault dir,
3
+ * docker container and network, and cloudflare sandbox suffix. Everything
4
+ * that needs such a name consumes actorKey(); nothing may re-derive or
5
+ * re-sanitize it — two sanitizers with divergent outputs used to make a
6
+ * container/vault mismatch a silent wrong-identity bug rather than an error.
7
+ */
8
+ export function sanitizeIdentitySegment(value) {
9
+ const sanitized = value
10
+ .toLowerCase()
11
+ .replace(/[^a-z0-9]+/g, "-")
12
+ .replace(/^-+|-+$/g, "");
13
+ return sanitized || "unknown";
14
+ }
15
+ /**
16
+ * The actor key for a sandbox config: per-conversation for managed sandboxes
17
+ * (image/gondolin/cloudflare/firecracker), the fixed container name for a shared
18
+ * container, and the platform user id on the host.
19
+ */
20
+ export function actorKey(baseConfig, ids) {
21
+ if (baseConfig.type === "container") {
22
+ return `container-${baseConfig.container}`;
23
+ }
24
+ if (baseConfig.type === "image" ||
25
+ baseConfig.type === "gondolin" ||
26
+ baseConfig.type === "cloudflare" ||
27
+ baseConfig.type === "firecracker") {
28
+ return sanitizeIdentitySegment(ids.conversationId);
29
+ }
30
+ return ids.userId;
31
+ }
32
+ /** Scope a base cloudflare sandbox id to one actor key. */
33
+ export function scopeCloudflareSandboxId(baseId, actorVaultKey) {
34
+ return `${baseId}-${sanitizeIdentitySegment(actorVaultKey)}`;
35
+ }
36
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/sandbox/identity.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAa;IACnD,MAAM,SAAS,GAAG,KAAK;SACpB,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC3B,OAAO,SAAS,IAAI,SAAS,CAAC;AAChC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CACtB,UAAyB,EACzB,GAA+C;IAE/C,IAAI,UAAU,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QACpC,OAAO,aAAa,UAAU,CAAC,SAAS,EAAE,CAAC;IAC7C,CAAC;IACD,IACE,UAAU,CAAC,IAAI,KAAK,OAAO;QAC3B,UAAU,CAAC,IAAI,KAAK,UAAU;QAC9B,UAAU,CAAC,IAAI,KAAK,YAAY;QAChC,UAAU,CAAC,IAAI,KAAK,aAAa,EACjC,CAAC;QACD,OAAO,uBAAuB,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,GAAG,CAAC,MAAM,CAAC;AACpB,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,wBAAwB,CAAC,MAAc,EAAE,aAAqB;IAC5E,OAAO,GAAG,MAAM,IAAI,uBAAuB,CAAC,aAAa,CAAC,EAAE,CAAC;AAC/D,CAAC","sourcesContent":["import type { SandboxConfig } from \"./types.js\";\n\n/**\n * Runtime actor identity: the one key that names a conversation's vault dir,\n * docker container and network, and cloudflare sandbox suffix. Everything\n * that needs such a name consumes actorKey(); nothing may re-derive or\n * re-sanitize it — two sanitizers with divergent outputs used to make a\n * container/vault mismatch a silent wrong-identity bug rather than an error.\n */\nexport function sanitizeIdentitySegment(value: string): string {\n const sanitized = value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n return sanitized || \"unknown\";\n}\n\n/**\n * The actor key for a sandbox config: per-conversation for managed sandboxes\n * (image/gondolin/cloudflare/firecracker), the fixed container name for a shared\n * container, and the platform user id on the host.\n */\nexport function actorKey(\n baseConfig: SandboxConfig,\n ids: { userId: string; conversationId: string },\n): string {\n if (baseConfig.type === \"container\") {\n return `container-${baseConfig.container}`;\n }\n if (\n baseConfig.type === \"image\" ||\n baseConfig.type === \"gondolin\" ||\n baseConfig.type === \"cloudflare\" ||\n baseConfig.type === \"firecracker\"\n ) {\n return sanitizeIdentitySegment(ids.conversationId);\n }\n return ids.userId;\n}\n\n/** Scope a base cloudflare sandbox id to one actor key. */\nexport function scopeCloudflareSandboxId(baseId: string, actorVaultKey: string): string {\n return `${baseId}-${sanitizeIdentitySegment(actorVaultKey)}`;\n}\n"]}