@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,82 +1,44 @@
1
1
  import type { IncomingMessage, ServerResponse } from 'node:http';
2
- import { errMsg, log } from './log.js';
2
+ import { log } from '@metro-labs/core/log';
3
+ import { healthOf } from './health.js';
4
+ import type { RemoteTool } from './tools.js';
5
+ import { normalizePolicy, type ToolPolicy } from '../policy/policy.js';
3
6
  import {
4
7
  apiFailure,
5
8
  apiSession,
6
- projectParam,
7
9
  bodyField,
8
10
  cors,
9
11
  readJsonBody,
10
12
  sendJson,
11
- type ApiSession,
12
- } from './api-http.js';
13
- import { parseId } from '../db/ids.js';
14
- import type { ConnectorCollectionRow } from '../db/connector-collections.js';
13
+ stringOf,
14
+ } from '@metro-labs/http/api-http';
15
+ import { parseId } from '@metro-labs/core/ids';
15
16
  import {
16
17
  handleCallback,
17
18
  handleConnect,
18
19
  hostOf,
19
20
  startOAuth,
20
21
  type OAuthRouteDeps,
21
- } from './connector-oauth-routes.js';
22
- import { ConnectorUnauthorized } from './connector-verify.js';
22
+ } from './oauth-routes.js';
23
+ import { ConnectorUnauthorized } from './verify.js';
23
24
  import type {
24
25
  Connector,
25
26
  ConnectorCheck,
26
27
  ConnectorInput,
27
28
  DeletedConnector,
28
- } from '../db/connectors.js';
29
+ } from './store.js';
29
30
 
30
31
  const PREFIX = '/api/connectors';
31
32
 
32
- const asText = (value: unknown): string =>
33
- typeof value === 'string' ? value : '';
34
-
35
33
  export interface ConnectorApiDeps extends OAuthRouteDeps {
36
- listConnectors: (email: string, project: string) => Promise<Connector[]>;
37
- freshConnectorsByIds: (ids: string[]) => Promise<Connector[]>;
38
- listCollections: (
39
- email: string,
40
- project: string,
41
- ) => Promise<ConnectorCollectionRow[]>;
42
- getCollection: (email: string, id: string) => Promise<ConnectorCollectionRow>;
43
- createCollection: (
44
- email: string,
45
- project: string,
46
- name: string,
47
- ) => Promise<ConnectorCollectionRow>;
48
- renameCollection: (
49
- email: string,
50
- id: string,
51
- name: string,
52
- ) => Promise<ConnectorCollectionRow>;
53
- deleteCollection: (
54
- email: string,
55
- id: string,
56
- ) => Promise<{ id: string; name: string }>;
57
- addToCollection: (
58
- email: string,
59
- id: string,
60
- connectorId: string,
61
- ) => Promise<ConnectorCollectionRow>;
62
- removeFromCollection: (
63
- email: string,
64
- id: string,
65
- connectorId: string,
66
- ) => Promise<ConnectorCollectionRow>;
67
- createConnector: (
68
- email: string,
69
- project: string,
70
- input: ConnectorInput,
71
- ) => Promise<Connector>;
72
- verifyConnector: (email: string, id: string) => Promise<ConnectorCheck>;
73
- disconnectConnector: (email: string, id: string) => Promise<Connector>;
74
- renameConnector: (
75
- email: string,
76
- id: string,
77
- name: string,
78
- ) => Promise<Connector>;
79
- deleteConnector: (email: string, id: string) => Promise<DeletedConnector>;
34
+ listConnectors: () => Promise<Connector[]>;
35
+ createConnector: (input: ConnectorInput) => Promise<Connector>;
36
+ verifyConnector: (id: string) => Promise<ConnectorCheck>;
37
+ connectorTools: (id: string) => Promise<RemoteTool[]>;
38
+ disconnectConnector: (id: string) => Promise<Connector>;
39
+ renameConnector: (id: string, name: string) => Promise<Connector>;
40
+ deleteConnector: (id: string) => Promise<DeletedConnector>;
41
+ setConnectorPolicy: (id: string, policy: ToolPolicy) => Promise<Connector>;
80
42
  }
81
43
 
82
44
  type Routable =
@@ -84,9 +46,11 @@ type Routable =
84
46
  | { kind: 'callback' }
