@geminixiang/mikan 1.0.0-beta.4 → 1.0.0-beta.40

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 (639) hide show
  1. package/CHANGELOG.md +688 -0
  2. package/README.md +99 -36
  3. package/dist/adapter.d.ts +11 -1
  4. package/dist/adapter.d.ts.map +1 -1
  5. package/dist/adapter.js +18 -1
  6. package/dist/adapter.js.map +1 -1
  7. package/dist/adapters/discord/bot.d.ts +6 -7
  8. package/dist/adapters/discord/bot.d.ts.map +1 -1
  9. package/dist/adapters/discord/bot.js +82 -117
  10. package/dist/adapters/discord/bot.js.map +1 -1
  11. package/dist/adapters/discord/context.d.ts +3 -1
  12. package/dist/adapters/discord/context.d.ts.map +1 -1
  13. package/dist/adapters/discord/context.js +54 -215
  14. package/dist/adapters/discord/context.js.map +1 -1
  15. package/dist/adapters/github/bot.d.ts +89 -0
  16. package/dist/adapters/github/bot.d.ts.map +1 -0
  17. package/dist/adapters/github/bot.js +653 -0
  18. package/dist/adapters/github/bot.js.map +1 -0
  19. package/dist/adapters/github/client.d.ts +122 -0
  20. package/dist/adapters/github/client.d.ts.map +1 -0
  21. package/dist/adapters/github/client.js +314 -0
  22. package/dist/adapters/github/client.js.map +1 -0
  23. package/dist/adapters/github/cloudbuild.d.ts +19 -0
  24. package/dist/adapters/github/cloudbuild.d.ts.map +1 -0
  25. package/dist/adapters/github/cloudbuild.js +71 -0
  26. package/dist/adapters/github/cloudbuild.js.map +1 -0
  27. package/dist/adapters/github/context.d.ts +12 -0
  28. package/dist/adapters/github/context.d.ts.map +1 -0
  29. package/dist/adapters/github/context.js +101 -0
  30. package/dist/adapters/github/context.js.map +1 -0
  31. package/dist/adapters/github/gcp-auth.d.ts +28 -0
  32. package/dist/adapters/github/gcp-auth.d.ts.map +1 -0
  33. package/dist/adapters/github/gcp-auth.js +196 -0
  34. package/dist/adapters/github/gcp-auth.js.map +1 -0
  35. package/dist/adapters/github/github-ops.d.ts +91 -0
  36. package/dist/adapters/github/github-ops.d.ts.map +1 -0
  37. package/dist/adapters/github/github-ops.js +406 -0
  38. package/dist/adapters/github/github-ops.js.map +1 -0
  39. package/dist/adapters/github/ids.d.ts +34 -0
  40. package/dist/adapters/github/ids.d.ts.map +1 -0
  41. package/dist/adapters/github/ids.js +57 -0
  42. package/dist/adapters/github/ids.js.map +1 -0
  43. package/dist/adapters/github/repo.d.ts +33 -0
  44. package/dist/adapters/github/repo.d.ts.map +1 -0
  45. package/dist/adapters/github/repo.js +141 -0
  46. package/dist/adapters/github/repo.js.map +1 -0
  47. package/dist/adapters/github/tool-pack.d.ts +14 -0
  48. package/dist/adapters/github/tool-pack.d.ts.map +1 -0
  49. package/dist/adapters/github/tool-pack.js +56 -0
  50. package/dist/adapters/github/tool-pack.js.map +1 -0
  51. package/dist/adapters/github/tools/checks.d.ts +19 -0
  52. package/dist/adapters/github/tools/checks.d.ts.map +1 -0
  53. package/dist/adapters/github/tools/checks.js +105 -0
  54. package/dist/adapters/github/tools/checks.js.map +1 -0
  55. package/dist/adapters/github/tools/issue.d.ts +21 -0
  56. package/dist/adapters/github/tools/issue.d.ts.map +1 -0
  57. package/dist/adapters/github/tools/issue.js +48 -0
  58. package/dist/adapters/github/tools/issue.js.map +1 -0
  59. package/dist/adapters/github/tools/pr.d.ts +22 -0
  60. package/dist/adapters/github/tools/pr.d.ts.map +1 -0
  61. package/dist/adapters/github/tools/pr.js +48 -0
  62. package/dist/adapters/github/tools/pr.js.map +1 -0
  63. package/dist/adapters/github/tools/read.d.ts +21 -0
  64. package/dist/adapters/github/tools/read.d.ts.map +1 -0
  65. package/dist/adapters/github/tools/read.js +141 -0
  66. package/dist/adapters/github/tools/read.js.map +1 -0
  67. package/dist/adapters/github/tools/review-reply.d.ts +17 -0
  68. package/dist/adapters/github/tools/review-reply.d.ts.map +1 -0
  69. package/dist/adapters/github/tools/review-reply.js +38 -0
  70. package/dist/adapters/github/tools/review-reply.js.map +1 -0
  71. package/dist/adapters/github/tools/sync.d.ts +17 -0
  72. package/dist/adapters/github/tools/sync.d.ts.map +1 -0
  73. package/dist/adapters/github/tools/sync.js +34 -0
  74. package/dist/adapters/github/tools/sync.js.map +1 -0
  75. package/dist/adapters/github/types.d.ts +373 -0
  76. package/dist/adapters/github/types.d.ts.map +1 -0
  77. package/dist/adapters/github/types.js +2 -0
  78. package/dist/adapters/github/types.js.map +1 -0
  79. package/dist/adapters/intake.d.ts +16 -5
  80. package/dist/adapters/intake.d.ts.map +1 -1
  81. package/dist/adapters/intake.js +86 -23
  82. package/dist/adapters/intake.js.map +1 -1
  83. package/dist/adapters/progressive-renderer.d.ts +7 -0
  84. package/dist/adapters/progressive-renderer.d.ts.map +1 -0
  85. package/dist/adapters/progressive-renderer.js +383 -0
  86. package/dist/adapters/progressive-renderer.js.map +1 -0
  87. package/dist/adapters/shared.d.ts +23 -10
  88. package/dist/adapters/shared.d.ts.map +1 -1
  89. package/dist/adapters/shared.js +60 -22
  90. package/dist/adapters/shared.js.map +1 -1
  91. package/dist/adapters/slack/blocks.d.ts +14 -0
  92. package/dist/adapters/slack/blocks.d.ts.map +1 -1
  93. package/dist/adapters/slack/blocks.js +147 -111
  94. package/dist/adapters/slack/blocks.js.map +1 -1
  95. package/dist/adapters/slack/bot.d.ts +43 -13
  96. package/dist/adapters/slack/bot.d.ts.map +1 -1
  97. package/dist/adapters/slack/bot.js +385 -207
  98. package/dist/adapters/slack/bot.js.map +1 -1
  99. package/dist/adapters/slack/context.d.ts +3 -1
  100. package/dist/adapters/slack/context.d.ts.map +1 -1
  101. package/dist/adapters/slack/context.js +11 -17
  102. package/dist/adapters/slack/context.js.map +1 -1
  103. package/dist/adapters/slack/response-lifecycle.d.ts.map +1 -1
  104. package/dist/adapters/slack/response-lifecycle.js +126 -323
  105. package/dist/adapters/slack/response-lifecycle.js.map +1 -1
  106. package/dist/adapters/slack/session.d.ts.map +1 -1
  107. package/dist/adapters/slack/session.js +7 -11
  108. package/dist/adapters/slack/session.js.map +1 -1
  109. package/dist/adapters/slack/tool-pack.d.ts +11 -0
  110. package/dist/adapters/slack/tool-pack.d.ts.map +1 -0
  111. package/dist/adapters/slack/tool-pack.js +45 -0
  112. package/dist/adapters/slack/tool-pack.js.map +1 -0
  113. package/dist/adapters/slack/tools/attach.js +1 -1
  114. package/dist/adapters/slack/tools/attach.js.map +1 -1
  115. package/dist/adapters/slack/tools/blockkit.d.ts +14 -0
  116. package/dist/adapters/slack/tools/blockkit.d.ts.map +1 -0
  117. package/dist/adapters/slack/tools/blockkit.js +106 -0
  118. package/dist/adapters/slack/tools/blockkit.js.map +1 -0
  119. package/dist/adapters/slack/types.d.ts +40 -2
  120. package/dist/adapters/slack/types.d.ts.map +1 -1
  121. package/dist/adapters/slack/types.js.map +1 -1
  122. package/dist/adapters/telegram/bot.d.ts +8 -9
  123. package/dist/adapters/telegram/bot.d.ts.map +1 -1
  124. package/dist/adapters/telegram/bot.js +90 -117
  125. package/dist/adapters/telegram/bot.js.map +1 -1
  126. package/dist/adapters/telegram/context.d.ts +2 -0
  127. package/dist/adapters/telegram/context.d.ts.map +1 -1
  128. package/dist/adapters/telegram/context.js +61 -184
  129. package/dist/adapters/telegram/context.js.map +1 -1
  130. package/dist/adapters/telegram/html.d.ts.map +1 -1
  131. package/dist/adapters/telegram/html.js +10 -7
  132. package/dist/adapters/telegram/html.js.map +1 -1
  133. package/dist/adapters/types.d.ts +109 -12
  134. package/dist/adapters/types.d.ts.map +1 -1
  135. package/dist/adapters/types.js.map +1 -1
  136. package/dist/agent-events.d.ts +3 -2
  137. package/dist/agent-events.d.ts.map +1 -1
  138. package/dist/agent-events.js +19 -1
  139. package/dist/agent-events.js.map +1 -1
  140. package/dist/agent.d.ts +14 -19
  141. package/dist/agent.d.ts.map +1 -1
  142. package/dist/agent.js +840 -298
  143. package/dist/agent.js.map +1 -1
  144. package/dist/cli/arg-grammar.d.ts +25 -0
  145. package/dist/cli/arg-grammar.d.ts.map +1 -0
  146. package/dist/cli/arg-grammar.js +61 -0
  147. package/dist/cli/arg-grammar.js.map +1 -0
  148. package/dist/cli/boot.d.ts +5 -0
  149. package/dist/cli/boot.d.ts.map +1 -0
  150. package/dist/cli/boot.js +117 -0
  151. package/dist/cli/boot.js.map +1 -0
  152. package/dist/cli/download.d.ts.map +1 -0
  153. package/dist/{download.js → cli/download.js} +2 -0
  154. package/dist/cli/download.js.map +1 -0
  155. package/dist/cli/ext-dev.d.ts +2 -0
  156. package/dist/cli/ext-dev.d.ts.map +1 -0
  157. package/dist/cli/ext-dev.js +188 -0
  158. package/dist/cli/ext-dev.js.map +1 -0
  159. package/dist/cli/ext.d.ts +2 -0
  160. package/dist/cli/ext.d.ts.map +1 -0
  161. package/dist/cli/ext.js +324 -0
  162. package/dist/cli/ext.js.map +1 -0
  163. package/dist/cli/office.d.ts +2 -0
  164. package/dist/cli/office.d.ts.map +1 -0
  165. package/dist/cli/office.js +91 -0
  166. package/dist/cli/office.js.map +1 -0
  167. package/dist/cli/types.d.ts +16 -0
  168. package/dist/cli/types.d.ts.map +1 -0
  169. package/dist/cli/types.js +2 -0
  170. package/dist/cli/types.js.map +1 -0
  171. package/dist/commands/admin.d.ts.map +1 -1
  172. package/dist/commands/admin.js +3 -2
  173. package/dist/commands/admin.js.map +1 -1
  174. package/dist/commands/auto-reply.d.ts.map +1 -1
  175. package/dist/commands/auto-reply.js +5 -9
  176. package/dist/commands/auto-reply.js.map +1 -1
  177. package/dist/commands/extensions.d.ts.map +1 -1
  178. package/dist/commands/extensions.js +9 -6
  179. package/dist/commands/extensions.js.map +1 -1
  180. package/dist/commands/login.d.ts +2 -1
  181. package/dist/commands/login.d.ts.map +1 -1
  182. package/dist/commands/login.js +40 -5
  183. package/dist/commands/login.js.map +1 -1
  184. package/dist/commands/manifest.d.ts +37 -0
  185. package/dist/commands/manifest.d.ts.map +1 -0
  186. package/dist/commands/manifest.js +151 -0
  187. package/dist/commands/manifest.js.map +1 -0
  188. package/dist/commands/model.d.ts +2 -3
  189. package/dist/commands/model.d.ts.map +1 -1
  190. package/dist/commands/model.js +63 -24
  191. package/dist/commands/model.js.map +1 -1
  192. package/dist/commands/new.d.ts.map +1 -1
  193. package/dist/commands/new.js +15 -3
  194. package/dist/commands/new.js.map +1 -1
  195. package/dist/commands/registry.d.ts +2 -2
  196. package/dist/commands/registry.d.ts.map +1 -1
  197. package/dist/commands/registry.js +1 -2
  198. package/dist/commands/registry.js.map +1 -1
  199. package/dist/commands/sandbox.d.ts.map +1 -1
  200. package/dist/commands/sandbox.js +83 -33
  201. package/dist/commands/sandbox.js.map +1 -1
  202. package/dist/commands/session-view.d.ts.map +1 -1
  203. package/dist/commands/session-view.js +6 -3
  204. package/dist/commands/session-view.js.map +1 -1
  205. package/dist/commands/types.d.ts +79 -7
  206. package/dist/commands/types.d.ts.map +1 -1
  207. package/dist/commands/types.js.map +1 -1
  208. package/dist/config.d.ts +23 -8
  209. package/dist/config.d.ts.map +1 -1
  210. package/dist/config.js +222 -135
  211. package/dist/config.js.map +1 -1
  212. package/dist/env-manifest.d.ts +30 -0
  213. package/dist/env-manifest.d.ts.map +1 -0
  214. package/dist/env-manifest.js +229 -0
  215. package/dist/env-manifest.js.map +1 -0
  216. package/dist/events.d.ts.map +1 -1
  217. package/dist/events.js +20 -81
  218. package/dist/events.js.map +1 -1
  219. package/dist/execution-resolver.d.ts +7 -8
  220. package/dist/execution-resolver.d.ts.map +1 -1
  221. package/dist/execution-resolver.js +106 -110
  222. package/dist/execution-resolver.js.map +1 -1
  223. package/dist/extension-schedules.d.ts +31 -0
  224. package/dist/extension-schedules.d.ts.map +1 -0
  225. package/dist/extension-schedules.js +229 -0
  226. package/dist/extension-schedules.js.map +1 -0
  227. package/dist/harness/auth.d.ts +2 -1
  228. package/dist/harness/auth.d.ts.map +1 -1
  229. package/dist/harness/auth.js +11 -5
  230. package/dist/harness/auth.js.map +1 -1
  231. package/dist/harness/event-format.d.ts +27 -0
  232. package/dist/harness/event-format.d.ts.map +1 -0
  233. package/dist/harness/event-format.js +160 -0
  234. package/dist/harness/event-format.js.map +1 -0
  235. package/dist/harness/extensions/loader.d.ts +27 -49
  236. package/dist/harness/extensions/loader.d.ts.map +1 -1
  237. package/dist/harness/extensions/loader.js +486 -130
  238. package/dist/harness/extensions/loader.js.map +1 -1
  239. package/dist/harness/extensions/registry.d.ts +107 -2
  240. package/dist/harness/extensions/registry.d.ts.map +1 -1
  241. package/dist/harness/extensions/registry.js +316 -0
  242. package/dist/harness/extensions/registry.js.map +1 -1
  243. package/dist/harness/extensions/types.d.ts +482 -42
  244. package/dist/harness/extensions/types.d.ts.map +1 -1
  245. package/dist/harness/extensions/types.js.map +1 -1
  246. package/dist/harness/index.d.ts +18 -8
  247. package/dist/harness/index.d.ts.map +1 -1
  248. package/dist/harness/index.js +7 -4
  249. package/dist/harness/index.js.map +1 -1
  250. package/dist/harness/models.d.ts +7 -4
  251. package/dist/harness/models.d.ts.map +1 -1
  252. package/dist/harness/models.js +46 -24
  253. package/dist/harness/models.js.map +1 -1
  254. package/dist/harness/runner.d.ts +50 -54
  255. package/dist/harness/runner.d.ts.map +1 -1
  256. package/dist/harness/runner.js +232 -46
  257. package/dist/harness/runner.js.map +1 -1
  258. package/dist/harness/session-store.d.ts +11 -5
  259. package/dist/harness/session-store.d.ts.map +1 -1
  260. package/dist/harness/session-store.js +141 -36
  261. package/dist/harness/session-store.js.map +1 -1
  262. package/dist/harness/settings.d.ts +2 -20
  263. package/dist/harness/settings.d.ts.map +1 -1
  264. package/dist/harness/settings.js +12 -1
  265. package/dist/harness/settings.js.map +1 -1
  266. package/dist/harness/skills.d.ts +10 -29
  267. package/dist/harness/skills.d.ts.map +1 -1
  268. package/dist/harness/skills.js +48 -6
  269. package/dist/harness/skills.js.map +1 -1
  270. package/dist/harness/subagent-profiles.d.ts +8 -0
  271. package/dist/harness/subagent-profiles.d.ts.map +1 -0
  272. package/dist/harness/subagent-profiles.js +299 -0
  273. package/dist/harness/subagent-profiles.js.map +1 -0
  274. package/dist/harness/subagent-runner.d.ts +39 -0
  275. package/dist/harness/subagent-runner.d.ts.map +1 -0
  276. package/dist/harness/subagent-runner.js +617 -0
  277. package/dist/harness/subagent-runner.js.map +1 -0
  278. package/dist/harness/types.d.ts +267 -1
  279. package/dist/harness/types.d.ts.map +1 -1
  280. package/dist/harness/types.js.map +1 -1
  281. package/dist/harness/usage.d.ts +6 -0
  282. package/dist/harness/usage.d.ts.map +1 -0
  283. package/dist/harness/usage.js +32 -0
  284. package/dist/harness/usage.js.map +1 -0
  285. package/dist/index.d.ts +36 -8
  286. package/dist/index.d.ts.map +1 -1
  287. package/dist/index.js +22 -6
  288. package/dist/index.js.map +1 -1
  289. package/dist/main.js +391 -127
  290. package/dist/main.js.map +1 -1
  291. package/dist/observability/instrument.js +7 -5
  292. package/dist/observability/instrument.js.map +1 -1
  293. package/dist/observability/sentry.d.ts +2 -0
  294. package/dist/observability/sentry.d.ts.map +1 -1
  295. package/dist/observability/sentry.js +10 -2
  296. package/dist/observability/sentry.js.map +1 -1
  297. package/dist/office/address.d.ts +31 -0
  298. package/dist/office/address.d.ts.map +1 -0
  299. package/dist/office/address.js +113 -0
  300. package/dist/office/address.js.map +1 -0
  301. package/dist/office/index.d.ts +11 -0
  302. package/dist/office/index.d.ts.map +1 -0
  303. package/dist/office/index.js +11 -0
  304. package/dist/office/index.js.map +1 -0
  305. package/dist/office/layout.d.ts +27 -0
  306. package/dist/office/layout.d.ts.map +1 -0
  307. package/dist/office/layout.js +97 -0
  308. package/dist/office/layout.js.map +1 -0
  309. package/dist/office/migration.d.ts +44 -0
  310. package/dist/office/migration.d.ts.map +1 -0
  311. package/dist/office/migration.js +255 -0
  312. package/dist/office/migration.js.map +1 -0
  313. package/dist/office/registry.d.ts +75 -0
  314. package/dist/office/registry.d.ts.map +1 -0
  315. package/dist/office/registry.js +646 -0
  316. package/dist/office/registry.js.map +1 -0
  317. package/dist/office/types.d.ts +71 -0
  318. package/dist/office/types.d.ts.map +1 -0
  319. package/dist/office/types.js +2 -0
  320. package/dist/office/types.js.map +1 -0
  321. package/dist/packages/admin.d.ts +17 -0
  322. package/dist/packages/admin.d.ts.map +1 -0
  323. package/dist/packages/admin.js +98 -0
  324. package/dist/packages/admin.js.map +1 -0
  325. package/dist/packages/index.d.ts +6 -0
  326. package/dist/packages/index.d.ts.map +1 -0
  327. package/dist/packages/index.js +6 -0
  328. package/dist/packages/index.js.map +1 -0
  329. package/dist/packages/inspect.d.ts +11 -0
  330. package/dist/packages/inspect.d.ts.map +1 -0
  331. package/dist/packages/inspect.js +98 -0
  332. package/dist/packages/inspect.js.map +1 -0
  333. package/dist/packages/materialize.d.ts +40 -0
  334. package/dist/packages/materialize.d.ts.map +1 -0
  335. package/dist/packages/materialize.js +297 -0
  336. package/dist/packages/materialize.js.map +1 -0
  337. package/dist/packages/resolve.d.ts +25 -0
  338. package/dist/packages/resolve.d.ts.map +1 -0
  339. package/dist/packages/resolve.js +208 -0
  340. package/dist/packages/resolve.js.map +1 -0
  341. package/dist/packages/source.d.ts +39 -0
  342. package/dist/packages/source.d.ts.map +1 -0
  343. package/dist/packages/source.js +189 -0
  344. package/dist/packages/source.js.map +1 -0
  345. package/dist/packages/types.d.ts +104 -0
  346. package/dist/packages/types.d.ts.map +1 -0
  347. package/dist/packages/types.js +2 -0
  348. package/dist/packages/types.js.map +1 -0
  349. package/dist/provisioner.d.ts +66 -0
  350. package/dist/provisioner.d.ts.map +1 -1
  351. package/dist/provisioner.js +335 -13
  352. package/dist/provisioner.js.map +1 -1
  353. package/dist/runtime/conversation-runtime.d.ts +1 -1
  354. package/dist/runtime/conversation-runtime.d.ts.map +1 -1
  355. package/dist/runtime/conversation-runtime.js +562 -118
  356. package/dist/runtime/conversation-runtime.js.map +1 -1
  357. package/dist/runtime/session-lifecycle.d.ts +38 -0
  358. package/dist/runtime/session-lifecycle.d.ts.map +1 -0
  359. package/dist/runtime/session-lifecycle.js +193 -0
  360. package/dist/runtime/session-lifecycle.js.map +1 -0
  361. package/dist/runtime/types.d.ts +66 -7
  362. package/dist/runtime/types.d.ts.map +1 -1
  363. package/dist/runtime/types.js.map +1 -1
  364. package/dist/sandbox/cloudflare.d.ts +3 -0
  365. package/dist/sandbox/cloudflare.d.ts.map +1 -1
  366. package/dist/sandbox/cloudflare.js +13 -1
  367. package/dist/sandbox/cloudflare.js.map +1 -1
  368. package/dist/sandbox/container.d.ts +4 -0
  369. package/dist/sandbox/container.d.ts.map +1 -1
  370. package/dist/sandbox/container.js +13 -3
  371. package/dist/sandbox/container.js.map +1 -1
  372. package/dist/sandbox/firecracker.d.ts +3 -0
  373. package/dist/sandbox/firecracker.d.ts.map +1 -1
  374. package/dist/sandbox/firecracker.js +13 -2
  375. package/dist/sandbox/firecracker.js.map +1 -1
  376. package/dist/sandbox/gondolin.d.ts +57 -0
  377. package/dist/sandbox/gondolin.d.ts.map +1 -0
  378. package/dist/sandbox/gondolin.js +764 -0
  379. package/dist/sandbox/gondolin.js.map +1 -0
  380. package/dist/sandbox/host.d.ts +3 -0
  381. package/dist/sandbox/host.d.ts.map +1 -1
  382. package/dist/sandbox/host.js +18 -3
  383. package/dist/sandbox/host.js.map +1 -1
  384. package/dist/sandbox/identity.d.ts +44 -0
  385. package/dist/sandbox/identity.d.ts.map +1 -0
  386. package/dist/sandbox/identity.js +68 -0
  387. package/dist/sandbox/identity.js.map +1 -0
  388. package/dist/sandbox/image.d.ts.map +1 -1
  389. package/dist/sandbox/image.js +2 -0
  390. package/dist/sandbox/image.js.map +1 -1
  391. package/dist/sandbox/index.d.ts +17 -4
  392. package/dist/sandbox/index.d.ts.map +1 -1
  393. package/dist/sandbox/index.js +37 -3
  394. package/dist/sandbox/index.js.map +1 -1
  395. package/dist/sandbox/types.d.ts +65 -1
  396. package/dist/sandbox/types.d.ts.map +1 -1
  397. package/dist/sandbox/types.js.map +1 -1
  398. package/dist/sandbox/utils.d.ts +14 -0
  399. package/dist/sandbox/utils.d.ts.map +1 -1
  400. package/dist/sandbox/utils.js +68 -1
  401. package/dist/sandbox/utils.js.map +1 -1
  402. package/dist/sessions/chat-history-sync.d.ts +25 -0
  403. package/dist/sessions/chat-history-sync.d.ts.map +1 -0
  404. package/dist/sessions/{agent-memory-file-manager.js → chat-history-sync.js} +135 -131
  405. package/dist/sessions/chat-history-sync.js.map +1 -0
  406. package/dist/sessions/conversation-log.d.ts +9 -0
  407. package/dist/sessions/conversation-log.d.ts.map +1 -0
  408. package/dist/sessions/conversation-log.js +50 -0
  409. package/dist/sessions/conversation-log.js.map +1 -0
  410. package/dist/sessions/history-line.d.ts +29 -0
  411. package/dist/sessions/history-line.d.ts.map +1 -0
  412. package/dist/sessions/history-line.js +45 -0
  413. package/dist/sessions/history-line.js.map +1 -0
  414. package/dist/sessions/rotation.d.ts +2 -0
  415. package/dist/sessions/rotation.d.ts.map +1 -0
  416. package/dist/sessions/rotation.js +39 -0
  417. package/dist/sessions/rotation.js.map +1 -0
  418. package/dist/sessions/session-key.d.ts +33 -0
  419. package/dist/sessions/session-key.d.ts.map +1 -0
  420. package/dist/sessions/session-key.js +115 -0
  421. package/dist/sessions/session-key.js.map +1 -0
  422. package/dist/sessions/store.d.ts +15 -7
  423. package/dist/sessions/store.d.ts.map +1 -1
  424. package/dist/sessions/store.js +127 -36
  425. package/dist/sessions/store.js.map +1 -1
  426. package/dist/sessions/types.d.ts +19 -5
  427. package/dist/sessions/types.d.ts.map +1 -1
  428. package/dist/sessions/types.js.map +1 -1
  429. package/dist/settings-mutation.d.ts +40 -0
  430. package/dist/settings-mutation.d.ts.map +1 -0
  431. package/dist/settings-mutation.js +61 -0
  432. package/dist/settings-mutation.js.map +1 -0
  433. package/dist/subagent-progress.d.ts +43 -0
  434. package/dist/subagent-progress.d.ts.map +1 -0
  435. package/dist/subagent-progress.js +220 -0
  436. package/dist/subagent-progress.js.map +1 -0
  437. package/dist/tools/bash.d.ts +3 -1
  438. package/dist/tools/bash.d.ts.map +1 -1
  439. package/dist/tools/bash.js +26 -18
  440. package/dist/tools/bash.js.map +1 -1
  441. package/dist/tools/edit.d.ts.map +1 -1
  442. package/dist/tools/edit.js +14 -13
  443. package/dist/tools/edit.js.map +1 -1
  444. package/dist/tools/event.d.ts +1 -1
  445. package/dist/tools/event.d.ts.map +1 -1
  446. package/dist/tools/event.js +58 -45
  447. package/dist/tools/event.js.map +1 -1
  448. package/dist/tools/generate-image.d.ts +23 -0
  449. package/dist/tools/generate-image.d.ts.map +1 -0
  450. package/dist/tools/generate-image.js +65 -0
  451. package/dist/tools/generate-image.js.map +1 -0
  452. package/dist/tools/host-fn-tool.d.ts +21 -0
  453. package/dist/tools/host-fn-tool.d.ts.map +1 -0
  454. package/dist/tools/host-fn-tool.js +32 -0
  455. package/dist/tools/host-fn-tool.js.map +1 -0
  456. package/dist/tools/index.d.ts +19 -2
  457. package/dist/tools/index.d.ts.map +1 -1
  458. package/dist/tools/index.js +25 -2
  459. package/dist/tools/index.js.map +1 -1
  460. package/dist/tools/react.d.ts +15 -0
  461. package/dist/tools/react.d.ts.map +1 -0
  462. package/dist/tools/react.js +29 -0
  463. package/dist/tools/react.js.map +1 -0
  464. package/dist/tools/read.d.ts +1 -0
  465. package/dist/tools/read.d.ts.map +1 -1
  466. package/dist/tools/read.js +39 -33
  467. package/dist/tools/read.js.map +1 -1
  468. package/dist/tools/sandbox.d.ts +2 -2
  469. package/dist/tools/sandbox.d.ts.map +1 -1
  470. package/dist/tools/sandbox.js +14 -9
  471. package/dist/tools/sandbox.js.map +1 -1
  472. package/dist/tools/subagent-slots.d.ts +28 -0
  473. package/dist/tools/subagent-slots.d.ts.map +1 -0
  474. package/dist/tools/subagent-slots.js +72 -0
  475. package/dist/tools/subagent-slots.js.map +1 -0
  476. package/dist/tools/subagent.d.ts +54 -0
  477. package/dist/tools/subagent.d.ts.map +1 -0
  478. package/dist/tools/subagent.js +411 -0
  479. package/dist/tools/subagent.js.map +1 -0
  480. package/dist/tools/types.d.ts +40 -32
  481. package/dist/tools/types.d.ts.map +1 -1
  482. package/dist/tools/types.js.map +1 -1
  483. package/dist/tools/write.d.ts.map +1 -1
  484. package/dist/tools/write.js +2 -8
  485. package/dist/tools/write.js.map +1 -1
  486. package/dist/trigger.d.ts +2 -1
  487. package/dist/trigger.d.ts.map +1 -1
  488. package/dist/trigger.js +6 -9
  489. package/dist/trigger.js.map +1 -1
  490. package/dist/types.d.ts +403 -59
  491. package/dist/types.d.ts.map +1 -1
  492. package/dist/types.js +2 -2
  493. package/dist/types.js.map +1 -1
  494. package/dist/utils/file-guards.d.ts +9 -0
  495. package/dist/utils/file-guards.d.ts.map +1 -1
  496. package/dist/utils/file-guards.js +44 -1
  497. package/dist/utils/file-guards.js.map +1 -1
  498. package/dist/vault/disabled.d.ts +9 -0
  499. package/dist/vault/disabled.d.ts.map +1 -0
  500. package/dist/vault/disabled.js +25 -0
  501. package/dist/vault/disabled.js.map +1 -0
  502. package/dist/vault/index.d.ts +45 -2
  503. package/dist/vault/index.d.ts.map +1 -1
  504. package/dist/vault/index.js +127 -36
  505. package/dist/vault/index.js.map +1 -1
  506. package/dist/vault/types.d.ts +6 -2
  507. package/dist/vault/types.d.ts.map +1 -1
  508. package/dist/vault/types.js.map +1 -1
  509. package/dist/web/admin/portal.d.ts +31 -3
  510. package/dist/web/admin/portal.d.ts.map +1 -1
  511. package/dist/web/admin/portal.js +846 -345
  512. package/dist/web/admin/portal.js.map +1 -1
  513. package/dist/web/admin/provider-models.js +1 -1
  514. package/dist/web/admin/provider-models.js.map +1 -1
  515. package/dist/web/admin/types.d.ts +23 -3
  516. package/dist/web/admin/types.d.ts.map +1 -1
  517. package/dist/web/admin/types.js.map +1 -1
  518. package/dist/web/login/oauth.d.ts +2 -3
  519. package/dist/web/login/oauth.d.ts.map +1 -1
  520. package/dist/web/login/oauth.js +1 -32
  521. package/dist/web/login/oauth.js.map +1 -1
  522. package/dist/web/login/portal.d.ts +1 -1
  523. package/dist/web/login/portal.d.ts.map +1 -1
  524. package/dist/web/login/portal.js +13 -36
  525. package/dist/web/login/portal.js.map +1 -1
  526. package/dist/web/login/types.d.ts +0 -11
  527. package/dist/web/login/types.d.ts.map +1 -1
  528. package/dist/web/login/types.js.map +1 -1
  529. package/dist/web/portal-shell.d.ts +21 -0
  530. package/dist/web/portal-shell.d.ts.map +1 -0
  531. package/dist/{portal-shell.js → web/portal-shell.js} +67 -2
  532. package/dist/web/portal-shell.js.map +1 -0
  533. package/dist/web/server.d.ts +3 -2
  534. package/dist/web/server.d.ts.map +1 -1
  535. package/dist/web/server.js +11 -4
  536. package/dist/web/server.js.map +1 -1
  537. package/dist/web/session-view/portal.d.ts +1 -1
  538. package/dist/web/session-view/portal.d.ts.map +1 -1
  539. package/dist/web/session-view/portal.js +37 -28
  540. package/dist/web/session-view/portal.js.map +1 -1
  541. package/dist/web/session-view/service.d.ts +1 -1
  542. package/dist/web/session-view/service.d.ts.map +1 -1
  543. package/dist/web/session-view/service.js +61 -18
  544. package/dist/web/session-view/service.js.map +1 -1
  545. package/dist/web/session-view/types.d.ts +0 -3
  546. package/dist/web/session-view/types.d.ts.map +1 -1
  547. package/dist/web/session-view/types.js.map +1 -1
  548. package/dist/web/token-store.js +1 -1
  549. package/dist/web/token-store.js.map +1 -1
  550. package/dist/workspace-projection/index.d.ts +10 -0
  551. package/dist/workspace-projection/index.d.ts.map +1 -0
  552. package/dist/workspace-projection/index.js +120 -0
  553. package/dist/workspace-projection/index.js.map +1 -0
  554. package/dist/workspace-projection/types.d.ts +16 -0
  555. package/dist/workspace-projection/types.d.ts.map +1 -0
  556. package/dist/workspace-projection/types.js +2 -0
  557. package/dist/workspace-projection/types.js.map +1 -0
  558. package/package.json +67 -37
  559. package/dist/adapters/streaming.d.ts +0 -18
  560. package/dist/adapters/streaming.d.ts.map +0 -1
  561. package/dist/adapters/streaming.js +0 -44
  562. package/dist/adapters/streaming.js.map +0 -1
  563. package/dist/commands/parse.d.ts +0 -7
  564. package/dist/commands/parse.d.ts.map +0 -1
  565. package/dist/commands/parse.js +0 -14
  566. package/dist/commands/parse.js.map +0 -1
  567. package/dist/download.d.ts.map +0 -1
  568. package/dist/download.js.map +0 -1
  569. package/dist/model-registry.d.ts +0 -4
  570. package/dist/model-registry.d.ts.map +0 -1
  571. package/dist/model-registry.js +0 -7
  572. package/dist/model-registry.js.map +0 -1
  573. package/dist/portal-shell.d.ts +0 -4
  574. package/dist/portal-shell.d.ts.map +0 -1
  575. package/dist/portal-shell.js.map +0 -1
  576. package/dist/runtime/agent-run-controller.d.ts +0 -31
  577. package/dist/runtime/agent-run-controller.d.ts.map +0 -1
  578. package/dist/runtime/agent-run-controller.js +0 -195
  579. package/dist/runtime/agent-run-controller.js.map +0 -1
  580. package/dist/sandbox/path-context.d.ts +0 -3
  581. package/dist/sandbox/path-context.d.ts.map +0 -1
  582. package/dist/sandbox/path-context.js +0 -20
  583. package/dist/sandbox/path-context.js.map +0 -1
  584. package/dist/sessions/agent-memory-file-manager.d.ts +0 -19
  585. package/dist/sessions/agent-memory-file-manager.d.ts.map +0 -1
  586. package/dist/sessions/agent-memory-file-manager.js.map +0 -1
  587. package/dist/sessions/metadata.d.ts +0 -3
  588. package/dist/sessions/metadata.d.ts.map +0 -1
  589. package/dist/sessions/metadata.js +0 -11
  590. package/dist/sessions/metadata.js.map +0 -1
  591. package/dist/sessions/policy.d.ts +0 -6
  592. package/dist/sessions/policy.d.ts.map +0 -1
  593. package/dist/sessions/policy.js +0 -23
  594. package/dist/sessions/policy.js.map +0 -1
  595. package/dist/store.d.ts +0 -46
  596. package/dist/store.d.ts.map +0 -1
  597. package/dist/store.js +0 -177
  598. package/dist/store.js.map +0 -1
  599. package/dist/tools/truncate.d.ts +0 -33
  600. package/dist/tools/truncate.d.ts.map +0 -1
  601. package/dist/tools/truncate.js +0 -184
  602. package/dist/tools/truncate.js.map +0 -1
  603. package/dist/utils/date.d.ts +0 -10
  604. package/dist/utils/date.d.ts.map +0 -1
  605. package/dist/utils/date.js +0 -23
  606. package/dist/utils/date.js.map +0 -1
  607. package/dist/utils/env.d.ts +0 -3
  608. package/dist/utils/env.d.ts.map +0 -1
  609. package/dist/utils/env.js +0 -12
  610. package/dist/utils/env.js.map +0 -1
  611. package/dist/utils/fs-atomic.d.ts +0 -10
  612. package/dist/utils/fs-atomic.d.ts.map +0 -1
  613. package/dist/utils/fs-atomic.js +0 -45
  614. package/dist/utils/fs-atomic.js.map +0 -1
  615. package/dist/utils/html.d.ts +0 -2
  616. package/dist/utils/html.d.ts.map +0 -1
  617. package/dist/utils/html.js +0 -4
  618. package/dist/utils/html.js.map +0 -1
  619. package/dist/utils/http-body.d.ts +0 -10
  620. package/dist/utils/http-body.d.ts.map +0 -1
  621. package/dist/utils/http-body.js +0 -34
  622. package/dist/utils/http-body.js.map +0 -1
  623. package/dist/vault/routing.d.ts +0 -3
  624. package/dist/vault/routing.d.ts.map +0 -1
  625. package/dist/vault/routing.js +0 -13
  626. package/dist/vault/routing.js.map +0 -1
  627. package/dist/web/agent-events/portal.d.ts +0 -3
  628. package/dist/web/agent-events/portal.d.ts.map +0 -1
  629. package/dist/web/agent-events/portal.js +0 -18
  630. package/dist/web/agent-events/portal.js.map +0 -1
  631. package/dist/web/request.d.ts +0 -3
  632. package/dist/web/request.d.ts.map +0 -1
  633. package/dist/web/request.js +0 -13
  634. package/dist/web/request.js.map +0 -1
  635. package/dist/web/session-view/command.d.ts +0 -4
  636. package/dist/web/session-view/command.d.ts.map +0 -1
  637. package/dist/web/session-view/command.js +0 -7
  638. package/dist/web/session-view/command.js.map +0 -1
  639. /package/dist/{download.d.ts → cli/download.d.ts} +0 -0
