@geminixiang/mikan 1.0.0-beta.39 → 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 (397) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +50 -23
  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 +2 -1
  7. package/dist/adapters/discord/bot.d.ts.map +1 -1
  8. package/dist/adapters/discord/bot.js +3 -3
  9. package/dist/adapters/discord/bot.js.map +1 -1
  10. package/dist/adapters/discord/context.d.ts +2 -1
  11. package/dist/adapters/discord/context.d.ts.map +1 -1
  12. package/dist/adapters/discord/context.js +1 -1
  13. package/dist/adapters/discord/context.js.map +1 -1
  14. package/dist/adapters/github/bot.d.ts +2 -1
  15. package/dist/adapters/github/bot.d.ts.map +1 -1
  16. package/dist/adapters/github/bot.js +11 -7
  17. package/dist/adapters/github/bot.js.map +1 -1
  18. package/dist/adapters/github/client.js +2 -2
  19. package/dist/adapters/github/client.js.map +1 -1
  20. package/dist/adapters/github/context.d.ts +4 -2
  21. package/dist/adapters/github/context.d.ts.map +1 -1
  22. package/dist/adapters/github/context.js +2 -2
  23. package/dist/adapters/github/context.js.map +1 -1
  24. package/dist/adapters/github/gcp-auth.js +2 -2
  25. package/dist/adapters/github/gcp-auth.js.map +1 -1
  26. package/dist/adapters/github/github-ops.d.ts +3 -2
  27. package/dist/adapters/github/github-ops.d.ts.map +1 -1
  28. package/dist/adapters/github/github-ops.js +1 -1
  29. package/dist/adapters/github/github-ops.js.map +1 -1
  30. package/dist/adapters/github/ids.d.ts.map +1 -1
  31. package/dist/adapters/github/ids.js +7 -3
  32. package/dist/adapters/github/ids.js.map +1 -1
  33. package/dist/adapters/github/repo.js +3 -3
  34. package/dist/adapters/github/repo.js.map +1 -1
  35. package/dist/adapters/github/types.d.ts +2 -1
  36. package/dist/adapters/github/types.d.ts.map +1 -1
  37. package/dist/adapters/github/types.js.map +1 -1
  38. package/dist/adapters/progressive-renderer.js +1 -1
  39. package/dist/adapters/progressive-renderer.js.map +1 -1
  40. package/dist/adapters/shared.js +4 -4
  41. package/dist/adapters/shared.js.map +1 -1
  42. package/dist/adapters/slack/blocks.d.ts.map +1 -1
  43. package/dist/adapters/slack/blocks.js +3 -1
  44. package/dist/adapters/slack/blocks.js.map +1 -1
  45. package/dist/adapters/slack/bot.d.ts +12 -2
  46. package/dist/adapters/slack/bot.d.ts.map +1 -1
  47. package/dist/adapters/slack/bot.js +70 -9
  48. package/dist/adapters/slack/bot.js.map +1 -1
  49. package/dist/adapters/slack/context.d.ts +2 -1
  50. package/dist/adapters/slack/context.d.ts.map +1 -1
  51. package/dist/adapters/slack/context.js +1 -0
  52. package/dist/adapters/slack/context.js.map +1 -1
  53. package/dist/adapters/slack/response-lifecycle.d.ts.map +1 -1
  54. package/dist/adapters/slack/response-lifecycle.js +4 -4
  55. package/dist/adapters/slack/response-lifecycle.js.map +1 -1
  56. package/dist/adapters/slack/session.d.ts.map +1 -1
  57. package/dist/adapters/slack/session.js +2 -3
  58. package/dist/adapters/slack/session.js.map +1 -1
  59. package/dist/adapters/slack/tools/attach.js +1 -1
  60. package/dist/adapters/slack/tools/attach.js.map +1 -1
  61. package/dist/adapters/telegram/bot.d.ts +2 -1
  62. package/dist/adapters/telegram/bot.d.ts.map +1 -1
  63. package/dist/adapters/telegram/bot.js +6 -6
  64. package/dist/adapters/telegram/bot.js.map +1 -1
  65. package/dist/adapters/telegram/context.d.ts +2 -1
  66. package/dist/adapters/telegram/context.d.ts.map +1 -1
  67. package/dist/adapters/telegram/context.js.map +1 -1
  68. package/dist/adapters/telegram/html.d.ts.map +1 -1
  69. package/dist/adapters/telegram/html.js +10 -7
  70. package/dist/adapters/telegram/html.js.map +1 -1
  71. package/dist/adapters/types.d.ts +4 -2
  72. package/dist/adapters/types.d.ts.map +1 -1
  73. package/dist/adapters/types.js.map +1 -1
  74. package/dist/agent-events.d.ts +3 -2
  75. package/dist/agent-events.d.ts.map +1 -1
  76. package/dist/agent-events.js +19 -1
  77. package/dist/agent-events.js.map +1 -1
  78. package/dist/agent.d.ts.map +1 -1
  79. package/dist/agent.js +34 -9
  80. package/dist/agent.js.map +1 -1
  81. package/dist/cli/arg-grammar.d.ts.map +1 -1
  82. package/dist/cli/arg-grammar.js +5 -3
  83. package/dist/cli/arg-grammar.js.map +1 -1
  84. package/dist/cli/boot.d.ts.map +1 -1
  85. package/dist/cli/boot.js +5 -3
  86. package/dist/cli/boot.js.map +1 -1
  87. package/dist/cli/download.d.ts.map +1 -1
  88. package/dist/cli/download.js +2 -0
  89. package/dist/cli/download.js.map +1 -1
  90. package/dist/cli/ext-dev.d.ts.map +1 -1
  91. package/dist/cli/ext-dev.js +4 -1
  92. package/dist/cli/ext-dev.js.map +1 -1
  93. package/dist/cli/ext.d.ts.map +1 -1
  94. package/dist/cli/ext.js +123 -23
  95. package/dist/cli/ext.js.map +1 -1
  96. package/dist/cli/office.d.ts.map +1 -1
  97. package/dist/cli/office.js +2 -0
  98. package/dist/cli/office.js.map +1 -1
  99. package/dist/cli/types.d.ts +0 -6
  100. package/dist/cli/types.d.ts.map +1 -1
  101. package/dist/cli/types.js.map +1 -1
  102. package/dist/commands/admin.js +1 -1
  103. package/dist/commands/admin.js.map +1 -1
  104. package/dist/commands/auto-reply.js +2 -2
  105. package/dist/commands/auto-reply.js.map +1 -1
  106. package/dist/commands/extensions.js +1 -1
  107. package/dist/commands/extensions.js.map +1 -1
  108. package/dist/commands/login.js +1 -1
  109. package/dist/commands/login.js.map +1 -1
  110. package/dist/commands/manifest.d.ts +7 -0
  111. package/dist/commands/manifest.d.ts.map +1 -1
  112. package/dist/commands/manifest.js +28 -0
  113. package/dist/commands/manifest.js.map +1 -1
  114. package/dist/commands/model.d.ts.map +1 -1
  115. package/dist/commands/model.js +4 -1
  116. package/dist/commands/model.js.map +1 -1
  117. package/dist/commands/new.js +1 -1
  118. package/dist/commands/new.js.map +1 -1
  119. package/dist/commands/sandbox.js +3 -3
  120. package/dist/commands/sandbox.js.map +1 -1
  121. package/dist/commands/session-view.d.ts.map +1 -1
  122. package/dist/commands/session-view.js +5 -2
  123. package/dist/commands/session-view.js.map +1 -1
  124. package/dist/commands/types.d.ts +1 -1
  125. package/dist/commands/types.d.ts.map +1 -1
  126. package/dist/commands/types.js.map +1 -1
  127. package/dist/config.js +4 -4
  128. package/dist/config.js.map +1 -1
  129. package/dist/env-manifest.d.ts +2 -0
  130. package/dist/env-manifest.d.ts.map +1 -1
  131. package/dist/env-manifest.js +11 -1
  132. package/dist/env-manifest.js.map +1 -1
  133. package/dist/events.d.ts.map +1 -1
  134. package/dist/events.js +7 -6
  135. package/dist/events.js.map +1 -1
  136. package/dist/execution-resolver.d.ts.map +1 -1
  137. package/dist/execution-resolver.js +3 -2
  138. package/dist/execution-resolver.js.map +1 -1
  139. package/dist/extension-schedules.d.ts +31 -0
  140. package/dist/extension-schedules.d.ts.map +1 -0
  141. package/dist/extension-schedules.js +229 -0
  142. package/dist/extension-schedules.js.map +1 -0
  143. package/dist/harness/auth.js +5 -5
  144. package/dist/harness/auth.js.map +1 -1
  145. package/dist/harness/event-format.d.ts +2 -0
  146. package/dist/harness/event-format.d.ts.map +1 -1
  147. package/dist/harness/event-format.js +2 -1
  148. package/dist/harness/event-format.js.map +1 -1
  149. package/dist/harness/extensions/loader.d.ts +2 -2
  150. package/dist/harness/extensions/loader.d.ts.map +1 -1
  151. package/dist/harness/extensions/loader.js +135 -33
  152. package/dist/harness/extensions/loader.js.map +1 -1
  153. package/dist/harness/extensions/registry.d.ts +33 -1
  154. package/dist/harness/extensions/registry.d.ts.map +1 -1
  155. package/dist/harness/extensions/registry.js +79 -2
  156. package/dist/harness/extensions/registry.js.map +1 -1
  157. package/dist/harness/extensions/types.d.ts +165 -21
  158. package/dist/harness/extensions/types.d.ts.map +1 -1
  159. package/dist/harness/extensions/types.js.map +1 -1
  160. package/dist/harness/index.d.ts +2 -2
  161. package/dist/harness/index.d.ts.map +1 -1
  162. package/dist/harness/index.js +1 -1
  163. package/dist/harness/index.js.map +1 -1
  164. package/dist/harness/models.d.ts.map +1 -1
  165. package/dist/harness/models.js +36 -24
  166. package/dist/harness/models.js.map +1 -1
  167. package/dist/harness/runner.js +2 -2
  168. package/dist/harness/runner.js.map +1 -1
  169. package/dist/harness/session-store.d.ts.map +1 -1
  170. package/dist/harness/session-store.js +9 -7
  171. package/dist/harness/session-store.js.map +1 -1
  172. package/dist/harness/skills.js +3 -3
  173. package/dist/harness/skills.js.map +1 -1
  174. package/dist/harness/subagent-profiles.js +2 -2
  175. package/dist/harness/subagent-profiles.js.map +1 -1
  176. package/dist/harness/subagent-runner.js +3 -3
  177. package/dist/harness/subagent-runner.js.map +1 -1
  178. package/dist/index.d.ts +8 -8
  179. package/dist/index.d.ts.map +1 -1
  180. package/dist/index.js +5 -5
  181. package/dist/index.js.map +1 -1
  182. package/dist/main.js +58 -9
  183. package/dist/main.js.map +1 -1
  184. package/dist/observability/instrument.js +1 -1
  185. package/dist/observability/instrument.js.map +1 -1
  186. package/dist/observability/sentry.js +1 -1
  187. package/dist/observability/sentry.js.map +1 -1
  188. package/dist/office/index.d.ts +1 -1
  189. package/dist/office/index.d.ts.map +1 -1
  190. package/dist/office/index.js +1 -1
  191. package/dist/office/index.js.map +1 -1
  192. package/dist/office/layout.d.ts +7 -0
  193. package/dist/office/layout.d.ts.map +1 -1
  194. package/dist/office/layout.js +10 -1
  195. package/dist/office/layout.js.map +1 -1
  196. package/dist/office/registry.d.ts.map +1 -1
  197. package/dist/office/registry.js +7 -5
  198. package/dist/office/registry.js.map +1 -1
  199. package/dist/packages/materialize.js +10 -3
  200. package/dist/packages/materialize.js.map +1 -1
  201. package/dist/packages/source.d.ts +6 -0
  202. package/dist/packages/source.d.ts.map +1 -1
  203. package/dist/packages/source.js +14 -2
  204. package/dist/packages/source.js.map +1 -1
  205. package/dist/packages/types.d.ts +5 -3
  206. package/dist/packages/types.d.ts.map +1 -1
  207. package/dist/packages/types.js.map +1 -1
  208. package/dist/provisioner.js +5 -5
  209. package/dist/provisioner.js.map +1 -1
  210. package/dist/runtime/conversation-runtime.d.ts.map +1 -1
  211. package/dist/runtime/conversation-runtime.js +44 -2
  212. package/dist/runtime/conversation-runtime.js.map +1 -1
  213. package/dist/runtime/types.d.ts +10 -2
  214. package/dist/runtime/types.d.ts.map +1 -1
  215. package/dist/runtime/types.js.map +1 -1
  216. package/dist/sandbox/cloudflare.js +1 -1
  217. package/dist/sandbox/cloudflare.js.map +1 -1
  218. package/dist/sandbox/container.js +1 -2
  219. package/dist/sandbox/container.js.map +1 -1
  220. package/dist/sandbox/firecracker.js +1 -1
  221. package/dist/sandbox/firecracker.js.map +1 -1
  222. package/dist/sandbox/gondolin.d.ts.map +1 -1
  223. package/dist/sandbox/gondolin.js +1 -2
  224. package/dist/sandbox/gondolin.js.map +1 -1
  225. package/dist/sandbox/host.d.ts.map +1 -1
  226. package/dist/sandbox/host.js +4 -5
  227. package/dist/sandbox/host.js.map +1 -1
  228. package/dist/sandbox/index.js +1 -1
  229. package/dist/sandbox/index.js.map +1 -1
  230. package/dist/sandbox/utils.d.ts +2 -0
  231. package/dist/sandbox/utils.d.ts.map +1 -1
  232. package/dist/sandbox/utils.js +30 -1
  233. package/dist/sandbox/utils.js.map +1 -1
  234. package/dist/sessions/chat-history-sync.d.ts.map +1 -1
  235. package/dist/sessions/chat-history-sync.js +9 -8
  236. package/dist/sessions/chat-history-sync.js.map +1 -1
  237. package/dist/sessions/conversation-log.d.ts.map +1 -1
  238. package/dist/sessions/conversation-log.js +5 -2
  239. package/dist/sessions/conversation-log.js.map +1 -1
  240. package/dist/sessions/history-line.d.ts +9 -0
  241. package/dist/sessions/history-line.d.ts.map +1 -1
  242. package/dist/sessions/history-line.js +22 -1
  243. package/dist/sessions/history-line.js.map +1 -1
  244. package/dist/sessions/session-key.d.ts +5 -12
  245. package/dist/sessions/session-key.d.ts.map +1 -1
  246. package/dist/sessions/session-key.js +23 -0
  247. package/dist/sessions/session-key.js.map +1 -1
  248. package/dist/sessions/store.d.ts +2 -6
  249. package/dist/sessions/store.d.ts.map +1 -1
  250. package/dist/sessions/store.js +16 -16
  251. package/dist/sessions/store.js.map +1 -1
  252. package/dist/sessions/types.d.ts +2 -1
  253. package/dist/sessions/types.d.ts.map +1 -1
  254. package/dist/sessions/types.js.map +1 -1
  255. package/dist/tools/bash.js +1 -1
  256. package/dist/tools/bash.js.map +1 -1
  257. package/dist/tools/edit.d.ts.map +1 -1
  258. package/dist/tools/edit.js +4 -1
  259. package/dist/tools/edit.js.map +1 -1
  260. package/dist/tools/event.js +1 -1
  261. package/dist/tools/event.js.map +1 -1
  262. package/dist/tools/generate-image.js +3 -3
  263. package/dist/tools/generate-image.js.map +1 -1
  264. package/dist/tools/read.js +4 -4
  265. package/dist/tools/read.js.map +1 -1
  266. package/dist/tools/subagent.d.ts.map +1 -1
  267. package/dist/tools/subagent.js +9 -2
  268. package/dist/tools/subagent.js.map +1 -1
  269. package/dist/tools/types.d.ts +0 -26
  270. package/dist/tools/types.d.ts.map +1 -1
  271. package/dist/tools/types.js.map +1 -1
  272. package/dist/trigger.d.ts +2 -1
  273. package/dist/trigger.d.ts.map +1 -1
  274. package/dist/trigger.js.map +1 -1
  275. package/dist/types.d.ts +108 -16
  276. package/dist/types.d.ts.map +1 -1
  277. package/dist/types.js +2 -2
  278. package/dist/types.js.map +1 -1
  279. package/dist/utils/file-guards.d.ts +9 -0
  280. package/dist/utils/file-guards.d.ts.map +1 -1
  281. package/dist/utils/file-guards.js +44 -1
  282. package/dist/utils/file-guards.js.map +1 -1
  283. package/dist/vault/disabled.d.ts.map +1 -1
  284. package/dist/vault/disabled.js +3 -0
  285. package/dist/vault/disabled.js.map +1 -1
  286. package/dist/vault/index.d.ts +29 -0
  287. package/dist/vault/index.d.ts.map +1 -1
  288. package/dist/vault/index.js +68 -4
  289. package/dist/vault/index.js.map +1 -1
  290. package/dist/vault/types.d.ts +2 -0
  291. package/dist/vault/types.d.ts.map +1 -1
  292. package/dist/vault/types.js.map +1 -1
  293. package/dist/web/admin/portal.d.ts +1 -1
  294. package/dist/web/admin/portal.d.ts.map +1 -1
  295. package/dist/web/admin/portal.js +194 -22
  296. package/dist/web/admin/portal.js.map +1 -1
  297. package/dist/web/admin/provider-models.js +1 -1
  298. package/dist/web/admin/provider-models.js.map +1 -1
  299. package/dist/web/login/oauth.js +1 -1
  300. package/dist/web/login/oauth.js.map +1 -1
  301. package/dist/web/login/portal.d.ts +1 -1
  302. package/dist/web/login/portal.d.ts.map +1 -1
  303. package/dist/web/login/portal.js +13 -36
  304. package/dist/web/login/portal.js.map +1 -1
  305. package/dist/web/portal-shell.d.ts +17 -0
  306. package/dist/web/portal-shell.d.ts.map +1 -1
  307. package/dist/web/portal-shell.js +66 -1
  308. package/dist/web/portal-shell.js.map +1 -1
  309. package/dist/web/server.d.ts +3 -2
  310. package/dist/web/server.d.ts.map +1 -1
  311. package/dist/web/server.js +3 -3
  312. package/dist/web/server.js.map +1 -1
  313. package/dist/web/session-view/portal.d.ts +1 -1
  314. package/dist/web/session-view/portal.d.ts.map +1 -1
  315. package/dist/web/session-view/portal.js +10 -12
  316. package/dist/web/session-view/portal.js.map +1 -1
  317. package/dist/web/session-view/service.d.ts.map +1 -1
  318. package/dist/web/session-view/service.js +11 -6
  319. package/dist/web/session-view/service.js.map +1 -1
  320. package/dist/web/session-view/types.d.ts +0 -4
  321. package/dist/web/session-view/types.d.ts.map +1 -1
  322. package/dist/web/session-view/types.js.map +1 -1
  323. package/dist/web/token-store.js +1 -1
  324. package/dist/web/token-store.js.map +1 -1
  325. package/package.json +8 -17
  326. package/dist/cli/ext-git.d.ts +0 -17
  327. package/dist/cli/ext-git.d.ts.map +0 -1
  328. package/dist/cli/ext-git.js +0 -107
  329. package/dist/cli/ext-git.js.map +0 -1
  330. package/dist/commands/parse.d.ts +0 -7
  331. package/dist/commands/parse.d.ts.map +0 -1
  332. package/dist/commands/parse.js +0 -14
  333. package/dist/commands/parse.js.map +0 -1
  334. package/dist/commands/text.d.ts +0 -2
  335. package/dist/commands/text.d.ts.map +0 -1
  336. package/dist/commands/text.js +0 -16
  337. package/dist/commands/text.js.map +0 -1
  338. package/dist/harness/extensions/blockkit.d.ts +0 -19
  339. package/dist/harness/extensions/blockkit.d.ts.map +0 -1
  340. package/dist/harness/extensions/blockkit.js +0 -42
  341. package/dist/harness/extensions/blockkit.js.map +0 -1
  342. package/dist/sandbox/path-context.d.ts +0 -3
  343. package/dist/sandbox/path-context.d.ts.map +0 -1
  344. package/dist/sandbox/path-context.js +0 -30
  345. package/dist/sandbox/path-context.js.map +0 -1
  346. package/dist/sessions/metadata.d.ts +0 -3
  347. package/dist/sessions/metadata.d.ts.map +0 -1
  348. package/dist/sessions/metadata.js +0 -11
  349. package/dist/sessions/metadata.js.map +0 -1
  350. package/dist/sessions/policy.d.ts +0 -6
  351. package/dist/sessions/policy.d.ts.map +0 -1
  352. package/dist/sessions/policy.js +0 -25
  353. package/dist/sessions/policy.js.map +0 -1
  354. package/dist/tools/truncate.d.ts +0 -33
  355. package/dist/tools/truncate.d.ts.map +0 -1
  356. package/dist/tools/truncate.js +0 -184
  357. package/dist/tools/truncate.js.map +0 -1
  358. package/dist/utils/date.d.ts +0 -10
  359. package/dist/utils/date.d.ts.map +0 -1
  360. package/dist/utils/date.js +0 -23
  361. package/dist/utils/date.js.map +0 -1
  362. package/dist/utils/env.d.ts +0 -3
  363. package/dist/utils/env.d.ts.map +0 -1
  364. package/dist/utils/env.js +0 -12
  365. package/dist/utils/env.js.map +0 -1
  366. package/dist/utils/fs-atomic.d.ts +0 -10
  367. package/dist/utils/fs-atomic.d.ts.map +0 -1
  368. package/dist/utils/fs-atomic.js +0 -45
  369. package/dist/utils/fs-atomic.js.map +0 -1
  370. package/dist/utils/html.d.ts +0 -2
  371. package/dist/utils/html.d.ts.map +0 -1
  372. package/dist/utils/html.js +0 -4
  373. package/dist/utils/html.js.map +0 -1
  374. package/dist/utils/http-body.d.ts +0 -10
  375. package/dist/utils/http-body.d.ts.map +0 -1
  376. package/dist/utils/http-body.js +0 -34
  377. package/dist/utils/http-body.js.map +0 -1
  378. package/dist/vault/injection.d.ts +0 -12
  379. package/dist/vault/injection.d.ts.map +0 -1
  380. package/dist/vault/injection.js +0 -30
  381. package/dist/vault/injection.js.map +0 -1
  382. package/dist/vault/policy.d.ts +0 -20
  383. package/dist/vault/policy.d.ts.map +0 -1
  384. package/dist/vault/policy.js +0 -20
  385. package/dist/vault/policy.js.map +0 -1
  386. package/dist/web/agent-events/portal.d.ts +0 -3
  387. package/dist/web/agent-events/portal.d.ts.map +0 -1
  388. package/dist/web/agent-events/portal.js +0 -19
  389. package/dist/web/agent-events/portal.js.map +0 -1
  390. package/dist/web/request.d.ts +0 -3
  391. package/dist/web/request.d.ts.map +0 -1
  392. package/dist/web/request.js +0 -13
  393. package/dist/web/request.js.map +0 -1
  394. package/dist/web/session-view/command.d.ts +0 -4
  395. package/dist/web/session-view/command.d.ts.map +0 -1
  396. package/dist/web/session-view/command.js +0 -10
  397. package/dist/web/session-view/command.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"arg-grammar.d.ts","sourceRoot":"","sources":["../../src/cli/arg-grammar.ts"],"names":[],"mappings":"AAaA,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EAAE,EACd,CAAC,EAAE,MAAM,EACT,IAAI,EAAE,MAAM,GACX;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAKlD;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,IAAI,GAAE,MAAM,EAA0B,EACtC,QAAQ,GAAE,MAAM,GAAG,SAAgC,GAClD,MAAM,CAYR;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C"}
