@geminixiang/mikan 1.0.0-beta.53 → 1.0.0-beta.55

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 (556) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +3 -2
  3. package/dist/adapters/commands/admin.d.ts.map +1 -0
  4. package/dist/{commands → adapters/commands}/admin.js +4 -8
  5. package/dist/adapters/commands/admin.js.map +1 -0
  6. package/dist/adapters/commands/login.d.ts.map +1 -0
  7. package/dist/adapters/commands/login.js +166 -0
  8. package/dist/adapters/commands/login.js.map +1 -0
  9. package/dist/adapters/commands/manifest.d.ts.map +1 -0
  10. package/dist/{commands → adapters/commands}/manifest.js +0 -7
  11. package/dist/adapters/commands/manifest.js.map +1 -0
  12. package/dist/{commands → adapters/commands}/model.d.ts +6 -0
  13. package/dist/adapters/commands/model.d.ts.map +1 -0
  14. package/dist/{commands → adapters/commands}/model.js +56 -44
  15. package/dist/adapters/commands/model.js.map +1 -0
  16. package/dist/adapters/commands/new.d.ts.map +1 -0
  17. package/dist/{commands → adapters/commands}/new.js +7 -8
  18. package/dist/adapters/commands/new.js.map +1 -0
  19. package/dist/adapters/commands/registry.d.ts.map +1 -0
  20. package/dist/{commands → adapters/commands}/registry.js +1 -3
  21. package/dist/adapters/commands/registry.js.map +1 -0
  22. package/dist/adapters/commands/sandbox.d.ts.map +1 -0
  23. package/dist/{commands → adapters/commands}/sandbox.js +22 -21
  24. package/dist/adapters/commands/sandbox.js.map +1 -0
  25. package/dist/adapters/commands/session-view.d.ts.map +1 -0
  26. package/dist/{commands → adapters/commands}/session-view.js +8 -11
  27. package/dist/adapters/commands/session-view.js.map +1 -0
  28. package/dist/{commands → adapters/commands}/types.d.ts +6 -6
  29. package/dist/adapters/commands/types.d.ts.map +1 -0
  30. package/dist/adapters/commands/types.js.map +1 -0
  31. package/dist/adapters/commands/utils.d.ts +14 -0
  32. package/dist/adapters/commands/utils.d.ts.map +1 -0
  33. package/dist/{commands → adapters/commands}/utils.js +18 -1
  34. package/dist/adapters/commands/utils.js.map +1 -0
  35. package/dist/adapters/discord/bot.d.ts.map +1 -1
  36. package/dist/adapters/discord/bot.js +4 -5
  37. package/dist/adapters/discord/bot.js.map +1 -1
  38. package/dist/adapters/github/bot.d.ts.map +1 -1
  39. package/dist/adapters/github/bot.js +3 -4
  40. package/dist/adapters/github/bot.js.map +1 -1
  41. package/dist/adapters/github/client.d.ts.map +1 -1
  42. package/dist/adapters/github/client.js +5 -18
  43. package/dist/adapters/github/client.js.map +1 -1
  44. package/dist/adapters/github/tool-pack.d.ts +1 -1
  45. package/dist/adapters/github/tool-pack.d.ts.map +1 -1
  46. package/dist/adapters/github/tool-pack.js.map +1 -1
  47. package/dist/adapters/github/tools/checks.js +1 -1
  48. package/dist/adapters/github/tools/checks.js.map +1 -1
  49. package/dist/adapters/github/tools/issue.js +1 -1
  50. package/dist/adapters/github/tools/issue.js.map +1 -1
  51. package/dist/adapters/github/tools/pr.js +1 -1
  52. package/dist/adapters/github/tools/pr.js.map +1 -1
  53. package/dist/adapters/github/tools/read.d.ts.map +1 -1
  54. package/dist/adapters/github/tools/read.js +53 -53
  55. package/dist/adapters/github/tools/read.js.map +1 -1
  56. package/dist/adapters/github/tools/review-reply.js +1 -1
  57. package/dist/adapters/github/tools/review-reply.js.map +1 -1
  58. package/dist/adapters/github/tools/sync.js +1 -1
  59. package/dist/adapters/github/tools/sync.js.map +1 -1
  60. package/dist/adapters/intake.d.ts +1 -1
  61. package/dist/adapters/intake.d.ts.map +1 -1
  62. package/dist/adapters/intake.js +2 -6
  63. package/dist/adapters/intake.js.map +1 -1
  64. package/dist/adapters/markdown-tables.d.ts +0 -13
  65. package/dist/adapters/markdown-tables.d.ts.map +1 -1
  66. package/dist/adapters/markdown-tables.js +26 -38
  67. package/dist/adapters/markdown-tables.js.map +1 -1
  68. package/dist/adapters/shared.js +1 -1
  69. package/dist/adapters/shared.js.map +1 -1
  70. package/dist/adapters/slack/bot.d.ts +7 -4
  71. package/dist/adapters/slack/bot.d.ts.map +1 -1
  72. package/dist/adapters/slack/bot.js +104 -122
  73. package/dist/adapters/slack/bot.js.map +1 -1
  74. package/dist/adapters/slack/response-lifecycle.d.ts.map +1 -1
  75. package/dist/adapters/slack/response-lifecycle.js +33 -25
  76. package/dist/adapters/slack/response-lifecycle.js.map +1 -1
  77. package/dist/adapters/slack/tool-pack.d.ts +1 -1
  78. package/dist/adapters/slack/tool-pack.d.ts.map +1 -1
  79. package/dist/adapters/slack/tool-pack.js.map +1 -1
  80. package/dist/adapters/slack/update-diagnostics.d.ts.map +1 -1
  81. package/dist/adapters/slack/update-diagnostics.js +8 -24
  82. package/dist/adapters/slack/update-diagnostics.js.map +1 -1
  83. package/dist/adapters/telegram/bot.d.ts.map +1 -1
  84. package/dist/adapters/telegram/bot.js +3 -4
  85. package/dist/adapters/telegram/bot.js.map +1 -1
  86. package/dist/adapters/types.d.ts +2 -4
  87. package/dist/adapters/types.d.ts.map +1 -1
  88. package/dist/adapters/types.js.map +1 -1
  89. package/dist/{web → adapters/web}/admin/portal.d.ts +3 -3
  90. package/dist/adapters/web/admin/portal.d.ts.map +1 -0
  91. package/dist/{web → adapters/web}/admin/portal.js +535 -709
  92. package/dist/adapters/web/admin/portal.js.map +1 -0
  93. package/dist/{web → adapters/web}/admin/provider-models.d.ts +1 -1
  94. package/dist/adapters/web/admin/provider-models.d.ts.map +1 -0
  95. package/dist/adapters/web/admin/provider-models.js.map +1 -0
  96. package/dist/{web → adapters/web}/admin/types.d.ts +5 -5
  97. package/dist/adapters/web/admin/types.d.ts.map +1 -0
  98. package/dist/adapters/web/admin/types.js.map +1 -0
  99. package/dist/adapters/web/login/oauth.d.ts.map +1 -0
  100. package/dist/{web → adapters/web}/login/oauth.js +50 -54
  101. package/dist/adapters/web/login/oauth.js.map +1 -0
  102. package/dist/{web → adapters/web}/login/portal.d.ts +2 -2
  103. package/dist/adapters/web/login/portal.d.ts.map +1 -0
  104. package/dist/{web → adapters/web}/login/portal.js +6 -6
  105. package/dist/adapters/web/login/portal.js.map +1 -0
  106. package/dist/{web → adapters/web}/login/types.d.ts +1 -1
  107. package/dist/adapters/web/login/types.d.ts.map +1 -0
  108. package/dist/adapters/web/login/types.js.map +1 -0
  109. package/dist/{web → adapters/web}/portal-shell.d.ts +2 -2
  110. package/dist/adapters/web/portal-shell.d.ts.map +1 -0
  111. package/dist/{web → adapters/web}/portal-shell.js +2 -2
  112. package/dist/adapters/web/portal-shell.js.map +1 -0
  113. package/dist/{web → adapters/web}/server.d.ts +5 -5
  114. package/dist/adapters/web/server.d.ts.map +1 -0
  115. package/dist/{web → adapters/web}/server.js +4 -7
  116. package/dist/adapters/web/server.js.map +1 -0
  117. package/dist/adapters/web/session-view/portal.d.ts.map +1 -0
  118. package/dist/{web → adapters/web}/session-view/portal.js +9 -9
  119. package/dist/adapters/web/session-view/portal.js.map +1 -0
  120. package/dist/{web → adapters/web}/session-view/types.d.ts +3 -3
  121. package/dist/adapters/web/session-view/types.d.ts.map +1 -0
  122. package/dist/adapters/web/session-view/types.js.map +1 -0
  123. package/dist/adapters/web/token-store.d.ts.map +1 -0
  124. package/dist/adapters/web/token-store.js.map +1 -0
  125. package/dist/adapters/web/types.d.ts.map +1 -0
  126. package/dist/adapters/web/types.js.map +1 -0
  127. package/dist/cli/arg-grammar.d.ts +24 -0
  128. package/dist/cli/arg-grammar.d.ts.map +1 -1
  129. package/dist/cli/arg-grammar.js +39 -8
  130. package/dist/cli/arg-grammar.js.map +1 -1
  131. package/dist/cli/boot.d.ts.map +1 -1
  132. package/dist/cli/boot.js +48 -62
  133. package/dist/cli/boot.js.map +1 -1
  134. package/dist/cli/download.d.ts.map +1 -1
  135. package/dist/cli/download.js +51 -54
  136. package/dist/cli/download.js.map +1 -1
  137. package/dist/cli/office.d.ts.map +1 -1
  138. package/dist/cli/office.js +9 -26
  139. package/dist/cli/office.js.map +1 -1
  140. package/dist/cli/onboard.d.ts.map +1 -1
  141. package/dist/cli/onboard.js +15 -11
  142. package/dist/cli/onboard.js.map +1 -1
  143. package/dist/cli/sessions.d.ts.map +1 -1
  144. package/dist/cli/sessions.js +49 -52
  145. package/dist/cli/sessions.js.map +1 -1
  146. package/dist/config.d.ts +4 -28
  147. package/dist/config.d.ts.map +1 -1
  148. package/dist/config.js +7 -112
  149. package/dist/config.js.map +1 -1
  150. package/dist/dream/index.d.ts.map +1 -1
  151. package/dist/dream/index.js +8 -2
  152. package/dist/dream/index.js.map +1 -1
  153. package/dist/dream/types.d.ts +1 -1
  154. package/dist/dream/types.d.ts.map +1 -1
  155. package/dist/dream/types.js.map +1 -1
  156. package/dist/env-manifest.d.ts +2 -0
  157. package/dist/env-manifest.d.ts.map +1 -1
  158. package/dist/env-manifest.js +29 -8
  159. package/dist/env-manifest.js.map +1 -1
  160. package/dist/events/index.d.ts +150 -0
  161. package/dist/events/index.d.ts.map +1 -0
  162. package/dist/{harness/event-format.js → events/index.js} +80 -2
  163. package/dist/events/index.js.map +1 -0
  164. package/dist/{events.d.ts → events/watcher.d.ts} +4 -4
  165. package/dist/events/watcher.d.ts.map +1 -0
  166. package/dist/{events.js → events/watcher.js} +8 -8
  167. package/dist/events/watcher.js.map +1 -0
  168. package/dist/file-guards.d.ts.map +1 -0
  169. package/dist/file-guards.js.map +1 -0
  170. package/dist/harness/execution-env.d.ts +19 -0
  171. package/dist/harness/execution-env.d.ts.map +1 -0
  172. package/dist/harness/execution-env.js +262 -0
  173. package/dist/harness/execution-env.js.map +1 -0
  174. package/dist/harness/execution-resolver.d.ts +25 -0
  175. package/dist/harness/execution-resolver.d.ts.map +1 -0
  176. package/dist/{execution-resolver.js → harness/execution-resolver.js} +12 -21
  177. package/dist/harness/execution-resolver.js.map +1 -0
  178. package/dist/harness/index.d.ts +9 -9
  179. package/dist/harness/index.d.ts.map +1 -1
  180. package/dist/harness/index.js +8 -8
  181. package/dist/harness/index.js.map +1 -1
  182. package/dist/harness/mcp.d.ts +38 -0
  183. package/dist/harness/mcp.d.ts.map +1 -0
  184. package/dist/{mcp/loader.js → harness/mcp.js} +155 -6
  185. package/dist/harness/mcp.js.map +1 -0
  186. package/dist/harness/models.js +1 -1
  187. package/dist/harness/models.js.map +1 -1
  188. package/dist/harness/open-connector.d.ts.map +1 -0
  189. package/dist/{mcp → harness}/open-connector.js +1 -1
  190. package/dist/harness/open-connector.js.map +1 -0
  191. package/dist/{agent → harness}/presenter.d.ts +2 -9
  192. package/dist/harness/presenter.d.ts.map +1 -0
  193. package/dist/{agent → harness}/presenter.js +170 -146
  194. package/dist/harness/presenter.js.map +1 -0
  195. package/dist/{agent → harness}/prompt.d.ts +10 -3
  196. package/dist/harness/prompt.d.ts.map +1 -0
  197. package/dist/{agent → harness}/prompt.js +137 -41
  198. package/dist/harness/prompt.js.map +1 -0
  199. package/dist/harness/runner.d.ts +2 -109
  200. package/dist/harness/runner.d.ts.map +1 -1
  201. package/dist/harness/runner.js +499 -467
  202. package/dist/harness/runner.js.map +1 -1
  203. package/dist/harness/session.d.ts +119 -0
  204. package/dist/harness/session.d.ts.map +1 -0
  205. package/dist/harness/session.js +561 -0
  206. package/dist/harness/session.js.map +1 -0
  207. package/dist/harness/skills.d.ts +10 -2
  208. package/dist/harness/skills.d.ts.map +1 -1
  209. package/dist/harness/skills.js +62 -39
  210. package/dist/harness/skills.js.map +1 -1
  211. package/dist/harness/{subagent-runner.d.ts → subagent.d.ts} +25 -6
  212. package/dist/harness/subagent.d.ts.map +1 -0
  213. package/dist/harness/{subagent-runner.js → subagent.js} +106 -54
  214. package/dist/harness/subagent.js.map +1 -0
  215. package/dist/harness/tools/attach.d.ts.map +1 -0
  216. package/dist/harness/tools/attach.js.map +1 -0
  217. package/dist/{tools → harness/tools}/event.d.ts +3 -32
  218. package/dist/harness/tools/event.d.ts.map +1 -0
  219. package/dist/harness/tools/event.js +178 -0
  220. package/dist/harness/tools/event.js.map +1 -0
  221. package/dist/harness/tools/generate-image.d.ts.map +1 -0
  222. package/dist/harness/tools/generate-image.js.map +1 -0
  223. package/dist/harness/tools/host-fn-tool.d.ts.map +1 -0
  224. package/dist/harness/tools/host-fn-tool.js.map +1 -0
  225. package/dist/{tools → harness/tools}/index.d.ts +5 -6
  226. package/dist/harness/tools/index.d.ts.map +1 -0
  227. package/dist/{tools → harness/tools}/index.js +12 -16
  228. package/dist/harness/tools/index.js.map +1 -0
  229. package/dist/harness/tools/pi-tools.d.ts +18 -0
  230. package/dist/harness/tools/pi-tools.d.ts.map +1 -0
  231. package/dist/harness/tools/pi-tools.js +84 -0
  232. package/dist/harness/tools/pi-tools.js.map +1 -0
  233. package/dist/harness/tools/react.d.ts.map +1 -0
  234. package/dist/harness/tools/react.js.map +1 -0
  235. package/dist/{tools → harness/tools}/sandbox.d.ts +2 -2
  236. package/dist/harness/tools/sandbox.d.ts.map +1 -0
  237. package/dist/{tools → harness/tools}/sandbox.js +1 -1
  238. package/dist/harness/tools/sandbox.js.map +1 -0
  239. package/dist/{tools → harness/tools}/subagent.d.ts +28 -1
  240. package/dist/harness/tools/subagent.d.ts.map +1 -0
  241. package/dist/{tools → harness/tools}/subagent.js +218 -2
  242. package/dist/harness/tools/subagent.js.map +1 -0
  243. package/dist/{tools → harness/tools}/types.d.ts +0 -33
  244. package/dist/harness/tools/types.d.ts.map +1 -0
  245. package/dist/harness/tools/types.js.map +1 -0
  246. package/dist/harness/types.d.ts +180 -97
  247. package/dist/harness/types.d.ts.map +1 -1
  248. package/dist/harness/types.js +1 -1
  249. package/dist/harness/types.js.map +1 -1
  250. package/dist/index.d.ts +12 -11
  251. package/dist/index.d.ts.map +1 -1
  252. package/dist/index.js +6 -6
  253. package/dist/index.js.map +1 -1
  254. package/dist/main.js +10 -12
  255. package/dist/main.js.map +1 -1
  256. package/dist/observability/index.d.ts +33 -0
  257. package/dist/observability/index.d.ts.map +1 -0
  258. package/dist/observability/index.js +256 -0
  259. package/dist/observability/index.js.map +1 -0
  260. package/dist/observability/instrument.js +7 -1
  261. package/dist/observability/instrument.js.map +1 -1
  262. package/dist/observability/otel.d.ts +10 -0
  263. package/dist/observability/otel.d.ts.map +1 -0
  264. package/dist/observability/otel.js +183 -0
  265. package/dist/observability/otel.js.map +1 -0
  266. package/dist/observability/sentry.d.ts +22 -5
  267. package/dist/observability/sentry.d.ts.map +1 -1
  268. package/dist/observability/sentry.js +68 -23
  269. package/dist/observability/sentry.js.map +1 -1
  270. package/dist/observability/types.d.ts +6 -2
  271. package/dist/observability/types.d.ts.map +1 -1
  272. package/dist/observability/types.js.map +1 -1
  273. package/dist/office/index.d.ts +2 -3
  274. package/dist/office/index.d.ts.map +1 -1
  275. package/dist/office/index.js +172 -140
  276. package/dist/office/index.js.map +1 -1
  277. package/dist/{workspace-projection/index.d.ts → office/projection.d.ts} +2 -2
  278. package/dist/office/projection.d.ts.map +1 -0
  279. package/dist/{workspace-projection/index.js → office/projection.js} +2 -2
  280. package/dist/office/projection.js.map +1 -0
  281. package/dist/office/types.d.ts +29 -2
  282. package/dist/office/types.d.ts.map +1 -1
  283. package/dist/office/types.js.map +1 -1
  284. package/dist/process-lifecycle.d.ts +1 -1
  285. package/dist/process-lifecycle.d.ts.map +1 -1
  286. package/dist/process-lifecycle.js +3 -3
  287. package/dist/process-lifecycle.js.map +1 -1
  288. package/dist/runtime/conversation-runtime.d.ts.map +1 -1
  289. package/dist/runtime/conversation-runtime.js +106 -107
  290. package/dist/runtime/conversation-runtime.js.map +1 -1
  291. package/dist/runtime/session-lifecycle.d.ts +10 -0
  292. package/dist/runtime/session-lifecycle.d.ts.map +1 -1
  293. package/dist/runtime/session-lifecycle.js +42 -24
  294. package/dist/runtime/session-lifecycle.js.map +1 -1
  295. package/dist/runtime/types.d.ts +3 -3
  296. package/dist/runtime/types.d.ts.map +1 -1
  297. package/dist/runtime/types.js.map +1 -1
  298. package/dist/sandbox/cloudflare.d.ts +1 -0
  299. package/dist/sandbox/cloudflare.d.ts.map +1 -1
  300. package/dist/sandbox/cloudflare.js +41 -50
  301. package/dist/sandbox/cloudflare.js.map +1 -1
  302. package/dist/sandbox/container.d.ts.map +1 -1
  303. package/dist/sandbox/container.js +7 -4
  304. package/dist/sandbox/container.js.map +1 -1
  305. package/dist/sandbox/host.d.ts.map +1 -1
  306. package/dist/sandbox/host.js +27 -35
  307. package/dist/sandbox/host.js.map +1 -1
  308. package/dist/sandbox/index.d.ts.map +1 -1
  309. package/dist/sandbox/index.js +8 -15
  310. package/dist/sandbox/index.js.map +1 -1
  311. package/dist/{provisioner.d.ts → sandbox/provisioner.d.ts} +2 -2
  312. package/dist/sandbox/provisioner.d.ts.map +1 -0
  313. package/dist/{provisioner.js → sandbox/provisioner.js} +3 -3
  314. package/dist/sandbox/provisioner.js.map +1 -0
  315. package/dist/sandbox/types.d.ts +2 -0
  316. package/dist/sandbox/types.d.ts.map +1 -1
  317. package/dist/sandbox/types.js.map +1 -1
  318. package/dist/sandbox/utils.d.ts +5 -0
  319. package/dist/sandbox/utils.d.ts.map +1 -1
  320. package/dist/sandbox/utils.js +14 -0
  321. package/dist/sandbox/utils.js.map +1 -1
  322. package/dist/sessions/chat-history-sync.d.ts.map +1 -1
  323. package/dist/sessions/chat-history-sync.js +72 -62
  324. package/dist/sessions/chat-history-sync.js.map +1 -1
  325. package/dist/sessions/migrate-common.d.ts +43 -0
  326. package/dist/sessions/migrate-common.d.ts.map +1 -0
  327. package/dist/sessions/migrate-common.js +99 -0
  328. package/dist/sessions/migrate-common.js.map +1 -0
  329. package/dist/sessions/migrate-pi-084.d.ts.map +1 -1
  330. package/dist/sessions/migrate-pi-084.js +152 -203
  331. package/dist/sessions/migrate-pi-084.js.map +1 -1
  332. package/dist/sessions/migrate-v3.d.ts +5 -0
  333. package/dist/sessions/migrate-v3.d.ts.map +1 -1
  334. package/dist/sessions/migrate-v3.js +161 -209
  335. package/dist/sessions/migrate-v3.js.map +1 -1
  336. package/dist/{harness → sessions}/session-store.d.ts +12 -1
  337. package/dist/sessions/session-store.d.ts.map +1 -0
  338. package/dist/{harness → sessions}/session-store.js +74 -35
  339. package/dist/sessions/session-store.js.map +1 -0
  340. package/dist/sessions/store.d.ts +1 -1
  341. package/dist/sessions/store.d.ts.map +1 -1
  342. package/dist/sessions/store.js +18 -17
  343. package/dist/sessions/store.js.map +1 -1
  344. package/dist/sessions/types.d.ts +40 -1
  345. package/dist/sessions/types.d.ts.map +1 -1
  346. package/dist/sessions/types.js +1 -1
  347. package/dist/sessions/types.js.map +1 -1
  348. package/dist/types.d.ts +7 -99
  349. package/dist/types.d.ts.map +1 -1
  350. package/dist/types.js.map +1 -1
  351. package/dist/vault/index.d.ts.map +1 -1
  352. package/dist/vault/index.js +70 -53
  353. package/dist/vault/index.js.map +1 -1
  354. package/package.json +10 -4
  355. package/dist/adapters/slack/tools/attach.d.ts.map +0 -1
  356. package/dist/adapters/slack/tools/attach.js.map +0 -1
  357. package/dist/agent/catalog.d.ts +0 -22
  358. package/dist/agent/catalog.d.ts.map +0 -1
  359. package/dist/agent/catalog.js +0 -104
  360. package/dist/agent/catalog.js.map +0 -1
  361. package/dist/agent/execution.d.ts +0 -25
  362. package/dist/agent/execution.d.ts.map +0 -1
  363. package/dist/agent/execution.js +0 -171
  364. package/dist/agent/execution.js.map +0 -1
  365. package/dist/agent/presenter.d.ts.map +0 -1
  366. package/dist/agent/presenter.js.map +0 -1
  367. package/dist/agent/prompt.d.ts.map +0 -1
  368. package/dist/agent/prompt.js.map +0 -1
  369. package/dist/agent/runner.d.ts +0 -3
  370. package/dist/agent/runner.d.ts.map +0 -1
  371. package/dist/agent/runner.js +0 -452
  372. package/dist/agent/runner.js.map +0 -1
  373. package/dist/agent/types.d.ts +0 -101
  374. package/dist/agent/types.d.ts.map +0 -1
  375. package/dist/agent/types.js +0 -3
  376. package/dist/agent/types.js.map +0 -1
  377. package/dist/agent-events.d.ts +0 -6
  378. package/dist/agent-events.d.ts.map +0 -1
  379. package/dist/agent-events.js +0 -44
  380. package/dist/agent-events.js.map +0 -1
  381. package/dist/commands/admin.d.ts.map +0 -1
  382. package/dist/commands/admin.js.map +0 -1
  383. package/dist/commands/auto-reply.d.ts +0 -8
  384. package/dist/commands/auto-reply.d.ts.map +0 -1
  385. package/dist/commands/auto-reply.js +0 -65
  386. package/dist/commands/auto-reply.js.map +0 -1
  387. package/dist/commands/login.d.ts.map +0 -1
  388. package/dist/commands/login.js +0 -158
  389. package/dist/commands/login.js.map +0 -1
  390. package/dist/commands/manifest.d.ts.map +0 -1
  391. package/dist/commands/manifest.js.map +0 -1
  392. package/dist/commands/model.d.ts.map +0 -1
  393. package/dist/commands/model.js.map +0 -1
  394. package/dist/commands/new.d.ts.map +0 -1
  395. package/dist/commands/new.js.map +0 -1
  396. package/dist/commands/registry.d.ts.map +0 -1
  397. package/dist/commands/registry.js.map +0 -1
  398. package/dist/commands/sandbox.d.ts.map +0 -1
  399. package/dist/commands/sandbox.js.map +0 -1
  400. package/dist/commands/session-view.d.ts.map +0 -1
  401. package/dist/commands/session-view.js.map +0 -1
  402. package/dist/commands/types.d.ts.map +0 -1
  403. package/dist/commands/types.js.map +0 -1
  404. package/dist/commands/utils.d.ts +0 -11
  405. package/dist/commands/utils.d.ts.map +0 -1
  406. package/dist/commands/utils.js.map +0 -1
  407. package/dist/events.d.ts.map +0 -1
  408. package/dist/events.js.map +0 -1
  409. package/dist/execution-resolver.d.ts +0 -27
  410. package/dist/execution-resolver.d.ts.map +0 -1
  411. package/dist/execution-resolver.js.map +0 -1
  412. package/dist/harness/event-format.d.ts +0 -33
  413. package/dist/harness/event-format.d.ts.map +0 -1
  414. package/dist/harness/event-format.js.map +0 -1
  415. package/dist/harness/session-store.d.ts.map +0 -1
  416. package/dist/harness/session-store.js.map +0 -1
  417. package/dist/harness/settings.d.ts +0 -29
  418. package/dist/harness/settings.d.ts.map +0 -1
  419. package/dist/harness/settings.js +0 -40
  420. package/dist/harness/settings.js.map +0 -1
  421. package/dist/harness/subagent-runner.d.ts.map +0 -1
  422. package/dist/harness/subagent-runner.js.map +0 -1
  423. package/dist/harness/subagent-slots.d.ts +0 -28
  424. package/dist/harness/subagent-slots.d.ts.map +0 -1
  425. package/dist/harness/subagent-slots.js +0 -72
  426. package/dist/harness/subagent-slots.js.map +0 -1
  427. package/dist/harness/usage.d.ts +0 -11
  428. package/dist/harness/usage.d.ts.map +0 -1
  429. package/dist/harness/usage.js +0 -38
  430. package/dist/harness/usage.js.map +0 -1
  431. package/dist/mcp/catalog.d.ts +0 -5
  432. package/dist/mcp/catalog.d.ts.map +0 -1
  433. package/dist/mcp/catalog.js +0 -68
  434. package/dist/mcp/catalog.js.map +0 -1
  435. package/dist/mcp/loader.d.ts +0 -12
  436. package/dist/mcp/loader.d.ts.map +0 -1
  437. package/dist/mcp/loader.js.map +0 -1
  438. package/dist/mcp/open-connector.d.ts.map +0 -1
  439. package/dist/mcp/open-connector.js.map +0 -1
  440. package/dist/mcp/types.d.ts +0 -66
  441. package/dist/mcp/types.d.ts.map +0 -1
  442. package/dist/mcp/types.js.map +0 -1
  443. package/dist/packages/index.d.ts +0 -169
  444. package/dist/packages/index.d.ts.map +0 -1
  445. package/dist/packages/index.js +0 -721
  446. package/dist/packages/index.js.map +0 -1
  447. package/dist/packages/types.d.ts +0 -100
  448. package/dist/packages/types.d.ts.map +0 -1
  449. package/dist/packages/types.js.map +0 -1
  450. package/dist/provisioner.d.ts.map +0 -1
  451. package/dist/provisioner.js.map +0 -1
  452. package/dist/subagent-progress.d.ts +0 -39
  453. package/dist/subagent-progress.d.ts.map +0 -1
  454. package/dist/subagent-progress.js +0 -225
  455. package/dist/subagent-progress.js.map +0 -1
  456. package/dist/tools/bash.d.ts +0 -12
  457. package/dist/tools/bash.d.ts.map +0 -1
  458. package/dist/tools/bash.js +0 -80
  459. package/dist/tools/bash.js.map +0 -1
  460. package/dist/tools/edit.d.ts +0 -11
  461. package/dist/tools/edit.d.ts.map +0 -1
  462. package/dist/tools/edit.js +0 -132
  463. package/dist/tools/edit.js.map +0 -1
  464. package/dist/tools/event.d.ts.map +0 -1
  465. package/dist/tools/event.js +0 -255
  466. package/dist/tools/event.js.map +0 -1
  467. package/dist/tools/generate-image.d.ts.map +0 -1
  468. package/dist/tools/generate-image.js.map +0 -1
  469. package/dist/tools/host-fn-tool.d.ts.map +0 -1
  470. package/dist/tools/host-fn-tool.js.map +0 -1
  471. package/dist/tools/index.d.ts.map +0 -1
  472. package/dist/tools/index.js.map +0 -1
  473. package/dist/tools/react.d.ts.map +0 -1
  474. package/dist/tools/react.js.map +0 -1
  475. package/dist/tools/read.d.ts +0 -12
  476. package/dist/tools/read.d.ts.map +0 -1
  477. package/dist/tools/read.js +0 -140
  478. package/dist/tools/read.js.map +0 -1
  479. package/dist/tools/sandbox.d.ts.map +0 -1
  480. package/dist/tools/sandbox.js.map +0 -1
  481. package/dist/tools/subagent.d.ts.map +0 -1
  482. package/dist/tools/subagent.js.map +0 -1
  483. package/dist/tools/types.d.ts.map +0 -1
  484. package/dist/tools/types.js.map +0 -1
  485. package/dist/tools/write.d.ts +0 -10
  486. package/dist/tools/write.d.ts.map +0 -1
  487. package/dist/tools/write.js +0 -23
  488. package/dist/tools/write.js.map +0 -1
  489. package/dist/trigger.d.ts +0 -23
  490. package/dist/trigger.d.ts.map +0 -1
  491. package/dist/trigger.js +0 -97
  492. package/dist/trigger.js.map +0 -1
  493. package/dist/utils/file-guards.d.ts.map +0 -1
  494. package/dist/utils/file-guards.js.map +0 -1
  495. package/dist/web/admin/portal.d.ts.map +0 -1
  496. package/dist/web/admin/portal.js.map +0 -1
  497. package/dist/web/admin/provider-models.d.ts.map +0 -1
  498. package/dist/web/admin/provider-models.js.map +0 -1
  499. package/dist/web/admin/types.d.ts.map +0 -1
  500. package/dist/web/admin/types.js.map +0 -1
  501. package/dist/web/login/oauth.d.ts.map +0 -1
  502. package/dist/web/login/oauth.js.map +0 -1
  503. package/dist/web/login/portal.d.ts.map +0 -1
  504. package/dist/web/login/portal.js.map +0 -1
  505. package/dist/web/login/types.d.ts.map +0 -1
  506. package/dist/web/login/types.js.map +0 -1
  507. package/dist/web/portal-shell.d.ts.map +0 -1
  508. package/dist/web/portal-shell.js.map +0 -1
  509. package/dist/web/server.d.ts.map +0 -1
  510. package/dist/web/server.js.map +0 -1
  511. package/dist/web/session-view/portal.d.ts.map +0 -1
  512. package/dist/web/session-view/portal.js.map +0 -1
  513. package/dist/web/session-view/types.d.ts.map +0 -1
  514. package/dist/web/session-view/types.js +0 -2
  515. package/dist/web/session-view/types.js.map +0 -1
  516. package/dist/web/token-store.d.ts.map +0 -1
  517. package/dist/web/token-store.js.map +0 -1
  518. package/dist/web/types.d.ts.map +0 -1
  519. package/dist/web/types.js +0 -2
  520. package/dist/web/types.js.map +0 -1
  521. package/dist/workspace-projection/index.d.ts.map +0 -1
  522. package/dist/workspace-projection/index.js.map +0 -1
  523. package/dist/workspace-projection/types.d.ts +0 -29
  524. package/dist/workspace-projection/types.d.ts.map +0 -1
  525. package/dist/workspace-projection/types.js +0 -2
  526. package/dist/workspace-projection/types.js.map +0 -1
  527. /package/dist/{commands → adapters/commands}/admin.d.ts +0 -0
  528. /package/dist/{commands → adapters/commands}/login.d.ts +0 -0
  529. /package/dist/{commands → adapters/commands}/manifest.d.ts +0 -0
  530. /package/dist/{commands → adapters/commands}/new.d.ts +0 -0
  531. /package/dist/{commands → adapters/commands}/registry.d.ts +0 -0
  532. /package/dist/{commands → adapters/commands}/sandbox.d.ts +0 -0
  533. /package/dist/{commands → adapters/commands}/session-view.d.ts +0 -0
  534. /package/dist/{commands → adapters/commands}/types.js +0 -0
  535. /package/dist/{web → adapters/web}/admin/provider-models.js +0 -0
  536. /package/dist/{mcp → adapters/web/admin}/types.js +0 -0
  537. /package/dist/{web → adapters/web}/login/oauth.d.ts +0 -0
  538. /package/dist/{packages → adapters/web/login}/types.js +0 -0
  539. /package/dist/{web → adapters/web}/session-view/portal.d.ts +0 -0
  540. /package/dist/{tools → adapters/web/session-view}/types.js +0 -0
  541. /package/dist/{web → adapters/web}/token-store.d.ts +0 -0
  542. /package/dist/{web → adapters/web}/token-store.js +0 -0
  543. /package/dist/{web → adapters/web}/types.d.ts +0 -0
  544. /package/dist/{web/admin → adapters/web}/types.js +0 -0
  545. /package/dist/{utils/file-guards.d.ts → file-guards.d.ts} +0 -0
  546. /package/dist/{utils/file-guards.js → file-guards.js} +0 -0
  547. /package/dist/{mcp → harness}/open-connector.d.ts +0 -0
  548. /package/dist/{adapters/slack → harness}/tools/attach.d.ts +0 -0
  549. /package/dist/{adapters/slack → harness}/tools/attach.js +0 -0
  550. /package/dist/{tools → harness/tools}/generate-image.d.ts +0 -0
  551. /package/dist/{tools → harness/tools}/generate-image.js +0 -0
  552. /package/dist/{tools → harness/tools}/host-fn-tool.d.ts +0 -0
  553. /package/dist/{tools → harness/tools}/host-fn-tool.js +0 -0
  554. /package/dist/{tools → harness/tools}/react.d.ts +0 -0
  555. /package/dist/{tools → harness/tools}/react.js +0 -0
  556. /package/dist/{web/login → harness/tools}/types.js +0 -0