@@ -12,31 +12,50 @@
12
12
  * under mikan's state dir.
13
13
  *
14
14
  * Directories are scanned in order; all discovered extensions activate.
15
- * Accepted layouts:
15
+ * Accepted layouts (entrypoint may be .mjs/.js/.ts/.mts — loaded via jiti):
16
16
  *
17
- * - `extensions/<name>.mjs` / `extensions/<name>.js`
18
- * - `extensions/<name>/index.mjs` / `extensions/<name>/index.js`
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)
19
21
  *
20
- * Modules are imported with a cache-busting query so edited extensions are
21
- * picked up when a new harness instance is created for a conversation.
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.
22
24
  */
23
- import { existsSync, mkdirSync, readdirSync, readFileSync, statSync } from "fs";
24
- import { homedir } from "os";
25
- import { basename, dirname, join } from "path";
26
- import { pathToFileURL } from "url";
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";
27
29
  import * as log from "../../log.js";
30
+ import { buildEventPayload } from "../event-format.js";
28
31
  import { loadSkillsFromDir } from "../skills.js";
29
- import { ExtensionRegistry } from "./registry.js";
30
- const EXTENSION_FILE_PATTERN = /\.(mjs|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"];
31
37
  /**
32
- * Canonical host-only extension directories for a conversation:
33
- * `<stateDir>/extensions/global` (all conversations) and
34
- * `<stateDir>/extensions/<conversationId>` (that conversation only).
35
- * `global` is reserved as a scope name; platform conversation ids never
36
- * take that value.
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.
37
42
  */
38
- export function defaultExtensionDirs(conversationId, stateDir = join(homedir(), ".mikan")) {
39
- return [join(stateDir, "extensions", "global"), join(stateDir, "extensions", conversationId)];
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
+ ];
40
59
  }
