@geminixiang/mikan 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (371) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/adapter.d.ts +1 -138
  3. package/dist/adapter.d.ts.map +1 -1
  4. package/dist/adapter.js.map +1 -1
  5. package/dist/adapters/discord/bot.d.ts +1 -4
  6. package/dist/adapters/discord/bot.d.ts.map +1 -1
  7. package/dist/adapters/discord/bot.js +25 -33
  8. package/dist/adapters/discord/bot.js.map +1 -1
  9. package/dist/adapters/discord/context.d.ts.map +1 -1
  10. package/dist/adapters/discord/context.js +28 -0
  11. package/dist/adapters/discord/context.js.map +1 -1
  12. package/dist/adapters/discord/types.d.ts +6 -0
  13. package/dist/adapters/discord/types.d.ts.map +1 -0
  14. package/dist/adapters/discord/types.js +2 -0
  15. package/dist/adapters/discord/types.js.map +1 -0
  16. package/dist/adapters/intake.d.ts +11 -0
  17. package/dist/adapters/intake.d.ts.map +1 -0
  18. package/dist/adapters/intake.js +42 -0
  19. package/dist/adapters/intake.js.map +1 -0
  20. package/dist/adapters/shared.d.ts +7 -31
  21. package/dist/adapters/shared.d.ts.map +1 -1
  22. package/dist/adapters/shared.js +18 -2
  23. package/dist/adapters/shared.js.map +1 -1
  24. package/dist/adapters/slack/bot.d.ts +14 -33
  25. package/dist/adapters/slack/bot.d.ts.map +1 -1
  26. package/dist/adapters/slack/bot.js +148 -116
  27. package/dist/adapters/slack/bot.js.map +1 -1
  28. package/dist/adapters/slack/context.d.ts +3 -4
  29. package/dist/adapters/slack/context.d.ts.map +1 -1
  30. package/dist/adapters/slack/context.js +97 -14
  31. package/dist/adapters/slack/context.js.map +1 -1
  32. package/dist/adapters/slack/session.d.ts +5 -20
  33. package/dist/adapters/slack/session.d.ts.map +1 -1
  34. package/dist/adapters/slack/session.js.map +1 -1
  35. package/dist/adapters/slack/types.d.ts +84 -0
  36. package/dist/adapters/slack/types.d.ts.map +1 -0
  37. package/dist/adapters/slack/types.js +2 -0
  38. package/dist/adapters/slack/types.js.map +1 -0
  39. package/dist/adapters/streaming.d.ts +18 -0
  40. package/dist/adapters/streaming.d.ts.map +1 -0
  41. package/dist/adapters/streaming.js +44 -0
  42. package/dist/adapters/streaming.js.map +1 -0
  43. package/dist/adapters/telegram/bot.d.ts +1 -4
  44. package/dist/adapters/telegram/bot.d.ts.map +1 -1
  45. package/dist/adapters/telegram/bot.js +32 -39
  46. package/dist/adapters/telegram/bot.js.map +1 -1
  47. package/dist/adapters/telegram/context.d.ts.map +1 -1
  48. package/dist/adapters/telegram/context.js +33 -0
  49. package/dist/adapters/telegram/context.js.map +1 -1
  50. package/dist/adapters/telegram/types.d.ts +6 -0
  51. package/dist/adapters/telegram/types.d.ts.map +1 -0
  52. package/dist/adapters/telegram/types.js +2 -0
  53. package/dist/adapters/telegram/types.js.map +1 -0
  54. package/dist/adapters/types.d.ts +58 -0
  55. package/dist/adapters/types.d.ts.map +1 -0
  56. package/dist/adapters/types.js +2 -0
  57. package/dist/adapters/types.js.map +1 -0
  58. package/dist/agent.d.ts +4 -16
  59. package/dist/agent.d.ts.map +1 -1
  60. package/dist/agent.js +33 -20
  61. package/dist/agent.js.map +1 -1
  62. package/dist/commands/admin.d.ts.map +1 -1
  63. package/dist/commands/admin.js +1 -1
  64. package/dist/commands/admin.js.map +1 -1
  65. package/dist/commands/auto-reply.d.ts.map +1 -1
  66. package/dist/commands/auto-reply.js +1 -8
  67. package/dist/commands/auto-reply.js.map +1 -1
  68. package/dist/commands/login.d.ts.map +1 -1
  69. package/dist/commands/login.js +3 -3
  70. package/dist/commands/login.js.map +1 -1
  71. package/dist/commands/model.d.ts +5 -8
  72. package/dist/commands/model.d.ts.map +1 -1
  73. package/dist/commands/model.js +15 -20
  74. package/dist/commands/model.js.map +1 -1
  75. package/dist/commands/new.d.ts.map +1 -1
  76. package/dist/commands/new.js +5 -10
  77. package/dist/commands/new.js.map +1 -1
  78. package/dist/commands/parse.d.ts.map +1 -1
  79. package/dist/commands/parse.js +1 -4
  80. package/dist/commands/parse.js.map +1 -1
  81. package/dist/commands/registry.d.ts +1 -0
  82. package/dist/commands/registry.d.ts.map +1 -1
  83. package/dist/commands/registry.js +23 -0
  84. package/dist/commands/registry.js.map +1 -1
  85. package/dist/commands/sandbox.d.ts +2 -5
  86. package/dist/commands/sandbox.d.ts.map +1 -1
  87. package/dist/commands/sandbox.js +11 -16
  88. package/dist/commands/sandbox.js.map +1 -1
  89. package/dist/commands/session-view.d.ts.map +1 -1
  90. package/dist/commands/session-view.js +10 -15
  91. package/dist/commands/session-view.js.map +1 -1
  92. package/dist/commands/types.d.ts +11 -2
  93. package/dist/commands/types.d.ts.map +1 -1
  94. package/dist/commands/types.js.map +1 -1
  95. package/dist/config.d.ts +6 -28
  96. package/dist/config.d.ts.map +1 -1
  97. package/dist/config.js +43 -41
  98. package/dist/config.js.map +1 -1
  99. package/dist/context.d.ts +1 -15
  100. package/dist/context.d.ts.map +1 -1
  101. package/dist/context.js.map +1 -1
  102. package/dist/events.d.ts +4 -44
  103. package/dist/events.d.ts.map +1 -1
  104. package/dist/events.js +24 -43
  105. package/dist/events.js.map +1 -1
  106. package/dist/execution-resolver.d.ts +3 -7
  107. package/dist/execution-resolver.d.ts.map +1 -1
  108. package/dist/execution-resolver.js +8 -8
  109. package/dist/execution-resolver.js.map +1 -1
  110. package/dist/index.d.ts +3 -3
  111. package/dist/index.d.ts.map +1 -1
  112. package/dist/index.js +2 -2
  113. package/dist/index.js.map +1 -1
  114. package/dist/log.d.ts +2 -6
  115. package/dist/log.d.ts.map +1 -1
  116. package/dist/log.js +1 -37
  117. package/dist/log.js.map +1 -1
  118. package/dist/main.d.ts +1 -1
  119. package/dist/main.d.ts.map +1 -1
  120. package/dist/main.js +16 -16
  121. package/dist/main.js.map +1 -1
  122. package/dist/observability/instrument.d.ts.map +1 -0
  123. package/dist/{instrument.js → observability/instrument.js} +2 -2
  124. package/dist/observability/instrument.js.map +1 -0
  125. package/dist/{sentry.d.ts → observability/sentry.d.ts} +10 -30
  126. package/dist/observability/sentry.d.ts.map +1 -0
  127. package/dist/{sentry.js → observability/sentry.js} +70 -6
  128. package/dist/observability/sentry.js.map +1 -0
  129. package/dist/observability/types.d.ts +47 -0
  130. package/dist/observability/types.d.ts.map +1 -0
  131. package/dist/observability/types.js +2 -0
  132. package/dist/observability/types.js.map +1 -0
  133. package/dist/{ui-copy.d.ts → platform-messages.d.ts} +1 -1
  134. package/dist/platform-messages.d.ts.map +1 -0
  135. package/dist/{ui-copy.js → platform-messages.js} +1 -1
  136. package/dist/platform-messages.js.map +1 -0
  137. package/dist/portal-shell.d.ts +2 -28
  138. package/dist/portal-shell.d.ts.map +1 -1
  139. package/dist/portal-shell.js +2 -2
  140. package/dist/portal-shell.js.map +1 -1
  141. package/dist/provisioner.d.ts +2 -23
  142. package/dist/provisioner.d.ts.map +1 -1
  143. package/dist/provisioner.js +1 -1
  144. package/dist/provisioner.js.map +1 -1
  145. package/dist/runtime/conversation-orchestrator.d.ts +4 -19
  146. package/dist/runtime/conversation-orchestrator.d.ts.map +1 -1
  147. package/dist/runtime/conversation-orchestrator.js +17 -8
  148. package/dist/runtime/conversation-orchestrator.js.map +1 -1
  149. package/dist/runtime/session-runtime.d.ts +2 -23
  150. package/dist/runtime/session-runtime.d.ts.map +1 -1
  151. package/dist/runtime/session-runtime.js +7 -9
  152. package/dist/runtime/session-runtime.js.map +1 -1
  153. package/dist/runtime/types.d.ts +35 -0
  154. package/dist/runtime/types.d.ts.map +1 -0
  155. package/dist/runtime/types.js +2 -0
  156. package/dist/runtime/types.js.map +1 -0
  157. package/dist/sandbox/cloudflare.d.ts.map +1 -1
  158. package/dist/sandbox/cloudflare.js +1 -1
  159. package/dist/sandbox/cloudflare.js.map +1 -1
  160. package/dist/sandbox/container.d.ts.map +1 -1
  161. package/dist/sandbox/container.js +1 -4
  162. package/dist/sandbox/container.js.map +1 -1
  163. package/dist/sessions/chat-session-manager.d.ts +2 -46
  164. package/dist/sessions/chat-session-manager.d.ts.map +1 -1
  165. package/dist/sessions/chat-session-manager.js +12 -40
  166. package/dist/sessions/chat-session-manager.js.map +1 -1
  167. package/dist/sessions/metadata.d.ts +1 -13
  168. package/dist/sessions/metadata.d.ts.map +1 -1
  169. package/dist/sessions/metadata.js.map +1 -1
  170. package/dist/sessions/policy.d.ts +3 -10
  171. package/dist/sessions/policy.d.ts.map +1 -1
  172. package/dist/sessions/policy.js.map +1 -1
  173. package/dist/sessions/store.d.ts +1 -12
  174. package/dist/sessions/store.d.ts.map +1 -1
  175. package/dist/sessions/store.js +4 -7
  176. package/dist/sessions/store.js.map +1 -1
  177. package/dist/sessions/types.d.ts +76 -0
  178. package/dist/sessions/types.d.ts.map +1 -0
  179. package/dist/sessions/types.js +2 -0
  180. package/dist/sessions/types.js.map +1 -0
  181. package/dist/store.d.ts +2 -19
  182. package/dist/store.d.ts.map +1 -1
  183. package/dist/store.js +1 -1
  184. package/dist/store.js.map +1 -1
  185. package/dist/tools/event.d.ts +30 -36
  186. package/dist/tools/event.d.ts.map +1 -1
  187. package/dist/tools/event.js +207 -26
  188. package/dist/tools/event.js.map +1 -1
  189. package/dist/tools/index.d.ts +2 -2
  190. package/dist/tools/index.d.ts.map +1 -1
  191. package/dist/tools/index.js.map +1 -1
  192. package/dist/tools/sandbox.d.ts.map +1 -1
  193. package/dist/tools/sandbox.js +1 -1
  194. package/dist/tools/sandbox.js.map +1 -1
  195. package/dist/tools/truncate.d.ts +2 -26
  196. package/dist/tools/truncate.d.ts.map +1 -1
  197. package/dist/tools/truncate.js.map +1 -1
  198. package/dist/tools/types.d.ts +54 -0
  199. package/dist/tools/types.d.ts.map +1 -0
  200. package/dist/tools/types.js +2 -0
  201. package/dist/tools/types.js.map +1 -0
  202. package/dist/trigger.d.ts +2 -13
  203. package/dist/trigger.d.ts.map +1 -1
  204. package/dist/trigger.js.map +1 -1
  205. package/dist/types.d.ts +307 -0
  206. package/dist/types.d.ts.map +1 -0
  207. package/dist/types.js +4 -0
  208. package/dist/types.js.map +1 -0
  209. package/dist/utils/date.d.ts +10 -0
  210. package/dist/utils/date.d.ts.map +1 -0
  211. package/dist/utils/date.js +23 -0
  212. package/dist/utils/date.js.map +1 -0
  213. package/dist/utils/env.d.ts.map +1 -0
  214. package/dist/utils/env.js.map +1 -0
  215. package/dist/utils/file-guards.d.ts.map +1 -0
  216. package/dist/utils/file-guards.js.map +1 -0
  217. package/dist/utils/fs-atomic.d.ts.map +1 -0
  218. package/dist/utils/fs-atomic.js.map +1 -0
  219. package/dist/utils/html.d.ts.map +1 -0
  220. package/dist/utils/html.js.map +1 -0
  221. package/dist/utils/http-body.d.ts +10 -0
  222. package/dist/utils/http-body.d.ts.map +1 -0
  223. package/dist/utils/http-body.js +34 -0
  224. package/dist/utils/http-body.js.map +1 -0
  225. package/dist/vault/index.d.ts +34 -0
  226. package/dist/vault/index.d.ts.map +1 -0
  227. package/dist/{vault.js → vault/index.js} +4 -4
  228. package/dist/vault/index.js.map +1 -0
  229. package/dist/{vault-routing.d.ts → vault/routing.d.ts} +2 -2
  230. package/dist/vault/routing.d.ts.map +1 -0
  231. package/dist/{vault-routing.js → vault/routing.js} +2 -2
  232. package/dist/vault/routing.js.map +1 -0
  233. package/dist/{vault.d.ts → vault/types.d.ts} +3 -34
  234. package/dist/vault/types.d.ts.map +1 -0
  235. package/dist/vault/types.js +2 -0
  236. package/dist/vault/types.js.map +1 -0
  237. package/dist/web/admin/portal.d.ts +5 -0
  238. package/dist/web/admin/portal.d.ts.map +1 -0
  239. package/dist/{admin → web/admin}/portal.js +140 -52
  240. package/dist/web/admin/portal.js.map +1 -0
  241. package/dist/web/admin/store.d.ts +13 -0
  242. package/dist/web/admin/store.d.ts.map +1 -0
  243. package/dist/web/admin/store.js +23 -0
  244. package/dist/web/admin/store.js.map +1 -0
  245. package/dist/web/admin/types.d.ts +28 -0
  246. package/dist/web/admin/types.d.ts.map +1 -0
  247. package/dist/web/admin/types.js +2 -0
  248. package/dist/web/admin/types.js.map +1 -0
  249. package/dist/web/login/oauth.d.ts +6 -0
  250. package/dist/web/login/oauth.d.ts.map +1 -0
  251. package/dist/{login/index.js → web/login/oauth.js} +107 -106
  252. package/dist/web/login/oauth.js.map +1 -0
  253. package/dist/{login → web/login}/portal.d.ts +5 -5
  254. package/dist/web/login/portal.d.ts.map +1 -0
  255. package/dist/{login → web/login}/portal.js +16 -35
  256. package/dist/web/login/portal.js.map +1 -0
  257. package/dist/web/login/store.d.ts +12 -0
  258. package/dist/web/login/store.d.ts.map +1 -0
  259. package/dist/web/login/store.js +28 -0
  260. package/dist/web/login/store.js.map +1 -0
  261. package/dist/web/login/types.d.ts +50 -0
  262. package/dist/web/login/types.d.ts.map +1 -0
  263. package/dist/web/login/types.js +2 -0
  264. package/dist/web/login/types.js.map +1 -0
  265. package/dist/web/session-view/command.d.ts +4 -0
  266. package/dist/web/session-view/command.d.ts.map +1 -0
  267. package/dist/{session-view → web/session-view}/command.js +1 -1
  268. package/dist/web/session-view/command.js.map +1 -0
  269. package/dist/{session-view → web/session-view}/portal.d.ts +2 -5
  270. package/dist/web/session-view/portal.d.ts.map +1 -0
  271. package/dist/{session-view → web/session-view}/portal.js +5 -5
  272. package/dist/web/session-view/portal.js.map +1 -0
  273. package/dist/web/session-view/service.d.ts +6 -0
  274. package/dist/web/session-view/service.d.ts.map +1 -0
  275. package/dist/{session-view → web/session-view}/service.js +6 -36
  276. package/dist/web/session-view/service.js.map +1 -0
  277. package/dist/web/session-view/store.d.ts +8 -0
  278. package/dist/web/session-view/store.d.ts.map +1 -0
  279. package/dist/web/session-view/store.js +20 -0
  280. package/dist/web/session-view/store.js.map +1 -0
  281. package/dist/{session-view/service.d.ts → web/session-view/types.d.ts} +20 -4
  282. package/dist/web/session-view/types.d.ts.map +1 -0
  283. package/dist/web/session-view/types.js +2 -0
  284. package/dist/web/session-view/types.js.map +1 -0
  285. package/dist/web/token-store.d.ts +19 -0
  286. package/dist/web/token-store.d.ts.map +1 -0
  287. package/dist/web/token-store.js +45 -0
  288. package/dist/web/token-store.js.map +1 -0
  289. package/dist/web/types.d.ts +5 -0
  290. package/dist/web/types.d.ts.map +1 -0
  291. package/dist/web/types.js +2 -0
  292. package/dist/web/types.js.map +1 -0
  293. package/package.json +1 -1
  294. package/dist/adapters/discord/index.d.ts +0 -3
  295. package/dist/adapters/discord/index.d.ts.map +0 -1
  296. package/dist/adapters/discord/index.js +0 -3
  297. package/dist/adapters/discord/index.js.map +0 -1
  298. package/dist/adapters/slack/index.d.ts +0 -3
  299. package/dist/adapters/slack/index.d.ts.map +0 -1
  300. package/dist/adapters/slack/index.js +0 -3
  301. package/dist/adapters/slack/index.js.map +0 -1
  302. package/dist/adapters/slack/thread-manager.d.ts +0 -19
  303. package/dist/adapters/slack/thread-manager.d.ts.map +0 -1
  304. package/dist/adapters/slack/thread-manager.js +0 -11
  305. package/dist/adapters/slack/thread-manager.js.map +0 -1
  306. package/dist/adapters/telegram/index.d.ts +0 -3
  307. package/dist/adapters/telegram/index.d.ts.map +0 -1
  308. package/dist/adapters/telegram/index.js +0 -3
  309. package/dist/adapters/telegram/index.js.map +0 -1
  310. package/dist/admin/portal.d.ts +0 -27
  311. package/dist/admin/portal.d.ts.map +0 -1
  312. package/dist/admin/portal.js.map +0 -1
  313. package/dist/admin/store.d.ts +0 -22
  314. package/dist/admin/store.d.ts.map +0 -1
  315. package/dist/admin/store.js +0 -39
  316. package/dist/admin/store.js.map +0 -1
  317. package/dist/commands/index.d.ts +0 -5
  318. package/dist/commands/index.d.ts.map +0 -1
  319. package/dist/commands/index.js +0 -20
  320. package/dist/commands/index.js.map +0 -1
  321. package/dist/env.d.ts.map +0 -1
  322. package/dist/env.js.map +0 -1
  323. package/dist/file-guards.d.ts.map +0 -1
  324. package/dist/file-guards.js.map +0 -1
  325. package/dist/fs-atomic.d.ts.map +0 -1
  326. package/dist/fs-atomic.js.map +0 -1
  327. package/dist/html.d.ts.map +0 -1
  328. package/dist/html.js.map +0 -1
  329. package/dist/instrument.d.ts.map +0 -1
  330. package/dist/instrument.js.map +0 -1
  331. package/dist/login/index.d.ts +0 -43
  332. package/dist/login/index.d.ts.map +0 -1
  333. package/dist/login/index.js.map +0 -1
  334. package/dist/login/portal.d.ts.map +0 -1
  335. package/dist/login/portal.js.map +0 -1
  336. package/dist/login/store.d.ts +0 -26
  337. package/dist/login/store.d.ts.map +0 -1
  338. package/dist/login/store.js +0 -56
  339. package/dist/login/store.js.map +0 -1
  340. package/dist/runtime/index.d.ts +0 -2
  341. package/dist/runtime/index.d.ts.map +0 -1
  342. package/dist/runtime/index.js +0 -2
  343. package/dist/runtime/index.js.map +0 -1
  344. package/dist/sentry.d.ts.map +0 -1
  345. package/dist/sentry.js.map +0 -1
  346. package/dist/session-view/command.d.ts +0 -5
  347. package/dist/session-view/command.d.ts.map +0 -1
  348. package/dist/session-view/command.js.map +0 -1
  349. package/dist/session-view/portal.d.ts.map +0 -1
  350. package/dist/session-view/portal.js.map +0 -1
  351. package/dist/session-view/service.d.ts.map +0 -1
  352. package/dist/session-view/service.js.map +0 -1
  353. package/dist/session-view/store.d.ts +0 -18
  354. package/dist/session-view/store.d.ts.map +0 -1
  355. package/dist/session-view/store.js +0 -36
  356. package/dist/session-view/store.js.map +0 -1
  357. package/dist/ui-copy.d.ts.map +0 -1
  358. package/dist/ui-copy.js.map +0 -1
  359. package/dist/vault-routing.d.ts.map +0 -1
  360. package/dist/vault-routing.js.map +0 -1
  361. package/dist/vault.d.ts.map +0 -1
  362. package/dist/vault.js.map +0 -1
  363. /package/dist/{instrument.d.ts → observability/instrument.d.ts} +0 -0
  364. /package/dist/{env.d.ts → utils/env.d.ts} +0 -0
  365. /package/dist/{env.js → utils/env.js} +0 -0
  366. /package/dist/{file-guards.d.ts → utils/file-guards.d.ts} +0 -0
  367. /package/dist/{file-guards.js → utils/file-guards.js} +0 -0
  368. /package/dist/{fs-atomic.d.ts → utils/fs-atomic.d.ts} +0 -0
  369. /package/dist/{fs-atomic.js → utils/fs-atomic.js} +0 -0
  370. /package/dist/{html.d.ts → utils/html.d.ts} +0 -0
  371. /package/dist/{html.js → utils/html.js} +0 -0
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Format a Date as a local-timezone timestamp string: YYYY-MM-DD HH:MM:SS±HH:MM
3
+ * Returns null when the date is invalid (non-finite time value).
4
+ *
5
+ * This format is used both when writing user messages (agent.ts) and when
6
+ * reading history back into sessions (chat-session-manager.ts). Keeping it
7
+ * in one place ensures normalizeComparableText's regex stays valid.
8
+ */
9
+ export function formatLocalTimestamp(date) {
10
+ const time = date.getTime();
11
+ if (!Number.isFinite(time))
12
+ return null;
13
+ const offset = -date.getTimezoneOffset();
14
+ const sign = offset >= 0 ? "+" : "-";
15
+ const abs = Math.abs(offset);
16
+ return (`${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ` +
17
+ `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}` +
18
+ `${sign}${pad(Math.floor(abs / 60))}:${pad(abs % 60)}`);
19
+ }
20
+ function pad(n) {
21
+ return n.toString().padStart(2, "0");
22
+ }
23
+ //# sourceMappingURL=date.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date.js","sourceRoot":"","sources":["../../src/utils/date.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAU;IAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAExC,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;IACzC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IACrC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,OAAO,CACL,GAAG,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG;QAC3E,GAAG,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE;QAC7E,GAAG,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,CACvD,CAAC;AACJ,CAAC;AAED,SAAS,GAAG,CAAC,CAAS;IACpB,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACvC,CAAC","sourcesContent":["/**\n * Format a Date as a local-timezone timestamp string: YYYY-MM-DD HH:MM:SS±HH:MM\n * Returns null when the date is invalid (non-finite time value).\n *\n * This format is used both when writing user messages (agent.ts) and when\n * reading history back into sessions (chat-session-manager.ts). Keeping it\n * in one place ensures normalizeComparableText's regex stays valid.\n */\nexport function formatLocalTimestamp(date: Date): string | null {\n const time = date.getTime();\n if (!Number.isFinite(time)) return null;\n\n const offset = -date.getTimezoneOffset();\n const sign = offset >= 0 ? \"+\" : \"-\";\n const abs = Math.abs(offset);\n return (\n `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ` +\n `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}` +\n `${sign}${pad(Math.floor(abs / 60))}:${pad(abs % 60)}`\n );\n}\n\nfunction pad(n: number): string {\n return n.toString().padStart(2, \"0\");\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/utils/env.ts"],"names":[],"mappings":"AAAA,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMxD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAG/D","sourcesContent":["export function readEnv(name: string): string | undefined {\n const raw = process.env[name]?.trim();\n if (raw) return raw;\n\n const prefixed = process.env[`MIKAN_${name}`]?.trim();\n return prefixed || undefined;\n}\n\nexport function setEnvAliases(name: string, value: string): void {\n process.env[name] = value;\n process.env[`MIKAN_${name}`] = value;\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/utils/env.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC;IACtC,IAAI,GAAG;QAAE,OAAO,GAAG,CAAC;IAEpB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC;IACtD,OAAO,QAAQ,IAAI,SAAS,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,KAAa;IACvD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;IAC1B,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC;AACvC,CAAC","sourcesContent":["export function readEnv(name: string): string | undefined {\n const raw = process.env[name]?.trim();\n if (raw) return raw;\n\n const prefixed = process.env[`MIKAN_${name}`]?.trim();\n return prefixed || undefined;\n}\n\nexport function setEnvAliases(name: string, value: string): void {\n process.env[name] = value;\n process.env[`MIKAN_${name}`] = value;\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-guards.d.ts","sourceRoot":"","sources":["../../src/utils/file-guards.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAIzD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEjD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CASrE;AAED,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,IAAI,CAAC,EACxC,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GAC3C,CAAC,GAAG,SAAS,CAGf;AAED,wBAAgB,0BAA0B,CAAC,CAAC,SAAS,OAAO,EAC1D,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,CAAC,EACT,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GAC3C,MAAM,CAAC,CAAC,CAAC,GAAG,SAAS,CAGvB;AAWD,wBAAgB,cAAc,CAAC,CAAC,EAC9B,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,IAAI,CAAC,EACxC,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GAC3C,CAAC,CAMH;AAED,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,OAAO,EACpD,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,CAAC,EACT,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GAC3C,MAAM,CAAC,CAAC,CAAC,CAeX;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE","sourcesContent":["import type { Static, TSchema } from \"@sinclair/typebox\";\nimport { Value } from \"@sinclair/typebox/value\";\nimport { mkdirSync, readFileSync } from \"fs\";\n\nexport function ensureDirExists(dir: string): void {\n mkdirSync(dir, { recursive: true });\n}\n\nexport function readTextFileIfExists(path: string): string | undefined {\n try {\n return readFileSync(path, \"utf-8\");\n } catch (err) {\n if (err instanceof Error && \"code\" in err && err.code === \"ENOENT\") {\n return undefined;\n }\n throw err;\n }\n}\n\nexport function readJsonFileIfExists<T>(\n path: string,\n validate: (value: unknown) => value is T,\n malformedMessage: (detail: string) => string,\n): T | undefined {\n const raw = readTextFileIfExists(path);\n return raw === undefined ? undefined : parseJsonValue(raw, validate, malformedMessage);\n}\n\nexport function readJsonSchemaFileIfExists<T extends TSchema>(\n path: string,\n schema: T,\n malformedMessage: (detail: string) => string,\n): Static<T> | undefined {\n const raw = readTextFileIfExists(path);\n return raw === undefined ? undefined : parseJsonSchemaValue(raw, schema, malformedMessage);\n}\n\nfunction parseJson(raw: string, malformedMessage: (detail: string) => string): unknown {\n try {\n return JSON.parse(raw);\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(malformedMessage(detail), { cause: err });\n }\n}\n\nexport function parseJsonValue<T>(\n raw: string,\n validate: (value: unknown) => value is T,\n malformedMessage: (detail: string) => string,\n): T {\n const parsed = parseJson(raw, malformedMessage);\n if (!validate(parsed)) {\n throw new Error(malformedMessage(\"unexpected JSON shape\"));\n }\n return parsed;\n}\n\nexport function parseJsonSchemaValue<T extends TSchema>(\n raw: string,\n schema: T,\n malformedMessage: (detail: string) => string,\n): Static<T> {\n const parsed = parseJson(raw, malformedMessage);\n if (!Value.Check(schema, parsed)) {\n let firstError: { path: string; message: string } | undefined;\n for (const err of Value.Errors(schema, parsed)) {\n firstError = err;\n break;\n }\n const detail =\n !firstError || firstError.path === \"\" || firstError.path === \"/\"\n ? \"unexpected JSON shape\"\n : `${firstError.path}: ${firstError.message}`;\n throw new Error(malformedMessage(detail));\n }\n return parsed;\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-guards.js","sourceRoot":"","sources":["../../src/utils/file-guards.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Static, TSchema } from \"@sinclair/typebox\";\nimport { Value } from \"@sinclair/typebox/value\";\nimport { mkdirSync, readFileSync } from \"fs\";\n\nexport function ensureDirExists(dir: string): void {\n mkdirSync(dir, { recursive: true });\n}\n\nexport function readTextFileIfExists(path: string): string | undefined {\n try {\n return readFileSync(path, \"utf-8\");\n } catch (err) {\n if (err instanceof Error && \"code\" in err && err.code === \"ENOENT\") {\n return undefined;\n }\n throw err;\n }\n}\n\nexport function readJsonFileIfExists<T>(\n path: string,\n validate: (value: unknown) => value is T,\n malformedMessage: (detail: string) => string,\n): T | undefined {\n const raw = readTextFileIfExists(path);\n return raw === undefined ? undefined : parseJsonValue(raw, validate, malformedMessage);\n}\n\nexport function readJsonSchemaFileIfExists<T extends TSchema>(\n path: string,\n schema: T,\n malformedMessage: (detail: string) => string,\n): Static<T> | undefined {\n const raw = readTextFileIfExists(path);\n return raw === undefined ? undefined : parseJsonSchemaValue(raw, schema, malformedMessage);\n}\n\nfunction parseJson(raw: string, malformedMessage: (detail: string) => string): unknown {\n try {\n return JSON.parse(raw);\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(malformedMessage(detail), { cause: err });\n }\n}\n\nexport function parseJsonValue<T>(\n raw: string,\n validate: (value: unknown) => value is T,\n malformedMessage: (detail: string) => string,\n): T {\n const parsed = parseJson(raw, malformedMessage);\n if (!validate(parsed)) {\n throw new Error(malformedMessage(\"unexpected JSON shape\"));\n }\n return parsed;\n}\n\nexport function parseJsonSchemaValue<T extends TSchema>(\n raw: string,\n schema: T,\n malformedMessage: (detail: string) => string,\n): Static<T> {\n const parsed = parseJson(raw, malformedMessage);\n if (!Value.Check(schema, parsed)) {\n let firstError: { path: string; message: string } | undefined;\n for (const err of Value.Errors(schema, parsed)) {\n firstError = err;\n break;\n }\n const detail =\n !firstError || firstError.path === \"\" || firstError.path === \"/\"\n ? \"unexpected JSON shape\"\n : `${firstError.path}: ${firstError.message}`;\n throw new Error(malformedMessage(detail));\n }\n return parsed;\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-atomic.d.ts","sourceRoot":"","sources":["../../src/utils/fs-atomic.ts"],"names":[],"mappings":"AAaA;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAiChF","sourcesContent":["import {\n closeSync,\n constants as fsConstants,\n openSync,\n renameSync,\n unlinkSync,\n writeSync,\n} from \"fs\";\nimport { randomBytes } from \"crypto\";\nimport { basename, dirname, join } from \"path\";\n\nconst PRIVATE_FILE_MODE = 0o600;\n\n/**\n * Write `content` to `targetPath` with mode 0600, even when `targetPath`\n * already exists. Uses O_CREAT|O_EXCL on a temp sibling (so the kernel\n * guarantees permissions at creation, not after a racy chmod) and then\n * rename(2) into place for atomicity. Readers never see a torn write,\n * and a crash mid-write leaves either the old file or a stray .tmp\n * (cleaned by the next attempt or manually) — never a half-written target.\n */\nexport function atomicWritePrivateFile(targetPath: string, content: string): void {\n const dir = dirname(targetPath);\n const tmpPath = join(\n dir,\n `.${basename(targetPath)}.${process.pid}.${randomBytes(8).toString(\"hex\")}.tmp`,\n );\n const fd = openSync(\n tmpPath,\n fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL,\n PRIVATE_FILE_MODE,\n );\n try {\n writeSync(fd, content);\n } catch (err) {\n try {\n unlinkSync(tmpPath);\n } catch {\n // ignore — original error is more informative\n }\n throw err;\n } finally {\n closeSync(fd);\n }\n try {\n renameSync(tmpPath, targetPath);\n } catch (err) {\n try {\n unlinkSync(tmpPath);\n } catch {\n // ignore\n }\n throw err;\n }\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-atomic.js","sourceRoot":"","sources":["../../src/utils/fs-atomic.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,SAAS,IAAI,WAAW,EACxB,QAAQ,EACR,UAAU,EACV,UAAU,EACV,SAAS,GACV,MAAM,IAAI,CAAC;AACZ,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE/C,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAEhC;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CAAC,UAAkB,EAAE,OAAe;IACxE,MAAM,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAChC,MAAM,OAAO,GAAG,IAAI,CAClB,GAAG,EACH,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAChF,CAAC;IACF,MAAM,EAAE,GAAG,QAAQ,CACjB,OAAO,EACP,WAAW,CAAC,QAAQ,GAAG,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,MAAM,EAC/D,iBAAiB,CAClB,CAAC;IACF,IAAI,CAAC;QACH,SAAS,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IACzB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC;YACH,UAAU,CAAC,OAAO,CAAC,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,8CAA8C;QAChD,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;YAAS,CAAC;QACT,SAAS,CAAC,EAAE,CAAC,CAAC;IAChB,CAAC;IACD,IAAI,CAAC;QACH,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC;YACH,UAAU,CAAC,OAAO,CAAC,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC","sourcesContent":["import {\n closeSync,\n constants as fsConstants,\n openSync,\n renameSync,\n unlinkSync,\n writeSync,\n} from \"fs\";\nimport { randomBytes } from \"crypto\";\nimport { basename, dirname, join } from \"path\";\n\nconst PRIVATE_FILE_MODE = 0o600;\n\n/**\n * Write `content` to `targetPath` with mode 0600, even when `targetPath`\n * already exists. Uses O_CREAT|O_EXCL on a temp sibling (so the kernel\n * guarantees permissions at creation, not after a racy chmod) and then\n * rename(2) into place for atomicity. Readers never see a torn write,\n * and a crash mid-write leaves either the old file or a stray .tmp\n * (cleaned by the next attempt or manually) — never a half-written target.\n */\nexport function atomicWritePrivateFile(targetPath: string, content: string): void {\n const dir = dirname(targetPath);\n const tmpPath = join(\n dir,\n `.${basename(targetPath)}.${process.pid}.${randomBytes(8).toString(\"hex\")}.tmp`,\n );\n const fd = openSync(\n tmpPath,\n fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL,\n PRIVATE_FILE_MODE,\n );\n try {\n writeSync(fd, content);\n } catch (err) {\n try {\n unlinkSync(tmpPath);\n } catch {\n // ignore — original error is more informative\n }\n throw err;\n } finally {\n closeSync(fd);\n }\n try {\n renameSync(tmpPath, targetPath);\n } catch (err) {\n try {\n unlinkSync(tmpPath);\n } catch {\n // ignore\n }\n throw err;\n }\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/utils/html.ts"],"names":[],"mappings":"AAAA,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKhD","sourcesContent":["export function escapeHtml(value: string): string {\n return value.replace(\n /[&<>\"']/g,\n (c) => ({ \"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\", '\"': \"&quot;\", \"'\": \"&#39;\" })[c]!,\n );\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/utils/html.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,KAAK,CAAC,OAAO,CAClB,UAAU,EACV,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAE,CACrF,CAAC;AACJ,CAAC","sourcesContent":["export function escapeHtml(value: string): string {\n return value.replace(\n /[&<>\"']/g,\n (c) => ({ \"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\", '\"': \"&quot;\", \"'\": \"&#39;\" })[c]!,\n );\n}\n"]}
@@ -0,0 +1,10 @@
1
+ import type { IncomingMessage, ServerResponse } from "http";
2
+ /**
3
+ * Read and size-limit an HTTP request body.
4
+ *
5
+ * Responds with 413 and destroys the request if the body exceeds `maxBytes`.
6
+ * Resolves with the raw body string on success, or `null` if the size limit
7
+ * was exceeded (the response has already been sent in that case).
8
+ */
9
+ export declare function readRawBody(req: IncomingMessage, res: ServerResponse, maxBytes: number): Promise<string | null>;
10
+ //# sourceMappingURL=http-body.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-body.d.ts","sourceRoot":"","sources":["../../src/utils/http-body.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAE5D;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAuBxB","sourcesContent":["import type { IncomingMessage, ServerResponse } from \"http\";\n\n/**\n * Read and size-limit an HTTP request body.\n *\n * Responds with 413 and destroys the request if the body exceeds `maxBytes`.\n * Resolves with the raw body string on success, or `null` if the size limit\n * was exceeded (the response has already been sent in that case).\n */\nexport function readRawBody(\n req: IncomingMessage,\n res: ServerResponse,\n maxBytes: number,\n): Promise<string | null> {\n return new Promise<string | null>((resolve) => {\n let data = \"\";\n let tooLarge = false;\n\n req.on(\"data\", (chunk: Buffer) => {\n if (tooLarge) return;\n data += chunk.toString();\n if (data.length > maxBytes) {\n tooLarge = true;\n res.writeHead(413);\n res.end();\n req.destroy();\n resolve(null);\n }\n });\n req.on(\"end\", () => {\n if (!tooLarge) resolve(data);\n });\n req.on(\"error\", () => {\n if (!tooLarge) resolve(data);\n });\n });\n}\n"]}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Read and size-limit an HTTP request body.
3
+ *
4
+ * Responds with 413 and destroys the request if the body exceeds `maxBytes`.
5
+ * Resolves with the raw body string on success, or `null` if the size limit
6
+ * was exceeded (the response has already been sent in that case).
7
+ */
8
+ export function readRawBody(req, res, maxBytes) {
9
+ return new Promise((resolve) => {
10
+ let data = "";
11
+ let tooLarge = false;
12
+ req.on("data", (chunk) => {
13
+ if (tooLarge)
14
+ return;
15
+ data += chunk.toString();
16
+ if (data.length > maxBytes) {
17
+ tooLarge = true;
18
+ res.writeHead(413);
19
+ res.end();
20
+ req.destroy();
21
+ resolve(null);
22
+ }
23
+ });
24
+ req.on("end", () => {
25
+ if (!tooLarge)
26
+ resolve(data);
27
+ });
28
+ req.on("error", () => {
29
+ if (!tooLarge)
30
+ resolve(data);
31
+ });
32
+ });
33
+ }
34
+ //# sourceMappingURL=http-body.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-body.js","sourceRoot":"","sources":["../../src/utils/http-body.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CACzB,GAAoB,EACpB,GAAmB,EACnB,QAAgB;IAEhB,OAAO,IAAI,OAAO,CAAgB,CAAC,OAAO,EAAE,EAAE;QAC5C,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,IAAI,QAAQ,GAAG,KAAK,CAAC;QAErB,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YAC/B,IAAI,QAAQ;gBAAE,OAAO;YACrB,IAAI,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC;gBAC3B,QAAQ,GAAG,IAAI,CAAC;gBAChB,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;gBACnB,GAAG,CAAC,GAAG,EAAE,CAAC;gBACV,GAAG,CAAC,OAAO,EAAE,CAAC;gBACd,OAAO,CAAC,IAAI,CAAC,CAAC;YAChB,CAAC;QACH,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACjB,IAAI,CAAC,QAAQ;gBAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACnB,IAAI,CAAC,QAAQ;gBAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { IncomingMessage, ServerResponse } from \"http\";\n\n/**\n * Read and size-limit an HTTP request body.\n *\n * Responds with 413 and destroys the request if the body exceeds `maxBytes`.\n * Resolves with the raw body string on success, or `null` if the size limit\n * was exceeded (the response has already been sent in that case).\n */\nexport function readRawBody(\n req: IncomingMessage,\n res: ServerResponse,\n maxBytes: number,\n): Promise<string | null> {\n return new Promise<string | null>((resolve) => {\n let data = \"\";\n let tooLarge = false;\n\n req.on(\"data\", (chunk: Buffer) => {\n if (tooLarge) return;\n data += chunk.toString();\n if (data.length > maxBytes) {\n tooLarge = true;\n res.writeHead(413);\n res.end();\n req.destroy();\n resolve(null);\n }\n });\n req.on(\"end\", () => {\n if (!tooLarge) resolve(data);\n });\n req.on(\"error\", () => {\n if (!tooLarge) resolve(data);\n });\n });\n}\n"]}
@@ -0,0 +1,34 @@
1
+ import type { SandboxConfig } from "../sandbox/index.js";
2
+ export declare function normalizeSharedVaultName(name: string): string | undefined;
3
+ export declare function sharedVaultKey(name: string): string | undefined;
4
+ export type { ResolvedVault, VaultManager } from "./types.js";
5
+ import type { ResolvedVault, VaultManager } from "./types.js";
6
+ /**
7
+ * Parse a KEY=VALUE env file. Supports:
8
+ * - Lines starting with # are comments
9
+ * - Empty lines are skipped
10
+ * - Values can be quoted with single or double quotes (quotes are stripped)
11
+ * - No variable expansion
12
+ * - The value is everything after the first `=` to end of line (no inline comments)
13
+ */
14
+ export declare function parseEnvFile(content: string): Record<string, string>;
15
+ export declare class FileVaultManager implements VaultManager {
16
+ private readonly vaultsDir;
17
+ constructor(stateDir: string);
18
+ isEnabled(): boolean;
19
+ hasEntry(key: string): boolean;
20
+ listSharedVaults(): string[];
21
+ deleteSharedVault(name: string): boolean;
22
+ copySharedVaultTo(name: string, targetKey: string): {
23
+ filesCopied: number;
24
+ envKeysCopied: number;
25
+ };
26
+ resolve(userId: string): ResolvedVault | undefined;
27
+ getSandboxConfig(userId: string, baseConfig: SandboxConfig): SandboxConfig;
28
+ list(): ResolvedVault[];
29
+ upsertEnv(key: string, env: Record<string, string>): void;
30
+ upsertFile(key: string, relativePath: string, content: string, targetPath?: string): void;
31
+ private buildResolved;
32
+ }
33
+ export declare function defaultVaultTargetPath(relativePath: string): string;
34
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vault/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAOzD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIzE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG/D;AAWD,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAsB,YAAY,EAAE,MAAM,YAAY,CAAC;AAIlF;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA2BpE;AAID,qBAAa,gBAAiB,YAAW,YAAY;IACnD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IAEnC,YAAY,QAAQ,EAAE,MAAM,EAE3B;IAED,SAAS,IAAI,OAAO,CAEnB;IAED,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE7B;IAED,gBAAgB,IAAI,MAAM,EAAE,CAO3B;IAED,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOvC;IAED,iBAAiB,CACf,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAChB;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAUhD;IAED,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAIjD;IAED,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,GAAG,aAAa,CAQzE;IAED,IAAI,IAAI,aAAa,EAAE,CAOtB;IAED,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAcxD;IAED,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAcxF;IAID,OAAO,CAAC,aAAa;CA6BtB;AAuFD,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAGnE","sourcesContent":["import { chmodSync, copyFileSync, existsSync, mkdirSync, readdirSync, rmSync } from \"fs\";\nimport { dirname, isAbsolute, join, normalize, sep } from \"path\";\nimport { readTextFileIfExists } from \"../utils/file-guards.js\";\nimport type { SandboxConfig } from \"../sandbox/index.js\";\nimport { atomicWritePrivateFile } from \"../utils/fs-atomic.js\";\nimport { reportUserFacingError } from \"../observability/sentry.js\";\n\nconst PRIVATE_DIR_MODE = 0o700;\nconst SHARED_VAULT_DIR = \"shared\";\n\nexport function normalizeSharedVaultName(name: string): string | undefined {\n const trimmed = name.trim();\n if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(trimmed)) return undefined;\n return trimmed;\n}\n\nexport function sharedVaultKey(name: string): string | undefined {\n const normalized = normalizeSharedVaultName(name);\n return normalized ? `${SHARED_VAULT_DIR}/${normalized}` : undefined;\n}\n\nfunction sanitizeCloudflareSandboxId(value: string): string {\n return (\n value\n .toLowerCase()\n .replace(/[^a-z0-9-]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\") || \"unknown\"\n );\n}\n\nexport type { ResolvedVault, VaultManager } from \"./types.js\";\nimport type { ResolvedVault, ResolvedVaultMount, VaultManager } from \"./types.js\";\n\n// ── parseEnvFile ───────────────────────────────────────────────────────────────\n\n/**\n * Parse a KEY=VALUE env file. Supports:\n * - Lines starting with # are comments\n * - Empty lines are skipped\n * - Values can be quoted with single or double quotes (quotes are stripped)\n * - No variable expansion\n * - The value is everything after the first `=` to end of line (no inline comments)\n */\nexport function parseEnvFile(content: string): Record<string, string> {\n const env: Record<string, string> = {};\n const lines = content.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\").split(\"\\n\");\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"#\")) continue;\n\n const eqIndex = trimmed.indexOf(\"=\");\n if (eqIndex === -1) continue;\n\n const key = trimmed.slice(0, eqIndex).trim();\n if (!key) continue;\n\n let value = trimmed.slice(eqIndex + 1);\n\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n\n env[key] = value;\n }\n\n return env;\n}\n\n// ── FileVaultManager ───────────────────────────────────────────────────────────\n\nexport class FileVaultManager implements VaultManager {\n private readonly vaultsDir: string;\n\n constructor(stateDir: string) {\n this.vaultsDir = join(stateDir, \"vaults\");\n }\n\n isEnabled(): boolean {\n return existsSync(this.vaultsDir);\n }\n\n hasEntry(key: string): boolean {\n return existsSync(join(this.vaultsDir, key));\n }\n\n listSharedVaults(): string[] {\n const sharedDir = join(this.vaultsDir, SHARED_VAULT_DIR);\n if (!existsSync(sharedDir)) return [];\n return readdirSync(sharedDir, { withFileTypes: true })\n .filter((entry) => entry.isDirectory() && normalizeSharedVaultName(entry.name) === entry.name)\n .map((entry) => entry.name)\n .toSorted((left, right) => left.localeCompare(right));\n }\n\n deleteSharedVault(name: string): boolean {\n const key = sharedVaultKey(name);\n if (!key) throw new Error(`vault: invalid shared login name: ${name}`);\n const dir = join(this.vaultsDir, key);\n const existed = existsSync(dir);\n rmSync(dir, { recursive: true, force: true });\n return existed;\n }\n\n copySharedVaultTo(\n name: string,\n targetKey: string,\n ): { filesCopied: number; envKeysCopied: number } {\n const sourceKey = sharedVaultKey(name);\n if (!sourceKey) throw new Error(`vault: invalid shared login name: ${name}`);\n const sourceDir = join(this.vaultsDir, sourceKey);\n if (!existsSync(sourceDir)) throw new Error(`vault: shared login \"${name}\" does not exist`);\n\n const targetDir = join(this.vaultsDir, targetKey);\n ensurePrivateDir(this.vaultsDir);\n ensurePrivateDir(targetDir);\n return copyVaultDir(sourceDir, targetDir);\n }\n\n resolve(userId: string): ResolvedVault | undefined {\n const dir = join(this.vaultsDir, userId);\n if (!existsSync(dir)) return undefined;\n return this.buildResolved(userId);\n }\n\n getSandboxConfig(userId: string, baseConfig: SandboxConfig): SandboxConfig {\n if (baseConfig.type === \"cloudflare\") {\n return {\n type: \"cloudflare\",\n sandboxId: `${baseConfig.sandboxId}-${sanitizeCloudflareSandboxId(userId)}`,\n };\n }\n return baseConfig;\n }\n\n list(): ResolvedVault[] {\n if (!existsSync(this.vaultsDir)) return [];\n const keys = new Set<string>();\n for (const entry of readdirSync(this.vaultsDir, { withFileTypes: true })) {\n if (entry.isDirectory()) keys.add(entry.name);\n }\n return Array.from(keys, (key) => this.buildResolved(key));\n }\n\n upsertEnv(key: string, env: Record<string, string>): void {\n const dir = join(this.vaultsDir, key);\n const envPath = join(dir, \"env\");\n ensurePrivateDir(this.vaultsDir);\n ensurePrivateDir(dir);\n const existingContent = readTextFileIfExists(envPath);\n const existing = existingContent ? parseEnvFile(existingContent) : {};\n const merged = { ...existing, ...env };\n const content =\n Object.entries(merged)\n .toSorted(([left], [right]) => left.localeCompare(right))\n .map(([envKey, value]) => `${envKey}=${value}`)\n .join(\"\\n\") + \"\\n\";\n atomicWritePrivateFile(envPath, content);\n }\n\n upsertFile(key: string, relativePath: string, content: string, targetPath?: string): void {\n const normalizedPath = normalizeVaultRelativePath(relativePath);\n if (!normalizedPath || (targetPath !== undefined && !normalizeVaultTargetPath(targetPath))) {\n throw new Error(`vault: invalid relative secret file path for \"${key}\": ${relativePath}`);\n }\n\n const dir = join(this.vaultsDir, key);\n const filePath = join(dir, normalizedPath);\n\n ensurePrivateDir(this.vaultsDir);\n ensurePrivateDir(dir);\n const parentDir = dirname(filePath);\n if (parentDir !== dir) ensurePrivateDir(parentDir);\n atomicWritePrivateFile(filePath, content);\n }\n\n // ── private ────────────────────────────────────────────────────────────────\n\n private buildResolved(key: string): ResolvedVault {\n const dir = join(this.vaultsDir, key);\n const mounts = inferMountsFromDir(dir);\n\n let env: Record<string, string> = {};\n const envContent = readTextFileIfExists(join(dir, \"env\"));\n if (envContent !== undefined) {\n try {\n env = parseEnvFile(envContent);\n } catch (err) {\n console.error(`vault: failed to parse env file for \"${key}\":`, err);\n reportUserFacingError(err, {\n domain: \"sandbox\",\n surface: \"vault_injection\",\n operation: \"parse_env\",\n severity: \"warning\",\n context: { vaultKey: key, fatal: false },\n });\n }\n }\n\n return {\n userId: key,\n displayName: key,\n dir,\n mounts,\n env,\n };\n }\n}\n\nfunction inferMountsFromDir(dir: string): ResolvedVaultMount[] {\n if (!existsSync(dir)) return [];\n\n const mounts: ResolvedVaultMount[] = [];\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (entry.name === \"env\") continue;\n const source = join(dir, entry.name);\n const target = inferredVaultTargetPath(entry.name);\n if (!target) continue;\n mounts.push({ source, target });\n }\n return mounts;\n}\n\nfunction ensurePrivateDir(path: string): void {\n mkdirSync(path, { recursive: true, mode: PRIVATE_DIR_MODE });\n chmodSync(path, PRIVATE_DIR_MODE);\n}\n\nfunction copyVaultDir(\n sourceDir: string,\n targetDir: string,\n): {\n filesCopied: number;\n envKeysCopied: number;\n} {\n let filesCopied = 0;\n let envKeysCopied = 0;\n\n for (const entry of readdirSync(sourceDir, { withFileTypes: true })) {\n const sourcePath = join(sourceDir, entry.name);\n const targetPath = join(targetDir, entry.name);\n\n if (entry.name === \"env\" && entry.isFile()) {\n const sourceEnv = parseEnvFile(readTextFileIfExists(sourcePath) ?? \"\");\n const targetEnv = parseEnvFile(readTextFileIfExists(targetPath) ?? \"\");\n const merged = { ...targetEnv, ...sourceEnv };\n const content =\n Object.entries(merged)\n .toSorted(([left], [right]) => left.localeCompare(right))\n .map(([envKey, value]) => `${envKey}=${value}`)\n .join(\"\\n\") + \"\\n\";\n atomicWritePrivateFile(targetPath, content);\n envKeysCopied += Object.keys(sourceEnv).length;\n continue;\n }\n\n if (entry.isDirectory()) {\n ensurePrivateDir(targetPath);\n const nested = copyVaultDir(sourcePath, targetPath);\n filesCopied += nested.filesCopied;\n envKeysCopied += nested.envKeysCopied;\n continue;\n }\n\n if (!entry.isFile()) continue;\n copyFileSync(sourcePath, targetPath);\n chmodSync(targetPath, 0o600);\n filesCopied++;\n }\n\n return { filesCopied, envKeysCopied };\n}\n\nfunction normalizeVaultRelativePath(relativePath: string): string | undefined {\n const trimmed = relativePath.trim();\n if (!trimmed || isAbsolute(trimmed)) return undefined;\n\n const normalized = normalize(trimmed).split(sep).join(\"/\");\n if (!normalized || normalized === \".\" || normalized === \"..\" || normalized.startsWith(\"../\")) {\n return undefined;\n }\n return normalized;\n}\n\nfunction normalizeVaultTargetPath(targetPath?: string): string | undefined {\n if (targetPath === undefined) return undefined;\n\n const trimmed = targetPath.trim();\n if (!trimmed || !trimmed.startsWith(\"/\")) return undefined;\n\n const normalized = normalize(trimmed).split(sep).join(\"/\");\n return normalized.startsWith(\"/\") ? normalized : undefined;\n}\n\nexport function defaultVaultTargetPath(relativePath: string): string {\n const normalized = normalizeVaultRelativePath(relativePath) ?? relativePath.replace(/^\\/+/, \"\");\n return `/root/${normalized}`;\n}\n\nfunction inferredVaultTargetPath(relativePath: string): string | undefined {\n const normalized = normalizeVaultRelativePath(relativePath);\n if (!normalized) return undefined;\n\n if (normalized === \"gws.json\") {\n return \"/root/.config/gws/credentials.json\";\n }\n if (normalized === \"gcloud-adc.json\") {\n return \"/root/.config/gcloud/application_default_credentials.json\";\n }\n if (normalized === \".ssh\" || normalized.startsWith(\".ssh/\")) {\n return \"/root/.ssh\";\n }\n if (normalized === \".kube\" || normalized.startsWith(\".kube/\")) {\n return \"/root/.kube\";\n }\n if (normalized === \".config/gh\" || normalized.startsWith(\".config/gh/\")) {\n return \"/root/.config/gh\";\n }\n\n return defaultVaultTargetPath(normalized);\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  import { chmodSync, copyFileSync, existsSync, mkdirSync, readdirSync, rmSync } from "fs";
2
2
  import { dirname, isAbsolute, join, normalize, sep } from "path";
