@stage-labs/metro 0.1.0-beta.21 → 0.1.0-beta.211

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 (436) hide show
  1. package/dist/api.js +9 -101
  2. package/dist/claude-settings.js +40 -0
  3. package/dist/claude.js +152 -0
  4. package/dist/cli.js +52 -109
  5. package/dist/control.js +47 -75
  6. package/dist/hold.js +210 -0
  7. package/dist/local.js +43 -0
  8. package/dist/mcp-config.js +25 -0
  9. package/dist/node-name.js +71 -0
  10. package/dist/onboarding.js +44 -0
  11. package/dist/provider-flags.js +9 -0
  12. package/dist/route.js +58 -0
  13. package/dist/runtime-install.js +96 -0
  14. package/dist/runtime.js +29 -52
  15. package/dist/serve.js +157 -0
  16. package/dist/service.js +304 -0
  17. package/dist/tail.js +119 -0
  18. package/dist/update.js +13 -1
  19. package/package.json +2 -23
  20. package/runtime/marketplace/.claude-plugin/marketplace.json +12 -0
  21. package/runtime/marketplace/plugin/.claude-plugin/plugin.json +17 -0
  22. package/runtime/marketplace/plugin/.mcp.json +1 -0
  23. package/runtime/marketplace/plugin/bin/guard.mjs +71 -0
  24. package/runtime/marketplace/plugin/bin/metro-plugin.mjs +30 -0
  25. package/runtime/marketplace/plugin/bin/policy.mjs +97 -0
  26. package/runtime/marketplace/plugin/bin/session-start.mjs +31 -0
  27. package/runtime/marketplace/plugin/hooks/hooks.json +25 -0
  28. package/runtime/marketplace/plugin/orchestrator.md +26 -0
  29. package/runtime/node_modules/@metro-labs/core/package.json +47 -0
  30. package/runtime/node_modules/@metro-labs/core/src/endpoints.ts +7 -0
  31. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/events.ts +11 -7
  32. package/runtime/node_modules/@metro-labs/{mcp/src/db → core/src}/ids.ts +5 -0
  33. package/runtime/node_modules/@metro-labs/core/src/is-record.ts +2 -0
  34. package/runtime/node_modules/@metro-labs/{mcp/src/stations → core/src}/lines.ts +24 -28
  35. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/protocol.ts +7 -4
  36. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/secure-fs.ts +17 -0
  37. package/runtime/node_modules/@metro-labs/core/src/station-names.ts +13 -0
  38. package/runtime/node_modules/@metro-labs/core/src/stations/account-files.ts +41 -0
  39. package/runtime/node_modules/@metro-labs/core/src/stations/account-store.ts +83 -0
  40. package/runtime/node_modules/@metro-labs/{mcp → core}/src/stations/attachments.ts +0 -1
  41. package/runtime/node_modules/@metro-labs/core/src/stations/messaging-normalize.ts +16 -0
  42. package/runtime/node_modules/@metro-labs/core/src/stations/profile.ts +58 -0
  43. package/runtime/node_modules/@metro-labs/core/src/stations/sender-profile.ts +64 -0
  44. package/runtime/node_modules/@metro-labs/{mcp → core}/src/stations/station-runtime.ts +6 -11
  45. package/runtime/node_modules/@metro-labs/core/src/stations/train-boot.ts +42 -0
  46. package/runtime/node_modules/@metro-labs/core/src/stations/train-events.ts +84 -0
  47. package/runtime/node_modules/@metro-labs/{mcp → core}/src/stations/types.ts +18 -1
  48. package/runtime/node_modules/@metro-labs/core/src/tickets.ts +37 -0
  49. package/runtime/node_modules/@metro-labs/core/src/version.ts +2 -0
  50. package/runtime/node_modules/@metro-labs/daemon/package.json +48 -0
  51. package/runtime/node_modules/@metro-labs/daemon/src/agent-user/agent-fs.ts +134 -0
  52. package/runtime/node_modules/@metro-labs/daemon/src/agent-user/files-api.ts +12 -0
  53. package/runtime/node_modules/@metro-labs/daemon/src/agent-user/files.ts +89 -0
  54. package/runtime/node_modules/@metro-labs/daemon/src/agent-user/home-fs.ts +113 -0
  55. package/runtime/node_modules/@metro-labs/daemon/src/agent-user/job-env.ts +51 -0
  56. package/runtime/node_modules/@metro-labs/daemon/src/agent-user/provision.ts +80 -0
  57. package/runtime/node_modules/@metro-labs/daemon/src/agent-user/schedule-detail.ts +99 -0
  58. package/runtime/node_modules/@metro-labs/daemon/src/agent-user/schedules-api.ts +27 -0
  59. package/runtime/node_modules/@metro-labs/daemon/src/agent-user/schedules.ts +144 -0
  60. package/runtime/node_modules/@metro-labs/daemon/src/agent-user/unit-files.ts +37 -0
  61. package/runtime/node_modules/@metro-labs/daemon/src/agent-user/user.ts +89 -0
  62. package/runtime/node_modules/@metro-labs/daemon/src/agent-user/view.ts +87 -0
  63. package/runtime/node_modules/@metro-labs/daemon/src/agents/account-attach.ts +19 -0
  64. package/runtime/node_modules/@metro-labs/daemon/src/agents/account-lookups.ts +55 -0
  65. package/runtime/node_modules/@metro-labs/daemon/src/agents/account-routes.ts +76 -0
  66. package/runtime/node_modules/@metro-labs/daemon/src/agents/accounts-api.ts +357 -0
  67. package/runtime/node_modules/@metro-labs/daemon/src/agents/admin.ts +30 -0
  68. package/runtime/node_modules/@metro-labs/daemon/src/agents/allowlist.ts +59 -0
  69. package/runtime/node_modules/@metro-labs/daemon/src/agents/api.ts +131 -0
  70. package/runtime/node_modules/@metro-labs/daemon/src/agents/bundle.ts +132 -0
  71. package/runtime/node_modules/@metro-labs/daemon/src/agents/file-admin.ts +305 -0
  72. package/runtime/node_modules/@metro-labs/daemon/src/agents/files.ts +142 -0
  73. package/runtime/node_modules/@metro-labs/{mcp/src/db/key-map.ts → daemon/src/agents/keys.ts} +1 -11
  74. package/runtime/node_modules/@metro-labs/{mcp/src/db/agent-map.ts → daemon/src/agents/map.ts} +58 -1
  75. package/runtime/node_modules/@metro-labs/daemon/src/agents/policy-route.ts +27 -0
  76. package/runtime/node_modules/@metro-labs/{mcp/src/db/agent-scope.ts → daemon/src/agents/scope.ts} +2 -2
  77. package/runtime/node_modules/@metro-labs/daemon/src/agents/sender-cards.ts +94 -0
  78. package/runtime/node_modules/@metro-labs/daemon/src/agents/senders.ts +38 -0
  79. package/runtime/node_modules/@metro-labs/daemon/src/approvals/api.ts +55 -0
  80. package/runtime/node_modules/@metro-labs/daemon/src/approvals/pending.ts +150 -0
  81. package/runtime/node_modules/@metro-labs/daemon/src/approvals/preview.ts +66 -0
  82. package/runtime/node_modules/@metro-labs/daemon/src/boot/boot.ts +218 -0
  83. package/runtime/node_modules/@metro-labs/daemon/src/boot/connect-hint.ts +36 -0
  84. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/boot}/crash-guard.ts +1 -1
  85. package/runtime/node_modules/@metro-labs/daemon/src/boot/local-owner.ts +21 -0
  86. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/boot}/paths.ts +6 -34
  87. package/runtime/node_modules/@metro-labs/daemon/src/channels/addressed.ts +26 -0
  88. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/inbound.ts +70 -45
  89. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/media-note.ts +11 -7
  90. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/pending.ts +4 -1
  91. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/relay.ts +2 -2
  92. package/runtime/node_modules/@metro-labs/daemon/src/claude/api.ts +355 -0
  93. package/runtime/node_modules/@metro-labs/daemon/src/claude/files.ts +359 -0
  94. package/runtime/node_modules/@metro-labs/daemon/src/claude/login.ts +208 -0
  95. package/runtime/node_modules/@metro-labs/daemon/src/claude/memory.ts +32 -0
  96. package/runtime/node_modules/@metro-labs/daemon/src/claude/onboarding.ts +60 -0
  97. package/runtime/node_modules/@metro-labs/daemon/src/claude/plugin-install.ts +149 -0
  98. package/runtime/node_modules/@metro-labs/daemon/src/claude/session-files.ts +75 -0
  99. package/runtime/node_modules/@metro-labs/daemon/src/claude/session.ts +313 -0
  100. package/runtime/node_modules/@metro-labs/daemon/src/claude/settings.ts +109 -0
  101. package/runtime/node_modules/@metro-labs/daemon/src/claude/setup.ts +273 -0
  102. package/runtime/node_modules/@metro-labs/daemon/src/claude/skills.ts +120 -0
  103. package/runtime/node_modules/@metro-labs/daemon/src/claude/version.ts +113 -0
  104. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/connector-api.ts → daemon/src/connectors/api.ts} +79 -113
  105. package/runtime/node_modules/@metro-labs/{mcp/src/db/connector-config.ts → daemon/src/connectors/config.ts} +67 -41
  106. package/runtime/node_modules/@metro-labs/daemon/src/connectors/gates.ts +72 -0
  107. package/runtime/node_modules/@metro-labs/daemon/src/connectors/health.ts +18 -0
  108. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/connectors}/oauth-client.ts +14 -17
  109. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/connectors}/oauth-discovery.ts +33 -20
  110. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/connector-oauth-routes.ts → daemon/src/connectors/oauth-routes.ts} +30 -32
  111. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/connector-oauth.ts → daemon/src/connectors/oauth.ts} +61 -22
  112. package/runtime/node_modules/@metro-labs/daemon/src/connectors/plugin-sync.ts +131 -0
  113. package/runtime/node_modules/@metro-labs/daemon/src/connectors/reach.ts +27 -0
  114. package/runtime/node_modules/@metro-labs/daemon/src/connectors/relay-policy.ts +90 -0
  115. package/runtime/node_modules/@metro-labs/daemon/src/connectors/relay.ts +347 -0
  116. package/runtime/node_modules/@metro-labs/daemon/src/connectors/store.ts +385 -0
  117. package/runtime/node_modules/@metro-labs/daemon/src/connectors/tools.ts +81 -0
  118. package/runtime/node_modules/@metro-labs/daemon/src/connectors/url.ts +37 -0
  119. package/runtime/node_modules/@metro-labs/daemon/src/connectors/verify.ts +106 -0
  120. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/files}/attach-grant.ts +4 -4
  121. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/files}/attach-owner.ts +3 -3
  122. package/runtime/node_modules/@metro-labs/daemon/src/files/attach-reaper.ts +174 -0
  123. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/files}/attach-serve.ts +12 -13
  124. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/files}/upload-api.ts +10 -27
  125. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/files}/upload-store.ts +4 -4
  126. package/runtime/node_modules/@metro-labs/daemon/src/gateway/bedrock.ts +233 -0
  127. package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-auth.ts +208 -0
  128. package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-device.ts +91 -0
  129. package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-stream.ts +173 -0
  130. package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-translate.ts +195 -0
  131. package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-version.ts +44 -0
  132. package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex.ts +128 -0
  133. package/runtime/node_modules/@metro-labs/daemon/src/gateway/effort.ts +77 -0
  134. package/runtime/node_modules/@metro-labs/daemon/src/gateway/eventstream.ts +123 -0
  135. package/runtime/node_modules/@metro-labs/daemon/src/gateway/forward.ts +237 -0
  136. package/runtime/node_modules/@metro-labs/daemon/src/gateway/frames.ts +118 -0
  137. package/runtime/node_modules/@metro-labs/daemon/src/gateway/gateway.ts +274 -0
  138. package/runtime/node_modules/@metro-labs/daemon/src/gateway/gemini-auth.ts +160 -0
  139. package/runtime/node_modules/@metro-labs/daemon/src/gateway/gemini-client.ts +46 -0
  140. package/runtime/node_modules/@metro-labs/daemon/src/gateway/gemini-setup.ts +150 -0
  141. package/runtime/node_modules/@metro-labs/daemon/src/gateway/gemini-stream.ts +139 -0
  142. package/runtime/node_modules/@metro-labs/daemon/src/gateway/gemini-translate.ts +224 -0
  143. package/runtime/node_modules/@metro-labs/daemon/src/gateway/gemini.ts +208 -0
  144. package/runtime/node_modules/@metro-labs/daemon/src/gateway/model-api.ts +199 -0
  145. package/runtime/node_modules/@metro-labs/daemon/src/gateway/model-config.ts +278 -0
  146. package/runtime/node_modules/@metro-labs/daemon/src/gateway/model-signin.ts +193 -0
  147. package/runtime/node_modules/@metro-labs/daemon/src/gateway/model-store.ts +70 -0
  148. package/runtime/node_modules/@metro-labs/daemon/src/gateway/openrouter.ts +90 -0
  149. package/runtime/node_modules/@metro-labs/daemon/src/gateway/pkce.ts +36 -0
  150. package/runtime/node_modules/@metro-labs/daemon/src/gateway/provider-models.ts +66 -0
  151. package/runtime/node_modules/@metro-labs/daemon/src/gateway/served.ts +18 -0
  152. package/runtime/node_modules/@metro-labs/daemon/src/gateway/subscription.ts +120 -0
  153. package/runtime/node_modules/@metro-labs/daemon/src/gateway/text.ts +14 -0
  154. package/runtime/node_modules/@metro-labs/daemon/src/gateway/usage.ts +244 -0
  155. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/accounts.ts +28 -17
  156. package/runtime/node_modules/@metro-labs/daemon/src/mcp/attachment-schema.ts +91 -0
  157. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/call-tools.ts +49 -20
  158. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/ctx.ts +4 -4
  159. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/event-store.ts +15 -16
  160. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/group-tools.ts +2 -2
  161. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/index.ts +24 -79
  162. package/runtime/node_modules/@metro-labs/daemon/src/mcp/instructions.ts +19 -0
  163. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/member-tools.ts +2 -2
  164. package/runtime/node_modules/@metro-labs/daemon/src/mcp/permission-prompt.ts +87 -0
  165. package/runtime/node_modules/@metro-labs/daemon/src/mcp/permission-relay.ts +79 -0
  166. package/runtime/node_modules/@metro-labs/daemon/src/mcp/policy-gate.ts +82 -0
  167. package/runtime/node_modules/@metro-labs/daemon/src/mcp/policy-snapshot.ts +79 -0
  168. package/runtime/node_modules/@metro-labs/daemon/src/mcp/profile-lookup.ts +60 -0
  169. package/runtime/node_modules/@metro-labs/daemon/src/mcp/profile-tool.ts +96 -0
  170. package/runtime/node_modules/@metro-labs/daemon/src/mcp/read-tool.ts +87 -0
  171. package/runtime/node_modules/@metro-labs/daemon/src/mcp/request-identity.ts +46 -0
  172. package/runtime/node_modules/@metro-labs/daemon/src/mcp/session-slot.ts +48 -0
  173. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/session.ts +33 -42
  174. package/runtime/node_modules/@metro-labs/daemon/src/mcp/tool-catalog.ts +88 -0
  175. package/runtime/node_modules/@metro-labs/daemon/src/mcp/tool-def.ts +9 -0
  176. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/tool-dispatch.ts +53 -40
  177. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/tool-schemas.ts +68 -119
  178. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/upload-tool.ts +6 -11
  179. package/runtime/node_modules/@metro-labs/daemon/src/metro-user/helper-script.ts +126 -0
  180. package/runtime/node_modules/@metro-labs/daemon/src/metro-user/install.ts +37 -0
  181. package/runtime/node_modules/@metro-labs/daemon/src/metro-user/privilege.ts +48 -0
  182. package/runtime/node_modules/@metro-labs/daemon/src/monitor/api.ts +132 -0
  183. package/runtime/node_modules/@metro-labs/daemon/src/net/tunnel.ts +316 -0
  184. package/runtime/node_modules/@metro-labs/daemon/src/policy/policy.ts +118 -0
  185. package/runtime/node_modules/@metro-labs/daemon/src/routes/bearer.ts +35 -0
  186. package/runtime/node_modules/@metro-labs/daemon/src/routes/body.ts +24 -0
  187. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/routes}/http.ts +59 -51
  188. package/runtime/node_modules/@metro-labs/daemon/src/routes/local-mode.ts +205 -0
  189. package/runtime/node_modules/@metro-labs/daemon/src/routes/session-apis.ts +66 -0
  190. package/runtime/node_modules/@metro-labs/daemon/src/routes/session.ts +29 -0
  191. package/runtime/node_modules/@metro-labs/daemon/src/routes/threema-callback.ts +103 -0
  192. package/runtime/node_modules/@metro-labs/daemon/src/server/control.ts +39 -0
  193. package/runtime/node_modules/@metro-labs/daemon/src/server/machine.ts +58 -0
  194. package/runtime/node_modules/@metro-labs/daemon/src/server/owner.ts +26 -0
  195. package/runtime/node_modules/@metro-labs/daemon/src/server/update.ts +90 -0
  196. package/runtime/node_modules/@metro-labs/daemon/src/server.ts +2 -0
  197. package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-driver.ts +42 -0
  198. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/attach-inline.ts +29 -1
  199. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/attach-interactive.ts +9 -36
  200. package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-outlook.ts +63 -0
  201. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/attach-resolve.ts +38 -13
  202. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/stations}/attach-session.ts +32 -22
  203. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/attach-xmtp.ts +8 -9
  204. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/attach.ts +75 -9
  205. package/runtime/node_modules/@metro-labs/daemon/src/stations/materialize.ts +265 -0
  206. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/registry.ts +22 -6
  207. package/runtime/node_modules/@metro-labs/daemon/src/stations/runtime-deps.ts +82 -0
  208. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/stations}/supervisor-io.ts +3 -3
  209. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/stations}/supervisor.ts +6 -9
  210. package/runtime/node_modules/@metro-labs/daemon/src/stations/threema-callbacks.ts +32 -0
  211. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/stations}/train-call.ts +1 -1
  212. package/runtime/node_modules/@metro-labs/daemon/src/stations/webhook-endpoints.ts +51 -0
  213. package/runtime/node_modules/@metro-labs/daemon/src/terminal/api.ts +84 -0
  214. package/runtime/node_modules/@metro-labs/daemon/src/terminal/socket.ts +124 -0
  215. package/runtime/node_modules/@metro-labs/daemon/src/terminal/tickets.ts +15 -0
  216. package/runtime/node_modules/@metro-labs/daemon/src/vault/api.ts +45 -0
  217. package/runtime/node_modules/@metro-labs/daemon/src/vault/config.ts +51 -0
  218. package/runtime/node_modules/@metro-labs/daemon/src/vault/firewall.ts +9 -0
  219. package/runtime/node_modules/@metro-labs/daemon/src/vault/index.ts +96 -0
  220. package/runtime/node_modules/@metro-labs/daemon/src/vault/install.ts +56 -0
  221. package/runtime/node_modules/@metro-labs/daemon/src/vault/paths.ts +26 -0
  222. package/runtime/node_modules/@metro-labs/daemon/src/vault/proxy.ts +147 -0
  223. package/runtime/node_modules/@metro-labs/daemon/src/vault/store.ts +129 -0
  224. package/runtime/node_modules/@metro-labs/daemon/src/vault/trust.ts +44 -0
  225. package/runtime/node_modules/@metro-labs/{discord → discord-bot}/package.json +3 -5
  226. package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/accounts.ts +8 -28
  227. package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/actions.ts +19 -187
  228. package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/attachments.ts +3 -3
  229. package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/format.ts +31 -72
  230. package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/group-actions.ts +2 -2
  231. package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/group.ts +2 -2
  232. package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/index.ts +15 -21
  233. package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/members.ts +2 -2
  234. package/runtime/node_modules/@metro-labs/discord-bot/src/profile.ts +68 -0
  235. package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/send-files.ts +12 -13
  236. package/runtime/node_modules/@metro-labs/discord-bot/src/station.ts +23 -0
  237. package/runtime/node_modules/@metro-labs/http/package.json +29 -0
  238. package/runtime/node_modules/@metro-labs/http/src/api-http.ts +135 -0
  239. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/session-api.ts → http/src/mode-api.ts} +13 -9
  240. package/runtime/node_modules/@metro-labs/http/src/return-to.ts +21 -0
  241. package/runtime/node_modules/@metro-labs/http/src/workos-token.ts +149 -0
  242. package/runtime/node_modules/@metro-labs/{telegram-user → outlook}/package.json +2 -5
  243. package/runtime/node_modules/@metro-labs/outlook/src/accounts.ts +93 -0
  244. package/runtime/node_modules/@metro-labs/outlook/src/actions.ts +14 -0
  245. package/runtime/node_modules/@metro-labs/outlook/src/attachments.ts +97 -0
  246. package/runtime/node_modules/@metro-labs/outlook/src/auth.ts +150 -0
  247. package/runtime/node_modules/@metro-labs/outlook/src/browser.ts +53 -0
  248. package/runtime/node_modules/@metro-labs/outlook/src/config.ts +36 -0
  249. package/runtime/node_modules/@metro-labs/outlook/src/format.ts +140 -0
  250. package/runtime/node_modules/@metro-labs/outlook/src/graph.ts +60 -0
  251. package/runtime/node_modules/@metro-labs/outlook/src/html.ts +72 -0
  252. package/runtime/node_modules/@metro-labs/outlook/src/inbound.ts +104 -0
  253. package/runtime/node_modules/@metro-labs/outlook/src/index.ts +12 -0
  254. package/runtime/node_modules/@metro-labs/outlook/src/login.ts +150 -0
  255. package/runtime/node_modules/@metro-labs/outlook/src/me.ts +41 -0
  256. package/runtime/node_modules/@metro-labs/outlook/src/outbound.ts +116 -0
  257. package/runtime/node_modules/@metro-labs/outlook/src/query.ts +119 -0
  258. package/runtime/node_modules/@metro-labs/outlook/src/state.ts +43 -0
  259. package/runtime/node_modules/@metro-labs/outlook/src/station.ts +15 -0
  260. package/runtime/node_modules/@metro-labs/outlook/src/trust.ts +70 -0
  261. package/runtime/node_modules/@metro-labs/telegram/package.json +3 -2
  262. package/runtime/node_modules/@metro-labs/telegram/src/accounts.ts +38 -96
  263. package/runtime/node_modules/@metro-labs/telegram/src/actions.ts +214 -253
  264. package/runtime/node_modules/@metro-labs/telegram/src/attachments.ts +67 -108
  265. package/runtime/node_modules/@metro-labs/{telegram-user → telegram}/src/client.ts +6 -6
  266. package/runtime/node_modules/@metro-labs/telegram/src/format.ts +101 -147
  267. package/runtime/node_modules/@metro-labs/{telegram-user → telegram}/src/group.ts +4 -4
  268. package/runtime/node_modules/@metro-labs/{telegram-user → telegram}/src/history.ts +1 -1
  269. package/runtime/node_modules/@metro-labs/telegram/src/inbound.ts +57 -0
  270. package/runtime/node_modules/@metro-labs/telegram/src/index.ts +6 -102
  271. package/runtime/node_modules/@metro-labs/{telegram-user → telegram}/src/login.ts +20 -20
  272. package/runtime/node_modules/@metro-labs/telegram/src/media-actions.ts +64 -151
  273. package/runtime/node_modules/@metro-labs/telegram/src/members.ts +61 -33
  274. package/runtime/node_modules/@metro-labs/telegram/src/profile.ts +70 -0
  275. package/runtime/node_modules/@metro-labs/{telegram-user → telegram}/src/reactions.ts +3 -3
  276. package/runtime/node_modules/@metro-labs/telegram/src/station.ts +11 -1
  277. package/runtime/node_modules/@metro-labs/telegram/src/types.ts +5 -47
  278. package/runtime/node_modules/@metro-labs/telegram-bot/package.json +25 -0
  279. package/runtime/node_modules/@metro-labs/telegram-bot/src/accounts.ts +86 -0
  280. package/runtime/node_modules/@metro-labs/telegram-bot/src/actions.ts +240 -0
  281. package/runtime/node_modules/@metro-labs/telegram-bot/src/attachments.ts +128 -0
  282. package/runtime/node_modules/@metro-labs/telegram-bot/src/format.ts +170 -0
  283. package/runtime/node_modules/@metro-labs/telegram-bot/src/index.ts +103 -0
  284. package/runtime/node_modules/@metro-labs/telegram-bot/src/media-actions.ts +90 -0
  285. package/runtime/node_modules/@metro-labs/telegram-bot/src/members.ts +47 -0
  286. package/runtime/node_modules/@metro-labs/telegram-bot/src/profile.ts +85 -0
  287. package/runtime/node_modules/@metro-labs/telegram-bot/src/station.ts +21 -0
  288. package/runtime/node_modules/@metro-labs/telegram-bot/src/types.ts +56 -0
  289. package/runtime/node_modules/@metro-labs/threema/package.json +26 -0
  290. package/runtime/node_modules/@metro-labs/threema/src/accounts.ts +95 -0
  291. package/runtime/node_modules/@metro-labs/threema/src/actions.ts +124 -0
  292. package/runtime/node_modules/@metro-labs/threema/src/api.ts +152 -0
  293. package/runtime/node_modules/@metro-labs/threema/src/crypto.ts +100 -0
  294. package/runtime/node_modules/@metro-labs/threema/src/files.ts +47 -0
  295. package/runtime/node_modules/@metro-labs/threema/src/format.ts +164 -0
  296. package/runtime/node_modules/@metro-labs/threema/src/groups.ts +96 -0
  297. package/runtime/node_modules/@metro-labs/threema/src/ids.ts +21 -0
  298. package/runtime/node_modules/@metro-labs/threema/src/inbound.ts +89 -0
  299. package/runtime/node_modules/@metro-labs/threema/src/index.ts +24 -0
  300. package/runtime/node_modules/@metro-labs/threema/src/messages.ts +264 -0
  301. package/runtime/node_modules/@metro-labs/threema/src/outbound.ts +160 -0
  302. package/runtime/node_modules/@metro-labs/threema/src/station.ts +13 -0
  303. package/runtime/node_modules/@metro-labs/threema/src/verify.ts +117 -0
  304. package/runtime/node_modules/@metro-labs/webhook/package.json +1 -1
  305. package/runtime/node_modules/@metro-labs/webhook/src/station.ts +5 -8
  306. package/runtime/node_modules/@metro-labs/whatsapp/package.json +2 -5
  307. package/runtime/node_modules/@metro-labs/whatsapp/src/accounts.ts +6 -28
  308. package/runtime/node_modules/@metro-labs/whatsapp/src/ack.ts +1 -1
  309. package/runtime/node_modules/@metro-labs/whatsapp/src/actions.ts +54 -11
  310. package/runtime/node_modules/@metro-labs/whatsapp/src/attachments.ts +2 -2
  311. package/runtime/node_modules/@metro-labs/whatsapp/src/auth-state.ts +1 -1
  312. package/runtime/node_modules/@metro-labs/whatsapp/src/client.ts +86 -4
  313. package/runtime/node_modules/@metro-labs/whatsapp/src/format.ts +7 -58
  314. package/runtime/node_modules/@metro-labs/whatsapp/src/inbound.ts +11 -28
  315. package/runtime/node_modules/@metro-labs/whatsapp/src/index.ts +4 -37
  316. package/runtime/node_modules/@metro-labs/whatsapp/src/keys.ts +1 -1
  317. package/runtime/node_modules/@metro-labs/whatsapp/src/login.ts +1 -1
  318. package/runtime/node_modules/@metro-labs/whatsapp/src/media.ts +1 -1
  319. package/runtime/node_modules/@metro-labs/whatsapp/src/names.ts +75 -0
  320. package/runtime/node_modules/@metro-labs/whatsapp/src/parse.ts +44 -0
  321. package/runtime/node_modules/@metro-labs/whatsapp/src/resolve.ts +52 -0
  322. package/runtime/node_modules/@metro-labs/whatsapp/src/station.ts +16 -1
  323. package/runtime/node_modules/@metro-labs/whatsapp/src/token-store.ts +5 -9
  324. package/runtime/node_modules/@metro-labs/whatsapp/src/types.ts +0 -1
  325. package/runtime/node_modules/@metro-labs/xmtp/package.json +3 -2
  326. package/runtime/node_modules/@metro-labs/xmtp/src/accounts.ts +10 -20
  327. package/runtime/node_modules/@metro-labs/xmtp/src/actions-close.ts +2 -2
  328. package/runtime/node_modules/@metro-labs/xmtp/src/actions-conv.ts +15 -204
  329. package/runtime/node_modules/@metro-labs/xmtp/src/actions-meta.ts +4 -43
  330. package/runtime/node_modules/@metro-labs/xmtp/src/actions.ts +41 -219
  331. package/runtime/node_modules/@metro-labs/xmtp/src/attachments.ts +3 -3
  332. package/runtime/node_modules/@metro-labs/xmtp/src/conv-helpers.ts +3 -3
  333. package/runtime/node_modules/@metro-labs/xmtp/src/emit-payloads.ts +7 -24
  334. package/runtime/node_modules/@metro-labs/xmtp/src/emit.ts +8 -18
  335. package/runtime/node_modules/@metro-labs/xmtp/src/group-members.ts +1 -1
  336. package/runtime/node_modules/@metro-labs/xmtp/src/group.ts +2 -2
  337. package/runtime/node_modules/@metro-labs/xmtp/src/identity.ts +30 -16
  338. package/runtime/node_modules/@metro-labs/xmtp/src/index.ts +12 -20
  339. package/runtime/node_modules/@metro-labs/xmtp/src/labels.ts +1 -19
  340. package/runtime/node_modules/@metro-labs/xmtp/src/member-args.ts +1 -1
  341. package/runtime/node_modules/@metro-labs/xmtp/src/names.ts +61 -0
  342. package/runtime/node_modules/@metro-labs/xmtp/src/profile.ts +153 -0
  343. package/runtime/node_modules/@metro-labs/xmtp/src/sender.ts +112 -0
  344. package/runtime/node_modules/@metro-labs/xmtp/src/smart.ts +72 -0
  345. package/runtime/node_modules/@metro-labs/xmtp/src/station.ts +5 -1
  346. package/runtime/node_modules/@metro-labs/xmtp/src/tools-handlers.ts +4 -51
  347. package/runtime/node_modules/@metro-labs/xmtp/src/tools.ts +30 -44
  348. package/runtime/node_modules/@metro-labs/xmtp/src/transcribe.ts +4 -6
  349. package/runtime/node_modules/@metro-labs/xmtp/src/verify.ts +19 -5
  350. package/runtime/node_modules/@metro-labs/xmtp/src/wire.ts +14 -4
  351. package/runtime/runtime.json +1 -1
  352. package/runtime/server.ts +1 -0
  353. package/runtime/stations.json +37 -0
  354. package/dist/prompt.js +0 -10
  355. package/dist/store.js +0 -70
  356. package/runtime/node_modules/@metro-labs/discord/src/station.ts +0 -19
  357. package/runtime/node_modules/@metro-labs/discord/src/voice-speak.ts +0 -195
  358. package/runtime/node_modules/@metro-labs/discord/src/voice-transcribe.ts +0 -292
  359. package/runtime/node_modules/@metro-labs/discord/src/voice.ts +0 -197
  360. package/runtime/node_modules/@metro-labs/discord/src/wire.ts +0 -5
  361. package/runtime/node_modules/@metro-labs/mcp/package.json +0 -66
  362. package/runtime/node_modules/@metro-labs/mcp/src/channels/dedupe.ts +0 -24
  363. package/runtime/node_modules/@metro-labs/mcp/src/daemon/account-api.ts +0 -311
  364. package/runtime/node_modules/@metro-labs/mcp/src/daemon/agent-api.ts +0 -335
  365. package/runtime/node_modules/@metro-labs/mcp/src/daemon/api-http.ts +0 -129
  366. package/runtime/node_modules/@metro-labs/mcp/src/daemon/boot.ts +0 -322
  367. package/runtime/node_modules/@metro-labs/mcp/src/daemon/cli-pair-api.ts +0 -111
  368. package/runtime/node_modules/@metro-labs/mcp/src/daemon/cli-pair.ts +0 -20
  369. package/runtime/node_modules/@metro-labs/mcp/src/daemon/collection-api.ts +0 -202
  370. package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-json.ts +0 -31
  371. package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-tools.ts +0 -100
  372. package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-url.ts +0 -57
  373. package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-verify.ts +0 -333
  374. package/runtime/node_modules/@metro-labs/mcp/src/daemon/google-auth.ts +0 -164
  375. package/runtime/node_modules/@metro-labs/mcp/src/daemon/google-oauth.ts +0 -208
  376. package/runtime/node_modules/@metro-labs/mcp/src/daemon/identity.ts +0 -79
  377. package/runtime/node_modules/@metro-labs/mcp/src/daemon/oauth-pending.ts +0 -65
  378. package/runtime/node_modules/@metro-labs/mcp/src/daemon/pair-codes.ts +0 -58
  379. package/runtime/node_modules/@metro-labs/mcp/src/daemon/project-api.ts +0 -214
  380. package/runtime/node_modules/@metro-labs/mcp/src/daemon/run-api.ts +0 -125
  381. package/runtime/node_modules/@metro-labs/mcp/src/daemon/run-pair.ts +0 -18
  382. package/runtime/node_modules/@metro-labs/mcp/src/daemon/runtime-source.ts +0 -105
  383. package/runtime/node_modules/@metro-labs/mcp/src/daemon/session-apis.ts +0 -41
  384. package/runtime/node_modules/@metro-labs/mcp/src/daemon/session.ts +0 -218
  385. package/runtime/node_modules/@metro-labs/mcp/src/daemon/tunnel.ts +0 -169
  386. package/runtime/node_modules/@metro-labs/mcp/src/db/account-attach.ts +0 -91
  387. package/runtime/node_modules/@metro-labs/mcp/src/db/agent-admin.ts +0 -215
  388. package/runtime/node_modules/@metro-labs/mcp/src/db/client.ts +0 -37
  389. package/runtime/node_modules/@metro-labs/mcp/src/db/connector-collections.ts +0 -218
  390. package/runtime/node_modules/@metro-labs/mcp/src/db/connectors.ts +0 -329
  391. package/runtime/node_modules/@metro-labs/mcp/src/db/materialize.ts +0 -364
  392. package/runtime/node_modules/@metro-labs/mcp/src/db/projects.ts +0 -300
  393. package/runtime/node_modules/@metro-labs/mcp/src/db/runtime-admin.ts +0 -31
  394. package/runtime/node_modules/@metro-labs/mcp/src/db/runtimes.ts +0 -105
  395. package/runtime/node_modules/@metro-labs/mcp/src/db/schema.ts +0 -131
  396. package/runtime/node_modules/@metro-labs/mcp/src/db/token-carry.ts +0 -45
  397. package/runtime/node_modules/@metro-labs/mcp/src/db/users.ts +0 -57
  398. package/runtime/node_modules/@metro-labs/mcp/src/db/whatsapp-login.ts +0 -18
  399. package/runtime/node_modules/@metro-labs/mcp/src/mcp/channel-owner.ts +0 -29
  400. package/runtime/node_modules/@metro-labs/mcp/src/mcp/frame-scope.ts +0 -21
  401. package/runtime/node_modules/@metro-labs/mcp/src/mcp/permission-relay.ts +0 -66
  402. package/runtime/node_modules/@metro-labs/mcp/src/mcp/request-identity.ts +0 -73
  403. package/runtime/node_modules/@metro-labs/mcp/src/mcp/session-registry.ts +0 -172
  404. package/runtime/node_modules/@metro-labs/mcp/src/mcp/session-route.ts +0 -43
  405. package/runtime/node_modules/@metro-labs/mcp/src/monitor/api.ts +0 -240
  406. package/runtime/node_modules/@metro-labs/mcp/src/server.ts +0 -2
  407. package/runtime/node_modules/@metro-labs/mcp/src/stations/account-store.ts +0 -80
  408. package/runtime/node_modules/@metro-labs/mcp/src/stations/messaging-normalize.ts +0 -88
  409. package/runtime/node_modules/@metro-labs/telegram/src/wire.ts +0 -3
  410. package/runtime/node_modules/@metro-labs/telegram-user/src/accounts.ts +0 -81
  411. package/runtime/node_modules/@metro-labs/telegram-user/src/actions.ts +0 -254
  412. package/runtime/node_modules/@metro-labs/telegram-user/src/attachments.ts +0 -87
  413. package/runtime/node_modules/@metro-labs/telegram-user/src/format.ts +0 -141
  414. package/runtime/node_modules/@metro-labs/telegram-user/src/inbound.ts +0 -78
  415. package/runtime/node_modules/@metro-labs/telegram-user/src/index.ts +0 -46
  416. package/runtime/node_modules/@metro-labs/telegram-user/src/media-actions.ts +0 -80
  417. package/runtime/node_modules/@metro-labs/telegram-user/src/members.ts +0 -75
  418. package/runtime/node_modules/@metro-labs/telegram-user/src/normalize.ts +0 -22
  419. package/runtime/node_modules/@metro-labs/telegram-user/src/station.ts +0 -24
  420. package/runtime/node_modules/@metro-labs/telegram-user/src/types.ts +0 -7
  421. package/runtime/node_modules/@metro-labs/telegram-user/src/wire.ts +0 -1
  422. package/runtime/node_modules/@metro-labs/whatsapp/src/normalize.ts +0 -22
  423. package/runtime/node_modules/@metro-labs/whatsapp/src/wire.ts +0 -5
  424. package/runtime/node_modules/@metro-labs/xmtp/src/actions-push.ts +0 -87
  425. package/runtime/node_modules/@metro-labs/xmtp/src/emit-core.ts +0 -55
  426. package/runtime/node_modules/@metro-labs/xmtp/src/push.ts +0 -349
  427. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/log.ts +0 -0
  428. /package/runtime/node_modules/@metro-labs/{mcp/src/mcp → core/src}/str.ts +0 -0
  429. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/train-error.ts +0 -0
  430. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/webhook-note.ts +0 -0
  431. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/raw-get-stream.ts +0 -0
  432. /package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/api-base.ts +0 -0
  433. /package/runtime/node_modules/@metro-labs/{discord → discord-bot}/src/verify.ts +0 -0
  434. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → http/src}/api-error.ts +0 -0
  435. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → http/src}/cors.ts +0 -0
  436. /package/runtime/node_modules/@metro-labs/{telegram → telegram-bot}/src/verify.ts +0 -0