package/CHANGELOG.md CHANGED
@@ -9,6 +9,35 @@ any release.
9
9
 
10
10
  ## [Unreleased]
11
11
 
12
+ ## [1.0.0-beta.55]
13
+
14
+ ### Added
15
+
16
+ - Export explicitly configured, content-free traces and metrics over standard OTLP HTTP/protobuf, including GenAI and OpenInference attribution for Arize Phoenix. Sentry remains available for sanitized issues and legacy metric fallback without duplicate spans; zero configuration remains network-free.
17
+ - Add a guided Admin dialog for configuring MCP servers, with structured fields or pasted standard `mcpServers` JSON and card-based installed-server management.
18
+
19
+ ### Changed
20
+
21
+ - Delegate the agent run loop, retries, compaction, persistence, cancellation, and the native `read`, `write`, `edit`, and `bash` tools to Pi's `AgentHarness` and execution-tool implementations. mikan retains budgets, platform presentation, authorization, and sandbox-backed execution routing.
22
+ - Upgrade `pi-agent-core` and `pi-ai` to 0.85.1, including GPT-6 Astra catalog entries and the 30-minute prompt-cache TTL for GPT-5.6+ Responses models.
23
+ - Consolidate harness, office, session, sandbox, web-adapter, and shared-command ownership without changing the published root exports.
24
+
25
+ ### Removed
26
+
27
+ - Remove managed skill packages and their Admin/package materialization surfaces. Workspace and conversation skills remain supported.
28
+ - Remove the auto-reply judge, command, configuration, and UI; explicit platform triggers remain supported.
29
+ - Remove the unused `/api/agent-events/stream` SSE mirror, its token setting, and supporting event types. The authenticated session viewer continues to use `/session/stream`.
30
+
31
+ ### Fixed
32
+
33
+ - Preserve Pi's native optional tool schemas, require an explicit authorized execution environment for native file/shell tools, and keep container working directories inside the guest instead of applying them to the host Docker process.
34
+
35
+ ## [1.0.0-beta.54]
36
+
37
+ ### Changed
38
+
39
+ - Admin portal: MCP servers are added by pasting the server's standard `mcpServers` JSON (Claude Desktop / Cursor shape), stored as-is; the old name / target / `KEY=value` form is gone. Every add and preset install is followed by a real connection check, and the response shows the tool count or the server's own error; a per-server **Test** button re-checks an installed entry. Query-string values in listed URLs are redacted. stdio entries now run their command on the host at save time.
40
+
12
41
  ## [1.0.0-beta.53]