3
- import { readTextFileIfExists } from "./file-guards.js";
4
- import { atomicWritePrivateFile } from "./fs-atomic.js";
5
- import { reportUserFacingError } from "./sentry.js";
3
+ import { readTextFileIfExists } from "../utils/file-guards.js";
4
+ import { atomicWritePrivateFile } from "../utils/fs-atomic.js";
5
+ import { reportUserFacingError } from "../observability/sentry.js";
6
6
  const PRIVATE_DIR_MODE = 0o700;
7
7
  const SHARED_VAULT_DIR = "shared";
8
8
  export function normalizeSharedVaultName(name) {
@@ -272,4 +272,4 @@ function inferredVaultTargetPath(relativePath) {
272
272
  }
273
273
  return defaultVaultTargetPath(normalized);
274
274
  }
275
- //# sourceMappingURL=vault.js.map
275
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vault/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { chmodSync, copyFileSync, existsSync, mkdirSync, readdirSync, rmSync } from \"fs\";\nimport { dirname, isAbsolute, join, normalize, sep } from \"path\";\nimport { readTextFileIfExists } from \"../utils/file-guards.js\";\nimport type { SandboxConfig } from \"../sandbox/index.js\";\nimport { atomicWritePrivateFile } from \"../utils/fs-atomic.js\";\nimport { reportUserFacingError } from \"../observability/sentry.js\";\n\nconst PRIVATE_DIR_MODE = 0o700;\nconst SHARED_VAULT_DIR = \"shared\";\n\nexport function normalizeSharedVaultName(name: string): string | undefined {\n const trimmed = name.trim();\n if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(trimmed)) return undefined;\n return trimmed;\n}\n\nexport function sharedVaultKey(name: string): string | undefined {\n const normalized = normalizeSharedVaultName(name);\n return normalized ? `${SHARED_VAULT_DIR}/${normalized}` : undefined;\n}\n\nfunction sanitizeCloudflareSandboxId(value: string): string {\n return (\n value\n .toLowerCase()\n .replace(/[^a-z0-9-]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\") || \"unknown\"\n );\n}\n\nexport type { ResolvedVault, VaultManager } from \"./types.js\";\nimport type { ResolvedVault, ResolvedVaultMount, VaultManager } from \"./types.js\";\n\n// ── parseEnvFile ───────────────────────────────────────────────────────────────\n\n/**\n * Parse a KEY=VALUE env file. Supports:\n * - Lines starting with # are comments\n * - Empty lines are skipped\n * - Values can be quoted with single or double quotes (quotes are stripped)\n * - No variable expansion\n * - The value is everything after the first `=` to end of line (no inline comments)\n */\nexport function parseEnvFile(content: string): Record<string, string> {\n const env: Record<string, string> = {};\n const lines = content.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\").split(\"\\n\");\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"#\")) continue;\n\n const eqIndex = trimmed.indexOf(\"=\");\n if (eqIndex === -1) continue;\n\n const key = trimmed.slice(0, eqIndex).trim();\n if (!key) continue;\n\n let value = trimmed.slice(eqIndex + 1);\n\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n\n env[key] = value;\n }\n\n return env;\n}\n\n// ── FileVaultManager ───────────────────────────────────────────────────────────\n\nexport class FileVaultManager implements VaultManager {\n private readonly vaultsDir: string;\n\n constructor(stateDir: string) {\n this.vaultsDir = join(stateDir, \"vaults\");\n }\n\n isEnabled(): boolean {\n return existsSync(this.vaultsDir);\n }\n\n hasEntry(key: string): boolean {\n return existsSync(join(this.vaultsDir, key));\n }\n\n listSharedVaults(): string[] {\n const sharedDir = join(this.vaultsDir, SHARED_VAULT_DIR);\n if (!existsSync(sharedDir)) return [];\n return readdirSync(sharedDir, { withFileTypes: true })\n .filter((entry) => entry.isDirectory() && normalizeSharedVaultName(entry.name) === entry.name)\n .map((entry) => entry.name)\n .toSorted((left, right) => left.localeCompare(right));\n }\n\n deleteSharedVault(name: string): boolean {\n const key = sharedVaultKey(name);\n if (!key) throw new Error(`vault: invalid shared login name: ${name}`);\n const dir = join(this.vaultsDir, key);\n const existed = existsSync(dir);\n rmSync(dir, { recursive: true, force: true });\n return existed;\n }\n\n copySharedVaultTo(\n name: string,\n targetKey: string,\n ): { filesCopied: number; envKeysCopied: number } {\n const sourceKey = sharedVaultKey(name);\n if (!sourceKey) throw new Error(`vault: invalid shared login name: ${name}`);\n const sourceDir = join(this.vaultsDir, sourceKey);\n if (!existsSync(sourceDir)) throw new Error(`vault: shared login \"${name}\" does not exist`);\n\n const targetDir = join(this.vaultsDir, targetKey);\n ensurePrivateDir(this.vaultsDir);\n ensurePrivateDir(targetDir);\n return copyVaultDir(sourceDir, targetDir);\n }\n\n resolve(userId: string): ResolvedVault | undefined {\n const dir = join(this.vaultsDir, userId);\n if (!existsSync(dir)) return undefined;\n return this.buildResolved(userId);\n }\n\n getSandboxConfig(userId: string, baseConfig: SandboxConfig): SandboxConfig {\n if (baseConfig.type === \"cloudflare\") {\n return {\n type: \"cloudflare\",\n sandboxId: `${baseConfig.sandboxId}-${sanitizeCloudflareSandboxId(userId)}`,\n };\n }\n return baseConfig;\n }\n\n list(): ResolvedVault[] {\n if (!existsSync(this.vaultsDir)) return [];\n const keys = new Set<string>();\n for (const entry of readdirSync(this.vaultsDir, { withFileTypes: true })) {\n if (entry.isDirectory()) keys.add(entry.name);\n }\n return Array.from(keys, (key) => this.buildResolved(key));\n }\n\n upsertEnv(key: string, env: Record<string, string>): void {\n const dir = join(this.vaultsDir, key);\n const envPath = join(dir, \"env\");\n ensurePrivateDir(this.vaultsDir);\n ensurePrivateDir(dir);\n const existingContent = readTextFileIfExists(envPath);\n const existing = existingContent ? parseEnvFile(existingContent) : {};\n const merged = { ...existing, ...env };\n const content =\n Object.entries(merged)\n .toSorted(([left], [right]) => left.localeCompare(right))\n .map(([envKey, value]) => `${envKey}=${value}`)\n .join(\"\\n\") + \"\\n\";\n atomicWritePrivateFile(envPath, content);\n }\n\n upsertFile(key: string, relativePath: string, content: string, targetPath?: string): void {\n const normalizedPath = normalizeVaultRelativePath(relativePath);\n if (!normalizedPath || (targetPath !== undefined && !normalizeVaultTargetPath(targetPath))) {\n throw new Error(`vault: invalid relative secret file path for \"${key}\": ${relativePath}`);\n }\n\n const dir = join(this.vaultsDir, key);\n const filePath = join(dir, normalizedPath);\n\n ensurePrivateDir(this.vaultsDir);\n ensurePrivateDir(dir);\n const parentDir = dirname(filePath);\n if (parentDir !== dir) ensurePrivateDir(parentDir);\n atomicWritePrivateFile(filePath, content);\n }\n\n // ── private ────────────────────────────────────────────────────────────────\n\n private buildResolved(key: string): ResolvedVault {\n const dir = join(this.vaultsDir, key);\n const mounts = inferMountsFromDir(dir);\n\n let env: Record<string, string> = {};\n const envContent = readTextFileIfExists(join(dir, \"env\"));\n if (envContent !== undefined) {\n try {\n env = parseEnvFile(envContent);\n } catch (err) {\n console.error(`vault: failed to parse env file for \"${key}\":`, err);\n reportUserFacingError(err, {\n domain: \"sandbox\",\n surface: \"vault_injection\",\n operation: \"parse_env\",\n severity: \"warning\",\n context: { vaultKey: key, fatal: false },\n });\n }\n }\n\n return {\n userId: key,\n displayName: key,\n dir,\n mounts,\n env,\n };\n }\n}\n\nfunction inferMountsFromDir(dir: string): ResolvedVaultMount[] {\n if (!existsSync(dir)) return [];\n\n const mounts: ResolvedVaultMount[] = [];\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (entry.name === \"env\") continue;\n const source = join(dir, entry.name);\n const target = inferredVaultTargetPath(entry.name);\n if (!target) continue;\n mounts.push({ source, target });\n }\n return mounts;\n}\n\nfunction ensurePrivateDir(path: string): void {\n mkdirSync(path, { recursive: true, mode: PRIVATE_DIR_MODE });\n chmodSync(path, PRIVATE_DIR_MODE);\n}\n\nfunction copyVaultDir(\n sourceDir: string,\n targetDir: string,\n): {\n filesCopied: number;\n envKeysCopied: number;\n} {\n let filesCopied = 0;\n let envKeysCopied = 0;\n\n for (const entry of readdirSync(sourceDir, { withFileTypes: true })) {\n const sourcePath = join(sourceDir, entry.name);\n const targetPath = join(targetDir, entry.name);\n\n if (entry.name === \"env\" && entry.isFile()) {\n const sourceEnv = parseEnvFile(readTextFileIfExists(sourcePath) ?? \"\");\n const targetEnv = parseEnvFile(readTextFileIfExists(targetPath) ?? \"\");\n const merged = { ...targetEnv, ...sourceEnv };\n const content =\n Object.entries(merged)\n .toSorted(([left], [right]) => left.localeCompare(right))\n .map(([envKey, value]) => `${envKey}=${value}`)\n .join(\"\\n\") + \"\\n\";\n atomicWritePrivateFile(targetPath, content);\n envKeysCopied += Object.keys(sourceEnv).length;\n continue;\n }\n\n if (entry.isDirectory()) {\n ensurePrivateDir(targetPath);\n const nested = copyVaultDir(sourcePath, targetPath);\n filesCopied += nested.filesCopied;\n envKeysCopied += nested.envKeysCopied;\n continue;\n }\n\n if (!entry.isFile()) continue;\n copyFileSync(sourcePath, targetPath);\n chmodSync(targetPath, 0o600);\n filesCopied++;\n }\n\n return { filesCopied, envKeysCopied };\n}\n\nfunction normalizeVaultRelativePath(relativePath: string): string | undefined {\n const trimmed = relativePath.trim();\n if (!trimmed || isAbsolute(trimmed)) return undefined;\n\n const normalized = normalize(trimmed).split(sep).join(\"/\");\n if (!normalized || normalized === \".\" || normalized === \"..\" || normalized.startsWith(\"../\")) {\n return undefined;\n }\n return normalized;\n}\n\nfunction normalizeVaultTargetPath(targetPath?: string): string | undefined {\n if (targetPath === undefined) return undefined;\n\n const trimmed = targetPath.trim();\n if (!trimmed || !trimmed.startsWith(\"/\")) return undefined;\n\n const normalized = normalize(trimmed).split(sep).join(\"/\");\n return normalized.startsWith(\"/\") ? normalized : undefined;\n}\n\nexport function defaultVaultTargetPath(relativePath: string): string {\n const normalized = normalizeVaultRelativePath(relativePath) ?? relativePath.replace(/^\\/+/, \"\");\n return `/root/${normalized}`;\n}\n\nfunction inferredVaultTargetPath(relativePath: string): string | undefined {\n const normalized = normalizeVaultRelativePath(relativePath);\n if (!normalized) return undefined;\n\n if (normalized === \"gws.json\") {\n return \"/root/.config/gws/credentials.json\";\n }\n if (normalized === \"gcloud-adc.json\") {\n return \"/root/.config/gcloud/application_default_credentials.json\";\n }\n if (normalized === \".ssh\" || normalized.startsWith(\".ssh/\")) {\n return \"/root/.ssh\";\n }\n if (normalized === \".kube\" || normalized.startsWith(\".kube/\")) {\n return \"/root/.kube\";\n }\n if (normalized === \".config/gh\" || normalized.startsWith(\".config/gh/\")) {\n return \"/root/.config/gh\";\n }\n\n return defaultVaultTargetPath(normalized);\n}\n"]}
@@ -1,3 +1,3 @@
1
- import type { SandboxConfig } from "./sandbox/index.js";
1
+ import type { SandboxConfig } from "../sandbox/index.js";
2
2
  export declare function resolveActorVaultKey(baseConfig: SandboxConfig, userId: string, conversationId: string): string;
