@stage-labs/metro 0.1.0-beta.76 → 0.1.0-beta.78

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 (233) hide show
  1. package/dist/cli.js +4 -4
  2. package/dist/runtime-install.js +7 -4
  3. package/dist/runtime.js +6 -2
  4. package/dist/serve.js +2 -3
  5. package/dist/service.js +29 -11
  6. package/package.json +1 -1
  7. package/runtime/node_modules/@metro-labs/core/package.json +43 -0
  8. package/runtime/node_modules/@metro-labs/core/src/endpoints.ts +7 -0
  9. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/events.ts +1 -1
  10. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/identity.ts +1 -1
  11. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/protocol.ts +1 -1
  12. package/runtime/node_modules/@metro-labs/{mcp → core}/src/stations/account-store.ts +2 -2
  13. package/runtime/node_modules/@metro-labs/{mcp → core}/src/stations/station-runtime.ts +1 -1
  14. package/runtime/node_modules/@metro-labs/daemon/package.json +47 -0
  15. package/runtime/node_modules/@metro-labs/{mcp/src/db → daemon/src/agents}/account-attach.ts +1 -1
  16. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/account-api.ts → daemon/src/agents/accounts-api.ts} +6 -6
  17. package/runtime/node_modules/@metro-labs/{mcp/src/db/agent-admin.ts → daemon/src/agents/admin.ts} +2 -2
  18. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/agent-api.ts → daemon/src/agents/api.ts} +6 -6
  19. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/bundle-api.ts → daemon/src/agents/bundle.ts} +7 -7
  20. package/runtime/node_modules/@metro-labs/{mcp/src/db → daemon/src/agents}/file-admin.ts +9 -9
  21. package/runtime/node_modules/@metro-labs/{mcp/src/db/file-source.ts → daemon/src/agents/files.ts} +4 -4
  22. package/runtime/node_modules/@metro-labs/{mcp/src/db/key-map.ts → daemon/src/agents/keys.ts} +1 -1
  23. package/runtime/node_modules/@metro-labs/{mcp/src/db/agent-scope.ts → daemon/src/agents/scope.ts} +2 -2
  24. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/boot}/boot.ts +23 -51
  25. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/boot}/crash-guard.ts +1 -1
  26. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/boot}/local-owner.ts +2 -2
  27. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/boot}/paths.ts +1 -4
  28. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/addressed.ts +1 -1
  29. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/dedupe.ts +1 -1
  30. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/inbound.ts +1 -1
  31. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/pending.ts +1 -1
  32. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/relay.ts +1 -1
  33. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/claude-api.ts → daemon/src/claude/api.ts} +7 -7
  34. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/claude-files.ts → daemon/src/claude/files.ts} +2 -2
  35. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/claude-login.ts → daemon/src/claude/login.ts} +3 -3
  36. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/claude-settings.ts → daemon/src/claude/settings.ts} +4 -4
  37. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/connector-api.ts → daemon/src/connectors/api.ts} +6 -6
  38. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/local-cli-api.ts → daemon/src/connectors/cli-api.ts} +5 -5
  39. package/runtime/node_modules/@metro-labs/{mcp/src/db/connector-config.ts → daemon/src/connectors/config.ts} +4 -4
  40. package/runtime/node_modules/@metro-labs/{mcp/src/db/connectors.ts → daemon/src/connectors/model.ts} +3 -3
  41. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/connectors}/oauth-client.ts +2 -2
  42. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/connectors}/oauth-discovery.ts +2 -2
  43. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/connector-oauth-routes.ts → daemon/src/connectors/oauth-routes.ts} +6 -6
  44. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/connector-oauth.ts → daemon/src/connectors/oauth.ts} +3 -3
  45. package/runtime/node_modules/@metro-labs/{mcp/src/db/connector-relay.ts → daemon/src/connectors/relay-target.ts} +1 -1
  46. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/connectors}/relay.ts +4 -4
  47. package/runtime/node_modules/@metro-labs/{mcp/src/db/local-connectors.ts → daemon/src/connectors/store.ts} +12 -12
  48. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/connector-tools.ts → daemon/src/connectors/tools.ts} +1 -1
  49. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/connector-url.ts → daemon/src/connectors/url.ts} +1 -1
  50. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/connector-verify.ts → daemon/src/connectors/verify.ts} +5 -5
  51. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/files}/attach-grant.ts +3 -3
  52. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/files}/attach-owner.ts +3 -3
  53. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/files}/attach-serve.ts +5 -12
  54. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/files}/upload-api.ts +5 -5
  55. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/files}/upload-store.ts +2 -2
  56. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/bedrock.ts +1 -1
  57. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/codex-auth.ts +1 -1
  58. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/codex-device.ts +2 -2
  59. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/codex-stream.ts +1 -1
  60. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/codex-translate.ts +1 -1
  61. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/codex.ts +2 -2
  62. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/gateway.ts +2 -2
  63. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/gateway}/model-api.ts +12 -12
  64. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/model-config.ts +3 -3
  65. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/openrouter.ts +1 -1
  66. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/accounts.ts +3 -7
  67. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/call-tools.ts +3 -3
  68. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/channel-owner.ts +1 -1
  69. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/ctx.ts +4 -4
  70. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/frame-scope.ts +2 -2
  71. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/group-tools.ts +2 -2
  72. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/index.ts +1 -1
  73. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/member-tools.ts +2 -2
  74. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/request-identity.ts +1 -1
  75. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/session-registry.ts +2 -2
  76. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/session.ts +2 -2
  77. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/tool-dispatch.ts +4 -4
  78. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/upload-tool.ts +5 -5
  79. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/monitor/api.ts +5 -5
  80. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/net}/tunnel.ts +6 -10
  81. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/routes}/http.ts +15 -15
  82. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/identity-routes.ts → daemon/src/routes/identity.ts} +5 -5
  83. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/routes}/local-mode.ts +16 -16
  84. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/routes}/session-apis.ts +14 -20
  85. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/session-api.ts → daemon/src/routes/session.ts} +1 -1
  86. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/control-api.ts → daemon/src/server/control.ts} +3 -3
  87. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/machine-api.ts → daemon/src/server/machine.ts} +8 -8
  88. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/update-api.ts → daemon/src/server/update.ts} +5 -5
  89. package/runtime/node_modules/@metro-labs/daemon/src/server.ts +2 -0
  90. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/attach-resolve.ts +5 -3
  91. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/stations}/attach-session.ts +4 -4
  92. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/attach-xmtp.ts +1 -1
  93. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/attach.ts +3 -3
  94. package/runtime/node_modules/@metro-labs/{mcp/src/db → daemon/src/stations}/materialize.ts +9 -14
  95. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/registry.ts +2 -2
  96. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/stations}/runtime-deps.ts +4 -4
  97. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/stations}/supervisor-io.ts +2 -2
  98. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/stations}/supervisor.ts +4 -4
  99. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/stations}/train-call.ts +1 -1
  100. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/terminal-api.ts → daemon/src/terminal/api.ts} +4 -4
  101. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/terminal-ws.ts → daemon/src/terminal/socket.ts} +3 -3
  102. package/runtime/node_modules/@metro-labs/discord-bot/package.json +1 -1
  103. package/runtime/node_modules/@metro-labs/discord-bot/src/accounts.ts +2 -2
  104. package/runtime/node_modules/@metro-labs/discord-bot/src/actions.ts +3 -3
  105. package/runtime/node_modules/@metro-labs/discord-bot/src/attachments.ts +2 -2
  106. package/runtime/node_modules/@metro-labs/discord-bot/src/group.ts +2 -2
  107. package/runtime/node_modules/@metro-labs/discord-bot/src/index.ts +2 -2
  108. package/runtime/node_modules/@metro-labs/discord-bot/src/members.ts +2 -2
  109. package/runtime/node_modules/@metro-labs/discord-bot/src/send-files.ts +1 -1
  110. package/runtime/node_modules/@metro-labs/discord-bot/src/station.ts +1 -1
  111. package/runtime/node_modules/@metro-labs/discord-bot/src/voice-speak.ts +1 -1
  112. package/runtime/node_modules/@metro-labs/discord-bot/src/voice-transcribe.ts +1 -1
  113. package/runtime/node_modules/@metro-labs/discord-bot/src/voice.ts +1 -1
  114. package/runtime/node_modules/@metro-labs/discord-bot/src/wire.ts +1 -1
  115. package/runtime/node_modules/@metro-labs/http/package.json +33 -0
  116. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → http/src}/api-http.ts +1 -1
  117. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → http/src}/signed-identity.ts +1 -1
  118. package/runtime/node_modules/@metro-labs/telegram/package.json +1 -1
  119. package/runtime/node_modules/@metro-labs/telegram/src/accounts.ts +1 -1
  120. package/runtime/node_modules/@metro-labs/telegram/src/actions.ts +3 -3
  121. package/runtime/node_modules/@metro-labs/telegram/src/attachments.ts +1 -1
  122. package/runtime/node_modules/@metro-labs/telegram/src/client.ts +2 -2
  123. package/runtime/node_modules/@metro-labs/telegram/src/format.ts +1 -1
  124. package/runtime/node_modules/@metro-labs/telegram/src/group.ts +3 -3
  125. package/runtime/node_modules/@metro-labs/telegram/src/inbound.ts +1 -1
  126. package/runtime/node_modules/@metro-labs/telegram/src/index.ts +3 -3
  127. package/runtime/node_modules/@metro-labs/telegram/src/media-actions.ts +1 -1
  128. package/runtime/node_modules/@metro-labs/telegram/src/members.ts +1 -1
  129. package/runtime/node_modules/@metro-labs/telegram/src/normalize.ts +1 -1
  130. package/runtime/node_modules/@metro-labs/telegram/src/reactions.ts +1 -1
  131. package/runtime/node_modules/@metro-labs/telegram/src/station.ts +1 -1
  132. package/runtime/node_modules/@metro-labs/telegram/src/wire.ts +1 -1
  133. package/runtime/node_modules/@metro-labs/telegram-bot/package.json +1 -1
  134. package/runtime/node_modules/@metro-labs/telegram-bot/src/accounts.ts +2 -2
  135. package/runtime/node_modules/@metro-labs/telegram-bot/src/actions.ts +4 -4
  136. package/runtime/node_modules/@metro-labs/telegram-bot/src/attachments.ts +2 -2
  137. package/runtime/node_modules/@metro-labs/telegram-bot/src/format.ts +1 -1
  138. package/runtime/node_modules/@metro-labs/telegram-bot/src/index.ts +2 -2
  139. package/runtime/node_modules/@metro-labs/telegram-bot/src/media-actions.ts +1 -1
  140. package/runtime/node_modules/@metro-labs/telegram-bot/src/members.ts +1 -1
  141. package/runtime/node_modules/@metro-labs/telegram-bot/src/station.ts +1 -1
  142. package/runtime/node_modules/@metro-labs/telegram-bot/src/wire.ts +1 -1
  143. package/runtime/node_modules/@metro-labs/webhook/package.json +1 -1
  144. package/runtime/node_modules/@metro-labs/webhook/src/station.ts +4 -4
  145. package/runtime/node_modules/@metro-labs/whatsapp/package.json +1 -1
  146. package/runtime/node_modules/@metro-labs/whatsapp/src/accounts.ts +1 -1
  147. package/runtime/node_modules/@metro-labs/whatsapp/src/ack.ts +1 -1
  148. package/runtime/node_modules/@metro-labs/whatsapp/src/actions.ts +4 -4
  149. package/runtime/node_modules/@metro-labs/whatsapp/src/attachments.ts +2 -2
  150. package/runtime/node_modules/@metro-labs/whatsapp/src/auth-state.ts +1 -1
  151. package/runtime/node_modules/@metro-labs/whatsapp/src/client.ts +2 -2
  152. package/runtime/node_modules/@metro-labs/whatsapp/src/format.ts +1 -1
  153. package/runtime/node_modules/@metro-labs/whatsapp/src/inbound.ts +1 -1
  154. package/runtime/node_modules/@metro-labs/whatsapp/src/index.ts +3 -3
  155. package/runtime/node_modules/@metro-labs/whatsapp/src/keys.ts +1 -1
  156. package/runtime/node_modules/@metro-labs/whatsapp/src/login.ts +1 -1
  157. package/runtime/node_modules/@metro-labs/whatsapp/src/media.ts +1 -1
  158. package/runtime/node_modules/@metro-labs/whatsapp/src/normalize.ts +1 -1
  159. package/runtime/node_modules/@metro-labs/whatsapp/src/station.ts +1 -1
  160. package/runtime/node_modules/@metro-labs/whatsapp/src/token-store.ts +2 -2
  161. package/runtime/node_modules/@metro-labs/whatsapp/src/wire.ts +1 -1
  162. package/runtime/node_modules/@metro-labs/xmtp/package.json +1 -1
  163. package/runtime/node_modules/@metro-labs/xmtp/src/accounts.ts +2 -2
  164. package/runtime/node_modules/@metro-labs/xmtp/src/actions-close.ts +1 -1
  165. package/runtime/node_modules/@metro-labs/xmtp/src/actions-conv.ts +1 -1
  166. package/runtime/node_modules/@metro-labs/xmtp/src/actions-meta.ts +1 -1
  167. package/runtime/node_modules/@metro-labs/xmtp/src/actions.ts +3 -3
  168. package/runtime/node_modules/@metro-labs/xmtp/src/attachments.ts +3 -3
  169. package/runtime/node_modules/@metro-labs/xmtp/src/conv-helpers.ts +2 -2
  170. package/runtime/node_modules/@metro-labs/xmtp/src/emit-payloads.ts +1 -1
  171. package/runtime/node_modules/@metro-labs/xmtp/src/emit.ts +1 -1
  172. package/runtime/node_modules/@metro-labs/xmtp/src/group-members.ts +1 -1
  173. package/runtime/node_modules/@metro-labs/xmtp/src/group.ts +2 -2
  174. package/runtime/node_modules/@metro-labs/xmtp/src/index.ts +2 -2
  175. package/runtime/node_modules/@metro-labs/xmtp/src/member-args.ts +1 -1
  176. package/runtime/node_modules/@metro-labs/xmtp/src/push.ts +2 -2
  177. package/runtime/node_modules/@metro-labs/xmtp/src/station.ts +1 -1
  178. package/runtime/node_modules/@metro-labs/xmtp/src/tools-handlers.ts +3 -3
  179. package/runtime/node_modules/@metro-labs/xmtp/src/tools.ts +1 -1
  180. package/runtime/node_modules/@metro-labs/xmtp/src/transcribe.ts +1 -1
  181. package/runtime/node_modules/@metro-labs/xmtp/src/wire.ts +1 -1
  182. package/runtime/runtime.json +1 -1
  183. package/runtime/server.ts +1 -0
  184. package/dist/bedrock-eventstream.js +0 -120
  185. package/dist/bedrock-proxy.js +0 -260
  186. package/dist/bedrock-upstream.js +0 -72
  187. package/dist/bedrock.js +0 -37
  188. package/runtime/node_modules/@metro-labs/mcp/package.json +0 -64
  189. package/runtime/node_modules/@metro-labs/mcp/src/daemon/server-types.ts +0 -21
  190. package/runtime/node_modules/@metro-labs/mcp/src/daemon/servers-api.ts +0 -80
  191. package/runtime/node_modules/@metro-labs/mcp/src/daemon/vault-api.ts +0 -78
  192. package/runtime/node_modules/@metro-labs/mcp/src/daemon/vault-types.ts +0 -12
  193. package/runtime/node_modules/@metro-labs/mcp/src/db/client.ts +0 -32
  194. package/runtime/node_modules/@metro-labs/mcp/src/db/schema.ts +0 -33
  195. package/runtime/node_modules/@metro-labs/mcp/src/db/servers.ts +0 -83
  196. package/runtime/node_modules/@metro-labs/mcp/src/db/vault.ts +0 -109
  197. package/runtime/node_modules/@metro-labs/mcp/src/server.ts +0 -2
  198. /package/runtime/node_modules/@metro-labs/{mcp/src/db → core/src}/address.ts +0 -0
  199. /package/runtime/node_modules/@metro-labs/{mcp/src/db → core/src}/ids.ts +0 -0
  200. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/is-record.ts +0 -0
  201. /package/runtime/node_modules/@metro-labs/{mcp/src/stations → core/src}/lines.ts +0 -0
  202. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/log.ts +0 -0
  203. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/secure-fs.ts +0 -0
  204. /package/runtime/node_modules/@metro-labs/{mcp/src/db/stations.ts → core/src/station-names.ts} +0 -0
  205. /package/runtime/node_modules/@metro-labs/{mcp → core}/src/stations/attachments.ts +0 -0
  206. /package/runtime/node_modules/@metro-labs/{mcp → core}/src/stations/messaging-normalize.ts +0 -0
  207. /package/runtime/node_modules/@metro-labs/{mcp → core}/src/stations/types.ts +0 -0
  208. /package/runtime/node_modules/@metro-labs/{mcp/src/mcp → core/src}/str.ts +0 -0
  209. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/train-error.ts +0 -0
  210. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/version.ts +0 -0
  211. /package/runtime/node_modules/@metro-labs/{mcp/src/db/agent-map.ts → daemon/src/agents/map.ts} +0 -0
  212. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/boot}/connect-hint.ts +0 -0
  213. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/media-note.ts +0 -0
  214. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/webhook-note.ts +0 -0
  215. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon/connector-json.ts → daemon/src/connectors/json.ts} +0 -0
  216. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/connectors}/oauth-pending.ts +0 -0
  217. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/eventstream.ts +0 -0
  218. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/forward.ts +0 -0
  219. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/served.ts +0 -0
  220. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/event-store.ts +0 -0
  221. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/permission-relay.ts +0 -0
  222. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/raw-get-stream.ts +0 -0
  223. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/session-route.ts +0 -0
  224. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/tool-schemas.ts +0 -0
  225. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/attach-inline.ts +0 -0
  226. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/attach-interactive.ts +0 -0
  227. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon/terminal-tickets.ts → daemon/src/terminal/tickets.ts} +0 -0
  228. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → http/src}/api-error.ts +0 -0
  229. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → http/src}/cors.ts +0 -0
  230. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → http/src}/identity-key.ts +0 -0
  231. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → http/src}/identity-registry.ts +0 -0
  232. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → http/src}/mode-api.ts +0 -0
  233. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → http/src}/return-to.ts +0 -0
