@geminixiang/mikan 1.0.0-beta.44 → 1.0.0-beta.46

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 (422) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +12 -19
  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 +3 -1
  7. package/dist/adapters/discord/bot.d.ts.map +1 -1
  8. package/dist/adapters/discord/bot.js +143 -141
  9. package/dist/adapters/discord/bot.js.map +1 -1
  10. package/dist/adapters/discord/context.d.ts +2 -8
  11. package/dist/adapters/discord/context.d.ts.map +1 -1
  12. package/dist/adapters/discord/context.js +1 -1
  13. package/dist/adapters/discord/context.js.map +1 -1
  14. package/dist/adapters/discord/format.d.ts.map +1 -1
  15. package/dist/adapters/discord/format.js +2 -4
  16. package/dist/adapters/discord/format.js.map +1 -1
  17. package/dist/adapters/github/bot.d.ts.map +1 -1
  18. package/dist/adapters/github/bot.js +1 -4
  19. package/dist/adapters/github/bot.js.map +1 -1
  20. package/dist/adapters/github/context.d.ts +2 -9
  21. package/dist/adapters/github/context.d.ts.map +1 -1
  22. package/dist/adapters/github/context.js.map +1 -1
  23. package/dist/adapters/github/github-ops.d.ts +4 -17
  24. package/dist/adapters/github/github-ops.d.ts.map +1 -1
  25. package/dist/adapters/github/github-ops.js +17 -86
  26. package/dist/adapters/github/github-ops.js.map +1 -1
  27. package/dist/adapters/github/tool-pack.d.ts.map +1 -1
  28. package/dist/adapters/github/tool-pack.js +0 -1
  29. package/dist/adapters/github/tool-pack.js.map +1 -1
  30. package/dist/adapters/github/tools/checks.d.ts +0 -1
  31. package/dist/adapters/github/tools/checks.d.ts.map +1 -1
  32. package/dist/adapters/github/tools/checks.js +3 -22
  33. package/dist/adapters/github/tools/checks.js.map +1 -1
  34. package/dist/adapters/github/types.d.ts +0 -33
  35. package/dist/adapters/github/types.d.ts.map +1 -1
  36. package/dist/adapters/github/types.js.map +1 -1
  37. package/dist/adapters/progressive-renderer.d.ts.map +1 -1
  38. package/dist/adapters/progressive-renderer.js +311 -318
  39. package/dist/adapters/progressive-renderer.js.map +1 -1
  40. package/dist/adapters/slack/blocks.d.ts.map +1 -1
  41. package/dist/adapters/slack/blocks.js +1 -4
  42. package/dist/adapters/slack/blocks.js.map +1 -1
  43. package/dist/adapters/slack/bot.d.ts +12 -0
  44. package/dist/adapters/slack/bot.d.ts.map +1 -1
  45. package/dist/adapters/slack/bot.js +158 -178
  46. package/dist/adapters/slack/bot.js.map +1 -1
  47. package/dist/adapters/slack/context.d.ts +2 -8
  48. package/dist/adapters/slack/context.d.ts.map +1 -1
  49. package/dist/adapters/slack/context.js +1 -1
  50. package/dist/adapters/slack/context.js.map +1 -1
  51. package/dist/adapters/slack/response-lifecycle.d.ts.map +1 -1
  52. package/dist/adapters/slack/response-lifecycle.js +135 -123
  53. package/dist/adapters/slack/response-lifecycle.js.map +1 -1
  54. package/dist/adapters/slack/stream-limits.d.ts +1 -1
  55. package/dist/adapters/slack/stream-limits.js +1 -1
  56. package/dist/adapters/slack/stream-limits.js.map +1 -1
  57. package/dist/adapters/slack/types.d.ts +4 -0
  58. package/dist/adapters/slack/types.d.ts.map +1 -1
  59. package/dist/adapters/slack/types.js.map +1 -1
  60. package/dist/adapters/telegram/context.d.ts +2 -8
  61. package/dist/adapters/telegram/context.d.ts.map +1 -1
  62. package/dist/adapters/telegram/context.js +1 -2
  63. package/dist/adapters/telegram/context.js.map +1 -1
  64. package/dist/adapters/types.d.ts +11 -5
  65. package/dist/adapters/types.d.ts.map +1 -1
  66. package/dist/adapters/types.js.map +1 -1
  67. package/dist/agent/catalog.d.ts +6 -18
  68. package/dist/agent/catalog.d.ts.map +1 -1
  69. package/dist/agent/catalog.js +19 -155
  70. package/dist/agent/catalog.js.map +1 -1
  71. package/dist/agent/execution.d.ts +0 -7
  72. package/dist/agent/execution.d.ts.map +1 -1
  73. package/dist/agent/execution.js +23 -21
  74. package/dist/agent/execution.js.map +1 -1
  75. package/dist/agent/presenter.d.ts +7 -9
  76. package/dist/agent/presenter.d.ts.map +1 -1
  77. package/dist/agent/presenter.js +355 -357
  78. package/dist/agent/presenter.js.map +1 -1
  79. package/dist/agent/prompt.d.ts +5 -12
  80. package/dist/agent/prompt.d.ts.map +1 -1
  81. package/dist/agent/prompt.js +56 -81
  82. package/dist/agent/prompt.js.map +1 -1
  83. package/dist/agent/runner.d.ts +0 -7
  84. package/dist/agent/runner.d.ts.map +1 -1
  85. package/dist/agent/runner.js +255 -308
  86. package/dist/agent/runner.js.map +1 -1
  87. package/dist/agent/types.d.ts +21 -17
  88. package/dist/agent/types.d.ts.map +1 -1
  89. package/dist/agent/types.js +0 -1
  90. package/dist/agent/types.js.map +1 -1
  91. package/dist/cli/boot.d.ts.map +1 -1
  92. package/dist/cli/boot.js +7 -10
  93. package/dist/cli/boot.js.map +1 -1
  94. package/dist/cli/onboard.d.ts +10 -0
  95. package/dist/cli/onboard.d.ts.map +1 -0
  96. package/dist/cli/onboard.js +237 -0
  97. package/dist/cli/onboard.js.map +1 -0
  98. package/dist/cli/types.d.ts +8 -3
  99. package/dist/cli/types.d.ts.map +1 -1
  100. package/dist/cli/types.js.map +1 -1
  101. package/dist/commands/auto-reply.d.ts.map +1 -1
  102. package/dist/commands/auto-reply.js +5 -12
  103. package/dist/commands/auto-reply.js.map +1 -1
  104. package/dist/commands/manifest.d.ts.map +1 -1
  105. package/dist/commands/manifest.js +9 -16
  106. package/dist/commands/manifest.js.map +1 -1
  107. package/dist/commands/new.d.ts.map +1 -1
  108. package/dist/commands/new.js +15 -10
  109. package/dist/commands/new.js.map +1 -1
  110. package/dist/commands/registry.d.ts.map +1 -1
  111. package/dist/commands/registry.js +0 -2
  112. package/dist/commands/registry.js.map +1 -1
  113. package/dist/commands/sandbox.d.ts.map +1 -1
  114. package/dist/commands/sandbox.js +89 -70
  115. package/dist/commands/sandbox.js.map +1 -1
  116. package/dist/commands/session-view.js +9 -2
  117. package/dist/commands/session-view.js.map +1 -1
  118. package/dist/commands/types.d.ts +4 -3
  119. package/dist/commands/types.d.ts.map +1 -1
  120. package/dist/commands/types.js.map +1 -1
  121. package/dist/config.d.ts +13 -17
  122. package/dist/config.d.ts.map +1 -1
  123. package/dist/config.js +39 -37
  124. package/dist/config.js.map +1 -1
  125. package/dist/dream/index.d.ts +20 -0
  126. package/dist/dream/index.d.ts.map +1 -0
  127. package/dist/dream/index.js +253 -0
  128. package/dist/dream/index.js.map +1 -0
  129. package/dist/dream/types.d.ts +30 -0
  130. package/dist/dream/types.d.ts.map +1 -0
  131. package/dist/dream/types.js.map +1 -0
  132. package/dist/env-manifest.d.ts.map +1 -1
  133. package/dist/env-manifest.js +2 -34
  134. package/dist/env-manifest.js.map +1 -1
  135. package/dist/execution-resolver.d.ts +9 -2
  136. package/dist/execution-resolver.d.ts.map +1 -1
  137. package/dist/execution-resolver.js +26 -27
  138. package/dist/execution-resolver.js.map +1 -1
  139. package/dist/harness/event-format.d.ts +1 -2
  140. package/dist/harness/event-format.d.ts.map +1 -1
  141. package/dist/harness/event-format.js +9 -15
  142. package/dist/harness/event-format.js.map +1 -1
  143. package/dist/harness/index.d.ts +1 -7
  144. package/dist/harness/index.d.ts.map +1 -1
  145. package/dist/harness/index.js +0 -4
  146. package/dist/harness/index.js.map +1 -1
  147. package/dist/harness/models.d.ts.map +1 -1
  148. package/dist/harness/models.js +15 -35
  149. package/dist/harness/models.js.map +1 -1
  150. package/dist/harness/runner.d.ts +7 -16
  151. package/dist/harness/runner.d.ts.map +1 -1
  152. package/dist/harness/runner.js +13 -131
  153. package/dist/harness/runner.js.map +1 -1
  154. package/dist/harness/session-store.d.ts +1 -1
  155. package/dist/harness/session-store.d.ts.map +1 -1
  156. package/dist/harness/session-store.js +1 -1
  157. package/dist/harness/session-store.js.map +1 -1
  158. package/dist/harness/subagent-runner.d.ts +2 -2
  159. package/dist/harness/subagent-runner.d.ts.map +1 -1
  160. package/dist/harness/subagent-runner.js +157 -162
  161. package/dist/harness/subagent-runner.js.map +1 -1
  162. package/dist/harness/types.d.ts +1 -13
  163. package/dist/harness/types.d.ts.map +1 -1
  164. package/dist/harness/types.js.map +1 -1
  165. package/dist/index.d.ts +3 -9
  166. package/dist/index.d.ts.map +1 -1
  167. package/dist/index.js +1 -5
  168. package/dist/index.js.map +1 -1
  169. package/dist/main.js +31 -212
  170. package/dist/main.js.map +1 -1
  171. package/dist/mcp/catalog.d.ts +5 -0
  172. package/dist/mcp/catalog.d.ts.map +1 -0
  173. package/dist/mcp/catalog.js +135 -0
  174. package/dist/mcp/catalog.js.map +1 -0
  175. package/dist/mcp/loader.d.ts.map +1 -1
  176. package/dist/mcp/loader.js +3 -6
  177. package/dist/mcp/loader.js.map +1 -1
  178. package/dist/mcp/types.d.ts +22 -0
  179. package/dist/mcp/types.d.ts.map +1 -1
  180. package/dist/mcp/types.js.map +1 -1
  181. package/dist/office/index.d.ts +136 -8
  182. package/dist/office/index.d.ts.map +1 -1
  183. package/dist/office/index.js +1050 -9
  184. package/dist/office/index.js.map +1 -1
  185. package/dist/office/types.d.ts +19 -1
  186. package/dist/office/types.d.ts.map +1 -1
  187. package/dist/office/types.js.map +1 -1
  188. package/dist/packages/index.d.ts +168 -5
  189. package/dist/packages/index.d.ts.map +1 -1
  190. package/dist/packages/index.js +749 -5
  191. package/dist/packages/index.js.map +1 -1
  192. package/dist/packages/types.d.ts +1 -5
  193. package/dist/packages/types.d.ts.map +1 -1
  194. package/dist/packages/types.js.map +1 -1
  195. package/dist/provisioner.d.ts +2 -9
  196. package/dist/provisioner.d.ts.map +1 -1
  197. package/dist/provisioner.js +3 -12
  198. package/dist/provisioner.js.map +1 -1
  199. package/dist/runtime/conversation-runtime.d.ts.map +1 -1
  200. package/dist/runtime/conversation-runtime.js +117 -380
  201. package/dist/runtime/conversation-runtime.js.map +1 -1
  202. package/dist/runtime/session-lifecycle.d.ts +32 -18
  203. package/dist/runtime/session-lifecycle.d.ts.map +1 -1
  204. package/dist/runtime/session-lifecycle.js +159 -46
  205. package/dist/runtime/session-lifecycle.js.map +1 -1
  206. package/dist/runtime/types.d.ts +4 -26
  207. package/dist/runtime/types.d.ts.map +1 -1
  208. package/dist/runtime/types.js.map +1 -1
  209. package/dist/sandbox/cloudflare.d.ts.map +1 -1
  210. package/dist/sandbox/cloudflare.js +2 -3
  211. package/dist/sandbox/cloudflare.js.map +1 -1
  212. package/dist/sandbox/container.d.ts +0 -1
  213. package/dist/sandbox/container.d.ts.map +1 -1
  214. package/dist/sandbox/container.js +2 -3
  215. package/dist/sandbox/container.js.map +1 -1
  216. package/dist/sandbox/host.d.ts.map +1 -1
  217. package/dist/sandbox/host.js +4 -2
  218. package/dist/sandbox/host.js.map +1 -1
  219. package/dist/sandbox/identity.d.ts +10 -19
  220. package/dist/sandbox/identity.d.ts.map +1 -1
  221. package/dist/sandbox/identity.js +8 -8
  222. package/dist/sandbox/identity.js.map +1 -1
  223. package/dist/sandbox/index.d.ts +7 -10
  224. package/dist/sandbox/index.d.ts.map +1 -1
  225. package/dist/sandbox/index.js +45 -16
  226. package/dist/sandbox/index.js.map +1 -1
  227. package/dist/sandbox/types.d.ts +13 -45
  228. package/dist/sandbox/types.d.ts.map +1 -1
  229. package/dist/sandbox/types.js.map +1 -1
  230. package/dist/sandbox/utils.d.ts +5 -0
  231. package/dist/sandbox/utils.d.ts.map +1 -1
  232. package/dist/sandbox/utils.js +10 -0
  233. package/dist/sandbox/utils.js.map +1 -1
  234. package/dist/sessions/chat-history-sync.d.ts +1 -3
  235. package/dist/sessions/chat-history-sync.d.ts.map +1 -1
  236. package/dist/sessions/chat-history-sync.js +58 -11
  237. package/dist/sessions/chat-history-sync.js.map +1 -1
  238. package/dist/sessions/migrate-v3.d.ts +2 -5
  239. package/dist/sessions/migrate-v3.d.ts.map +1 -1
  240. package/dist/sessions/migrate-v3.js +34 -4
  241. package/dist/sessions/migrate-v3.js.map +1 -1
  242. package/dist/sessions/store.d.ts +5 -6
  243. package/dist/sessions/store.d.ts.map +1 -1
  244. package/dist/sessions/store.js +62 -2
  245. package/dist/sessions/store.js.map +1 -1
  246. package/dist/sessions/types.d.ts +9 -0
  247. package/dist/sessions/types.d.ts.map +1 -1
  248. package/dist/sessions/types.js.map +1 -1
  249. package/dist/tools/bash.d.ts.map +1 -1
  250. package/dist/tools/bash.js +2 -10
  251. package/dist/tools/bash.js.map +1 -1
  252. package/dist/tools/read.js +2 -2
  253. package/dist/tools/read.js.map +1 -1
  254. package/dist/tools/sandbox.d.ts.map +1 -1
  255. package/dist/tools/sandbox.js +2 -3
  256. package/dist/tools/sandbox.js.map +1 -1
  257. package/dist/tools/subagent.d.ts +1 -1
  258. package/dist/tools/subagent.js.map +1 -1
  259. package/dist/types.d.ts +38 -127
  260. package/dist/types.d.ts.map +1 -1
  261. package/dist/types.js.map +1 -1
  262. package/dist/vault/index.d.ts +9 -2
  263. package/dist/vault/index.d.ts.map +1 -1
  264. package/dist/vault/index.js +29 -5
  265. package/dist/vault/index.js.map +1 -1
  266. package/dist/web/admin/portal.d.ts +12 -1
  267. package/dist/web/admin/portal.d.ts.map +1 -1
  268. package/dist/web/admin/portal.js +437 -422
  269. package/dist/web/admin/portal.js.map +1 -1
  270. package/dist/web/admin/types.d.ts +2 -2
  271. package/dist/web/admin/types.d.ts.map +1 -1
  272. package/dist/web/admin/types.js.map +1 -1
  273. package/dist/web/login/portal.d.ts +7 -1
  274. package/dist/web/login/portal.d.ts.map +1 -1
  275. package/dist/web/login/portal.js +143 -78
  276. package/dist/web/login/portal.js.map +1 -1
  277. package/dist/web/portal-shell.d.ts +1 -0
  278. package/dist/web/portal-shell.d.ts.map +1 -1
  279. package/dist/web/portal-shell.js +12 -1
  280. package/dist/web/portal-shell.js.map +1 -1
  281. package/dist/web/server.d.ts +3 -3
  282. package/dist/web/server.d.ts.map +1 -1
  283. package/dist/web/server.js.map +1 -1
  284. package/dist/web/session-view/portal.d.ts +8 -1
  285. package/dist/web/session-view/portal.d.ts.map +1 -1
  286. package/dist/web/session-view/portal.js +609 -132
  287. package/dist/web/session-view/portal.js.map +1 -1
  288. package/dist/web/session-view/types.d.ts +8 -0
  289. package/dist/web/session-view/types.d.ts.map +1 -1
  290. package/dist/web/session-view/types.js.map +1 -1
  291. package/dist/workspace-projection/index.d.ts +14 -2
  292. package/dist/workspace-projection/index.d.ts.map +1 -1
  293. package/dist/workspace-projection/index.js +102 -14
  294. package/dist/workspace-projection/index.js.map +1 -1
  295. package/dist/workspace-projection/types.d.ts +14 -1
  296. package/dist/workspace-projection/types.d.ts.map +1 -1
  297. package/dist/workspace-projection/types.js.map +1 -1
  298. package/package.json +3 -5
  299. package/dist/adapters/github/cloudbuild.d.ts +0 -19
  300. package/dist/adapters/github/cloudbuild.d.ts.map +0 -1
  301. package/dist/adapters/github/cloudbuild.js +0 -71
  302. package/dist/adapters/github/cloudbuild.js.map +0 -1
  303. package/dist/adapters/github/gcp-auth.d.ts +0 -28
  304. package/dist/adapters/github/gcp-auth.d.ts.map +0 -1
  305. package/dist/adapters/github/gcp-auth.js +0 -196
  306. package/dist/adapters/github/gcp-auth.js.map +0 -1
  307. package/dist/agent/index.d.ts +0 -9
  308. package/dist/agent/index.d.ts.map +0 -1
  309. package/dist/agent/index.js +0 -8
  310. package/dist/agent/index.js.map +0 -1
  311. package/dist/cli/ext-dev.d.ts +0 -2
  312. package/dist/cli/ext-dev.d.ts.map +0 -1
  313. package/dist/cli/ext-dev.js +0 -188
  314. package/dist/cli/ext-dev.js.map +0 -1
  315. package/dist/cli/ext.d.ts +0 -2
  316. package/dist/cli/ext.d.ts.map +0 -1
  317. package/dist/cli/ext.js +0 -324
  318. package/dist/cli/ext.js.map +0 -1
  319. package/dist/commands/extensions.d.ts +0 -26
  320. package/dist/commands/extensions.d.ts.map +0 -1
  321. package/dist/commands/extensions.js +0 -103
  322. package/dist/commands/extensions.js.map +0 -1
  323. package/dist/extension-schedules.d.ts +0 -31
  324. package/dist/extension-schedules.d.ts.map +0 -1
  325. package/dist/extension-schedules.js +0 -229
  326. package/dist/extension-schedules.js.map +0 -1
  327. package/dist/harness/auth.d.ts +0 -17
  328. package/dist/harness/auth.d.ts.map +0 -1
  329. package/dist/harness/auth.js +0 -92
  330. package/dist/harness/auth.js.map +0 -1
  331. package/dist/harness/extensions/loader.d.ts +0 -40
  332. package/dist/harness/extensions/loader.d.ts.map +0 -1
  333. package/dist/harness/extensions/loader.js +0 -723
  334. package/dist/harness/extensions/loader.js.map +0 -1
  335. package/dist/harness/extensions/registry.d.ts +0 -155
  336. package/dist/harness/extensions/registry.d.ts.map +0 -1
  337. package/dist/harness/extensions/registry.js +0 -420
  338. package/dist/harness/extensions/registry.js.map +0 -1
  339. package/dist/harness/extensions/types.d.ts +0 -665
  340. package/dist/harness/extensions/types.d.ts.map +0 -1
  341. package/dist/harness/extensions/types.js.map +0 -1
  342. package/dist/office/address.d.ts +0 -31
  343. package/dist/office/address.d.ts.map +0 -1
  344. package/dist/office/address.js +0 -113
  345. package/dist/office/address.js.map +0 -1
  346. package/dist/office/layout.d.ts +0 -27
  347. package/dist/office/layout.d.ts.map +0 -1
  348. package/dist/office/layout.js +0 -97
  349. package/dist/office/layout.js.map +0 -1
  350. package/dist/office/migration.d.ts +0 -44
  351. package/dist/office/migration.d.ts.map +0 -1
  352. package/dist/office/migration.js +0 -255
  353. package/dist/office/migration.js.map +0 -1
  354. package/dist/office/registry.d.ts +0 -75
  355. package/dist/office/registry.d.ts.map +0 -1
  356. package/dist/office/registry.js +0 -646
  357. package/dist/office/registry.js.map +0 -1
  358. package/dist/packages/admin.d.ts +0 -17
  359. package/dist/packages/admin.d.ts.map +0 -1
  360. package/dist/packages/admin.js +0 -98
  361. package/dist/packages/admin.js.map +0 -1
  362. package/dist/packages/inspect.d.ts +0 -11
  363. package/dist/packages/inspect.d.ts.map +0 -1
  364. package/dist/packages/inspect.js +0 -98
  365. package/dist/packages/inspect.js.map +0 -1
  366. package/dist/packages/materialize.d.ts +0 -40
  367. package/dist/packages/materialize.d.ts.map +0 -1
  368. package/dist/packages/materialize.js +0 -297
  369. package/dist/packages/materialize.js.map +0 -1
  370. package/dist/packages/resolve.d.ts +0 -25
  371. package/dist/packages/resolve.d.ts.map +0 -1
  372. package/dist/packages/resolve.js +0 -208
  373. package/dist/packages/resolve.js.map +0 -1
  374. package/dist/packages/source.d.ts +0 -39
  375. package/dist/packages/source.d.ts.map +0 -1
  376. package/dist/packages/source.js +0 -189
  377. package/dist/packages/source.js.map +0 -1
  378. package/dist/sandbox/errors.d.ts +0 -6
  379. package/dist/sandbox/errors.d.ts.map +0 -1
  380. package/dist/sandbox/errors.js +0 -11
  381. package/dist/sandbox/errors.js.map +0 -1
  382. package/dist/sandbox/firecracker.d.ts +0 -18
  383. package/dist/sandbox/firecracker.d.ts.map +0 -1
  384. package/dist/sandbox/firecracker.js +0 -223
  385. package/dist/sandbox/firecracker.js.map +0 -1
  386. package/dist/sandbox/gondolin.d.ts +0 -57
  387. package/dist/sandbox/gondolin.d.ts.map +0 -1
  388. package/dist/sandbox/gondolin.js +0 -764
  389. package/dist/sandbox/gondolin.js.map +0 -1
  390. package/dist/sandbox/image.d.ts +0 -3
  391. package/dist/sandbox/image.d.ts.map +0 -1
  392. package/dist/sandbox/image.js +0 -29
  393. package/dist/sandbox/image.js.map +0 -1
  394. package/dist/sessions/conversation-log.d.ts +0 -9
  395. package/dist/sessions/conversation-log.d.ts.map +0 -1
  396. package/dist/sessions/conversation-log.js +0 -50
  397. package/dist/sessions/conversation-log.js.map +0 -1
  398. package/dist/sessions/rotation.d.ts +0 -2
  399. package/dist/sessions/rotation.d.ts.map +0 -1
  400. package/dist/sessions/rotation.js +0 -41
  401. package/dist/sessions/rotation.js.map +0 -1
  402. package/dist/vault/disabled.d.ts +0 -9
  403. package/dist/vault/disabled.d.ts.map +0 -1
  404. package/dist/vault/disabled.js +0 -25
  405. package/dist/vault/disabled.js.map +0 -1
  406. package/dist/web/admin/store.d.ts +0 -13
  407. package/dist/web/admin/store.d.ts.map +0 -1
  408. package/dist/web/admin/store.js +0 -14
  409. package/dist/web/admin/store.js.map +0 -1
  410. package/dist/web/login/store.d.ts +0 -8
  411. package/dist/web/login/store.d.ts.map +0 -1
  412. package/dist/web/login/store.js +0 -15
  413. package/dist/web/login/store.js.map +0 -1
  414. package/dist/web/session-view/service.d.ts +0 -6
  415. package/dist/web/session-view/service.d.ts.map +0 -1
  416. package/dist/web/session-view/service.js +0 -517
  417. package/dist/web/session-view/service.js.map +0 -1
  418. package/dist/web/session-view/store.d.ts +0 -8
  419. package/dist/web/session-view/store.d.ts.map +0 -1
  420. package/dist/web/session-view/store.js +0 -15
  421. package/dist/web/session-view/store.js.map +0 -1
  422. /package/dist/{harness/extensions → dream}/types.js +0 -0