3
- //# sourceMappingURL=vault-routing.d.ts.map
3
+ //# sourceMappingURL=routing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../src/vault/routing.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,aAAa,EACzB,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM,GACrB,MAAM,CAcR","sourcesContent":["import { DockerContainerManager } from \"../provisioner.js\";\nimport type { SandboxConfig } from \"../sandbox/index.js\";\nexport function resolveActorVaultKey(\n baseConfig: SandboxConfig,\n userId: string,\n conversationId: string,\n): string {\n if (baseConfig.type === \"container\") {\n return `container-${baseConfig.container}`;\n }\n\n if (\n baseConfig.type === \"image\" ||\n baseConfig.type === \"cloudflare\" ||\n baseConfig.type === \"firecracker\"\n ) {\n return DockerContainerManager.sanitizeSegment(conversationId);\n }\n\n return userId;\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { DockerContainerManager } from "./provisioner.js";
1
+ import { DockerContainerManager } from "../provisioner.js";
2
2
  export function resolveActorVaultKey(baseConfig, userId, conversationId) {
3
3
  if (baseConfig.type === "container") {
4
4
  return `container-${baseConfig.container}`;
@@ -10,4 +10,4 @@ export function resolveActorVaultKey(baseConfig, userId, conversationId) {
10
10
  }
11
11
  return userId;
12
12
  }
13
- //# sourceMappingURL=vault-routing.js.map
13
+ //# sourceMappingURL=routing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing.js","sourceRoot":"","sources":["../../src/vault/routing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,MAAM,UAAU,oBAAoB,CAClC,UAAyB,EACzB,MAAc,EACd,cAAsB;IAEtB,IAAI,UAAU,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QACpC,OAAO,aAAa,UAAU,CAAC,SAAS,EAAE,CAAC;IAC7C,CAAC;IAED,IACE,UAAU,CAAC,IAAI,KAAK,OAAO;QAC3B,UAAU,CAAC,IAAI,KAAK,YAAY;QAChC,UAAU,CAAC,IAAI,KAAK,aAAa,EACjC,CAAC;QACD,OAAO,sBAAsB,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;IAChE,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import { DockerContainerManager } from \"../provisioner.js\";\nimport type { SandboxConfig } from \"../sandbox/index.js\";\nexport function resolveActorVaultKey(\n baseConfig: SandboxConfig,\n userId: string,\n conversationId: string,\n): string {\n if (baseConfig.type === \"container\") {\n return `container-${baseConfig.container}`;\n }\n\n if (\n baseConfig.type === \"image\" ||\n baseConfig.type === \"cloudflare\" ||\n baseConfig.type === \"firecracker\"\n ) {\n return DockerContainerManager.sanitizeSegment(conversationId);\n }\n\n return userId;\n}\n"]}
@@ -1,7 +1,5 @@
1
- import type { SandboxConfig } from "./sandbox/index.js";
2
- export declare function normalizeSharedVaultName(name: string): string | undefined;
3
- export declare function sharedVaultKey(name: string): string | undefined;
4
- interface ResolvedVaultMount {
1
+ import type { SandboxConfig } from "../sandbox/index.js";
2
+ export interface ResolvedVaultMount {
5
3
  source: string;
6
4
  target: string;
7
5
  }
@@ -41,33 +39,4 @@ export interface VaultManager {
41
39
  envKeysCopied: number;
42
40
  };
43
41
  }
44
- /**
45
- * Parse a KEY=VALUE env file. Supports:
46
- * - Lines starting with # are comments
47
- * - Empty lines are skipped
48
- * - Values can be quoted with single or double quotes (quotes are stripped)
49
- * - No variable expansion
50
- * - The value is everything after the first `=` to end of line (no inline comments)
51
- */
52
- export declare function parseEnvFile(content: string): Record<string, string>;
53
- export declare class FileVaultManager implements VaultManager {
54
- private readonly vaultsDir;
55
- constructor(stateDir: string);
56
- isEnabled(): boolean;
57
- hasEntry(key: string): boolean;
58
- listSharedVaults(): string[];
59
- deleteSharedVault(name: string): boolean;
60
- copySharedVaultTo(name: string, targetKey: string): {
61
- filesCopied: number;
62
- envKeysCopied: number;
63
- };
64
- resolve(userId: string): ResolvedVault | undefined;
65
- getSandboxConfig(userId: string, baseConfig: SandboxConfig): SandboxConfig;
66
- list(): ResolvedVault[];
67
- upsertEnv(key: string, env: Record<string, string>): void;
68
- upsertFile(key: string, relativePath: string, content: string, targetPath?: string): void;
69
- private buildResolved;
70
- }
71
- export declare function defaultVaultTargetPath(relativePath: string): string;
72
- export {};
73
- //# sourceMappingURL=vault.d.ts.map
42
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/vault/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,8CAA8C;AAC9C,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,2BAA2B;IAC3B,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,2BAA2B;IAC3B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,oEAAoE;IACpE,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B,4EAA4E;IAC5E,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAAC;IACnD,8DAA8D;IAC9D,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,GAAG,aAAa,CAAC;IAC3E,gDAAgD;IAChD,IAAI,IAAI,aAAa,EAAE,CAAC;IACxB,4CAA4C;IAC5C,SAAS,IAAI,OAAO,CAAC;IACrB,kFAAkF;IAClF,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IAC1D,yFAAyF;IACzF,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1F,6DAA6D;IAC7D,gBAAgB,IAAI,MAAM,EAAE,CAAC;IAC7B,+EAA+E;IAC/E,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACzC,wEAAwE;IACxE,iBAAiB,CACf,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAChB;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;CACnD","sourcesContent":["import type { SandboxConfig } from \"../sandbox/index.js\";\n\nexport interface ResolvedVaultMount {\n source: string;\n target: string;\n}\n\n/** Resolved vault ready for use at runtime */\nexport interface ResolvedVault {\n userId: string;\n displayName: string;\n /** Absolute path to vault directory */\n dir: string;\n /** Absolute mount specs */\n mounts: ResolvedVaultMount[];\n /** Parsed from env file */\n env: Record<string, string>;\n}\n\nexport interface VaultManager {\n /** Return true when a vault directory exists for this exact key. */\n hasEntry(key: string): boolean;\n /** Resolve vault for a user; returns undefined when no directory exists. */\n resolve(userId: string): ResolvedVault | undefined;\n /** Get sandbox config with credential injection for a user */\n getSandboxConfig(userId: string, baseConfig: SandboxConfig): SandboxConfig;\n /** List all vaults discovered under vaults/. */\n list(): ResolvedVault[];\n /** Check if the vaults directory exists. */\n isEnabled(): boolean;\n /** Merge environment variables into vaults/<key>/env and persist them to disk. */\n upsertEnv(key: string, env: Record<string, string>): void;\n /** Write a private file into vaults/<key>/ and ensure it is mounted into the sandbox. */\n upsertFile(key: string, relativePath: string, content: string, targetPath?: string): void;\n /** List named shared login profiles under vaults/shared/. */\n listSharedVaults(): string[];\n /** Delete a shared login profile's directory. Returns true when it existed. */\n deleteSharedVault(name: string): boolean;\n /** Copy a shared login profile's files into another vault directory. */\n copySharedVaultTo(\n name: string,\n targetKey: string,\n ): { filesCopied: number; envKeysCopied: number };\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/vault/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { SandboxConfig } from \"../sandbox/index.js\";\n\nexport interface ResolvedVaultMount {\n source: string;\n target: string;\n}\n\n/** Resolved vault ready for use at runtime */\nexport interface ResolvedVault {\n userId: string;\n displayName: string;\n /** Absolute path to vault directory */\n dir: string;\n /** Absolute mount specs */\n mounts: ResolvedVaultMount[];\n /** Parsed from env file */\n env: Record<string, string>;\n}\n\nexport interface VaultManager {\n /** Return true when a vault directory exists for this exact key. */\n hasEntry(key: string): boolean;\n /** Resolve vault for a user; returns undefined when no directory exists. */\n resolve(userId: string): ResolvedVault | undefined;\n /** Get sandbox config with credential injection for a user */\n getSandboxConfig(userId: string, baseConfig: SandboxConfig): SandboxConfig;\n /** List all vaults discovered under vaults/. */\n list(): ResolvedVault[];\n /** Check if the vaults directory exists. */\n isEnabled(): boolean;\n /** Merge environment variables into vaults/<key>/env and persist them to disk. */\n upsertEnv(key: string, env: Record<string, string>): void;\n /** Write a private file into vaults/<key>/ and ensure it is mounted into the sandbox. */\n upsertFile(key: string, relativePath: string, content: string, targetPath?: string): void;\n /** List named shared login profiles under vaults/shared/. */\n listSharedVaults(): string[];\n /** Delete a shared login profile's directory. Returns true when it existed. */\n deleteSharedVault(name: string): boolean;\n /** Copy a shared login profile's files into another vault directory. */\n copySharedVaultTo(\n name: string,\n targetKey: string,\n ): { filesCopied: number; envKeysCopied: number };\n}\n"]}
@@ -0,0 +1,5 @@
1
+ import type { IncomingMessage, ServerResponse } from "http";
2
+ export type { AdminRuntimeBridge, AdminServices } from "./types.js";
3
+ import type { AdminServices } from "./types.js";
4
+ export declare function handleAdminRequest(req: IncomingMessage, res: ServerResponse, url: URL, services: AdminServices): boolean;
5
+ //# sourceMappingURL=portal.d.ts.map