41
60
  /**
42
61
  * List installed extensions without importing or activating them — safe for
@@ -46,9 +65,9 @@ export function defaultExtensionDirs(conversationId, stateDir = join(homedir(),
46
65
  export function listInstalledExtensions(dirs) {
47
66
  const infos = [];
48
67
  for (const dir of dirs) {
49
- for (const entrypoint of discoverExtensionEntrypoints(dir)) {
50
- const slug = extensionSlug(entrypoint);
51
- const manifest = readManifest(entrypoint);
68
+ for (const { entrypoint, rootDir } of discoverExtensionEntrypoints(dir)) {
69
+ const slug = extensionSlug(rootDir);
70
+ const manifest = readManifest(rootDir);
52
71
  infos.push({
53
72
  name: manifest.name ?? slug,
54
73
  slug,
@@ -56,7 +75,8 @@ export function listInstalledExtensions(dirs) {
56
75
  dir,
57
76
  version: manifest.version,
58
77
  description: manifest.description,
59
- skillNames: loadExtensionSkills(entrypoint, slug).map((skill) => skill.name),
78
+ skillNames: loadExtensionSkills(rootDir, slug).map((skill) => skill.name),
79
+ secrets: manifest.secrets ?? [],
60
80
  });
61
81
  }
62
82
  }
@@ -65,11 +85,11 @@ export function listInstalledExtensions(dirs) {
65
85
  function discoverExtensionEntrypoints(dir) {
66
86
  if (!existsSync(dir))
67
87
  return [];
68
- const entrypoints = [];
88
+ const found = [];
69
89
  for (const name of readdirSync(dir).toSorted()) {
70
90
  if (name.startsWith("."))
71
91
  continue;
72
- if (/^index\.(mjs|js)$/.test(name)) {
92
+ if (INDEX_FILE_PATTERN.test(name)) {
73
93
  // An index file at the scan root means the extension's contents were
74
94
  // copied into the scope directory itself; the slug would degenerate to
75
95
  // the scope name (e.g. the conversation id), mis-keying its data dir,
@@ -86,55 +106,150 @@ function discoverExtensionEntrypoints(dir) {
86
106
  continue;
87
107
  }
88
108
  if (stats.isFile() && EXTENSION_FILE_PATTERN.test(name)) {
89
- entrypoints.push(fullPath);
109
+ // Bare-file form: the file is both entrypoint and (its own) root.
110
+ found.push({ entrypoint: fullPath, rootDir: fullPath, slug: extensionSlug(fullPath) });
90
111
  continue;
91
112
  }
92
113
  if (stats.isDirectory()) {
93
- for (const candidate of ["index.mjs", "index.js"]) {
94
- const indexPath = join(fullPath, candidate);
95
- if (existsSync(indexPath)) {
96
- entrypoints.push(indexPath);
97
- break;
98
- }
114
+ const entrypoint = resolveDirectoryEntrypoint(fullPath);
115
+ if (entrypoint) {
116
+ found.push({ entrypoint, rootDir: fullPath, slug: extensionSlug(fullPath) });
99
117
  }
100
118
  }
101
119
  }
102
- return entrypoints;
120
+ return found;
103
121
  }
104
122
  /**
105
- * Filesystem-safe identifier for an extension, derived from its install
106
- * location (directory name for `<name>/index.mjs`, file basename otherwise).
107
- * The slug keys the extension's data dir, secrets vault, and schedule
108
- * ownership — installing the same extension globally and per-conversation
109
- * shares one slug and therefore one data dir.
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.
110
128
  */
