@stage-labs/metro 0.1.0-beta.13 → 0.1.0-beta.130

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 (328) hide show
  1. package/dist/api.js +14 -0
  2. package/dist/claude-settings.js +40 -0
  3. package/dist/claude.js +176 -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/mcp-config.js +25 -0
  9. package/dist/node-name.js +71 -0
  10. package/dist/onboarding.js +43 -0
  11. package/dist/plugin.js +120 -0
  12. package/dist/provider-flags.js +9 -0
  13. package/dist/route.js +38 -0
  14. package/dist/runtime-install.js +97 -0
  15. package/dist/runtime.js +74 -0
  16. package/dist/serve.js +150 -0
  17. package/dist/service.js +242 -0
  18. package/dist/tail.js +119 -0
  19. package/dist/update.js +45 -0
  20. package/dist/version.js +97 -0
  21. package/package.json +14 -27
  22. package/runtime/marketplace/.claude-plugin/marketplace.json +12 -0
  23. package/runtime/marketplace/plugin/.claude-plugin/plugin.json +18 -0
  24. package/runtime/marketplace/plugin/.mcp.json +1 -0
  25. package/runtime/marketplace/plugin/bin/guard.mjs +55 -0
  26. package/runtime/marketplace/plugin/bin/metro-plugin.mjs +122 -0
  27. package/runtime/marketplace/plugin/bin/session-start.mjs +31 -0
  28. package/runtime/marketplace/plugin/hooks/hooks.json +25 -0
  29. package/runtime/marketplace/plugin/orchestrator.md +16 -0
  30. package/runtime/marketplace/plugin/skills/refresh/SKILL.md +15 -0
  31. package/runtime/node_modules/@metro-labs/core/package.json +43 -0
  32. package/runtime/node_modules/@metro-labs/core/src/address.ts +6 -0
  33. package/runtime/node_modules/@metro-labs/core/src/endpoints.ts +7 -0
  34. package/runtime/node_modules/@metro-labs/core/src/events.ts +120 -0
  35. package/runtime/node_modules/@metro-labs/core/src/identity.ts +7 -0
  36. package/runtime/node_modules/@metro-labs/core/src/ids.ts +21 -0
  37. package/runtime/node_modules/@metro-labs/core/src/is-record.ts +2 -0
  38. package/runtime/node_modules/@metro-labs/core/src/lines.ts +87 -0
  39. package/runtime/node_modules/@metro-labs/core/src/log.ts +42 -0
  40. package/runtime/node_modules/@metro-labs/core/src/protocol.ts +226 -0
  41. package/runtime/node_modules/@metro-labs/core/src/secure-fs.ts +57 -0
  42. package/runtime/node_modules/@metro-labs/core/src/station-names.ts +13 -0
  43. package/runtime/node_modules/@metro-labs/core/src/stations/account-store.ts +60 -0
  44. package/runtime/node_modules/@metro-labs/core/src/stations/attachments.ts +196 -0
  45. package/runtime/node_modules/@metro-labs/core/src/stations/messaging-normalize.ts +88 -0
  46. package/runtime/node_modules/@metro-labs/core/src/stations/station-runtime.ts +64 -0
  47. package/runtime/node_modules/@metro-labs/core/src/stations/types.ts +108 -0
  48. package/runtime/node_modules/@metro-labs/core/src/str.ts +5 -0
  49. package/runtime/node_modules/@metro-labs/core/src/train-error.ts +53 -0
  50. package/runtime/node_modules/@metro-labs/core/src/version.ts +2 -0
  51. package/runtime/node_modules/@metro-labs/daemon/package.json +48 -0
  52. package/runtime/node_modules/@metro-labs/daemon/src/agents/account-attach.ts +19 -0
  53. package/runtime/node_modules/@metro-labs/daemon/src/agents/account-routes.ts +70 -0
  54. package/runtime/node_modules/@metro-labs/daemon/src/agents/accounts-api.ts +365 -0
  55. package/runtime/node_modules/@metro-labs/daemon/src/agents/admin.ts +43 -0
  56. package/runtime/node_modules/@metro-labs/daemon/src/agents/allowlist.ts +37 -0
  57. package/runtime/node_modules/@metro-labs/daemon/src/agents/api.ts +300 -0
  58. package/runtime/node_modules/@metro-labs/daemon/src/agents/bundle.ts +122 -0
  59. package/runtime/node_modules/@metro-labs/daemon/src/agents/file-admin.ts +371 -0
  60. package/runtime/node_modules/@metro-labs/daemon/src/agents/files.ts +155 -0
  61. package/runtime/node_modules/@metro-labs/daemon/src/agents/keys.ts +45 -0
  62. package/runtime/node_modules/@metro-labs/daemon/src/agents/map.ts +95 -0
  63. package/runtime/node_modules/@metro-labs/daemon/src/agents/scope.ts +64 -0
  64. package/runtime/node_modules/@metro-labs/daemon/src/agents/senders.ts +38 -0
  65. package/runtime/node_modules/@metro-labs/daemon/src/boot/boot.ts +207 -0
  66. package/runtime/node_modules/@metro-labs/daemon/src/boot/connect-hint.ts +39 -0
  67. package/runtime/node_modules/@metro-labs/daemon/src/boot/crash-guard.ts +49 -0
  68. package/runtime/node_modules/@metro-labs/daemon/src/boot/local-owner.ts +14 -0
  69. package/runtime/node_modules/@metro-labs/daemon/src/boot/paths.ts +106 -0
  70. package/runtime/node_modules/@metro-labs/daemon/src/channels/addressed.ts +25 -0
  71. package/runtime/node_modules/@metro-labs/daemon/src/channels/dedupe.ts +24 -0
  72. package/runtime/node_modules/@metro-labs/daemon/src/channels/inbound.ts +377 -0
  73. package/runtime/node_modules/@metro-labs/daemon/src/channels/media-note.ts +85 -0
  74. package/runtime/node_modules/@metro-labs/daemon/src/channels/pending.ts +75 -0
  75. package/runtime/node_modules/@metro-labs/daemon/src/channels/relay.ts +129 -0
  76. package/runtime/node_modules/@metro-labs/daemon/src/channels/webhook-note.ts +51 -0
  77. package/runtime/node_modules/@metro-labs/daemon/src/claude/api.ts +309 -0
  78. package/runtime/node_modules/@metro-labs/daemon/src/claude/files.ts +358 -0
  79. package/runtime/node_modules/@metro-labs/daemon/src/claude/login.ts +169 -0
  80. package/runtime/node_modules/@metro-labs/daemon/src/claude/onboarding.ts +56 -0
  81. package/runtime/node_modules/@metro-labs/daemon/src/claude/plugin-install.ts +140 -0
  82. package/runtime/node_modules/@metro-labs/daemon/src/claude/session-files.ts +90 -0
  83. package/runtime/node_modules/@metro-labs/daemon/src/claude/session.ts +253 -0
  84. package/runtime/node_modules/@metro-labs/daemon/src/claude/settings.ts +117 -0
  85. package/runtime/node_modules/@metro-labs/daemon/src/claude/setup.ts +239 -0
  86. package/runtime/node_modules/@metro-labs/daemon/src/claude/skills.ts +154 -0
  87. package/runtime/node_modules/@metro-labs/daemon/src/claude/version.ts +109 -0
  88. package/runtime/node_modules/@metro-labs/daemon/src/connectors/api.ts +310 -0
  89. package/runtime/node_modules/@metro-labs/daemon/src/connectors/cli-api.ts +63 -0
  90. package/runtime/node_modules/@metro-labs/daemon/src/connectors/config.ts +175 -0
  91. package/runtime/node_modules/@metro-labs/daemon/src/connectors/json.ts +21 -0
  92. package/runtime/node_modules/@metro-labs/daemon/src/connectors/model.ts +77 -0
  93. package/runtime/node_modules/@metro-labs/daemon/src/connectors/oauth-client.ts +166 -0
  94. package/runtime/node_modules/@metro-labs/daemon/src/connectors/oauth-discovery.ts +139 -0
  95. package/runtime/node_modules/@metro-labs/daemon/src/connectors/oauth-pending.ts +65 -0
  96. package/runtime/node_modules/@metro-labs/daemon/src/connectors/oauth-routes.ts +171 -0
  97. package/runtime/node_modules/@metro-labs/daemon/src/connectors/oauth.ts +155 -0
  98. package/runtime/node_modules/@metro-labs/daemon/src/connectors/plugin-sync.ts +122 -0
  99. package/runtime/node_modules/@metro-labs/daemon/src/connectors/reach.ts +27 -0
  100. package/runtime/node_modules/@metro-labs/daemon/src/connectors/relay-target.ts +39 -0
  101. package/runtime/node_modules/@metro-labs/daemon/src/connectors/relay.ts +296 -0
  102. package/runtime/node_modules/@metro-labs/daemon/src/connectors/store.ts +286 -0
  103. package/runtime/node_modules/@metro-labs/daemon/src/connectors/tools.ts +98 -0
  104. package/runtime/node_modules/@metro-labs/daemon/src/connectors/url.ts +70 -0
  105. package/runtime/node_modules/@metro-labs/daemon/src/connectors/verify.ts +332 -0
  106. package/runtime/node_modules/@metro-labs/daemon/src/connectors/watch.ts +54 -0
  107. package/runtime/node_modules/@metro-labs/daemon/src/files/attach-grant.ts +99 -0
  108. package/runtime/node_modules/@metro-labs/daemon/src/files/attach-owner.ts +32 -0
  109. package/runtime/node_modules/@metro-labs/daemon/src/files/attach-serve.ts +121 -0
  110. package/runtime/node_modules/@metro-labs/daemon/src/files/upload-api.ts +294 -0
  111. package/runtime/node_modules/@metro-labs/daemon/src/files/upload-store.ts +181 -0
  112. package/runtime/node_modules/@metro-labs/daemon/src/gateway/bedrock.ts +259 -0
  113. package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-auth.ts +231 -0
  114. package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-device.ts +91 -0
  115. package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-stream.ts +288 -0
  116. package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-translate.ts +203 -0
  117. package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex.ts +231 -0
  118. package/runtime/node_modules/@metro-labs/daemon/src/gateway/eventstream.ts +123 -0
  119. package/runtime/node_modules/@metro-labs/daemon/src/gateway/forward.ts +187 -0
  120. package/runtime/node_modules/@metro-labs/daemon/src/gateway/gateway.ts +229 -0
  121. package/runtime/node_modules/@metro-labs/daemon/src/gateway/model-api.ts +269 -0
  122. package/runtime/node_modules/@metro-labs/daemon/src/gateway/model-config.ts +207 -0
  123. package/runtime/node_modules/@metro-labs/daemon/src/gateway/openrouter.ts +90 -0
  124. package/runtime/node_modules/@metro-labs/daemon/src/gateway/provider-models.ts +65 -0
  125. package/runtime/node_modules/@metro-labs/daemon/src/gateway/served.ts +17 -0
  126. package/runtime/node_modules/@metro-labs/daemon/src/gateway/usage.ts +229 -0
  127. package/runtime/node_modules/@metro-labs/daemon/src/mcp/accounts.ts +151 -0
  128. package/runtime/node_modules/@metro-labs/daemon/src/mcp/call-tools.ts +216 -0
  129. package/runtime/node_modules/@metro-labs/daemon/src/mcp/channel-owner.ts +29 -0
  130. package/runtime/node_modules/@metro-labs/daemon/src/mcp/ctx.ts +62 -0
  131. package/runtime/node_modules/@metro-labs/daemon/src/mcp/event-store.ts +91 -0
  132. package/runtime/node_modules/@metro-labs/daemon/src/mcp/frame-scope.ts +21 -0
  133. package/runtime/node_modules/@metro-labs/daemon/src/mcp/group-tools.ts +129 -0
  134. package/runtime/node_modules/@metro-labs/daemon/src/mcp/index.ts +191 -0
  135. package/runtime/node_modules/@metro-labs/daemon/src/mcp/member-tools.ts +72 -0
  136. package/runtime/node_modules/@metro-labs/daemon/src/mcp/permission-relay.ts +66 -0
  137. package/runtime/node_modules/@metro-labs/daemon/src/mcp/raw-get-stream.ts +207 -0
  138. package/runtime/node_modules/@metro-labs/daemon/src/mcp/request-identity.ts +47 -0
  139. package/runtime/node_modules/@metro-labs/daemon/src/mcp/session-registry.ts +172 -0
  140. package/runtime/node_modules/@metro-labs/daemon/src/mcp/session-route.ts +43 -0
  141. package/runtime/node_modules/@metro-labs/daemon/src/mcp/session.ts +215 -0
  142. package/runtime/node_modules/@metro-labs/daemon/src/mcp/tool-dispatch.ts +215 -0
  143. package/runtime/node_modules/@metro-labs/daemon/src/mcp/tool-schemas.ts +400 -0
  144. package/runtime/node_modules/@metro-labs/daemon/src/mcp/upload-tool.ts +66 -0
  145. package/runtime/node_modules/@metro-labs/daemon/src/monitor/api.ts +237 -0
  146. package/runtime/node_modules/@metro-labs/daemon/src/net/tunnel.ts +389 -0
  147. package/runtime/node_modules/@metro-labs/daemon/src/routes/body.ts +24 -0
  148. package/runtime/node_modules/@metro-labs/daemon/src/routes/http.ts +372 -0
  149. package/runtime/node_modules/@metro-labs/daemon/src/routes/identity.ts +54 -0
  150. package/runtime/node_modules/@metro-labs/daemon/src/routes/local-mode.ts +223 -0
  151. package/runtime/node_modules/@metro-labs/daemon/src/routes/session-apis.ts +60 -0
  152. package/runtime/node_modules/@metro-labs/daemon/src/routes/session.ts +29 -0
  153. package/runtime/node_modules/@metro-labs/daemon/src/routes/threema-callback.ts +103 -0
  154. package/runtime/node_modules/@metro-labs/daemon/src/server/control.ts +64 -0
  155. package/runtime/node_modules/@metro-labs/daemon/src/server/machine.ts +61 -0
  156. package/runtime/node_modules/@metro-labs/daemon/src/server/update.ts +116 -0
  157. package/runtime/node_modules/@metro-labs/daemon/src/server.ts +2 -0
  158. package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-inline.ts +100 -0
  159. package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-interactive.ts +161 -0
  160. package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-resolve.ts +202 -0
  161. package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-session.ts +280 -0
  162. package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-xmtp.ts +111 -0
  163. package/runtime/node_modules/@metro-labs/daemon/src/stations/attach.ts +248 -0
  164. package/runtime/node_modules/@metro-labs/daemon/src/stations/materialize.ts +261 -0
  165. package/runtime/node_modules/@metro-labs/daemon/src/stations/registry.ts +37 -0
  166. package/runtime/node_modules/@metro-labs/daemon/src/stations/runtime-deps.ts +82 -0
  167. package/runtime/node_modules/@metro-labs/daemon/src/stations/supervisor-io.ts +97 -0
  168. package/runtime/node_modules/@metro-labs/daemon/src/stations/supervisor.ts +320 -0
  169. package/runtime/node_modules/@metro-labs/daemon/src/stations/threema-callbacks.ts +32 -0
  170. package/runtime/node_modules/@metro-labs/daemon/src/stations/train-call.ts +22 -0
  171. package/runtime/node_modules/@metro-labs/daemon/src/terminal/api.ts +96 -0
  172. package/runtime/node_modules/@metro-labs/daemon/src/terminal/socket.ts +123 -0
  173. package/runtime/node_modules/@metro-labs/daemon/src/terminal/tickets.ts +40 -0
  174. package/runtime/node_modules/@metro-labs/discord-bot/package.json +28 -0
  175. package/runtime/node_modules/@metro-labs/discord-bot/src/accounts.ts +118 -0
  176. package/runtime/node_modules/@metro-labs/discord-bot/src/actions.ts +388 -0
  177. package/runtime/node_modules/@metro-labs/discord-bot/src/api-base.ts +1 -0
  178. package/runtime/node_modules/@metro-labs/discord-bot/src/attachments.ts +29 -0
  179. package/runtime/node_modules/@metro-labs/discord-bot/src/format.ts +220 -0
  180. package/runtime/node_modules/@metro-labs/discord-bot/src/group-actions.ts +50 -0
  181. package/runtime/node_modules/@metro-labs/discord-bot/src/group.ts +115 -0
  182. package/runtime/node_modules/@metro-labs/discord-bot/src/index.ts +127 -0
  183. package/runtime/node_modules/@metro-labs/discord-bot/src/members.ts +215 -0
  184. package/runtime/node_modules/@metro-labs/discord-bot/src/send-files.ts +43 -0
  185. package/runtime/node_modules/@metro-labs/discord-bot/src/station.ts +19 -0
  186. package/runtime/node_modules/@metro-labs/discord-bot/src/verify.ts +82 -0
  187. package/runtime/node_modules/@metro-labs/discord-bot/src/voice-speak.ts +195 -0
  188. package/runtime/node_modules/@metro-labs/discord-bot/src/voice-transcribe.ts +292 -0
  189. package/runtime/node_modules/@metro-labs/discord-bot/src/voice.ts +197 -0
  190. package/runtime/node_modules/@metro-labs/discord-bot/src/wire.ts +5 -0
  191. package/runtime/node_modules/@metro-labs/http/package.json +33 -0
  192. package/runtime/node_modules/@metro-labs/http/src/api-error.ts +8 -0
  193. package/runtime/node_modules/@metro-labs/http/src/api-http.ts +95 -0
  194. package/runtime/node_modules/@metro-labs/http/src/cors.ts +29 -0
  195. package/runtime/node_modules/@metro-labs/http/src/identity-key.ts +33 -0
  196. package/runtime/node_modules/@metro-labs/http/src/identity-registry.ts +13 -0
  197. package/runtime/node_modules/@metro-labs/http/src/mode-api.ts +32 -0
  198. package/runtime/node_modules/@metro-labs/http/src/return-to.ts +21 -0
  199. package/runtime/node_modules/@metro-labs/http/src/signed-identity.ts +36 -0
  200. package/runtime/node_modules/@metro-labs/telegram/package.json +26 -0
  201. package/runtime/node_modules/@metro-labs/telegram/src/accounts.ts +80 -0
  202. package/runtime/node_modules/@metro-labs/telegram/src/actions.ts +254 -0
  203. package/runtime/node_modules/@metro-labs/telegram/src/attachments.ts +87 -0
  204. package/runtime/node_modules/@metro-labs/telegram/src/client.ts +77 -0
  205. package/runtime/node_modules/@metro-labs/telegram/src/format.ts +156 -0
  206. package/runtime/node_modules/@metro-labs/telegram/src/group.ts +261 -0
  207. package/runtime/node_modules/@metro-labs/telegram/src/history.ts +52 -0
  208. package/runtime/node_modules/@metro-labs/telegram/src/inbound.ts +78 -0
  209. package/runtime/node_modules/@metro-labs/telegram/src/index.ts +46 -0
  210. package/runtime/node_modules/@metro-labs/telegram/src/login.ts +166 -0
  211. package/runtime/node_modules/@metro-labs/telegram/src/media-actions.ts +80 -0
  212. package/runtime/node_modules/@metro-labs/telegram/src/members.ts +75 -0
  213. package/runtime/node_modules/@metro-labs/telegram/src/normalize.ts +22 -0
  214. package/runtime/node_modules/@metro-labs/telegram/src/reactions.ts +167 -0
  215. package/runtime/node_modules/@metro-labs/telegram/src/station.ts +24 -0
  216. package/runtime/node_modules/@metro-labs/telegram/src/types.ts +7 -0
  217. package/runtime/node_modules/@metro-labs/telegram/src/wire.ts +1 -0
  218. package/runtime/node_modules/@metro-labs/telegram-bot/package.json +25 -0
  219. package/runtime/node_modules/@metro-labs/telegram-bot/src/accounts.ts +120 -0
  220. package/runtime/node_modules/@metro-labs/telegram-bot/src/actions.ts +295 -0
  221. package/runtime/node_modules/@metro-labs/telegram-bot/src/attachments.ts +128 -0
  222. package/runtime/node_modules/@metro-labs/telegram-bot/src/format.ts +201 -0
  223. package/runtime/node_modules/@metro-labs/telegram-bot/src/index.ts +109 -0
  224. package/runtime/node_modules/@metro-labs/telegram-bot/src/media-actions.ts +166 -0
  225. package/runtime/node_modules/@metro-labs/telegram-bot/src/members.ts +47 -0
  226. package/runtime/node_modules/@metro-labs/telegram-bot/src/station.ts +17 -0
  227. package/runtime/node_modules/@metro-labs/telegram-bot/src/types.ts +58 -0
  228. package/runtime/node_modules/@metro-labs/telegram-bot/src/verify.ts +38 -0
  229. package/runtime/node_modules/@metro-labs/telegram-bot/src/wire.ts +3 -0
  230. package/runtime/node_modules/@metro-labs/threema/package.json +26 -0
  231. package/runtime/node_modules/@metro-labs/threema/src/accounts.ts +100 -0
  232. package/runtime/node_modules/@metro-labs/threema/src/actions.ts +219 -0
  233. package/runtime/node_modules/@metro-labs/threema/src/api.ts +130 -0
  234. package/runtime/node_modules/@metro-labs/threema/src/crypto.ts +132 -0
  235. package/runtime/node_modules/@metro-labs/threema/src/format.ts +123 -0
  236. package/runtime/node_modules/@metro-labs/threema/src/ids.ts +21 -0
  237. package/runtime/node_modules/@metro-labs/threema/src/index.ts +29 -0
  238. package/runtime/node_modules/@metro-labs/threema/src/station.ts +10 -0
  239. package/runtime/node_modules/@metro-labs/threema/src/verify.ts +117 -0
  240. package/runtime/node_modules/@metro-labs/webhook/package.json +23 -0
  241. package/runtime/node_modules/@metro-labs/webhook/src/station.ts +37 -0
  242. package/runtime/node_modules/@metro-labs/whatsapp/package.json +27 -0
  243. package/runtime/node_modules/@metro-labs/whatsapp/src/accounts.ts +66 -0
  244. package/runtime/node_modules/@metro-labs/whatsapp/src/ack.ts +101 -0
  245. package/runtime/node_modules/@metro-labs/whatsapp/src/actions.ts +190 -0
  246. package/runtime/node_modules/@metro-labs/whatsapp/src/attachments.ts +72 -0
  247. package/runtime/node_modules/@metro-labs/whatsapp/src/auth-state.ts +129 -0
  248. package/runtime/node_modules/@metro-labs/whatsapp/src/client.ts +347 -0
  249. package/runtime/node_modules/@metro-labs/whatsapp/src/delivery.ts +49 -0
  250. package/runtime/node_modules/@metro-labs/whatsapp/src/format.ts +138 -0
  251. package/runtime/node_modules/@metro-labs/whatsapp/src/inbound.ts +57 -0
  252. package/runtime/node_modules/@metro-labs/whatsapp/src/index.ts +40 -0
  253. package/runtime/node_modules/@metro-labs/whatsapp/src/keys.ts +59 -0
  254. package/runtime/node_modules/@metro-labs/whatsapp/src/logger.ts +60 -0
  255. package/runtime/node_modules/@metro-labs/whatsapp/src/login.ts +176 -0
  256. package/runtime/node_modules/@metro-labs/whatsapp/src/media.ts +84 -0
  257. package/runtime/node_modules/@metro-labs/whatsapp/src/normalize.ts +22 -0
  258. package/runtime/node_modules/@metro-labs/whatsapp/src/outbox.ts +38 -0
  259. package/runtime/node_modules/@metro-labs/whatsapp/src/parse.ts +185 -0
  260. package/runtime/node_modules/@metro-labs/whatsapp/src/resolve.ts +52 -0
  261. package/runtime/node_modules/@metro-labs/whatsapp/src/station.ts +18 -0
  262. package/runtime/node_modules/@metro-labs/whatsapp/src/token-store.ts +98 -0
  263. package/runtime/node_modules/@metro-labs/whatsapp/src/types.ts +6 -0
  264. package/runtime/node_modules/@metro-labs/whatsapp/src/wire.ts +5 -0
  265. package/runtime/node_modules/@metro-labs/xmtp/package.json +33 -0
  266. package/runtime/node_modules/@metro-labs/xmtp/src/accounts.ts +112 -0
  267. package/runtime/node_modules/@metro-labs/xmtp/src/actions-close.ts +110 -0
  268. package/runtime/node_modules/@metro-labs/xmtp/src/actions-conv.ts +299 -0
  269. package/runtime/node_modules/@metro-labs/xmtp/src/actions-meta.ts +157 -0
  270. package/runtime/node_modules/@metro-labs/xmtp/src/actions-push.ts +87 -0
  271. package/runtime/node_modules/@metro-labs/xmtp/src/actions.ts +375 -0
  272. package/runtime/node_modules/@metro-labs/xmtp/src/attachments.ts +107 -0
  273. package/runtime/node_modules/@metro-labs/xmtp/src/codecs.ts +171 -0
  274. package/runtime/node_modules/@metro-labs/xmtp/src/conv-helpers.ts +239 -0
  275. package/runtime/node_modules/@metro-labs/xmtp/src/emit-core.ts +55 -0
  276. package/runtime/node_modules/@metro-labs/xmtp/src/emit-payloads.ts +335 -0
  277. package/runtime/node_modules/@metro-labs/xmtp/src/emit.ts +80 -0
  278. package/runtime/node_modules/@metro-labs/xmtp/src/group-members.ts +34 -0
  279. package/runtime/node_modules/@metro-labs/xmtp/src/group.ts +56 -0
  280. package/runtime/node_modules/@metro-labs/xmtp/src/identity.ts +33 -0
  281. package/runtime/node_modules/@metro-labs/xmtp/src/index.ts +125 -0
  282. package/runtime/node_modules/@metro-labs/xmtp/src/labels.ts +157 -0
  283. package/runtime/node_modules/@metro-labs/xmtp/src/member-args.ts +40 -0
  284. package/runtime/node_modules/@metro-labs/xmtp/src/push.ts +349 -0
  285. package/runtime/node_modules/@metro-labs/xmtp/src/station.ts +13 -0
  286. package/runtime/node_modules/@metro-labs/xmtp/src/tools-handlers.ts +126 -0
  287. package/runtime/node_modules/@metro-labs/xmtp/src/tools.ts +212 -0
  288. package/runtime/node_modules/@metro-labs/xmtp/src/transcribe.ts +90 -0
  289. package/runtime/node_modules/@metro-labs/xmtp/src/verify.ts +84 -0
  290. package/runtime/node_modules/@metro-labs/xmtp/src/wire.ts +53 -0
  291. package/runtime/runtime.json +3 -0
  292. package/runtime/server.ts +1 -0
  293. package/runtime/stations.json +39 -0
  294. package/runtime/trains/.keep +0 -0
  295. package/LICENSE +0 -21
  296. package/README.md +0 -252
  297. package/dist/broker.js +0 -202
  298. package/dist/cache.js +0 -69
  299. package/dist/cli/actions.js +0 -206
  300. package/dist/cli/config.js +0 -185
  301. package/dist/cli/index.js +0 -188
  302. package/dist/cli/skill.js +0 -62
  303. package/dist/cli/tail.js +0 -164
  304. package/dist/cli/util.js +0 -72
  305. package/dist/cli/webhook.js +0 -81
  306. package/dist/codex-rc.js +0 -245
  307. package/dist/dispatcher.js +0 -128
  308. package/dist/history.js +0 -121
  309. package/dist/ipc.js +0 -72
  310. package/dist/log.js +0 -15
  311. package/dist/monitor.js +0 -194
  312. package/dist/paths.js +0 -68
  313. package/dist/registry.js +0 -48
  314. package/dist/stations/claude.js +0 -45
  315. package/dist/stations/codex.js +0 -68
  316. package/dist/stations/discord.js +0 -216
  317. package/dist/stations/index.js +0 -129
  318. package/dist/stations/telegram-md.js +0 -34
  319. package/dist/stations/telegram-upload.js +0 -113
  320. package/dist/stations/telegram.js +0 -234
  321. package/dist/stations/webhook.js +0 -103
  322. package/dist/tunnel.js +0 -64
  323. package/dist/webhooks.js +0 -41
  324. package/docs/broker.md +0 -214
  325. package/docs/monitor.md +0 -163
  326. package/docs/uri-scheme.md +0 -124
  327. package/docs/users.md +0 -226
  328. package/skills/metro/SKILL.md +0 -256
