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

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 (230) hide show
  1. package/dist/cli.js +0 -3
  2. package/dist/runtime.js +1 -1
  3. package/dist/serve.js +0 -1
  4. package/package.json +1 -1
  5. package/runtime/node_modules/@metro-labs/core/package.json +43 -0
  6. package/runtime/node_modules/@metro-labs/core/src/endpoints.ts +7 -0
  7. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/events.ts +1 -1
  8. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/identity.ts +1 -1
  9. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/protocol.ts +1 -1
  10. package/runtime/node_modules/@metro-labs/{mcp → core}/src/stations/account-store.ts +2 -2
  11. package/runtime/node_modules/@metro-labs/{mcp → core}/src/stations/station-runtime.ts +1 -1
  12. package/runtime/node_modules/@metro-labs/daemon/package.json +47 -0
  13. package/runtime/node_modules/@metro-labs/{mcp/src/db → daemon/src/agents}/account-attach.ts +1 -1
  14. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/account-api.ts → daemon/src/agents/accounts-api.ts} +6 -6
  15. package/runtime/node_modules/@metro-labs/{mcp/src/db/agent-admin.ts → daemon/src/agents/admin.ts} +2 -2
  16. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/agent-api.ts → daemon/src/agents/api.ts} +6 -6
  17. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/bundle-api.ts → daemon/src/agents/bundle.ts} +7 -7
  18. package/runtime/node_modules/@metro-labs/{mcp/src/db → daemon/src/agents}/file-admin.ts +9 -9
  19. package/runtime/node_modules/@metro-labs/{mcp/src/db/file-source.ts → daemon/src/agents/files.ts} +4 -4
  20. package/runtime/node_modules/@metro-labs/{mcp/src/db/key-map.ts → daemon/src/agents/keys.ts} +1 -1
  21. package/runtime/node_modules/@metro-labs/{mcp/src/db/agent-scope.ts → daemon/src/agents/scope.ts} +2 -2
  22. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/boot}/boot.ts +23 -51
  23. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/boot}/crash-guard.ts +1 -1
  24. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/boot}/local-owner.ts +2 -2
  25. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/boot}/paths.ts +1 -4
  26. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/addressed.ts +1 -1
  27. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/dedupe.ts +1 -1
  28. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/inbound.ts +1 -1
  29. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/pending.ts +1 -1
  30. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/relay.ts +1 -1
  31. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/claude-api.ts → daemon/src/claude/api.ts} +7 -7
  32. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/claude-files.ts → daemon/src/claude/files.ts} +2 -2
  33. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/claude-login.ts → daemon/src/claude/login.ts} +3 -3
  34. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/claude-settings.ts → daemon/src/claude/settings.ts} +4 -4
  35. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/connector-api.ts → daemon/src/connectors/api.ts} +6 -6
  36. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/local-cli-api.ts → daemon/src/connectors/cli-api.ts} +5 -5
  37. package/runtime/node_modules/@metro-labs/{mcp/src/db/connector-config.ts → daemon/src/connectors/config.ts} +4 -4
  38. package/runtime/node_modules/@metro-labs/{mcp/src/db/connectors.ts → daemon/src/connectors/model.ts} +3 -3
  39. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/connectors}/oauth-client.ts +2 -2
  40. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/connectors}/oauth-discovery.ts +2 -2
  41. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/connector-oauth-routes.ts → daemon/src/connectors/oauth-routes.ts} +6 -6
  42. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/connector-oauth.ts → daemon/src/connectors/oauth.ts} +3 -3
  43. package/runtime/node_modules/@metro-labs/{mcp/src/db/connector-relay.ts → daemon/src/connectors/relay-target.ts} +1 -1
  44. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/connectors}/relay.ts +4 -4
  45. package/runtime/node_modules/@metro-labs/{mcp/src/db/local-connectors.ts → daemon/src/connectors/store.ts} +12 -12
  46. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/connector-tools.ts → daemon/src/connectors/tools.ts} +1 -1
  47. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/connector-url.ts → daemon/src/connectors/url.ts} +1 -1
  48. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/connector-verify.ts → daemon/src/connectors/verify.ts} +5 -5
  49. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/files}/attach-grant.ts +3 -3
  50. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/files}/attach-owner.ts +3 -3
  51. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/files}/attach-serve.ts +5 -12
  52. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/files}/upload-api.ts +5 -5
  53. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/files}/upload-store.ts +2 -2
  54. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/bedrock.ts +1 -1
  55. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/codex-auth.ts +1 -1
  56. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/codex-device.ts +2 -2
  57. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/codex-stream.ts +1 -1
  58. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/codex-translate.ts +1 -1
  59. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/codex.ts +2 -2
  60. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/gateway.ts +2 -2
  61. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/gateway}/model-api.ts +12 -12
  62. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/model-config.ts +3 -3
  63. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/openrouter.ts +1 -1
  64. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/accounts.ts +3 -7
  65. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/call-tools.ts +3 -3
  66. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/channel-owner.ts +1 -1
  67. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/ctx.ts +4 -4
  68. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/frame-scope.ts +2 -2
  69. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/group-tools.ts +2 -2
  70. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/index.ts +1 -1
  71. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/member-tools.ts +2 -2
  72. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/request-identity.ts +1 -1
  73. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/session-registry.ts +2 -2
  74. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/session.ts +2 -2
  75. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/tool-dispatch.ts +4 -4
  76. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/upload-tool.ts +5 -5
  77. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/monitor/api.ts +5 -5
  78. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/net}/tunnel.ts +6 -10
  79. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/routes}/http.ts +15 -15
  80. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/identity-routes.ts → daemon/src/routes/identity.ts} +5 -5
  81. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/routes}/local-mode.ts +16 -16
  82. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/routes}/session-apis.ts +14 -20
  83. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/session-api.ts → daemon/src/routes/session.ts} +1 -1
  84. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/control-api.ts → daemon/src/server/control.ts} +3 -3
  85. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/machine-api.ts → daemon/src/server/machine.ts} +8 -8
  86. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/update-api.ts → daemon/src/server/update.ts} +5 -5
  87. package/runtime/node_modules/@metro-labs/daemon/src/server.ts +2 -0
  88. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/attach-resolve.ts +3 -3
  89. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/stations}/attach-session.ts +4 -4
  90. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/attach-xmtp.ts +1 -1
  91. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/attach.ts +3 -3
  92. package/runtime/node_modules/@metro-labs/{mcp/src/db → daemon/src/stations}/materialize.ts +9 -14
  93. package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/registry.ts +2 -2
  94. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/stations}/runtime-deps.ts +4 -4
  95. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/stations}/supervisor-io.ts +2 -2
  96. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/stations}/supervisor.ts +4 -4
  97. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/stations}/train-call.ts +1 -1
  98. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/terminal-api.ts → daemon/src/terminal/api.ts} +4 -4
  99. package/runtime/node_modules/@metro-labs/{mcp/src/daemon/terminal-ws.ts → daemon/src/terminal/socket.ts} +3 -3
  100. package/runtime/node_modules/@metro-labs/discord-bot/package.json +1 -1
  101. package/runtime/node_modules/@metro-labs/discord-bot/src/accounts.ts +2 -2
  102. package/runtime/node_modules/@metro-labs/discord-bot/src/actions.ts +3 -3
  103. package/runtime/node_modules/@metro-labs/discord-bot/src/attachments.ts +2 -2
  104. package/runtime/node_modules/@metro-labs/discord-bot/src/group.ts +2 -2
  105. package/runtime/node_modules/@metro-labs/discord-bot/src/index.ts +2 -2
  106. package/runtime/node_modules/@metro-labs/discord-bot/src/members.ts +2 -2
  107. package/runtime/node_modules/@metro-labs/discord-bot/src/send-files.ts +1 -1
  108. package/runtime/node_modules/@metro-labs/discord-bot/src/station.ts +1 -1
  109. package/runtime/node_modules/@metro-labs/discord-bot/src/voice-speak.ts +1 -1
  110. package/runtime/node_modules/@metro-labs/discord-bot/src/voice-transcribe.ts +1 -1
  111. package/runtime/node_modules/@metro-labs/discord-bot/src/voice.ts +1 -1
  112. package/runtime/node_modules/@metro-labs/discord-bot/src/wire.ts +1 -1
  113. package/runtime/node_modules/@metro-labs/http/package.json +33 -0
  114. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → http/src}/api-http.ts +1 -1
  115. package/runtime/node_modules/@metro-labs/{mcp/src/daemon → http/src}/signed-identity.ts +1 -1
  116. package/runtime/node_modules/@metro-labs/telegram/package.json +1 -1
  117. package/runtime/node_modules/@metro-labs/telegram/src/accounts.ts +1 -1
  118. package/runtime/node_modules/@metro-labs/telegram/src/actions.ts +3 -3
  119. package/runtime/node_modules/@metro-labs/telegram/src/attachments.ts +1 -1
  120. package/runtime/node_modules/@metro-labs/telegram/src/client.ts +2 -2
  121. package/runtime/node_modules/@metro-labs/telegram/src/format.ts +1 -1
  122. package/runtime/node_modules/@metro-labs/telegram/src/group.ts +3 -3
  123. package/runtime/node_modules/@metro-labs/telegram/src/inbound.ts +1 -1
  124. package/runtime/node_modules/@metro-labs/telegram/src/index.ts +3 -3
  125. package/runtime/node_modules/@metro-labs/telegram/src/media-actions.ts +1 -1
  126. package/runtime/node_modules/@metro-labs/telegram/src/members.ts +1 -1
  127. package/runtime/node_modules/@metro-labs/telegram/src/normalize.ts +1 -1
  128. package/runtime/node_modules/@metro-labs/telegram/src/reactions.ts +1 -1
  129. package/runtime/node_modules/@metro-labs/telegram/src/station.ts +1 -1
  130. package/runtime/node_modules/@metro-labs/telegram/src/wire.ts +1 -1
  131. package/runtime/node_modules/@metro-labs/telegram-bot/package.json +1 -1
  132. package/runtime/node_modules/@metro-labs/telegram-bot/src/accounts.ts +2 -2
  133. package/runtime/node_modules/@metro-labs/telegram-bot/src/actions.ts +4 -4
  134. package/runtime/node_modules/@metro-labs/telegram-bot/src/attachments.ts +2 -2
  135. package/runtime/node_modules/@metro-labs/telegram-bot/src/format.ts +1 -1
  136. package/runtime/node_modules/@metro-labs/telegram-bot/src/index.ts +2 -2
  137. package/runtime/node_modules/@metro-labs/telegram-bot/src/media-actions.ts +1 -1
  138. package/runtime/node_modules/@metro-labs/telegram-bot/src/members.ts +1 -1
  139. package/runtime/node_modules/@metro-labs/telegram-bot/src/station.ts +1 -1
  140. package/runtime/node_modules/@metro-labs/telegram-bot/src/wire.ts +1 -1
  141. package/runtime/node_modules/@metro-labs/webhook/package.json +1 -1
  142. package/runtime/node_modules/@metro-labs/webhook/src/station.ts +4 -4
  143. package/runtime/node_modules/@metro-labs/whatsapp/package.json +1 -1
  144. package/runtime/node_modules/@metro-labs/whatsapp/src/accounts.ts +1 -1
  145. package/runtime/node_modules/@metro-labs/whatsapp/src/ack.ts +1 -1
  146. package/runtime/node_modules/@metro-labs/whatsapp/src/actions.ts +4 -4
  147. package/runtime/node_modules/@metro-labs/whatsapp/src/attachments.ts +2 -2
  148. package/runtime/node_modules/@metro-labs/whatsapp/src/auth-state.ts +1 -1
  149. package/runtime/node_modules/@metro-labs/whatsapp/src/client.ts +2 -2
  150. package/runtime/node_modules/@metro-labs/whatsapp/src/format.ts +1 -1
  151. package/runtime/node_modules/@metro-labs/whatsapp/src/inbound.ts +1 -1
  152. package/runtime/node_modules/@metro-labs/whatsapp/src/index.ts +3 -3
  153. package/runtime/node_modules/@metro-labs/whatsapp/src/keys.ts +1 -1
  154. package/runtime/node_modules/@metro-labs/whatsapp/src/login.ts +1 -1
  155. package/runtime/node_modules/@metro-labs/whatsapp/src/media.ts +1 -1
  156. package/runtime/node_modules/@metro-labs/whatsapp/src/normalize.ts +1 -1
  157. package/runtime/node_modules/@metro-labs/whatsapp/src/station.ts +1 -1
  158. package/runtime/node_modules/@metro-labs/whatsapp/src/token-store.ts +2 -2
  159. package/runtime/node_modules/@metro-labs/whatsapp/src/wire.ts +1 -1
  160. package/runtime/node_modules/@metro-labs/xmtp/package.json +1 -1
  161. package/runtime/node_modules/@metro-labs/xmtp/src/accounts.ts +2 -2
  162. package/runtime/node_modules/@metro-labs/xmtp/src/actions-close.ts +1 -1
  163. package/runtime/node_modules/@metro-labs/xmtp/src/actions-conv.ts +1 -1
  164. package/runtime/node_modules/@metro-labs/xmtp/src/actions-meta.ts +1 -1
  165. package/runtime/node_modules/@metro-labs/xmtp/src/actions.ts +3 -3
  166. package/runtime/node_modules/@metro-labs/xmtp/src/attachments.ts +3 -3
  167. package/runtime/node_modules/@metro-labs/xmtp/src/conv-helpers.ts +2 -2
  168. package/runtime/node_modules/@metro-labs/xmtp/src/emit-payloads.ts +1 -1
  169. package/runtime/node_modules/@metro-labs/xmtp/src/emit.ts +1 -1
  170. package/runtime/node_modules/@metro-labs/xmtp/src/group-members.ts +1 -1
  171. package/runtime/node_modules/@metro-labs/xmtp/src/group.ts +2 -2
  172. package/runtime/node_modules/@metro-labs/xmtp/src/index.ts +2 -2
  173. package/runtime/node_modules/@metro-labs/xmtp/src/member-args.ts +1 -1
  174. package/runtime/node_modules/@metro-labs/xmtp/src/push.ts +2 -2
  175. package/runtime/node_modules/@metro-labs/xmtp/src/station.ts +1 -1
  176. package/runtime/node_modules/@metro-labs/xmtp/src/tools-handlers.ts +3 -3
  177. package/runtime/node_modules/@metro-labs/xmtp/src/tools.ts +1 -1
  178. package/runtime/node_modules/@metro-labs/xmtp/src/transcribe.ts +1 -1
  179. package/runtime/node_modules/@metro-labs/xmtp/src/wire.ts +1 -1
  180. package/runtime/runtime.json +1 -1
  181. package/dist/bedrock-eventstream.js +0 -120
  182. package/dist/bedrock-proxy.js +0 -260
  183. package/dist/bedrock-upstream.js +0 -72
  184. package/dist/bedrock.js +0 -37
  185. package/runtime/node_modules/@metro-labs/mcp/package.json +0 -64
  186. package/runtime/node_modules/@metro-labs/mcp/src/daemon/server-types.ts +0 -21
  187. package/runtime/node_modules/@metro-labs/mcp/src/daemon/servers-api.ts +0 -80
  188. package/runtime/node_modules/@metro-labs/mcp/src/daemon/vault-api.ts +0 -78
  189. package/runtime/node_modules/@metro-labs/mcp/src/daemon/vault-types.ts +0 -12
  190. package/runtime/node_modules/@metro-labs/mcp/src/db/client.ts +0 -32
  191. package/runtime/node_modules/@metro-labs/mcp/src/db/schema.ts +0 -33
  192. package/runtime/node_modules/@metro-labs/mcp/src/db/servers.ts +0 -83
  193. package/runtime/node_modules/@metro-labs/mcp/src/db/vault.ts +0 -109
  194. package/runtime/node_modules/@metro-labs/mcp/src/server.ts +0 -2
  195. /package/runtime/node_modules/@metro-labs/{mcp/src/db → core/src}/address.ts +0 -0
  196. /package/runtime/node_modules/@metro-labs/{mcp/src/db → core/src}/ids.ts +0 -0
  197. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/is-record.ts +0 -0
  198. /package/runtime/node_modules/@metro-labs/{mcp/src/stations → core/src}/lines.ts +0 -0
  199. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/log.ts +0 -0
  200. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/secure-fs.ts +0 -0
  201. /package/runtime/node_modules/@metro-labs/{mcp/src/db/stations.ts → core/src/station-names.ts} +0 -0
  202. /package/runtime/node_modules/@metro-labs/{mcp → core}/src/stations/attachments.ts +0 -0
  203. /package/runtime/node_modules/@metro-labs/{mcp → core}/src/stations/messaging-normalize.ts +0 -0
  204. /package/runtime/node_modules/@metro-labs/{mcp → core}/src/stations/types.ts +0 -0
  205. /package/runtime/node_modules/@metro-labs/{mcp/src/mcp → core/src}/str.ts +0 -0
  206. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/train-error.ts +0 -0
  207. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/version.ts +0 -0
  208. /package/runtime/node_modules/@metro-labs/{mcp/src/db/agent-map.ts → daemon/src/agents/map.ts} +0 -0
  209. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/boot}/connect-hint.ts +0 -0
  210. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/media-note.ts +0 -0
  211. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/webhook-note.ts +0 -0
  212. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon/connector-json.ts → daemon/src/connectors/json.ts} +0 -0
  213. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/connectors}/oauth-pending.ts +0 -0
  214. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/eventstream.ts +0 -0
  215. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/forward.ts +0 -0
  216. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/gateway/served.ts +0 -0
  217. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/event-store.ts +0 -0
  218. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/permission-relay.ts +0 -0
  219. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/raw-get-stream.ts +0 -0
  220. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/session-route.ts +0 -0
  221. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/tool-schemas.ts +0 -0
  222. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/attach-inline.ts +0 -0
  223. /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/attach-interactive.ts +0 -0
  224. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon/terminal-tickets.ts → daemon/src/terminal/tickets.ts} +0 -0
  225. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → http/src}/api-error.ts +0 -0
  226. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → http/src}/cors.ts +0 -0
  227. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → http/src}/identity-key.ts +0 -0
  228. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → http/src}/identity-registry.ts +0 -0
  229. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → http/src}/mode-api.ts +0 -0
  230. /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → http/src}/return-to.ts +0 -0