111
- export function extensionSlug(entrypoint) {
112
- const base = /^index\.(mjs|js)$/.test(basename(entrypoint))
113
- ? basename(dirname(entrypoint))
114
- : basename(entrypoint).replace(EXTENSION_FILE_PATTERN, "");
115
- const slug = base
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
116
196
  .toLowerCase()
117
197
  .replace(/[^a-z0-9_-]+/g, "-")
118
198
  .replace(/^-+|-+$/g, "")
119
199
  .slice(0, 64);
120
- return slug || "extension";
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));
121
218
  }
122
219
  /** Sanitize an extension-chosen schedule name into a filename segment. */
123
220
  function scheduleNameSegment(name) {
124
- const segment = name
125
- .toLowerCase()
126
- .replace(/[^a-z0-9_-]+/g, "-")
127
- .replace(/^-+|-+$/g, "")
128
- .slice(0, 64);
221
+ const segment = sanitizeSegment(name);
129
222
  if (!segment)
130
223
  throw new Error(`Invalid schedule name: ${JSON.stringify(name)}`);
131
224
  return segment;
132
225
  }
133
- /** Read `manifest.json` next to a directory-form extension's entrypoint. */
134
- function readManifest(entrypoint) {
135
- if (!/^index\.(mjs|js)$/.test(basename(entrypoint)))
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)))
136
237
  return {};