1
+ {"version":3,"file":"arg-grammar.d.ts","sourceRoot":"","sources":["../../src/cli/arg-grammar.ts"],"names":[],"mappings":"AAaA,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EAAE,EACd,CAAC,EAAE,MAAM,EACT,IAAI,EAAE,MAAM,GACX;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAMlD;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,IAAI,GAAE,MAAM,EAA0B,EACtC,QAAQ,GAAE,MAAM,GAAG,SAAgC,GAClD,MAAM,CAYR;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C"}
@@ -7,9 +7,9 @@
7
7
  * state dir, and an early `--state-dir` probe for import-time consumers
8
8
  * (Sentry instrumentation) that must not load the boot path.
9
9
  */
10
- import { homedir } from "os";
11
- import { join, resolve } from "path";
12
- import { readEnv } from "../utils/env.js";
10
+ import { homedir } from "node:os";
11
+ import { join, resolve } from "node:path";
12
+ import { readEnv } from "../env-manifest.js";
13
13
  export function defaultStateDir() {
14
14
  return join(homedir(), ".mikan");
15
15
  }
@@ -20,6 +20,8 @@ export function defaultStateDir() {
20
20
  */
21
21
  export function takeValueFlag(args, i, name) {
22
22
  const arg = args[i];
23
+ if (arg === undefined)
24
+ return undefined;
23
25
  if (arg === name)
24
26
  return { value: args[i + 1] ?? "", lastIndex: i + 1 };
25
27
  if (arg.startsWith(name + "="))
@@ -1 +1 @@
1
- {"version":3,"file":"arg-grammar.js","sourceRoot":"","sources":["../../src/cli/arg-grammar.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,MAAM,UAAU,eAAe;IAC7B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AACnC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAc,EACd,CAAS,EACT,IAAY;IAEZ,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;IACxE,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,GAAG,GAAG,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IAC3F,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC7B,IAAI,GAAa,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EACtC,QAAQ,GAAuB,OAAO,CAAC,WAAW,CAAC;IAEnD,IAAI,SAA6B,CAAC;IAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC,EAAE,aAAa,CAAC,CAAC;QACpD,IAAI,KAAK,EAAE,CAAC;YACV,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC;YACxB,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC;QACtB,CAAC;IACH,CAAC;IACD,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC,SAAS,CAAC,CAAC;IACvD,IAAI,QAAQ;QAAE,OAAO,OAAO,CAAC,QAAQ,CAAC,CAAC;IACvC,OAAO,eAAe,EAAE,CAAC;AAC3B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,eAAe,CAAC,EAAE,CAAC,CAAC;AAC7B,CAAC","sourcesContent":["/**\n * Shared pieces of the CLI flag grammar.\n *\n * `resolveBoot` (cli/boot.ts) is the daemon's only full argv parser. This\n * module holds what other scanners must agree with it on: the value-flag\n * spelling (`--flag value` / `--flag=value`) via `takeValueFlag`, the default\n * state dir, and an early `--state-dir` probe for import-time consumers\n * (Sentry instrumentation) that must not load the boot path.\n */\nimport { homedir } from \"os\";\nimport { join, resolve } from \"path\";\nimport { readEnv } from \"../utils/env.js\";\n\nexport function defaultStateDir(): string {\n return join(homedir(), \".mikan\");\n}\n\n/**\n * Match `args[i]` against a value flag, accepting both `--name value` and\n * `--name=value`. Returns the raw value and the index of the last argv slot\n * consumed, or undefined when `args[i]` is not this flag.\n */\nexport function takeValueFlag(\n args: string[],\n i: number,\n name: string,\n): { value: string; lastIndex: number } | undefined {\n const arg = args[i];\n if (arg === name) return { value: args[i + 1] ?? \"\", lastIndex: i + 1 };\n if (arg.startsWith(name + \"=\")) return { value: arg.slice(name.length + 1), lastIndex: i };\n return undefined;\n}\n\n/**\n * Effective state dir — the ONE place its precedence is decided:\n * `--state-dir` flag (last occurrence wins) > STATE_DIR / MIKAN_STATE_DIR\n * env > `~/.mikan`. Boot writes the resolved value back into the env\n * (setEnvAliases) purely as a compatibility channel for code that runs\n * without access to the boot plan — see `effectiveStateDir`.\n */\nexport function resolveStateDir(\n args: string[] = process.argv.slice(2),\n envValue: string | undefined = readEnv(\"STATE_DIR\"),\n): string {\n let flagValue: string | undefined;\n for (let i = 0; i < args.length; i++) {\n const taken = takeValueFlag(args, i, \"--state-dir\");\n if (taken) {\n flagValue = taken.value;\n i = taken.lastIndex;\n }\n }\n if (flagValue !== undefined) return resolve(flagValue);\n if (envValue) return resolve(envValue);\n return defaultStateDir();\n}\n\n/**\n * State dir for post-boot readers: the env channel (which boot populated\n * from the resolved plan) with the shared default. Never re-reads argv —\n * by the time this runs, any `--state-dir` flag is already folded in.\n */\nexport function effectiveStateDir(): string {\n return resolveStateDir([]);\n}\n"]}
1
+ {"version":3,"file":"arg-grammar.js","sourceRoot":"","sources":["../../src/cli/arg-grammar.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,MAAM,UAAU,eAAe;IAC7B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AACnC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAc,EACd,CAAS,EACT,IAAY;IAEZ,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACxC,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;IACxE,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,GAAG,GAAG,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IAC3F,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC7B,IAAI,GAAa,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EACtC,QAAQ,GAAuB,OAAO,CAAC,WAAW,CAAC;IAEnD,IAAI,SAA6B,CAAC;IAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC,EAAE,aAAa,CAAC,CAAC;QACpD,IAAI,KAAK,EAAE,CAAC;YACV,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC;YACxB,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC;QACtB,CAAC;IACH,CAAC;IACD,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC,SAAS,CAAC,CAAC;IACvD,IAAI,QAAQ;QAAE,OAAO,OAAO,CAAC,QAAQ,CAAC,CAAC;IACvC,OAAO,eAAe,EAAE,CAAC;AAC3B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,eAAe,CAAC,EAAE,CAAC,CAAC;AAC7B,CAAC","sourcesContent":["/**\n * Shared pieces of the CLI flag grammar.\n *\n * `resolveBoot` (cli/boot.ts) is the daemon's only full argv parser. This\n * module holds what other scanners must agree with it on: the value-flag\n * spelling (`--flag value` / `--flag=value`) via `takeValueFlag`, the default\n * state dir, and an early `--state-dir` probe for import-time consumers\n * (Sentry instrumentation) that must not load the boot path.\n */\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport { readEnv } from \"../env-manifest.js\";\n\nexport function defaultStateDir(): string {\n return join(homedir(), \".mikan\");\n}\n\n/**\n * Match `args[i]` against a value flag, accepting both `--name value` and\n * `--name=value`. Returns the raw value and the index of the last argv slot\n * consumed, or undefined when `args[i]` is not this flag.\n */\nexport function takeValueFlag(\n args: string[],\n i: number,\n name: string,\n): { value: string; lastIndex: number } | undefined {\n const arg = args[i];\n if (arg === undefined) return undefined;\n if (arg === name) return { value: args[i + 1] ?? \"\", lastIndex: i + 1 };\n if (arg.startsWith(name + \"=\")) return { value: arg.slice(name.length + 1), lastIndex: i };\n return undefined;\n}\n\n/**\n * Effective state dir — the ONE place its precedence is decided:\n * `--state-dir` flag (last occurrence wins) > STATE_DIR / MIKAN_STATE_DIR\n * env > `~/.mikan`. Boot writes the resolved value back into the env\n * (setEnvAliases) purely as a compatibility channel for code that runs\n * without access to the boot plan — see `effectiveStateDir`.\n */\nexport function resolveStateDir(\n args: string[] = process.argv.slice(2),\n envValue: string | undefined = readEnv(\"STATE_DIR\"),\n): string {\n let flagValue: string | undefined;\n for (let i = 0; i < args.length; i++) {\n const taken = takeValueFlag(args, i, \"--state-dir\");\n if (taken) {\n flagValue = taken.value;\n i = taken.lastIndex;\n }\n }\n if (flagValue !== undefined) return resolve(flagValue);\n if (envValue) return resolve(envValue);\n return defaultStateDir();\n}\n\n/**\n * State dir for post-boot readers: the env channel (which boot populated\n * from the resolved plan) with the shared default. Never re-reads argv —\n * by the time this runs, any `--state-dir` flag is already folded in.\n */\nexport function effectiveStateDir(): string {\n return resolveStateDir([]);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"boot.d.ts","sourceRoot":"","sources":["../../src/cli/boot.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG3C,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,wBAAgB,WAAW,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,QAAQ,CA+D5E;AAED,wBAAgB,QAAQ,IAAI,MAAM,CAgCjC"}
1
+ {"version":3,"file":"boot.d.ts","sourceRoot":"","sources":["../../src/cli/boot.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG3C,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,wBAAgB,WAAW,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,QAAQ,CAgE5E;AAED,wBAAgB,QAAQ,IAAI,MAAM,CAgCjC"}
package/dist/cli/boot.js CHANGED
@@ -4,10 +4,10 @@
4
4
  * the grammar that actually drives the daemon is testable without spawning a
5
5
  * process; main.ts just executes the plan.
6
6
  *
7
- * Modes, highest priority first: `ext` (own grammar, never flag-parsed here),
8
- * `help`, `version`, `onboard`, `download`, `run`.
7
+ * Modes, highest priority first: `ext`, `office`, `env` (own grammars, never
8
+ * flag-parsed here), `help`, `version`, `onboard`, `download`, `run`.
9
9
  */
10
- import { join, resolve } from "path";
10
+ import { join, resolve } from "node:path";
11
11
  import { envSummaryLines } from "../env-manifest.js";
12
12
  import { parseSandboxArg } from "../sandbox/index.js";
13
13
  import { defaultStateDir, resolveStateDir, takeValueFlag } from "./arg-grammar.js";
@@ -31,6 +31,8 @@ export function resolveBoot(args = process.argv.slice(2)) {
31
31
  let onboard = false;
32
32
  for (let i = 0; i < args.length; i++) {
33
33
  const arg = args[i];
34
+ if (arg === undefined)
35
+ continue;
34
36
  let taken;
35
37
  if (arg === "--help" || arg === "-h") {
36
38
  help = true;
@@ -1 +1 @@
1
- {"version":3,"file":"boot.js","sourceRoot":"","sources":["../../src/cli/boot.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAGtD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAInF,MAAM,UAAU,WAAW,CAAC,IAAI,GAAa,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAChE,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC;QACnE,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;YACb,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACxD,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9D,QAAQ,EAAE,eAAe,EAAE;YAC3B,UAAU,EAAE,IAAI,CAAC,eAAe,EAAE,EAAE,WAAW,CAAC;YAChD,kBAAkB,EAAE,KAAK;YACzB,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;SAC1B,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,GAAkB,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC9C,IAAI,aAAiC,CAAC;IACtC,IAAI,eAAmC,CAAC;IACxC,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,KAAK,CAAC;QACV,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACrC,IAAI,GAAG,IAAI,CAAC;QACd,CAAC;aAAM,IAAI,GAAG,KAAK,WAAW,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YAC/D,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;aAAM,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;YAC/B,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;aAAM,IAAI,CAAC,KAAK,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC;YACzD,OAAO,GAAG,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACvC,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC;QACtB,CAAC;aAAM,IAAI,CAAC,KAAK,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC;YAC3D,mEAAmE;YACnE,8DAA8D;YAC9D,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC;QACtB,CAAC;aAAM,IAAI,CAAC,KAAK,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC;YAC1D,eAAe,GAAG,KAAK,CAAC,KAAK,CAAC;YAC9B,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC;QACtB,CAAC;aAAM,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAChC,aAAa,GAAG,GAAG,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,iBAAiB,GAAG,mCAAmC,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO;QACL,IAAI,EAAE,IAAI;YACR,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,OAAO;gBACP,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,OAAO;oBACP,CAAC,CAAC,SAAS;oBACX,CAAC,CAAC,eAAe;wBACf,CAAC,CAAC,UAAU;wBACZ,CAAC,CAAC,KAAK;QACf,QAAQ;QACR,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC;QAChF,kBAAkB,EAAE,aAAa,KAAK,SAAS;QAC/C,OAAO;QACP,eAAe;KAChB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6BP,eAAe,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;0CACY,CAAC;AAC3C,CAAC","sourcesContent":["/**\n * Boot resolution for the `mikan` binary: argv → a BootPlan saying which mode\n * to run and with what configuration. Pure — no side effects, no exits — so\n * the grammar that actually drives the daemon is testable without spawning a\n * process; main.ts just executes the plan.\n *\n * Modes, highest priority first: `ext` (own grammar, never flag-parsed here),\n * `help`, `version`, `onboard`, `download`, `run`.\n */\nimport { join, resolve } from \"path\";\nimport { envSummaryLines } from \"../env-manifest.js\";\nimport { parseSandboxArg } from \"../sandbox/index.js\";\nimport type { SandboxConfig } from \"../sandbox/types.js\";\nimport type { BootPlan } from \"./types.js\";\nimport { defaultStateDir, resolveStateDir, takeValueFlag } from \"./arg-grammar.js\";\n\nexport type { BootPlan } from \"./types.js\";\n\nexport function resolveBoot(args: string[] = process.argv.slice(2)): BootPlan {\n if (args[0] === \"ext\" || args[0] === \"office\" || args[0] === \"env\") {\n return {\n mode: args[0],\n ...(args[0] === \"ext\" ? { extArgs: args.slice(1) } : {}),\n ...(args[0] === \"office\" ? { officeArgs: args.slice(1) } : {}),\n stateDir: defaultStateDir(),\n workingDir: join(defaultStateDir(), \"workspace\"),\n workingDirExplicit: false,\n sandbox: { type: \"host\" },\n };\n }\n\n let sandbox: SandboxConfig = { type: \"host\" };\n let workingDirArg: string | undefined;\n let downloadChannel: string | undefined;\n let help = false;\n let version = false;\n let onboard = false;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n let taken;\n if (arg === \"--help\" || arg === \"-h\") {\n help = true;\n } else if (arg === \"--version\" || arg === \"-v\" || arg === \"-V\") {\n version = true;\n } else if (arg === \"--onboard\") {\n onboard = true;\n } else if ((taken = takeValueFlag(args, i, \"--sandbox\"))) {\n sandbox = parseSandboxArg(taken.value);\n i = taken.lastIndex;\n } else if ((taken = takeValueFlag(args, i, \"--state-dir\"))) {\n // Consumed here so its value never reads as the positional working\n // dir; the value itself is resolved by resolveStateDir below.\n i = taken.lastIndex;\n } else if ((taken = takeValueFlag(args, i, \"--download\"))) {\n downloadChannel = taken.value;\n i = taken.lastIndex;\n } else if (!arg.startsWith(\"-\")) {\n workingDirArg = arg;\n } else {\n throw new Error(`Unknown flag: ${arg}. Run \\`mikan --help\\` for usage.`);\n }\n }\n\n const stateDir = resolveStateDir(args);\n return {\n mode: help\n ? \"help\"\n : version\n ? \"version\"\n : onboard\n ? \"onboard\"\n : downloadChannel\n ? \"download\"\n : \"run\",\n stateDir,\n workingDir: workingDirArg ? resolve(workingDirArg) : join(stateDir, \"workspace\"),\n workingDirExplicit: workingDirArg !== undefined,\n sandbox,\n downloadChannel,\n };\n}\n\nexport function helpText(): string {\n return `mikan — multi-platform chat agent daemon\n\nUsage:\n mikan [options] [working-directory]\n Start the daemon. The working directory defaults to <state-dir>/workspace.\n mikan ext <install|validate|list|remove> …\n Manage extensions (run \\`mikan ext\\` for details).\n mikan office <list|claim> …\n Inspect conversation offices and claim legacy directories for a platform.\n mikan env\n Show the full environment-variable inventory and what is currently set.\n\nOptions:\n --state-dir <dir> State directory (settings.json, vaults, extensions).\n Default: ~/.mikan\n --sandbox <spec> Execution sandbox. One of:\n host\n container:<existing-container-name>\n image:<image[:tag]>\n gondolin:default\n firecracker:<vm-id>:<host-path>[:<ssh-user>[:<ssh-port>]]\n cloudflare:<sandbox-id>\n Default: host\n --onboard Create <state-dir>/settings.json from a template, then exit.\n --download <channel> Dump a Slack channel's history (Slack only), then exit.\n --version, -v Print the version.\n --help, -h Show this help.\n\nEnvironment (platform tokens select which chat adapters start):\n${envSummaryLines().join(\"\\n\")}\nRun \\`mikan env\\` for the full inventory.`;\n}\n"]}
1
+ {"version":3,"file":"boot.js","sourceRoot":"","sources":["../../src/cli/boot.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Boot resolution for the `mikan` binary: argv → a BootPlan saying which mode\n * to run and with what configuration. Pure — no side effects, no exits — so\n * the grammar that actually drives the daemon is testable without spawning a\n * process; main.ts just executes the plan.\n *\n * Modes, highest priority first: `ext`, `office`, `env` (own grammars, never\n * flag-parsed here), `help`, `version`, `onboard`, `download`, `run`.\n */\nimport { join, resolve } from \"node:path\";\nimport { envSummaryLines } from \"../env-manifest.js\";\nimport { parseSandboxArg } from \"../sandbox/index.js\";\nimport type { SandboxConfig } from \"../sandbox/types.js\";\nimport type { BootPlan } from \"./types.js\";\nimport { defaultStateDir, resolveStateDir, takeValueFlag } from \"./arg-grammar.js\";\n\nexport type { BootPlan } from \"./types.js\";\n\nexport function resolveBoot(args: string[] = process.argv.slice(2)): BootPlan {\n if (args[0] === \"ext\" || args[0] === \"office\" || args[0] === \"env\") {\n return {\n mode: args[0],\n ...(args[0] === \"ext\" ? { extArgs: args.slice(1) } : {}),\n ...(args[0] === \"office\" ? { officeArgs: args.slice(1) } : {}),\n stateDir: defaultStateDir(),\n workingDir: join(defaultStateDir(), \"workspace\"),\n workingDirExplicit: false,\n sandbox: { type: \"host\" },\n };\n }\n\n let sandbox: SandboxConfig = { type: \"host\" };\n let workingDirArg: string | undefined;\n let downloadChannel: string | undefined;\n let help = false;\n let version = false;\n let onboard = false;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === undefined) continue;\n let taken;\n if (arg === \"--help\" || arg === \"-h\") {\n help = true;\n } else if (arg === \"--version\" || arg === \"-v\" || arg === \"-V\") {\n version = true;\n } else if (arg === \"--onboard\") {\n onboard = true;\n } else if ((taken = takeValueFlag(args, i, \"--sandbox\"))) {\n sandbox = parseSandboxArg(taken.value);\n i = taken.lastIndex;\n } else if ((taken = takeValueFlag(args, i, \"--state-dir\"))) {\n // Consumed here so its value never reads as the positional working\n // dir; the value itself is resolved by resolveStateDir below.\n i = taken.lastIndex;\n } else if ((taken = takeValueFlag(args, i, \"--download\"))) {\n downloadChannel = taken.value;\n i = taken.lastIndex;\n } else if (!arg.startsWith(\"-\")) {\n workingDirArg = arg;\n } else {\n throw new Error(`Unknown flag: ${arg}. Run \\`mikan --help\\` for usage.`);\n }\n }\n\n const stateDir = resolveStateDir(args);\n return {\n mode: help\n ? \"help\"\n : version\n ? \"version\"\n : onboard\n ? \"onboard\"\n : downloadChannel\n ? \"download\"\n : \"run\",\n stateDir,\n workingDir: workingDirArg ? resolve(workingDirArg) : join(stateDir, \"workspace\"),\n workingDirExplicit: workingDirArg !== undefined,\n sandbox,\n downloadChannel,\n };\n}\n\nexport function helpText(): string {\n return `mikan — multi-platform chat agent daemon\n\nUsage:\n mikan [options] [working-directory]\n Start the daemon. The working directory defaults to <state-dir>/workspace.\n mikan ext <install|validate|list|remove> …\n Manage extensions (run \\`mikan ext\\` for details).\n mikan office <list|claim> …\n Inspect conversation offices and claim legacy directories for a platform.\n mikan env\n Show the full environment-variable inventory and what is currently set.\n\nOptions:\n --state-dir <dir> State directory (settings.json, vaults, extensions).\n Default: ~/.mikan\n --sandbox <spec> Execution sandbox. One of:\n host\n container:<existing-container-name>\n image:<image[:tag]>\n gondolin:default\n firecracker:<vm-id>:<host-path>[:<ssh-user>[:<ssh-port>]]\n cloudflare:<sandbox-id>\n Default: host\n --onboard Create <state-dir>/settings.json from a template, then exit.\n --download <channel> Dump a Slack channel's history (Slack only), then exit.\n --version, -v Print the version.\n --help, -h Show this help.\n\nEnvironment (platform tokens select which chat adapters start):\n${envSummaryLines().join(\"\\n\")}\nRun \\`mikan env\\` for the full inventory.`;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../../src/cli/download.ts"],"names":[],"mappings":"AA6BA,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAuFxF"}
1
+ {"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../../src/cli/download.ts"],"names":[],"mappings":"AA6BA,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwFxF"}
@@ -52,6 +52,8 @@ export async function downloadChannel(channelId, botToken) {
52
52
  console.error(`Fetching ${threadsToFetch.length} threads...`);
53
53
  for (let i = 0; i < threadsToFetch.length; i++) {
54
54
  const parent = threadsToFetch[i];
55
+ if (parent === undefined)
56
+ continue;
55
57
  console.error(` Thread ${i + 1}/${threadsToFetch.length} (${parent.reply_count} replies)...`);
56
58
  const replies = [];
57
59
  let threadCursor;
@@ -1 +1 @@
1
- {"version":3,"file":"download.js","sourceRoot":"","sources":["../../src/cli/download.ts"],"names":[],"mappings":"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","sourcesContent":["import { LogLevel, WebClient } from \"@slack/web-api\";\n\ninterface Message {\n ts: string;\n user?: string;\n text?: string;\n thread_ts?: string;\n reply_count?: number;\n files?: Array<{ name: string; url_private?: string }>;\n}\n\nfunction formatTs(ts: string): string {\n const date = new Date(parseFloat(ts) * 1000);\n return date\n .toISOString()\n .replace(\"T\", \" \")\n .replace(/\\.\\d+Z$/, \"\");\n}\n\nfunction formatMessage(ts: string, user: string, text: string, indent = \"\"): string {\n const prefix = `[${formatTs(ts)}] ${user}: `;\n const lines = text.split(\"\\n\");\n const firstLine = `${indent}${prefix}${lines[0]}`;\n if (lines.length === 1) return firstLine;\n // All continuation lines get same indent as content start\n const contentIndent = indent + \" \".repeat(prefix.length);\n return [firstLine, ...lines.slice(1).map((l) => contentIndent + l)].join(\"\\n\");\n}\n\nexport async function downloadChannel(channelId: string, botToken: string): Promise<void> {\n const client = new WebClient(botToken, { logLevel: LogLevel.ERROR });\n\n console.error(`Fetching channel info for ${channelId}...`);\n\n // Get channel info\n let channelName = channelId;\n try {\n const info = await client.conversations.info({ channel: channelId });\n channelName = typeof info.channel?.name === \"string\" ? info.channel.name : channelId;\n } catch {\n // DM channels don't have names, that's fine\n }\n\n console.error(`Downloading history for #${channelName} (${channelId})...`);\n\n // Fetch all messages\n const messages: Message[] = [];\n let cursor: string | undefined;\n\n do {\n const response = await client.conversations.history({\n channel: channelId,\n limit: 200,\n cursor,\n });\n\n if (response.messages) {\n messages.push(...(response.messages as Message[]));\n }\n\n cursor = response.response_metadata?.next_cursor;\n console.error(` Fetched ${messages.length} messages...`);\n } while (cursor);\n\n // Reverse to chronological order\n messages.reverse();\n\n // Build map of thread replies\n const threadReplies = new Map<string, Message[]>();\n const threadsToFetch = messages.filter((m) => m.reply_count && m.reply_count > 0);\n\n console.error(`Fetching ${threadsToFetch.length} threads...`);\n\n for (let i = 0; i < threadsToFetch.length; i++) {\n const parent = threadsToFetch[i];\n console.error(` Thread ${i + 1}/${threadsToFetch.length} (${parent.reply_count} replies)...`);\n\n const replies: Message[] = [];\n let threadCursor: string | undefined;\n\n do {\n const response = await client.conversations.replies({\n channel: channelId,\n ts: parent.ts,\n limit: 200,\n cursor: threadCursor,\n });\n\n if (response.messages) {\n // Skip the first message (it's the parent)\n replies.push(...(response.messages as Message[]).slice(1));\n }\n\n threadCursor = response.response_metadata?.next_cursor;\n } while (threadCursor);\n\n threadReplies.set(parent.ts, replies);\n }\n\n // Output messages with thread replies interleaved\n let totalReplies = 0;\n for (const msg of messages) {\n // Output the message\n console.log(formatMessage(msg.ts, msg.user || \"unknown\", msg.text || \"\"));\n\n // Output thread replies right after parent (indented)\n const replies = threadReplies.get(msg.ts);\n if (replies) {\n for (const reply of replies) {\n console.log(formatMessage(reply.ts, reply.user || \"unknown\", reply.text || \"\", \" \"));\n totalReplies++;\n }\n }\n }\n\n console.error(`Done! ${messages.length} messages, ${totalReplies} thread replies`);\n}\n"]}
1
+ {"version":3,"file":"download.js","sourceRoot":"","sources":["../../src/cli/download.ts"],"names":[],"mappings":"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","sourcesContent":["import { LogLevel, WebClient } from \"@slack/web-api\";\n\ninterface Message {\n ts: string;\n user?: string;\n text?: string;\n thread_ts?: string;\n reply_count?: number;\n files?: Array<{ name: string; url_private?: string }>;\n}\n\nfunction formatTs(ts: string): string {\n const date = new Date(parseFloat(ts) * 1000);\n return date\n .toISOString()\n .replace(\"T\", \" \")\n .replace(/\\.\\d+Z$/, \"\");\n}\n\nfunction formatMessage(ts: string, user: string, text: string, indent = \"\"): string {\n const prefix = `[${formatTs(ts)}] ${user}: `;\n const lines = text.split(\"\\n\");\n const firstLine = `${indent}${prefix}${lines[0]}`;\n if (lines.length === 1) return firstLine;\n // All continuation lines get same indent as content start\n const contentIndent = indent + \" \".repeat(prefix.length);\n return [firstLine, ...lines.slice(1).map((l) => contentIndent + l)].join(\"\\n\");\n}\n\nexport async function downloadChannel(channelId: string, botToken: string): Promise<void> {\n const client = new WebClient(botToken, { logLevel: LogLevel.ERROR });\n\n console.error(`Fetching channel info for ${channelId}...`);\n\n // Get channel info\n let channelName = channelId;\n try {\n const info = await client.conversations.info({ channel: channelId });\n channelName = typeof info.channel?.name === \"string\" ? info.channel.name : channelId;\n } catch {\n // DM channels don't have names, that's fine\n }\n\n console.error(`Downloading history for #${channelName} (${channelId})...`);\n\n // Fetch all messages\n const messages: Message[] = [];\n let cursor: string | undefined;\n\n do {\n const response = await client.conversations.history({\n channel: channelId,\n limit: 200,\n cursor,\n });\n\n if (response.messages) {\n messages.push(...(response.messages as Message[]));\n }\n\n cursor = response.response_metadata?.next_cursor;\n console.error(` Fetched ${messages.length} messages...`);\n } while (cursor);\n\n // Reverse to chronological order\n messages.reverse();\n\n // Build map of thread replies\n const threadReplies = new Map<string, Message[]>();\n const threadsToFetch = messages.filter((m) => m.reply_count && m.reply_count > 0);\n\n console.error(`Fetching ${threadsToFetch.length} threads...`);\n\n for (let i = 0; i < threadsToFetch.length; i++) {\n const parent = threadsToFetch[i];\n if (parent === undefined) continue;\n console.error(` Thread ${i + 1}/${threadsToFetch.length} (${parent.reply_count} replies)...`);\n\n const replies: Message[] = [];\n let threadCursor: string | undefined;\n\n do {\n const response = await client.conversations.replies({\n channel: channelId,\n ts: parent.ts,\n limit: 200,\n cursor: threadCursor,\n });\n\n if (response.messages) {\n // Skip the first message (it's the parent)\n replies.push(...(response.messages as Message[]).slice(1));\n }\n\n threadCursor = response.response_metadata?.next_cursor;\n } while (threadCursor);\n\n threadReplies.set(parent.ts, replies);\n }\n\n // Output messages with thread replies interleaved\n let totalReplies = 0;\n for (const msg of messages) {\n // Output the message\n console.log(formatMessage(msg.ts, msg.user || \"unknown\", msg.text || \"\"));\n\n // Output thread replies right after parent (indented)\n const replies = threadReplies.get(msg.ts);\n if (replies) {\n for (const reply of replies) {\n console.log(formatMessage(reply.ts, reply.user || \"unknown\", reply.text || \"\", \" \"));\n totalReplies++;\n }\n }\n }\n\n console.error(`Done! ${messages.length} messages, ${totalReplies} thread replies`);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ext-dev.d.ts","sourceRoot":"","sources":["../../src/cli/ext-dev.ts"],"names":[],"mappings":"AA0DA,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAuDtE"}
1
+ {"version":3,"file":"ext-dev.d.ts","sourceRoot":"","sources":["../../src/cli/ext-dev.ts"],"names":[],"mappings":"AA2DA,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAyDtE"}
@@ -50,6 +50,9 @@ export async function runExtDevCommand(argv) {
50
50
  let workspaceDir;
51
51
  const positional = [];
52
52
  for (let i = 0; i < argv.length; i++) {
53
+ const arg = argv[i];
54
+ if (arg === undefined)
55
+ continue;
53
56
  let taken;
54
57
  if ((taken = takeValueFlag(argv, i, "--workspace"))) {
55
58
  workspaceDir = taken.value;
@@ -59,7 +62,7 @@ export async function runExtDevCommand(argv) {
59
62
  i = taken.lastIndex; // already folded in by resolveStateDir
60
63
  }
61
64
  else
62
- positional.push(argv[i]);
65
+ positional.push(arg);
63
66
  }
64
67
  const target = positional[0];
65
68
  if (!target) {
@@ -1 +1 @@
1
- {"version":3,"file":"ext-dev.js","sourceRoot":"","sources":["../../src/cli/ext-dev.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `mikan ext dev <path>` — develop an extension without a Slack workspace.\n *\n * mikan ext dev ./my-extension\n * > add a poll for lunch\n * [agent reply]\n * > /pi-new # picks up your edits\n *\n * The alternative this exists to avoid is asking every extension author to\n * install mikan into a real Slack workspace, create an app, and deploy before\n * they can see whether their `activate()` even runs.\n *\n * It is a stdin/stdout conversation on the same runtime production uses — same\n * package resolution, same loader, same commands — with the platform swapped\n * for the terminal and the sandbox set to `host`. That equivalence is the\n * point: an extension that works here works in a channel, because nothing\n * about how it is found or activated differs.\n *\n * The working copy is registered as a conversation-scoped local package, which\n * is by-reference rather than copied, so the edit → `/pi-new` → test loop needs\n * no reinstall step.\n */\nimport { createInterface } from \"node:readline\";\nimport { existsSync, statSync } from \"node:fs\";\nimport { basename, resolve as resolvePath } from \"node:path\";\nimport { join } from \"node:path\";\nimport {\n createConversationEvent,\n createConversationMessage,\n createConversationRuntime,\n type ConversationContext,\n type ConversationResponder,\n type MessagingBot,\n type MessagingInfo,\n} from \"../index.js\";\nimport { updateConversationSettings } from \"../config.js\";\nimport { formatSource, parseSource } from \"../packages/index.js\";\nimport { resolveStateDir, takeValueFlag } from \"./arg-grammar.js\";\nimport { createOfficeAddress, createWorkspace } from \"../office/index.js\";\n\nconst USAGE = `Usage:\n mikan ext dev <path|source> [--workspace <dir>] [--state-dir <dir>]\n\n <path> a working copy of an extension (or a package directory)\n --workspace where conversation state is written (default: ./.mikan-ext-dev)\n\n Type a message to run the agent against your extension. /pi-new reloads it\n after an edit; Ctrl-D exits.`;\n\n/**\n * One dev conversation per extension, so two extensions can be developed side\n * by side without overwriting each other's settings or session history.\n */\nfunction devConversationId(source: string): string {\n const name = basename(source.replace(/[#@].*$/, \"\").replace(/\\/+$/, \"\")) || \"extension\";\n return `ext-dev-${name.toLowerCase().replace(/[^a-z0-9_-]+/g, \"-\")}`.slice(0, 64);\n}\n\nexport async function runExtDevCommand(argv: string[]): Promise<number> {\n const stateDir = resolveStateDir(argv);\n let workspaceDir: string | undefined;\n const positional: string[] = [];\n for (let i = 0; i < argv.length; i++) {\n let taken;\n if ((taken = takeValueFlag(argv, i, \"--workspace\"))) {\n workspaceDir = taken.value;\n i = taken.lastIndex;\n } else if ((taken = takeValueFlag(argv, i, \"--state-dir\"))) {\n i = taken.lastIndex; // already folded in by resolveStateDir\n } else positional.push(argv[i]);\n }\n\n const target = positional[0];\n if (!target) {\n console.error(USAGE);\n return 1;\n }\n\n // A local working copy is the common case; resolve it to an absolute path so\n // the stored package source does not depend on the shell's cwd.\n let source: string;\n try {\n const parsed = parseSource(\n existsSync(target) && !target.startsWith(\".\") ? resolvePath(target) : target,\n );\n source = formatSource(parsed);\n if (parsed.type === \"local\" && !statSync(parsed.path).isDirectory()) {\n console.error(`Not a directory: ${parsed.path}`);\n return 1;\n }\n } catch (err) {\n console.error(err instanceof Error ? err.message : String(err));\n return 1;\n }\n\n const conversationId = devConversationId(target);\n const workingDir = resolvePath(workspaceDir ?? join(process.cwd(), \".mikan-ext-dev\"));\n\n // Declaring the working copy as this conversation's package is what makes\n // the dev loop use the real resolution path rather than a bespoke one.\n process.env.MIKAN_STATE_DIR = stateDir;\n const workspace = createWorkspace({ root: workingDir, stateDir });\n const devOffice = workspace.office(createOfficeAddress(\"slack\", conversationId));\n devOffice.ensure();\n updateConversationSettings(devOffice, { packages: [source] });\n\n console.log(`mikan ext dev — ${source}`);\n console.log(` conversation: ${conversationId}`);\n console.log(` workspace: ${workingDir}`);\n console.log(` state dir: ${stateDir}`);\n console.log(\"Type a message. /pi-new reloads after an edit. Ctrl-D exits.\\n\");\n\n return runDevLoop({ conversationId, workspace });\n}\n\nfunction write(text: string): void {\n process.stdout.write(`${text}\\n`);\n}\n\nfunction runDevLoop(options: {\n conversationId: string;\n workspace: import(\"../office/types.js\").Workspace;\n}): Promise<number> {\n const { conversationId, workspace } = options;\n\n const platform: MessagingInfo = {\n name: \"ext-dev\",\n formattingGuide: \"Reply in plain text.\",\n channels: [{ id: conversationId, name: conversationId }],\n users: [{ id: \"dev\", userName: \"dev\", displayName: \"Developer\" }],\n };\n\n const runtime = createConversationRuntime({\n workspace,\n // The host executor keeps the loop dependency-free: no Docker, no image\n // pull, no VM. An extension's own tools and hooks do not observe the\n // difference, and the ones that shell out see the developer's machine —\n // which is what they want while iterating.\n sandbox: { type: \"host\" },\n });\n\n const bot: MessagingBot = {\n start: async () => {},\n postMessage: async (_conversationId, text) => {\n write(text);\n return `${Date.now()}`;\n },\n updateMessage: async (_conversationId, _ts, text) => write(text),\n enqueueEvent: () => false,\n getMessagingInfo: () => platform,\n };\n\n const responder: ConversationResponder = {\n respond: async (text) => write(text),\n replaceResponse: async (text) => write(text),\n respondDiagnostic: async (text) => write(`· ${text}`),\n respondToolResult: async (result) => write(`· [${result.toolName}]`),\n setTyping: async () => {},\n setWorking: async () => {},\n uploadFile: async (filePath) => write(`· [file] ${filePath}`),\n deleteResponse: async () => {},\n };\n\n let counter = 0;\n const handleLine = async (line: string): Promise<void> => {\n const ts = `${++counter}`;\n const event = createConversationEvent({\n platform: \"slack\",\n type: \"message\",\n conversationId,\n conversationKind: \"direct\",\n ts,\n user: \"dev\",\n text: line,\n sessionKey: conversationId,\n });\n const message = createConversationMessage({\n platform: \"slack\",\n conversationId,\n id: ts,\n sessionKey: conversationId,\n conversationKind: \"direct\",\n userId: \"dev\",\n userName: \"Developer\",\n text: line,\n });\n const context: ConversationContext = {\n address: event.address,\n message,\n responder,\n platform,\n };\n await runtime.handleEvent(event, bot, context);\n };\n\n return new Promise<number>((resolveLoop) => {\n const rl = createInterface({ input: process.stdin, output: process.stdout, prompt: \"> \" });\n rl.prompt();\n rl.on(\"line\", (line) => {\n if (!line.trim()) return rl.prompt();\n void handleLine(line)\n .catch((err: unknown) => write(`· error: ${err instanceof Error ? err.message : err}`))\n .finally(() => rl.prompt());\n });\n rl.on(\"close\", () => {\n void runtime.shutdown().then(() => resolveLoop(0));\n });\n });\n}\n"]}
1
+ {"version":3,"file":"ext-dev.js","sourceRoot":"","sources":["../../src/cli/ext-dev.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `mikan ext dev <path>` — develop an extension without a Slack workspace.\n *\n * mikan ext dev ./my-extension\n * > add a poll for lunch\n * [agent reply]\n * > /pi-new # picks up your edits\n *\n * The alternative this exists to avoid is asking every extension author to\n * install mikan into a real Slack workspace, create an app, and deploy before\n * they can see whether their `activate()` even runs.\n *\n * It is a stdin/stdout conversation on the same runtime production uses — same\n * package resolution, same loader, same commands — with the platform swapped\n * for the terminal and the sandbox set to `host`. That equivalence is the\n * point: an extension that works here works in a channel, because nothing\n * about how it is found or activated differs.\n *\n * The working copy is registered as a conversation-scoped local package, which\n * is by-reference rather than copied, so the edit → `/pi-new` → test loop needs\n * no reinstall step.\n */\nimport { createInterface } from \"node:readline\";\nimport { existsSync, statSync } from \"node:fs\";\nimport { basename, resolve as resolvePath } from \"node:path\";\nimport { join } from \"node:path\";\nimport {\n createConversationEvent,\n createConversationMessage,\n createConversationRuntime,\n type ConversationContext,\n type ConversationResponder,\n type MessagingBot,\n type MessagingInfo,\n} from \"../index.js\";\nimport { updateConversationSettings } from \"../config.js\";\nimport { formatSource, parseSource } from \"../packages/index.js\";\nimport { resolveStateDir, takeValueFlag } from \"./arg-grammar.js\";\nimport { createOfficeAddress, createWorkspace } from \"../office/index.js\";\nimport type { Workspace } from \"../office/types.js\";\n\nconst USAGE = `Usage:\n mikan ext dev <path|source> [--workspace <dir>] [--state-dir <dir>]\n\n <path> a working copy of an extension (or a package directory)\n --workspace where conversation state is written (default: ./.mikan-ext-dev)\n\n Type a message to run the agent against your extension. /pi-new reloads it\n after an edit; Ctrl-D exits.`;\n\n/**\n * One dev conversation per extension, so two extensions can be developed side\n * by side without overwriting each other's settings or session history.\n */\nfunction devConversationId(source: string): string {\n const name = basename(source.replace(/[#@].*$/, \"\").replace(/\\/+$/, \"\")) || \"extension\";\n return `ext-dev-${name.toLowerCase().replace(/[^a-z0-9_-]+/g, \"-\")}`.slice(0, 64);\n}\n\nexport async function runExtDevCommand(argv: string[]): Promise<number> {\n const stateDir = resolveStateDir(argv);\n let workspaceDir: string | undefined;\n const positional: string[] = [];\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n if (arg === undefined) continue;\n let taken;\n if ((taken = takeValueFlag(argv, i, \"--workspace\"))) {\n workspaceDir = taken.value;\n i = taken.lastIndex;\n } else if ((taken = takeValueFlag(argv, i, \"--state-dir\"))) {\n i = taken.lastIndex; // already folded in by resolveStateDir\n } else positional.push(arg);\n }\n\n const target = positional[0];\n if (!target) {\n console.error(USAGE);\n return 1;\n }\n\n // A local working copy is the common case; resolve it to an absolute path so\n // the stored package source does not depend on the shell's cwd.\n let source: string;\n try {\n const parsed = parseSource(\n existsSync(target) && !target.startsWith(\".\") ? resolvePath(target) : target,\n );\n source = formatSource(parsed);\n if (parsed.type === \"local\" && !statSync(parsed.path).isDirectory()) {\n console.error(`Not a directory: ${parsed.path}`);\n return 1;\n }\n } catch (err) {\n console.error(err instanceof Error ? err.message : String(err));\n return 1;\n }\n\n const conversationId = devConversationId(target);\n const workingDir = resolvePath(workspaceDir ?? join(process.cwd(), \".mikan-ext-dev\"));\n\n // Declaring the working copy as this conversation's package is what makes\n // the dev loop use the real resolution path rather than a bespoke one.\n process.env.MIKAN_STATE_DIR = stateDir;\n const workspace = createWorkspace({ root: workingDir, stateDir });\n const devOffice = workspace.office(createOfficeAddress(\"slack\", conversationId));\n devOffice.ensure();\n updateConversationSettings(devOffice, { packages: [source] });\n\n console.log(`mikan ext dev — ${source}`);\n console.log(` conversation: ${conversationId}`);\n console.log(` workspace: ${workingDir}`);\n console.log(` state dir: ${stateDir}`);\n console.log(\"Type a message. /pi-new reloads after an edit. Ctrl-D exits.\\n\");\n\n return runDevLoop({ conversationId, workspace });\n}\n\nfunction write(text: string): void {\n process.stdout.write(`${text}\\n`);\n}\n\nfunction runDevLoop(options: { conversationId: string; workspace: Workspace }): Promise<number> {\n const { conversationId, workspace } = options;\n\n const platform: MessagingInfo = {\n name: \"ext-dev\",\n formattingGuide: \"Reply in plain text.\",\n channels: [{ id: conversationId, name: conversationId }],\n users: [{ id: \"dev\", userName: \"dev\", displayName: \"Developer\" }],\n };\n\n const runtime = createConversationRuntime({\n workspace,\n // The host executor keeps the loop dependency-free: no Docker, no image\n // pull, no VM. An extension's own tools and hooks do not observe the\n // difference, and the ones that shell out see the developer's machine —\n // which is what they want while iterating.\n sandbox: { type: \"host\" },\n });\n\n const bot: MessagingBot = {\n start: async () => {},\n postMessage: async (_conversationId, text) => {\n write(text);\n return `${Date.now()}`;\n },\n updateMessage: async (_conversationId, _ts, text) => write(text),\n enqueueEvent: () => false,\n getMessagingInfo: () => platform,\n };\n\n const responder: ConversationResponder = {\n respond: async (text) => write(text),\n replaceResponse: async (text) => write(text),\n respondDiagnostic: async (text) => write(`· ${text}`),\n respondToolResult: async (result) => write(`· [${result.toolName}]`),\n setTyping: async () => {},\n setWorking: async () => {},\n uploadFile: async (filePath) => write(`· [file] ${filePath}`),\n deleteResponse: async () => {},\n };\n\n let counter = 0;\n const handleLine = async (line: string): Promise<void> => {\n const ts = `${++counter}`;\n const event = createConversationEvent({\n platform: \"slack\",\n type: \"message\",\n conversationId,\n conversationKind: \"direct\",\n ts,\n user: \"dev\",\n text: line,\n sessionKey: conversationId,\n });\n const message = createConversationMessage({\n platform: \"slack\",\n conversationId,\n id: ts,\n sessionKey: conversationId,\n conversationKind: \"direct\",\n userId: \"dev\",\n userName: \"Developer\",\n text: line,\n });\n const context: ConversationContext = {\n address: event.address,\n message,\n responder,\n platform,\n };\n await runtime.handleEvent(event, bot, context);\n };\n\n return new Promise<number>((resolveLoop) => {\n const rl = createInterface({ input: process.stdin, output: process.stdout, prompt: \"> \" });\n rl.prompt();\n rl.on(\"line\", (line) => {\n if (!line.trim()) return rl.prompt();\n void handleLine(line)\n .catch((err: unknown) => write(`· error: ${err instanceof Error ? err.message : err}`))\n .finally(() => rl.prompt());\n });\n rl.on(\"close\", () => {\n void runtime.shutdown().then(() => resolveLoop(0));\n });\n });\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ext.d.ts","sourceRoot":"","sources":["../../src/cli/ext.ts"],"names":[],"mappings":"AAoFA,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAmBnE"}
1
+ {"version":3,"file":"ext.d.ts","sourceRoot":"","sources":["../../src/cli/ext.ts"],"names":[],"mappings":"AA4GA,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAmBnE"}
package/dist/cli/ext.js CHANGED
@@ -11,12 +11,13 @@
11
11
  * existing extension updates it (data is preserved). Extensions install into the
12
12
  * host-only state dir (never the workspace); see src/harness/extensions/LAYOUT.md.
13
13
  */
14
- import { cpSync, existsSync, mkdirSync, rmSync } from "node:fs";
14
+ import { cpSync, existsSync, mkdirSync, readdirSync, rmSync } from "node:fs";
15
15
  import { basename, join, resolve } from "node:path";
16
16
  import { defaultExtensionDirs, listInstalledExtensions, validateExtension, } from "../harness/index.js";
17
17
  import { resolveStateDir, takeValueFlag } from "./arg-grammar.js";
18
18
  import { runExtDevCommand } from "./ext-dev.js";
19
- import { parseGitSource, resolveGitSource } from "./ext-git.js";
19
+ import { materializeSource } from "../packages/materialize.js";
20
+ import { isGitSourceString } from "../packages/source.js";
20
21
  import { officeStateDir } from "../office/index.js";
21
22
  import { resolveOwnedOfficeAddress } from "../office/index.js";
22
23
  function parseExtArgs(argv) {
@@ -24,24 +25,42 @@ function parseExtArgs(argv) {
24
25
  const stateDir = resolveStateDir(argv);
25
26
  let scope;
26
27
  let conversationId;
28
+ let workspaceDir;
29
+ let purge = false;
27
30
  const positional = [];
28
31
  for (let i = 0; i < argv.length; i++) {
29
32
  const arg = argv[i];
33
+ if (arg === undefined)
34
+ continue;
30
35
  let taken;
31
36
  if (arg === "--global")
32
37
  scope = "global";
38
+ else if (arg === "--purge")
39
+ purge = true;
33
40
  else if ((taken = takeValueFlag(argv, i, "--conversation"))) {
34
41
  scope = "conversation";
35
42
  conversationId = taken.value || undefined;
36
43
  i = taken.lastIndex;
37
44
  }
45
+ else if ((taken = takeValueFlag(argv, i, "--workspace"))) {
46
+ workspaceDir = taken.value ? resolve(taken.value) : undefined;
47
+ i = taken.lastIndex;
48
+ }
38
49
  else if ((taken = takeValueFlag(argv, i, "--state-dir"))) {
39
50
  i = taken.lastIndex; // value already folded in by resolveStateDir
40
51
  }
41
52
  else
42
53
  positional.push(arg);
43
54
  }
44
- return { action: positional[0], target: positional[1], stateDir, scope, conversationId };
55
+ return {
56
+ action: positional[0] ?? "",
57
+ target: positional[1],
58
+ stateDir,
59
+ scope,
60
+ conversationId,
61
+ workspaceDir,
62
+ purge,
63
+ };
45
64
  }
46
65
  /** Directory that extension CODE for the chosen scope lives in. */
47
66
  function scopeExtensionsDir(args) {
@@ -49,7 +68,11 @@ function scopeExtensionsDir(args) {
49
68
  return join(args.stateDir, "global", "extensions");
50
69
  if (args.scope === "conversation" && args.conversationId) {
51
70
  // defaultExtensionDirs returns [global, conversation]; take the conversation one.
52
- return defaultExtensionDirs(resolveOwnedOfficeAddress(args.conversationId, args.stateDir), args.stateDir)[1];
71
+ const conversationDir = defaultExtensionDirs(resolveOwnedOfficeAddress(args.conversationId, args.stateDir), args.stateDir)[1];
72
+ if (conversationDir === undefined) {
73
+ throw new Error("defaultExtensionDirs returned no conversation directory");
74
+ }
75
+ return conversationDir;
53
76
  }
54
77
  throw new Error("Specify a scope: --global or --conversation <id>");
55
78
  }
@@ -58,13 +81,14 @@ const USAGE = `Usage:
58
81
  Run an extension in a local stdin/stdout conversation — no Slack, no
59
82
  install. Edit, send /pi-new, test again.
60
83
  mikan ext install <source> (--global | --conversation <id>) [--state-dir <dir>]
61
- <source>: a local path, or a git URL / github:owner/repo with optional #subpath
84
+ <source>: a local path, or a git URL / github:owner/repo with optional @ref and #subpath
62
85
  e.g. github:geminixiang/mikan#deploy/examples/extensions/agent-pm
63
86
  Reinstalling over an existing extension updates it (data preserved).
64
87
  mikan ext validate <path>
65
88
  mikan ext list [--conversation <id>] [--state-dir <dir>]
66
- mikan ext remove <slug> (--global | --conversation <id>) [--state-dir <dir>]`;
67
- function noop() { }
89
+ mikan ext remove <slug> (--global | --conversation <id>) [--purge] [--workspace <dir>] [--state-dir <dir>]
90
+ Removes the extension's code. --purge also sweeps its schedules, secrets
91
+ vault, and data dirs; add --workspace to sweep its event files too.`;
68
92
  export async function runExtCommand(argv) {
69
93
  const args = parseExtArgs(argv);
70
94
  switch (args.action) {
@@ -106,31 +130,30 @@ async function installAction(args) {
106
130
  console.error(err instanceof Error ? err.message : String(err));
107
131
  return 1;
108
132
  }
109
- // Resolve the source: a git URL (optionally with #subpath) is cloned to a
110
- // temp dir; a local path is used directly.
111
- const gitSpec = parseGitSource(args.target);
133
+ // Resolve the source: a git source materializes through the packages layer
134
+ // (cached clone under the scope's git/ dir, @ref supported); a local path is
135
+ // used directly. `refresh` re-fetches so reinstall always picks up updates.
112
136
  let source;
113
- let cleanup = noop;
114
- if (gitSpec) {
137
+ if (isGitSourceString(args.target)) {
115
138
  try {
116
- const resolved = resolveGitSource(gitSpec);
117
- source = resolved.dir;
118
- cleanup = resolved.cleanup;
139
+ source = materializeSource(args.target, {
140
+ scope: args.scope,
141
+ address: args.scope === "conversation"
142
+ ? resolveOwnedOfficeAddress(args.conversationId, args.stateDir)
143
+ : undefined,
144
+ stateDir: args.stateDir,
145
+ mode: "refresh",
146
+ }).dir;
119
147
  }
120
148
  catch (err) {
121
- console.error(`Failed to fetch ${gitSpec.url}: ${err instanceof Error ? err.message : err}`);
149
+ console.error(`Failed to fetch ${args.target}: ${err instanceof Error ? err.message : err}`);
122
150
  return 1;
123
151
  }
124
152
  }
125
153
  else {
126
154
  source = resolve(args.target);
127
155
  }
128
- try {
129
- return await installResolved(args, source, destDir);
130
- }
131
- finally {
132
- cleanup();
133
- }
156
+ return await installResolved(args, source, destDir);
134
157
  }
135
158
  async function installResolved(args, source, destDir) {
136
159
  const result = await validateExtension(source);
@@ -178,9 +201,47 @@ function listAction(args) {
178
201
  console.log(` ${info.description}`);
179
202
  if (info.skillNames.length > 0)
180
203
  console.log(` skills: ${info.skillNames.join(", ")}`);
204
+ if (info.secrets.length > 0) {
205
+ const keys = info.secrets.map((s) => `${s.key}${s.required ? " (required)" : ""}`);
206
+ console.log(` secrets: ${keys.join(", ")}`);
207
+ }
181
208
  }
182
209
  return 0;
183
210
  }
211
+ /** Files in `dir` (non-recursive) whose names satisfy `matches`; [] when absent. */
212
+ function matchingFiles(dir, matches) {
213
+ if (!existsSync(dir))
214
+ return [];
215
+ return readdirSync(dir)
216
+ .filter(matches)
217
+ .map((filename) => join(dir, filename));
218
+ }
219
+ function findExtensionResidue(slug, stateDir, workspaceDir) {
220
+ const callbackScheduleFiles = [];
221
+ const dataDirs = [];
222
+ const conversationsDir = join(stateDir, "conversations");
223
+ const officeDirs = existsSync(conversationsDir) ? readdirSync(conversationsDir) : [];
224
+ for (const officeDir of officeDirs) {
225
+ callbackScheduleFiles.push(...matchingFiles(join(conversationsDir, officeDir, "extension-schedules"), (filename) => filename.startsWith(`${slug}.`) && filename.endsWith(".json")));
226
+ const dataDir = join(conversationsDir, officeDir, "extension-data", slug);
227
+ if (existsSync(dataDir))
228
+ dataDirs.push(dataDir);
229
+ }
230
+ const globalDataDir = join(stateDir, "global", "extension-data", slug);
231
+ if (existsSync(globalDataDir))
232
+ dataDirs.push(globalDataDir);
233
+ const eventFiles = workspaceDir
234
+ ? matchingFiles(join(workspaceDir, "events"), (filename) => (filename.startsWith(`ext.${slug}.`) || filename.startsWith(`extrun.${slug}.`)) &&
235
+ filename.endsWith(".json"))
236
+ : [];
237
+ const vaultDir = join(stateDir, "vaults", "extensions", slug);
238
+ return {
239
+ callbackScheduleFiles,
240
+ ...(existsSync(vaultDir) ? { vaultDir } : {}),
241
+ dataDirs,
242
+ eventFiles,
243
+ };
244
+ }
184
245
  function removeAction(args) {
185
246
  if (!args.target) {
186
247
  console.error("ext remove: missing <slug>");
@@ -205,7 +266,42 @@ function removeAction(args) {
205
266
  const parent = resolve(match.path, "..");
206
267
  const removeTarget = parent === resolve(destDir) ? match.path : parent;
207
268
  rmSync(removeTarget, { recursive: true, force: true });
208
- console.log(`Removed ${match.name} (slug: ${match.slug}). Data left in place.`);
269
+ console.log(`Removed ${match.name} (slug: ${match.slug}).`);
270
+ // Never sweep implicitly: the same slug may still be active through another
271
+ // scope or a PACKAGES declaration this command cannot see. --purge is the
272
+ // admin's statement that nothing else owns it.
273
+ const residue = findExtensionResidue(match.slug, args.stateDir, args.workspaceDir);
274
+ if (args.purge) {
275
+ for (const file of [...residue.callbackScheduleFiles, ...residue.eventFiles]) {
276
+ rmSync(file, { force: true });
277
+ }
278
+ for (const dataDir of residue.dataDirs)
279
+ rmSync(dataDir, { recursive: true, force: true });
280
+ if (residue.vaultDir)
281
+ rmSync(residue.vaultDir, { recursive: true, force: true });
282
+ console.log(`Purged: ${residue.callbackScheduleFiles.length} schedule file(s), ` +
283
+ `${residue.eventFiles.length} event file(s), ${residue.dataDirs.length} data dir(s)` +
284
+ `${residue.vaultDir ? ", secrets vault" : ""}.`);
285
+ if (!args.workspaceDir) {
286
+ console.log("Note: events-bus files were not swept — pass --workspace <dir> to include them.");
287
+ }
288
+ if (residue.callbackScheduleFiles.length > 0) {
289
+ console.log("A running daemon keeps deleted schedules armed until restart.");
290
+ }
291
+ }
292
+ else {
293
+ const leftovers = [
294
+ residue.callbackScheduleFiles.length > 0
295
+ ? `${residue.callbackScheduleFiles.length} schedule file(s)`
296
+ : undefined,
297
+ residue.vaultDir ? "secrets vault" : undefined,
298
+ residue.dataDirs.length > 0 ? `${residue.dataDirs.length} data dir(s)` : undefined,
299
+ residue.eventFiles.length > 0 ? `${residue.eventFiles.length} event file(s)` : undefined,
300
+ ].filter(Boolean);
301
+ if (leftovers.length > 0) {
302
+ console.log(`Left in place: ${leftovers.join(", ")}. Re-run with --purge to sweep.`);
303
+ }
304
+ }
209
305
  console.log("Run /pi-new in the conversation to apply.");
210
306
  return 0;
211
307
  }
@@ -215,6 +311,10 @@ function printValidation(result) {
215
311
  console.log(` entrypoint: ${result.entrypoint}`);
216
312
  if (result.skillNames.length > 0)
217
313
  console.log(` skills: ${result.skillNames.join(", ")}`);
314
+ if (result.secrets.length > 0) {
315
+ const keys = result.secrets.map((s) => `${s.key}${s.required ? " (required)" : ""}`);
316
+ console.log(` secrets: ${keys.join(", ")}`);
317
+ }
218
318
  for (const warning of result.warnings)
219
319
  console.log(` warning: ${warning}`);
220
320
  for (const error of result.errors)