package/dist/cli/index.js DELETED
@@ -1,188 +0,0 @@
1
- #!/usr/bin/env node
2
- /** Metro CLI entry: parses argv, dispatches to subcommands, owns action + info commands. */
3
- import pkg from '../../package.json' with { type: 'json' };
4
- import { errMsg } from '../log.js';
5
- import { listLines } from '../cache.js';
6
- import { fmtCapabilities, listStations } from '../stations/index.js';
7
- import { listUsers } from '../registry.js';
8
- import { loadMetroEnv } from '../paths.js';
9
- import { readHistory } from '../history.js';
10
- import { cmdDoctor, cmdSetup, cmdUpdate } from './config.js';
11
- import { cmdDownload, cmdEdit, cmdFetch, cmdReact, cmdReply, cmdSend, } from './actions.js';
12
- import { cmdClaim, cmdClaims, cmdRelease, cmdTail } from './tail.js';
13
- import { cmdTunnel, cmdWebhook } from './webhook.js';
14
- import { flagOne, isJson, parseArgs, writeJson, } from './util.js';
15
- const USAGE = `metro — Telegram + Discord stream for your Claude Code / Codex user
16
-
17
- Usage:
18
- metro Run the dispatcher (emits JSON events on stdout).
19
- metro setup [telegram|discord <token>] Save token, or show status with no args.
20
- metro setup clear [telegram|discord|all] Remove tokens.
21
- metro setup skill [clear] Install the metro skill into ~/.claude / ~/.codex.
22
- metro doctor Health check.
23
- metro stations List stations + capabilities.
24
- metro lines List recently-seen conversations.
25
- metro send <line> <text> [--image=<path>]… [--document=<path>]… [--voice=<path>] [--buttons=<json>] [--no-claim] [--claim]
26
- Post a fresh message; repeat --image/--document for multi-file albums.
27
- First outbound on a DM auto-claims; --no-claim or METRO_NO_AUTO_CLAIM=1 opts out;
28
- --claim forces auto-claim even on group/public lines.
29
- Note: send/reply/edit/react read bot tokens from ~/.config/metro/.env and post
30
- directly to the platform — METRO_STATE_DIR isolates claims/history but NOT creds.
31
- metro reply <line> <message_id> <text> [--image=… --document=… --voice=… --buttons=…] [--no-claim] [--claim]
32
- Threaded reply (same flags as send).
33
- metro edit <line> <message_id> <text> [--buttons=<json>] [--no-claim] [--claim]
34
- Edit a previously-sent message (text + buttons).
35
- metro react <line> <message_id> <emoji> [--no-claim] [--claim]
36
- Set or clear ('') a reaction.
37
- metro download <line> <message_id> [--out=<dir>]
38
- Download image attachments to disk.
39
- metro fetch <line> [--limit=N] Recent-message lookback (Discord only).
40
- metro history [--limit=N] [--line=…] [--station=…] [--kind=…] [--from=…] [--text=…] [--since=…]
41
- Read the universal message log (newest first).
42
- metro tail [--as=<user-uri>] [--follow] [--strict | --unclaimed | --all] [--include-webhooks]
43
- [--chat=<line>] [--station=…] [--since=<offset|tail>] [--limit=N]
44
- Subscribe to the event log; claim-aware by default. See docs/broker.md.
45
- Webhooks are hidden in personal modes unless --include-webhooks is set.
46
- metro claim <line> [--as=<user-uri>] Take exclusive ownership of a line (so only you receive its events).
47
- metro release <line> Release a line (it returns to broadcast).
48
- metro claims Print the current claims map.
49
- metro webhook add <label> [--secret=…] Register an HTTP receive endpoint (GitHub, Intercom, …).
50
- metro webhook list | remove <id> List or remove webhook endpoints.
51
- metro tunnel setup <name> <hostname> Configure a Cloudflare named tunnel (run cloudflared tunnel login first).
52
- metro tunnel status Show current tunnel config.
53
- metro update Upgrade in place.
54
- metro --version | --help
55
-
56
- Lines: metro://<station>/<path>. See docs/uri-scheme.md.
57
- Multi-line --text: pipe on stdin in place of the positional arg.
58
- Exit codes: 0 success · 1 usage · 2 config · 3 upstream
59
- `;
60
- async function cmdStations(_, f) {
61
- loadMetroEnv();
62
- const rows = listStations();
63
- const usersByStation = {
64
- claude: listUsers('claude'),
65
- codex: listUsers('codex'),
66
- };
67
- if (isJson(f))
68
- return writeJson({ stations: rows, users: usersByStation });
69
- process.stdout.write('metro stations\n\n');
70
- for (const s of rows) {
71
- const mark = s.configured === true ? '✓' : s.configured === false ? '✗' : '·';
72
- process.stdout.write(` ${mark} ${s.name.padEnd(10)} ${fmtCapabilities(s.capabilities)}\n ${s.detail}\n`);
73
- const seen = usersByStation[s.name] ?? [];
74
- for (const inst of seen) {
75
- const sessionsTxt = inst.sessions.length ? ` · sessions: ${inst.sessions.length}` : '';
76
- process.stdout.write(` seen: ${inst.userId}${sessionsTxt}\n`);
77
- }
78
- }
79
- process.stdout.write('\n');
80
- }
81
- async function cmdLines(_, f) {
82
- loadMetroEnv();
83
- const rows = listLines()
84
- .map(({ line, entry }) => ({ line, name: entry.name ?? null, lastSeenAt: entry.lastSeenAt ?? null }))
85
- .sort((a, b) => (b.lastSeenAt ?? '').localeCompare(a.lastSeenAt ?? ''));
86
- if (isJson(f))
87
- return writeJson({ lines: rows });
88
- if (!rows.length)
89
- return void process.stdout.write('metro lines\n\n (none yet — start the dispatcher and send a message)\n\n');
90
- const widest = Math.max(...rows.map(r => r.line.length));
91
- process.stdout.write('metro lines\n\n');
92
- for (const r of rows) {
93
- const when = r.lastSeenAt ? humanAgo(r.lastSeenAt) : '—';
94
- const tag = r.name ? ` ${r.name.slice(0, 40)}${r.name.length > 40 ? '…' : ''}` : '';
95
- process.stdout.write(` ${when.padEnd(10)} ${r.line.padEnd(widest)}${tag}\n`);
96
- }
97
- process.stdout.write('\n');
98
- }
99
- function humanAgo(iso) {
100
- const sec = Math.max(0, Math.floor((Date.now() - new Date(iso).getTime()) / 1000));
101
- if (sec < 60)
102
- return `${sec}s ago`;
103
- if (sec < 3600)
104
- return `${Math.floor(sec / 60)}m ago`;
105
- if (sec < 86400)
106
- return `${Math.floor(sec / 3600)}h ago`;
107
- return `${Math.floor(sec / 86400)}d ago`;
108
- }
109
- async function cmdHistory(_, f) {
110
- loadMetroEnv();
111
- const since = flagOne(f, 'since');
112
- const entries = readHistory({
113
- line: flagOne(f, 'line'),
114
- station: flagOne(f, 'station'),
115
- kind: flagOne(f, 'kind'),
116
- from: flagOne(f, 'from'),
117
- textContains: flagOne(f, 'text'),
118
- since: since ? new Date(since) : undefined,
119
- limit: Number(flagOne(f, 'limit')) || 50,
120
- });
121
- if (isJson(f))
122
- return writeJson({ entries });
123
- if (!entries.length) {
124
- process.stdout.write('(no matching history entries)\n');
125
- return;
126
- }
127
- process.stdout.write('time id kind from → to body\n');
128
- for (const e of entries.reverse()) {
129
- const ts = e.ts.slice(11, 19);
130
- const from = pad(fmtActor(e.from, e.fromName), 24);
131
- const to = pad(fmtActor(e.to), 24);
132
- const body = e.text ?? (e.emoji ? `[react ${e.emoji}]` : '');
133
- const text = body.length > 60 ? body.slice(0, 59) + '…' : body;
134
- process.stdout.write(`${ts} ${e.id.padEnd(12)} ${e.kind.padEnd(12)} ${from} → ${to} ${text}\n`);
135
- }
136
- }
137
- /** Compact display: fromName if known; else `station:@<id>` (user) or `station:<id>`. */
138
- function fmtActor(uri, name) {
139
- if (name)
140
- return name;
141
- const m = uri.match(/^metro:\/\/([^/]+)(?:\/(?:(user)\/)?(.*))?$/);
142
- if (!m)
143
- return uri;
144
- const [, station, kind, rest] = m;
145
- if (kind === 'user')
146
- return `${station}:@${shortId(rest ?? '')}`;
147
- return rest ? `${station}:${shortId(rest)}` : station;
148
- }
149
- const shortId = (s) => s.length <= 12 ? s : `${s.slice(0, 5)}…${s.slice(-4)}`;
150
- const pad = (s, n) => (s.length > n ? `${s.slice(0, n - 1)}…` : s.padEnd(n));
151
- const COMMANDS = {
152
- setup: cmdSetup, doctor: cmdDoctor, stations: cmdStations, lines: cmdLines,
153
- send: cmdSend, reply: cmdReply, edit: cmdEdit, react: cmdReact,
154
- download: cmdDownload, fetch: cmdFetch,
155
- webhook: cmdWebhook, tunnel: cmdTunnel,
156
- history: cmdHistory, tail: cmdTail,
157
- claim: cmdClaim, release: cmdRelease, claims: cmdClaims,
158
- update: cmdUpdate,
159
- };
160
- async function main() {
161
- const cmd = process.argv[2];
162
- if (cmd === '--version' || cmd === '-v')
163
- return void process.stdout.write(`${pkg.version}\n`);
164
- if (cmd === '--help' || cmd === '-h')
165
- return void process.stdout.write(USAGE);
166
- if (!cmd) {
167
- await import('../dispatcher.js');
168
- return;
169
- }
170
- const handler = COMMANDS[cmd];
171
- if (!handler) {
172
- process.stderr.write(`unknown command '${cmd}'\n\n${USAGE}`);
173
- process.exit(1);
174
- }
175
- const { positional, flags } = parseArgs(process.argv.slice(3));
176
- try {
177
- await handler(positional, flags);
178
- }
179
- catch (err) {
180
- const code = err.code;
181
- if (isJson(flags))
182
- writeJson({ ok: false, error: errMsg(err), code: code ?? 1 });
183
- else
184
- process.stderr.write(`error: ${errMsg(err)}\n`);
185
- process.exit(typeof code === 'number' ? code : 1);
186
- }
187
- }
188
- await main();
package/dist/cli/skill.js DELETED
@@ -1,62 +0,0 @@
1
- /** `metro setup skill` — install the bundled SKILL.md into each detected user runtime. */
2
- import { copyFileSync, existsSync, mkdirSync, unlinkSync } from 'node:fs';
3
- import { homedir } from 'node:os';
4
- import { dirname, join } from 'node:path';
5
- import { fileURLToPath } from 'node:url';
6
- import { errMsg } from '../log.js';
7
- import { emit, exitErr } from './util.js';
8
- const RUNTIME_DIRS = {
9
- 'claude-code': join(homedir(), '.claude', 'skills', 'metro'),
10
- codex: join(homedir(), '.codex', 'skills', 'metro'),
11
- };
12
- /** dist/cli/skill.js → <package-root>/skills/metro/SKILL.md */
13
- const bundledPath = () => join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'skills', 'metro', 'SKILL.md');
14
- const dest = (r) => join(RUNTIME_DIRS[r], 'SKILL.md');
15
- export const skillStatus = () => ({
16
- 'claude-code': existsSync(dest('claude-code')),
17
- codex: existsSync(dest('codex')),
18
- });
19
- export async function cmdSetupSkill(p, f) {
20
- const [sub] = p;
21
- if (sub === 'clear')
22
- return clear(f);
23
- if (sub && sub !== 'install')
24
- throw exitErr(`unknown skill subcommand '${sub}' (try: install, clear)`, 1);
25
- return install(f);
26
- }
27
- function install(f) {
28
- const src = bundledPath();
29
- if (!existsSync(src))
30
- throw exitErr(`bundled SKILL.md missing at ${src} (broken install?)`, 2);
31
- const installed = [];
32
- for (const r of Object.keys(RUNTIME_DIRS)) {
33
- if (!existsSync(join(homedir(), r === 'claude-code' ? '.claude' : '.codex')))
34
- continue;
35
- try {
36
- mkdirSync(RUNTIME_DIRS[r], { recursive: true });
37
- copyFileSync(src, dest(r));
38
- installed.push(dest(r));
39
- }
40
- catch (err) {
41
- throw exitErr(`failed to install skill for ${r}: ${errMsg(err)}`, 2);
42
- }
43
- }
44
- if (!installed.length) {
45
- throw exitErr('no user runtime detected (~/.claude or ~/.codex). Install one and rerun.', 2);
46
- }
47
- emit(f, `installed metro skill → ${installed.join(', ')}`, { ok: true, installed });
48
- }
49
- function clear(f) {
50
- const removed = [];
51
- for (const r of Object.keys(RUNTIME_DIRS)) {
52
- const path = dest(r);
53
- if (existsSync(path)) {
54
- try {
55
- unlinkSync(path);
56
- removed.push(path);
57
- }
58
- catch { /* ignore */ }
59
- }
60
- }
61
- emit(f, removed.length ? `removed metro skill from ${removed.join(', ')}` : 'no installed skill found', { ok: true, removed });
62
- }
package/dist/cli/tail.js DELETED
@@ -1,164 +0,0 @@
1
- /** CLI subcommands: `metro tail` (claim-aware log subscriber) + `metro claim|release|claims`. */
2
- import { existsSync, watch } from 'node:fs';
3
- import { CLAIMS_FILE, HISTORY_FILE, claimLine, cursorKey, historySize, passesMode, readClaims, readCursor, readEntriesFrom, releaseLine, writeCursor, } from '../broker.js';
4
- import { userSelf } from '../history.js';
5
- import { asLine } from '../stations/index.js';
6
- import { loadMetroEnv } from '../paths.js';
7
- import { emit, exitErr, flagOne, isJson, need, writeJson } from './util.js';
8
- function resolveMode(f, self) {
9
- const strict = f.strict === true, unclaimed = f.unclaimed === true, all = f.all === true;
10
- if ([strict, unclaimed, all].filter(Boolean).length > 1) {
11
- throw exitErr('--strict, --unclaimed, --all are mutually exclusive', 1);
12
- }
13
- if (strict) {
14
- if (!self)
15
- throw exitErr('--strict requires --as <user-uri>', 1);
16
- return 'mine-only';
17
- }
18
- if (unclaimed)
19
- return 'unclaimed';
20
- if (all || !self)
21
- return 'all';
22
- return 'mine-or-unclaimed';
23
- }
24
- /** Generic fallback returned by `userSelf()` when there's no Claude/Codex env — treat as "no identity". */
25
- const GENERIC_USER = 'metro://user';
26
- function resolveSelf(f) {
27
- const raw = flagOne(f, 'as');
28
- if (raw !== undefined)
29
- return asLine(raw);
30
- const auto = userSelf();
31
- return auto === GENERIC_USER ? null : auto;
32
- }
33
- function resolveStartOffset(f, key) {
34
- const since = flagOne(f, 'since');
35
- if (since === 'tail')
36
- return historySize();
37
- if (since !== undefined) {
38
- const n = Number(since);
39
- if (!Number.isFinite(n) || n < 0)
40
- throw exitErr(`--since must be a byte offset or 'tail' (got '${since}')`, 1);
41
- return n;
42
- }
43
- return key ? readCursor(key) : 0;
44
- }
45
- export async function cmdTail(_, f) {
46
- loadMetroEnv();
47
- const self = resolveSelf(f);
48
- const mode = resolveMode(f, self);
49
- const follow = f.follow === true;
50
- const chatFilter = flagOne(f, 'chat');
51
- const stationFilter = flagOne(f, 'station');
52
- const limit = Number(flagOne(f, 'limit')) || 0;
53
- const json = isJson(f);
54
- const includeWebhooks = f['include-webhooks'] === true;
55
- /** Cursor key derives from the effective mode (not userSelf), so `--all` / `--unclaimed` */
56
- /** don't trample the personal `--as=<me>` cursor in a CLAUDECODE shell. */
57
- const key = cursorKey(mode, self, { includeWebhooks });
58
- const startOffset = resolveStartOffset(f, key);
59
- let emitted = 0;
60
- let offset = startOffset;
61
- const drain = () => {
62
- /** read claims once per drain so a burst of events shares a snapshot */
63
- const claims = readClaims();
64
- for (const { entry, offset: next } of readEntriesFrom(offset)) {
65
- offset = next;
66
- if (chatFilter && entry.line !== chatFilter)
67
- continue;
68
- if (stationFilter && entry.station !== stationFilter)
69
- continue;
70
- if (!passesMode(entry, mode, self, claims, { includeWebhooks }))
71
- continue;
72
- if (json)
73
- process.stdout.write(JSON.stringify(entry) + '\n');
74
- else
75
- process.stdout.write(fmtRow(entry) + '\n');
76
- if (key)
77
- writeCursor(key, offset);
78
- emitted++;
79
- if (limit && emitted >= limit)
80
- return true;
81
- }
82
- return false;
83
- };
84
- if (drain() && !follow)
85
- return;
86
- if (!follow)
87
- return;
88
- /** fs.watch on macOS sometimes coalesces or drops events — poll every 500ms as a backstop. */
89
- await new Promise(resolve => {
90
- let watcher = null;
91
- const trigger = () => { if (drain())
92
- cleanup(); };
93
- const cleanup = () => {
94
- if (watcher) {
95
- try {
96
- watcher.close();
97
- }
98
- catch { /* ignore */ }
99
- watcher = null;
100
- }
101
- clearInterval(poll);
102
- resolve();
103
- };
104
- const poll = setInterval(trigger, 500);
105
- const startWatcher = () => {
106
- if (!existsSync(HISTORY_FILE))
107
- return;
108
- try {
109
- watcher = watch(HISTORY_FILE, () => trigger());
110
- }
111
- catch { /* ignore — poll will catch */ }
112
- };
113
- startWatcher();
114
- process.on('SIGINT', cleanup);
115
- process.on('SIGTERM', cleanup);
116
- process.stdin.on('end', cleanup).on('close', cleanup);
117
- });
118
- }
119
- function fmtRow(e) {
120
- const ts = e.ts.slice(11, 19);
121
- const body = e.text ?? (e.emoji ? `[react ${e.emoji}]` : '');
122
- const text = body.length > 80 ? body.slice(0, 79) + '…' : body;
123
- const who = (e.fromName ?? e.from).padEnd(28).slice(0, 28);
124
- const where = e.line.padEnd(40).slice(0, 40);
125
- return `${ts} ${e.id.padEnd(12)} ${e.kind.padEnd(8)} ${who} ${where} ${text}`;
126
- }
127
- export async function cmdClaim(p, f) {
128
- loadMetroEnv();
129
- need(p, 1, 'metro claim <line> [--as <user-uri>]');
130
- const line = asLine(p[0]);
131
- const asRaw = flagOne(f, 'as');
132
- const owner = asRaw ? asLine(asRaw) : userSelf();
133
- const claims = claimLine(line, owner);
134
- emit(f, `claimed ${line} → ${owner}`, { ok: true, line, owner, claims });
135
- }
136
- export async function cmdRelease(p, f) {
137
- loadMetroEnv();
138
- need(p, 1, 'metro release <line>');
139
- const line = asLine(p[0]);
140
- const { released, claims } = releaseLine(line);
141
- if (!released) {
142
- emit(f, `${line} was not claimed`, { ok: true, released: false, line, claims });
143
- return;
144
- }
145
- emit(f, `released ${line}`, { ok: true, released: true, line, claims });
146
- }
147
- export async function cmdClaims(_, f) {
148
- loadMetroEnv();
149
- const claims = readClaims();
150
- const entries = Object.entries(claims);
151
- if (isJson(f))
152
- return writeJson({ claims });
153
- if (!entries.length) {
154
- process.stdout.write('(no claims — every tail with matching filters receives every event)\n');
155
- process.stdout.write(`file: ${CLAIMS_FILE}${existsSync(CLAIMS_FILE) ? '' : ' (not created yet)'}\n`);
156
- return;
157
- }
158
- const widest = Math.max(...entries.map(([l]) => l.length));
159
- process.stdout.write('metro claims\n\n');
160
- for (const [line, owner] of entries) {
161
- process.stdout.write(` ${line.padEnd(widest)} → ${owner}\n`);
162
- }
163
- process.stdout.write(`\n${entries.length} claim${entries.length === 1 ? '' : 's'} · ${CLAIMS_FILE}\n`);
164
- }
package/dist/cli/util.js DELETED
@@ -1,72 +0,0 @@
1
- /** Shared CLI primitives consumed by index.ts + config.ts. */
2
- export const exitErr = (msg, code) => Object.assign(new Error(msg), { code });
3
- export const isJson = (f) => f.json === true;
4
- export const writeJson = (obj) => void process.stdout.write(JSON.stringify(obj) + '\n');
5
- export const emit = (f, human, structured) => isJson(f) ? writeJson(structured) : void process.stdout.write(human + '\n');
6
- export const need = (positional, min, usage) => {
7
- if (positional.length < min)
8
- throw exitErr(`usage: ${usage}`, 1);
9
- };
10
- /** Return the last string value for `key` (or undefined). */
11
- export function flagOne(f, key) {
12
- const v = f[key];
13
- if (typeof v === 'string')
14
- return v;
15
- if (Array.isArray(v) && v.length)
16
- return v[v.length - 1];
17
- return undefined;
18
- }
19
- /** Return all string values for `key`, also splitting comma-separated entries. */
20
- export function flagList(f, key) {
21
- const v = f[key];
22
- const raw = typeof v === 'string' ? [v] : Array.isArray(v) ? v : [];
23
- return raw.flatMap(s => s.split(',').map(p => p.trim()).filter(Boolean));
24
- }
25
- export function parseArgs(argv) {
26
- const positional = [], flags = {};
27
- const add = (k, val) => {
28
- const cur = flags[k];
29
- if (cur === undefined) {
30
- flags[k] = val;
31
- return;
32
- }
33
- if (typeof val === 'boolean') {
34
- flags[k] = val;
35
- return;
36
- }
37
- flags[k] = Array.isArray(cur) ? [...cur, val] : [cur, val];
38
- };
39
- for (let i = 0; i < argv.length; i++) {
40
- const a = argv[i];
41
- if (!a.startsWith('--')) {
42
- positional.push(a);
43
- continue;
44
- }
45
- const eq = a.indexOf('=');
46
- if (eq !== -1) {
47
- add(a.slice(2, eq), a.slice(eq + 1));
48
- continue;
49
- }
50
- const next = argv[i + 1];
51
- if (next !== undefined && !next.startsWith('--')) {
52
- add(a.slice(2), next);
53
- i++;
54
- }
55
- else
56
- add(a.slice(2), true);
57
- }
58
- return { positional, flags };
59
- }
60
- export async function resolveText(positional, from) {
61
- if (positional.length > from)
62
- return positional.slice(from).join(' ');
63
- if (process.stdin.isTTY)
64
- throw exitErr('text is required (or pipe text on stdin)', 1);
65
- const chunks = [];
66
- for await (const c of process.stdin)
67
- chunks.push(c);
68
- const stdin = Buffer.concat(chunks).toString('utf8').replace(/\n$/, '');
69
- if (!stdin)
70
- throw exitErr('text is required (or pipe text on stdin)', 1);
71
- return stdin;
72
- }
@@ -1,81 +0,0 @@
1
- /** CLI subcommands: `metro webhook add|list|remove` + `metro tunnel setup`. */
2
- import { spawnSync } from 'node:child_process';
3
- import { addEndpoint, listEndpoints, removeEndpoint, webhookPort } from '../webhooks.js';
4
- import { loadTunnelConfig, saveTunnelConfig } from '../tunnel.js';
5
- import { emit, exitErr, flagOne, isJson, need, writeJson } from './util.js';
6
- function urlFor(endpointId) {
7
- const t = loadTunnelConfig();
8
- return t ? `https://${t.hostname}/wh/${endpointId}` : `http://127.0.0.1:${webhookPort()}/wh/${endpointId}`;
9
- }
10
- export async function cmdWebhook(p, f) {
11
- const sub = p[0];
12
- if (sub === 'add')
13
- return cmdWebhookAdd(p.slice(1), f);
14
- if (sub === 'list' || sub === undefined)
15
- return cmdWebhookList(f);
16
- if (sub === 'remove' || sub === 'rm')
17
- return cmdWebhookRemove(p.slice(1), f);
18
- throw exitErr('usage: metro webhook [add <label> [--secret=…] | list | remove <id>]', 1);
19
- }
20
- async function cmdWebhookAdd(p, f) {
21
- need(p, 1, 'metro webhook add <label> [--secret=<shared-secret>]');
22
- const ep = addEndpoint(p[0], flagOne(f, 'secret'));
23
- const url = urlFor(ep.id);
24
- emit(f, `webhook ${ep.id} (${ep.label}) → ${url}${ep.secret ? `\nshared secret: ${ep.secret}` : ''}`, { ok: true, endpoint: ep, url });
25
- }
26
- async function cmdWebhookList(f) {
27
- const eps = listEndpoints().map(ep => ({ ...ep, url: urlFor(ep.id) }));
28
- if (isJson(f))
29
- return writeJson({ endpoints: eps });
30
- if (!eps.length)
31
- return void process.stdout.write('metro webhooks\n\n (none — run `metro webhook add <label>`)\n\n');
32
- process.stdout.write('metro webhooks\n\n');
33
- for (const ep of eps) {
34
- process.stdout.write(` ${ep.id} ${ep.label}${ep.secret ? ' (signed)' : ''}\n ${ep.url}\n`);
35
- }
36
- process.stdout.write('\n');
37
- }
38
- async function cmdWebhookRemove(p, f) {
39
- need(p, 1, 'metro webhook remove <id>');
40
- const ok = removeEndpoint(p[0]);
41
- if (!ok)
42
- throw exitErr(`no webhook with id "${p[0]}"`, 1);
43
- emit(f, `removed webhook ${p[0]}`, { ok: true, id: p[0] });
44
- }
45
- export async function cmdTunnel(p, f) {
46
- const sub = p[0];
47
- if (sub === 'setup')
48
- return cmdTunnelSetup(p.slice(1), f);
49
- if (sub === 'status' || sub === undefined)
50
- return cmdTunnelStatus(f);
51
- throw exitErr('usage: metro tunnel [setup <name> <hostname> | status]', 1);
52
- }
53
- async function cmdTunnelSetup(p, f) {
54
- need(p, 2, 'metro tunnel setup <tunnel-name> <hostname> (e.g. `metro tunnel setup metro webhook.example.com`)');
55
- const [name, hostname] = p;
56
- if (!hasCloudflared()) {
57
- throw exitErr('cloudflared not on PATH — install with `brew install cloudflared` (or see https://developers.cloudflare.com/cloudflared/)', 2);
58
- }
59
- /** Idempotent: if tunnel exists, `tunnel create` errors with "already exists" — that's fine, continue. */
60
- run('cloudflared', ['tunnel', 'create', name], { allowFail: true });
61
- /** DNS route is also idempotent in newer cloudflared; older versions error if the CNAME exists. Same handling. */
62
- run('cloudflared', ['tunnel', 'route', 'dns', name, hostname], { allowFail: true });
63
- saveTunnelConfig({ name, hostname });
64
- emit(f, `tunnel saved: ${name} → ${hostname}\n` +
65
- 'first run: `cloudflared tunnel login` if you haven\'t (browser OAuth).\n' +
66
- 'then start metro — the daemon will spawn `cloudflared tunnel run` for you.', { ok: true, name, hostname });
67
- }
68
- async function cmdTunnelStatus(f) {
69
- const cfg = loadTunnelConfig();
70
- if (isJson(f))
71
- return writeJson({ configured: !!cfg, tunnel: cfg });
72
- if (!cfg)
73
- return void process.stdout.write('metro tunnel\n\n (not configured — run `metro tunnel setup <name> <hostname>`)\n\n');
74
- process.stdout.write(`metro tunnel\n\n name: ${cfg.name}\n hostname: ${cfg.hostname}\n\n`);
75
- }
76
- const hasCloudflared = () => spawnSync('cloudflared', ['--version'], { stdio: 'ignore' }).status === 0;
77
- function run(cmd, args, opts = {}) {
78
- const r = spawnSync(cmd, args, { stdio: 'inherit' });
79
- if (r.status !== 0 && !opts.allowFail)
80
- throw exitErr(`${cmd} ${args.join(' ')} exited ${r.status}`, 2);
81
- }