@stage-labs/metro 0.1.0-beta.8 → 0.1.0-beta.80

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 (282) hide show
  1. package/dist/api.js +14 -0
  2. package/dist/claude-settings.js +40 -0
  3. package/dist/claude.js +107 -0
  4. package/dist/cli.js +101 -0
  5. package/dist/control.js +74 -0
  6. package/dist/hold.js +211 -0
  7. package/dist/local.js +93 -0
  8. package/dist/node-name.js +71 -0
  9. package/dist/plugin.js +80 -0
  10. package/dist/provider-flags.js +9 -0
  11. package/dist/runtime-install.js +87 -0
  12. package/dist/runtime.js +74 -0
  13. package/dist/serve.js +146 -0
  14. package/dist/service.js +242 -0
  15. package/dist/tail.js +119 -0
  16. package/dist/update.js +45 -0
  17. package/dist/version.js +97 -0
  18. package/package.json +14 -25
  19. package/runtime/node_modules/@metro-labs/core/package.json +43 -0
  20. package/runtime/node_modules/@metro-labs/core/src/address.ts +6 -0
  21. package/runtime/node_modules/@metro-labs/core/src/endpoints.ts +7 -0
  22. package/runtime/node_modules/@metro-labs/core/src/events.ts +120 -0
  23. package/runtime/node_modules/@metro-labs/core/src/identity.ts +7 -0
  24. package/runtime/node_modules/@metro-labs/core/src/ids.ts +21 -0
  25. package/runtime/node_modules/@metro-labs/core/src/is-record.ts +2 -0
  26. package/runtime/node_modules/@metro-labs/core/src/lines.ts +82 -0
  27. package/runtime/node_modules/@metro-labs/core/src/log.ts +42 -0
  28. package/runtime/node_modules/@metro-labs/core/src/protocol.ts +226 -0
  29. package/runtime/node_modules/@metro-labs/core/src/secure-fs.ts +57 -0
  30. package/runtime/node_modules/@metro-labs/core/src/station-names.ts +12 -0
  31. package/runtime/node_modules/@metro-labs/core/src/stations/account-store.ts +60 -0
  32. package/runtime/node_modules/@metro-labs/core/src/stations/attachments.ts +196 -0
  33. package/runtime/node_modules/@metro-labs/core/src/stations/messaging-normalize.ts +88 -0
  34. package/runtime/node_modules/@metro-labs/core/src/stations/station-runtime.ts +64 -0
  35. package/runtime/node_modules/@metro-labs/core/src/stations/types.ts +107 -0
  36. package/runtime/node_modules/@metro-labs/core/src/str.ts +5 -0
  37. package/runtime/node_modules/@metro-labs/core/src/train-error.ts +53 -0
  38. package/runtime/node_modules/@metro-labs/core/src/version.ts +2 -0
  39. package/runtime/node_modules/@metro-labs/daemon/package.json +47 -0
  40. package/runtime/node_modules/@metro-labs/daemon/src/agents/account-attach.ts +19 -0
  41. package/runtime/node_modules/@metro-labs/daemon/src/agents/accounts-api.ts +311 -0
  42. package/runtime/node_modules/@metro-labs/daemon/src/agents/admin.ts +43 -0
  43. package/runtime/node_modules/@metro-labs/daemon/src/agents/api.ts +302 -0
  44. package/runtime/node_modules/@metro-labs/daemon/src/agents/bundle.ts +111 -0
  45. package/runtime/node_modules/@metro-labs/daemon/src/agents/file-admin.ts +329 -0
  46. package/runtime/node_modules/@metro-labs/daemon/src/agents/files.ts +155 -0
  47. package/runtime/node_modules/@metro-labs/daemon/src/agents/keys.ts +45 -0
  48. package/runtime/node_modules/@metro-labs/daemon/src/agents/map.ts +84 -0
  49. package/runtime/node_modules/@metro-labs/daemon/src/agents/scope.ts +64 -0
  50. package/runtime/node_modules/@metro-labs/daemon/src/boot/boot.ts +176 -0
  51. package/runtime/node_modules/@metro-labs/daemon/src/boot/connect-hint.ts +39 -0
  52. package/runtime/node_modules/@metro-labs/daemon/src/boot/crash-guard.ts +49 -0
  53. package/runtime/node_modules/@metro-labs/daemon/src/boot/local-owner.ts +14 -0
  54. package/runtime/node_modules/@metro-labs/daemon/src/boot/paths.ts +106 -0
  55. package/runtime/node_modules/@metro-labs/daemon/src/channels/addressed.ts +25 -0
  56. package/runtime/node_modules/@metro-labs/daemon/src/channels/dedupe.ts +24 -0
  57. package/runtime/node_modules/@metro-labs/daemon/src/channels/inbound.ts +377 -0
  58. package/runtime/node_modules/@metro-labs/daemon/src/channels/media-note.ts +85 -0
  59. package/runtime/node_modules/@metro-labs/daemon/src/channels/pending.ts +75 -0
  60. package/runtime/node_modules/@metro-labs/daemon/src/channels/relay.ts +129 -0
  61. package/runtime/node_modules/@metro-labs/daemon/src/channels/webhook-note.ts +51 -0
  62. package/runtime/node_modules/@metro-labs/daemon/src/claude/api.ts +148 -0
  63. package/runtime/node_modules/@metro-labs/daemon/src/claude/files.ts +329 -0
  64. package/runtime/node_modules/@metro-labs/daemon/src/claude/login.ts +167 -0
  65. package/runtime/node_modules/@metro-labs/daemon/src/claude/settings.ts +117 -0
  66. package/runtime/node_modules/@metro-labs/daemon/src/connectors/api.ts +307 -0
  67. package/runtime/node_modules/@metro-labs/daemon/src/connectors/cli-api.ts +63 -0
  68. package/runtime/node_modules/@metro-labs/daemon/src/connectors/config.ts +144 -0
  69. package/runtime/node_modules/@metro-labs/daemon/src/connectors/json.ts +21 -0
  70. package/runtime/node_modules/@metro-labs/daemon/src/connectors/model.ts +69 -0
  71. package/runtime/node_modules/@metro-labs/daemon/src/connectors/oauth-client.ts +159 -0
  72. package/runtime/node_modules/@metro-labs/daemon/src/connectors/oauth-discovery.ts +117 -0
  73. package/runtime/node_modules/@metro-labs/daemon/src/connectors/oauth-pending.ts +65 -0
  74. package/runtime/node_modules/@metro-labs/daemon/src/connectors/oauth-routes.ts +157 -0
  75. package/runtime/node_modules/@metro-labs/daemon/src/connectors/oauth.ts +127 -0
  76. package/runtime/node_modules/@metro-labs/daemon/src/connectors/relay-target.ts +39 -0
  77. package/runtime/node_modules/@metro-labs/daemon/src/connectors/relay.ts +295 -0
  78. package/runtime/node_modules/@metro-labs/daemon/src/connectors/store.ts +277 -0
  79. package/runtime/node_modules/@metro-labs/daemon/src/connectors/tools.ts +98 -0
  80. package/runtime/node_modules/@metro-labs/daemon/src/connectors/url.ts +70 -0
  81. package/runtime/node_modules/@metro-labs/daemon/src/connectors/verify.ts +330 -0
  82. package/runtime/node_modules/@metro-labs/daemon/src/files/attach-grant.ts +99 -0
  83. package/runtime/node_modules/@metro-labs/daemon/src/files/attach-owner.ts +32 -0
  84. package/runtime/node_modules/@metro-labs/daemon/src/files/attach-serve.ts +121 -0
  85. package/runtime/node_modules/@metro-labs/daemon/src/files/upload-api.ts +294 -0
  86. package/runtime/node_modules/@metro-labs/daemon/src/files/upload-store.ts +181 -0
  87. package/runtime/node_modules/@metro-labs/daemon/src/gateway/bedrock.ts +252 -0
  88. package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-auth.ts +231 -0
  89. package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-device.ts +91 -0
  90. package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-stream.ts +288 -0
  91. package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-translate.ts +203 -0
  92. package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex.ts +220 -0
  93. package/runtime/node_modules/@metro-labs/daemon/src/gateway/eventstream.ts +123 -0
  94. package/runtime/node_modules/@metro-labs/daemon/src/gateway/forward.ts +182 -0
  95. package/runtime/node_modules/@metro-labs/daemon/src/gateway/gateway.ts +197 -0
  96. package/runtime/node_modules/@metro-labs/daemon/src/gateway/model-api.ts +195 -0
  97. package/runtime/node_modules/@metro-labs/daemon/src/gateway/model-config.ts +198 -0
  98. package/runtime/node_modules/@metro-labs/daemon/src/gateway/openrouter.ts +40 -0
  99. package/runtime/node_modules/@metro-labs/daemon/src/gateway/served.ts +17 -0
  100. package/runtime/node_modules/@metro-labs/daemon/src/mcp/accounts.ts +137 -0
  101. package/runtime/node_modules/@metro-labs/daemon/src/mcp/call-tools.ts +216 -0
  102. package/runtime/node_modules/@metro-labs/daemon/src/mcp/channel-owner.ts +29 -0
  103. package/runtime/node_modules/@metro-labs/daemon/src/mcp/ctx.ts +62 -0
  104. package/runtime/node_modules/@metro-labs/daemon/src/mcp/event-store.ts +91 -0
  105. package/runtime/node_modules/@metro-labs/daemon/src/mcp/frame-scope.ts +21 -0
  106. package/runtime/node_modules/@metro-labs/daemon/src/mcp/group-tools.ts +129 -0
  107. package/runtime/node_modules/@metro-labs/daemon/src/mcp/index.ts +191 -0
  108. package/runtime/node_modules/@metro-labs/daemon/src/mcp/member-tools.ts +72 -0
  109. package/runtime/node_modules/@metro-labs/daemon/src/mcp/permission-relay.ts +66 -0
  110. package/runtime/node_modules/@metro-labs/daemon/src/mcp/raw-get-stream.ts +207 -0
  111. package/runtime/node_modules/@metro-labs/daemon/src/mcp/request-identity.ts +47 -0
  112. package/runtime/node_modules/@metro-labs/daemon/src/mcp/session-registry.ts +172 -0
  113. package/runtime/node_modules/@metro-labs/daemon/src/mcp/session-route.ts +43 -0
  114. package/runtime/node_modules/@metro-labs/daemon/src/mcp/session.ts +215 -0
  115. package/runtime/node_modules/@metro-labs/daemon/src/mcp/tool-dispatch.ts +215 -0
  116. package/runtime/node_modules/@metro-labs/daemon/src/mcp/tool-schemas.ts +400 -0
  117. package/runtime/node_modules/@metro-labs/daemon/src/mcp/upload-tool.ts +66 -0
  118. package/runtime/node_modules/@metro-labs/daemon/src/monitor/api.ts +237 -0
  119. package/runtime/node_modules/@metro-labs/daemon/src/net/tunnel.ts +389 -0
  120. package/runtime/node_modules/@metro-labs/daemon/src/routes/http.ts +390 -0
  121. package/runtime/node_modules/@metro-labs/daemon/src/routes/identity.ts +54 -0
  122. package/runtime/node_modules/@metro-labs/daemon/src/routes/local-mode.ts +187 -0
  123. package/runtime/node_modules/@metro-labs/daemon/src/routes/session-apis.ts +60 -0
  124. package/runtime/node_modules/@metro-labs/daemon/src/routes/session.ts +29 -0
  125. package/runtime/node_modules/@metro-labs/daemon/src/server/control.ts +64 -0
  126. package/runtime/node_modules/@metro-labs/daemon/src/server/machine.ts +61 -0
  127. package/runtime/node_modules/@metro-labs/daemon/src/server/update.ts +116 -0
  128. package/runtime/node_modules/@metro-labs/daemon/src/server.ts +2 -0
  129. package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-inline.ts +100 -0
  130. package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-interactive.ts +161 -0
  131. package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-resolve.ts +202 -0
  132. package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-session.ts +280 -0
  133. package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-xmtp.ts +111 -0
  134. package/runtime/node_modules/@metro-labs/daemon/src/stations/attach.ts +184 -0
  135. package/runtime/node_modules/@metro-labs/daemon/src/stations/materialize.ts +248 -0
  136. package/runtime/node_modules/@metro-labs/daemon/src/stations/registry.ts +35 -0
  137. package/runtime/node_modules/@metro-labs/daemon/src/stations/runtime-deps.ts +82 -0
  138. package/runtime/node_modules/@metro-labs/daemon/src/stations/supervisor-io.ts +97 -0
  139. package/runtime/node_modules/@metro-labs/daemon/src/stations/supervisor.ts +320 -0
  140. package/runtime/node_modules/@metro-labs/daemon/src/stations/train-call.ts +22 -0
  141. package/runtime/node_modules/@metro-labs/daemon/src/terminal/api.ts +71 -0
  142. package/runtime/node_modules/@metro-labs/daemon/src/terminal/socket.ts +123 -0
  143. package/runtime/node_modules/@metro-labs/daemon/src/terminal/tickets.ts +40 -0
  144. package/runtime/node_modules/@metro-labs/discord-bot/package.json +28 -0
  145. package/runtime/node_modules/@metro-labs/discord-bot/src/accounts.ts +118 -0
  146. package/runtime/node_modules/@metro-labs/discord-bot/src/actions.ts +388 -0
  147. package/runtime/node_modules/@metro-labs/discord-bot/src/api-base.ts +1 -0
  148. package/runtime/node_modules/@metro-labs/discord-bot/src/attachments.ts +29 -0
  149. package/runtime/node_modules/@metro-labs/discord-bot/src/format.ts +220 -0
  150. package/runtime/node_modules/@metro-labs/discord-bot/src/group-actions.ts +50 -0
  151. package/runtime/node_modules/@metro-labs/discord-bot/src/group.ts +115 -0
  152. package/runtime/node_modules/@metro-labs/discord-bot/src/index.ts +127 -0
  153. package/runtime/node_modules/@metro-labs/discord-bot/src/members.ts +215 -0
  154. package/runtime/node_modules/@metro-labs/discord-bot/src/send-files.ts +43 -0
  155. package/runtime/node_modules/@metro-labs/discord-bot/src/station.ts +19 -0
  156. package/runtime/node_modules/@metro-labs/discord-bot/src/verify.ts +82 -0
  157. package/runtime/node_modules/@metro-labs/discord-bot/src/voice-speak.ts +195 -0
  158. package/runtime/node_modules/@metro-labs/discord-bot/src/voice-transcribe.ts +292 -0
  159. package/runtime/node_modules/@metro-labs/discord-bot/src/voice.ts +197 -0
  160. package/runtime/node_modules/@metro-labs/discord-bot/src/wire.ts +5 -0
  161. package/runtime/node_modules/@metro-labs/http/package.json +33 -0
  162. package/runtime/node_modules/@metro-labs/http/src/api-error.ts +8 -0
  163. package/runtime/node_modules/@metro-labs/http/src/api-http.ts +95 -0
  164. package/runtime/node_modules/@metro-labs/http/src/cors.ts +29 -0
  165. package/runtime/node_modules/@metro-labs/http/src/identity-key.ts +33 -0
  166. package/runtime/node_modules/@metro-labs/http/src/identity-registry.ts +13 -0
  167. package/runtime/node_modules/@metro-labs/http/src/mode-api.ts +32 -0
  168. package/runtime/node_modules/@metro-labs/http/src/return-to.ts +21 -0
  169. package/runtime/node_modules/@metro-labs/http/src/signed-identity.ts +36 -0
  170. package/runtime/node_modules/@metro-labs/telegram/package.json +26 -0
  171. package/runtime/node_modules/@metro-labs/telegram/src/accounts.ts +80 -0
  172. package/runtime/node_modules/@metro-labs/telegram/src/actions.ts +254 -0
  173. package/runtime/node_modules/@metro-labs/telegram/src/attachments.ts +87 -0
  174. package/runtime/node_modules/@metro-labs/telegram/src/client.ts +77 -0
  175. package/runtime/node_modules/@metro-labs/telegram/src/format.ts +156 -0
  176. package/runtime/node_modules/@metro-labs/telegram/src/group.ts +261 -0
  177. package/runtime/node_modules/@metro-labs/telegram/src/history.ts +52 -0
  178. package/runtime/node_modules/@metro-labs/telegram/src/inbound.ts +78 -0
  179. package/runtime/node_modules/@metro-labs/telegram/src/index.ts +46 -0
  180. package/runtime/node_modules/@metro-labs/telegram/src/login.ts +166 -0
  181. package/runtime/node_modules/@metro-labs/telegram/src/media-actions.ts +80 -0
  182. package/runtime/node_modules/@metro-labs/telegram/src/members.ts +75 -0
  183. package/runtime/node_modules/@metro-labs/telegram/src/normalize.ts +22 -0
  184. package/runtime/node_modules/@metro-labs/telegram/src/reactions.ts +167 -0
  185. package/runtime/node_modules/@metro-labs/telegram/src/station.ts +24 -0
  186. package/runtime/node_modules/@metro-labs/telegram/src/types.ts +7 -0
  187. package/runtime/node_modules/@metro-labs/telegram/src/wire.ts +1 -0
  188. package/runtime/node_modules/@metro-labs/telegram-bot/package.json +25 -0
  189. package/runtime/node_modules/@metro-labs/telegram-bot/src/accounts.ts +120 -0
  190. package/runtime/node_modules/@metro-labs/telegram-bot/src/actions.ts +295 -0
  191. package/runtime/node_modules/@metro-labs/telegram-bot/src/attachments.ts +128 -0
  192. package/runtime/node_modules/@metro-labs/telegram-bot/src/format.ts +201 -0
  193. package/runtime/node_modules/@metro-labs/telegram-bot/src/index.ts +109 -0
  194. package/runtime/node_modules/@metro-labs/telegram-bot/src/media-actions.ts +166 -0
  195. package/runtime/node_modules/@metro-labs/telegram-bot/src/members.ts +47 -0
  196. package/runtime/node_modules/@metro-labs/telegram-bot/src/station.ts +17 -0
  197. package/runtime/node_modules/@metro-labs/telegram-bot/src/types.ts +58 -0
  198. package/runtime/node_modules/@metro-labs/telegram-bot/src/verify.ts +38 -0
  199. package/runtime/node_modules/@metro-labs/telegram-bot/src/wire.ts +3 -0
  200. package/runtime/node_modules/@metro-labs/webhook/package.json +23 -0
  201. package/runtime/node_modules/@metro-labs/webhook/src/station.ts +37 -0
  202. package/runtime/node_modules/@metro-labs/whatsapp/package.json +27 -0
  203. package/runtime/node_modules/@metro-labs/whatsapp/src/accounts.ts +66 -0
  204. package/runtime/node_modules/@metro-labs/whatsapp/src/ack.ts +101 -0
  205. package/runtime/node_modules/@metro-labs/whatsapp/src/actions.ts +178 -0
  206. package/runtime/node_modules/@metro-labs/whatsapp/src/attachments.ts +72 -0
  207. package/runtime/node_modules/@metro-labs/whatsapp/src/auth-state.ts +129 -0
  208. package/runtime/node_modules/@metro-labs/whatsapp/src/client.ts +327 -0
  209. package/runtime/node_modules/@metro-labs/whatsapp/src/delivery.ts +49 -0
  210. package/runtime/node_modules/@metro-labs/whatsapp/src/format.ts +138 -0
  211. package/runtime/node_modules/@metro-labs/whatsapp/src/inbound.ts +57 -0
  212. package/runtime/node_modules/@metro-labs/whatsapp/src/index.ts +40 -0
  213. package/runtime/node_modules/@metro-labs/whatsapp/src/keys.ts +59 -0
  214. package/runtime/node_modules/@metro-labs/whatsapp/src/logger.ts +60 -0
  215. package/runtime/node_modules/@metro-labs/whatsapp/src/login.ts +176 -0
  216. package/runtime/node_modules/@metro-labs/whatsapp/src/media.ts +84 -0
  217. package/runtime/node_modules/@metro-labs/whatsapp/src/normalize.ts +22 -0
  218. package/runtime/node_modules/@metro-labs/whatsapp/src/outbox.ts +38 -0
  219. package/runtime/node_modules/@metro-labs/whatsapp/src/parse.ts +185 -0
  220. package/runtime/node_modules/@metro-labs/whatsapp/src/station.ts +17 -0
  221. package/runtime/node_modules/@metro-labs/whatsapp/src/token-store.ts +98 -0
  222. package/runtime/node_modules/@metro-labs/whatsapp/src/types.ts +6 -0
  223. package/runtime/node_modules/@metro-labs/whatsapp/src/wire.ts +5 -0
  224. package/runtime/node_modules/@metro-labs/xmtp/package.json +33 -0
  225. package/runtime/node_modules/@metro-labs/xmtp/src/accounts.ts +112 -0
  226. package/runtime/node_modules/@metro-labs/xmtp/src/actions-close.ts +110 -0
  227. package/runtime/node_modules/@metro-labs/xmtp/src/actions-conv.ts +299 -0
  228. package/runtime/node_modules/@metro-labs/xmtp/src/actions-meta.ts +157 -0
  229. package/runtime/node_modules/@metro-labs/xmtp/src/actions-push.ts +87 -0
  230. package/runtime/node_modules/@metro-labs/xmtp/src/actions.ts +375 -0
  231. package/runtime/node_modules/@metro-labs/xmtp/src/attachments.ts +107 -0
  232. package/runtime/node_modules/@metro-labs/xmtp/src/codecs.ts +171 -0
  233. package/runtime/node_modules/@metro-labs/xmtp/src/conv-helpers.ts +239 -0
  234. package/runtime/node_modules/@metro-labs/xmtp/src/emit-core.ts +55 -0
  235. package/runtime/node_modules/@metro-labs/xmtp/src/emit-payloads.ts +335 -0
  236. package/runtime/node_modules/@metro-labs/xmtp/src/emit.ts +80 -0
  237. package/runtime/node_modules/@metro-labs/xmtp/src/group-members.ts +34 -0
  238. package/runtime/node_modules/@metro-labs/xmtp/src/group.ts +56 -0
  239. package/runtime/node_modules/@metro-labs/xmtp/src/identity.ts +33 -0
  240. package/runtime/node_modules/@metro-labs/xmtp/src/index.ts +125 -0
  241. package/runtime/node_modules/@metro-labs/xmtp/src/labels.ts +157 -0
  242. package/runtime/node_modules/@metro-labs/xmtp/src/member-args.ts +40 -0
  243. package/runtime/node_modules/@metro-labs/xmtp/src/push.ts +349 -0
  244. package/runtime/node_modules/@metro-labs/xmtp/src/station.ts +13 -0
  245. package/runtime/node_modules/@metro-labs/xmtp/src/tools-handlers.ts +126 -0
  246. package/runtime/node_modules/@metro-labs/xmtp/src/tools.ts +212 -0
  247. package/runtime/node_modules/@metro-labs/xmtp/src/transcribe.ts +90 -0
  248. package/runtime/node_modules/@metro-labs/xmtp/src/verify.ts +84 -0
  249. package/runtime/node_modules/@metro-labs/xmtp/src/wire.ts +53 -0
  250. package/runtime/runtime.json +3 -0
  251. package/runtime/server.ts +1 -0
  252. package/runtime/stations.json +36 -0
  253. package/runtime/trains/.keep +0 -0
  254. package/LICENSE +0 -21
  255. package/README.md +0 -249
  256. package/dist/cache.js +0 -75
  257. package/dist/cli/actions.js +0 -139
  258. package/dist/cli/config.js +0 -185
  259. package/dist/cli/index.js +0 -177
  260. package/dist/cli/skill.js +0 -62
  261. package/dist/cli/util.js +0 -72
  262. package/dist/cli/webhook.js +0 -83
  263. package/dist/codex-rc.js +0 -245
  264. package/dist/dispatcher.js +0 -122
  265. package/dist/history.js +0 -99
  266. package/dist/ipc.js +0 -72
  267. package/dist/log.js +0 -15
  268. package/dist/paths.js +0 -68
  269. package/dist/registry.js +0 -48
  270. package/dist/stations/claude.js +0 -45
  271. package/dist/stations/codex.js +0 -68
  272. package/dist/stations/discord.js +0 -200
  273. package/dist/stations/index.js +0 -133
  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/dist/stations/webhook.js +0 -100
  278. package/dist/tunnel.js +0 -49
  279. package/dist/webhooks.js +0 -40
  280. package/docs/agents.md +0 -216
  281. package/docs/uri-scheme.md +0 -125
  282. package/skills/metro/SKILL.md +0 -249