13
42
 
14
43
  ### Changed
package/README.md CHANGED
@@ -21,7 +21,7 @@ mikan keeps the chat record, agent session, and execution runtime separate:
21
21
  - **Conversation office** is the unit everything else hangs off: one conversation's working area plus its own sandbox runtime. An office is identified by its platform and raw conversation id, and its directory is named by an office key (`v1-<platform>-<readable-id>-<hash>`), so two platforms can never collide on the same raw id.
22
22
  - **Chat / conversation data** is the platform-facing record: `log.jsonl`, attachments, and conversation files.
23
23
  - **Session orchestration** turns platform events into agent runs, handles top-level/thread scopes, and persists structured context under `sessions/*.jsonl`.
24
- - **mikan agent harness** (`src/harness/`, built on pi-agent-core and pi-ai) runs the model loop, session persistence, compaction, and calls mikan tools.
24
+ - **mikan agent harness** (`src/harness/`, built on pi-agent-core and pi-ai) owns run preparation, authorized prompts/tools, response presentation, and native Pi session integration. Pi handles the model/tool loop, persistence, compaction, retries, and cancellation.
25
25
  - **Sandbox runtime** is where tool commands execute: host, Docker container/image, or the experimental Cloudflare bridge.
26
26
  - **Vault** provides runtime credentials as env vars and mounted secret files.