@@ -1,723 +0,0 @@
1
- /**
2
- * Extension discovery and activation.
3
- *
4
- * Extension modules execute inside the mikan host process with its full
5
- * privileges (platform tokens, vault, host filesystem). They must therefore
6
- * only ever load from host-controlled directories: installing an extension
7
- * is an administrator action. In particular, extension directories must not
8
- * live under paths mounted into sandbox containers (workspace and
9
- * conversation dirs in image mode), or code written from inside the sandbox
10
- * would be imported into the host process — a sandbox escape.
11
- * {@link defaultExtensionDirs} returns the canonical host-only locations
12
- * under mikan's state dir.
13
- *
14
- * Directories are scanned in order; all discovered extensions activate.
15
- * Accepted layouts (entrypoint may be .mjs/.js/.ts/.mts — loaded via jiti):
16
- *
17
- * - `extensions/<name>.<ext>` (bare file)
18
- * - `extensions/<name>/index.<ext>` (directory + index)
19
- * - `extensions/<name>/package.json` (mikan.extensions entrypoint;
20
- * may carry npm dependencies in node_modules)
21
- *
22
- * Modules are imported with a fresh jiti instance (no cache) so edited
23
- * extensions are picked up when a new harness instance is created.
24
- */
25
- import { existsSync, mkdirSync, readdirSync, readFileSync, statSync } from "node:fs";
26
- import { homedir } from "node:os";
27
- import { basename, join } from "node:path";
28
- import { createJiti } from "jiti";
29
- import * as log from "../../log.js";
30
- import { buildEventPayload } from "../event-format.js";
31
- import { loadSkillsFromDir } from "../skills.js";
32
- import { ExtensionRegistry, namespaceActionIds } from "./registry.js";
33
- import { officeStateDir } from "../../office/index.js";
34
- const EXTENSION_FILE_PATTERN = /\.(mjs|js|ts|mts)$/;
35
- const INDEX_FILE_PATTERN = /^index\.(mjs|js|ts|mts)$/;
36
- const INDEX_CANDIDATES = ["index.mjs", "index.js", "index.ts", "index.mts"];
37
- /**
38
- * Import an extension entrypoint through jiti so it can be TypeScript and can
39
- * use node_modules dependencies, transparently compiling on the fly. A fresh
40
- * jiti instance with caching disabled is used per load so edited extensions
41
- * are picked up when a new harness instance is created for a conversation.
42
- */
43
- async function importExtensionModule(entrypoint) {
44
- const jiti = createJiti(import.meta.url, { moduleCache: false, fsCache: false });
45
- return jiti.import(entrypoint);
46
- }
47
- /**
48
- * Canonical host-only extension code directories for a conversation, in load
49
- * order: `<stateDir>/global/extensions` (all conversations) then
50
- * `<stateDir>/conversations/<office key>/extensions` (that conversation
51
- * only). `global` and `conversations` are the two sibling scopes; see
52
- * `LAYOUT.md`.
53
- */
54
- export function defaultExtensionDirs(address, stateDir = join(homedir(), ".mikan")) {
55
- return [
56
- join(stateDir, "global", "extensions"),
57
- join(officeStateDir(stateDir, address), "extensions"),
58
- ];
59
- }
60
- /**
61
- * List installed extensions without importing or activating them — safe for
62
- * inventory surfaces (commands, portal). Activation side effects (schedule
63
- * upserts, tool registration) only happen in {@link loadExtensions}.
64
- */
65
- export function listInstalledExtensions(dirs) {
66
- const infos = [];
67
- for (const dir of dirs) {
68
- for (const { entrypoint, rootDir } of discoverExtensionEntrypoints(dir)) {
69
- const slug = extensionSlug(rootDir);
70
- const manifest = readManifest(rootDir);
71
- infos.push({
72
- name: manifest.name ?? slug,
73
- slug,
74
- path: entrypoint,
75
- dir,
76
- version: manifest.version,
77
- description: manifest.description,
78
- skillNames: loadExtensionSkills(rootDir, slug).map((skill) => skill.name),
79
- secrets: manifest.secrets ?? [],
80
- });
81
- }
82
- }
83
- return infos;
84
- }
85
- function discoverExtensionEntrypoints(dir) {
86
- if (!existsSync(dir))
87
- return [];
88
- const found = [];
89
- for (const name of readdirSync(dir).toSorted()) {
90
- if (name.startsWith("."))
91
- continue;
92
- if (INDEX_FILE_PATTERN.test(name)) {
93
- // An index file at the scan root means the extension's contents were
94
- // copied into the scope directory itself; the slug would degenerate to
95
- // the scope name (e.g. the conversation id), mis-keying its data dir,
96
- // secrets, and schedules. Require a named form instead.
97
- log.logWarning(`Ignoring extension index file at scope root: ${join(dir, name)}`, "install into a named subdirectory (e.g. extensions/<scope>/my-ext/index.mjs)");
98
- continue;
99
- }
100
- const fullPath = join(dir, name);
101
- let stats;
102
- try {
103
- stats = statSync(fullPath);
104
- }
105
- catch {
106
- continue;
107
- }
108
- if (stats.isFile() && EXTENSION_FILE_PATTERN.test(name)) {
109
- // Bare-file form: the file is both entrypoint and (its own) root.
110
- found.push({ entrypoint: fullPath, rootDir: fullPath, slug: extensionSlug(fullPath) });
111
- continue;
112
- }
113
- if (stats.isDirectory()) {
114
- const entrypoint = resolveDirectoryEntrypoint(fullPath);
115
- if (entrypoint) {
116
- found.push({ entrypoint, rootDir: fullPath, slug: extensionSlug(fullPath) });
117
- }
118
- }
119
- }
120
- return found;
121
- }
122
- /**
123
- * Resolve a directory-form extension's entrypoint. A `package.json` with a
124
- * `mikan.extensions` array (first entry, relative to the dir) wins — this is
125
- * how an extension declares a TypeScript entry and pulls in npm dependencies.
126
- * Otherwise fall back to an `index.{mjs,js,ts,mts}` file. Returns undefined
127
- * when neither is present.
128
- */
129
- function resolveDirectoryEntrypoint(dir) {
130
- const declared = readMikanManifestEntrypoints(dir)[0];
131
- if (declared) {
132
- const resolved = join(dir, declared);
133
- if (existsSync(resolved))
134
- return resolved;
135
- log.logWarning(`Extension package.json declares a missing entrypoint: ${resolved}`, "falling back to an index file");
136
- }
137
- for (const candidate of INDEX_CANDIDATES) {
138
- const indexPath = join(dir, candidate);
139
- if (existsSync(indexPath))
140
- return indexPath;
141
- }
142
- return undefined;
143
- }
144
- const SECRET_KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
145
- /** Shape one `mikan.secrets` entry defensively; undefined when unusable. */
146
- function readSecretDeclaration(entry) {
147
- if (!entry || typeof entry !== "object")
148
- return undefined;
149
- const record = entry;
150
- if (typeof record.key !== "string" || !SECRET_KEY_PATTERN.test(record.key))
151
- return undefined;
152
- return {
153
- key: record.key,
154
- ...(typeof record.description === "string" ? { description: record.description } : {}),
155
- ...(typeof record.required === "boolean" ? { required: record.required } : {}),
156
- };
157
- }
158
- /** Read and shape a directory's package.json; undefined when absent/malformed. */
159
- function readPackageJson(dir) {
160
- const packageJsonPath = join(dir, "package.json");
161
- if (!existsSync(packageJsonPath))
162
- return undefined;
163
- try {
164
- const parsed = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
165
- if (!parsed || typeof parsed !== "object")
166
- return undefined;
167
- const record = parsed;
168
- const mikanRaw = record.mikan;
169
- return {
170
- name: typeof record.name === "string" ? record.name : undefined,
171
- version: typeof record.version === "string" ? record.version : undefined,
172
- description: typeof record.description === "string" ? record.description : undefined,
173
- mikan: {
174
- extensions: Array.isArray(mikanRaw?.extensions)
175
- ? mikanRaw.extensions.filter((entry) => typeof entry === "string")
176
- : undefined,
177
- displayName: typeof mikanRaw?.displayName === "string" ? mikanRaw.displayName : undefined,
178
- secrets: Array.isArray(mikanRaw?.secrets)
179
- ? mikanRaw.secrets.flatMap((entry) => readSecretDeclaration(entry) ?? [])
180
- : undefined,
181
- },
182
- };
183
- }
184
- catch (err) {
185
- log.logWarning(`Ignoring malformed package.json: ${packageJsonPath}`, String(err));
186
- return undefined;
187
- }
188
- }
189
- /** Read the `mikan.extensions` entrypoint list from a directory's package.json. */
190
- function readMikanManifestEntrypoints(dir) {
191
- return readPackageJson(dir)?.mikan?.extensions ?? [];
192
- }
193
- /** The one filesystem-safe segment sanitizer for extension identity and schedule names. */
194
- function sanitizeSegment(value) {
195
- return value
196
- .toLowerCase()
197
- .replace(/[^a-z0-9_-]+/g, "-")
198
- .replace(/^-+|-+$/g, "")
199
- .slice(0, 64);
200
- }
201
- function sanitizeSlug(base) {
202
- return sanitizeSegment(base) || "extension";
203
- }
204
- /**
205
- * Filesystem-safe identifier for an extension, derived from its root (the
206
- * install directory, or the file path for a bare-file extension). The slug
207
- * keys the extension's data dir, secrets vault, and schedule ownership —
208
- * installing the same extension globally and per-conversation shares one
209
- * slug and therefore one shared data dir. This is the only slug derivation:
210
- * a second one keyed off a different input (e.g. the entrypoint, which for
211
- * package.json-form extensions can live under dist/) would silently split an
212
- * extension's identity.
213
- */
214
- export function extensionSlug(rootDir) {
215
- return EXTENSION_FILE_PATTERN.test(basename(rootDir))
216
- ? sanitizeSlug(basename(rootDir).replace(EXTENSION_FILE_PATTERN, ""))
217
- : sanitizeSlug(basename(rootDir));
218
- }
219
- /** Sanitize an extension-chosen schedule name into a filename segment. */
220
- function scheduleNameSegment(name) {
221
- const segment = sanitizeSegment(name);
222
- if (!segment)
223
- throw new Error(`Invalid schedule name: ${JSON.stringify(name)}`);
224
- return segment;
225
- }
226
- /**
227
- * Read display metadata (name/version/description) for a directory-form
228
- * extension. `package.json` is the primary source — its standard `name`,
229
- * `version`, `description`, plus an optional `mikan.displayName` that
230
- * overrides the npm name for the user-facing label (npm names are
231
- * lowercase/scoped; display names can be arbitrary). A `manifest.json` is a
232
- * fallback for extensions that ship no package.json.
233
- */
234
- function readManifest(rootDir) {
235
- // Bare-file extensions (rootDir is a *.mjs/.ts file) have no manifest.
236
- if (EXTENSION_FILE_PATTERN.test(basename(rootDir)))
237
- return {};
238
- const pkg = readPackageJson(rootDir);
239
- if (pkg &&
240
- (pkg.mikan?.displayName ??
241
- pkg.name ??
242
- pkg.version ??
243
- pkg.description ??
244
- pkg.mikan?.secrets?.length)) {
245
- return {
246
- name: pkg.mikan?.displayName ?? pkg.name,
247
- version: pkg.version,
248
- description: pkg.description,
249
- ...(pkg.mikan?.secrets?.length ? { secrets: pkg.mikan.secrets } : {}),
250
- };
251
- }
252
- const manifestPath = join(rootDir, "manifest.json");
253
- if (!existsSync(manifestPath))
254
- return {};
255
- try {
256
- const parsed = JSON.parse(readFileSync(manifestPath, "utf-8"));
257
- if (!parsed || typeof parsed !== "object")
258
- return {};
259
- const record = parsed;
260
- return {
261
- name: typeof record.name === "string" ? record.name : undefined,
262
- version: typeof record.version === "string" ? record.version : undefined,
263
- description: typeof record.description === "string" ? record.description : undefined,
264
- };
265
- }
266
- catch (err) {
267
- log.logWarning(`Ignoring malformed extension manifest: ${manifestPath}`, String(err));
268
- return {};
269
- }
270
- }
271
- /**
272
- * Skills shipped inside a directory-form extension (`<dir>/skills/`).
273
- * Marked inline: extension files live under the host-only state dir, which
274
- * sandbox containers cannot read, so skill bodies must ride in the prompt.
275
- */
276
- function loadExtensionSkills(rootDir, slug) {
277
- // Bare-file extensions (rootDir is a *.mjs/.ts file) ship no skills.
278
- if (EXTENSION_FILE_PATTERN.test(basename(rootDir)))
279
- return [];
280
- const skillsDir = join(rootDir, "skills");
281
- if (!existsSync(skillsDir))
282
- return [];
283
- const result = loadSkillsFromDir({ dir: skillsDir, source: `extension:${slug}` });
284
- for (const diagnostic of result.diagnostics) {
285
- log.logWarning(`Extension skill warning (${slug}): ${diagnostic.message}`, diagnostic.path);
286
- }
287
- for (const skill of result.skills)
288
- skill.inline = true;
289
- return result.skills;
290
- }
291
- const SCHEDULE_FILE_SUFFIX = ".json";
292
- function schedulePrefix(slug, conversationId) {
293
- return `ext.${slug}.${scheduleNameSegment(conversationId)}.`;
294
- }
295
- function payloadFromSpec(spec, conversationId, defaultPlatform) {
296
- // Per-type validation (schedule/timezone for periodic, at for one-shot)
297
- // is owned by the event-format builder.
298
- return buildEventPayload({
299
- type: spec.type,
300
- conversationId,
301
- text: spec.text,
302
- platform: spec.platform ?? defaultPlatform,
303
- ...(spec.type === "periodic"
304
- ? { schedule: spec.schedule, timezone: spec.timezone }
305
- : { at: spec.at }),
306
- });
307
- }
308
- function specFromPayload(payload) {
309
- if (payload.type === "periodic") {
310
- return {
311
- type: "periodic",
312
- schedule: payload.schedule,
313
- timezone: payload.timezone,
314
- text: payload.text,
315
- ...(payload.platform ? { platform: payload.platform } : {}),
316
- };
317
- }
318
- // `immediate` payloads never appear under the schedules namespace (they
319
- // live under "extrun."); tolerate them as an empty one-shot rather than
320
- // widening the spec union.
321
- return {
322
- type: "one-shot",
323
- at: payload.type === "one-shot" ? payload.at : "",
324
- text: payload.text,
325
- ...(payload.platform ? { platform: payload.platform } : {}),
326
- };
327
- }
328
- /** Build the v2 api surface for one extension over the injected services. */
329
- function buildExtensionApi(params) {
330
- const { name, slug, registry, context, services } = params;
331
- const stateDir = services.stateDir ?? join(homedir(), ".mikan");
332
- const conversationId = context.conversationId;
333
- const conversationStateDir = officeStateDir(stateDir, context.address);
334
- // Default platform for proactive messaging and schedules: the platform this
335
- // conversation lives on. Extensions only name a platform explicitly when
336
- // targeting a conversation on a different one.
337
- const ownPlatform = context.address.platform;
338
- const requireScheduleStore = () => {
339
- if (!services.scheduleStore) {
340
- throw new Error("api.schedules is unavailable: this context provides no schedule store");
341
- }
342
- return services.scheduleStore;
343
- };
344
- const requireCallbackScheduleStore = () => {
345
- if (!services.callbackScheduleStore) {
346
- throw new Error("api.schedules callback specs are unavailable: this context provides no callback-schedule store");
347
- }
348
- return services.callbackScheduleStore;
349
- };
350
- const scheduleFilename = (scheduleName) => `${schedulePrefix(slug, conversationId)}${scheduleNameSegment(scheduleName)}${SCHEDULE_FILE_SUFFIX}`;
351
- return {
352
- on: (hook, handler) => registry.register(name, hook, handler),
353
- registerTool: (tool) => registry.registerTool(name, tool),
354
- registerCommand: (command) => registry.registerCommand(name, command),
355
- onDispose: (disposer) => registry.registerDisposer(name, disposer),
356
- log: (message) => log.logInfo(`[extension:${name}] ${message}`),
357
- context,
358
- paths: {
359
- get dataDir() {
360
- // This conversation's own data, co-located with the conversation's
361
- // other host-only assets; removed when the conversation is deleted.
362
- const dir = join(conversationStateDir, "extension-data", slug);
363
- mkdirSync(dir, { recursive: true });
364
- return dir;
365
- },
366
- get sharedDataDir() {
367
- // Cross-conversation data under the sibling `global` scope.
368
- const dir = join(stateDir, "global", "extension-data", slug);
369
- mkdirSync(dir, { recursive: true });
370
- return dir;
371
- },
372
- },
373
- secrets: {
374
- get: (key) => services.resolveSecrets?.(slug)[key],
375
- list: () => Object.keys(services.resolveSecrets?.(slug) ?? {}),
376
- },
377
- schedules: {
378
- upsert: async (scheduleName, spec) => {
379
- const nameSegment = scheduleNameSegment(scheduleName);
380
- // One name namespace across both action kinds: an upsert switches the
381
- // schedule's kind by also dropping its counterpart in the other store.
382
- if (spec.callback !== undefined) {
383
- await requireCallbackScheduleStore().upsert(slug, nameSegment, spec);
384
- await services.scheduleStore?.delete(scheduleFilename(scheduleName));
385
- return;
386
- }
387
- const store = requireScheduleStore();
388
- await store.write(scheduleFilename(scheduleName), payloadFromSpec(spec, conversationId, ownPlatform));
389
- await services.callbackScheduleStore?.delete(slug, nameSegment);
390
- },
391
- delete: async (scheduleName) => {
392
- if (!services.scheduleStore && !services.callbackScheduleStore)
393
- requireScheduleStore();
394
- const deletedCallback = (await services.callbackScheduleStore?.delete(slug, scheduleNameSegment(scheduleName))) ??
395
- false;
396
- const deletedText = (await services.scheduleStore?.delete(scheduleFilename(scheduleName))) ?? false;
397
- return deletedCallback || deletedText;
398
- },
399
- list: async () => {
400
- if (!services.scheduleStore && !services.callbackScheduleStore)
401
- requireScheduleStore();
402
- const infos = [];
403
- if (services.scheduleStore) {
404
- const prefix = schedulePrefix(slug, conversationId);
405
- for (const entry of await services.scheduleStore.list()) {
406
- if (!entry.filename.startsWith(prefix))
407
- continue;
408
- if (!entry.filename.endsWith(SCHEDULE_FILE_SUFFIX))
409
- continue;
410
- infos.push({
411
- name: entry.filename.slice(prefix.length, -SCHEDULE_FILE_SUFFIX.length),
412
- spec: specFromPayload(entry.payload),
413
- });
414
- }
415
- }
416
- if (services.callbackScheduleStore) {
417
- infos.push(...(await services.callbackScheduleStore.list(slug)));
418
- }
419
- return infos;
420
- },
421
- onCallback: (callbackName, handler) => registry.registerScheduleCallback(slug, callbackName, handler),
422
- },
423
- subagent: {
424
- run: async (request) => {
425
- if (!services.runSubagent) {
426
- throw new Error("api.subagent is unavailable: this context provides no subagent runner");
427
- }
428
- return services.runSubagent(request, registry.getContributedTools());
429
- },
430
- },
431
- notify: async (text, options) => {
432
- if (!services.postMessage) {
433
- throw new Error("api.notify is unavailable: this context provides no platform messaging");
434
- }
435
- return services.postMessage(options?.conversationId ?? conversationId, text, {
436
- platform: options?.platform ?? ownPlatform,
437
- ...(options?.threadTs ? { threadTs: options.threadTs } : {}),
438
- });
439
- },
440
- openDm: async (userId) => {
441
- if (!services.openDirectConversation) {
442
- throw new Error("api.openDm is unavailable: this context provides no DM resolution");
443
- }
444
- return services.openDirectConversation(userId, ownPlatform);
445
- },
446
- fetchHistory: async (options) => {
447
- if (!services.fetchHistory) {
448
- throw new Error("api.fetchHistory is unavailable: this context provides no history reads");
449
- }
450
- const { conversationId: target, ...historyOptions } = options ?? {};
451
- return services.fetchHistory(target ?? conversationId, {
452
- ...historyOptions,
453
- platform: ownPlatform,
454
- });
455
- },
456
- listUsers: async () => {
457
- if (!services.listUsers) {
458
- throw new Error("api.listUsers is unavailable: this context provides no user listings");
459
- }
460
- return services.listUsers(ownPlatform);
461
- },
462
- blockkit: {
463
- post: async (message) => {
464
- if (!services.postBlocks) {
465
- throw new Error("api.blockkit is unavailable: this context provides no Block Kit messaging");
466
- }
467
- return services.postBlocks(conversationId, {
468
- text: message.text,
469
- blocks: namespaceActionIds(message.blocks, slug),
470
- threadTs: message.threadTs,
471
- }, ownPlatform);
472
- },
473
- update: async (messageTs, message) => {
474
- if (!services.updateBlocks) {
475
- throw new Error("api.blockkit is unavailable: this context provides no Block Kit messaging");
476
- }
477
- await services.updateBlocks(conversationId, messageTs, {
478
- text: message.text,
479
- blocks: namespaceActionIds(message.blocks, slug),
480
- }, ownPlatform);
481
- },
482
- onAction: (actionId, handler) => registry.registerAction(slug, actionId, handler),
483
- },
484
- react: async (messageTs, emoji) => {
485
- if (!services.addReaction) {
486
- throw new Error("api.react is unavailable: this context provides no reaction support");
487
- }
488
- await services.addReaction(conversationId, messageTs, emoji, ownPlatform);
489
- },
490
- uploadFile: async (filePath, title) => {
491
- if (!services.uploadFile) {
492
- throw new Error("api.uploadFile is unavailable: this context provides no file uploads");
493
- }
494
- await services.uploadFile(conversationId, filePath, title, ownPlatform);
495
- },
496
- triggerRun: async (text) => {
497
- const store = requireScheduleStore();
498
- // Distinct "extrun." namespace: run files must never surface in
499
- // api.schedules.list(), whose ownership filter is the "ext." prefix.
500
- // The embedder's watcher fires and deletes the file immediately.
501
- const filename = `extrun.${slug}.${scheduleNameSegment(conversationId)}.${Date.now()}-${runCounter++}${SCHEDULE_FILE_SUFFIX}`;
502
- await store.write(filename, {
503
- type: "immediate",
504
- platform: ownPlatform,
505
- conversationId,
506
- text,
507
- });
508
- },
509
- };
510
- }
511
- /** Monotonic suffix so rapid triggerRun calls in one process never collide. */
512
- let runCounter = 0;
513
- function resolveActivate(moduleExports) {
514
- if (!moduleExports || typeof moduleExports !== "object")
515
- return undefined;
516
- const candidates = [moduleExports.default, moduleExports];
517
- for (const candidate of candidates) {
518
- if (typeof candidate === "function") {
519
- return { activate: candidate };
520
- }
521
- if (candidate && typeof candidate === "object") {
522
- const activate = candidate.activate;
523
- if (typeof activate === "function") {
524
- return {
525
- name: typeof candidate.name === "string"
526
- ? candidate.name
527
- : undefined,
528
- activate: activate,
529
- };
530
- }
531
- }
532
- }
533
- return undefined;
534
- }
535
- /** Load and activate all extensions found in the given directories. */
536
- export async function loadExtensions(options) {
537
- const registry = new ExtensionRegistry();
538
- const extensions = [];
539
- const errors = [];
540
- const skills = [];
541
- const services = options.services ?? {};
542
- for (const { entrypoint, rootDir, slug } of collectExtensions(options)) {
543
- try {
544
- const manifest = readManifest(rootDir);
545
- // Enforce declared-required secrets before importing: a clear
546
- // provisioning hint beats whatever error the extension would throw at
547
- // first `api.secrets.get` miss. Only enforceable when this context
548
- // resolves secrets at all (`mikan ext dev` and secret-less embedders
549
- // still activate; `api.secrets.get` returns undefined there).
550
- if (services.resolveSecrets) {
551
- const provisioned = services.resolveSecrets(slug);
552
- const missing = (manifest.secrets ?? [])
553
- .filter((secret) => secret.required && !(secret.key in provisioned))
554
- .map((secret) => secret.key);
555
- if (missing.length > 0) {
556
- errors.push({
557
- path: entrypoint,
558
- error: `missing required secrets: ${missing.join(", ")} — provision them in the admin ` +
559
- `portal or in <stateDir>/vaults/extensions/${slug}/env`,
560
- });
561
- continue;
562
- }
563
- }
564
- const moduleExports = await importExtensionModule(entrypoint);
565
- const extension = resolveActivate(moduleExports);
566
- if (!extension) {
567
- errors.push({
568
- path: entrypoint,
569
- error: "extension must export an activate function (default or named)",
570
- });
571
- continue;
572
- }
573
- const name = manifest.name ?? extension.name ?? slug;
574
- const api = buildExtensionApi({
575
- name,
576
- slug,
577
- registry,
578
- context: options.context,
579
- services,
580
- });
581
- let disposer;
582
- try {
583
- disposer = await extension.activate(api);
584
- }
585
- catch (err) {
586
- // A throw mid-activate leaves whatever the extension already
587
- // registered in the shared registry; roll its registrations back and
588
- // release its resources so a failed extension is fully absent.
589
- await registry.rollbackOwner(name, slug);
590
- throw err;
591
- }
592
- if (typeof disposer === "function")
593
- registry.registerDisposer(name, disposer);
594
- const extensionSkills = loadExtensionSkills(rootDir, slug);
595
- skills.push(...extensionSkills);
596
- extensions.push({
597
- name,
598
- path: entrypoint,
599
- slug,
600
- version: manifest.version,
601
- description: manifest.description,
602
- skills: extensionSkills,
603
- });
604
- }
605
- catch (err) {
606
- errors.push({
607
- path: entrypoint,
608
- error: err instanceof Error ? err.message : String(err),
609
- });
610
- }
611
- }
612
- return { registry, extensions, errors, skills, dispose: () => registry.dispose() };
613
- }
614
- /**
615
- * Everything to activate, in final order, with at most one entry per slug.
616
- *
617
- * Deduplication happens here rather than at activation time on purpose. The
618
- * slug keys an extension's data dir, secrets, and schedules, so activating two
619
- * copies of one extension would have them fight over the same state — and the
620
- * registry's first-wins rule for commands would silently pick the opposite
621
- * copy from the one that ran its hooks. Resolving to a single winner before
622
- * anything is imported keeps those decisions consistent.
623
- *
624
- * Precedence follows scan order, so the narrowest scope wins: global
625
- * directories first, then the conversation's, then explicit roots.
626
- */
627
- function collectExtensions(options) {
628
- const bySlug = new Map();
629
- const candidates = [
630
- ...options.dirs.flatMap(discoverExtensionEntrypoints),
631
- ...(options.roots ?? []).flatMap(resolveExtensionRoot),
632
- ];
633
- for (const candidate of candidates) {
634
- const shadowed = bySlug.get(candidate.slug);
635
- if (shadowed && shadowed.rootDir !== candidate.rootDir) {
636
- log.logInfo(`Extension "${candidate.slug}" from ${candidate.rootDir} shadows ${shadowed.rootDir}`);
637
- }
638
- bySlug.set(candidate.slug, candidate);
639
- }
640
- return [...bySlug.values()];
641
- }
642
- /** Resolve one explicit extension root (directory with an entrypoint, or a bare file). */
643
- function resolveExtensionRoot(rootDir) {
644
- let stats;
645
- try {
646
- stats = statSync(rootDir);
647
- }
648
- catch {
649
- log.logWarning(`Extension path does not exist: ${rootDir}`);
650
- return [];
651
- }
652
- if (stats.isFile()) {
653
- return EXTENSION_FILE_PATTERN.test(basename(rootDir))
654
- ? [{ entrypoint: rootDir, rootDir, slug: extensionSlug(rootDir) }]
655
- : [];
656
- }
657
- const entrypoint = resolveDirectoryEntrypoint(rootDir);
658
- if (!entrypoint) {
659
- log.logWarning(`No extension entrypoint in ${rootDir}`, "expected an index.{mjs,js,ts,mts} or a package.json with mikan.extensions");
660
- return [];
661
- }
662
- return [{ entrypoint, rootDir, slug: extensionSlug(rootDir) }];
663
- }
664
- /**
665
- * Validate an extension source path (a directory or a single file) WITHOUT
666
- * activating it: resolves the entrypoint (package.json `mikan.extensions`,
667
- * index file, or the file itself), imports it, and checks it exports an
668
- * `activate` function. Used by `mikan ext install` as a preflight and by
669
- * `mikan ext validate`. Importing runs top-level module code but not
670
- * `activate`, so there are no schedule/tool side effects.
671
- */
672
- export async function validateExtension(sourcePath) {
673
- const errors = [];
674
- const warnings = [];
675
- const rootDir = sourcePath.replace(/[/\\]+$/, "");
676
- const base = basename(rootDir);
677
- if (INDEX_FILE_PATTERN.test(base)) {
678
- warnings.push("Entry is a bare index file; install into a named directory so the slug is stable.");
679
- }
680
- let entrypoint;
681
- if (!existsSync(rootDir)) {
682
- errors.push(`Path does not exist: ${rootDir}`);
683
- }
684
- else if (statSync(rootDir).isDirectory()) {
685
- entrypoint = resolveDirectoryEntrypoint(rootDir);
686
- if (!entrypoint) {
687
- errors.push("No entrypoint found: expected package.json with a mikan.extensions entry, or an index.{mjs,js,ts,mts}.");
688
- }
689
- }
690
- else if (EXTENSION_FILE_PATTERN.test(base)) {
691
- entrypoint = rootDir;
692
- }
693
- else {
694
- errors.push(`Not an extension file (expected .mjs/.js/.ts/.mts): ${rootDir}`);
695
- }
696
- const slug = extensionSlug(rootDir);
697
- const manifest = readManifest(rootDir);
698
- const skillNames = loadExtensionSkills(rootDir, slug).map((skill) => skill.name);
699
- if (entrypoint) {
700
- try {
701
- const moduleExports = await importExtensionModule(entrypoint);
702
- if (!resolveActivate(moduleExports)) {
703
- errors.push("Module does not export an activate function (default or named).");
704
- }
705
- }
706
- catch (err) {
707
- errors.push(`Failed to import: ${err instanceof Error ? err.message : String(err)}`);
708
- }
709
- }
710
- return {
711
- ok: errors.length === 0,
712
- slug,
713
- name: manifest.name ?? slug,
714
- version: manifest.version,
715
- description: manifest.description,
716
- entrypoint,
717
- skillNames,
718
- secrets: manifest.secrets ?? [],
719
- errors,
720
- warnings,
721
- };
722
- }
723
- //# sourceMappingURL=loader.js.map