@stage-labs/metro 0.1.0-beta.7 โ†’ 0.1.0-beta.71

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 (279) hide show
  1. package/dist/api.js +14 -0
  2. package/dist/bedrock-eventstream.js +120 -0
  3. package/dist/bedrock-proxy.js +260 -0
  4. package/dist/bedrock-upstream.js +72 -0
  5. package/dist/bedrock.js +37 -0
  6. package/dist/claude-settings.js +40 -0
  7. package/dist/claude.js +107 -0
  8. package/dist/cli.js +101 -0
  9. package/dist/control.js +74 -0
  10. package/dist/hold.js +211 -0
  11. package/dist/local.js +93 -0
  12. package/dist/node-name.js +51 -0
  13. package/dist/plugin.js +80 -0
  14. package/dist/provider-flags.js +9 -0
  15. package/dist/runtime-install.js +84 -0
  16. package/dist/runtime.js +70 -0
  17. package/dist/serve.js +147 -0
  18. package/dist/service.js +224 -0
  19. package/dist/tail.js +119 -0
  20. package/dist/update.js +45 -0
  21. package/dist/version.js +97 -0
  22. package/package.json +14 -25
  23. package/runtime/node_modules/@metro-labs/discord-bot/package.json +28 -0
  24. package/runtime/node_modules/@metro-labs/discord-bot/src/accounts.ts +118 -0
  25. package/runtime/node_modules/@metro-labs/discord-bot/src/actions.ts +388 -0
  26. package/runtime/node_modules/@metro-labs/discord-bot/src/api-base.ts +1 -0
  27. package/runtime/node_modules/@metro-labs/discord-bot/src/attachments.ts +29 -0
  28. package/runtime/node_modules/@metro-labs/discord-bot/src/format.ts +220 -0
  29. package/runtime/node_modules/@metro-labs/discord-bot/src/group-actions.ts +50 -0
  30. package/runtime/node_modules/@metro-labs/discord-bot/src/group.ts +115 -0
  31. package/runtime/node_modules/@metro-labs/discord-bot/src/index.ts +127 -0
  32. package/runtime/node_modules/@metro-labs/discord-bot/src/members.ts +215 -0
  33. package/runtime/node_modules/@metro-labs/discord-bot/src/send-files.ts +43 -0
  34. package/runtime/node_modules/@metro-labs/discord-bot/src/station.ts +19 -0
  35. package/runtime/node_modules/@metro-labs/discord-bot/src/verify.ts +82 -0
  36. package/runtime/node_modules/@metro-labs/discord-bot/src/voice-speak.ts +195 -0
  37. package/runtime/node_modules/@metro-labs/discord-bot/src/voice-transcribe.ts +292 -0
  38. package/runtime/node_modules/@metro-labs/discord-bot/src/voice.ts +197 -0
  39. package/runtime/node_modules/@metro-labs/discord-bot/src/wire.ts +5 -0
  40. package/runtime/node_modules/@metro-labs/mcp/package.json +64 -0
  41. package/runtime/node_modules/@metro-labs/mcp/src/channels/addressed.ts +25 -0
  42. package/runtime/node_modules/@metro-labs/mcp/src/channels/dedupe.ts +24 -0
  43. package/runtime/node_modules/@metro-labs/mcp/src/channels/inbound.ts +377 -0
  44. package/runtime/node_modules/@metro-labs/mcp/src/channels/media-note.ts +85 -0
  45. package/runtime/node_modules/@metro-labs/mcp/src/channels/pending.ts +75 -0
  46. package/runtime/node_modules/@metro-labs/mcp/src/channels/relay.ts +129 -0
  47. package/runtime/node_modules/@metro-labs/mcp/src/channels/webhook-note.ts +51 -0
  48. package/runtime/node_modules/@metro-labs/mcp/src/daemon/account-api.ts +311 -0
  49. package/runtime/node_modules/@metro-labs/mcp/src/daemon/agent-api.ts +302 -0
  50. package/runtime/node_modules/@metro-labs/mcp/src/daemon/api-error.ts +8 -0
  51. package/runtime/node_modules/@metro-labs/mcp/src/daemon/api-http.ts +95 -0
  52. package/runtime/node_modules/@metro-labs/mcp/src/daemon/attach-grant.ts +99 -0
  53. package/runtime/node_modules/@metro-labs/mcp/src/daemon/attach-owner.ts +32 -0
  54. package/runtime/node_modules/@metro-labs/mcp/src/daemon/attach-serve.ts +128 -0
  55. package/runtime/node_modules/@metro-labs/mcp/src/daemon/attach-session.ts +280 -0
  56. package/runtime/node_modules/@metro-labs/mcp/src/daemon/boot.ts +204 -0
  57. package/runtime/node_modules/@metro-labs/mcp/src/daemon/bundle-api.ts +111 -0
  58. package/runtime/node_modules/@metro-labs/mcp/src/daemon/claude-api.ts +97 -0
  59. package/runtime/node_modules/@metro-labs/mcp/src/daemon/claude-files.ts +329 -0
  60. package/runtime/node_modules/@metro-labs/mcp/src/daemon/connect-hint.ts +39 -0
  61. package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-api.ts +307 -0
  62. package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-json.ts +21 -0
  63. package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-oauth-routes.ts +157 -0
  64. package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-oauth.ts +127 -0
  65. package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-tools.ts +98 -0
  66. package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-url.ts +70 -0
  67. package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-verify.ts +330 -0
  68. package/runtime/node_modules/@metro-labs/mcp/src/daemon/control-api.ts +64 -0
  69. package/runtime/node_modules/@metro-labs/mcp/src/daemon/cors.ts +29 -0
  70. package/runtime/node_modules/@metro-labs/mcp/src/daemon/crash-guard.ts +49 -0
  71. package/runtime/node_modules/@metro-labs/mcp/src/daemon/events.ts +120 -0
  72. package/runtime/node_modules/@metro-labs/mcp/src/daemon/http.ts +390 -0
  73. package/runtime/node_modules/@metro-labs/mcp/src/daemon/identity-key.ts +33 -0
  74. package/runtime/node_modules/@metro-labs/mcp/src/daemon/identity-registry.ts +13 -0
  75. package/runtime/node_modules/@metro-labs/mcp/src/daemon/identity-routes.ts +54 -0
  76. package/runtime/node_modules/@metro-labs/mcp/src/daemon/identity.ts +7 -0
  77. package/runtime/node_modules/@metro-labs/mcp/src/daemon/is-record.ts +2 -0
  78. package/runtime/node_modules/@metro-labs/mcp/src/daemon/local-cli-api.ts +63 -0
  79. package/runtime/node_modules/@metro-labs/mcp/src/daemon/local-mode.ts +187 -0
  80. package/runtime/node_modules/@metro-labs/mcp/src/daemon/local-owner.ts +14 -0
  81. package/runtime/node_modules/@metro-labs/mcp/src/daemon/log.ts +42 -0
  82. package/runtime/node_modules/@metro-labs/mcp/src/daemon/machine-api.ts +61 -0
  83. package/runtime/node_modules/@metro-labs/mcp/src/daemon/mode-api.ts +32 -0
  84. package/runtime/node_modules/@metro-labs/mcp/src/daemon/model-api.ts +169 -0
  85. package/runtime/node_modules/@metro-labs/mcp/src/daemon/oauth-client.ts +159 -0
  86. package/runtime/node_modules/@metro-labs/mcp/src/daemon/oauth-discovery.ts +117 -0
  87. package/runtime/node_modules/@metro-labs/mcp/src/daemon/oauth-pending.ts +65 -0
  88. package/runtime/node_modules/@metro-labs/mcp/src/daemon/paths.ts +109 -0
  89. package/runtime/node_modules/@metro-labs/mcp/src/daemon/protocol.ts +226 -0
  90. package/runtime/node_modules/@metro-labs/mcp/src/daemon/relay.ts +295 -0
  91. package/runtime/node_modules/@metro-labs/mcp/src/daemon/return-to.ts +21 -0
  92. package/runtime/node_modules/@metro-labs/mcp/src/daemon/runtime-deps.ts +82 -0
  93. package/runtime/node_modules/@metro-labs/mcp/src/daemon/secure-fs.ts +57 -0
  94. package/runtime/node_modules/@metro-labs/mcp/src/daemon/server-types.ts +21 -0
  95. package/runtime/node_modules/@metro-labs/mcp/src/daemon/servers-api.ts +80 -0
  96. package/runtime/node_modules/@metro-labs/mcp/src/daemon/session-api.ts +29 -0
  97. package/runtime/node_modules/@metro-labs/mcp/src/daemon/session-apis.ts +66 -0
  98. package/runtime/node_modules/@metro-labs/mcp/src/daemon/signed-identity.ts +36 -0
  99. package/runtime/node_modules/@metro-labs/mcp/src/daemon/supervisor-io.ts +97 -0
  100. package/runtime/node_modules/@metro-labs/mcp/src/daemon/supervisor.ts +320 -0
  101. package/runtime/node_modules/@metro-labs/mcp/src/daemon/terminal-api.ts +71 -0
  102. package/runtime/node_modules/@metro-labs/mcp/src/daemon/terminal-tickets.ts +40 -0
  103. package/runtime/node_modules/@metro-labs/mcp/src/daemon/terminal-ws.ts +114 -0
  104. package/runtime/node_modules/@metro-labs/mcp/src/daemon/train-call.ts +22 -0
  105. package/runtime/node_modules/@metro-labs/mcp/src/daemon/train-error.ts +53 -0
  106. package/runtime/node_modules/@metro-labs/mcp/src/daemon/tunnel.ts +352 -0
  107. package/runtime/node_modules/@metro-labs/mcp/src/daemon/update-api.ts +116 -0
  108. package/runtime/node_modules/@metro-labs/mcp/src/daemon/upload-api.ts +294 -0
  109. package/runtime/node_modules/@metro-labs/mcp/src/daemon/upload-store.ts +181 -0
  110. package/runtime/node_modules/@metro-labs/mcp/src/daemon/vault-api.ts +78 -0
  111. package/runtime/node_modules/@metro-labs/mcp/src/daemon/vault-types.ts +12 -0
  112. package/runtime/node_modules/@metro-labs/mcp/src/daemon/version.ts +2 -0
  113. package/runtime/node_modules/@metro-labs/mcp/src/db/account-attach.ts +19 -0
  114. package/runtime/node_modules/@metro-labs/mcp/src/db/address.ts +6 -0
  115. package/runtime/node_modules/@metro-labs/mcp/src/db/agent-admin.ts +43 -0
  116. package/runtime/node_modules/@metro-labs/mcp/src/db/agent-map.ts +84 -0
  117. package/runtime/node_modules/@metro-labs/mcp/src/db/agent-scope.ts +64 -0
  118. package/runtime/node_modules/@metro-labs/mcp/src/db/client.ts +32 -0
  119. package/runtime/node_modules/@metro-labs/mcp/src/db/connector-config.ts +144 -0
  120. package/runtime/node_modules/@metro-labs/mcp/src/db/connector-relay.ts +39 -0
  121. package/runtime/node_modules/@metro-labs/mcp/src/db/connectors.ts +69 -0
  122. package/runtime/node_modules/@metro-labs/mcp/src/db/file-admin.ts +329 -0
  123. package/runtime/node_modules/@metro-labs/mcp/src/db/file-source.ts +155 -0
  124. package/runtime/node_modules/@metro-labs/mcp/src/db/ids.ts +21 -0
  125. package/runtime/node_modules/@metro-labs/mcp/src/db/key-map.ts +45 -0
  126. package/runtime/node_modules/@metro-labs/mcp/src/db/local-connectors.ts +277 -0
  127. package/runtime/node_modules/@metro-labs/mcp/src/db/materialize.ts +253 -0
  128. package/runtime/node_modules/@metro-labs/mcp/src/db/schema.ts +33 -0
  129. package/runtime/node_modules/@metro-labs/mcp/src/db/servers.ts +83 -0
  130. package/runtime/node_modules/@metro-labs/mcp/src/db/stations.ts +12 -0
  131. package/runtime/node_modules/@metro-labs/mcp/src/db/vault.ts +109 -0
  132. package/runtime/node_modules/@metro-labs/mcp/src/gateway/bedrock.ts +252 -0
  133. package/runtime/node_modules/@metro-labs/mcp/src/gateway/codex-auth.ts +231 -0
  134. package/runtime/node_modules/@metro-labs/mcp/src/gateway/codex-device.ts +91 -0
  135. package/runtime/node_modules/@metro-labs/mcp/src/gateway/codex-stream.ts +288 -0
  136. package/runtime/node_modules/@metro-labs/mcp/src/gateway/codex-translate.ts +203 -0
  137. package/runtime/node_modules/@metro-labs/mcp/src/gateway/codex.ts +211 -0
  138. package/runtime/node_modules/@metro-labs/mcp/src/gateway/eventstream.ts +123 -0
  139. package/runtime/node_modules/@metro-labs/mcp/src/gateway/forward.ts +169 -0
  140. package/runtime/node_modules/@metro-labs/mcp/src/gateway/gateway.ts +193 -0
  141. package/runtime/node_modules/@metro-labs/mcp/src/gateway/model-config.ts +180 -0
  142. package/runtime/node_modules/@metro-labs/mcp/src/mcp/accounts.ts +141 -0
  143. package/runtime/node_modules/@metro-labs/mcp/src/mcp/call-tools.ts +216 -0
  144. package/runtime/node_modules/@metro-labs/mcp/src/mcp/channel-owner.ts +29 -0
  145. package/runtime/node_modules/@metro-labs/mcp/src/mcp/ctx.ts +62 -0
  146. package/runtime/node_modules/@metro-labs/mcp/src/mcp/event-store.ts +91 -0
  147. package/runtime/node_modules/@metro-labs/mcp/src/mcp/frame-scope.ts +21 -0
  148. package/runtime/node_modules/@metro-labs/mcp/src/mcp/group-tools.ts +129 -0
  149. package/runtime/node_modules/@metro-labs/mcp/src/mcp/index.ts +191 -0
  150. package/runtime/node_modules/@metro-labs/mcp/src/mcp/member-tools.ts +72 -0
  151. package/runtime/node_modules/@metro-labs/mcp/src/mcp/permission-relay.ts +66 -0
  152. package/runtime/node_modules/@metro-labs/mcp/src/mcp/raw-get-stream.ts +207 -0
  153. package/runtime/node_modules/@metro-labs/mcp/src/mcp/request-identity.ts +47 -0
  154. package/runtime/node_modules/@metro-labs/mcp/src/mcp/session-registry.ts +172 -0
  155. package/runtime/node_modules/@metro-labs/mcp/src/mcp/session-route.ts +43 -0
  156. package/runtime/node_modules/@metro-labs/mcp/src/mcp/session.ts +215 -0
  157. package/runtime/node_modules/@metro-labs/mcp/src/mcp/str.ts +5 -0
  158. package/runtime/node_modules/@metro-labs/mcp/src/mcp/tool-dispatch.ts +215 -0
  159. package/runtime/node_modules/@metro-labs/mcp/src/mcp/tool-schemas.ts +400 -0
  160. package/runtime/node_modules/@metro-labs/mcp/src/mcp/upload-tool.ts +66 -0
  161. package/runtime/node_modules/@metro-labs/mcp/src/monitor/api.ts +237 -0
  162. package/runtime/node_modules/@metro-labs/mcp/src/server.ts +2 -0
  163. package/runtime/node_modules/@metro-labs/mcp/src/stations/account-store.ts +60 -0
  164. package/runtime/node_modules/@metro-labs/mcp/src/stations/attach-inline.ts +100 -0
  165. package/runtime/node_modules/@metro-labs/mcp/src/stations/attach-interactive.ts +161 -0
  166. package/runtime/node_modules/@metro-labs/mcp/src/stations/attach-resolve.ts +200 -0
  167. package/runtime/node_modules/@metro-labs/mcp/src/stations/attach-xmtp.ts +111 -0
  168. package/runtime/node_modules/@metro-labs/mcp/src/stations/attach.ts +184 -0
  169. package/runtime/node_modules/@metro-labs/mcp/src/stations/attachments.ts +196 -0
  170. package/runtime/node_modules/@metro-labs/mcp/src/stations/lines.ts +82 -0
  171. package/runtime/node_modules/@metro-labs/mcp/src/stations/messaging-normalize.ts +88 -0
  172. package/runtime/node_modules/@metro-labs/mcp/src/stations/registry.ts +35 -0
  173. package/runtime/node_modules/@metro-labs/mcp/src/stations/station-runtime.ts +64 -0
  174. package/runtime/node_modules/@metro-labs/mcp/src/stations/types.ts +107 -0
  175. package/runtime/node_modules/@metro-labs/telegram/package.json +26 -0
  176. package/runtime/node_modules/@metro-labs/telegram/src/accounts.ts +80 -0
  177. package/runtime/node_modules/@metro-labs/telegram/src/actions.ts +254 -0
  178. package/runtime/node_modules/@metro-labs/telegram/src/attachments.ts +87 -0
  179. package/runtime/node_modules/@metro-labs/telegram/src/client.ts +77 -0
  180. package/runtime/node_modules/@metro-labs/telegram/src/format.ts +156 -0
  181. package/runtime/node_modules/@metro-labs/telegram/src/group.ts +261 -0
  182. package/runtime/node_modules/@metro-labs/telegram/src/history.ts +52 -0
  183. package/runtime/node_modules/@metro-labs/telegram/src/inbound.ts +78 -0
  184. package/runtime/node_modules/@metro-labs/telegram/src/index.ts +46 -0
  185. package/runtime/node_modules/@metro-labs/telegram/src/login.ts +166 -0
  186. package/runtime/node_modules/@metro-labs/telegram/src/media-actions.ts +80 -0
  187. package/runtime/node_modules/@metro-labs/telegram/src/members.ts +75 -0
  188. package/runtime/node_modules/@metro-labs/telegram/src/normalize.ts +22 -0
  189. package/runtime/node_modules/@metro-labs/telegram/src/reactions.ts +167 -0
  190. package/runtime/node_modules/@metro-labs/telegram/src/station.ts +24 -0
  191. package/runtime/node_modules/@metro-labs/telegram/src/types.ts +7 -0
  192. package/runtime/node_modules/@metro-labs/telegram/src/wire.ts +1 -0
  193. package/runtime/node_modules/@metro-labs/telegram-bot/package.json +25 -0
  194. package/runtime/node_modules/@metro-labs/telegram-bot/src/accounts.ts +120 -0
  195. package/runtime/node_modules/@metro-labs/telegram-bot/src/actions.ts +295 -0
  196. package/runtime/node_modules/@metro-labs/telegram-bot/src/attachments.ts +128 -0
  197. package/runtime/node_modules/@metro-labs/telegram-bot/src/format.ts +201 -0
  198. package/runtime/node_modules/@metro-labs/telegram-bot/src/index.ts +109 -0
  199. package/runtime/node_modules/@metro-labs/telegram-bot/src/media-actions.ts +166 -0
  200. package/runtime/node_modules/@metro-labs/telegram-bot/src/members.ts +47 -0
  201. package/runtime/node_modules/@metro-labs/telegram-bot/src/station.ts +17 -0
  202. package/runtime/node_modules/@metro-labs/telegram-bot/src/types.ts +58 -0
  203. package/runtime/node_modules/@metro-labs/telegram-bot/src/verify.ts +38 -0
  204. package/runtime/node_modules/@metro-labs/telegram-bot/src/wire.ts +3 -0
  205. package/runtime/node_modules/@metro-labs/webhook/package.json +23 -0
  206. package/runtime/node_modules/@metro-labs/webhook/src/station.ts +37 -0
  207. package/runtime/node_modules/@metro-labs/whatsapp/package.json +27 -0
  208. package/runtime/node_modules/@metro-labs/whatsapp/src/accounts.ts +66 -0
  209. package/runtime/node_modules/@metro-labs/whatsapp/src/ack.ts +101 -0
  210. package/runtime/node_modules/@metro-labs/whatsapp/src/actions.ts +178 -0
  211. package/runtime/node_modules/@metro-labs/whatsapp/src/attachments.ts +72 -0
  212. package/runtime/node_modules/@metro-labs/whatsapp/src/auth-state.ts +129 -0
  213. package/runtime/node_modules/@metro-labs/whatsapp/src/client.ts +327 -0
  214. package/runtime/node_modules/@metro-labs/whatsapp/src/delivery.ts +49 -0
  215. package/runtime/node_modules/@metro-labs/whatsapp/src/format.ts +138 -0
  216. package/runtime/node_modules/@metro-labs/whatsapp/src/inbound.ts +57 -0
  217. package/runtime/node_modules/@metro-labs/whatsapp/src/index.ts +40 -0
  218. package/runtime/node_modules/@metro-labs/whatsapp/src/keys.ts +59 -0
  219. package/runtime/node_modules/@metro-labs/whatsapp/src/logger.ts +60 -0
  220. package/runtime/node_modules/@metro-labs/whatsapp/src/login.ts +176 -0
  221. package/runtime/node_modules/@metro-labs/whatsapp/src/media.ts +84 -0
  222. package/runtime/node_modules/@metro-labs/whatsapp/src/normalize.ts +22 -0
  223. package/runtime/node_modules/@metro-labs/whatsapp/src/outbox.ts +38 -0
  224. package/runtime/node_modules/@metro-labs/whatsapp/src/parse.ts +185 -0
  225. package/runtime/node_modules/@metro-labs/whatsapp/src/station.ts +17 -0
  226. package/runtime/node_modules/@metro-labs/whatsapp/src/token-store.ts +98 -0
  227. package/runtime/node_modules/@metro-labs/whatsapp/src/types.ts +6 -0
  228. package/runtime/node_modules/@metro-labs/whatsapp/src/wire.ts +5 -0
  229. package/runtime/node_modules/@metro-labs/xmtp/package.json +33 -0
  230. package/runtime/node_modules/@metro-labs/xmtp/src/accounts.ts +112 -0
  231. package/runtime/node_modules/@metro-labs/xmtp/src/actions-close.ts +110 -0
  232. package/runtime/node_modules/@metro-labs/xmtp/src/actions-conv.ts +299 -0
  233. package/runtime/node_modules/@metro-labs/xmtp/src/actions-meta.ts +157 -0
  234. package/runtime/node_modules/@metro-labs/xmtp/src/actions-push.ts +87 -0
  235. package/runtime/node_modules/@metro-labs/xmtp/src/actions.ts +375 -0
  236. package/runtime/node_modules/@metro-labs/xmtp/src/attachments.ts +107 -0
  237. package/runtime/node_modules/@metro-labs/xmtp/src/codecs.ts +171 -0
  238. package/runtime/node_modules/@metro-labs/xmtp/src/conv-helpers.ts +239 -0
  239. package/runtime/node_modules/@metro-labs/xmtp/src/emit-core.ts +55 -0
  240. package/runtime/node_modules/@metro-labs/xmtp/src/emit-payloads.ts +335 -0
  241. package/runtime/node_modules/@metro-labs/xmtp/src/emit.ts +80 -0
  242. package/runtime/node_modules/@metro-labs/xmtp/src/group-members.ts +34 -0
  243. package/runtime/node_modules/@metro-labs/xmtp/src/group.ts +56 -0
  244. package/runtime/node_modules/@metro-labs/xmtp/src/identity.ts +33 -0
  245. package/runtime/node_modules/@metro-labs/xmtp/src/index.ts +125 -0
  246. package/runtime/node_modules/@metro-labs/xmtp/src/labels.ts +157 -0
  247. package/runtime/node_modules/@metro-labs/xmtp/src/member-args.ts +40 -0
  248. package/runtime/node_modules/@metro-labs/xmtp/src/push.ts +349 -0
  249. package/runtime/node_modules/@metro-labs/xmtp/src/station.ts +13 -0
  250. package/runtime/node_modules/@metro-labs/xmtp/src/tools-handlers.ts +126 -0
  251. package/runtime/node_modules/@metro-labs/xmtp/src/tools.ts +212 -0
  252. package/runtime/node_modules/@metro-labs/xmtp/src/transcribe.ts +90 -0
  253. package/runtime/node_modules/@metro-labs/xmtp/src/verify.ts +84 -0
  254. package/runtime/node_modules/@metro-labs/xmtp/src/wire.ts +53 -0
  255. package/runtime/runtime.json +3 -0
  256. package/runtime/stations.json +36 -0
  257. package/runtime/trains/.keep +0 -0
  258. package/LICENSE +0 -21
  259. package/README.md +0 -193
  260. package/dist/cache.js +0 -75
  261. package/dist/cli/actions.js +0 -139
  262. package/dist/cli/config.js +0 -185
  263. package/dist/cli/index.js +0 -159
  264. package/dist/cli/skill.js +0 -62
  265. package/dist/cli/util.js +0 -72
  266. package/dist/codex-rc.js +0 -236
  267. package/dist/dispatcher.js +0 -95
  268. package/dist/history.js +0 -84
  269. package/dist/ipc.js +0 -72
  270. package/dist/log.js +0 -15
  271. package/dist/paths.js +0 -68
  272. package/dist/stations/discord.js +0 -200
  273. package/dist/stations/index.js +0 -73
  274. package/dist/stations/telegram-md.js +0 -34
  275. package/dist/stations/telegram-upload.js +0 -113
  276. package/dist/stations/telegram.js +0 -213
  277. package/docs/agents.md +0 -185
  278. package/docs/uri-scheme.md +0 -71
  279. package/skills/metro/SKILL.md +0 -241