27
27
 
@@ -141,7 +141,6 @@ For routing, mounts, vault behavior, managed container details, and Cloudflare n
141
141
  | `/model` / `/pi-model provider/model[:thinking]` | Switch the LLM for the current conversation |
142
142
  | `/sandbox` / `/pi-sandbox [boost\|door …]` | Show sandbox status, boost limits, or set the office door policy |
143
143
  | `/admin` / `/pi-admin` | Open the admin portal |
144
- | `/auto-reply` / `/pi-auto-reply on\|off\|status` | Control group/channel auto-reply |
145
144
  | `stop` / `/stop` | Stop the current run (works on every platform) |
146
145
 
147
146
  `session` is the only command accepted without a leading slash. See [src/content/docs/commands.mdx](src/content/docs/commands.mdx) for the full command reference and web session viewer setup.
@@ -224,3 +223,5 @@ PRs welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) for dev setup, commit sty
224
223
  ## License
225
224
 
226
225
  MIT — see [LICENSE](LICENSE).
226
+
227
+ Auto-reply has been retired. Existing `auto-reply` / `auto-reply.disabled` marker files and `llm.autoReply` / `autoReply` settings no longer take effect; reading configuration does not delete these files.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../../../src/adapters/commands/admin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAKjE,qBAAa,mBAAoB,YAAW,cAAc;IAClD,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAuBzD;CACF"}
@@ -1,16 +1,12 @@
1
- import { slashForms } from "./manifest.js";
2
- import { matchCommand } from "./manifest.js";
3
- import { formatCommandSummary, replyPrivatelyWithContext } from "./utils.js";
1
+ import { slashForms, matchCommand } from "./manifest.js";
2
+ import { portalNotConfiguredLines, replySummaryPrivately } from "./utils.js";
4
3
  const ADMIN_COMMANDS = slashForms("admin");
5
4
  export class AdminCommandHandler {
6
5
  async tryHandle(context) {
7
6
  if (!matchCommand(context.commandText, ADMIN_COMMANDS, { stripMention: true }))
8
7
  return false;
9
8
  if (!context.services.portalBaseUrl) {
10
- await replyPrivatelyWithContext(context, formatCommandSummary("Admin", [
11
- "Admin portal is not configured.",
12
- "Set `MIKAN_LINK_URL` or `MIKAN_LINK_PORT` on the server.",
13
- ]), { style: "muted" });
9
+ await replySummaryPrivately(context, "Admin", portalNotConfiguredLines("Admin portal"));
14
10
  return true;
15
11
  }
16
12
  const platformUser = context.bot
@@ -24,7 +20,7 @@ export class AdminCommandHandler {
24
20
  ...(platformUserName ? { platformUserName } : {}),
25
21
  });
26
22
  const url = `${context.services.portalBaseUrl}/admin?token=${token.token}`;
27
- await replyPrivatelyWithContext(context, formatCommandSummary("Admin", [url, "Expires: 30 minutes"]), { style: "muted" });
23
+ await replySummaryPrivately(context, "Admin", [url, "Expires: 30 minutes"]);
28
24
  return true;
29
25
  }