85
47
  | { kind: 'connector'; id: string }
86
48
  | { kind: 'verify'; id: string }
49
+ | { kind: 'tools'; id: string }
87
50
  | { kind: 'connect'; id: string }
88
51
  | { kind: 'disconnect'; id: string }
89
- | { kind: 'rename'; id: string };
52
+ | { kind: 'rename'; id: string }
53
+ | { kind: 'policy'; id: string };
90
54
 
91
55
  type Target = Routable | { kind: 'unknown' } | null;
92
56
 
@@ -95,9 +59,11 @@ function subTarget(id: string, rest: string[]): Target {
95
59
  if (rest.length > 1) return { kind: 'unknown' };
96
60
  const head = rest[0];
97
61
  if (head === 'verify') return { kind: 'verify', id };
62
+ if (head === 'tools') return { kind: 'tools', id };
98
63
  if (head === 'connect') return { kind: 'connect', id };
99
64
  if (head === 'disconnect') return { kind: 'disconnect', id };
100
65
  if (head === 'rename') return { kind: 'rename', id };
66
+ if (head === 'policy') return { kind: 'policy', id };
101
67
  return { kind: 'unknown' };
102
68
  }
103
69
 
@@ -112,20 +78,18 @@ function target(path: string): Target {
112
78
  return id === null ? { kind: 'unknown' } : subTarget(id, segments.slice(1));
113
79
  }
114
80
 