@@ -0,0 +1,330 @@
1
+ import { errMsg, log } from './log.js';
2
+ import {
3
+ ConnectorNotMcp,
4
+ ConnectorUnauthorized,
5
+ refused,
6
+ safeIconSrc,
7
+ } from './connector-url.js';
8
+ import { toToolList, type ToolInfo } from './connector-tools.js';
9
+
10
+ export {
11
+ ConnectorUnauthorized,
12
+ ConnectorVerifyError,
13
+ connectorUrlText,
14
+ parseConnectorUrl,
15
+ } from './connector-url.js';
16
+ import { isRecord } from './is-record.js';
17
+
18
+ export interface OAuthTokens {
19
+ accessToken: string;
20
+ refreshToken?: string;
21
+ expiresAt?: number;
22
+ }
23
+
24
+ export interface OAuthAuth extends OAuthTokens {
25
+ kind: 'oauth';
26
+ issuer: string;
27
+ tokenEndpoint: string;
28
+ clientId: string;
29
+ clientSecret?: string;
30
+ }
31
+
32
+ export type ConnectorAuth =
33
+ | { kind: 'none' }
34
+ | { kind: 'header'; name: string; value: string }
35
+ | OAuthAuth;
36
+
37
+ export interface VerifiedServer {
38
+ server: string;
39
+ version: string;
40
+ protocol: string;
41
+ icon: string;
42
+ tools: number;
43
+ catalog: ToolInfo[];
44
+ }
45
+
46
+ export interface VerifiedRecord extends VerifiedServer {
47
+ at: string;
48
+ }
49
+
50
+ const PROTOCOL_VERSIONS = ['2025-11-25', '2025-06-18'] as const;
51
+ const MAX_TOOL_PAGES = 10;
52
+
53
+ function notMcp(url: URL): ConnectorNotMcp {
54
+ return new ConnectorNotMcp(
55
+ `${url.hostname} answered, but it does not speak MCP.`,
56
+ 400,
57
+ );
58
+ }
59
+ const PROBE_TIMEOUT_MS = 10_000;
60
+ const ACCEPT = 'application/json, text/event-stream';
61
+
62
+ async function discard(res: Response): Promise<void> {
63
+ await res.body?.cancel().catch((err: unknown) => {
64
+ log.debug(
65
+ { err: errMsg(err) },
66
+ 'connector-verify: could not discard a response body',
67
+ );
68
+ });
69
+ }
70
+
71
+ function authHeaders(auth: ConnectorAuth): Record<string, string> {
72
+ if (auth.kind === 'header') return { [auth.name]: auth.value };
73
+ if (auth.kind === 'oauth')
74
+ return { authorization: `Bearer ${auth.accessToken}` };
75
+ return {};
76
+ }
77
+
78
+ async function frame(
79
+ url: URL,
80
+ auth: ConnectorAuth,
81
+ extra: Record<string, string>,
82
+ body: unknown,
83
+ signal: AbortSignal,
84
+ ): Promise<Response> {
85
+ let res: Response;
86
+ try {
87
+ res = await fetch(url, {
88
+ method: 'POST',
89
+ redirect: 'manual',
90
+ signal,
91
+ headers: {
92
+ 'content-type': 'application/json',
93
+ accept: ACCEPT,
94
+ ...authHeaders(auth),
95
+ ...extra,
96
+ },
97
+ body: JSON.stringify(body),
98
+ });
99
+ } catch {
100
+ throw refused(`Metro could not reach ${url.hostname}.`);
101
+ }
102
+ if (res.status >= 300 && res.status < 400) {
103
+ await discard(res);
104
+ throw refused('that url redirects โ€” use the url it redirects to');
105
+ }
106
+ return res;
107
+ }
108
+
109
+ function sseData(body: string): string {
110
+ for (const line of body.replace(/\r\n/g, '\n').split('\n'))
111
+ if (line.startsWith('data:')) return line.slice(5).trim();
112
+ return '';
113
+ }
114
+
115
+ async function payloadOf(res: Response): Promise<string> {
116
+ const contentType = res.headers.get('content-type') ?? '';
117
+ const text = await res.text().catch(() => '');
118
+ return contentType.includes('text/event-stream') ? sseData(text) : text;
119
+ }
120
+
121
+ async function resultOrNull(
122
+ res: Response,
123
+ ): Promise<Record<string, unknown> | null> {
124
+ const payload = await payloadOf(res);
125
+ let parsed: unknown;
126
+ try {
127
+ parsed = JSON.parse(payload);
128
+ } catch {
129
+ return null;
130
+ }
131
+ if (!isRecord(parsed) || !isRecord(parsed.result)) return null;
132
+ return parsed.result;
133
+ }
134
+
135
+ function initializeBody(version: string): unknown {
136
+ return {
137
+ jsonrpc: '2.0',
138
+ id: 1,
139
+ method: 'initialize',
140
+ params: {
141
+ protocolVersion: version,
142
+ capabilities: {},
143
+ clientInfo: { name: 'metro', version: '0.1.0' },
144
+ },
145
+ };
146
+ }
147
+
148
+ function iconOf(info: Record<string, unknown>): string {
149
+ const icons = info.icons;
150
+ if (!Array.isArray(icons)) return '';
151
+ for (const entry of icons) {
152
+ if (!isRecord(entry)) continue;
153
+ const src = safeIconSrc(entry.src);
154
+ if (src !== '') return src;
155
+ }
156
+ return '';
157
+ }
158
+
159
+ function serverFrom(url: URL, result: Record<string, unknown>): VerifiedServer {
160
+ const protocol = result.protocolVersion;
161
+ if (typeof protocol !== 'string') throw notMcp(url);
162
+ const info = isRecord(result.serverInfo) ? result.serverInfo : {};
163
+ const title = typeof info.title === 'string' ? info.title : '';
164
+ return {
165
+ server:
166
+ title !== ''
167
+ ? title
168
+ : typeof info.name === 'string'
169
+ ? info.name
170
+ : url.hostname,
171
+ version: typeof info.version === 'string' ? info.version : '',
172
+ protocol,
173
+ icon: iconOf(info),
174
+ tools: 0,
175
+ catalog: [],
176
+ };
177
+ }
178
+
179
+ async function initialize(
180
+ url: URL,
181
+ auth: ConnectorAuth,
182
+ signal: AbortSignal,
183
+ version: string,
184
+ ): Promise<{ session: string | null; server: VerifiedServer }> {
185
+ const res = await frame(url, auth, {}, initializeBody(version), signal);
186
+ if (res.status === 401 || res.status === 403) {
187
+ await discard(res);
188
+ throw new ConnectorUnauthorized(
189
+ auth.kind === 'none'
190
+ ? `${url.hostname} requires authorization.`
191
+ : `${url.hostname} rejected that credential.`,
192
+ 400,
193
+ );
194
+ }
195
+ if (res.status === 404 || res.status === 405) {
196
+ await discard(res);
197
+ throw refused(
198
+ `${url.hostname} did not accept an MCP initialize over HTTP POST. ` +
199
+ 'If it is a legacy SSE server, Metro cannot verify it yet.',
200
+ );
201
+ }
202
+ if (!res.ok) {
203
+ await discard(res);
204
+ throw notMcp(url);
205
+ }
206
+ const result = await resultOrNull(res);
207
+ if (result === null) throw notMcp(url);
208
+ return {
209
+ session: res.headers.get('mcp-session-id'),
210
+ server: serverFrom(url, result),
211
+ };
212
+ }
213
+
214
+ function sessionHeaders(
215
+ session: string | null,
216
+ version: string,
217
+ ): Record<string, string> {
218
+ const headers: Record<string, string> = {
219
+ 'mcp-protocol-version': version,
220
+ };
221
+ if (session !== null && session !== '') headers['mcp-session-id'] = session;
222
+ return headers;
223
+ }
224
+
225
+ async function announce(
226
+ url: URL,
227
+ auth: ConnectorAuth,
228
+ headers: Record<string, string>,
229
+ signal: AbortSignal,
230
+ ): Promise<void> {
231
+ const res = await frame(
232
+ url,
233
+ auth,
234
+ headers,
235
+ { jsonrpc: '2.0', method: 'notifications/initialized' },
236
+ signal,
237
+ );
238
+ await discard(res);
239
+ }
240
+
241
+ async function toolPage(
242
+ url: URL,
243
+ auth: ConnectorAuth,
244
+ headers: Record<string, string>,
245
+ signal: AbortSignal,
246
+ cursor: string,
247
+ ): Promise<Record<string, unknown> | null> {
248
+ const params = cursor === '' ? {} : { cursor };
249
+ const res = await frame(
250
+ url,
251
+ auth,
252
+ headers,
253
+ { jsonrpc: '2.0', id: 2, method: 'tools/list', params },
254
+ signal,
255
+ );
256
+ if (!res.ok) {
257
+ await discard(res);
258
+ return null;
259
+ }
260
+ return resultOrNull(res);
261
+ }
262
+
263
+ async function listTools(
264
+ url: URL,
265
+ auth: ConnectorAuth,
266
+ headers: Record<string, string>,
267
+ signal: AbortSignal,
268
+ ): Promise<ToolInfo[]> {
269
+ const tools: ToolInfo[] = [];
270
+ let cursor = '';
271
+ for (let page = 0; page < MAX_TOOL_PAGES; page += 1) {
272
+ const result = await toolPage(url, auth, headers, signal, cursor);
273
+ if (result === null) break;
274
+ tools.push(...toToolList(result.tools));
275
+ const next = result.nextCursor;
276
+ if (typeof next !== 'string' || next === '' || next === cursor) break;
277
+ cursor = next;
278
+ }
279
+ return tools;
280
+ }
281
+
282
+ async function terminate(
283
+ url: URL,
284
+ auth: ConnectorAuth,
285
+ headers: Record<string, string>,
286
+ signal: AbortSignal,
287
+ ): Promise<void> {
288
+ const res = await fetch(url, {
289
+ method: 'DELETE',
290
+ redirect: 'manual',
291
+ signal,
292
+ headers: { ...authHeaders(auth), ...headers },
293
+ });
294
+ await discard(res);
295
+ }
296
+
297
+ async function probeWith(
298
+ url: URL,
299
+ auth: ConnectorAuth,
300
+ version: string,
301
+ ): Promise<VerifiedServer> {
302
+ const signal = AbortSignal.timeout(PROBE_TIMEOUT_MS);
303
+ const { session, server } = await initialize(url, auth, signal, version);
304
+ const headers = sessionHeaders(session, server.protocol);
305
+ await announce(url, auth, headers, signal);
306
+ const catalog = await listTools(url, auth, headers, signal);
307
+ await terminate(url, auth, headers, signal).catch((err: unknown) => {
308
+ log.debug(
309
+ { host: url.hostname, err: errMsg(err) },
310
+ 'connector-verify: the remote declined to end the session',
311
+ );
312
+ });
313
+ return { ...server, tools: catalog.length, catalog };
314
+ }
315
+
316
+ export async function verifyRemoteMcp(
317
+ url: URL,
318
+ auth: ConnectorAuth,
319
+ ): Promise<VerifiedServer> {
320
+ let last: unknown;
321
+ for (const version of PROTOCOL_VERSIONS) {
322
+ try {
323
+ return await probeWith(url, auth, version);
324
+ } catch (err) {
325
+ if (!(err instanceof ConnectorNotMcp)) throw err;
326
+ last = err;
327
+ }
328
+ }
329
+ throw last;
330
+ }
@@ -0,0 +1,64 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import { ApiError } from './api-error.js';
3
+ import { apiFailure, apiSession, cors, sendJson } from './api-http.js';
4
+ import { errMsg, log } from './log.js';
5
+
6
+ const STOP = '/api/stop';
7
+ const RESTART = '/api/restart';
8
+ const EXIT_DELAY_MS = 500;
9
+
10
+ export interface ControlApiDeps {
11
+ authorize: (subject: string) => void;
12
+ restart: () => void;
13
+ stop: () => void;
14
+ served?: () => boolean;
15
+ }
16
+
17
+ interface Action {
18
+ run: () => void;
19
+ body: Record<string, boolean>;
20
+ }
21
+
22
+ const servedByCli = (): boolean => (process.env.METRO_CLI_BIN?.trim() ?? '') !== '';
23
+
24
+ function actionFor(path: string, deps: ControlApiDeps): Action | null {
25
+ if (path === STOP) return { run: deps.stop, body: { stopping: true } };
26
+ if (path === RESTART) return { run: deps.restart, body: { restarting: true } };
27
+ return null;
28
+ }
29
+
30
+ export function handleControlRequest(req: IncomingMessage, res: ServerResponse, deps: ControlApiDeps): boolean {
31
+ const path = (req.url ?? '').split('?')[0] ?? '';
32
+ const action = actionFor(path, deps);
33
+ if (action === null) return false;
34
+ if (req.method === 'OPTIONS') {
35
+ res.writeHead(204, cors(req)).end();
36
+ return true;
37
+ }
38
+ if (req.method !== 'POST') {
39
+ sendJson(req, res, 405, { error: 'method not allowed' });
40
+ return true;
41
+ }
42
+ Promise.resolve()
43
+ .then(async () => {
44
+ const session = await apiSession(req);
45
+ if (!session) throw new ApiError('unauthorized', 401);
46
+ deps.authorize(session.subject);
47
+ if (!(deps.served ?? servedByCli)())
48
+ throw new ApiError(
49
+ 'this daemon was not started by metro serve, so nothing on the machine would bring it back: use the shell instead',
50
+ 400,
51
+ );
52
+ log.info({ path, subject: session.subject }, 'control-api: requested from the page');
53
+ setTimeout(action.run, EXIT_DELAY_MS).unref();
54
+ sendJson(req, res, 200, action.body);
55
+ })
56
+ .catch((err: unknown) => {
57
+ if (err instanceof ApiError) apiFailure(req, res, err, 'control-api');
58
+ else {
59
+ log.warn({ err: errMsg(err) }, 'control-api: request failed');
60
+ if (!res.headersSent) sendJson(req, res, 500, { error: 'control api failed' });
61
+ }
62
+ });
63
+ return true;
64
+ }
@@ -0,0 +1,29 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+
3
+ export function applyMcpCors(
4
+ req: IncomingMessage,
5
+ res: ServerResponse,
6
+ ): void {
7
+ const origin = req.headers.origin;
8
+ res.setHeader(
9
+ 'Access-Control-Allow-Origin',
10
+ origin !== undefined && origin !== '' ? origin : '*',
11
+ );
12
+ res.setHeader('Vary', 'Origin');
13
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
14
+ res.setHeader(
15
+ 'Access-Control-Allow-Headers',
16
+ 'Authorization, Content-Type, Accept, Mcp-Session-Id, Mcp-Protocol-Version, Last-Event-ID',
17
+ );
18
+ res.setHeader('Access-Control-Expose-Headers', 'Mcp-Session-Id');
19
+ res.setHeader('Access-Control-Max-Age', '86400');
20
+ }
21
+
22
+ export function handleMcpPreflight(
23
+ req: IncomingMessage,
24
+ res: ServerResponse,
25
+ ): boolean {
26
+ if (req.method !== 'OPTIONS') return false;
27
+ res.writeHead(204).end();
28
+ return true;
29
+ }
@@ -0,0 +1,49 @@
1
+ import { errMsg, log, logFatalSync } from './log.js';
2
+
3
+ export type CrashKind = 'unhandledRejection' | 'uncaughtException';
4
+
5
+ const seen: Record<CrashKind, number> = {
6
+ unhandledRejection: 0,
7
+ uncaughtException: 0,
8
+ };
9
+
10
+ let ready = false;
11
+ let installed = false;
12
+
13
+ export function markDaemonReady(): void {
14
+ ready = true;
15
+ }
16
+
17
+ export function crashCount(kind: CrashKind): number {
18
+ return seen[kind];
19
+ }
20
+
21
+ function fields(kind: CrashKind, err: unknown): Record<string, unknown> {
22
+ return {
23
+ crash: kind,
24
+ seen: seen[kind],
25
+ err: errMsg(err),
26
+ errType: err instanceof Error ? err.name : typeof err,
27
+ stack: err instanceof Error ? err.stack : undefined,
28
+ };
29
+ }
30
+
31
+ function reportCrash(kind: CrashKind, err: unknown): void {
32
+ seen[kind] += 1;
33
+ if (!ready) {
34
+ logFatalSync(fields(kind, err), 'daemon: failed before it was ready');
35
+ process.exit(1);
36
+ }
37
+ log.error(fields(kind, err), 'daemon: kept running through a crash');
38
+ }
39
+
40
+ export function installCrashGuard(): void {
41
+ if (installed) return;
42
+ installed = true;
43
+ process.on('unhandledRejection', (reason: unknown) => {
44
+ reportCrash('unhandledRejection', reason);
45
+ });
46
+ process.on('uncaughtException', (err: unknown) => {
47
+ reportCrash('uncaughtException', err);
48
+ });
49
+ }
@@ -0,0 +1,120 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ import { Line } from '../stations/lines.js';
3
+
4
+ export { userSelf, daemonSelf } from './identity.js';
5
+
6
+ export type StructuredEvent =
7
+ | { type: 'msg' }
8
+ | { type: 'react'; emoji?: string; targetId?: string }
9
+ | { type: 'edit'; targetId?: string }
10
+ | { type: 'delete'; targetId?: string }
11
+ | { type: 'reply'; replyTo?: string }
12
+ | { type: 'system'; source?: string; eventName?: string };
13
+
14
+ export interface MetroEvent {
15
+ id: string;
16
+ ts: string;
17
+ station: string;
18
+ line: Line;
19
+ lineName?: string;
20
+ from: Line;
21
+ fromName?: string;
22
+ fromDisplayName?: string;
23
+ to: Line;
24
+ text?: string;
25
+ messageId?: string;
26
+ replyTo?: string;
27
+ isPrivate?: boolean;
28
+ mentionsSelf?: boolean;
29
+ replyToSelf?: boolean;
30
+ payload?: unknown;
31
+ display?: string;
32
+ event?: StructuredEvent;
33
+ agent?: string;
34
+ seq?: number;
35
+ }
36
+
37
+ function isExternalWebhook(e: MetroEvent): boolean {
38
+ return e.station === 'webhook' && !Line.isLocal(e.from);
39
+ }
40
+
41
+ function webhookEventName(e: MetroEvent): string | undefined {
42
+ const headers = (e.payload as { headers?: Record<string, string> } | undefined)
43
+ ?.headers;
44
+ return headers?.['x-github-event'] ?? headers?.['x-intercom-topic'];
45
+ }
46
+
47
+ export function classifyEvent(e: MetroEvent): StructuredEvent {
48
+ if (isExternalWebhook(e)) {
49
+ return {
50
+ type: 'system',
51
+ source: 'webhook',
52
+ eventName: webhookEventName(e),
53
+ };
54
+ }
55
+ const emoji =
56
+ (e.payload as { emoji?: string } | undefined)?.emoji ??
57
+ e.text?.match(/^\[react (.+)\]$/)?.[1];
58
+ if (emoji) return { type: 'react', emoji, targetId: e.replyTo };
59
+ if (e.replyTo) return { type: 'reply', replyTo: e.replyTo };
60
+ return { type: 'msg' };
61
+ }
62
+
63
+ export function formatDisplay(e: MetroEvent): string {
64
+ const headerFor = (icon: string, parts: (string | undefined)[]): string =>
65
+ `**${icon} ${parts.filter(Boolean).join(' ยท ')}**`;
66
+ const body = e.text ?? '';
67
+ if (isExternalWebhook(e)) {
68
+ const ev = webhookEventName(e);
69
+ return `${headerFor('๐Ÿช', ['webhook', e.lineName, ev])}\n> ${body}`;
70
+ }
71
+ if (Line.isLocal(e.from)) {
72
+ return `${headerFor('๐Ÿ“ค', [e.station, 'โ†’', e.fromName ?? e.to])}\n> ${body}`;
73
+ }
74
+ return `${headerFor('๐Ÿ“ฉ', [e.station, e.fromName ?? e.from, e.lineName])}\n> ${body}`;
75
+ }
76
+
77
+ export const mintId = (): string =>
78
+ `msg_${randomBytes(6).toString('base64url')}`;
79
+
80
+ export type BusListener = (event: MetroEvent, busSeq: number) => void;
81
+
82
+ export interface BufferedEvent {
83
+ busSeq: number;
84
+ event: MetroEvent;
85
+ }
86
+
87
+ const BUS_BUFFER_MAX = 500;
88
+
89
+ const listeners = new Set<BusListener>();
90
+ const buffer: BufferedEvent[] = [];
91
+ let busSeq = 0;
92
+
93
+ export function publishEvent(event: MetroEvent): void {
94
+ busSeq += 1;
95
+ const seq = busSeq;
96
+ buffer.push({ busSeq: seq, event });
97
+ if (buffer.length > BUS_BUFFER_MAX) buffer.shift();
98
+ for (const fn of [...listeners]) {
99
+ try {
100
+ fn(event, seq);
101
+ } catch (err) {
102
+ console.error('[metro-bus] listener threw for busSeq', seq, err);
103
+ }
104
+ }
105
+ }
106
+
107
+ export function currentBusSeq(): number {
108
+ return busSeq;
109
+ }
110
+
111
+ export function bufferedSince(afterBusSeq: number): BufferedEvent[] {
112
+ return buffer.filter((b) => b.busSeq > afterBusSeq);
113
+ }
114
+
115
+ export function subscribeEvents(fn: BusListener): () => void {
116
+ listeners.add(fn);
117
+ return () => {
118
+ listeners.delete(fn);
119
+ };
120
+ }