30
26
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.js","sourceRoot":"","sources":["../../../src/adapters/commands/admin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAEzD,OAAO,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAE7E,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;AAE3C,MAAM,OAAO,mBAAmB;IAC9B,KAAK,CAAC,SAAS,CAAC,OAAuB;QACrC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,cAAc,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;YAAE,OAAO,KAAK,CAAC;QAE7F,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;YACpC,MAAM,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,wBAAwB,CAAC,cAAc,CAAC,CAAC,CAAC;YACxF,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG;aAC7B,gBAAgB,EAAE;aAClB,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;QAC5D,MAAM,gBAAgB,GAAG,YAAY,EAAE,QAAQ,IAAI,YAAY,EAAE,WAAW,CAAC;QAE7E,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC;YACpD,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,cAAc,EAAE,OAAO,CAAC,cAAc;YACtC,cAAc,EAAE,OAAO,CAAC,cAAc;YACtC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAClD,CAAC,CAAC;QAEH,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,aAAa,gBAAgB,KAAK,CAAC,KAAK,EAAE,CAAC;QAC3E,MAAM,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC,CAAC;QAC5E,OAAO,IAAI,CAAC;IACd,CAAC;CACF","sourcesContent":["import { slashForms, matchCommand } from \"./manifest.js\";\nimport type { CommandContext, CommandHandler } from \"./types.js\";\nimport { portalNotConfiguredLines, replySummaryPrivately } from \"./utils.js\";\n\nconst ADMIN_COMMANDS = slashForms(\"admin\");\n\nexport class AdminCommandHandler implements CommandHandler {\n async tryHandle(context: CommandContext): Promise<boolean> {\n if (!matchCommand(context.commandText, ADMIN_COMMANDS, { stripMention: true })) return false;\n\n if (!context.services.portalBaseUrl) {\n await replySummaryPrivately(context, \"Admin\", portalNotConfiguredLines(\"Admin portal\"));\n return true;\n }\n\n const platformUser = context.bot\n .getMessagingInfo()\n .users.find((user) => user.id === context.platformUserId);\n const platformUserName = platformUser?.userName || platformUser?.displayName;\n\n const token = context.services.adminTokenStore.create({\n platform: context.platform,\n platformUserId: context.platformUserId,\n conversationId: context.conversationId,\n ...(platformUserName ? { platformUserName } : {}),\n });\n\n const url = `${context.services.portalBaseUrl}/admin?token=${token.token}`;\n await replySummaryPrivately(context, \"Admin\", [url, \"Expires: 30 minutes\"]);\n return true;\n }\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/adapters/commands/login.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAQrF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAazE;AAkDD,qBAAa,mBAAoB,YAAW,cAAc;IAClD,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAiBzD;CACF"}
@@ -0,0 +1,166 @@
1
+ import * as log from "../../log.js";
2
+ import { credentialAuthorizationKey, runtimeResourceKey } from "../../sandbox/identity.js";
3
+ import { sharedVaultKey } from "../../vault/index.js";
4
+ import { slashForms, matchCommand } from "./manifest.js";
5
+ import { portalNotConfiguredLines, replySummary } from "./utils.js";
6
+ import { createOfficeAddress } from "../../office/index.js";
7
+ const LOGIN_COMMANDS = slashForms("login");
8
+ const SHARED_OPERATIONS = ["create", "update", "delete"];
9
+ export function parseLoginCommand(text) {
10
+ const matched = matchCommand(text, LOGIN_COMMANDS);
11
+ if (!matched)
12
+ return null;
13
+ const [subcommand, operation, name, ...extra] = matched.args;
14
+ if (!subcommand)
15
+ return { action: "setup" };
16
+ if (extra.length > 0)
17
+ return null;
18
+ const verb = subcommand.toLowerCase();
19
+ if (verb === "shared")
20
+ return parseSharedLogin(operation?.toLowerCase(), name);
21
+ if (verb === "copy" && operation && !name)
22
+ return { action: "copy_shared", name: operation };
23
+ // Backward-compatible provider arguments open the generic login page.
24
+ return operation ? null : { action: "setup" };
25
+ }
26
+ function parseSharedLogin(operation, name) {
27
+ if (operation === "list")
28
+ return name ? null : { action: "shared_list" };
29
+ const matched = SHARED_OPERATIONS.find((candidate) => candidate === operation);
30
+ if (!matched || !name)
31
+ return null;
32
+ return { action: `shared_${matched}`, name };
33
+ }
34
+ function ensureLoginVault(context) {
35
+ const { services, platformUserId, conversationId, vaultConversationId } = context;
36
+ // The vault target is a conversation on the same platform; a command may
37
+ // aim at another conversation's vault via vaultConversationId.
38
+ return credentialAuthorizationKey(services.sandbox, {
39
+ userId: platformUserId,
40
+ address: createOfficeAddress(context.address.platform, vaultConversationId ?? conversationId),
41
+ });
42
+ }
43
+ async function refreshCopiedVaultRuntime(context) {
44
+ if (context.services.sandbox.type !== "image")
45
+ return undefined;
46
+ const targetAddress = createOfficeAddress(context.address.platform, context.vaultConversationId ?? context.conversationId);
47
+ const cleared = context.services.runtime?.refreshConversationEnvironment(targetAddress);
48
+ if (cleared === false) {
49
+ return "A session is currently running, so the sandbox was not restarted. The copied credentials will be applied after the run finishes and the sandbox is recreated.";
50
+ }
51
+ if (!context.services.provisioner) {
52
+ return "The cached session was refreshed. The sandbox will pick up copied credentials on the next provision.";
53
+ }
54
+ // The provisioner names containers by runtime resource key, not by the
55
+ // credential key the vault copy used — the two identities differ in image
56
+ // mode (office key vs raw-conversation key). Removing by the wrong key
57
+ // would silently leave the real container running with stale mounts.
58
+ const resourceKey = runtimeResourceKey(context.services.sandbox, {
59
+ userId: context.platformUserId,
60
+ address: targetAddress,
61
+ });
62
+ await context.services.provisioner.remove(resourceKey);
63
+ return "The sandbox container was removed and will be recreated with the copied env and file mounts on the next message.";
64
+ }
65
+ export class LoginCommandHandler {
66
+ async tryHandle(context) {
67
+ const parsed = parseLoginCommand(context.commandText);
68
+ if (!parsed)
69
+ return false;
70
+ if (!context.privateConversation) {
71
+ await replySummary(context, "Vault", [
72
+ "為了保護你的憑證,`/login` 只能在與機器人的私訊中使用。",
73
+ "請先私訊機器人,再重新執行 `/login`。",
74
+ ]);
75
+ return true;
76
+ }
77
+ if (parsed.action === "shared_list")
78
+ await listSharedProfiles(context);
79
+ else if (parsed.action === "shared_delete")
80
+ await deleteSharedProfile(context, parsed.name);
81
+ else if (parsed.action === "copy_shared")
82
+ await copySharedProfile(context, parsed.name);
83
+ else
84
+ await startLoginSetup(context, parsed);
85
+ return true;
86
+ }
87
+ }
88
+ /** Surface a vault-manager failure to the user without failing the command. */
89
+ async function replyVaultError(context, error) {
90
+ await replySummary(context, "Vault", [error instanceof Error ? error.message : String(error)]);
91
+ }
92
+ async function listSharedProfiles(context) {
93
+ const profiles = context.services.vaultManager.listSharedVaults();
94
+ await replySummary(context, "Vault", profiles.length > 0
95
+ ? ["Shared login profiles:", ...profiles.map((name) => `- ${name}`)]
96
+ : ["No shared login profiles found."]);
97
+ }
98
+ async function deleteSharedProfile(context, name) {
99
+ try {
100
+ const deleted = context.services.vaultManager.deleteSharedVault(name);
101
+ await replySummary(context, "Vault", [
102
+ deleted
103
+ ? `Deleted shared login profile \`${name}\`.`
104
+ : `Shared login profile \`${name}\` does not exist.`,
105
+ ]);
106
+ }
107
+ catch (error) {
108
+ await replyVaultError(context, error);
109
+ }
110
+ }
111
+ async function copySharedProfile(context, name) {
112
+ try {
113
+ const vaultId = ensureLoginVault(context);
114
+ const result = context.services.vaultManager.copySharedVaultTo(name, vaultId);
115
+ const refreshNote = await refreshCopiedVaultRuntime(context);
116
+ await replySummary(context, "Vault", [
117
+ `Copied shared login profile \`${name}\` into this conversation.`,
118
+ "Shared values overwrite matching conversation values; conversation-only values are kept.",
119
+ `Copied: ${result.envKeysCopied} env key(s), ${result.filesCopied} file(s).`,
120
+ ...(refreshNote ? [refreshNote] : []),
121
+ ]);
122
+ }
123
+ catch (error) {
124
+ await replyVaultError(context, error);
125
+ }
126
+ }
127
+ /** Issue a portal link for this conversation's vault, or for a shared profile. */
128
+ async function startLoginSetup(context, parsed) {
129
+ if (!context.services.portalBaseUrl) {
130
+ await replySummary(context, "Vault", portalNotConfiguredLines("Login"));
131
+ return;
132
+ }
133
+ let vaultId;
134
+ try {
135
+ vaultId = resolveLoginVaultId(context, parsed);
136
+ }
137
+ catch (error) {
138
+ log.logWarning(`[${context.conversationId}] Failed to prepare login vault for ${context.platform}/${context.platformUserId}`, error instanceof Error ? error.message : String(error));
139
+ await replySummary(context, "Vault", [
140
+ "Login setup failed on the server.",
141
+ "請稍後重試,或聯絡管理員檢查 vault 儲存權限。",
142
+ ]);
143
+ return;
144
+ }
145
+ const token = context.services.linkTokenStore.create(context.platform, context.platformUserId, context.conversationId, vaultId, "");
146
+ await replySummary(context, "Vault", [
147
+ `${context.services.portalBaseUrl}/link?token=${token.token}`,
148
+ `Target: ${loginVaultLabel(context, parsed, vaultId)} · Expires: 15 minutes`,
149
+ ]);
150
+ }
151
+ function resolveLoginVaultId(context, parsed) {
152
+ const isSharedSetup = parsed.action === "shared_create" || parsed.action === "shared_update";
153
+ const vaultId = isSharedSetup ? (sharedVaultKey(parsed.name) ?? "") : ensureLoginVault(context);
154
+ if (vaultId)
155
+ return vaultId;
156
+ throw new Error(isSharedSetup ? `Invalid shared login profile name: ${parsed.name}` : "Invalid vault id");
157
+ }
158
+ function loginVaultLabel(context, parsed, vaultId) {
159
+ if (parsed.action === "shared_create" || parsed.action === "shared_update") {
160
+ return `shared login profile (${parsed.name})`;
161
+ }
162
+ return context.services.sandbox.type === "container"
163
+ ? `container vault (${vaultId})`
164
+ : "your vault";
165
+ }
166
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/adapters/commands/login.ts"],"names":[],"mappings":"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","sourcesContent":["import * as log from \"../../log.js\";\nimport { credentialAuthorizationKey, runtimeResourceKey } from \"../../sandbox/identity.js\";\nimport { sharedVaultKey } from \"../../vault/index.js\";\nimport { slashForms, matchCommand } from \"./manifest.js\";\nimport type { CommandContext, CommandHandler, ParsedLoginCommand } from \"./types.js\";\nimport { portalNotConfiguredLines, replySummary } from \"./utils.js\";\nimport { createOfficeAddress } from \"../../office/index.js\";\n\nconst LOGIN_COMMANDS = slashForms(\"login\");\n\nconst SHARED_OPERATIONS = [\"create\", \"update\", \"delete\"] as const;\n\nexport function parseLoginCommand(text: string): ParsedLoginCommand | null {\n const matched = matchCommand(text, LOGIN_COMMANDS);\n if (!matched) return null;\n\n const [subcommand, operation, name, ...extra] = matched.args;\n if (!subcommand) return { action: \"setup\" };\n if (extra.length > 0) return null;\n\n const verb = subcommand.toLowerCase();\n if (verb === \"shared\") return parseSharedLogin(operation?.toLowerCase(), name);\n if (verb === \"copy\" && operation && !name) return { action: \"copy_shared\", name: operation };\n // Backward-compatible provider arguments open the generic login page.\n return operation ? null : { action: \"setup\" };\n}\n\nfunction parseSharedLogin(\n operation: string | undefined,\n name: string | undefined,\n): ParsedLoginCommand | null {\n if (operation === \"list\") return name ? null : { action: \"shared_list\" };\n const matched = SHARED_OPERATIONS.find((candidate) => candidate === operation);\n if (!matched || !name) return null;\n return { action: `shared_${matched}`, name };\n}\n\nfunction ensureLoginVault(context: CommandContext): string {\n const { services, platformUserId, conversationId, vaultConversationId } = context;\n // The vault target is a conversation on the same platform; a command may\n // aim at another conversation's vault via vaultConversationId.\n return credentialAuthorizationKey(services.sandbox, {\n userId: platformUserId,\n address: createOfficeAddress(context.address.platform, vaultConversationId ?? conversationId),\n });\n}\n\nasync function refreshCopiedVaultRuntime(context: CommandContext): Promise<string | undefined> {\n if (context.services.sandbox.type !== \"image\") return undefined;\n\n const targetAddress = createOfficeAddress(\n context.address.platform,\n context.vaultConversationId ?? context.conversationId,\n );\n const cleared = context.services.runtime?.refreshConversationEnvironment(targetAddress);\n if (cleared === false) {\n return \"A session is currently running, so the sandbox was not restarted. The copied credentials will be applied after the run finishes and the sandbox is recreated.\";\n }\n\n if (!context.services.provisioner) {\n return \"The cached session was refreshed. The sandbox will pick up copied credentials on the next provision.\";\n }\n\n // The provisioner names containers by runtime resource key, not by the\n // credential key the vault copy used — the two identities differ in image\n // mode (office key vs raw-conversation key). Removing by the wrong key\n // would silently leave the real container running with stale mounts.\n const resourceKey = runtimeResourceKey(context.services.sandbox, {\n userId: context.platformUserId,\n address: targetAddress,\n });\n await context.services.provisioner.remove(resourceKey);\n return \"The sandbox container was removed and will be recreated with the copied env and file mounts on the next message.\";\n}\n\nexport class LoginCommandHandler implements CommandHandler {\n async tryHandle(context: CommandContext): Promise<boolean> {\n const parsed = parseLoginCommand(context.commandText);\n if (!parsed) return false;\n\n if (!context.privateConversation) {\n await replySummary(context, \"Vault\", [\n \"為了保護你的憑證,`/login` 只能在與機器人的私訊中使用。\",\n \"請先私訊機器人,再重新執行 `/login`。\",\n ]);\n return true;\n }\n\n if (parsed.action === \"shared_list\") await listSharedProfiles(context);\n else if (parsed.action === \"shared_delete\") await deleteSharedProfile(context, parsed.name);\n else if (parsed.action === \"copy_shared\") await copySharedProfile(context, parsed.name);\n else await startLoginSetup(context, parsed);\n return true;\n }\n}\n\n/** Surface a vault-manager failure to the user without failing the command. */\nasync function replyVaultError(context: CommandContext, error: unknown): Promise<void> {\n await replySummary(context, \"Vault\", [error instanceof Error ? error.message : String(error)]);\n}\n\nasync function listSharedProfiles(context: CommandContext): Promise<void> {\n const profiles = context.services.vaultManager.listSharedVaults();\n await replySummary(\n context,\n \"Vault\",\n profiles.length > 0\n ? [\"Shared login profiles:\", ...profiles.map((name) => `- ${name}`)]\n : [\"No shared login profiles found.\"],\n );\n}\n\nasync function deleteSharedProfile(context: CommandContext, name: string): Promise<void> {\n try {\n const deleted = context.services.vaultManager.deleteSharedVault(name);\n await replySummary(context, \"Vault\", [\n deleted\n ? `Deleted shared login profile \\`${name}\\`.`\n : `Shared login profile \\`${name}\\` does not exist.`,\n ]);\n } catch (error) {\n await replyVaultError(context, error);\n }\n}\n\nasync function copySharedProfile(context: CommandContext, name: string): Promise<void> {\n try {\n const vaultId = ensureLoginVault(context);\n const result = context.services.vaultManager.copySharedVaultTo(name, vaultId);\n const refreshNote = await refreshCopiedVaultRuntime(context);\n await replySummary(context, \"Vault\", [\n `Copied shared login profile \\`${name}\\` into this conversation.`,\n \"Shared values overwrite matching conversation values; conversation-only values are kept.\",\n `Copied: ${result.envKeysCopied} env key(s), ${result.filesCopied} file(s).`,\n ...(refreshNote ? [refreshNote] : []),\n ]);\n } catch (error) {\n await replyVaultError(context, error);\n }\n}\n\n/** Issue a portal link for this conversation's vault, or for a shared profile. */\nasync function startLoginSetup(context: CommandContext, parsed: ParsedLoginCommand): Promise<void> {\n if (!context.services.portalBaseUrl) {\n await replySummary(context, \"Vault\", portalNotConfiguredLines(\"Login\"));\n return;\n }\n\n let vaultId: string;\n try {\n vaultId = resolveLoginVaultId(context, parsed);\n } catch (error) {\n log.logWarning(\n `[${context.conversationId}] Failed to prepare login vault for ${context.platform}/${context.platformUserId}`,\n error instanceof Error ? error.message : String(error),\n );\n await replySummary(context, \"Vault\", [\n \"Login setup failed on the server.\",\n \"請稍後重試,或聯絡管理員檢查 vault 儲存權限。\",\n ]);\n return;\n }\n\n const token = context.services.linkTokenStore.create(\n context.platform,\n context.platformUserId,\n context.conversationId,\n vaultId,\n \"\",\n );\n await replySummary(context, \"Vault\", [\n `${context.services.portalBaseUrl}/link?token=${token.token}`,\n `Target: ${loginVaultLabel(context, parsed, vaultId)} · Expires: 15 minutes`,\n ]);\n}\n\nfunction resolveLoginVaultId(context: CommandContext, parsed: ParsedLoginCommand): string {\n const isSharedSetup = parsed.action === \"shared_create\" || parsed.action === \"shared_update\";\n const vaultId = isSharedSetup ? (sharedVaultKey(parsed.name) ?? \"\") : ensureLoginVault(context);\n if (vaultId) return vaultId;\n throw new Error(\n isSharedSetup ? `Invalid shared login profile name: ${parsed.name}` : \"Invalid vault id\",\n );\n}\n\nfunction loginVaultLabel(\n context: CommandContext,\n parsed: ParsedLoginCommand,\n vaultId: string,\n): string {\n if (parsed.action === \"shared_create\" || parsed.action === \"shared_update\") {\n return `shared login profile (${parsed.name})`;\n }\n return context.services.sandbox.type === \"container\"\n ? `container vault (${vaultId})`\n : \"your vault\";\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/adapters/commands/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD,YAAY,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAExE,sDAAsD;AACtD,eAAO,MAAM,gBAAgB,EAAE,SAAS,oBAAoB,EAyE3D,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,CAIvE;AAED,4FAA4F;AAC5F,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAM1D;AAED,0FAA0F;AAC1F,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAG5D;AAED,iFAAiF;AACjF,wBAAgB,mBAAmB,IAAI;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,EAAE,CAKhF;AAED,wBAAgB,YAAY,CAAC,OAAO,SAAS,MAAM,EACjD,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,SAAS,OAAO,EAAE,EAC3B,OAAO,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,GACnC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CAQ7C;AAkBD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD"}
@@ -87,13 +87,6 @@ export const COMMAND_MANIFEST = [
87
87
  slackCommand: "/pi-admin",
88
88
  slackRoute: { thread: true },
89
89
  },