@@ -1,260 +0,0 @@
1
- import { createServer, } from 'node:http';
2
- import { EventStreamDecoder } from './bedrock-eventstream.js';
3
- import { callBedrock, freshAdaptations, invoke, invokeUrl, upstreamMessage, } from './bedrock-upstream.js';
4
- export class BedrockConfigError extends Error {
5
- }
6
- class ProxyError extends Error {
7
- status;
8
- kind;
9
- constructor(status, kind, message) {
10
- super(message);
11
- this.status = status;
12
- this.kind = kind;
13
- }
14
- }
15
- const ANTHROPIC_VERSION = 'bedrock-2023-05-31';
16
- const BODY_MAX = 64 * 1024 * 1024;
17
- const MESSAGES_PATH = '/v1/messages';
18
- const COUNT_PATH = '/v1/messages/count_tokens';
19
- function firstEnv(env, names) {
20
- for (const name of names) {
21
- const value = env[name]?.trim() ?? '';
22
- if (value !== '')
23
- return value;
24
- }
25
- return '';
26
- }
27
- export function bedrockConfigFromEnv(env = process.env) {
28
- const bearerToken = firstEnv(env, ['AWS_BEARER_TOKEN_BEDROCK']);
29
- if (bearerToken === '')
30
- throw new BedrockConfigError('AWS_BEARER_TOKEN_BEDROCK is not set. Create an Amazon Bedrock API key in the AWS console (Bedrock → API keys) and export it.');
31
- const region = firstEnv(env, ['METRO_BEDROCK_REGION', 'AWS_REGION', 'AWS_DEFAULT_REGION']);
32
- if (region === '')
33
- throw new BedrockConfigError('no AWS region: set AWS_REGION (or METRO_BEDROCK_REGION) to the region your Bedrock API key belongs to');
34
- const model = firstEnv(env, ['METRO_BEDROCK_MODEL']);
35
- return { region, bearerToken, model: model === '' ? null : model };
36
- }
37
- const PREFIXES = [
38
- [/^us-gov-/, 'us-gov'],
39
- [/^us-/, 'us'],
40
- [/^eu-/, 'eu'],
41
- [/^ap-/, 'apac'],
42
- ];
43
- export function regionPrefix(region) {
44
- for (const [pattern, prefix] of PREFIXES)
45
- if (pattern.test(region))
46
- return prefix;
47
- return 'global';
48
- }
49
- export function mapModel(requested, cfg) {
50
- if (cfg.model !== null)
51
- return cfg.model;
52
- if (requested.includes('anthropic.'))
53
- return requested;
54
- return `${regionPrefix(cfg.region)}.anthropic.${requested}`;
55
- }
56
- export const upstreamBase = (cfg, override) => override ?? `https://bedrock-runtime.${cfg.region}.amazonaws.com`;
57
- function splitBetas(header) {
58
- const raw = Array.isArray(header) ? header.join(',') : (header ?? '');
59
- return raw
60
- .split(',')
61
- .map((b) => b.trim())
62
- .filter((b) => b !== '');
63
- }
64
- export function rewriteBody(raw, betaHeader, cfg) {
65
- if (typeof raw !== 'object' || raw === null || Array.isArray(raw))
66
- throw new ProxyError(400, 'invalid_request_error', 'body must be a JSON object');
67
- const { model, stream, ...rest } = raw;
68
- if (typeof model !== 'string' || model === '')
69
- throw new ProxyError(400, 'invalid_request_error', 'model is required');
70
- const betas = splitBetas(betaHeader);
71
- const body = { ...rest, anthropic_version: ANTHROPIC_VERSION };
72
- if (betas.length > 0)
73
- body.anthropic_beta = betas;
74
- return { modelId: mapModel(model, cfg), stream: stream === true, body, betas };
75
- }
76
- export function errorKind(status, errorType) {
77
- if (status === 429 || errorType === 'ThrottlingException')
78
- return 'rate_limit_error';
79
- if (status === 400)
80
- return 'invalid_request_error';
81
- if (status === 401)
82
- return 'authentication_error';
83
- if (status === 403)
84
- return 'permission_error';
85
- if (status === 404)
86
- return 'not_found_error';
87
- if (status === 503)
88
- return 'overloaded_error';
89
- return 'api_error';
90
- }
91
- function sendError(res, status, kind, message) {
92
- res.writeHead(status, { 'content-type': 'application/json' });
93
- res.end(JSON.stringify({ type: 'error', error: { type: kind, message } }));
94
- }
95
- async function readBody(req) {
96
- const chunks = [];
97
- let total = 0;
98
- for await (const chunk of req) {
99
- const buf = chunk;
100
- total += buf.length;
101
- if (total > BODY_MAX)
102
- throw new ProxyError(413, 'invalid_request_error', 'request too large');
103
- chunks.push(buf);
104
- }
105
- try {
106
- return JSON.parse(Buffer.concat(chunks).toString('utf8'));
107
- }
108
- catch {
109
- throw new ProxyError(400, 'invalid_request_error', 'body must be JSON');
110
- }
111
- }
112
- async function relayError(upstream, res) {
113
- const text = await upstream.text();
114
- const kind = errorKind(upstream.status, upstream.headers.get('x-amzn-errortype'));
115
- sendError(res, upstream.status, kind, upstreamMessage(text));
116
- }
117
- function eventTypeOf(event) {
118
- try {
119
- const parsed = JSON.parse(event);
120
- return typeof parsed.type === 'string' ? parsed.type : 'message';
121
- }
122
- catch {
123
- return 'message';
124
- }
125
- }
126
- function writeEvent(res, message) {
127
- if (message.headers[':message-type'] === 'event') {
128
- const parsed = JSON.parse(message.payload.toString('utf8'));
129
- if (typeof parsed.bytes !== 'string')
130
- return;
131
- const event = Buffer.from(parsed.bytes, 'base64').toString('utf8');
132
- res.write(`event: ${eventTypeOf(event)}\ndata: ${event}\n\n`);
133
- return;
134
- }
135
- const errorType = message.headers[':exception-type'] ?? message.headers[':error-code'] ?? null;
136
- const body = {
137
- type: 'error',
138
- error: {
139
- type: errorKind(500, errorType),
140
- message: upstreamMessage(message.payload.toString('utf8')),
141
- },
142
- };
143
- res.write(`event: error\ndata: ${JSON.stringify(body)}\n\n`);
144
- }
145
- async function relayStream(upstream, res) {
146
- res.writeHead(200, {
147
- 'content-type': 'text/event-stream',
148
- 'cache-control': 'no-store',
149
- connection: 'keep-alive',
150
- });
151
- const body = upstream.body;
152
- if (body === null) {
153
- res.end();
154
- return;
155
- }
156
- const decoder = new EventStreamDecoder();
157
- const reader = body.getReader();
158
- for (;;) {
159
- const { done, value } = await reader.read();
160
- if (done)
161
- break;
162
- for (const message of decoder.push(Buffer.from(value)))
163
- writeEvent(res, message);
164
- }
165
- res.end();
166
- }
167
- async function relayJson(upstream, res) {
168
- const text = await upstream.text();
169
- res.writeHead(200, { 'content-type': 'application/json' });
170
- res.end(text);
171
- }
172
- async function handleMessages(req, res, up) {
173
- const rewritten = rewriteBody(await readBody(req), req.headers['anthropic-beta'], up.cfg);
174
- const controller = new AbortController();
175
- res.on('close', () => {
176
- if (!res.writableEnded)
177
- controller.abort();
178
- });
179
- const upstream = await invoke(up, rewritten, controller.signal);
180
- if (!upstream.ok) {
181
- await relayError(upstream, res);
182
- return;
183
- }
184
- if (rewritten.stream)
185
- await relayStream(upstream, res);
186
- else
187
- await relayJson(upstream, res);
188
- }
189
- function estimateTokens(body) {
190
- return Math.ceil(JSON.stringify(body).length / 4);
191
- }
192
- async function handleCount(req, res, up) {
193
- const rewritten = rewriteBody(await readBody(req), req.headers['anthropic-beta'], up.cfg);
194
- const controller = new AbortController();
195
- const upstream = await callBedrock(up, invokeUrl(up, rewritten.modelId, 'count-tokens'), { input: { invokeModel: { body: JSON.stringify(rewritten.body) } } }, 'application/json', controller.signal);
196
- const text = await upstream.text();
197
- let counted = null;
198
- if (upstream.ok) {
199
- const parsed = JSON.parse(text);
200
- if (typeof parsed.inputTokens === 'number')
201
- counted = parsed.inputTokens;
202
- }
203
- res.writeHead(200, { 'content-type': 'application/json' });
204
- res.end(JSON.stringify({ input_tokens: counted ?? estimateTokens(rewritten.body) }));
205
- }
206
- function presentedToken(req) {
207
- const auth = req.headers.authorization ?? '';
208
- if (auth.toLowerCase().startsWith('bearer '))
209
- return auth.slice(7).trim();
210
- const key = req.headers['x-api-key'];
211
- return Array.isArray(key) ? (key[0] ?? '') : (key ?? '');
212
- }
213
- async function route(req, res, cfg, opts, learned) {
214
- if (presentedToken(req) !== opts.token)
215
- throw new ProxyError(401, 'authentication_error', 'unauthorized');
216
- const path = (req.url ?? '').split('?')[0] ?? '';
217
- const up = { cfg, base: upstreamBase(cfg, opts.upstream), learned };
218
- if (req.method === 'POST' && path === MESSAGES_PATH)
219
- return handleMessages(req, res, up);
220
- if (req.method === 'POST' && path === COUNT_PATH)
221
- return handleCount(req, res, up);
222
- throw new ProxyError(404, 'not_found_error', 'not found');
223
- }
224
- function failed(res, err) {
225
- if (res.headersSent) {
226
- res.end();
227
- return;
228
- }
229
- if (err instanceof ProxyError) {
230
- sendError(res, err.status, err.kind, err.message);
231
- return;
232
- }
233
- const message = err instanceof Error ? err.message : 'proxy failure';
234
- sendError(res, 502, 'api_error', `metro bedrock proxy: ${message}`);
235
- }
236
- export function startBedrockProxy(cfg, opts) {
237
- const learned = freshAdaptations();
238
- const server = createServer((req, res) => {
239
- route(req, res, cfg, opts, learned).catch((err) => {
240
- failed(res, err);
241
- });
242
- });
243
- return new Promise((resolve, reject) => {
244
- server.once('error', reject);
245
- server.listen(opts.port ?? 0, '127.0.0.1', () => {
246
- const address = server.address();
247
- const port = typeof address === 'object' && address !== null ? address.port : 0;
248
- resolve({
249
- port,
250
- server,
251
- learned,
252
- close: () => new Promise((done) => {
253
- server.close(() => {
254
- done();
255
- });
256
- }),
257
- });
258
- });
259
- });
260
- }
@@ -1,72 +0,0 @@
1
- export const freshAdaptations = () => ({
2
- fields: new Set(),
3
- dropBetas: false,
4
- });
5
- const EXTRA_INPUT_RE = /^([A-Za-z0-9_]+)(?:\.[^:]*)?: Extra inputs are not permitted/;
6
- const MAX_REPAIRS = 4;
7
- export function invokeUrl(up, modelId, action) {
8
- return `${up.base}/model/${encodeURIComponent(modelId)}/${action}`;
9
- }
10
- export function callBedrock(up, url, body, accept, signal) {
11
- return fetch(url, {
12
- method: 'POST',
13
- headers: {
14
- authorization: `Bearer ${up.cfg.bearerToken}`,
15
- 'content-type': 'application/json',
16
- accept,
17
- },
18
- body: JSON.stringify(body),
19
- signal,
20
- });
21
- }
22
- export function upstreamMessage(text) {
23
- const fallback = text === '' ? 'Bedrock returned no body' : text;
24
- try {
25
- const parsed = JSON.parse(text);
26
- const message = parsed.message ?? parsed.Message;
27
- return typeof message === 'string' && message !== '' ? message : fallback;
28
- }
29
- catch {
30
- return fallback;
31
- }
32
- }
33
- const without = (body, keys) => Object.fromEntries(Object.entries(body).filter(([key]) => !keys.has(key)));
34
- function applyLearned(req, learned) {
35
- const dropped = new Set(learned.fields);
36
- if (learned.dropBetas)
37
- dropped.add('anthropic_beta');
38
- return {
39
- body: without(req.body, dropped),
40
- betas: learned.dropBetas ? [] : req.betas,
41
- };
42
- }
43
- function repair(attempt, learned, message) {
44
- const named = EXTRA_INPUT_RE.exec(message)?.[1];
45
- if (named !== undefined && named in attempt.body) {
46
- learned.fields.add(named);
47
- process.stderr.write(`metro bedrock: Bedrock refused "${named}" (extra input); dropping it from every request\n`);
48
- return { body: without(attempt.body, new Set([named])), betas: attempt.betas };
49
- }
50
- if (attempt.betas.length > 0) {
51
- learned.dropBetas = true;
52
- process.stderr.write(`metro bedrock: retrying without anthropic_beta [${attempt.betas.join(', ')}]\n`);
53
- return { body: without(attempt.body, new Set(['anthropic_beta'])), betas: [] };
54
- }
55
- return null;
56
- }
57
- export async function invoke(up, req, signal) {
58
- const action = req.stream ? 'invoke-with-response-stream' : 'invoke';
59
- const accept = req.stream ? 'application/vnd.amazon.eventstream' : 'application/json';
60
- const url = invokeUrl(up, req.modelId, action);
61
- let attempt = applyLearned(req, up.learned);
62
- for (let repairs = 0;; repairs += 1) {
63
- const res = await callBedrock(up, url, attempt.body, accept, signal);
64
- if (res.status !== 400 || repairs >= MAX_REPAIRS)
65
- return res;
66
- const text = await res.text();
67
- const next = repair(attempt, up.learned, upstreamMessage(text));
68
- if (next === null)
69
- return new Response(text, { status: 400, headers: res.headers });
70
- attempt = next;
71
- }
72
- }
package/dist/bedrock.js DELETED
@@ -1,37 +0,0 @@
1
- import { randomBytes } from 'node:crypto';
2
- import { claudeArgs, runClaude } from './claude.js';
3
- import { bedrockConfigFromEnv, startBedrockProxy } from './bedrock-proxy.js';
4
- import { settingsConflicts, settingsFiles } from './claude-settings.js';
5
- import { PROVIDER_FLAGS } from './provider-flags.js';
6
- export { PROVIDER_FLAGS, settingsConflicts, settingsFiles };
7
- const SCRUBBED = [...PROVIDER_FLAGS, 'ANTHROPIC_API_KEY', 'AWS_BEARER_TOKEN_BEDROCK'];
8
- export function firstPartyModelId(bedrockId) {
9
- return bedrockId.replace(/^(?:[a-z-]+\.)?anthropic\./, '').replace(/-v\d+:\d+$/, '');
10
- }
11
- export function claudeEnv(base, port, token, pinned = null) {
12
- const kept = Object.entries(base).filter(([key]) => !SCRUBBED.includes(key));
13
- const model = (base.ANTHROPIC_MODEL ?? '').trim();
14
- return {
15
- ...Object.fromEntries(kept),
16
- ...(pinned !== null && model === '' && { ANTHROPIC_MODEL: firstPartyModelId(pinned) }),
17
- ANTHROPIC_BASE_URL: `http://127.0.0.1:${String(port)}`,
18
- ANTHROPIC_AUTH_TOKEN: token,
19
- };
20
- }
21
- export async function bedrock(argv) {
22
- const cfg = bedrockConfigFromEnv();
23
- const conflicts = settingsConflicts(settingsFiles());
24
- if (conflicts.length > 0)
25
- throw new Error('metro bedrock: these settings would put Claude Code back on a third-party provider, or override the proxy. Remove them, or point CLAUDE_CONFIG_DIR at a separate profile:\n ' +
26
- conflicts.join('\n '));
27
- const token = `mb_${randomBytes(18).toString('base64url')}`;
28
- const proxy = await startBedrockProxy(cfg, { token });
29
- const pinned = cfg.model === null ? '' : ` (${cfg.model})`;
30
- process.stderr.write(`metro bedrock: Claude Code → http://127.0.0.1:${String(proxy.port)} → Bedrock ${cfg.region}${pinned}\n`);
31
- try {
32
- return await runClaude(claudeArgs(argv), claudeEnv(process.env, proxy.port, token, cfg.model));
33
- }
34
- finally {
35
- await proxy.close();
36
- }
37
- }
@@ -1,64 +0,0 @@
1
- {
2
- "name": "@metro-labs/mcp",
3
- "version": "0.1.0-beta.15",
4
- "private": true,
5
- "description": "Event-interception wire. Supervises train subprocesses in ~/.metro/trains/, multiplexes their JSON event stream onto stdout, and routes outbound action calls back via stdin. Per-platform code is written by the agent (or user) as train scripts — metro core is pure transport.",
6
- "license": "MIT",
7
- "repository": {
8
- "type": "git",
9
- "url": "git+https://github.com/bonustrack/metro.git"
10
- },
11
- "homepage": "https://github.com/bonustrack/metro#readme",
12
- "bugs": "https://github.com/bonustrack/metro/issues",
13
- "type": "module",
14
- "engines": {
15
- "node": ">=22"
16
- },
17
- "exports": {
18
- ".": "./src/mcp/index.ts",
19
- "./log": "./src/daemon/log.ts",
20
- "./train-error": "./src/daemon/train-error.ts",
21
- "./secure-fs": "./src/daemon/secure-fs.ts",
22
- "./lines": "./src/stations/lines.ts",
23
- "./events": "./src/daemon/events.ts",
24
- "./endpoints": "./src/daemon/tunnel.ts",
25
- "./trains/protocol": "./src/daemon/protocol.ts",
26
- "./stations/types": "./src/stations/types.ts",
27
- "./stations/station-runtime": "./src/stations/station-runtime.ts",
28
- "./stations/account-store": "./src/stations/account-store.ts",
29
- "./stations/attachments": "./src/stations/attachments.ts",
30
- "./stations/messaging-normalize": "./src/stations/messaging-normalize.ts"
31
- },
32
- "scripts": {
33
- "start": "bun src/server.ts",
34
- "build": "tsc",
35
- "db:migrate": "drizzle-kit migrate",
36
- "test": "tsc --noEmit && DYLD_FALLBACK_LIBRARY_PATH=/usr/lib METRO_STATE_DIR=\"$(mktemp -d /tmp/metro-test.XXXXXX)\" bun test test/"
37
- },
38
- "dependencies": {
39
- "@metro-labs/discord-bot": "workspace:*",
40
- "@metro-labs/telegram": "workspace:*",
41
- "@metro-labs/telegram-bot": "workspace:*",
42
- "@metro-labs/webhook": "workspace:*",
43
- "@metro-labs/whatsapp": "workspace:*",
44
- "@metro-labs/xmtp": "workspace:*",
45
- "@modelcontextprotocol/sdk": "^1.12.0",
46
- "@noble/curves": "^1.9.7",
47
- "drizzle-kit": "^0.31.0",
48
- "drizzle-orm": "^0.44.0",
49
- "pino": "^9.5.0",
50
- "pino-pretty": "^13.1.3",
51
- "postgres": "^3.4.5",
52
- "viem": "2.52.2",
53
- "ws": "^8.18.0",
54
- "zod": "^3.23.8"
55
- },
56
- "devDependencies": {
57
- "@stage-labs/config": "0.1.0-beta.2",
58
- "@types/ws": "^8.18.0",
59
- "eslint": "^10.3.0",
60
- "knip": "^6.15.0",
61
- "madge": "^8.0.0",
62
- "typescript": "^5"
63
- }
64
- }
@@ -1,21 +0,0 @@
1
- export interface ServerEntry {
2
- id: string;
3
- host: string;
4
- name: string | null;
5
- addedAt: string;
6
- }
7
-
8
- const HOST_RE = /^[a-z0-9][a-z0-9.-]*(?::\d{1,5})?$/;
9
- const HOST_MAX = 253;
10
- const NAME_MAX = 40;
11
-
12
- export function parseServerHost(raw: string): string | null {
13
- const host = raw.trim().toLowerCase();
14
- return host.length <= HOST_MAX && HOST_RE.test(host) ? host : null;
15
- }
16
-
17
- export function parseServerName(raw: unknown): string | null {
18
- if (typeof raw !== 'string') return null;
19
- const name = raw.replace(/[\p{Cc}]/gu, '').trim().slice(0, NAME_MAX);
20
- return name === '' ? null : name;
21
- }
@@ -1,80 +0,0 @@
1
- import type { IncomingMessage, ServerResponse } from 'node:http';
2
- import { log } from './log.js';
3
- import { apiFailure, cors, readJsonBody, sendJson } from './api-http.js';
4
- import { signedIdentity } from './signed-identity.js';
5
- import type { ServerEntry } from './server-types.js';
6
- import { parseId } from '../db/ids.js';
7
-
8
- const PREFIX = '/api/servers';
9
-
10
- export interface ServersApiDeps {
11
- list: (subject: string) => Promise<ServerEntry[]>;
12
- add: (subject: string, body: unknown) => Promise<ServerEntry>;
13
- rename: (subject: string, id: string, body: unknown) => Promise<ServerEntry>;
14
- remove: (subject: string, id: string) => Promise<{ id: string; host: string }>;
15
- }
16
-
17
- type Target = { kind: 'index' } | { kind: 'server'; id: string } | { kind: 'unknown' } | null;
18
-
19
- function target(path: string): Target {
20
- if (path === PREFIX || path === `${PREFIX}/`) return { kind: 'index' };
21
- if (!path.startsWith(`${PREFIX}/`)) return null;
22
- const segments = path.slice(PREFIX.length + 1).split('/').filter(Boolean);
23
- const id = parseId(segments[0] ?? '');
24
- return id === null || segments.length !== 1 ? { kind: 'unknown' } : { kind: 'server', id };
25
- }
26
-
27
- const ALLOWED: Record<'index' | 'server', string[]> = { index: ['GET', 'POST'], server: ['PUT', 'DELETE'] };
28
-
29
- async function answer(
30
- req: IncomingMessage,
31
- deps: ServersApiDeps,
32
- owner: string,
33
- tgt: { kind: 'index' } | { kind: 'server'; id: string },
34
- ): Promise<unknown> {
35
- if (tgt.kind === 'index')
36
- return req.method === 'GET' ? { servers: await deps.list(owner) } : deps.add(owner, await readJsonBody(req));
37
- return req.method === 'DELETE' ? deps.remove(owner, tgt.id) : deps.rename(owner, tgt.id, await readJsonBody(req));
38
- }
39
-
40
- async function route(
41
- req: IncomingMessage,
42
- res: ServerResponse,
43
- deps: ServersApiDeps,
44
- tgt: { kind: 'index' } | { kind: 'server'; id: string },
45
- ): Promise<void> {
46
- try {
47
- const owner = await signedIdentity(req);
48
- if (owner === null) {
49
- sendJson(req, res, 401, { error: 'unauthorized' });
50
- return;
51
- }
52
- const body = await answer(req, deps, owner, tgt);
53
- if (req.method !== 'GET') log.info({ method: req.method, target: tgt }, 'servers-api: list changed');
54
- sendJson(req, res, 200, body);
55
- } catch (err) {
56
- apiFailure(req, res, err, 'servers-api');
57
- }
58
- }
59
-
60
- export function handleServersApiRequest(req: IncomingMessage, res: ServerResponse, deps: ServersApiDeps): boolean {
61
- const path = (req.url ?? '').split('?')[0] ?? '';
62
- const tgt = target(path);
63
- if (tgt === null) return false;
64
- if (req.method === 'OPTIONS') {
65
- res.writeHead(204, cors(req)).end();
66
- return true;
67
- }
68
- if (tgt.kind === 'unknown') {
69
- sendJson(req, res, 404, { error: 'no such server' });
70
- return true;
71
- }
72
- if (!ALLOWED[tgt.kind].includes(req.method ?? '')) {
73
- sendJson(req, res, 405, { error: 'method not allowed' });
74
- return true;
75
- }
76
- route(req, res, deps, tgt).catch((err: unknown) => {
77
- apiFailure(req, res, err, 'servers-api');
78
- });
79
- return true;
80
- }
@@ -1,78 +0,0 @@
1
- import type { IncomingMessage, ServerResponse } from 'node:http';
2
- import { errMsg, log } from './log.js';
3
- import { apiFailure, cors, readJsonBody, sendJson } from './api-http.js';
4
- import { parseId } from '../db/ids.js';
5
- import { ENVELOPE_MAX, type VaultBundle, type VaultEntry } from './vault-types.js';
6
- import { signedIdentity } from './signed-identity.js';
7
-
8
- const PREFIX = '/api/vault';
9
- const BODY_MAX = ENVELOPE_MAX + 64 * 1024;
10
-
11
- export interface VaultApiDeps {
12
- list: (subject: string) => Promise<VaultEntry[]>;
13
- put: (subject: string, id: string, body: unknown) => Promise<VaultEntry>;
14
- get: (subject: string, id: string) => Promise<VaultBundle>;
15
- remove: (subject: string, id: string) => Promise<{ id: string; name: string }>;
16
- }
17
-
18
- type Target = { kind: 'index' } | { kind: 'bundle'; id: string } | { kind: 'unknown' } | null;
19
-
20
- function target(path: string): Target {
21
- if (path === PREFIX || path === `${PREFIX}/`) return { kind: 'index' };
22
- if (!path.startsWith(`${PREFIX}/`)) return null;
23
- const segments = path.slice(PREFIX.length + 1).split('/').filter(Boolean);
24
- const id = parseId(segments[0] ?? '');
25
- return id === null || segments.length !== 1 ? { kind: 'unknown' } : { kind: 'bundle', id };
26
- }
27
-
28
- const ALLOWED: Record<'index' | 'bundle', string[]> = { index: ['GET'], bundle: ['GET', 'PUT', 'DELETE'] };
29
-
30
- async function route(
31
- req: IncomingMessage,
32
- res: ServerResponse,
33
- deps: VaultApiDeps,
34
- tgt: { kind: 'index' } | { kind: 'bundle'; id: string },
35
- ): Promise<void> {
36
- try {
37
- const owner = await signedIdentity(req);
38
- if (owner === null) {
39
- sendJson(req, res, 401, { error: 'unauthorized' });
40
- return;
41
- }
42
- if (tgt.kind === 'index') {
43
- sendJson(req, res, 200, { entries: await deps.list(owner) });
44
- return;
45
- }
46
- if (req.method === 'GET') sendJson(req, res, 200, await deps.get(owner, tgt.id));
47
- else if (req.method === 'DELETE') sendJson(req, res, 200, await deps.remove(owner, tgt.id));
48
- else {
49
- const saved = await deps.put(owner, tgt.id, await readJsonBody(req, BODY_MAX));
50
- log.info({ id: saved.id, name: saved.name }, 'vault-api: bundle stored');
51
- sendJson(req, res, 200, saved);
52
- }
53
- } catch (err) {
54
- apiFailure(req, res, err, 'vault-api');
55
- }
56
- }
57
-
58
- export function handleVaultApiRequest(req: IncomingMessage, res: ServerResponse, deps: VaultApiDeps): boolean {
59
- const tgt = target((req.url ?? '').split('?')[0] ?? '');
60
- if (tgt === null) return false;
61
- if (req.method === 'OPTIONS') {
62
- res.writeHead(204, cors(req)).end();
63
- return true;
64
- }
65
- if (tgt.kind === 'unknown') {
66
- sendJson(req, res, 404, { error: 'no such bundle' });
67
- return true;
68
- }
69
- if (!ALLOWED[tgt.kind].includes(req.method ?? '')) {
70
- sendJson(req, res, 405, { error: 'method not allowed' });
71
- return true;
72
- }
73
- route(req, res, deps, tgt).catch((err: unknown) => {
74
- log.warn({ err: errMsg(err) }, 'vault-api: unhandled error');
75
- if (!res.headersSent) sendJson(req, res, 500, { error: 'vault api failed' });
76
- });
77
- return true;
78
- }
@@ -1,12 +0,0 @@
1
- export interface VaultEntry {
2
- id: string;
3
- name: string;
4
- stations: string[];
5
- syncedAt: string;
6
- }
7
-
8
- export interface VaultBundle extends VaultEntry {
9
- envelope: Record<string, unknown>;
10
- }
11
-
12
- export const ENVELOPE_MAX = 2 * 1024 * 1024;
@@ -1,32 +0,0 @@
1
- import { drizzle, type PostgresJsDatabase } from 'drizzle-orm/postgres-js';
2
- import postgres from 'postgres';
3
- import { log } from '../daemon/log.js';
4
- import * as schema from './schema.js';
5
-
6
- export type Db = PostgresJsDatabase<typeof schema>;
7
-
8
- let sql: ReturnType<typeof postgres> | null = null;
9
- let db: Db | null = null;
10
-
11
- export function databaseUrl(): string | undefined {
12
- const url = process.env.DATABASE_URL?.trim();
13
- if (!url) return undefined;
14
- return url;
15
- }
16
-
17
- export function getDb(): Db {
18
- const url = databaseUrl();
19
- if (!url) throw new Error('DATABASE_URL is not set');
20
- if (!db) {
21
- sql = postgres(url, {
22
- max: 4,
23
- prepare: false,
24
- onnotice: (notice) => {
25
- log.debug({ notice: notice.message }, 'postgres notice');
26
- },
27
- });
28
- db = drizzle(sql, { schema });
29
- }
30
- return db;
31
- }
32
-