@geminixiang/mikan 1.0.0-beta.3 → 1.0.0-beta.30

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