@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 @@
1
+ {"version":3,"file":"gondolin-join.js","sourceRoot":"","sources":["../../src/sandbox/gondolin-join.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFile } from \"node:child_process\";\nimport { X509Certificate, createHash, randomBytes, timingSafeEqual } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport * as log from \"../log.js\";\nimport { isRecord, readJsonFileIfExists } from \"../utils/file-guards.js\";\n\nconst execFileAsync = promisify(execFile);\n\nconst TOKEN_TTL_SECONDS = 15 * 60;\nconst CA_DAYS = 3650;\nconst SERVER_CERT_DAYS = 825;\nconst WORKER_CERT_DAYS = 365;\n\ninterface JoinTokenRecord {\n id: string;\n secretHash: string;\n expiresAt: number;\n usedAt?: number;\n}\n\nfunction isTokenTable(value: unknown): value is { tokens: JoinTokenRecord[] } {\n return (\n isRecord(value) &&\n Array.isArray(value.tokens) &&\n value.tokens.every(\n (entry) =>\n isRecord(entry) &&\n typeof entry.id === \"string\" &&\n typeof entry.secretHash === \"string\" &&\n typeof entry.expiresAt === \"number\",\n )\n );\n}\n\nfunction sha256Hex(data: string | Buffer): string {\n return createHash(\"sha256\").update(data).digest(\"hex\");\n}\n\n/**\n * Certificate provisioning and join-token authority for dial-home workers.\n *\n * Owns a private CA under the state dir (`gondolin-gateway/`), auto-issues the\n * gateway's own server certificate from it, and exchanges one-time join\n * tokens for CA-signed worker client certificates — the kubeadm-style\n * bootstrap that replaces hand-provisioned mTLS material. All X.509 issuance\n * shells out to openssl (Node can parse but not issue certificates).\n */\nclass GondolinJoinService {\n private dir?: string;\n private execImpl: (cmd: string, args: string[]) => Promise<unknown> = execFileAsync;\n private now: () => number = Date.now;\n private tokenTtlSeconds = TOKEN_TTL_SECONDS;\n\n configure(\n dir?: string,\n overrides?: {\n execFile?: (cmd: string, args: string[]) => Promise<unknown>;\n now?: () => number;\n tokenTtlSeconds?: number;\n },\n ): void {\n this.dir = dir;\n this.execImpl = overrides?.execFile ?? execFileAsync;\n this.now = overrides?.now ?? Date.now;\n this.tokenTtlSeconds = overrides?.tokenTtlSeconds ?? TOKEN_TTL_SECONDS;\n }\n\n isConfigured(): boolean {\n return this.dir !== undefined;\n }\n\n paths(): {\n caFile: string;\n caKeyFile: string;\n serverCertFile: string;\n serverKeyFile: string;\n } {\n const dir = this.requireDir();\n return {\n caFile: join(dir, \"ca.pem\"),\n caKeyFile: join(dir, \"ca-key.pem\"),\n serverCertFile: join(dir, \"server.pem\"),\n serverKeyFile: join(dir, \"server-key.pem\"),\n };\n }\n\n /** Create the worker CA on first use; idempotent afterwards. */\n async ensureCa(): Promise<void> {\n const { caFile, caKeyFile } = this.paths();\n if (existsSync(caFile) && existsSync(caKeyFile)) return;\n mkdirSync(this.requireDir(), { recursive: true, mode: 0o700 });\n await this.openssl([\n \"req\",\n \"-x509\",\n \"-newkey\",\n \"ec\",\n \"-pkeyopt\",\n \"ec_paramgen_curve:P-256\",\n \"-keyout\",\n caKeyFile,\n \"-out\",\n caFile,\n \"-days\",\n String(CA_DAYS),\n \"-nodes\",\n \"-subj\",\n \"/CN=mikan-worker-ca\",\n ]);\n log.logInfo(`Gondolin worker CA created at ${caFile} (pin ${this.caFingerprint()})`);\n }\n\n /**\n * Issue the gateway's server certificate from the worker CA so joining\n * workers can verify the host against the pinned CA. Reissued when the SAN\n * list changes.\n */\n async ensureServerCert(hostnames: string[]): Promise<{ certFile: string; keyFile: string }> {\n await this.ensureCa();\n const { caFile, caKeyFile, serverCertFile, serverKeyFile } = this.paths();\n const altNames = this.subjectAltNames(hostnames);\n if (existsSync(serverCertFile) && existsSync(serverKeyFile)) {\n const existing = new X509Certificate(readFileSync(serverCertFile));\n const current = (existing.subjectAltName ?? \"\")\n .split(\", \")\n .filter(Boolean)\n .toSorted()\n .join(\",\");\n const wanted = altNames\n .split(\",\")\n .map((entry) => entry.replace(\"DNS:\", \"DNS:\").replace(\"IP:\", \"IP Address:\"))\n .toSorted()\n .join(\",\");\n if (current === wanted && this.now() < existing.validToDate.getTime() - 24 * 3600 * 1000) {\n return { certFile: serverCertFile, keyFile: serverKeyFile };\n }\n }\n const csrFile = join(this.requireDir(), \"server.csr\");\n const extFile = join(this.requireDir(), \"server.ext\");\n writeFileSync(extFile, `subjectAltName=${altNames}\\n`);\n await this.openssl([\n \"req\",\n \"-newkey\",\n \"ec\",\n \"-pkeyopt\",\n \"ec_paramgen_curve:P-256\",\n \"-keyout\",\n serverKeyFile,\n \"-out\",\n csrFile,\n \"-nodes\",\n \"-subj\",\n \"/CN=mikan-gateway\",\n ]);\n await this.openssl([\n \"x509\",\n \"-req\",\n \"-in\",\n csrFile,\n \"-CA\",\n caFile,\n \"-CAkey\",\n caKeyFile,\n \"-CAcreateserial\",\n \"-days\",\n String(SERVER_CERT_DAYS),\n \"-extfile\",\n extFile,\n \"-out\",\n serverCertFile,\n ]);\n rmSync(csrFile, { force: true });\n rmSync(extFile, { force: true });\n log.logInfo(`Gondolin gateway certificate issued for ${altNames}`);\n return { certFile: serverCertFile, keyFile: serverKeyFile };\n }\n\n /** SHA-256 of the CA certificate DER — the join command's --ca-pin. */\n caFingerprint(): string {\n const certificate = new X509Certificate(readFileSync(this.paths().caFile));\n return `sha256:${certificate.fingerprint256.replaceAll(\":\", \"\").toLowerCase()}`;\n }\n\n /** Mint a single-use join token; only its hash is stored. */\n async mintToken(): Promise<{ token: string; fingerprint: string; expiresAt: number }> {\n await this.ensureCa();\n const id = randomBytes(4).toString(\"hex\");\n const secret = randomBytes(24).toString(\"base64url\");\n const expiresAt = this.now() + this.tokenTtlSeconds * 1000;\n const table = this.readTokens();\n table.push({ id, secretHash: sha256Hex(secret), expiresAt });\n this.writeTokens(table);\n return { token: `${id}.${secret}`, fingerprint: this.caFingerprint(), expiresAt };\n }\n\n /** Validate and burn a join token (single use, TTL-bounded). */\n consumeToken(token: string): boolean {\n const separator = token.indexOf(\".\");\n if (separator <= 0) return false;\n const id = token.slice(0, separator);\n const secret = token.slice(separator + 1);\n const table = this.readTokens();\n const record = table.find((entry) => entry.id === id);\n if (!record || record.usedAt !== undefined || this.now() > record.expiresAt) return false;\n const expected = Buffer.from(record.secretHash, \"hex\");\n const actual = createHash(\"sha256\").update(secret).digest();\n if (expected.length !== actual.length || !timingSafeEqual(expected, actual)) return false;\n record.usedAt = this.now();\n this.writeTokens(table);\n return true;\n }\n\n /** Sign a joining worker's CSR with the worker CA. */\n async signCsr(csrPem: string): Promise<{ certPem: string; caPem: string }> {\n await this.ensureCa();\n const { caFile, caKeyFile } = this.paths();\n const scratch = join(tmpdir(), `mikan-join-${randomBytes(6).toString(\"hex\")}`);\n mkdirSync(scratch, { recursive: true, mode: 0o700 });\n const csrFile = join(scratch, \"worker.csr\");\n const certFile = join(scratch, \"worker.pem\");\n try {\n writeFileSync(csrFile, csrPem);\n await this.openssl([\n \"x509\",\n \"-req\",\n \"-in\",\n csrFile,\n \"-CA\",\n caFile,\n \"-CAkey\",\n caKeyFile,\n \"-CAcreateserial\",\n \"-days\",\n String(WORKER_CERT_DAYS),\n \"-out\",\n certFile,\n ]);\n return {\n certPem: readFileSync(certFile, \"utf8\"),\n caPem: readFileSync(caFile, \"utf8\"),\n };\n } finally {\n rmSync(scratch, { recursive: true, force: true });\n }\n }\n\n private subjectAltNames(hostnames: string[]): string {\n const entries = new Set<string>([\"IP:127.0.0.1\", \"DNS:localhost\"]);\n for (const name of hostnames) {\n if (/^\\d+\\.\\d+\\.\\d+\\.\\d+$/.test(name) || name.includes(\":\")) entries.add(`IP:${name}`);\n else entries.add(`DNS:${name}`);\n }\n return Array.from(entries).join(\",\");\n }\n\n private async openssl(args: string[]): Promise<void> {\n try {\n await this.execImpl(\"openssl\", args);\n } catch (err) {\n throw new Error(\n `openssl ${args[0]} failed (is openssl installed?): ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n }\n\n private tokensPath(): string {\n return join(this.requireDir(), \"tokens.json\");\n }\n\n private readTokens(): JoinTokenRecord[] {\n let table: JoinTokenRecord[] = [];\n try {\n const parsed = readJsonFileIfExists(\n this.tokensPath(),\n isTokenTable,\n (detail) => `Malformed join token table: ${detail}`,\n );\n table = parsed?.tokens ?? [];\n } catch (err) {\n log.logWarning(\n \"Resetting Gondolin join token table\",\n err instanceof Error ? err.message : String(err),\n );\n }\n return table.filter((entry) => this.now() <= entry.expiresAt);\n }\n\n private writeTokens(tokens: JoinTokenRecord[]): void {\n mkdirSync(this.requireDir(), { recursive: true, mode: 0o700 });\n const staged = `${this.tokensPath()}.tmp`;\n writeFileSync(staged, JSON.stringify({ tokens }, null, 2) + \"\\n\", { mode: 0o600 });\n renameSync(staged, this.tokensPath());\n }\n\n private requireDir(): string {\n if (!this.dir) throw new Error(\"gondolin join service is not configured\");\n return this.dir;\n }\n}\n\nexport const gondolinJoin = new GondolinJoinService();\n"]}
@@ -0,0 +1,15 @@
1
+ interface NfsAdvisoryDeps {
2
+ os?: NodeJS.Platform;
3
+ run?: (cmd: string, args: string[]) => string;
4
+ emit?: (line: string) => void;
5
+ }
6
+ /**
7
+ * Startup advisory for gondolin:remote workers: they need the mikan-host
8
+ * workspace on shared storage, and the simplest way is to NFS-export it from
9
+ * the host itself. mikan does NOT touch root or system files — it only checks
10
+ * whether the workspace is already exported and, if not, prints the
11
+ * OS-appropriate commands the operator runs once by hand.
12
+ */
13
+ export declare function checkWorkspaceExported(workspaceDir: string, gatewayHostname?: string, deps?: NfsAdvisoryDeps): void;
14
+ export {};
15
+ //# sourceMappingURL=gondolin-nfs-advisory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gondolin-nfs-advisory.d.ts","sourceRoot":"","sources":["../../src/sandbox/gondolin-nfs-advisory.ts"],"names":[],"mappings":"AAIA,UAAU,eAAe;IACvB,EAAE,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IACrB,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,CAAC;IAC9C,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/B;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,MAAM,EACpB,eAAe,CAAC,EAAE,MAAM,EACxB,IAAI,GAAE,eAAoB,GACzB,IAAI,CAcN"}
@@ -0,0 +1,60 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { platform } from "node:os";
3
+ import * as log from "../log.js";
4
+ /**
5
+ * Startup advisory for gondolin:remote workers: they need the mikan-host
6
+ * workspace on shared storage, and the simplest way is to NFS-export it from
7
+ * the host itself. mikan does NOT touch root or system files — it only checks
8
+ * whether the workspace is already exported and, if not, prints the
9
+ * OS-appropriate commands the operator runs once by hand.
10
+ */
11
+ export function checkWorkspaceExported(workspaceDir, gatewayHostname, deps = {}) {
12
+ const os = deps.os ?? platform();
13
+ const emit = deps.emit ?? ((line) => console.log(line));
14
+ if (os !== "darwin" && os !== "linux") {
15
+ log.logWarning(`gondolin:remote workers need ${workspaceDir} on shared storage; NFS auto-detection is unavailable on ${os}`);
16
+ return;
17
+ }
18
+ if (isExported(os, workspaceDir, deps.run)) {
19
+ log.logInfo(`Workspace ${workspaceDir} is NFS-exported for remote workers`);
20
+ return;
21
+ }
22
+ for (const line of setupLines(os, workspaceDir, gatewayHostname))
23
+ emit(line);
24
+ }
25
+ function isExported(os, workspaceDir, run) {
26
+ const exec = run ?? ((cmd, args) => execFileSync(cmd, args, { encoding: "utf8" }));
27
+ try {
28
+ if (os === "darwin") {
29
+ const out = exec("showmount", ["-e", "localhost"]);
30
+ return out.split("\n").some((line) => line.trimStart().startsWith(workspaceDir));
31
+ }
32
+ // linux: exportfs -s lists current exports
33
+ const out = exec("exportfs", ["-s"]);
34
+ return out
35
+ .split("\n")
36
+ .some((line) => line.startsWith(workspaceDir + " ") || line === workspaceDir);
37
+ }
38
+ catch {
39
+ // no NFS server running / tool missing → treat as not exported
40
+ return false;
41
+ }
42
+ }
43
+ function setupLines(os, workspaceDir, gatewayHostname) {
44
+ const hostHint = gatewayHostname ?? "<host-tailscale-ip>";
45
+ const lines = [
46
+ "",
47
+ " ⚠ gondolin:remote workers need this workspace on shared storage.",
48
+ ` Export it from this host once (mikan will not modify system files):`,
49
+ "",
50
+ ];
51
+ if (os === "darwin") {
52
+ lines.push(` echo '${workspaceDir} -network 100.64.0.0 -mask 255.192.0.0 -mapall=$(id -u):$(id -g)' | sudo tee -a /etc/exports`, ` sudo nfsd enable && sudo nfsd start`);
53
+ }
54
+ else {
55
+ lines.push(` echo '${workspaceDir} 100.64.0.0/10(rw,sync,no_subtree_check,all_squash,anonuid=$(id -u),anongid=$(id -g))' | sudo tee -a /etc/exports`, ` sudo exportfs -ra && sudo systemctl enable --now nfs-server`);
56
+ }
57
+ lines.push("", " Then on each worker (over tailscale), mount it and point --workspace-root at it:", ` sudo mount -t nfs -o vers=3,resvport,nolock ${hostHint}:${workspaceDir} /mnt/mikan-workspace`, "", " 100.64.0.0/10 is the tailscale range; -mapall/all_squash makes worker", " writes owned by you on the host. Skip this only if you already share the", " workspace another way (existing NFS, GCS-fuse, etc.).", "");
58
+ return lines;
59
+ }
60
+ //# sourceMappingURL=gondolin-nfs-advisory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gondolin-nfs-advisory.js","sourceRoot":"","sources":["../../src/sandbox/gondolin-nfs-advisory.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFileSync } from \"node:child_process\";\nimport { platform } from \"node:os\";\nimport * as log from \"../log.js\";\n\ninterface NfsAdvisoryDeps {\n os?: NodeJS.Platform;\n run?: (cmd: string, args: string[]) => string;\n emit?: (line: string) => void;\n}\n\n/**\n * Startup advisory for gondolin:remote workers: they need the mikan-host\n * workspace on shared storage, and the simplest way is to NFS-export it from\n * the host itself. mikan does NOT touch root or system files — it only checks\n * whether the workspace is already exported and, if not, prints the\n * OS-appropriate commands the operator runs once by hand.\n */\nexport function checkWorkspaceExported(\n workspaceDir: string,\n gatewayHostname?: string,\n deps: NfsAdvisoryDeps = {},\n): void {\n const os = deps.os ?? platform();\n const emit = deps.emit ?? ((line: string) => console.log(line));\n if (os !== \"darwin\" && os !== \"linux\") {\n log.logWarning(\n `gondolin:remote workers need ${workspaceDir} on shared storage; NFS auto-detection is unavailable on ${os}`,\n );\n return;\n }\n if (isExported(os, workspaceDir, deps.run)) {\n log.logInfo(`Workspace ${workspaceDir} is NFS-exported for remote workers`);\n return;\n }\n for (const line of setupLines(os, workspaceDir, gatewayHostname)) emit(line);\n}\n\nfunction isExported(\n os: NodeJS.Platform,\n workspaceDir: string,\n run: NfsAdvisoryDeps[\"run\"],\n): boolean {\n const exec =\n run ?? ((cmd: string, args: string[]) => execFileSync(cmd, args, { encoding: \"utf8\" }));\n try {\n if (os === \"darwin\") {\n const out = exec(\"showmount\", [\"-e\", \"localhost\"]);\n return out.split(\"\\n\").some((line) => line.trimStart().startsWith(workspaceDir));\n }\n // linux: exportfs -s lists current exports\n const out = exec(\"exportfs\", [\"-s\"]);\n return out\n .split(\"\\n\")\n .some((line) => line.startsWith(workspaceDir + \" \") || line === workspaceDir);\n } catch {\n // no NFS server running / tool missing → treat as not exported\n return false;\n }\n}\n\nfunction setupLines(os: NodeJS.Platform, workspaceDir: string, gatewayHostname?: string): string[] {\n const hostHint = gatewayHostname ?? \"<host-tailscale-ip>\";\n const lines: string[] = [\n \"\",\n \" ⚠ gondolin:remote workers need this workspace on shared storage.\",\n ` Export it from this host once (mikan will not modify system files):`,\n \"\",\n ];\n if (os === \"darwin\") {\n lines.push(\n ` echo '${workspaceDir} -network 100.64.0.0 -mask 255.192.0.0 -mapall=$(id -u):$(id -g)' | sudo tee -a /etc/exports`,\n ` sudo nfsd enable && sudo nfsd start`,\n );\n } else {\n lines.push(\n ` echo '${workspaceDir} 100.64.0.0/10(rw,sync,no_subtree_check,all_squash,anonuid=$(id -u),anongid=$(id -g))' | sudo tee -a /etc/exports`,\n ` sudo exportfs -ra && sudo systemctl enable --now nfs-server`,\n );\n }\n lines.push(\n \"\",\n \" Then on each worker (over tailscale), mount it and point --workspace-root at it:\",\n ` sudo mount -t nfs -o vers=3,resvport,nolock ${hostHint}:${workspaceDir} /mnt/mikan-workspace`,\n \"\",\n \" 100.64.0.0/10 is the tailscale range; -mapall/all_squash makes worker\",\n \" writes owned by you on the host. Skip this only if you already share the\",\n \" workspace another way (existing NFS, GCS-fuse, etc.).\",\n \"\",\n );\n return lines;\n}\n"]}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Where one conversation's runtime lives in the fleet, plus the fencing
3
+ * watermark failover must respect: the worker-side lease cannot outlive
4
+ * `leaseExpiresAt` (mikan clock), after which the old worker's janitor has
5
+ * stopped the runtime and the shared-storage single-writer rule allows a
6
+ * placement elsewhere.
7
+ */
8
+ export interface GondolinPlacementRecord {
9
+ instanceId: string;
10
+ worker: string;
11
+ leaseExpiresAt: number;
12
+ updatedAt: number;
13
+ }
14
+ /**
15
+ * Durable instanceId → worker map. mikan is the only scheduler, so a single
16
+ * atomically-replaced JSON file under the state dir is the source of truth.
17
+ */
18
+ export declare class GondolinPlacementStore {
19
+ private path?;
20
+ private table;
21
+ configure(path?: string): void;
22
+ get(instanceId: string): GondolinPlacementRecord | undefined;
23
+ list(): GondolinPlacementRecord[];
24
+ countByWorker(worker: string): number;
25
+ set(instanceId: string, worker: string, leaseExpiresAt: number): void;
26
+ /** Refresh the fencing watermark without moving the placement. */
27
+ touch(instanceId: string, leaseExpiresAt: number): void;
28
+ delete(instanceId: string): void;
29
+ private persist;
30
+ }
31
+ export declare const gondolinPlacements: GondolinPlacementStore;
32
+ //# sourceMappingURL=gondolin-placement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gondolin-placement.d.ts","sourceRoot":"","sources":["../../src/sandbox/gondolin-placement.ts"],"names":[],"mappings":"AAKA;;;;;;GAMG;AACH,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB;AAcD;;;GAGG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,IAAI,CAAC,CAAS;IACtB,OAAO,CAAC,KAAK,CAA8C;IAE3D,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAiB7B;IAED,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,uBAAuB,GAAG,SAAS,CAE3D;IAED,IAAI,IAAI,uBAAuB,EAAE,CAEhC;IAED,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEpC;IAED,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,CAGpE;IAED,kEAAkE;IAClE,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,CAMtD;IAED,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAE/B;IAED,OAAO,CAAC,OAAO;CAehB;AAED,eAAO,MAAM,kBAAkB,wBAA+B,CAAC"}
@@ -0,0 +1,83 @@
1
+ import { readFileSync, renameSync, writeFileSync } from "node:fs";
2
+ import { dirname } from "node:path";
3
+ import * as log from "../log.js";
4
+ import { ensureDirExists, isRecord } from "../utils/file-guards.js";
5
+ function isPlacementTable(value) {
6
+ if (!isRecord(value))
7
+ return false;
8
+ return Object.values(value).every((entry) => isRecord(entry) &&
9
+ typeof entry.instanceId === "string" &&
10
+ typeof entry.worker === "string" &&
11
+ typeof entry.leaseExpiresAt === "number" &&
12
+ typeof entry.updatedAt === "number");
13
+ }
14
+ /**
15
+ * Durable instanceId → worker map. mikan is the only scheduler, so a single
16
+ * atomically-replaced JSON file under the state dir is the source of truth.
17
+ */
18
+ export class GondolinPlacementStore {
19
+ constructor() {
20
+ this.table = new Map();
21
+ }
22
+ configure(path) {
23
+ this.path = path;
24
+ this.table.clear();
25
+ if (!path)
26
+ return;
27
+ try {
28
+ const raw = readFileSync(path, "utf8");
29
+ const parsed = JSON.parse(raw);
30
+ if (!isPlacementTable(parsed))
31
+ throw new Error("unexpected placement table shape");
32
+ for (const record of Object.values(parsed))
33
+ this.table.set(record.instanceId, record);
34
+ }
35
+ catch (err) {
36
+ if (err.code !== "ENOENT") {
37
+ log.logWarning("Starting with an empty Gondolin placement table", err instanceof Error ? err.message : String(err));
38
+ }
39
+ }
40
+ }
41
+ get(instanceId) {
42
+ return this.table.get(instanceId);
43
+ }
44
+ list() {
45
+ return Array.from(this.table.values());
46
+ }
47
+ countByWorker(worker) {
48
+ return this.list().filter((record) => record.worker === worker).length;
49
+ }
50
+ set(instanceId, worker, leaseExpiresAt) {
51
+ this.table.set(instanceId, { instanceId, worker, leaseExpiresAt, updatedAt: Date.now() });
52
+ this.persist();
53
+ }
54
+ /** Refresh the fencing watermark without moving the placement. */
55
+ touch(instanceId, leaseExpiresAt) {
56
+ const record = this.table.get(instanceId);
57
+ if (!record || leaseExpiresAt <= record.leaseExpiresAt)
58
+ return;
59
+ record.leaseExpiresAt = leaseExpiresAt;
60
+ record.updatedAt = Date.now();
61
+ this.persist();
62
+ }
63
+ delete(instanceId) {
64
+ if (this.table.delete(instanceId))
65
+ this.persist();
66
+ }
67
+ persist() {
68
+ if (!this.path)
69
+ return;
70
+ try {
71
+ ensureDirExists(dirname(this.path));
72
+ const snapshot = Object.fromEntries(this.table);
73
+ const staged = `${this.path}.tmp`;
74
+ writeFileSync(staged, JSON.stringify(snapshot, null, 2) + "\n");
75
+ renameSync(staged, this.path);
76
+ }
77
+ catch (err) {
78
+ log.logWarning("Failed to persist Gondolin placement table", err instanceof Error ? err.message : String(err));
79
+ }
80
+ }
81
+ }
82
+ export const gondolinPlacements = new GondolinPlacementStore();
83
+ //# sourceMappingURL=gondolin-placement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gondolin-placement.js","sourceRoot":"","sources":["../../src/sandbox/gondolin-placement.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport * as log from \"../log.js\";\nimport { ensureDirExists, isRecord } from \"../utils/file-guards.js\";\n\n/**\n * Where one conversation's runtime lives in the fleet, plus the fencing\n * watermark failover must respect: the worker-side lease cannot outlive\n * `leaseExpiresAt` (mikan clock), after which the old worker's janitor has\n * stopped the runtime and the shared-storage single-writer rule allows a\n * placement elsewhere.\n */\nexport interface GondolinPlacementRecord {\n instanceId: string;\n worker: string;\n leaseExpiresAt: number;\n updatedAt: number;\n}\n\nfunction isPlacementTable(value: unknown): value is Record<string, GondolinPlacementRecord> {\n if (!isRecord(value)) return false;\n return Object.values(value).every(\n (entry) =>\n isRecord(entry) &&\n typeof entry.instanceId === \"string\" &&\n typeof entry.worker === \"string\" &&\n typeof entry.leaseExpiresAt === \"number\" &&\n typeof entry.updatedAt === \"number\",\n );\n}\n\n/**\n * Durable instanceId → worker map. mikan is the only scheduler, so a single\n * atomically-replaced JSON file under the state dir is the source of truth.\n */\nexport class GondolinPlacementStore {\n private path?: string;\n private table = new Map<string, GondolinPlacementRecord>();\n\n configure(path?: string): void {\n this.path = path;\n this.table.clear();\n if (!path) return;\n try {\n const raw = readFileSync(path, \"utf8\");\n const parsed: unknown = JSON.parse(raw);\n if (!isPlacementTable(parsed)) throw new Error(\"unexpected placement table shape\");\n for (const record of Object.values(parsed)) this.table.set(record.instanceId, record);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n log.logWarning(\n \"Starting with an empty Gondolin placement table\",\n err instanceof Error ? err.message : String(err),\n );\n }\n }\n }\n\n get(instanceId: string): GondolinPlacementRecord | undefined {\n return this.table.get(instanceId);\n }\n\n list(): GondolinPlacementRecord[] {\n return Array.from(this.table.values());\n }\n\n countByWorker(worker: string): number {\n return this.list().filter((record) => record.worker === worker).length;\n }\n\n set(instanceId: string, worker: string, leaseExpiresAt: number): void {\n this.table.set(instanceId, { instanceId, worker, leaseExpiresAt, updatedAt: Date.now() });\n this.persist();\n }\n\n /** Refresh the fencing watermark without moving the placement. */\n touch(instanceId: string, leaseExpiresAt: number): void {\n const record = this.table.get(instanceId);\n if (!record || leaseExpiresAt <= record.leaseExpiresAt) return;\n record.leaseExpiresAt = leaseExpiresAt;\n record.updatedAt = Date.now();\n this.persist();\n }\n\n delete(instanceId: string): void {\n if (this.table.delete(instanceId)) this.persist();\n }\n\n private persist(): void {\n if (!this.path) return;\n try {\n ensureDirExists(dirname(this.path));\n const snapshot = Object.fromEntries(this.table);\n const staged = `${this.path}.tmp`;\n writeFileSync(staged, JSON.stringify(snapshot, null, 2) + \"\\n\");\n renameSync(staged, this.path);\n } catch (err) {\n log.logWarning(\n \"Failed to persist Gondolin placement table\",\n err instanceof Error ? err.message : String(err),\n );\n }\n }\n}\n\nexport const gondolinPlacements = new GondolinPlacementStore();\n"]}
@@ -0,0 +1,73 @@
1
+ import type { GondolinRemoteWorkerSettings } from "../types.js";
2
+ import { type GondolinRuntimeHandle, type GondolinRuntimeSpec, type SessionClient, type SessionClientCallbacks } from "./gondolin-worker-client.js";
3
+ import type { ExecResult } from "./types.js";
4
+ interface RemoteResponse {
5
+ status: number;
6
+ json: Record<string, unknown>;
7
+ }
8
+ /** A request that never reached the daemon (network/TLS/timeout failure). */
9
+ export declare class GondolinWorkerUnreachableError extends Error {
10
+ }
11
+ export interface GondolinRemoteOverrides {
12
+ request?: (method: string, path: string, body?: object, headers?: Record<string, string>) => Promise<RemoteResponse>;
13
+ tunnel?: (path: string, headers: Record<string, string>, callbacks: SessionClientCallbacks) => SessionClient | Promise<SessionClient>;
14
+ leaseTtlSeconds?: number;
15
+ requestTimeoutMs?: number;
16
+ /** Reports lease grants/renewals so the fleet can persist fencing watermarks. */
17
+ onLeaseActivity?: (instanceId: string, expiresAtMs: number) => void;
18
+ }
19
+ /** Parses the daemon-to-client session framing: u8 type + u32be length + payload. */
20
+ export declare function createSessionFrameParser(callbacks: SessionClientCallbacks): (chunk: Buffer) => void;
21
+ /** Encodes a client-to-daemon session message: u32be length + JSON. */
22
+ export declare function encodeSessionMessage(message: object): Buffer;
23
+ /**
24
+ * One mikan-worker daemon as seen from mikan: mTLS requests, per-instance
25
+ * fenced leases with heartbeat renewal, and per-command upgraded tunnels.
26
+ * Commands travel through one tunnel each, so abort semantics match the local
27
+ * transport exactly.
28
+ */
29
+ export declare class GondolinRemoteConnection {
30
+ private readonly settings;
31
+ private readonly overrides;
32
+ private readonly leases;
33
+ private readonly leaseTtlSeconds;
34
+ private readonly requestTimeoutMs;
35
+ private tls?;
36
+ constructor(settings: GondolinRemoteWorkerSettings, overrides?: GondolinRemoteOverrides);
37
+ /** Drop lease timers and caches (does not touch the daemon). */
38
+ dispose(): void;
39
+ health(): Promise<Record<string, unknown>>;
40
+ ensure(instanceId: string, spec: GondolinRuntimeSpec): Promise<GondolinRuntimeHandle>;
41
+ stop(handle: Pick<GondolinRuntimeHandle, "workerPid" | "sessionId" | "instanceId">): Promise<void>;
42
+ isRuntimeAlive(handle: GondolinRuntimeHandle): Promise<boolean>;
43
+ /** Live runtimes hosted by this worker (fleet reconciliation). */
44
+ listRuntimes(): Promise<Array<{
45
+ sessionId: string;
46
+ instanceId: string;
47
+ }>>;
48
+ exec(handle: GondolinRuntimeHandle, command: string, options?: {
49
+ env?: Record<string, string>;
50
+ signal?: AbortSignal;
51
+ }): Promise<ExecResult>;
52
+ /**
53
+ * Split mounts for the remote worker:
54
+ * - sources under the mikan-host workspace are translated to the worker's
55
+ * shared `workspaceRoot` (shared POSIX storage), and
56
+ * - sources outside it that are files (vault credentials, which live in the
57
+ * host state dir, not the shared workspace) are read and shipped as
58
+ * content payloads for the worker to project into the guest.
59
+ * A non-file source outside the workspace has nowhere to go and is dropped.
60
+ */
61
+ private translateMounts;
62
+ private leaseFor;
63
+ private renew;
64
+ private reportLeaseActivity;
65
+ private releaseLease;
66
+ private dropLease;
67
+ private leaseHeaders;
68
+ private request;
69
+ private openTunnel;
70
+ private tlsOptions;
71
+ }
72
+ export {};
73
+ //# sourceMappingURL=gondolin-remote.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gondolin-remote.d.ts","sourceRoot":"","sources":["../../src/sandbox/gondolin-remote.ts"],"names":[],"mappings":"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"}