90
- {
91
- name: "auto-reply",
92
- description: "Enable, disable, or show auto-reply for this channel",
93
- aliases: ["autoreply"],
94
- slackCommand: "/pi-auto-reply",
95
- slackRoute: { includeText: true },
96
- },
97
90
  ];
98
91
  export function commandManifestEntry(name) {
99
92
  const entry = COMMAND_MANIFEST.find((candidate) => candidate.name === name);
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../src/adapters/commands/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,sDAAsD;AACtD,MAAM,CAAC,MAAM,gBAAgB,GAAoC;IAC/D;QACE,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,yCAAyC;QACtD,YAAY,EAAE,WAAW;QACzB,UAAU,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE;QACvD,OAAO,EAAE,IAAI;QACb,YAAY,EAAE,EAAE;KACjB;IACD;QACE,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,4CAA4C;QACzD,IAAI,EAAE,IAAI;QACV,YAAY,EAAE,aAAa;QAC3B,UAAU,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;QAC5B,OAAO,EAAE,IAAI;QACb,YAAY,EAAE,EAAE;KACjB;IACD;QACE,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,sCAAsC;QACnD,GAAG,EAAE;YACH,IAAI,EAAE,OAAO;YACb,WAAW,EAAE,iEAAiE;YAC9E,QAAQ,EAAE,KAAK;SAChB;QACD,YAAY,EAAE,WAAW;QACzB,UAAU,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE;QACjC,OAAO,EAAE,IAAI;QACb,YAAY,EAAE,EAAE;KACjB;IACD;QACE,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,qCAAqC;QAClD,GAAG,EAAE;YACH,IAAI,EAAE,QAAQ;YACd,mEAAmE;YACnE,0DAA0D;YAC1D,sEAAsE;YACtE,kEAAkE;YAClE,mEAAmE;YACnE,uBAAuB;YACvB,WAAW,EAAE,yDAAyD;YACtE,QAAQ,EAAE,KAAK;SAChB;QACD,YAAY,EAAE,aAAa;QAC3B,UAAU,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE;QACjC,OAAO,EAAE,IAAI;QACb,YAAY,EAAE,EAAE,WAAW,EAAE,8BAA8B,EAAE;QAC7D,eAAe,EAAE,IAAI;KACtB;IACD;QACE,IAAI,EAAE,MAAM;QACZ,WAAW,EAAE,+BAA+B;QAC5C,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,IAAI;QACb,YAAY,EAAE,EAAE,WAAW,EAAE,2BAA2B,EAAE;KAC3D;IACD;QACE,IAAI,EAAE,KAAK;QACX,WAAW,EAAE,4CAA4C;QACzD,YAAY,EAAE,SAAS;QACvB,UAAU,EAAE,EAAE;QACd,OAAO,EAAE,IAAI;QACb,YAAY,EAAE,EAAE;QAChB,eAAe,EAAE,IAAI;KACtB;IACD;QACE,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,uBAAuB;QACpC,YAAY,EAAE,WAAW;QACzB,UAAU,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;KAC7B;CACF,CAAC;AAEF,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAC5E,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,IAAI,EAAE,CAAC,CAAC;IACpE,OAAO,KAAK,CAAC;AACf,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACzC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC;QAClE,IAAI,QAAQ,EAAE;QACd,OAAO,QAAQ,EAAE;KAClB,CAAC,CAAC;AACL,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;AACpE,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,mBAAmB;IACjC,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC5E,OAAO,EAAE,KAAK,CAAC,IAAI;QACnB,WAAW,EAAE,KAAK,CAAC,YAAY,EAAE,WAAW,IAAI,KAAK,CAAC,WAAW;KAClE,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,IAAY,EACZ,OAA2B,EAC3B,OAAoC;IAEpC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACxD,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACxB,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAErC,MAAM,KAAK,GAAG,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC1E,MAAM,OAAO,GAAG,KAAK,CAAC,WAAW,EAAa,CAAC;IAC/C,OAAO,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/E,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,aAAa,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;AAEpG,MAAM,oBAAoB,GAAG,IAAI,MAAM,CACrC,qBAAqB,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,sBAAsB,EAClE,GAAG,CACJ,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;AAChD,CAAC","sourcesContent":["/**\n * Platform-agnostic command manifest — the single inventory that platform\n * adapters derive their native slash-command registration and routing from,\n * and that `isCommandText` and the handler grammars mirror.\n *\n * Adding a command means adding a manifest entry plus a handler in this\n * directory; adapters pick up registration and routing from the entry instead\n * of hand-restating the inventory (where a missed spot used to mean a silent\n * no-response).\n *\n * Per CONTEXT.md, slash commands are a minimal chat control surface: detailed\n * or infrequent settings belong in Admin, and bare commands are limited to\n * `session`. `stop` is listed for platform registration/UI only — it is a\n * magic word owned by conversation intake, not a command handler.\n */\n\nimport type { CommandManifestEntry } from \"./types.js\";\n\nexport type { CommandManifestEntry, SlackSlashRoute } from \"./types.js\";\n\n/** Entry order is the Telegram command-menu order. */\nexport const COMMAND_MANIFEST: readonly CommandManifestEntry[] = [\n {\n name: \"login\",\n description: \"Store credentials in your private vault\",\n slackCommand: \"/pi-login\",\n slackRoute: { includeText: true, privateCommand: true },\n discord: true,\n telegramMenu: {},\n },\n {\n name: \"session\",\n description: \"Open the current session in the web viewer\",\n bare: true,\n slackCommand: \"/pi-session\",\n slackRoute: { thread: true },\n discord: true,\n telegramMenu: {},\n },\n {\n name: \"model\",\n description: \"Switch this conversation's LLM model\",\n arg: {\n name: \"model\",\n description: \"provider/model[:thinking], e.g. anthropic/claude-sonnet-4-6:off\",\n required: false,\n },\n slackCommand: \"/pi-model\",\n slackRoute: { includeText: true },\n discord: true,\n telegramMenu: {},\n },\n {\n name: \"sandbox\",\n description: \"Show sandbox status or boost limits\",\n arg: {\n name: \"action\",\n // Discord caps option descriptions at 100 characters (registration\n // fails otherwise); commands.test.ts enforces the budget.\n // The `door` action still works but is deliberately undocumented: the\n // workspace posture follows the platform's own channel visibility\n // automatically, and overriding it is an admin escape hatch, not a\n // user-facing feature.\n description: \"'boost' temporarily applies the configured boost limits\",\n required: false,\n },\n slackCommand: \"/pi-sandbox\",\n slackRoute: { includeText: true },\n discord: true,\n telegramMenu: { description: \"Show or boost sandbox limits\" },\n telegramCommand: true,\n },\n {\n name: \"stop\",\n description: \"Stop the current conversation\",\n magicWord: true,\n discord: true,\n telegramMenu: { description: \"Stop ongoing conversation\" },\n },\n {\n name: \"new\",\n description: \"Reset conversation history and start fresh\",\n slackCommand: \"/pi-new\",\n slackRoute: {},\n discord: true,\n telegramMenu: {},\n telegramCommand: true,\n },\n {\n name: \"admin\",\n description: \"Open the admin portal\",\n slackCommand: \"/pi-admin\",\n slackRoute: { thread: true },\n },\n];\n\nexport function commandManifestEntry(name: string): CommandManifestEntry {\n const entry = COMMAND_MANIFEST.find((candidate) => candidate.name === name);\n if (!entry) throw new Error(`Unknown command in manifest: ${name}`);\n return entry;\n}\n\n/** Slash spellings of a command: `/<name>` and `/pi-<name>` for the name and each alias. */\nexport function slashForms(name: string): readonly string[] {\n const entry = commandManifestEntry(name);\n return [entry.name, ...(entry.aliases ?? [])].flatMap((spelling) => [\n `/${spelling}`,\n `/pi-${spelling}`,\n ]);\n}\n\n/** Every accepted spelling: the bare name (when the command is bare) plus slash forms. */\nexport function commandForms(name: string): readonly string[] {\n const entry = commandManifestEntry(name);\n return [...(entry.bare ? [entry.name] : []), ...slashForms(name)];\n}\n\n/** Telegram `setMyCommands` payload (menu registration; routing is separate). */\nexport function telegramCommandMenu(): { command: string; description: string }[] {\n return COMMAND_MANIFEST.filter((entry) => entry.telegramMenu).map((entry) => ({\n command: entry.name,\n description: entry.telegramMenu?.description ?? entry.description,\n }));\n}\n\nexport function matchCommand<Command extends string>(\n text: string,\n aliases: readonly Command[],\n options?: { stripMention?: boolean },\n): { command: Command; args: string[] } | null {\n const tokens = text.trim().split(/\\s+/).filter(Boolean);\n const first = tokens[0];\n if (first === undefined) return null;\n\n const token = options?.stripMention ? first.replace(/@\\w+$/i, \"\") : first;\n const command = token.toLowerCase() as Command;\n return aliases.includes(command) ? { command, args: tokens.slice(1) } : null;\n}\n\n/**\n * Chat-command text recognition, derived from the command manifest so the\n * inventory has a single source of truth. Session resume uses it to keep\n * command messages out of replayed history.\n *\n * The `pi-[\\w-]+` alternative is a catch-all for platform-prefixed command\n * names (including ones a platform registers but this build no longer\n * handles), independent of the manifest.\n */\nconst COMMAND_NAMES = COMMAND_MANIFEST.flatMap((entry) => [entry.name].concat(entry.aliases ?? []));\n\nconst COMMAND_TEXT_PATTERN = new RegExp(\n `^\\\\/(?:pi-[\\\\w-]+|${COMMAND_NAMES.join(\"|\")})(?:@\\\\w+)?(?:\\\\s|$)`,\n \"i\",\n);\n\nexport function isCommandText(text: string): boolean {\n return COMMAND_TEXT_PATTERN.test(text.trim());\n}\n"]}
@@ -5,5 +5,11 @@ export declare class ModelCommandHandler implements CommandHandler {
5
5
  private readonly modelRegistry;
6
6
  constructor(modelRegistry: ModelRegistry);
7
7
  tryHandle(context: CommandContext): Promise<boolean>;
8
+ /**
9
+ * Resolve the spec against the registry. A `:suffix` is first tried as part
10
+ * of the model id, then as a thinking level on the bare id — so a model
11
+ * whose real name contains a colon still wins over the suffix reading.
12
+ */
13
+ private selectModel;
8
14
  }