115
- function connectorPayload(
116
- row: Connector,
117
- detail = false,
118
- ): Record<string, unknown> {
119
- const { catalog, ...summary } = row.verified;
81
+ function connectorPayload(row: Connector): Record<string, unknown> {
120
82
  return {
121
83
  id: row.id,
122
84
  name: row.name,
123
85
  url: row.url,
124
- transport: row.transport,
125
86
  auth: row.auth,
126
87
  header: row.header,
88
+ clientId: row.client?.clientId ?? null,
127
89
  signIn: row.signIn,
128
- verified: detail ? { ...summary, catalog } : summary,
90
+ verified: row.verified,
91
+ policy: row.policy,
92
+ health: healthOf(row.id),
129
93
  };
130
94
  }
131
95
 
@@ -133,14 +97,8 @@ async function handleList(
133
97
  req: IncomingMessage,
134
98
  res: ServerResponse,
135
99
  deps: ConnectorApiDeps,
136
- session: ApiSession,
137
100
  ): Promise<void> {
138
- const project = projectParam(req);
139
- if (project === null) {
140
- sendJson(req, res, 400, { error: 'a project is required' });
141
- return;
142
- }
143
- const rows = await deps.listConnectors(session.email, project);
101
+ const rows = await deps.listConnectors();
144
102
  sendJson(req, res, 200, {
145
103
  connectors: rows.map((row) => connectorPayload(row)),
146
104
  });
@@ -150,21 +108,17 @@ async function handleCreate(
150
108
  req: IncomingMessage,
151
109
  res: ServerResponse,
152
110
  deps: ConnectorApiDeps,
153
- session: ApiSession,
154
111
  ): Promise<void> {
155
112
  const body = await readJsonBody(req);
156
- const project = projectParam(req);
157
- if (project === null) {
158
- sendJson(req, res, 400, { error: 'a project is required' });
159
- return;
160
- }
161
- const offered = asText(bodyField(body, 'value')).trim() !== '';
113
+ const offered = stringOf(bodyField(body, 'value')).trim() !== '';
162
114
  try {
163
- const created = await deps.createConnector(session.email, project, {
115
+ const created = await deps.createConnector({
164
116
  name: bodyField(body, 'name'),
165
117
  url: bodyField(body, 'url'),
166
118
  header: bodyField(body, 'header'),
167
119
  value: bodyField(body, 'value'),
120
+ clientId: bodyField(body, 'clientId'),
121
+ clientSecret: bodyField(body, 'clientSecret'),
168
122
  });
169
123
  log.info(
170
124
  { id: created.id, name: created.name, host: hostOf(created.url) },
@@ -173,7 +127,7 @@ async function handleCreate(
173
127
  sendJson(req, res, 201, connectorPayload(created));
174
128
  } catch (err) {
175
129
  if (offered || !(err instanceof ConnectorUnauthorized)) throw err;
176
- await startOAuth(req, res, deps, session, project, body, (row) =>
130
+ await startOAuth(req, res, deps, body, (row) =>
177
131
  connectorPayload(row),
178
132
  );
179
133
  }
@@ -183,10 +137,9 @@ async function handleVerify(
183
137
  req: IncomingMessage,
184
138
  res: ServerResponse,
185
139
  deps: ConnectorApiDeps,
186
- session: ApiSession,
187
140
  id: string,
188
141
  ): Promise<void> {
189
- const check = await deps.verifyConnector(session.email, id);
142
+ const check = await deps.verifyConnector(id);
190
143
  log.info(
191
144
  { id: check.id, name: check.name, ok: check.ok },
192
145
  'connector-api: re-verified connector',
@@ -198,10 +151,9 @@ async function handleDisconnect(
198
151
  req: IncomingMessage,
199
152
  res: ServerResponse,
200
153
  deps: ConnectorApiDeps,
201
- session: ApiSession,
202
154
  id: string,
203
155
  ): Promise<void> {
204
- const row = await deps.disconnectConnector(session.email, id);
156
+ const row = await deps.disconnectConnector(id);
205
157
  log.info(
206
158
  { id: row.id, name: row.name },
207
159
  'connector-api: signed the connector out',
@@ -213,10 +165,9 @@ async function handleDelete(
213
165
  req: IncomingMessage,
214
166
  res: ServerResponse,
215
167
  deps: ConnectorApiDeps,
216
- session: ApiSession,
217
168
  id: string,
218
169
  ): Promise<void> {
219
- const gone = await deps.deleteConnector(session.email, id);
170
+ const gone = await deps.deleteConnector(id);
220
171
  log.info(
221
172
  { id: gone.id, name: gone.name },
222
173
  'connector-api: deleted connector',
@@ -228,22 +179,20 @@ async function handleConnector(
228
179
  req: IncomingMessage,
229
180
  res: ServerResponse,
230
181
  deps: ConnectorApiDeps,
231
- session: ApiSession,
232
182
  id: string,
233
183
  ): Promise<void> {
234
184
  if (req.method !== 'GET') {
235
- await handleDelete(req, res, deps, session, id);
185
+ await handleDelete(req, res, deps, id);
236
186
  return;
237
187
  }
238
- const row = await deps.getConnector(session.email, id);
239
- sendJson(req, res, 200, connectorPayload(row, true));
188
+ const row = await deps.getConnector(id);
189
+ sendJson(req, res, 200, connectorPayload(row));
240
190
  }
241
191
 
242
192
  async function handleRename(
243
193
  req: IncomingMessage,
244
194
  res: ServerResponse,
245
195
  deps: ConnectorApiDeps,
246
- session: ApiSession,
247
196
  id: string,
248
197
  ): Promise<void> {
249
198
  const name = bodyField(await readJsonBody(req), 'name');
@@ -251,32 +200,48 @@ async function handleRename(
251
200
  sendJson(req, res, 400, { error: 'name is required' });
252
201
  return;
253
202
  }
254
- const row = await deps.renameConnector(session.email, id, name);
203
+ const row = await deps.renameConnector(id, name);
255
204
  log.info({ id: row.id, name: row.name }, 'connector-api: renamed connector');
256
205
  sendJson(req, res, 200, connectorPayload(row));
257
206
  }
258
207
 
208
+ async function handlePolicy(
209
+ req: IncomingMessage,
210
+ res: ServerResponse,
211
+ deps: ConnectorApiDeps,
212
+ id: string,
213
+ ): Promise<void> {
214
+ const policy = normalizePolicy(bodyField(await readJsonBody(req), 'policy'));
215
+ const row = await deps.setConnectorPolicy(id, policy);
216
+ log.info({ id: row.id, name: row.name, policy: row.policy }, 'connector-api: tool policy set');
217
+ sendJson(req, res, 200, connectorPayload(row));
218
+ }
219
+
220
+ type ById = Exclude<Routable['kind'], 'collection' | 'callback'>;
221
+
222
+ const BY_ID: Record<ById, (req: IncomingMessage, res: ServerResponse, deps: ConnectorApiDeps, id: string) => Promise<void>> = {
223
+ verify: handleVerify,
224
+ tools: async (req, res, deps, id) => {
225
+ sendJson(req, res, 200, { tools: await deps.connectorTools(id) });
226
+ },
227
+ connect: handleConnect,
228
+ disconnect: handleDisconnect,
229
+ rename: handleRename,
230
+ policy: handlePolicy,
231
+ connector: handleConnector,
232
+ };
233
+
259
234
  async function route(
260
235
  req: IncomingMessage,
261
236
  res: ServerResponse,
262
237
  deps: ConnectorApiDeps,
263
- session: ApiSession,
264
238
  tgt: Routable,
265
239
  ): Promise<void> {
266
240
  try {
267
241
  if (tgt.kind === 'callback') return;
268
- if (tgt.kind === 'verify')
269
- await handleVerify(req, res, deps, session, tgt.id);
270
- else if (tgt.kind === 'connect')
271
- await handleConnect(req, res, deps, session, tgt.id);
272
- else if (tgt.kind === 'disconnect')
273
- await handleDisconnect(req, res, deps, session, tgt.id);
274
- else if (tgt.kind === 'rename')
275
- await handleRename(req, res, deps, session, tgt.id);
276
- else if (tgt.kind === 'connector')
277
- await handleConnector(req, res, deps, session, tgt.id);
278
- else if (req.method === 'GET') await handleList(req, res, deps, session);
279
- else await handleCreate(req, res, deps, session);
242
+ if (tgt.kind !== 'collection') await BY_ID[tgt.kind](req, res, deps, tgt.id);
243
+ else if (req.method === 'GET') await handleList(req, res, deps);
244
+ else await handleCreate(req, res, deps);
280
245
  } catch (err) {
281
246
  apiFailure(req, res, err, 'connector-api');
282
247
  }
@@ -287,12 +252,14 @@ const ALLOWED: Record<Routable['kind'], string[]> = {
287
252
  callback: ['GET'],
288
253
  connector: ['GET', 'DELETE'],
289
254
  verify: ['POST'],
255
+ tools: ['GET'],
290
256
  connect: ['POST'],
291
257
  disconnect: ['POST'],
292
258
  rename: ['POST'],
259
+ policy: ['PUT'],
293
260
  };
294
261
 
295
- function dispatch(
262
+ async function dispatch(
296
263
  req: IncomingMessage,
297
264
  res: ServerResponse,
298
265
  deps: ConnectorApiDeps,
@@ -300,14 +267,14 @@ function dispatch(
300
267
  ): Promise<void> {
301
268
  if (tgt.kind === 'callback') {
302
269
  handleCallback(req, res, deps);
303
- return Promise.resolve();
270
+ return;
304
271
  }
305
- const session = apiSession(req);
272
+ const session = await apiSession(req);
306
273
  if (!session) {
307
274
  sendJson(req, res, 401, { error: 'unauthorized' });
308
- return Promise.resolve();
275
+ return;
309
276
  }
310
- return route(req, res, deps, session, tgt);
277
+ await route(req, res, deps, tgt);
311
278
  }
312
279
 
313
280
  export function handleConnectorApiRequest(
@@ -330,9 +297,8 @@ export function handleConnectorApiRequest(
330
297
  return true;
331
298
  }
332
299
  dispatch(req, res, deps, tgt).catch((err: unknown) => {
333
- log.warn({ err: errMsg(err) }, 'connector-api: unhandled error');
334
- if (!res.headersSent)
335
- sendJson(req, res, 500, { error: 'connector api failed' });
300
+ if (res.headersSent) return;
301
+ apiFailure(req, res, err, 'connector-api');
336
302
  });
337
303
  return true;
338
304
  }
@@ -1,14 +1,20 @@
1
- import { ApiError } from '../daemon/api-error.js';
1
+ import { ApiError } from '@metro-labs/http/api-error';
2
+ import { stringOf } from '@metro-labs/http/api-http';
2
3
  import type {
3
4
  ConnectorAuth,
4
5
  VerifiedRecord,
5
6
  VerifiedServer,
6
- } from '../daemon/connector-verify.js';
7
- import { readStoredTools } from '../daemon/connector-tools.js';
7
+ } from './verify.js';
8
+ import type { OAuthClient } from './oauth-client.js';
9
+ import { isRecord } from '@metro-labs/core/is-record';
10
+ import type { ToolGroup } from '@metro-labs/core/stations/types';
11
+ import { parsePolicy, type ToolPolicy } from '../policy/policy.js';
8
12
 
9
13
  const CONNECTOR_NAME_MAX = 64;
10
14
  const HEADER_NAME_RE = /^[A-Za-z0-9!#$%&'*+.^_`|~-]{1,64}$/;
11
15
  const HEADER_VALUE_RE = /^[\x20-\x7e]{1,4096}$/;
16
+ const CLIENT_ID_RE = /^[\x21-\x7e]{1,256}$/;
17
+ const CLIENT_SECRET_RE = /^[\x21-\x7e]{1,1024}$/;
12
18
  const DEFAULT_HEADER = 'Authorization';
13
19
 
14
20
  export class ConnectorError extends ApiError {}
@@ -20,14 +26,9 @@ export interface ConnectorConfig {
20
26
  createdAt: string;
21
27
  verified: VerifiedRecord;
22
28
  oauth: boolean;
23
- }
24
-
25
- function isRecord(value: unknown): value is Record<string, unknown> {
26
- return typeof value === 'object' && value !== null && !Array.isArray(value);
27
- }
28
-
29
- function text(value: unknown): string {
30
- return typeof value === 'string' ? value : '';
29
+ client: OAuthClient | null;
30
+ policy?: ToolPolicy;
31
+ toolGroups?: Record<string, ToolGroup>;
31
32
  }
32
33
 
33
34
  function hasControlChar(value: string): boolean {
@@ -58,8 +59,8 @@ export function connectorAuth(
58
59
  rawHeader: unknown,
59
60
  rawValue: unknown,
60
61
  ): ConnectorAuth {
61
- const header = text(rawHeader).trim();
62
- const value = text(rawValue).trim();
62
+ const header = stringOf(rawHeader).trim();
63
+ const value = stringOf(rawValue).trim();
63
64
  if (header === '' && value === '') return { kind: 'none' };
64
65
  if (value === '')
65
66
  throw new ConnectorError(
@@ -74,22 +75,48 @@ export function connectorAuth(
74
75
  return { kind: 'header', name, value };
75
76
  }
76
77
 
78
+ export function connectorClient(
79
+ rawId: unknown,
80
+ rawSecret: unknown,
81
+ ): OAuthClient | null {
82
+ const clientId = stringOf(rawId).trim();
83
+ const clientSecret = stringOf(rawSecret).trim();
84
+ if (clientId === '' && clientSecret === '') return null;
85
+ if (clientId === '')
86
+ throw new ConnectorError('a client secret needs the client ID it belongs to', 400);
87
+ if (!CLIENT_ID_RE.test(clientId))
88
+ throw new ConnectorError('that is not a client ID Metro can send', 400);
89
+ if (clientSecret !== '' && !CLIENT_SECRET_RE.test(clientSecret))
90
+ throw new ConnectorError('that client secret is not sendable', 400);
91
+ return { clientId, ...(clientSecret === '' ? {} : { clientSecret }) };
92
+ }
93
+
94
+ function readClient(raw: unknown): OAuthClient | null {
95
+ if (!isRecord(raw)) return null;
96
+ const clientId = stringOf(raw.clientId);
97
+ if (clientId === '') return null;
98
+ const clientSecret = stringOf(raw.clientSecret);
99
+ return { clientId, ...(clientSecret === '' ? {} : { clientSecret }) };
100
+ }
101
+
77
102
  function readOAuth(raw: Record<string, unknown>): ConnectorAuth {
78
- const accessToken = text(raw.accessToken);
79
- const clientId = text(raw.clientId);
80
- const tokenEndpoint = text(raw.tokenEndpoint);
103
+ const accessToken = stringOf(raw.accessToken);
104
+ const clientId = stringOf(raw.clientId);
105
+ const tokenEndpoint = stringOf(raw.tokenEndpoint);
81
106
  if (accessToken === '' || clientId === '' || tokenEndpoint === '')
82
107
  return { kind: 'none' };
83
- const refreshToken = text(raw.refreshToken);
84
- const clientSecret = text(raw.clientSecret);
108
+ const refreshToken = stringOf(raw.refreshToken);
109
+ const clientSecret = stringOf(raw.clientSecret);
110
+ const scope = stringOf(raw.scope);
85
111
  return {
86
112
  kind: 'oauth',
87
113
  accessToken,
88
114
  clientId,
89
115
  tokenEndpoint,
90
- issuer: text(raw.issuer),
116
+ issuer: stringOf(raw.issuer),
91
117
  ...(refreshToken === '' ? {} : { refreshToken }),
92
118
  ...(clientSecret === '' ? {} : { clientSecret }),
119
+ ...(scope === '' ? {} : { scope }),
93
120
  ...(typeof raw.expiresAt === 'number' ? { expiresAt: raw.expiresAt } : {}),
94
121
  };
95
122
  }
@@ -98,34 +125,41 @@ function readAuth(raw: unknown): ConnectorAuth {
98
125
  if (!isRecord(raw)) return { kind: 'none' };
99
126
  if (raw.kind === 'oauth') return readOAuth(raw);
100
127
  if (raw.kind !== 'header') return { kind: 'none' };
101
- const name = text(raw.name);
102
- const value = text(raw.value);
128
+ const name = stringOf(raw.name);
129
+ const value = stringOf(raw.value);
103
130
  if (name === '' || value === '') return { kind: 'none' };
104
131
  return { kind: 'header', name, value };
105
132
  }
106
133
 
107
134
  function readVerified(raw: unknown): VerifiedRecord {
108
135
  const record = isRecord(raw) ? raw : {};
109
- const catalog = readStoredTools(record.catalog);
110
- return {
111
- at: text(record.at),
112
- server: text(record.server),
113
- version: text(record.version),
114
- protocol: text(record.protocol),
115
- icon: text(record.icon),
116
- tools: typeof record.tools === 'number' ? record.tools : 0,
117
- catalog,
118
- };
136
+ return { at: stringOf(record.at), server: stringOf(record.server) };
137
+ }
138
+
139
+ const TOOL_NAME_MAX = 128;
140
+ const TOOL_GROUPS_MAX = 1000;
141
+
142
+ function readToolGroups(raw: unknown): Record<string, ToolGroup> | undefined {
143
+ if (!isRecord(raw)) return undefined;
144
+ const kept = Object.entries(raw)
145
+ .filter((entry): entry is [string, ToolGroup] => entry[0].length <= TOOL_NAME_MAX && (entry[1] === 'read' || entry[1] === 'write'))
146
+ .slice(0, TOOL_GROUPS_MAX);
147
+ return kept.length > 0 ? Object.fromEntries(kept) : undefined;
119
148
  }
120
149
 
121
150
  export function readConfig(raw: unknown): ConnectorConfig {
122
151
  const record = isRecord(raw) ? raw : {};
123
152
  const auth = readAuth(record.auth);
153
+ const policy = parsePolicy(record.policy, 'connectors.json');
154
+ const toolGroups = readToolGroups(record.toolGroups);
124
155
  return {
125
156
  auth,
126
- createdAt: text(record.createdAt),
157
+ createdAt: stringOf(record.createdAt),
127
158
  verified: readVerified(record.verified),
128
159
  oauth: record.oauth === true || auth.kind === 'oauth',
160
+ client: readClient(record.client),
161
+ ...(policy === undefined || Object.keys(policy).length === 0 ? {} : { policy }),
162
+ ...(toolGroups === undefined ? {} : { toolGroups }),
129
163
  };
130
164
  }
131
165
 
@@ -135,13 +169,5 @@ export function signInState(config: ConnectorConfig): ConnectorSignIn {
135
169
  }
136
170
 
137
171
  export function stamp(server: VerifiedServer): VerifiedRecord {
138
- return {
139
- at: new Date().toISOString(),
140
- server: server.server,
141
- version: server.version,
142
- protocol: server.protocol,
143
- icon: server.icon,
144
- tools: server.tools,
145
- catalog: server.catalog,
146
- };
172
+ return { at: new Date().toISOString(), server: server.server };
147
173
  }
@@ -0,0 +1,72 @@
1
+ import type { ToolGroup } from '@metro-labs/core/stations/types';
2
+ import { policyFor, setPolicies, type PolicyTarget, type ToolPolicy } from '../policy/policy.js';
3
+ import { serverKeysOf } from './plugin-sync.js';
4
+ import { NEEDS_APPROVAL, settlePrompts, takeGrant } from '../approvals/pending.js';
5
+
6
+ interface GateRow {
7
+ id: string;
8
+ name: string;
9
+ config: { policy?: ToolPolicy; toolGroups?: Record<string, ToolGroup> };
10
+ }
11
+
12
+ export interface ConnectorGate {
13
+ id: string;
14
+ name: string;
15
+ server: string;
16
+ policy: ToolPolicy;
17
+ tools: Record<string, ToolGroup>;
18
+ }
19
+
20
+ let gates: ConnectorGate[] = [];
21
+
22
+ const normalized = (name: string): string => name.replace(/[^a-zA-Z0-9_-]/g, '_');
23
+
24
+ export function registerConnectors(rows: readonly GateRow[]): void {
25
+ const keys = serverKeysOf([...rows]);
26
+ gates = rows.map((row) => ({
27
+ id: row.id,
28
+ name: row.name,
29
+ server: keys.get(row.id) ?? '',
30
+ policy: row.config.policy ?? {},
31
+ tools: row.config.toolGroups ?? {},
32
+ }));
33
+ const entries = rows.flatMap((row): [PolicyTarget, ToolPolicy][] =>
34
+ row.config.policy === undefined ? [] : [[{ kind: 'connector', id: row.id }, row.config.policy]],
35
+ );
36
+ setPolicies('connector', entries);
37
+ }
38
+
39
+ export const connectorGates = (): readonly ConnectorGate[] => gates;
40
+
41
+ export const toolGroupOf = (gate: ConnectorGate, tool: string): ToolGroup => (gate.tools[tool] === 'read' ? 'read' : 'write');
42
+
43
+ const promptFor = (connectorId: string, tool: string) => (asked: string): boolean => {
44
+ const found = connectorToolOf(asked);
45
+ return found?.gate.id === connectorId && found.tool === tool;
46
+ };
47
+
48
+ export function blockedReason(connectorId: string, tool: string, args: Record<string, unknown> = {}): string | null {
49
+ const gate = gates.find((g) => g.id === connectorId);
50
+ if (gate === undefined) return null;
51
+ settlePrompts(promptFor(connectorId, tool), args);
52
+ const access = policyFor({ kind: 'connector', id: connectorId }, { name: tool, group: toolGroupOf(gate, tool) });
53
+ if (access === 'deny') return `Blocked by the owner's policy for ${gate.name} (${tool}).`;
54
+ if (access === 'allow' || takeGrant(promptFor(connectorId, tool), args)) return null;
55
+ return NEEDS_APPROVAL(gate.name, tool);
56
+ }
57
+
58
+ function prefixesOf(gate: ConnectorGate): string[] {
59
+ return [`mcp__plugin_metro_${gate.server}__`, `mcp__${gate.server}__`, `mcp__${normalized(`metro.box ${gate.name}`)}__`];
60
+ }
61
+
62
+ export function connectorToolOf(toolName: string): { gate: ConnectorGate; tool: string } | undefined {
63
+ if (toolName.startsWith('mcp__metro__')) return undefined;
64
+ for (const gate of gates)
65
+ for (const prefix of prefixesOf(gate))
66
+ if (toolName.startsWith(prefix) && toolName.length > prefix.length) {
67
+ const called = toolName.slice(prefix.length);
68
+ const known = [...Object.keys(gate.tools), ...Object.keys(gate.policy.tools ?? {})];
69
+ return { gate, tool: known.find((name) => name === called) ?? known.find((name) => normalized(name) === called) ?? called };
70
+ }
71
+ return undefined;
72
+ }
@@ -0,0 +1,18 @@
1
+ export interface ConnectorHealth {
2
+ ok: boolean;
3
+ reason: string | null;
4
+ at: string;
5
+ }
6
+
7
+ const seen = new Map<string, ConnectorHealth>();
8
+
9
+ export function noteHealth(id: string, ok: boolean, reason: string | null = null): void {
10
+ seen.set(id, { ok, reason: ok ? null : reason, at: new Date().toISOString() });
11
+ }
12
+
13
+ export const healthOf = (id: string): ConnectorHealth | null => seen.get(id) ?? null;
14
+
15
+ export function forgetHealth(id?: string): void {
16
+ if (id === undefined) seen.clear();
17
+ else seen.delete(id);
18
+ }