137
- const manifestPath = join(dirname(entrypoint), "manifest.json");
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");
138
253
  if (!existsSync(manifestPath))
139
254
  return {};
140
255
  try {
@@ -158,10 +273,11 @@ function readManifest(entrypoint) {
158
273
  * Marked inline: extension files live under the host-only state dir, which
159
274
  * sandbox containers cannot read, so skill bodies must ride in the prompt.
160
275
  */
161
- function loadExtensionSkills(entrypoint, slug) {
162
- if (!/^index\.(mjs|js)$/.test(basename(entrypoint)))
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)))
163
279
  return [];
164
- const skillsDir = join(dirname(entrypoint), "skills");
280
+ const skillsDir = join(rootDir, "skills");
165
281
  if (!existsSync(skillsDir))
166
282
  return [];
167
283
  const result = loadSkillsFromDir({ dir: skillsDir, source: `extension:${slug}` });
@@ -176,43 +292,35 @@ const SCHEDULE_FILE_SUFFIX = ".json";
176
292
  function schedulePrefix(slug, conversationId) {
177
293
  return `ext.${slug}.${scheduleNameSegment(conversationId)}.`;
178
294
  }
179
- function payloadFromSpec(spec, conversationId) {
180
- if (spec.type === "periodic") {
181
- if (!spec.schedule || !spec.timezone) {
182
- throw new Error("periodic schedule requires schedule and timezone");
183
- }
184
- return {
185
- type: "periodic",
186
- conversationId,
187
- text: spec.text,
188
- schedule: spec.schedule,
189
- timezone: spec.timezone,
190
- ...(spec.platform ? { platform: spec.platform } : {}),
191
- };
192
- }
193
- if (!spec.at)
194
- throw new Error("one-shot schedule requires at");
195
- return {
196
- type: "one-shot",
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,
197
300
  conversationId,
198
301
  text: spec.text,
199
- at: spec.at,
200
- ...(spec.platform ? { platform: spec.platform } : {}),
201
- };
302
+ platform: spec.platform ?? defaultPlatform,
303
+ ...(spec.type === "periodic"
304
+ ? { schedule: spec.schedule, timezone: spec.timezone }
305
+ : { at: spec.at }),
306
+ });
202
307
  }