@@ -1,4 +1,5 @@
1
1
  import { createHash } from 'node:crypto';
2
+ import { Line } from '@metro-labs/core/lines';
2
3
  import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
4
  import {
4
5
  ListToolsRequestSchema,
@@ -9,10 +10,12 @@ import {
9
10
  STATIONS,
10
11
  accountStationCapabilities,
11
12
  } from '../stations/registry.js';
12
- import type { Station, StationTool, ToolResult } from '../stations/types.js';
13
- import { COMMON_TOOLS, LIST_ACCOUNTS_TOOL } from './tool-schemas.js';
13
+ import type { Station, StationTool, ToolResult } from '@metro-labs/core/stations/types';
14
+ import { listedTools, stationForTool, type PublishedTool } from './tool-catalog.js';
15
+ import { policyGate, withEffectivePolicy } from './policy-gate.js';
16
+ import { settlePromptsFor } from '../approvals/pending.js';
14
17
  import { errResult, makeCtx, okJson, toErr } from './ctx.js';
15
- import { dispatchMessageTool } from './call-tools.js';
18
+ import { dispatchMessageTool, type ToolHooks } from './call-tools.js';
16
19
  import { dispatchListMembers } from './member-tools.js';
17
20
  import {
18
21
  dispatchAddMembers,
@@ -21,16 +24,19 @@ import {
21
24
  dispatchRemoveMembers,
22
25
  } from './group-tools.js';
23
26
  import { dispatchCreateUpload } from './upload-tool.js';
24
- import { callTargetDenied, lineTargetDenied } from '../db/agent-scope.js';
27
+ import { dispatchSetProfile, profileCapabilities } from './profile-tool.js';
28
+ import { dispatchGetProfile, profileScopeLine } from './profile-lookup.js';
29
+ import { callTargetDenied, lineTargetDenied } from '../agents/scope.js';
25
30
  import { SOURCE_KEYS } from '../stations/attach-resolve.js';
26
31
  import { decodedLengthOf } from '../stations/attach-inline.js';
27
- import { log } from '../daemon/log.js';
32
+ import { log } from '@metro-labs/core/log';
28
33
  import {
29
34
  allowedAgents,
30
35
  currentIdentity,
31
36
  type RequestIdentity,
32
37
  } from './request-identity.js';
33
- import { str } from './str.js';
38
+ import { str } from '@metro-labs/core/str';
39
+ import { linelessRead, stationOfAccount } from './read-tool.js';
34
40
 
35
41
  const STATION_TOOLS = new Map<
36
42
  string,
@@ -49,21 +55,11 @@ const CORE_DISPATCH: Record<
49
55
  remove_members: dispatchRemoveMembers,
50
56
  export_invite: dispatchInviteLink,
51
57
  create_upload: dispatchCreateUpload,
58
+ set_profile: dispatchSetProfile,
59
+ get_profile: dispatchGetProfile,
52
60
  };
53
61
 
54
- const toolList = (): { tools: unknown[] } => ({
55
- tools: [
56
- ...COMMON_TOOLS,
57
- ...STATIONS.flatMap((s) =>
58
- s.tools.map((t) => ({
59
- name: t.name,
60
- description: t.description,
61
- inputSchema: t.inputSchema,
62
- })),
63
- ),
64
- LIST_ACCOUNTS_TOOL,
65
- ],
66
- });
62
+ export const toolList = (): { tools: PublishedTool[] } => ({ tools: listedTools() });
67
63
 
68
64
  let schemaSignature: string | undefined;
69
65
 
@@ -80,28 +76,31 @@ async function handleListAccounts(
80
76
  ): Promise<ToolResult> {
81
77
  try {
82
78
  return okJson({
83
- accounts: await gatherAccounts(allowedAgents(identity)),
79
+ accounts: withEffectivePolicy(await gatherAccounts(allowedAgents(identity))),
84
80
  capabilities: accountStationCapabilities(),
81
+ profiles: profileCapabilities(),
85
82
  });
86
83
  } catch (e) {
87
84
  return errResult(`metro list_accounts failed: ${String(e)}`);
88
85
  }
89
86
  }
90
87
 
91
- function stationForTool(
92
- name: string,
93
- args: Record<string, unknown>,
94
- ): string | undefined {
95
- if (name === 'create_group') return str(args.station) || undefined;
96
- return STATION_TOOLS.get(name)?.station.name;
97
- }
98
-
99
88
  export function scopeDenied(
100
89
  identity: RequestIdentity | undefined,
101
90
  name: string,
102
91
  args: Record<string, unknown>,
103
92
  ): boolean {
104
93
  const allowed = allowedAgents(identity);
94
+ if (name === 'read' && !str(args.line)) {
95
+ const account = str(args.account);
96
+ if (!account) return false;
97
+ const station = stationOfAccount(account);
98
+ return station === undefined || callTargetDenied(allowed, station, args);
99
+ }
100
+ if (name === 'get_profile') {
101
+ const line = profileScopeLine(args);
102
+ return line === undefined || callTargetDenied(allowed, Line.station(line) ?? '', { line });
103
+ }
105
104
  const station = stationForTool(name, args);
106
105
  if (station !== undefined) return callTargetDenied(allowed, station, args);
107
106
  return lineTargetDenied(allowed, args);
@@ -142,9 +141,10 @@ function logToolFailure(
142
141
  );
143
142
  }
144
143
 
145
- async function runTool(req: {
146
- params: { name: string; arguments?: Record<string, unknown> };
147
- }): Promise<ToolResult> {
144
+ async function runTool(
145
+ req: { params: { name: string; arguments?: Record<string, unknown> } },
146
+ hooks: ToolHooks,
147
+ ): Promise<ToolResult> {
148
148
  const name = req.params.name;
149
149
  const a = req.params.arguments ?? {};
150
150
 
@@ -152,6 +152,19 @@ async function runTool(req: {
152
152
  if (name !== 'list_accounts' && scopeDenied(identity, name, a))
153
153
  return errResult('metro: this account is outside your authorized scope');
154
154
 
155
+ settlePromptsFor(name, a);
156
+ const blocked = policyGate(name, a);
157
+ if (blocked) return blocked;
158
+
159
+ return dispatchTool(name, a, identity, hooks);
160
+ }
161
+
162
+ async function dispatchTool(
163
+ name: string,
164
+ a: Record<string, unknown>,
165
+ identity: RequestIdentity | undefined,
166
+ hooks: ToolHooks,
167
+ ): Promise<ToolResult> {
155
168
  const owned = STATION_TOOLS.get(name);
156
169
  if (owned) {
157
170
  try {
@@ -160,19 +173,18 @@ async function runTool(req: {
160
173
  return toErr(name, e);
161
174
  }
162
175
  }
163
-
164
176
  const core = CORE_DISPATCH[name];
165
177
  if (core) return core(a);
166
-
167
178
  if (name === 'list_accounts') return handleListAccounts(identity);
168
-
169
- return dispatchMessageTool(name, a);
179
+ if (name === 'read' && !str(a.line)) return linelessRead(a);
180
+ return dispatchMessageTool(name, a, hooks);
170
181
  }
171
182
 
172
- export async function callToolHandler(req: {
173
- params: { name: string; arguments?: Record<string, unknown> };
174
- }): Promise<ToolResult> {
175
- const result = await runTool(req);
183
+ export async function callToolHandler(
184
+ req: { params: { name: string; arguments?: Record<string, unknown> } },
185
+ hooks: ToolHooks = {},
186
+ ): Promise<ToolResult> {
187
+ const result = await runTool(req, hooks);
176
188
  if (result.isError === true)
177
189
  logToolFailure(req.params.name, req.params.arguments ?? {}, result);
178
190
  return result;
@@ -192,6 +204,7 @@ interface NotifyingExtra {
192
204
  export function registerToolHandlers(
193
205
  server: Server,
194
206
  notice?: SchemaNotice,
207
+ hooks: ToolHooks = {},
195
208
  ): void {
196
209
  server.setRequestHandler(ListToolsRequestSchema, () => {
197
210
  notice?.markCurrent();
@@ -206,7 +219,7 @@ export function registerToolHandlers(
206
219
  notice?.deliver(() =>
207
220
  extra.sendNotification({ method: TOOL_LIST_CHANGED }),
208
221
  );
209
- return callToolHandler(req);
222
+ return callToolHandler(req, hooks);
210
223
  }) as Parameters<typeof server.setRequestHandler>[1],
211
224
  );
212
225
  }
@@ -1,3 +1,6 @@
1
+ import type { ToolDef } from './tool-def.js';
2
+ import { attachmentItem, CREATE_UPLOAD_TOOL } from './attachment-schema.js';
3
+
1
4
  const lineProp = {
2
5
  type: 'string',
3
6
  description:
@@ -8,98 +11,10 @@ const msgIdProp = {
8
11
  description: 'The target message_id.',
9
12
  } as const;
10
13
 
11
- const attachmentItem = {
12
- type: 'object',
13
- description:
14
- 'A file to attach. Provide EXACTLY ONE source; naming two is an error and so is naming ' +
15
- 'none. Which one to use: `upload` for any real file on your own machine, including a ' +
16
- 'confidential one (call `create_upload` first, push the bytes over HTTP, then name the ' +
17
- 'id here); `data` ONLY for a tiny file, a few KB at most, because the base64 has to be ' +
18
- 'written out verbatim in this tool call and long base64 gets corrupted in the writing; ' +
19
- '`url` when the file is ALREADY published somewhere the daemon can fetch it; `path` ONLY ' +
20
- 'for a file that is already sitting on the daemon host, which is almost never your ' +
21
- 'machine.',
22
- properties: {
23
- upload: {
24
- type: 'string',
25
- description:
26
- 'The `upload_id` of a file already pushed to metro over HTTP (`create_upload` mints ' +
27
- 'the slot and the one-line command; the bytes never pass through this conversation). ' +
28
- 'THIS IS THE ROUTE FOR ANYTHING REAL: it takes files up to 64 MiB, works for a file on ' +
29
- 'your own machine, and publishes nothing. The upload belongs to your agent, expires ' +
30
- '30 minutes after it is created, and no other agent can name it.',
31
- },
32
- data: {
33
- type: 'string',
34
- description:
35
- 'Base64-encoded file bytes, inline in this call. ONLY FOR TINY FILES. The hard cap is ' +
36
- '8 MiB decoded, but the real ceiling is far lower and is not enforced by the daemon: ' +
37
- 'this base64 has to be emitted verbatim as part of the tool call, and past roughly ' +
38
- '10 KB (~13 KB of base64) it comes out corrupted, so the file arrives silently ' +
39
- 'damaged or fails to decode. Use `upload` instead for anything bigger. A ' +
40
- '`data:<mime>;base64,` prefix is accepted and supplies the mime when `mime` is ' +
41
- 'omitted. Stations impose their own, lower limits (xmtp refuses non-image files over ' +
42
- '~190 KiB).',
43
- },
44
- url: {
45
- type: 'string',
46
- description:
47
- 'http(s) URL fetched BY THE DAEMON, so it must already be publicly reachable from the ' +
48
- 'daemon host. Right when the file is already published; never for anything ' +
49
- 'confidential, because it has to be public for this to work at all. Use `upload` for ' +
50
- 'a confidential file.',
51
- },
52
- path: {
53
- type: 'string',
54
- description:
55
- 'Absolute path resolved ON THE DAEMON HOST, which is a different machine from yours. ' +
56
- 'A path on your own disk does NOT resolve here and is refused, however local it ' +
57
- 'looks. Use `upload` for a file on your machine.',
58
- },
59
- mime: {
60
- type: 'string',
61
- description: 'MIME type (guessed from the name/extension if omitted).',
62
- },
63
- name: {
64
- type: 'string',
65
- description:
66
- 'Filename to present (defaults to the basename, or to the name given at upload time).',
67
- },
68
- },
69
- } as const;
70
-
71
- const CREATE_UPLOAD_TOOL = {
72
- name: 'create_upload',
73
- description:
74
- 'Reserve a slot to push a file to metro over HTTP so you can attach it with `send`. Use ' +
75
- 'this for any file that actually matters: it is the only attachment route that carries a ' +
76
- 'file from YOUR machine without publishing it and without the bytes passing through this ' +
77
- 'conversation. Args: name? (the filename to present), mime?. Returns `upload_id`, a ' +
78
- 'single-use `upload_url` and a ready-to-run `curl` line. ONE STEP NEEDS A SHELL: run that ' +
79
- 'command (or any HTTP client) to push the bytes; there is no way to move a local file to ' +
80
- 'the daemon over MCP alone, because anything in an MCP call has to be written out by the ' +
81
- 'model first. If you have no shell, hand the single command to a subagent that does and ' +
82
- 'keep the `upload_id` -- the slot belongs to this metro agent, not to whoever runs the ' +
83
- 'command. Then: send({line, attachments:[{upload:"<upload_id>"}]}). Up to 64 MiB, expires ' +
84
- '30 minutes after it is created, and no other agent can reference it.',
85
- inputSchema: {
86
- type: 'object',
87
- properties: {
88
- name: {
89
- type: 'string',
90
- description: 'Filename to present to the recipient (e.g. `report.pdf`).',
91
- },
92
- mime: {
93
- type: 'string',
94
- description: 'MIME type (guessed from the name/extension if omitted).',
95
- },
96
- },
97
- },
98
- };
99
-
100
- export const COMMON_TOOLS = [
14
+ export const COMMON_TOOLS: ToolDef[] = [
101
15
  {
102
16
  name: 'reply',
17
+ group: 'write',
103
18
  description:
104
19
  'Reply to a specific message in a Metro conversation (text quotes the target). Args: ' +
105
20
  "line, message_id, text. The station is derived from the line. Returns the daemon's " +
@@ -116,9 +31,12 @@ export const COMMON_TOOLS = [
116
31
  },
117
32
  {
118
33
  name: 'send',
34
+ group: 'write',
119
35
  description:
120
36
  'Send a message (and/or media) to a Metro conversation. Args: line, text?, reply_to?, ' +
121
- 'attachments?. The station is derived from the line. Each attachment names EXACTLY ONE ' +
37
+ 'subject?, attachments?. The station is derived from the line. Outlook: send to ' +
38
+ 'metro://outlook/<account>/<email address> to start a new email (subject defaults to the ' +
39
+ 'first line of text); the result names the new thread line. Each attachment names EXACTLY ONE ' +
122
40
  'source, and the choice matters: `upload` (an `upload_id` from `create_upload`, the ' +
123
41
  'route for any real file on your own machine, confidential or not, up to 64 MiB); ' +
124
42
  '`data` (base64 inline -- TINY FILES ONLY, a few KB, because the base64 has to be ' +
@@ -139,6 +57,10 @@ export const COMMON_TOOLS = [
139
57
  type: 'string',
140
58
  description: 'Optional message_id to quote/reply to.',
141
59
  },
60
+ subject: {
61
+ type: 'string',
62
+ description: 'Outlook only: the subject of a new email.',
63
+ },
142
64
  attachments: {
143
65
  type: 'array',
144
66
  description: 'Optional files to attach.',
@@ -150,6 +72,7 @@ export const COMMON_TOOLS = [
150
72
  },
151
73
  {
152
74
  name: 'react',
75
+ group: 'write',
153
76
  description:
154
77
  'Add an emoji reaction to a message. Args: line, message_id, emoji. The station is derived from the line.',
155
78
  inputSchema: {
@@ -162,8 +85,22 @@ export const COMMON_TOOLS = [
162
85
  required: ['line', 'message_id', 'emoji'],
163
86
  },
164
87
  },
88
+ {
89
+ name: 'typing',
90
+ group: 'write',
91
+ description:
92
+ 'Show "typing…" once in a chat while you prepare an answer. The network clears it by itself after its own time (about 5 s on the Telegram bot, 10 s on Discord, 25 s on WhatsApp) or when you send. Call it again to show it again. Args: line.',
93
+ inputSchema: {
94
+ type: 'object',
95
+ properties: {
96
+ line: lineProp,
97
+ },
98
+ required: ['line'],
99
+ },
100
+ },
165
101
  {
166
102
  name: 'unreact',
103
+ group: 'write',
167
104
  description:
168
105
  'Remove an emoji reaction from a message. Args: line, message_id, emoji. The station is derived from the line.',
169
106
  inputSchema: {
@@ -181,6 +118,7 @@ export const COMMON_TOOLS = [
181
118
  },
182
119
  {
183
120
  name: 'edit',
121
+ group: 'write',
184
122
  description:
185
123
  'Edit the text of a message you sent. Args: line, message_id, text. The station is ' +
186
124
  "derived from the line. Returns the daemon's reason if the station does not support edits.",
@@ -196,6 +134,8 @@ export const COMMON_TOOLS = [
196
134
  },
197
135
  {
198
136
  name: 'delete',
137
+ group: 'write',
138
+ destructive: true,
199
139
  description:
200
140
  'Delete a message you sent. Args: line, message_id. The station is derived from the line. ' +
201
141
  "Returns the daemon's reason if the station does not support deletes.",
@@ -207,14 +147,26 @@ export const COMMON_TOOLS = [
207
147
  },
208
148
  {
209
149
  name: 'read',
150
+ group: 'read',
210
151
  description:
211
- 'Read recent message history for a conversation. Args: line, limit?, before?, since?. The ' +
212
- 'station is derived from the line. Returns the raw history JSON (shapes differ per ' +
213
- "station), or the daemon's reason if the station does not support reads.",
152
+ 'Read message history. Args: line?, account?, limit?, before?, since?, until?, query?, ' +
153
+ 'from?, unread_only?, message_id?. Give a line to read one conversation, or an account ' +
154
+ '(from list_accounts) instead of a line to read across that whole account, where the ' +
155
+ 'station allows it. `message_id` returns that one message in full, with its files saved ' +
156
+ 'like inbound media (url and local_path). Each station applies the filters it supports; ' +
157
+ 'the answer lists any it did not apply in `ignored`, so check it. Returns the raw JSON ' +
158
+ "(shapes differ per station), or the daemon's reason if the station does not support " +
159
+ 'reads. Outlook: `query` is a Microsoft search over all mail (with `from` folded into it; ' +
160
+ 'line, since, until and unread_only then narrow what the search found), and without ' +
161
+ '`query` every filter is applied by Outlook itself, newest first.',
214
162
  inputSchema: {
215
163
  type: 'object',
216
164
  properties: {
217
165
  line: lineProp,
166
+ account: {
167
+ type: 'string',
168
+ description: 'An account id from list_accounts, to read the whole account when you give no line.',
169
+ },
218
170
  limit: { type: 'number', description: 'Max messages to return.' },
219
171
  before: {
220
172
  type: 'string',
@@ -224,18 +176,26 @@ export const COMMON_TOOLS = [
224
176
  type: 'string',
225
177
  description: 'Return messages since this timestamp.',
226
178
  },
179
+ until: {
180
+ type: 'string',
181
+ description: 'Return messages before this timestamp.',
182
+ },
183
+ query: { type: 'string', description: 'Free text to search for.' },
184
+ from: { type: 'string', description: 'Only messages from this sender (an id or an address).' },
185
+ unread_only: { type: 'boolean', description: 'Only messages not read yet.' },
186
+ message_id: { type: 'string', description: 'Return this one message in full.' },
227
187
  },
228
- required: ['line'],
229
188
  },
230
189
  },
231
190
  {
232
191
  name: 'list_members',
192
+ group: 'read',
233
193
  description:
234
194
  'List the members of a Metro group/channel in a station-agnostic shape. Args: line, ' +
235
195
  'limit?. The station is derived from the line. Returns {line, station, memberCount, ' +
236
196
  'members:[{id, name?, display_name?, address?, roles?, is_admin?, is_bot?}], capability:' +
237
197
  '{supported, complete, reason?, total?}}. Each station fills the fields it has (xmtp: id=' +
238
- 'inboxId + address; discord: id + username/nick + roles + is_bot; telegram/telegram-user: ' +
198
+ 'inboxId + address; discord-bot: id + username/nick + roles + is_bot; telegram-bot/telegram: ' +
239
199
  'id + username/first_name). Never throws on "not supported": stations that cannot ' +
240
200
  'enumerate (e.g. the Telegram Bot API) return an empty or partial list with a reason in ' +
241
201
  '`capability`. Check `capability.complete` before assuming the roster is exhaustive.',
@@ -253,11 +213,12 @@ export const COMMON_TOOLS = [
253
213
  },
254
214
  {
255
215
  name: 'create_group',
216
+ group: 'write',
256
217
  description:
257
218
  'Create a new group/channel on a station and add members, in a station-agnostic shape. ' +
258
- 'Args: station (required, xmtp|telegram-user|discord|telegram), name (required), members? ' +
259
- '(string[]; xmtp: 0x address or inboxId, telegram-user: @username or user id, discord: ' +
260
- 'user id), account? (which station account), parent? (discord only: the metro:// line of ' +
219
+ 'Args: station (required, xmtp|telegram|discord-bot|telegram-bot), name (required), members? ' +
220
+ '(string[]; xmtp: 0x address or inboxId, telegram: @username or user id, discord-bot: ' +
221
+ 'user id), account? (which station account), parent? (discord-bot only: the metro:// line of ' +
261
222
  'the channel to open the thread under). Returns {op, line (the NEW group line), station, ' +
262
223
  'supported, reason?, id?, name?, members:[{id, status: added|invited|removed|failed, ' +
263
224
  'reason?}], inviteLink?}. Never throws on "not supported": stations that lack the op ' +
@@ -269,7 +230,7 @@ export const COMMON_TOOLS = [
269
230
  properties: {
270
231
  station: {
271
232
  type: 'string',
272
- description: 'The station to create the group on (xmtp|telegram-user|discord).',
233
+ description: 'The station to create the group on (xmtp|telegram|discord-bot).',
273
234
  },
274
235
  name: { type: 'string', description: 'The group/channel name.' },
275
236
  members: {
@@ -292,6 +253,7 @@ export const COMMON_TOOLS = [
292
253
  },
293
254
  {
294
255
  name: 'add_members',
256
+ group: 'write',
295
257
  description:
296
258
  'Add members to an existing Metro group, in a station-agnostic shape. Args: line ' +
297
259
  '(required), members? (string[]; station-specific identifiers). xmtp also accepts ' +
@@ -324,6 +286,8 @@ export const COMMON_TOOLS = [
324
286
  },
325
287
  {
326
288
  name: 'remove_members',
289
+ group: 'write',
290
+ destructive: true,
327
291
  description:
328
292
  'Remove members from an existing Metro group, in a station-agnostic shape. Args: line ' +
329
293
  '(required), members? (string[]). xmtp also accepts addresses?/inboxIds? for backward ' +
@@ -354,10 +318,11 @@ export const COMMON_TOOLS = [
354
318
  },
355
319
  {
356
320
  name: 'export_invite',
321
+ group: 'write',
357
322
  description:
358
323
  'Get a join/invite link for a Metro group, for platforms where direct-add is not always ' +
359
324
  'permitted. Args: line (required). The station is derived from the line. Returns {op, ' +
360
- 'line, station, supported, reason?, inviteLink?}. Only telegram-user supports this today; ' +
325
+ 'line, station, supported, reason?, inviteLink?}. Only telegram supports this today; ' +
361
326
  'other stations return {supported:false, reason}. Never throws on "not supported".',
362
327
  inputSchema: {
363
328
  type: 'object',
@@ -368,8 +333,9 @@ export const COMMON_TOOLS = [
368
333
  CREATE_UPLOAD_TOOL,
369
334
  ];
370
335
 
371
- export const LIST_ACCOUNTS_TOOL = {
336
+ export const LIST_ACCOUNTS_TOOL: ToolDef = {
372
337
  name: 'list_accounts',
338
+ group: 'read',
373
339
  description:
374
340
  'List the configured messaging accounts across all stations (PUBLIC identity only: ' +
375
341
  'addresses, bot ids/usernames). No args. Never returns tokens, private keys, or the ' +
@@ -378,20 +344,3 @@ export const LIST_ACCOUNTS_TOOL = {
378
344
  'verb need not be discovered by trial and error.',
379
345
  inputSchema: { type: 'object', properties: {} },
380
346
  };
381
-
382
- export const MCP_INSTRUCTIONS =
383
- 'Messages from Metro chat arrive as <channel source="metro" line="..." from="..." ' +
384
- 'station="..." message_id="...">. To respond, use the messaging tools, always passing the ' +
385
- '`line` attribute verbatim (the station is derived from it): `send` (text and/or media via ' +
386
- '`attachments`, optional `reply_to`), `reply` (quote a `message_id` with `text`), `react`/' +
387
- '`unreact` (emoji on a `message_id`), `edit`/`delete` (a `message_id`), and `read` (recent ' +
388
- "history). Station support varies - the tool returns the daemon's reason if a verb is " +
389
- 'unsupported on that line. An inbound attachment is surfaced as a note carrying the ' +
390
- "sender's own text alongside a `Public URL` - fetch that url to read the file; the note's " +
391
- '`local_path` resolves on the DAEMON host, not on yours, so the Read tool works on it only ' +
392
- 'for an agent running there. To send a file OUT, call `create_upload`, ' +
393
- 'run the one curl line it hands back (that step needs a shell; the bytes go from your disk ' +
394
- 'straight to metro and never through this conversation), then `send` with ' +
395
- 'attachments:[{upload:"<upload_id>"}]. Inline `data` is for tiny files only, `url` only for ' +
396
- 'an already-public file, and `path` is read on the DAEMON host, not yours. Tool-approval ' +
397
- 'prompts are relayed to the same chat - answer "yes <id>"/"no <id>".';
@@ -1,34 +1,29 @@
1
- import { publicBaseOrDefault } from '../daemon/attach-serve.js';
1
+ import { publicBaseOrDefault } from '../files/attach-serve.js';
2
2
  import { safeFileName } from '../stations/attach-inline.js';
3
- import { guessMime } from '../stations/attachments.js';
3
+ import { guessMime } from '@metro-labs/core/stations/attachments';
4
4
  import {
5
5
  createUploadSlot,
6
6
  issueUploadTicket,
7
7
  MAX_UPLOAD_BYTES,
8
8
  removeUpload,
9
9
  UPLOAD_TTL_MS,
10
- } from '../daemon/upload-store.js';
11
- import type { ToolResult } from '../stations/types.js';
10
+ } from '../files/upload-store.js';
11
+ import type { ToolResult } from '@metro-labs/core/stations/types';
12
12
  import { errResult, okJson } from './ctx.js';
13
13
  import { allowedAgents, currentIdentity } from './request-identity.js';
14
- import { str } from './str.js';
14
+ import { str } from '@metro-labs/core/str';
15
15
 
16
16
  const ttlMinutes = (): number => Math.round(UPLOAD_TTL_MS / 60_000);
17
17
 
18
18
  const NO_AGENT =
19
19
  'create_upload needs an agent credential; this session is not scoped to one agent';
20
20
 
21
- const manyAgents = (n: number): string =>
22
- `create_upload is scoped to one agent, but this session covers ${String(n)}` +
23
- ' (a multi-agent sign-in); use `POST /api/uploads?agent=<id>` directly instead';
24
-
25
21
  type OwnerAgent = { agentId: string } | { error: string };
26
22
 
27
23
  function ownerAgent(): OwnerAgent {
28
24
  const allowed = allowedAgents(currentIdentity());
29
25
  const [only] = [...allowed];
30
- if (allowed.size === 1 && only !== undefined) return { agentId: only };
31
- return { error: allowed.size === 0 ? NO_AGENT : manyAgents(allowed.size) };
26
+ return allowed.size === 1 && only !== undefined ? { agentId: only } : { error: NO_AGENT };
32
27
  }
33
28
 
34
29
  export function dispatchCreateUpload(