@@ -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
-
@@ -1,33 +0,0 @@
1
- import { index, jsonb, pgTable, text, uniqueIndex } from 'drizzle-orm/pg-core';
2
-
3
- import { STATIONS, type ConnectorTransport, type StationName } from './stations.js';
4
-
5
- export { STATIONS, type ConnectorTransport, type StationName };
6
-
7
- export type ProjectRole = 'admin' | 'member';
8
-
9
-
10
- export const vaults = pgTable(
11
- 'vaults',
12
- {
13
- id: text('id').primaryKey(),
14
- owner: text('owner').notNull(),
15
- name: text('name').notNull(),
16
- stations: jsonb('stations').notNull(),
17
- envelope: jsonb('envelope').notNull(),
18
- syncedAt: text('synced_at').notNull(),
19
- },
20
- (t) => [index('vaults_owner_idx').on(t.owner)],
21
- );
22
-
23
- export const servers = pgTable(
24
- 'servers',
25
- {
26
- id: text('id').primaryKey(),
27
- owner: text('owner').notNull(),
28
- host: text('host').notNull(),
29
- name: text('name'),
30
- addedAt: text('added_at').notNull(),
31
- },
32
- (t) => [uniqueIndex('servers_owner_host_idx').on(t.owner, t.host), index('servers_owner_idx').on(t.owner)],
33
- );
@@ -1,83 +0,0 @@
1
- import { and, asc, eq } from 'drizzle-orm';
2
- import { ApiError } from '../daemon/api-error.js';
3
- import { isRecord } from '../daemon/is-record.js';
4
- import { getDb } from './client.js';
5
- import { newId, parseId } from './ids.js';
6
- import { servers } from './schema.js';
7
- import { normalizeAddress } from './address.js';
8
- import { parseServerHost, parseServerName, type ServerEntry } from '../daemon/server-types.js';
9
-
10
- export class ServerListError extends ApiError {}
11
-
12
- const missing = (): ServerListError => new ServerListError('no such server', 404);
13
-
14
- function ownerOf(subject: string): string {
15
- const address = normalizeAddress(subject);
16
- if (address === null) throw new ServerListError('the server list needs a signed identity', 403);
17
- return address;
18
- }
19
-
20
- function idOf(raw: string): string {
21
- const id = parseId(raw);
22
- if (id === null) throw missing();
23
- return id;
24
- }
25
-
26
- const entryOf = (row: { id: string; host: string; name: string | null; addedAt: string }): ServerEntry => ({
27
- id: row.id,
28
- host: row.host,
29
- name: row.name,
30
- addedAt: row.addedAt,
31
- });
32
-
33
- const columns = { id: servers.id, host: servers.host, name: servers.name, addedAt: servers.addedAt };
34
-
35
- export async function listServersForOwner(subject: string): Promise<ServerEntry[]> {
36
- const owner = ownerOf(subject);
37
- const rows = await getDb().select(columns).from(servers).where(eq(servers.owner, owner)).orderBy(asc(servers.addedAt));
38
- return rows.map(entryOf);
39
- }
40
-
41
- export async function addServerForOwner(subject: string, body: unknown): Promise<ServerEntry> {
42
- const owner = ownerOf(subject);
43
- const host = parseServerHost(isRecord(body) && typeof body.host === 'string' ? body.host : '');
44
- if (host === null) throw new ServerListError('host is not a server address', 400);
45
- const name = parseServerName(isRecord(body) ? body.name : undefined);
46
- const db = getDb();
47
- const held = await db.select(columns).from(servers).where(and(eq(servers.owner, owner), eq(servers.host, host)));
48
- const row = held[0];
49
- if (row !== undefined) {
50
- if (name === null) return entryOf(row);
51
- await db.update(servers).set({ name }).where(eq(servers.id, row.id));
52
- return entryOf({ ...row, name });
53
- }
54
- const next = { id: newId(), owner, host, name, addedAt: new Date().toISOString() };
55
- await db.insert(servers).values(next);
56
- return entryOf(next);
57
- }
58
-
59
- export async function renameServerForOwner(subject: string, rawId: string, body: unknown): Promise<ServerEntry> {
60
- const owner = ownerOf(subject);
61
- const id = idOf(rawId);
62
- const name = parseServerName(isRecord(body) ? body.name : undefined);
63
- const rows = await getDb()
64
- .update(servers)
65
- .set({ name })
66
- .where(and(eq(servers.id, id), eq(servers.owner, owner)))
67
- .returning(columns);
68
- const row = rows[0];
69
- if (row === undefined) throw missing();
70
- return entryOf(row);
71
- }
72
-
73
- export async function deleteServerForOwner(subject: string, rawId: string): Promise<{ id: string; host: string }> {
74
- const owner = ownerOf(subject);
75
- const id = idOf(rawId);
76
- const gone = await getDb()
77
- .delete(servers)
78
- .where(and(eq(servers.id, id), eq(servers.owner, owner)))
79
- .returning({ id: servers.id, host: servers.host });
80
- const row = gone[0];
81
- if (row === undefined) throw missing();
82
- return row;
83
- }
@@ -1,109 +0,0 @@
1
- import { and, asc, eq } from 'drizzle-orm';
2
- import { ApiError } from '../daemon/api-error.js';
3
- import { isRecord } from '../daemon/is-record.js';
4
- import { getDb } from './client.js';
5
- import { AGENT_NAME_RE, parseId } from './ids.js';
6
- import { vaults } from './schema.js';
7
- import { STATIONS } from './stations.js';
8
- import { normalizeAddress } from './address.js';
9
-
10
- export class VaultError extends ApiError {}
11
-
12
- import { ENVELOPE_MAX, type VaultBundle, type VaultEntry } from '../daemon/vault-types.js';
13
-
14
- export interface VaultInput {
15
- name: string;
16
- stations: string[];
17
- envelope: Record<string, unknown>;
18
- }
19
- const STATION_NAMES = new Set<string>(STATIONS);
20
-
21
- const missing = (): VaultError => new VaultError('no such bundle', 404);
22
-
23
- function ownerOf(subject: string): string {
24
- const address = normalizeAddress(subject);
25
- if (address === null) throw new VaultError('the vault needs a vault identity', 403);
26
- return address;
27
- }
28
-
29
- function stationsOf(raw: unknown): string[] {
30
- if (!Array.isArray(raw)) throw new VaultError('stations must be a list of station names', 400);
31
- const list = raw.map((s: unknown) => (typeof s === 'string' ? s : ''));
32
- const bad = list.find((s) => !STATION_NAMES.has(s));
33
- if (bad !== undefined) throw new VaultError(`'${bad}' is not a station`, 400);
34
- return [...new Set(list)];
35
- }
36
-
37
- function envelopeOf(raw: unknown, id: string): Record<string, unknown> {
38
- if (!isRecord(raw) || raw.v !== 1 || raw.agentId !== id)
39
- throw new VaultError('envelope must be a v1 envelope for this agent', 400);
40
- const key = raw.key;
41
- if (!isRecord(key) || normalizeAddress(typeof key.recipient === 'string' ? key.recipient : '') === null)
42
- throw new VaultError('envelope must name the wallet it was sealed to', 400);
43
- if (typeof raw.ciphertext !== 'string' || typeof raw.nonce !== 'string')
44
- throw new VaultError('envelope carries no ciphertext', 400);
45
- if (JSON.stringify(raw).length > ENVELOPE_MAX)
46
- throw new VaultError(`envelope is over ${String(ENVELOPE_MAX)} bytes`, 413);
47
- return raw;
48
- }
49
-
50
- export function parseVaultInput(subject: string, id: string, body: unknown): VaultInput & { owner: string } {
51
- const owner = ownerOf(subject);
52
- if (parseId(id) === null) throw missing();
53
- if (!isRecord(body)) throw new VaultError('body must be an object', 400);
54
- const name = typeof body.name === 'string' ? body.name.trim() : '';
55
- if (!AGENT_NAME_RE.test(name)) throw new VaultError('name is not an agent name', 400);
56
- return { owner, name, stations: stationsOf(body.stations), envelope: envelopeOf(body.envelope, id) };
57
- }
58
-
59
- const entryOf = (row: { id: string; name: string; stations: unknown; syncedAt: string }): VaultEntry => ({
60
- id: row.id,
61
- name: row.name,
62
- stations: Array.isArray(row.stations) ? row.stations.filter((s): s is string => typeof s === 'string') : [],
63
- syncedAt: row.syncedAt,
64
- });
65
-
66
- export async function listVaultForOwner(subject: string): Promise<VaultEntry[]> {
67
- const owner = ownerOf(subject);
68
- const rows = await getDb()
69
- .select({ id: vaults.id, name: vaults.name, stations: vaults.stations, syncedAt: vaults.syncedAt })
70
- .from(vaults)
71
- .where(eq(vaults.owner, owner))
72
- .orderBy(asc(vaults.name));
73
- return rows.map(entryOf);
74
- }
75
-
76
- export async function putVaultForOwner(subject: string, id: string, body: unknown): Promise<VaultEntry> {
77
- const input = parseVaultInput(subject, id, body);
78
- const syncedAt = new Date().toISOString();
79
- const values = { id, owner: input.owner, name: input.name, stations: input.stations, envelope: input.envelope, syncedAt };
80
- const db = getDb();
81
- const held = await db.select({ owner: vaults.owner }).from(vaults).where(eq(vaults.id, id));
82
- if (held[0] !== undefined && held[0].owner !== input.owner) throw missing();
83
- await db
84
- .insert(vaults)
85
- .values(values)
86
- .onConflictDoUpdate({ target: vaults.id, set: { name: input.name, stations: input.stations, envelope: input.envelope, syncedAt } });
87
- return entryOf(values);
88
- }
89
-
90
- export async function getVaultForOwner(subject: string, id: string): Promise<VaultBundle> {
91
- const owner = ownerOf(subject);
92
- if (parseId(id) === null) throw missing();
93
- const rows = await getDb().select().from(vaults).where(and(eq(vaults.id, id), eq(vaults.owner, owner)));
94
- const row = rows[0];
95
- if (row === undefined) throw missing();
96
- return { ...entryOf(row), envelope: isRecord(row.envelope) ? row.envelope : {} };
97
- }
98
-
99
- export async function deleteVaultForOwner(subject: string, id: string): Promise<{ id: string; name: string }> {
100
- const owner = ownerOf(subject);
101
- if (parseId(id) === null) throw missing();
102
- const gone = await getDb()
103
- .delete(vaults)
104
- .where(and(eq(vaults.id, id), eq(vaults.owner, owner)))
105
- .returning({ id: vaults.id, name: vaults.name });
106
- const row = gone[0];
107
- if (row === undefined) throw missing();
108
- return row;
109
- }
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env bun
2
- import './daemon/boot.js';