203
308
  function specFromPayload(payload) {
204
309
  if (payload.type === "periodic") {
205
310
  return {
206
311
  type: "periodic",
207
- schedule: payload.schedule ?? "",
208
- timezone: payload.timezone ?? "",
312
+ schedule: payload.schedule,
313
+ timezone: payload.timezone,
209
314
  text: payload.text,
210
315
  ...(payload.platform ? { platform: payload.platform } : {}),
211
316
  };
212
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.
213
321
  return {
214
322
  type: "one-shot",
215
- at: payload.at ?? "",
323
+ at: payload.type === "one-shot" ? payload.at : "",
216
324
  text: payload.text,
217
325
  ...(payload.platform ? { platform: payload.platform } : {}),
218
326
  };
@@ -222,20 +330,42 @@ function buildExtensionApi(params) {
222
330
  const { name, slug, registry, context, services } = params;
223
331
  const stateDir = services.stateDir ?? join(homedir(), ".mikan");
224
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;
225
338
  const requireScheduleStore = () => {
226
339
  if (!services.scheduleStore) {
227
340
  throw new Error("api.schedules is unavailable: this context provides no schedule store");
228
341
  }
229
342
  return services.scheduleStore;
230
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}`;
231
351
  return {
232
352
  on: (hook, handler) => registry.register(name, hook, handler),
233
353
  registerTool: (tool) => registry.registerTool(tool),
354
+ registerCommand: (command) => registry.registerCommand(name, command),
355
+ onDispose: (disposer) => registry.registerDisposer(name, disposer),
234
356
  log: (message) => log.logInfo(`[extension:${name}] ${message}`),
235
357
  context,
236
358
  paths: {
237
359
  get dataDir() {
238
- const dir = join(stateDir, "extension-data", slug);
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);
239
369
  mkdirSync(dir, { recursive: true });
240
370
  return dir;
241
371
  },
@@ -246,40 +376,140 @@ function buildExtensionApi(params) {
246
376
  },
247
377
  schedules: {
248
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
+ }
249
387
  const store = requireScheduleStore();
250
- const filename = `${schedulePrefix(slug, conversationId)}${scheduleNameSegment(scheduleName)}${SCHEDULE_FILE_SUFFIX}`;
251
- await store.write(filename, payloadFromSpec(spec, conversationId));
388
+ await store.write(scheduleFilename(scheduleName), payloadFromSpec(spec, conversationId, ownPlatform));
389
+ await services.callbackScheduleStore?.delete(slug, nameSegment);
252
390
  },
253
391
  delete: async (scheduleName) => {
254
- const store = requireScheduleStore();
255
- const filename = `${schedulePrefix(slug, conversationId)}${scheduleNameSegment(scheduleName)}${SCHEDULE_FILE_SUFFIX}`;
256
- return store.delete(filename);
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;
257
398
  },
258
399
  list: async () => {
259
- const store = requireScheduleStore();
260
- const prefix = schedulePrefix(slug, conversationId);
400
+ if (!services.scheduleStore && !services.callbackScheduleStore)
401
+ requireScheduleStore();
261
402
  const infos = [];
262
- for (const entry of await store.list()) {
263
- if (!entry.filename.startsWith(prefix))
264
- continue;
265
- if (!entry.filename.endsWith(SCHEDULE_FILE_SUFFIX))
266
- continue;
267
- infos.push({
268
- name: entry.filename.slice(prefix.length, -SCHEDULE_FILE_SUFFIX.length),
269
- spec: specFromPayload(entry.payload),
270
- });
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)));
271
418
  }
272
419
  return infos;
273
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
+ },
274
430
  },
275
- notify: async (text) => {
431
+ notify: async (text, options) => {
276
432
  if (!services.postMessage) {
277
433
  throw new Error("api.notify is unavailable: this context provides no platform messaging");
278
434
  }
279
- await services.postMessage(conversationId, text);
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
+ });
280
508
  },
281
509
  };
282
510
  }
511
+ /** Monotonic suffix so rapid triggerRun calls in one process never collide. */
512
+ let runCounter = 0;
283
513
  function resolveActivate(moduleExports) {
284
514
  if (!moduleExports || typeof moduleExports !== "object")
285
515
  return undefined;
@@ -309,49 +539,175 @@ export async function loadExtensions(options) {
309
539
  const errors = [];
310
540
  const skills = [];
311
541
  const services = options.services ?? {};
312
- for (const dir of options.dirs) {
313
- for (const entrypoint of discoverExtensionEntrypoints(dir)) {
314
- try {
315
- const moduleUrl = `${pathToFileURL(entrypoint).href}?t=${Date.now()}`;
316
- const moduleExports = await import(moduleUrl);
317
- const extension = resolveActivate(moduleExports);
318
- if (!extension) {
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) {
319
556
  errors.push({
320
557
  path: entrypoint,
321
- error: "extension must export an activate function (default or named)",
558
+ error: `missing required secrets: ${missing.join(", ")} — provision them in the admin ` +
559
+ `portal or in <stateDir>/vaults/extensions/${slug}/env`,
322
560
  });
323
561
  continue;
324
562
  }
325
- const slug = extensionSlug(entrypoint);
326
- const manifest = readManifest(entrypoint);
327
- const name = manifest.name ?? extension.name ?? slug;
328
- const api = buildExtensionApi({
329
- name,
330
- slug,
331
- registry,
332
- context: options.context,
333
- services,
334
- });
335
- await extension.activate(api);
336
- const extensionSkills = loadExtensionSkills(entrypoint, slug);
337
- skills.push(...extensionSkills);
338
- extensions.push({
339
- name,
340
- path: entrypoint,
341
- slug,
342
- version: manifest.version,
343
- description: manifest.description,
344
- skills: extensionSkills,
345
- });
346
563
  }
347
- catch (err) {
564
+ const moduleExports = await importExtensionModule(entrypoint);
565
+ const extension = resolveActivate(moduleExports);
566
+ if (!extension) {
348
567
  errors.push({
349
568
  path: entrypoint,
350
- error: err instanceof Error ? err.message : String(err),
569
+ error: "extension must export an activate function (default or named)",
351
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
+ const disposer = await extension.activate(api);
582
+ if (typeof disposer === "function")
583
+ registry.registerDisposer(name, disposer);
584
+ const extensionSkills = loadExtensionSkills(rootDir, slug);
585
+ skills.push(...extensionSkills);
586
+ extensions.push({
587
+ name,
588
+ path: entrypoint,
589
+ slug,
590
+ version: manifest.version,
591
+ description: manifest.description,
592
+ skills: extensionSkills,
593
+ });
594
+ }
595
+ catch (err) {
596
+ errors.push({
597
+ path: entrypoint,
598
+ error: err instanceof Error ? err.message : String(err),
599
+ });
600
+ }
601
+ }
602
+ return { registry, extensions, errors, skills, dispose: () => registry.dispose() };
603
+ }
604
+ /**
605
+ * Everything to activate, in final order, with at most one entry per slug.
606
+ *
607
+ * Deduplication happens here rather than at activation time on purpose. The
608
+ * slug keys an extension's data dir, secrets, and schedules, so activating two
609
+ * copies of one extension would have them fight over the same state — and the
610
+ * registry's first-wins rule for commands would silently pick the opposite
611
+ * copy from the one that ran its hooks. Resolving to a single winner before
612
+ * anything is imported keeps those decisions consistent.
613
+ *
614
+ * Precedence follows scan order, so the narrowest scope wins: global
615
+ * directories first, then the conversation's, then explicit roots.
616
+ */
617
+ function collectExtensions(options) {
618
+ const bySlug = new Map();
619
+ const candidates = [
620
+ ...options.dirs.flatMap(discoverExtensionEntrypoints),
621
+ ...(options.roots ?? []).flatMap(resolveExtensionRoot),
622
+ ];
623
+ for (const candidate of candidates) {
624
+ const shadowed = bySlug.get(candidate.slug);
625
+ if (shadowed && shadowed.rootDir !== candidate.rootDir) {
626
+ log.logInfo(`Extension "${candidate.slug}" from ${candidate.rootDir} shadows ${shadowed.rootDir}`);
627
+ }
628
+ bySlug.set(candidate.slug, candidate);
629
+ }
630
+ return [...bySlug.values()];
631
+ }
632
+ /** Resolve one explicit extension root (directory with an entrypoint, or a bare file). */
633
+ function resolveExtensionRoot(rootDir) {
634
+ let stats;
635
+ try {
636
+ stats = statSync(rootDir);
637
+ }
638
+ catch {
639
+ log.logWarning(`Extension path does not exist: ${rootDir}`);
640
+ return [];
641
+ }
642
+ if (stats.isFile()) {
643
+ return EXTENSION_FILE_PATTERN.test(basename(rootDir))
644
+ ? [{ entrypoint: rootDir, rootDir, slug: extensionSlug(rootDir) }]
645
+ : [];
646
+ }
647
+ const entrypoint = resolveDirectoryEntrypoint(rootDir);
648
+ if (!entrypoint) {
649
+ log.logWarning(`No extension entrypoint in ${rootDir}`, "expected an index.{mjs,js,ts,mts} or a package.json with mikan.extensions");
650
+ return [];
651
+ }
652
+ return [{ entrypoint, rootDir, slug: extensionSlug(rootDir) }];
653
+ }
654
+ /**
655
+ * Validate an extension source path (a directory or a single file) WITHOUT
656
+ * activating it: resolves the entrypoint (package.json `mikan.extensions`,
657
+ * index file, or the file itself), imports it, and checks it exports an
658
+ * `activate` function. Used by `mikan ext install` as a preflight and by
659
+ * `mikan ext validate`. Importing runs top-level module code but not
660
+ * `activate`, so there are no schedule/tool side effects.
661
+ */
662
+ export async function validateExtension(sourcePath) {
663
+ const errors = [];
664
+ const warnings = [];
665
+ const rootDir = sourcePath.replace(/[/\\]+$/, "");
666
+ const base = basename(rootDir);
667
+ if (INDEX_FILE_PATTERN.test(base)) {
668
+ warnings.push("Entry is a bare index file; install into a named directory so the slug is stable.");
669
+ }
670
+ let entrypoint;
671
+ if (!existsSync(rootDir)) {
672
+ errors.push(`Path does not exist: ${rootDir}`);
673
+ }
674
+ else if (statSync(rootDir).isDirectory()) {
675
+ entrypoint = resolveDirectoryEntrypoint(rootDir);
676
+ if (!entrypoint) {
677
+ errors.push("No entrypoint found: expected package.json with a mikan.extensions entry, or an index.{mjs,js,ts,mts}.");
678
+ }
679
+ }
680
+ else if (EXTENSION_FILE_PATTERN.test(base)) {
681
+ entrypoint = rootDir;
682
+ }
683
+ else {
684
+ errors.push(`Not an extension file (expected .mjs/.js/.ts/.mts): ${rootDir}`);
685
+ }
686
+ const slug = extensionSlug(rootDir);
687
+ const manifest = readManifest(rootDir);
688
+ const skillNames = loadExtensionSkills(rootDir, slug).map((skill) => skill.name);
689
+ if (entrypoint) {
690
+ try {
691
+ const moduleExports = await importExtensionModule(entrypoint);
692
+ if (!resolveActivate(moduleExports)) {
693
+ errors.push("Module does not export an activate function (default or named).");
352
694
  }
353
695
  }
696
+ catch (err) {
697
+ errors.push(`Failed to import: ${err instanceof Error ? err.message : String(err)}`);
698
+ }
354
699
  }
355
- return { registry, extensions, errors, skills };
700
+ return {
701
+ ok: errors.length === 0,
702
+ slug,
703
+ name: manifest.name ?? slug,
704
+ version: manifest.version,
705
+ description: manifest.description,
706
+ entrypoint,
707
+ skillNames,
708
+ secrets: manifest.secrets ?? [],
709
+ errors,
710
+ warnings,
711
+ };
356
712
  }
357
713
  //# sourceMappingURL=loader.js.map