9
15
  //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/adapters/commands/model.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAapG,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAIrD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CA+BzE;AAoCD,qBAAa,mBAAoB,YAAW,cAAc;IAC5C,OAAO,CAAC,QAAQ,CAAC,aAAa;IAA1C,YAA6B,aAAa,EAAE,aAAa,EAAI;IACvD,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAsDzD;IAED;;;;OAIG;IACH,OAAO,CAAC,WAAW;CA6BpB"}
@@ -1,8 +1,7 @@
1
- import { resolveConversationSettings } from "../config.js";
2
- import { applyConversationSettings } from "../settings-mutation.js";
3
- import { slashForms } from "./manifest.js";
4
- import { matchCommand } from "./manifest.js";
5
- import { formatCommandSummary, replyDiagnosticWithContext } from "./utils.js";
1
+ import { resolveConversationSettings } from "../../config.js";
2
+ import { applyConversationSettings } from "../../settings-mutation.js";
3
+ import { slashForms, matchCommand } from "./manifest.js";
4
+ import { replySummary } from "./utils.js";
6
5
  const PI_AI_THINKING_LEVELS = [
7
6
  "minimal",
8
7
  "low",
@@ -62,6 +61,7 @@ function parseModelThinkingLevel(modelSpec) {
62
61
  function formatModelSpec(provider, model, thinkingLevel) {
63
62
  return `${provider}/${model}${thinkingLevel ? `:${thinkingLevel}` : ""}`;
64
63
  }
64
+ const USAGE_EXAMPLE = "Example: `/pi-model anthropic/claude-sonnet-4-6:off`";
65
65
  export class ModelCommandHandler {
66
66
  constructor(modelRegistry) {
67
67
  this.modelRegistry = modelRegistry;
@@ -71,71 +71,83 @@ export class ModelCommandHandler {
71
71
  if (!parsed)
72
72
  return false;
73
73
  if (parsed.error) {
74
- await replyDiagnosticWithContext(context.responder, formatCommandSummary("Model", [
74
+ await replySummary(context, "Model", [
75
75
  "無效的模型參數,請使用 `provider/model[:thinking]`。",
76
- "Example: `/pi-model anthropic/claude-sonnet-4-6:off`",
77
- ]), { style: "muted" });
76
+ USAGE_EXAMPLE,
77
+ ]);
78
78
  return true;
79
79
  }
80
80
  const office = context.services.workspace.office(context.address);
81
81
  if (!parsed.provider || !parsed.model) {
82
82
  const current = resolveConversationSettings(office);
83
- await replyDiagnosticWithContext(context.responder, formatCommandSummary("Model", [
83
+ await replySummary(context, "Model", [
84
84
  `Current: \`${formatModelSpec(current.provider, current.model, current.thinkingLevel)}\``,
85
85
  "",
86
86
  "Usage: `/pi-model provider/model[:thinking]`",
87
- "Example: `/pi-model anthropic/claude-sonnet-4-6:off`",
88
- ]), { style: "muted" });
87
+ USAGE_EXAMPLE,
88
+ ]);
89
89
  return true;
90
90
  }
91
- const exactModelId = parsed.modelCandidate ?? parsed.model;
92
- let selectedModelId = exactModelId;
93
- let selectedThinkingLevel = parsed.thinkingLevel;
94
- let registeredModel = this.modelRegistry.find(parsed.provider, exactModelId);
95
- if (!registeredModel && parsed.modelCandidate) {
96
- if (parsed.thinkingLevelCandidate &&
97
- !THINKING_LEVELS.has(parsed.thinkingLevelCandidate)) {
98
- await replyDiagnosticWithContext(context.responder, formatCommandSummary("Model", [
99
- "未知的 thinking level,請使用 `off`、`minimal`、`low`、`medium`、`high`、`xhigh` 或 `max`。",
100
- "Example: `/pi-model anthropic/claude-sonnet-4-6:off`",
101
- ]), { style: "muted" });
102
- return true;
103
- }
104
- selectedModelId = parsed.model;
105
- registeredModel = this.modelRegistry.find(parsed.provider, selectedModelId);
106
- }
107
- if (!registeredModel) {
108
- await replyDiagnosticWithContext(context.responder, formatCommandSummary("Model", [
109
- `找不到模型:\`${formatModelSpec(parsed.provider, selectedModelId, selectedThinkingLevel)}\``,
110
- "請確認 provider/model 名稱,或先在 pi models.json 註冊自訂模型。",
111
- ]), { style: "muted" });
91
+ const selection = this.selectModel(parsed.provider, parsed.model, parsed);
92
+ if ("lines" in selection) {
93
+ await replySummary(context, "Model", selection.lines);
112
94
  return true;
113
95
  }
114
- if (parsed.modelCandidate && selectedModelId === parsed.modelCandidate) {
115
- selectedThinkingLevel = undefined;
116
- }
117
96
  if (!context.services.runtime) {
118
- await replyDiagnosticWithContext(context.responder, formatCommandSummary("Model", [
97
+ await replySummary(context, "Model", [
119
98
  "Model command is not configured correctly on the server. Please try again later.",
120
- ]), { style: "muted" });
99
+ ]);
121
100
  return true;
122
101
  }
123
102
  const result = applyConversationSettings(context.services.runtime, office, {
124
103
  provider: parsed.provider,
125
- model: selectedModelId,
126
- ...(selectedThinkingLevel ? { thinkingLevel: selectedThinkingLevel } : {}),
104
+ model: selection.modelId,
105
+ ...(selection.thinkingLevel ? { thinkingLevel: selection.thinkingLevel } : {}),
127
106
  });
128
107
  if (!result.ok) {
129
- await replyDiagnosticWithContext(context.responder, formatCommandSummary("Model", [
108
+ await replySummary(context, "Model", [
130
109
  "目前這個 conversation 有執行中的工作,請等它完成或先 `/stop` 後再切換模型。",
131
- ]), { style: "muted" });
110
+ ]);
132
111
  return true;
133
112
  }
134
- await replyDiagnosticWithContext(context.responder, formatCommandSummary("Model", [
135
- `Switched: \`${formatModelSpec(parsed.provider, selectedModelId, selectedThinkingLevel)}\``,
113
+ await replySummary(context, "Model", [
114
+ `Switched: \`${formatModelSpec(parsed.provider, selection.modelId, selection.thinkingLevel)}\``,
136
115
  "下一則訊息會使用新模型。",
137
- ]), { style: "muted" });
116
+ ]);
138
117
  return true;
139
118
  }
119
+ /**
120
+ * Resolve the spec against the registry. A `:suffix` is first tried as part
121
+ * of the model id, then as a thinking level on the bare id — so a model
122
+ * whose real name contains a colon still wins over the suffix reading.
123
+ */
124
+ selectModel(provider, model, parsed) {
125
+ const exactModelId = parsed.modelCandidate ?? model;
126
+ if (this.modelRegistry.find(provider, exactModelId))
127
+ return { modelId: exactModelId };
128
+ if (parsed.modelCandidate) {
129
+ const suffix = parsed.thinkingLevelCandidate;
130
+ if (suffix && !THINKING_LEVELS.has(suffix)) {
131
+ return {
132
+ lines: [
133
+ "未知的 thinking level,請使用 `off`、`minimal`、`low`、`medium`、`high`、`xhigh` 或 `max`。",
134
+ USAGE_EXAMPLE,
135
+ ],
136
+ };
137
+ }
138
+ if (this.modelRegistry.find(provider, model)) {
139
+ return {
140
+ modelId: model,
141
+ ...(parsed.thinkingLevel ? { thinkingLevel: parsed.thinkingLevel } : {}),
142
+ };
143
+ }
144
+ }
145
+ return {
146
+ lines: [
147
+ `找不到模型:\`${formatModelSpec(provider, model, parsed.thinkingLevel)}\``,
148
+ "請確認 provider/model 名稱,或先在 pi models.json 註冊自訂模型。",
149
+ ],
150
+ };
151
+ }
140
152
  }
141
153
  //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../../src/adapters/commands/model.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type { ThinkingLevel as PiAiThinkingLevel } from \"@earendil-works/pi-ai\";\nimport { resolveConversationSettings } from \"../../config.js\";\nimport { applyConversationSettings } from \"../../settings-mutation.js\";\nimport { slashForms, matchCommand } from \"./manifest.js\";\nimport type { CommandContext, CommandHandler, ModelRegistry, ParsedModelCommand } from \"./types.js\";\nimport { replySummary } from \"./utils.js\";\n\nconst PI_AI_THINKING_LEVELS = [\n \"minimal\",\n \"low\",\n \"medium\",\n \"high\",\n \"xhigh\",\n \"max\",\n] satisfies PiAiThinkingLevel[];\nconst THINKING_LEVELS = new Set<ThinkingLevel>([\"off\", ...PI_AI_THINKING_LEVELS]);\n\nexport type { ParsedModelCommand } from \"./types.js\";\n\nconst MODEL_COMMANDS = slashForms(\"model\");\n\nexport function parseModelCommand(text: string): ParsedModelCommand | null {\n const matched = matchCommand(text, MODEL_COMMANDS);\n if (!matched) return null;\n\n if (matched.args.length === 0) {\n return {};\n }\n\n if (matched.args.length !== 1) {\n return { error: \"invalid_spec\" };\n }\n\n const spec = matched.args[0];\n if (spec === undefined) {\n return { error: \"invalid_spec\" };\n }\n const slash = spec.indexOf(\"/\");\n if (slash <= 0 || slash === spec.length - 1) {\n return { error: \"invalid_spec\" };\n }\n\n const modelSpec = spec.slice(slash + 1);\n const parsedModel = parseModelThinkingLevel(modelSpec);\n if (parsedModel.error) {\n return { error: parsedModel.error };\n }\n\n return {\n provider: spec.slice(0, slash),\n ...parsedModel,\n };\n}\n\nfunction parseModelThinkingLevel(modelSpec: string): {\n model?: string;\n modelCandidate?: string;\n thinkingLevelCandidate?: string;\n thinkingLevel?: ThinkingLevel;\n error?: \"invalid_spec\";\n} {\n const colon = modelSpec.lastIndexOf(\":\");\n if (colon === 0 || colon === modelSpec.length - 1) {\n return { error: \"invalid_spec\" };\n }\n if (colon < 0) {\n return { model: modelSpec };\n }\n\n const suffix = modelSpec.slice(colon + 1);\n return {\n model: modelSpec.slice(0, colon),\n modelCandidate: modelSpec,\n thinkingLevelCandidate: suffix,\n ...(THINKING_LEVELS.has(suffix as ThinkingLevel)\n ? { thinkingLevel: suffix as ThinkingLevel }\n : {}),\n };\n}\n\nfunction formatModelSpec(provider: string, model: string, thinkingLevel?: ThinkingLevel): string {\n return `${provider}/${model}${thinkingLevel ? `:${thinkingLevel}` : \"\"}`;\n}\n\nconst USAGE_EXAMPLE = \"Example: `/pi-model anthropic/claude-sonnet-4-6:off`\";\n\ntype ModelSelection = { modelId: string; thinkingLevel?: ThinkingLevel } | { lines: string[] };\n\nexport class ModelCommandHandler implements CommandHandler {\n constructor(private readonly modelRegistry: ModelRegistry) {}\n async tryHandle(context: CommandContext): Promise<boolean> {\n const parsed = parseModelCommand(context.commandText);\n if (!parsed) return false;\n\n if (parsed.error) {\n await replySummary(context, \"Model\", [\n \"無效的模型參數,請使用 `provider/model[:thinking]`。\",\n USAGE_EXAMPLE,\n ]);\n return true;\n }\n\n const office = context.services.workspace.office(context.address);\n if (!parsed.provider || !parsed.model) {\n const current = resolveConversationSettings(office);\n await replySummary(context, \"Model\", [\n `Current: \\`${formatModelSpec(current.provider, current.model, current.thinkingLevel)}\\``,\n \"\",\n \"Usage: `/pi-model provider/model[:thinking]`\",\n USAGE_EXAMPLE,\n ]);\n return true;\n }\n\n const selection = this.selectModel(parsed.provider, parsed.model, parsed);\n if (\"lines\" in selection) {\n await replySummary(context, \"Model\", selection.lines);\n return true;\n }\n\n if (!context.services.runtime) {\n await replySummary(context, \"Model\", [\n \"Model command is not configured correctly on the server. Please try again later.\",\n ]);\n return true;\n }\n\n const result = applyConversationSettings(context.services.runtime, office, {\n provider: parsed.provider,\n model: selection.modelId,\n ...(selection.thinkingLevel ? { thinkingLevel: selection.thinkingLevel } : {}),\n });\n if (!result.ok) {\n await replySummary(context, \"Model\", [\n \"目前這個 conversation 有執行中的工作,請等它完成或先 `/stop` 後再切換模型。\",\n ]);\n return true;\n }\n\n await replySummary(context, \"Model\", [\n `Switched: \\`${formatModelSpec(parsed.provider, selection.modelId, selection.thinkingLevel)}\\``,\n \"下一則訊息會使用新模型。\",\n ]);\n return true;\n }\n\n /**\n * Resolve the spec against the registry. A `:suffix` is first tried as part\n * of the model id, then as a thinking level on the bare id — so a model\n * whose real name contains a colon still wins over the suffix reading.\n */\n private selectModel(provider: string, model: string, parsed: ParsedModelCommand): ModelSelection {\n const exactModelId = parsed.modelCandidate ?? model;\n if (this.modelRegistry.find(provider, exactModelId)) return { modelId: exactModelId };\n\n if (parsed.modelCandidate) {\n const suffix = parsed.thinkingLevelCandidate;\n if (suffix && !THINKING_LEVELS.has(suffix as ThinkingLevel)) {\n return {\n lines: [\n \"未知的 thinking level,請使用 `off`、`minimal`、`low`、`medium`、`high`、`xhigh` 或 `max`。\",\n USAGE_EXAMPLE,\n ],\n };\n }\n if (this.modelRegistry.find(provider, model)) {\n return {\n modelId: model,\n ...(parsed.thinkingLevel ? { thinkingLevel: parsed.thinkingLevel } : {}),\n };\n }\n }\n\n return {\n lines: [\n `找不到模型:\\`${formatModelSpec(provider, model, parsed.thinkingLevel)}\\``,\n \"請確認 provider/model 名稱,或先在 pi models.json 註冊自訂模型。\",\n ],\n };\n }\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"new.d.ts","sourceRoot":"","sources":["../../../src/adapters/commands/new.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAKjE,qBAAa,iBAAkB,YAAW,cAAc;IAChD,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAmCzD;CACF"}
@@ -1,23 +1,22 @@
1
- import { createConversationMessage } from "../adapter.js";
2
- import { slashForms } from "./manifest.js";
3
- import { matchCommand } from "./manifest.js";
4
- import { formatCommandSummary, replyDiagnosticWithContext } from "./utils.js";
1
+ import { createConversationMessage } from "../../adapter.js";
2
+ import { slashForms, matchCommand } from "./manifest.js";
3
+ import { replySummary } from "./utils.js";
5
4
  const NEW_COMMANDS = slashForms("new");
6
5
  export class NewCommandHandler {
7
6
  async tryHandle(context) {
8
7
  if (!matchCommand(context.commandText, NEW_COMMANDS))
9
8
  return false;
10
9
  if (!context.privateConversation) {
11
- await replyDiagnosticWithContext(context.responder, formatCommandSummary("New Session", [
10
+ await replySummary(context, "New Session", [
12
11
  "為了避免誤清除共享上下文,`/new` 目前只能在與機器人的私訊 / DM 中使用。",
13
- ]), { style: "muted" });
12
+ ]);
14
13
  return true;
15
14
  }
16
15
  if (!context.services.runtime) {
17
- await replyDiagnosticWithContext(context.responder, formatCommandSummary("New Session", [
16
+ await replySummary(context, "New Session", [
18
17
  "New command is not configured correctly on the server.",
19
18
  "Please try again later.",
20
- ]), { style: "muted" });
19
+ ]);
21
20
  return true;
22
21
  }
23
22
  await context.services.runtime.handleNewCommand({
@@ -0,0 +1 @@
1
+ {"version":3,"file":"new.js","sourceRoot":"","sources":["../../../src/adapters/commands/new.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,YAAY,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;AAEvC,MAAM,OAAO,iBAAiB;IAC5B,KAAK,CAAC,SAAS,CAAC,OAAuB;QACrC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,YAAY,CAAC;YAAE,OAAO,KAAK,CAAC;QAEnE,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC;YACjC,MAAM,YAAY,CAAC,OAAO,EAAE,aAAa,EAAE;gBACzC,4CAA4C;aAC7C,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YAC9B,MAAM,YAAY,CAAC,OAAO,EAAE,aAAa,EAAE;gBACzC,wDAAwD;gBACxD,yBAAyB;aAC1B,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,gBAAgB,CAAC;YAC9C,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,cAAc,EAAE,OAAO,CAAC,cAAc;YACtC,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,OAAO,EAAE,yBAAyB,CAAC;gBACjC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,QAAQ;gBAClC,cAAc,EAAE,OAAO,CAAC,OAAO,CAAC,cAAc;gBAC9C,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,EAAE,EAAE,UAAU,OAAO,CAAC,UAAU,EAAE;gBAClC,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,gBAAgB,EAAE,QAAQ;gBAC1B,MAAM,EAAE,OAAO,CAAC,cAAc;gBAC9B,QAAQ,EAAE,OAAO,CAAC,gBAAgB;gBAClC,IAAI,EAAE,OAAO,CAAC,WAAW;aAC1B,CAAC;SACH,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;CACF","sourcesContent":["import { createConversationMessage } from \"../../adapter.js\";\nimport { slashForms, matchCommand } from \"./manifest.js\";\nimport type { CommandContext, CommandHandler } from \"./types.js\";\nimport { replySummary } from \"./utils.js\";\n\nconst NEW_COMMANDS = slashForms(\"new\");\n\nexport class NewCommandHandler implements CommandHandler {\n async tryHandle(context: CommandContext): Promise<boolean> {\n if (!matchCommand(context.commandText, NEW_COMMANDS)) return false;\n\n if (!context.privateConversation) {\n await replySummary(context, \"New Session\", [\n \"為了避免誤清除共享上下文,`/new` 目前只能在與機器人的私訊 / DM 中使用。\",\n ]);\n return true;\n }\n\n if (!context.services.runtime) {\n await replySummary(context, \"New Session\", [\n \"New command is not configured correctly on the server.\",\n \"Please try again later.\",\n ]);\n return true;\n }\n\n await context.services.runtime.handleNewCommand({\n sessionKey: context.sessionKey,\n conversationId: context.conversationId,\n bot: context.bot,\n message: createConversationMessage({\n platform: context.address.platform,\n conversationId: context.address.conversationId,\n address: context.address,\n id: `memory:${context.sessionKey}`,\n sessionKey: context.sessionKey,\n conversationKind: \"direct\",\n userId: context.platformUserId,\n userName: context.platformUserName,\n text: context.commandText,\n }),\n });\n return true;\n }\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/adapters/commands/registry.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAkBhF,wBAAgB,sBAAsB,CACpC,aAAa,GAAE,aAAoC,GAClD,cAAc,EAAE,CAUlB;AAED,gFAAgF;AAChF,wBAAsB,eAAe,CACnC,QAAQ,EAAE,SAAS,cAAc,EAAE,EACnC,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,OAAO,CAAC,CAKlB"}
@@ -1,6 +1,5 @@
1
- import { MikanModels } from "../harness/index.js";
1
+ import { MikanModels } from "../../harness/index.js";
2
2
  import { AdminCommandHandler } from "./admin.js";
3
- import { AutoReplyCommandHandler } from "./auto-reply.js";
4
3
  import { LoginCommandHandler } from "./login.js";
5
4
  import { COMMAND_MANIFEST } from "./manifest.js";
6
5
  import { ModelCommandHandler } from "./model.js";
@@ -18,7 +17,6 @@ const HANDLER_FACTORIES = {
18
17
  admin: () => new AdminCommandHandler(),
19
18
  login: () => new LoginCommandHandler(),
20
19
  session: () => new SessionViewCommandHandler(),
21
- "auto-reply": () => new AutoReplyCommandHandler(),
22
20
  model: (modelRegistry) => new ModelCommandHandler(modelRegistry),
23
21
  sandbox: () => new SandboxCommandHandler(),
24
22
  new: () => new NewCommandHandler(),
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/adapters/commands/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAG9D;;;;;;GAMG;AACH,MAAM,iBAAiB,GAAqE;IAC1F,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,mBAAmB,EAAE;IACtC,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,mBAAmB,EAAE;IACtC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,yBAAyB,EAAE;IAC9C,KAAK,EAAE,CAAC,aAAa,EAAE,EAAE,CAAC,IAAI,mBAAmB,CAAC,aAAa,CAAC;IAChE,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,qBAAqB,EAAE;IAC1C,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,iBAAiB,EAAE;CACnC,CAAC;AAEF,MAAM,UAAU,sBAAsB,CACpC,aAAa,GAAkB,WAAW,CAAC,MAAM,EAAE;IAEnD,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACxE,MAAM,OAAO,GAAG,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,2BAA2B,KAAK,CAAC,IAAI,kDAAkD,CACxF,CAAC;QACJ,CAAC;QACD,OAAO,OAAO,CAAC,aAAa,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,gFAAgF;AAChF,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,QAAmC,EACnC,OAAuB;IAEvB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,MAAM,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC;YAAE,OAAO,IAAI,CAAC;IACpD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import { MikanModels } from \"../../harness/index.js\";\nimport { AdminCommandHandler } from \"./admin.js\";\nimport { LoginCommandHandler } from \"./login.js\";\nimport { COMMAND_MANIFEST } from \"./manifest.js\";\nimport { ModelCommandHandler } from \"./model.js\";\nimport { NewCommandHandler } from \"./new.js\";\nimport { SandboxCommandHandler } from \"./sandbox.js\";\nimport { SessionViewCommandHandler } from \"./session-view.js\";\nimport type { CommandContext, CommandHandler, ModelRegistry } from \"./types.js\";\n\n/**\n * Handler factory per manifest command name. The manifest is the inventory\n * authority; this map only binds each entry to its implementation, and\n * `defaultCommandHandlers` verifies the binding is complete so a manifest\n * entry without a handler fails at construction instead of dispatching into\n * silence. Magic-word entries (routed by conversation intake) are exempt.\n */\nconst HANDLER_FACTORIES: Record<string, (modelRegistry: ModelRegistry) => CommandHandler> = {\n admin: () => new AdminCommandHandler(),\n login: () => new LoginCommandHandler(),\n session: () => new SessionViewCommandHandler(),\n model: (modelRegistry) => new ModelCommandHandler(modelRegistry),\n sandbox: () => new SandboxCommandHandler(),\n new: () => new NewCommandHandler(),\n};\n\nexport function defaultCommandHandlers(\n modelRegistry: ModelRegistry = MikanModels.create(),\n): CommandHandler[] {\n return COMMAND_MANIFEST.filter((entry) => !entry.magicWord).map((entry) => {\n const factory = HANDLER_FACTORIES[entry.name];\n if (!factory) {\n throw new Error(\n `Command manifest entry \"${entry.name}\" has no handler factory in commands/registry.ts`,\n );\n }\n return factory(modelRegistry);\n });\n}\n\n/** Run handlers in order, returning true as soon as one accepts the command. */\nexport async function dispatchCommand(\n handlers: readonly CommandHandler[],\n context: CommandContext,\n): Promise<boolean> {\n for (const handler of handlers) {\n if (await handler.tryHandle(context)) return true;\n }\n return false;\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../../src/adapters/commands/sandbox.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AA4BvF,YAAY,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAIvD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAe7E;AAED,qBAAa,qBAAsB,YAAW,cAAc;IACpD,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAwBzD;CACF"}