@@ -0,0 +1,191 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import {
3
+ BodyTooLargeError,
4
+ readBody as readBodyBuffer,
5
+ } from '../routes/http.js';
6
+ import {
7
+ allowedAgents,
8
+ authenticate,
9
+ runWithIdentity,
10
+ type RequestIdentity,
11
+ } from './request-identity.js';
12
+ import {
13
+ headerValue,
14
+ isStandaloneGet,
15
+ serveChannelGet,
16
+ } from './raw-get-stream.js';
17
+ import { channelLog, type McpSession } from './session.js';
18
+ import {
19
+ SessionCapacityError,
20
+ SessionRegistry,
21
+ type AgentLiveness,
22
+ } from './session-registry.js';
23
+ import { routeSession, sessionScopeKey } from './session-route.js';
24
+
25
+ const isInitialize = (b: unknown): boolean =>
26
+ !!b &&
27
+ typeof b === 'object' &&
28
+ (b as { method?: string }).method === 'initialize';
29
+
30
+ const MCP_BODY_MAX = 32 * 1024 * 1024;
31
+
32
+ async function readBody(req: IncomingMessage): Promise<unknown> {
33
+ const raw = (await readBodyBuffer(req, MCP_BODY_MAX)).toString('utf8');
34
+ try {
35
+ return raw ? JSON.parse(raw) : undefined;
36
+ } catch {
37
+ return undefined;
38
+ }
39
+ }
40
+
41
+ type ParsedBody = { ok: true; body: unknown } | { ok: false };
42
+
43
+ async function readOrReject(
44
+ req: IncomingMessage,
45
+ res: ServerResponse,
46
+ ): Promise<ParsedBody> {
47
+ try {
48
+ const body = req.method === 'POST' ? await readBody(req) : undefined;
49
+ return { ok: true, body };
50
+ } catch (err) {
51
+ if (!(err instanceof BodyTooLargeError)) throw err;
52
+ res.writeHead(413).end('payload too large');
53
+ return { ok: false };
54
+ }
55
+ }
56
+
57
+ async function resolveSession(
58
+ registry: SessionRegistry,
59
+ req: IncomingMessage,
60
+ body: unknown,
61
+ identity: RequestIdentity,
62
+ res: ServerResponse,
63
+ ): Promise<McpSession | undefined> {
64
+ const presented = headerValue(req, 'mcp-session-id');
65
+ const scopeKey = sessionScopeKey(identity);
66
+ const route = routeSession({
67
+ isInitialize: isInitialize(body),
68
+ presented,
69
+ ownership: registry.ownership(presented, scopeKey),
70
+ hasOwnSession: registry.forScope(scopeKey) !== undefined,
71
+ });
72
+ if (route.kind === 'reject') {
73
+ channelLog(
74
+ 'session: refused',
75
+ 'status',
76
+ route.status,
77
+ 'presented',
78
+ presented ?? '(none)',
79
+ 'scope',
80
+ scopeKey,
81
+ );
82
+ res.writeHead(route.status).end(route.message);
83
+ return undefined;
84
+ }
85
+ if (route.kind === 'use') {
86
+ const found =
87
+ presented === undefined
88
+ ? registry.forScope(scopeKey)
89
+ : registry.get(presented);
90
+ if (found) return found;
91
+ res.writeHead(404).end('Session not found');
92
+ return undefined;
93
+ }
94
+ try {
95
+ return await registry.create(identity, route.adoptId);
96
+ } catch (err) {
97
+ if (!(err instanceof SessionCapacityError)) throw err;
98
+ res.writeHead(503).end(err.message);
99
+ return undefined;
100
+ }
101
+ }
102
+
103
+ async function serveGet(
104
+ session: McpSession,
105
+ req: IncomingMessage,
106
+ res: ServerResponse,
107
+ identity: RequestIdentity,
108
+ ): Promise<void> {
109
+ if (session.currentSink && !session.owner.streamBelongsTo(identity)) {
110
+ channelLog(
111
+ 'session: refused stream takeover',
112
+ 'session',
113
+ session.id,
114
+ 'scope',
115
+ session.scopeKey,
116
+ );
117
+ res.writeHead(409).end('Conflict: stream held by another identity');
118
+ return;
119
+ }
120
+ const served = await serveChannelGet({
121
+ transport: session.transport,
122
+ eventStore: session.eventStore,
123
+ scope: allowedAgents(identity),
124
+ req,
125
+ res,
126
+ previous: session.currentSink,
127
+ log: channelLog,
128
+ registerSink: (sink) => {
129
+ session.bindSink(sink, identity);
130
+ },
131
+ });
132
+ if (served) session.channel.replayMissed();
133
+ }
134
+
135
+ let activeRegistry: SessionRegistry | undefined;
136
+
137
+ export function agentLiveness(): Map<string, AgentLiveness> {
138
+ return activeRegistry?.liveness() ?? new Map<string, AgentLiveness>();
139
+ }
140
+
141
+ export async function closeAgentSession(agentId: string): Promise<boolean> {
142
+ const scopeKey = sessionScopeKey({ kind: 'agent', agentId });
143
+ return (await activeRegistry?.closeScope(scopeKey)) ?? false;
144
+ }
145
+
146
+ export async function createMetroMcp(): Promise<{
147
+ httpHandler: (req: IncomingMessage, res: ServerResponse) => Promise<void>;
148
+ startInbound: () => void;
149
+ }> {
150
+ await activeRegistry?.closeAll();
151
+ const registry = new SessionRegistry(channelLog);
152
+ activeRegistry = registry;
153
+
154
+ const httpHandler = async (
155
+ req: IncomingMessage,
156
+ res: ServerResponse,
157
+ ): Promise<void> => {
158
+ const identity = authenticate(req);
159
+ if (!identity) {
160
+ res.writeHead(401).end('unauthorized');
161
+ return;
162
+ }
163
+ const parsed = await readOrReject(req, res);
164
+ if (!parsed.ok) return;
165
+ await runWithIdentity(identity, async () => {
166
+ const session = await resolveSession(
167
+ registry,
168
+ req,
169
+ parsed.body,
170
+ identity,
171
+ res,
172
+ );
173
+ if (!session) return;
174
+ session.touch();
175
+ if (isStandaloneGet(req)) {
176
+ await serveGet(session, req, res, identity);
177
+ return;
178
+ }
179
+ await session.transport.handleRequest(req, res, parsed.body);
180
+ });
181
+ };
182
+
183
+ const startInbound = (): void => {
184
+ registry.startInbound();
185
+ channelLog(
186
+ 'inbound: per-session bus subscriptions (bounded replay on reconnect)',
187
+ );
188
+ };
189
+
190
+ return { httpHandler, startInbound };
191
+ }
@@ -0,0 +1,72 @@
1
+ import { stationForLine } from '../stations/registry.js';
2
+ import type {
3
+ MemberCapability,
4
+ MemberList,
5
+ MetroMember,
6
+ ToolResult,
7
+ } from '@metro-labs/core/stations/types';
8
+ import { makeCtx, okJson, toErr } from './ctx.js';
9
+ import { str } from '@metro-labs/core/str';
10
+
11
+ export interface MemberListResult {
12
+ line: string;
13
+ station: string;
14
+ memberCount: number;
15
+ members: MetroMember[];
16
+ capability: MemberCapability;
17
+ }
18
+
19
+ export function wrapMemberList(
20
+ line: string,
21
+ station: string,
22
+ list: MemberList,
23
+ ): MemberListResult {
24
+ const members = Array.isArray(list.members) ? list.members : [];
25
+ return {
26
+ line,
27
+ station,
28
+ memberCount: members.length,
29
+ members,
30
+ capability: list.capability,
31
+ };
32
+ }
33
+
34
+ export function unsupportedMembers(
35
+ line: string,
36
+ station: string,
37
+ reason: string,
38
+ ): MemberListResult {
39
+ return {
40
+ line,
41
+ station,
42
+ memberCount: 0,
43
+ members: [],
44
+ capability: { supported: false, complete: false, reason },
45
+ };
46
+ }
47
+
48
+ export async function dispatchListMembers(
49
+ a: Record<string, unknown>,
50
+ ): Promise<ToolResult> {
51
+ const line = str(a.line);
52
+ if (!line) return okJson(unsupportedMembers('', '', 'list_members requires `line`'));
53
+ const station = stationForLine(line);
54
+ if (!station)
55
+ return okJson(unsupportedMembers(line, '', `no station for line ${line}`));
56
+ if (!station.hasAccounts || !station.hasTrain)
57
+ return okJson(
58
+ unsupportedMembers(
59
+ line,
60
+ station.name,
61
+ `${station.name} lines have no member roster`,
62
+ ),
63
+ );
64
+ const args: Record<string, unknown> = { line };
65
+ if (typeof a.limit === 'number') args.limit = a.limit;
66
+ try {
67
+ const { result } = await makeCtx(station.name).call('listMembers', args);
68
+ return okJson(wrapMemberList(line, station.name, result as MemberList));
69
+ } catch (e) {
70
+ return toErr('list_members', e);
71
+ }
72
+ }
@@ -0,0 +1,66 @@
1
+ import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { z } from 'zod';
3
+ import type { InboundRelay } from '../channels/inbound.js';
4
+ import type { ChannelOwner } from './channel-owner.js';
5
+ import { metroCall } from './ctx.js';
6
+
7
+ const PermissionRequestSchema = z.object({
8
+ method: z.literal('notifications/claude/channel/permission_request'),
9
+ params: z.object({
10
+ request_id: z.string(),
11
+ tool_name: z.string(),
12
+ description: z.string(),
13
+ input_preview: z.string(),
14
+ }),
15
+ });
16
+
17
+ type PermissionRequest = z.infer<typeof PermissionRequestSchema>;
18
+
19
+ const trainOf = (line: string): string => line.split('/')[2] ?? '';
20
+
21
+ async function metroSend(line: string, text: string): Promise<void> {
22
+ await metroCall(trainOf(line), 'send', { line, text });
23
+ }
24
+
25
+ function promptBody(params: PermissionRequest['params']): string {
26
+ return (
27
+ `Claude wants to run ${params.tool_name}: ${params.description}\n` +
28
+ (params.input_preview ? `\n${params.input_preview}\n` : '') +
29
+ `\nReply "yes ${params.request_id}" or "no ${params.request_id}"`
30
+ );
31
+ }
32
+
33
+ export interface PermissionRelayDeps {
34
+ mcp: Server;
35
+ relay: InboundRelay;
36
+ owner: ChannelOwner;
37
+ log: (...a: unknown[]) => void;
38
+ }
39
+
40
+ export function registerPermissionRelay(deps: PermissionRelayDeps): void {
41
+ const { mcp, relay, owner, log } = deps;
42
+ mcp.setNotificationHandler(
43
+ PermissionRequestSchema as never,
44
+ async (n: PermissionRequest) => {
45
+ const { params } = n;
46
+ const line = relay.knownLine;
47
+ if (!line) {
48
+ log('permission_request but no known line to relay to', params.request_id);
49
+ return;
50
+ }
51
+ if (!owner.inScope(line)) {
52
+ log(
53
+ 'permission_request: known line is outside the channel session scope',
54
+ params.request_id,
55
+ );
56
+ return;
57
+ }
58
+ relay.registerPermission(params.request_id);
59
+ try {
60
+ await metroSend(line, promptBody(params));
61
+ } catch (e) {
62
+ log('relay send failed', e);
63
+ }
64
+ },
65
+ );
66
+ }
@@ -0,0 +1,207 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import type {
3
+ StreamableHTTPServerTransport,
4
+ EventId,
5
+ } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
6
+ import type { JSONRPCMessage } from '@modelcontextprotocol/sdk/types.js';
7
+ import type { BoundedEventStore } from './event-store.js';
8
+
9
+ const STANDALONE_STREAM_ID = '_GET_stream';
10
+ const KEEPALIVE_MS = 15_000;
11
+ const RECONNECT_RETRY_MS = 15_000;
12
+ const COMMENT = ':\n\n';
13
+ const RETRY_DIRECTIVE = `retry: ${RECONNECT_RETRY_MS}\n\n`;
14
+
15
+ interface StreamEntry {
16
+ controller: { enqueue: (chunk: Uint8Array) => void };
17
+ encoder: { encode: (input: string) => Uint8Array };
18
+ cleanup: () => void;
19
+ }
20
+
21
+ export interface WebTransport {
22
+ sessionId?: string;
23
+ _initialized?: boolean;
24
+ _streamMapping?: Map<string, StreamEntry>;
25
+ }
26
+
27
+ interface AdaptedTransport {
28
+ _webStandardTransport?: WebTransport;
29
+ }
30
+
31
+ export const web = (
32
+ transport: StreamableHTTPServerTransport,
33
+ ): WebTransport | undefined =>
34
+ (transport as unknown as AdaptedTransport)._webStandardTransport;
35
+
36
+ export const isStandaloneGet = (req: IncomingMessage): boolean => {
37
+ if (req.method !== 'GET') return false;
38
+ const accept = req.headers.accept;
39
+ const value = Array.isArray(accept) ? accept.join(',') : (accept ?? '');
40
+ return value.includes('text/event-stream');
41
+ };
42
+
43
+ export const headerValue = (
44
+ req: IncomingMessage,
45
+ name: string,
46
+ ): string | undefined => {
47
+ const raw = req.headers[name];
48
+ if (Array.isArray(raw)) return raw[0];
49
+ return typeof raw === 'string' ? raw : undefined;
50
+ };
51
+
52
+ export interface RawGetSink {
53
+ closed: boolean;
54
+ attach: (transport: StreamableHTTPServerTransport) => void;
55
+ close: () => void;
56
+ }
57
+
58
+ export interface ValidateResult {
59
+ ok: boolean;
60
+ status?: number;
61
+ message?: string;
62
+ }
63
+
64
+ export function validateStandaloneSession(
65
+ transport: StreamableHTTPServerTransport,
66
+ req: IncomingMessage,
67
+ ): ValidateResult {
68
+ const inner = web(transport);
69
+ if (!inner) return { ok: false, status: 500, message: 'transport not ready' };
70
+ if (!inner._initialized)
71
+ return {
72
+ ok: false,
73
+ status: 400,
74
+ message: 'Bad Request: Server not initialized',
75
+ };
76
+ const presented = headerValue(req, 'mcp-session-id');
77
+ if (!presented)
78
+ return {
79
+ ok: false,
80
+ status: 400,
81
+ message: 'Bad Request: Mcp-Session-Id header is required',
82
+ };
83
+ if (presented !== inner.sessionId)
84
+ return { ok: false, status: 404, message: 'Session not found' };
85
+ return { ok: true };
86
+ }
87
+
88
+ export interface ServeOpts {
89
+ transport: StreamableHTTPServerTransport;
90
+ eventStore: BoundedEventStore;
91
+ scope: Set<string>;
92
+ req: IncomingMessage;
93
+ res: ServerResponse;
94
+ log: (...a: unknown[]) => void;
95
+ registerSink: (sink: RawGetSink | undefined) => void;
96
+ }
97
+
98
+ export async function serveStandaloneGet(opts: ServeOpts): Promise<void> {
99
+ const { transport, eventStore, scope, req, res, log, registerSink } = opts;
100
+ const sessionId = web(transport)?.sessionId;
101
+
102
+ res.writeHead(200, {
103
+ 'content-type': 'text/event-stream',
104
+ 'cache-control': 'no-cache, no-transform',
105
+ connection: 'keep-alive',
106
+ 'x-accel-buffering': 'no',
107
+ ...(sessionId ? { 'mcp-session-id': sessionId } : {}),
108
+ });
109
+ res.flushHeaders?.();
110
+ res.write(RETRY_DIRECTIVE);
111
+ res.write(COMMENT);
112
+
113
+ let active = transport;
114
+ const timers: { keepalive?: ReturnType<typeof setInterval> } = {};
115
+ const closeStream = (): void => {
116
+ if (sink.closed) return;
117
+ sink.closed = true;
118
+ if (timers.keepalive) clearInterval(timers.keepalive);
119
+ web(active)?._streamMapping?.delete(STANDALONE_STREAM_ID);
120
+ registerSink(undefined);
121
+ try {
122
+ res.end();
123
+ } catch {
124
+ log('raw-get-stream: end failed');
125
+ }
126
+ };
127
+ const sink: RawGetSink = {
128
+ closed: false,
129
+ attach: (next: StreamableHTTPServerTransport): void => {
130
+ active = next;
131
+ const entry: StreamEntry = {
132
+ controller: {
133
+ enqueue: (chunk: Uint8Array): void => {
134
+ if (sink.closed) return;
135
+ if (res.destroyed || res.writableEnded) {
136
+ closeStream();
137
+ return;
138
+ }
139
+ res.write(Buffer.from(chunk));
140
+ },
141
+ },
142
+ encoder: { encode: (input: string): Uint8Array => Buffer.from(input) },
143
+ cleanup: closeStream,
144
+ };
145
+ web(next)?._streamMapping?.set(STANDALONE_STREAM_ID, entry);
146
+ },
147
+ close: closeStream,
148
+ };
149
+
150
+ const lastEventId = headerValue(req, 'last-event-id');
151
+ if (lastEventId) {
152
+ await eventStore.replayEventsAfter(lastEventId, {
153
+ scope,
154
+ send: (id: EventId, message: JSONRPCMessage): Promise<void> => {
155
+ if (!sink.closed)
156
+ res.write(`event: message\nid: ${id}\ndata: ${JSON.stringify(message)}\n\n`);
157
+ return Promise.resolve();
158
+ },
159
+ onWithheld: (id: EventId, line: string | undefined): void => {
160
+ log(
161
+ 'raw-get-stream: withheld replay (frame outside the reconnecting session scope)',
162
+ 'id',
163
+ id,
164
+ 'line',
165
+ line ?? '(none)',
166
+ );
167
+ },
168
+ });
169
+ }
170
+
171
+ sink.attach(transport);
172
+ registerSink(sink);
173
+
174
+ timers.keepalive = setInterval(() => {
175
+ if (sink.closed) return;
176
+ if (res.destroyed || res.writableEnded) {
177
+ closeStream();
178
+ return;
179
+ }
180
+ try {
181
+ res.write(COMMENT);
182
+ } catch (err) {
183
+ log('raw-get-stream: keepalive write failed', err);
184
+ closeStream();
185
+ }
186
+ }, KEEPALIVE_MS);
187
+ timers.keepalive.unref?.();
188
+
189
+ res.on('close', closeStream);
190
+ res.on('error', closeStream);
191
+ req.on('close', closeStream);
192
+ }
193
+
194
+ export interface ChannelGetOpts extends ServeOpts {
195
+ previous: RawGetSink | undefined;
196
+ }
197
+
198
+ export async function serveChannelGet(opts: ChannelGetOpts): Promise<boolean> {
199
+ const check = validateStandaloneSession(opts.transport, opts.req);
200
+ if (!check.ok) {
201
+ opts.res.writeHead(check.status ?? 400).end(check.message ?? 'bad request');
202
+ return false;
203
+ }
204
+ if (opts.previous && !opts.previous.closed) opts.previous.close();
205
+ await serveStandaloneGet(opts);
206
+ return true;
207
+ }
@@ -0,0 +1,47 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks';
2
+ import type { IncomingMessage } from 'node:http';
3
+ import { agentIdForKey } from '../agents/keys.js';
4
+
5
+ export type RequestIdentity =
6
+ | { kind: 'agent'; agentId: string }
7
+ | { kind: 'session'; subject: string; agentIds: string[] };
8
+
9
+ const storage = new AsyncLocalStorage<RequestIdentity>();
10
+
11
+ export function runWithIdentity<T>(
12
+ identity: RequestIdentity,
13
+ fn: () => Promise<T>,
14
+ ): Promise<T> {
15
+ return storage.run(identity, fn);
16
+ }
17
+
18
+ export function currentIdentity(): RequestIdentity | undefined {
19
+ return storage.getStore();
20
+ }
21
+
22
+ export function extractToken(req: IncomingMessage): string | undefined {
23
+ const header = req.headers.authorization;
24
+ if (header?.startsWith('Bearer ')) {
25
+ const t = header.slice(7).trim();
26
+ if (t) return t;
27
+ }
28
+ const qt = new URL(req.url ?? '/', 'http://localhost').searchParams.get(
29
+ 'token',
30
+ );
31
+ return qt ?? undefined;
32
+ }
33
+
34
+ export function authenticate(req: IncomingMessage): RequestIdentity | null {
35
+ const token = extractToken(req);
36
+ if (!token) return null;
37
+ const agentId = agentIdForKey(token);
38
+ return agentId === undefined ? null : { kind: 'agent', agentId };
39
+ }
40
+
41
+ export function allowedAgents(
42
+ identity: RequestIdentity | undefined,
43
+ ): Set<string> {
44
+ if (identity?.kind === 'session') return new Set(identity.agentIds);
45
+ if (identity?.kind === 'agent') return new Set([identity.agentId]);
46
+ return new Set();
47
+ }