@stage-labs/metro 0.1.0-beta.32 → 0.1.0-beta.321
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.
- package/dist/agent.js +123 -0
- package/dist/api.js +9 -129
- package/dist/automation.js +56 -0
- package/dist/child.js +33 -0
- package/dist/claude-env.js +113 -0
- package/dist/claude-settings.js +40 -0
- package/dist/cli.js +60 -139
- package/dist/control.js +19 -103
- package/dist/hold.js +210 -0
- package/dist/local.js +43 -0
- package/dist/lock.js +62 -0
- package/dist/memory.js +206 -0
- package/dist/node-name.js +71 -0
- package/dist/provider-flags.js +9 -0
- package/dist/root-release-io.js +160 -0
- package/dist/root-release.js +74 -0
- package/dist/route.js +65 -0
- package/dist/runtime-install.js +106 -0
- package/dist/runtime.js +29 -55
- package/dist/serve.js +117 -17
- package/dist/service.js +328 -0
- package/dist/tail.js +10 -11
- package/dist/update.js +13 -1
- package/hooks/guard.mjs +77 -0
- package/hooks/policy.mjs +74 -0
- package/hooks/session-start.mjs +31 -0
- package/package.json +6 -25
- package/runtime/node_modules/@metro-labs/core/package.json +61 -0
- package/runtime/node_modules/@metro-labs/core/src/automation-files.ts +216 -0
- package/runtime/node_modules/@metro-labs/core/src/automation-store.ts +171 -0
- package/runtime/node_modules/@metro-labs/core/src/automation-types.ts +141 -0
- package/runtime/node_modules/@metro-labs/core/src/call.ts +81 -0
- package/runtime/node_modules/@metro-labs/core/src/claude-token.ts +3 -0
- package/runtime/node_modules/@metro-labs/core/src/effort.ts +21 -0
- package/runtime/node_modules/@metro-labs/core/src/endpoints.ts +7 -0
- package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/events.ts +54 -6
- package/runtime/node_modules/@metro-labs/{mcp/src/db → core/src}/ids.ts +8 -1
- package/runtime/node_modules/@metro-labs/core/src/is-record.ts +2 -0
- package/runtime/node_modules/@metro-labs/{mcp/src/stations → core/src}/lines.ts +22 -26
- package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/protocol.ts +7 -4
- package/runtime/node_modules/@metro-labs/core/src/runner-activity.ts +270 -0
- package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/secure-fs.ts +17 -0
- package/runtime/node_modules/@metro-labs/core/src/skill-source.ts +96 -0
- package/runtime/node_modules/@metro-labs/core/src/station-names.ts +14 -0
- package/runtime/node_modules/@metro-labs/core/src/stations/account-files.ts +41 -0
- package/runtime/node_modules/@metro-labs/core/src/stations/account-status.ts +26 -0
- package/runtime/node_modules/@metro-labs/core/src/stations/account-store.ts +83 -0
- package/runtime/node_modules/@metro-labs/{mcp → core}/src/stations/attachments.ts +9 -3
- package/runtime/node_modules/@metro-labs/core/src/stations/channel-directory.ts +159 -0
- package/runtime/node_modules/@metro-labs/core/src/stations/channel-pages.ts +129 -0
- package/runtime/node_modules/@metro-labs/core/src/stations/mail-text.ts +72 -0
- package/runtime/node_modules/@metro-labs/core/src/stations/mail-trust.ts +29 -0
- package/runtime/node_modules/@metro-labs/core/src/stations/mail.ts +212 -0
- package/runtime/node_modules/@metro-labs/core/src/stations/messaging-normalize.ts +16 -0
- package/runtime/node_modules/@metro-labs/core/src/stations/oauth.ts +126 -0
- package/runtime/node_modules/@metro-labs/core/src/stations/profile.ts +58 -0
- package/runtime/node_modules/@metro-labs/core/src/stations/sender-profile.ts +64 -0
- package/runtime/node_modules/@metro-labs/{mcp → core}/src/stations/station-runtime.ts +6 -11
- package/runtime/node_modules/@metro-labs/core/src/stations/train-boot.ts +63 -0
- package/runtime/node_modules/@metro-labs/core/src/stations/train-events.ts +84 -0
- package/runtime/node_modules/@metro-labs/{mcp → core}/src/stations/types.ts +22 -1
- package/runtime/node_modules/@metro-labs/core/src/tickets.ts +44 -0
- package/runtime/node_modules/@metro-labs/core/src/version.ts +2 -0
- package/runtime/node_modules/@metro-labs/daemon/package.json +51 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/agent-fs.ts +246 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/crontab.ts +38 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/files-api.ts +12 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/files.ts +89 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/home-fs.ts +86 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/metro-home.ts +42 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/provision.ts +57 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/schedule-detail.ts +93 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/schedules-api.ts +27 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/schedules.ts +144 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/unit-files.ts +29 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/user.ts +101 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/view.ts +90 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agents/account-attach.ts +19 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agents/account-lookups.ts +55 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agents/account-routes.ts +78 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agents/accounts-api.ts +383 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agents/admin.ts +30 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agents/allowlist.ts +59 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agents/api.ts +134 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agents/bundle.ts +124 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agents/file-admin.ts +334 -0
- package/runtime/node_modules/@metro-labs/{mcp/src/db/file-source.ts → daemon/src/agents/files.ts} +40 -50
- package/runtime/node_modules/@metro-labs/{mcp/src/db/key-map.ts → daemon/src/agents/keys.ts} +1 -11
- package/runtime/node_modules/@metro-labs/daemon/src/agents/map.ts +135 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agents/policy-route.ts +27 -0
- package/runtime/node_modules/@metro-labs/{mcp/src/db/agent-scope.ts → daemon/src/agents/scope.ts} +2 -2
- package/runtime/node_modules/@metro-labs/daemon/src/agents/sender-cards.ts +94 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agents/senders.ts +38 -0
- package/runtime/node_modules/@metro-labs/daemon/src/approvals/api.ts +55 -0
- package/runtime/node_modules/@metro-labs/daemon/src/approvals/owner-line.ts +45 -0
- package/runtime/node_modules/@metro-labs/daemon/src/approvals/pending.ts +190 -0
- package/runtime/node_modules/@metro-labs/daemon/src/approvals/preview.ts +66 -0
- package/runtime/node_modules/@metro-labs/daemon/src/boot/boot.ts +259 -0
- package/runtime/node_modules/@metro-labs/daemon/src/boot/connect-hint.ts +36 -0
- package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/boot}/crash-guard.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/boot/local-owner.ts +21 -0
- package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/boot}/paths.ts +3 -41
- package/runtime/node_modules/@metro-labs/daemon/src/channels/addressed.ts +26 -0
- package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/inbound.ts +99 -73
- package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/media-note.ts +11 -7
- package/runtime/node_modules/@metro-labs/daemon/src/channels/notice.ts +22 -0
- package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/pending.ts +13 -1
- package/runtime/node_modules/@metro-labs/daemon/src/channels/react-note.ts +13 -0
- package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/relay.ts +6 -2
- package/runtime/node_modules/@metro-labs/daemon/src/claude/api.ts +269 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/cli-files.ts +28 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/files.ts +359 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/github-api.ts +12 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/github-fetch.ts +160 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/github-skills.ts +255 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/github-validate.ts +53 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/hooks.ts +60 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/memory-routine.ts +123 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/memory.ts +32 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/runner-activity.ts +17 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/runner-process.ts +52 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/session-files.ts +75 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/session.ts +294 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/settings.ts +109 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/setup-api.ts +114 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/setup-state.ts +18 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/setup.ts +325 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/skills.ts +123 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/agent-key.ts +145 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/enroll-api.ts +99 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/leftovers.ts +59 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/metro-api.ts +93 -0
- package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/files}/attach-grant.ts +4 -4
- package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/files}/attach-owner.ts +3 -3
- package/runtime/node_modules/@metro-labs/daemon/src/files/attach-reaper.ts +174 -0
- package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/files}/attach-serve.ts +11 -19
- package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/files}/upload-api.ts +10 -27
- package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/files}/upload-store.ts +4 -4
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/bedrock.ts +253 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/cache-ttl.ts +43 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-stream.ts +186 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-translate.ts +209 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-version.ts +44 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex.ts +137 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/delivered.ts +102 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/effective.ts +32 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/effort.ts +130 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/eventstream.ts +123 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/failures.ts +40 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/fallback.ts +149 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/forward.ts +305 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/frames.ts +118 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/gateway.ts +372 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/model-api.ts +121 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/model-config.ts +150 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/model-leftovers.ts +63 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/openrouter.ts +25 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/org-models.ts +203 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/routeway.ts +88 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/served.ts +18 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/subscription.ts +60 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/text.ts +33 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/tool-search.ts +126 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/usage-refresh.ts +51 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/usage.ts +265 -0
- package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/accounts.ts +66 -19
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/attachment-schema.ts +91 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/call-bridge.ts +45 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/call-permission.ts +25 -0
- package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/call-tools.ts +88 -38
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/channel-tool.ts +80 -0
- package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/ctx.ts +4 -4
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/diagnostics.ts +102 -0
- package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/event-store.ts +24 -18
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/frame-schema.ts +44 -0
- package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/group-tools.ts +2 -2
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/index.ts +167 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/instructions.ts +21 -0
- package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/member-tools.ts +2 -2
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/permission-prompt.ts +115 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/permission-relay.ts +111 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/policy-gate.ts +88 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/policy-snapshot.ts +65 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/profile-lookup.ts +60 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/profile-tool.ts +96 -0
- package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/raw-get-stream.ts +55 -17
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/read-tool.ts +87 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/request-identity.ts +48 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/server-approvals.ts +118 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/session-slot.ts +137 -0
- package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/session.ts +103 -52
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/speech-schema.ts +11 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/speech-send.ts +15 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/tool-catalog.ts +108 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/tool-def.ts +9 -0
- package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/tool-dispatch.ts +74 -48
- package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/tool-schemas.ts +87 -114
- package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/mcp/upload-tool.ts +6 -11
- package/runtime/node_modules/@metro-labs/daemon/src/mcp-server/announced.ts +68 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp-server/config.ts +29 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp-server/connector-tools.ts +114 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp-server/link.ts +197 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp-server/rpc.ts +67 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp-server/token.ts +50 -0
- package/runtime/node_modules/@metro-labs/daemon/src/metro-user/helper-script.ts +183 -0
- package/runtime/node_modules/@metro-labs/daemon/src/metro-user/imds.ts +16 -0
- package/runtime/node_modules/@metro-labs/daemon/src/metro-user/install.ts +78 -0
- package/runtime/node_modules/@metro-labs/daemon/src/metro-user/privilege.ts +50 -0
- package/runtime/node_modules/@metro-labs/daemon/src/metro-user/root-follow.ts +16 -0
- package/runtime/node_modules/@metro-labs/daemon/src/monitor/api.ts +132 -0
- package/runtime/node_modules/@metro-labs/daemon/src/monitor/run-event.ts +139 -0
- package/runtime/node_modules/@metro-labs/daemon/src/monitor/run-events.ts +101 -0
- package/runtime/node_modules/@metro-labs/daemon/src/net/tunnel.ts +323 -0
- package/runtime/node_modules/@metro-labs/daemon/src/policy/policy.ts +120 -0
- package/runtime/node_modules/@metro-labs/daemon/src/routes/bearer.ts +35 -0
- package/runtime/node_modules/@metro-labs/daemon/src/routes/body.ts +24 -0
- package/runtime/node_modules/@metro-labs/daemon/src/routes/gmail-attach.ts +67 -0
- package/runtime/node_modules/@metro-labs/daemon/src/routes/gmail-detach.ts +37 -0
- package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/routes}/http.ts +55 -56
- package/runtime/node_modules/@metro-labs/daemon/src/routes/local-mode.ts +155 -0
- package/runtime/node_modules/@metro-labs/daemon/src/routes/pair-again.ts +23 -0
- package/runtime/node_modules/@metro-labs/daemon/src/routes/session-apis.ts +63 -0
- package/runtime/node_modules/@metro-labs/{mcp/src/daemon/session-api.ts → daemon/src/routes/session.ts} +9 -7
- package/runtime/node_modules/@metro-labs/daemon/src/routes/threema-callback.ts +103 -0
- package/runtime/node_modules/@metro-labs/daemon/src/server/cloudwatch.ts +178 -0
- package/runtime/node_modules/@metro-labs/daemon/src/server/control.ts +39 -0
- package/runtime/node_modules/@metro-labs/daemon/src/server/machine.ts +58 -0
- package/runtime/node_modules/@metro-labs/daemon/src/server/owner.ts +26 -0
- package/runtime/node_modules/@metro-labs/daemon/src/server/update.ts +90 -0
- package/runtime/node_modules/@metro-labs/daemon/src/server.ts +2 -0
- package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-browser.ts +107 -0
- package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-driver.ts +42 -0
- package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-gmail.ts +78 -0
- package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/attach-inline.ts +29 -1
- package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/attach-interactive.ts +6 -32
- package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/attach-resolve.ts +84 -13
- package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/stations}/attach-session.ts +70 -27
- package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/attach-xmtp.ts +8 -9
- package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/attach.ts +69 -3
- package/runtime/node_modules/@metro-labs/{mcp/src/db → daemon/src/stations}/materialize.ts +50 -181
- package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/stations/registry.ts +26 -2
- package/runtime/node_modules/@metro-labs/daemon/src/stations/runtime-deps.ts +135 -0
- package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/stations}/supervisor-io.ts +3 -3
- package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/stations}/supervisor.ts +5 -5
- package/runtime/node_modules/@metro-labs/daemon/src/stations/threema-callbacks.ts +32 -0
- package/runtime/node_modules/@metro-labs/{mcp/src/daemon → daemon/src/stations}/train-call.ts +1 -1
- package/runtime/node_modules/@metro-labs/daemon/src/stations/webhook-endpoints.ts +51 -0
- package/runtime/node_modules/@metro-labs/daemon/src/terminal/api.ts +84 -0
- package/runtime/node_modules/@metro-labs/daemon/src/terminal/socket.ts +124 -0
- package/runtime/node_modules/@metro-labs/daemon/src/terminal/tickets.ts +15 -0
- package/runtime/node_modules/@metro-labs/daemon/src/voice/api.ts +14 -0
- package/runtime/node_modules/@metro-labs/daemon/src/voice/audio.ts +193 -0
- package/runtime/node_modules/@metro-labs/daemon/src/voice/call.ts +191 -0
- package/runtime/node_modules/@metro-labs/daemon/src/voice/calls.ts +153 -0
- package/runtime/node_modules/@metro-labs/daemon/src/voice/peer.ts +85 -0
- package/runtime/node_modules/@metro-labs/daemon/src/voice/scribe.ts +115 -0
- package/runtime/node_modules/@metro-labs/daemon/src/voice/shared-talk.ts +85 -0
- package/runtime/node_modules/@metro-labs/daemon/src/voice/shared.ts +198 -0
- package/runtime/node_modules/@metro-labs/daemon/src/voice/speech-queue.ts +200 -0
- package/runtime/node_modules/@metro-labs/daemon/src/voice/speech.ts +125 -0
- package/runtime/node_modules/@metro-labs/daemon/src/voice/store.ts +103 -0
- package/runtime/node_modules/@metro-labs/discord-bot/package.json +3 -5
- package/runtime/node_modules/@metro-labs/discord-bot/src/accounts.ts +3 -23
- package/runtime/node_modules/@metro-labs/discord-bot/src/actions.ts +21 -187
- package/runtime/node_modules/@metro-labs/discord-bot/src/attachments.ts +2 -2
- package/runtime/node_modules/@metro-labs/discord-bot/src/channel-source.ts +79 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/channels.ts +186 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/format.ts +26 -67
- package/runtime/node_modules/@metro-labs/discord-bot/src/group-actions.ts +1 -1
- package/runtime/node_modules/@metro-labs/discord-bot/src/group.ts +2 -2
- package/runtime/node_modules/@metro-labs/discord-bot/src/index.ts +8 -14
- package/runtime/node_modules/@metro-labs/discord-bot/src/members.ts +2 -2
- package/runtime/node_modules/@metro-labs/discord-bot/src/profile.ts +68 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/send-files.ts +12 -13
- package/runtime/node_modules/@metro-labs/discord-bot/src/station.ts +6 -1
- package/runtime/node_modules/@metro-labs/gmail/package.json +27 -0
- package/runtime/node_modules/@metro-labs/gmail/src/accounts.ts +133 -0
- package/runtime/node_modules/@metro-labs/gmail/src/actions.ts +20 -0
- package/runtime/node_modules/@metro-labs/gmail/src/api.ts +34 -0
- package/runtime/node_modules/@metro-labs/gmail/src/attachments.ts +38 -0
- package/runtime/node_modules/@metro-labs/gmail/src/auth.ts +115 -0
- package/runtime/node_modules/@metro-labs/gmail/src/channels.ts +66 -0
- package/runtime/node_modules/@metro-labs/gmail/src/config.ts +15 -0
- package/runtime/node_modules/@metro-labs/gmail/src/inbound.ts +97 -0
- package/runtime/node_modules/@metro-labs/gmail/src/index.ts +12 -0
- package/runtime/node_modules/@metro-labs/gmail/src/login.ts +39 -0
- package/runtime/node_modules/@metro-labs/gmail/src/managed-binding.ts +33 -0
- package/runtime/node_modules/@metro-labs/gmail/src/managed.ts +45 -0
- package/runtime/node_modules/@metro-labs/gmail/src/message.ts +125 -0
- package/runtime/node_modules/@metro-labs/gmail/src/mime.ts +70 -0
- package/runtime/node_modules/@metro-labs/gmail/src/outbound.ts +125 -0
- package/runtime/node_modules/@metro-labs/gmail/src/query.ts +101 -0
- package/runtime/node_modules/@metro-labs/gmail/src/state.ts +30 -0
- package/runtime/node_modules/@metro-labs/gmail/src/station.ts +16 -0
- package/runtime/node_modules/@metro-labs/gmail/src/trust.ts +42 -0
- package/runtime/node_modules/@metro-labs/http/package.json +44 -0
- package/runtime/node_modules/@metro-labs/http/src/agent-signature.ts +95 -0
- package/runtime/node_modules/@metro-labs/http/src/api-http.ts +146 -0
- package/runtime/node_modules/@metro-labs/{mcp/src/daemon/oauth-discovery.ts → http/src/connector-discovery.ts} +57 -27
- package/runtime/node_modules/@metro-labs/http/src/connector-grant.ts +8 -0
- package/runtime/node_modules/@metro-labs/http/src/connector-input.ts +73 -0
- package/runtime/node_modules/@metro-labs/http/src/connector-mcp.ts +108 -0
- package/runtime/node_modules/@metro-labs/{mcp/src/daemon/oauth-client.ts → http/src/connector-oauth.ts} +60 -31
- package/runtime/node_modules/@metro-labs/http/src/connector-policy.ts +92 -0
- package/runtime/node_modules/@metro-labs/http/src/connector-public-url.ts +64 -0
- package/runtime/node_modules/@metro-labs/http/src/connector-reach.ts +27 -0
- package/runtime/node_modules/@metro-labs/http/src/connector-resource.ts +108 -0
- package/runtime/node_modules/@metro-labs/http/src/connector-tools.ts +101 -0
- package/runtime/node_modules/@metro-labs/{mcp/src/daemon → http/src}/connector-url.ts +8 -28
- package/runtime/node_modules/@metro-labs/http/src/ed25519.ts +56 -0
- package/runtime/node_modules/@metro-labs/http/src/mcp-server-protocol.ts +99 -0
- package/runtime/node_modules/@metro-labs/http/src/mcp-server-tools.ts +104 -0
- package/runtime/node_modules/@metro-labs/{mcp/src/daemon → http/src}/mode-api.ts +2 -2
- package/runtime/node_modules/@metro-labs/{mcp/src/daemon/session-config.ts → http/src/return-to.ts} +4 -6
- package/runtime/node_modules/@metro-labs/http/src/sigv4.ts +90 -0
- package/runtime/node_modules/@metro-labs/http/src/workos-token.ts +149 -0
- package/runtime/node_modules/@metro-labs/outlook/package.json +25 -0
- package/runtime/node_modules/@metro-labs/outlook/src/accounts.ts +78 -0
- package/runtime/node_modules/@metro-labs/outlook/src/actions.ts +15 -0
- package/runtime/node_modules/@metro-labs/outlook/src/attachments.ts +81 -0
- package/runtime/node_modules/@metro-labs/outlook/src/auth.ts +120 -0
- package/runtime/node_modules/@metro-labs/outlook/src/browser.ts +42 -0
- package/runtime/node_modules/@metro-labs/outlook/src/channels.ts +60 -0
- package/runtime/node_modules/@metro-labs/outlook/src/config.ts +23 -0
- package/runtime/node_modules/@metro-labs/outlook/src/format.ts +59 -0
- package/runtime/node_modules/@metro-labs/outlook/src/graph.ts +55 -0
- package/runtime/node_modules/@metro-labs/outlook/src/inbound.ts +96 -0
- package/runtime/node_modules/@metro-labs/outlook/src/index.ts +12 -0
- package/runtime/node_modules/@metro-labs/outlook/src/login.ts +129 -0
- package/runtime/node_modules/@metro-labs/outlook/src/me.ts +31 -0
- package/runtime/node_modules/@metro-labs/outlook/src/outbound.ts +103 -0
- package/runtime/node_modules/@metro-labs/outlook/src/query.ts +84 -0
- package/runtime/node_modules/@metro-labs/outlook/src/state.ts +28 -0
- package/runtime/node_modules/@metro-labs/outlook/src/station.ts +16 -0
- package/runtime/node_modules/@metro-labs/outlook/src/trust.ts +41 -0
- package/runtime/node_modules/@metro-labs/telegram/package.json +2 -4
- package/runtime/node_modules/@metro-labs/telegram/src/accounts.ts +5 -24
- package/runtime/node_modules/@metro-labs/telegram/src/actions.ts +27 -6
- package/runtime/node_modules/@metro-labs/telegram/src/attachments.ts +1 -1
- package/runtime/node_modules/@metro-labs/telegram/src/channels.ts +58 -0
- package/runtime/node_modules/@metro-labs/telegram/src/client.ts +4 -4
- package/runtime/node_modules/@metro-labs/telegram/src/format.ts +19 -34
- package/runtime/node_modules/@metro-labs/telegram/src/group.ts +3 -3
- package/runtime/node_modules/@metro-labs/telegram/src/inbound.ts +13 -34
- package/runtime/node_modules/@metro-labs/telegram/src/index.ts +4 -43
- package/runtime/node_modules/@metro-labs/telegram/src/media-actions.ts +2 -3
- package/runtime/node_modules/@metro-labs/telegram/src/members.ts +1 -1
- package/runtime/node_modules/@metro-labs/telegram/src/profile.ts +70 -0
- package/runtime/node_modules/@metro-labs/telegram/src/reactions.ts +2 -2
- package/runtime/node_modules/@metro-labs/telegram/src/station.ts +5 -1
- package/runtime/node_modules/@metro-labs/telegram/src/types.ts +0 -1
- package/runtime/node_modules/@metro-labs/telegram-bot/package.json +2 -2
- package/runtime/node_modules/@metro-labs/telegram-bot/src/accounts.ts +7 -41
- package/runtime/node_modules/@metro-labs/telegram-bot/src/actions.ts +24 -77
- package/runtime/node_modules/@metro-labs/telegram-bot/src/attachments.ts +2 -2
- package/runtime/node_modules/@metro-labs/telegram-bot/src/channel-files.ts +3 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/channels.ts +43 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/format.ts +46 -48
- package/runtime/node_modules/@metro-labs/telegram-bot/src/index.ts +15 -44
- package/runtime/node_modules/@metro-labs/telegram-bot/src/media-actions.ts +6 -82
- package/runtime/node_modules/@metro-labs/telegram-bot/src/members.ts +1 -1
- package/runtime/node_modules/@metro-labs/telegram-bot/src/observed-chats.ts +172 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/profile.ts +85 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/station.ts +9 -1
- package/runtime/node_modules/@metro-labs/telegram-bot/src/types.ts +50 -15
- package/runtime/node_modules/@metro-labs/telegram-bot/src/updates.ts +26 -0
- package/runtime/node_modules/@metro-labs/threema/package.json +26 -0
- package/runtime/node_modules/@metro-labs/threema/src/accounts.ts +108 -0
- package/runtime/node_modules/@metro-labs/threema/src/actions.ts +130 -0
- package/runtime/node_modules/@metro-labs/threema/src/api.ts +152 -0
- package/runtime/node_modules/@metro-labs/threema/src/channels.ts +37 -0
- package/runtime/node_modules/@metro-labs/threema/src/chats.ts +88 -0
- package/runtime/node_modules/@metro-labs/threema/src/crypto.ts +100 -0
- package/runtime/node_modules/@metro-labs/threema/src/files.ts +47 -0
- package/runtime/node_modules/@metro-labs/threema/src/format.ts +164 -0
- package/runtime/node_modules/@metro-labs/threema/src/groups.ts +96 -0
- package/runtime/node_modules/@metro-labs/threema/src/ids.ts +21 -0
- package/runtime/node_modules/@metro-labs/threema/src/inbound.ts +92 -0
- package/runtime/node_modules/@metro-labs/threema/src/index.ts +24 -0
- package/runtime/node_modules/@metro-labs/threema/src/messages.ts +264 -0
- package/runtime/node_modules/@metro-labs/threema/src/outbound.ts +161 -0
- package/runtime/node_modules/@metro-labs/threema/src/station.ts +21 -0
- package/runtime/node_modules/@metro-labs/threema/src/verify.ts +117 -0
- package/runtime/node_modules/@metro-labs/webhook/package.json +2 -2
- package/runtime/node_modules/@metro-labs/webhook/src/station.ts +5 -8
- package/runtime/node_modules/@metro-labs/whatsapp/package.json +3 -6
- package/runtime/node_modules/@metro-labs/whatsapp/src/accounts.ts +6 -28
- package/runtime/node_modules/@metro-labs/whatsapp/src/ack.ts +1 -1
- package/runtime/node_modules/@metro-labs/whatsapp/src/actions.ts +100 -14
- package/runtime/node_modules/@metro-labs/whatsapp/src/app-state.ts +49 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/attachments.ts +2 -2
- package/runtime/node_modules/@metro-labs/whatsapp/src/auth-state.ts +1 -1
- package/runtime/node_modules/@metro-labs/whatsapp/src/channel-chats.ts +137 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/channels.ts +48 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/client-history.ts +31 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/client-types.ts +50 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/client.ts +161 -84
- package/runtime/node_modules/@metro-labs/whatsapp/src/connection.ts +139 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/format.ts +7 -58
- package/runtime/node_modules/@metro-labs/whatsapp/src/history-events.ts +127 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/history-files.ts +39 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/history-identity.ts +58 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/history-message.ts +161 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/history-state.ts +344 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/history-types.ts +91 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/history.ts +195 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/inbound.ts +11 -28
- package/runtime/node_modules/@metro-labs/whatsapp/src/index.ts +4 -37
- package/runtime/node_modules/@metro-labs/whatsapp/src/keys.ts +1 -1
- package/runtime/node_modules/@metro-labs/whatsapp/src/login.ts +37 -4
- package/runtime/node_modules/@metro-labs/whatsapp/src/media.ts +1 -1
- package/runtime/node_modules/@metro-labs/whatsapp/src/members.ts +94 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/messages.ts +91 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/names.ts +106 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/parse.ts +44 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/profile.ts +158 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/resolve.ts +52 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/send-expiry.ts +65 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/station.ts +26 -1
- package/runtime/node_modules/@metro-labs/whatsapp/src/token-store.ts +5 -9
- package/runtime/node_modules/@metro-labs/whatsapp/src/types.ts +0 -1
- package/runtime/node_modules/@metro-labs/xmtp/package.json +4 -3
- package/runtime/node_modules/@metro-labs/xmtp/src/accounts.ts +10 -20
- package/runtime/node_modules/@metro-labs/xmtp/src/actions-close.ts +2 -2
- package/runtime/node_modules/@metro-labs/xmtp/src/actions-conv.ts +55 -224
- package/runtime/node_modules/@metro-labs/xmtp/src/actions-meta.ts +55 -54
- package/runtime/node_modules/@metro-labs/xmtp/src/actions.ts +114 -223
- package/runtime/node_modules/@metro-labs/xmtp/src/attachments.ts +58 -15
- package/runtime/node_modules/@metro-labs/xmtp/src/call-leftovers.ts +48 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/channels.ts +56 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/codecs.ts +114 -3
- package/runtime/node_modules/@metro-labs/xmtp/src/conv-helpers.ts +36 -20
- package/runtime/node_modules/@metro-labs/xmtp/src/delete-requests.ts +34 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/emit-payloads.ts +38 -25
- package/runtime/node_modules/@metro-labs/xmtp/src/emit.ts +8 -18
- package/runtime/node_modules/@metro-labs/xmtp/src/frames.ts +190 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/group-members.ts +1 -1
- package/runtime/node_modules/@metro-labs/xmtp/src/group.ts +2 -2
- package/runtime/node_modules/@metro-labs/xmtp/src/identity.ts +30 -16
- package/runtime/node_modules/@metro-labs/xmtp/src/index.ts +18 -70
- package/runtime/node_modules/@metro-labs/xmtp/src/labels.ts +102 -50
- package/runtime/node_modules/@metro-labs/xmtp/src/member-args.ts +1 -1
- package/runtime/node_modules/@metro-labs/xmtp/src/names.ts +61 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/network.ts +114 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/profile.ts +160 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/read-attachments.ts +37 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/resolve.ts +44 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/sender.ts +112 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/smart.ts +79 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/station.ts +10 -2
- package/runtime/node_modules/@metro-labs/xmtp/src/stream.ts +66 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/tools-handlers.ts +32 -60
- package/runtime/node_modules/@metro-labs/xmtp/src/tools.ts +78 -49
- package/runtime/node_modules/@metro-labs/xmtp/src/transcribe.ts +4 -6
- package/runtime/node_modules/@metro-labs/xmtp/src/verify.ts +19 -5
- package/runtime/node_modules/@metro-labs/xmtp/src/wallet.ts +28 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/wire.ts +14 -4
- package/runtime/patches/5bca2c07d5852d3f58453cff0448dd85da13d3665b61e3d758905b298d432d7c.patch +31 -0
- package/runtime/runtime.json +1 -1
- package/runtime/sdk-runner/node_modules/@metro-labs/core/package.json +61 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/automation-files.ts +216 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/automation-store.ts +171 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/automation-types.ts +141 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/call.ts +81 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/claude-token.ts +3 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/effort.ts +21 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/endpoints.ts +7 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/events.ts +165 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/ids.ts +28 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/is-record.ts +2 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/lines.ts +78 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/log.ts +42 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/protocol.ts +227 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/runner-activity.ts +270 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/secure-fs.ts +74 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/skill-source.ts +96 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/station-names.ts +14 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/stations/account-files.ts +41 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/stations/account-status.ts +26 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/stations/account-store.ts +83 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/stations/attachments.ts +202 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/stations/channel-directory.ts +159 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/stations/channel-pages.ts +129 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/stations/mail-text.ts +72 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/stations/mail-trust.ts +29 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/stations/mail.ts +212 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/stations/messaging-normalize.ts +16 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/stations/oauth.ts +126 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/stations/profile.ts +58 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/stations/sender-profile.ts +64 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/stations/station-runtime.ts +59 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/stations/train-boot.ts +63 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/stations/train-events.ts +84 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/stations/types.ts +128 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/str.ts +5 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/tickets.ts +44 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/train-error.ts +53 -0
- package/runtime/sdk-runner/node_modules/@metro-labs/core/src/version.ts +2 -0
- package/runtime/sdk-runner/runner.json +10 -0
- package/runtime/sdk-runner/src/activity-tasks.ts +194 -0
- package/runtime/sdk-runner/src/activity.ts +392 -0
- package/runtime/sdk-runner/src/app.ts +87 -0
- package/runtime/sdk-runner/src/approvals.ts +37 -0
- package/runtime/sdk-runner/src/automation-cli.ts +10 -0
- package/runtime/sdk-runner/src/automation-command.ts +151 -0
- package/runtime/sdk-runner/src/automation.ts +145 -0
- package/runtime/sdk-runner/src/calls.ts +133 -0
- package/runtime/sdk-runner/src/channel-text.ts +26 -0
- package/runtime/sdk-runner/src/config.ts +50 -0
- package/runtime/sdk-runner/src/errors.ts +142 -0
- package/runtime/sdk-runner/src/inbox.ts +168 -0
- package/runtime/sdk-runner/src/input-queue.ts +77 -0
- package/runtime/sdk-runner/src/input-timing.ts +68 -0
- package/runtime/sdk-runner/src/link.ts +154 -0
- package/runtime/sdk-runner/src/main.ts +57 -0
- package/runtime/sdk-runner/src/recovery.ts +46 -0
- package/runtime/sdk-runner/src/rules.ts +28 -0
- package/runtime/sdk-runner/src/runner.ts +358 -0
- package/runtime/sdk-runner/src/session-store.ts +129 -0
- package/runtime/sdk-runner/src/session-watch.ts +158 -0
- package/runtime/sdk-runner/src/singleton.ts +15 -0
- package/runtime/sdk-runner/src/skill-work.ts +76 -0
- package/runtime/sdk-runner/src/skills-files.ts +169 -0
- package/runtime/sdk-runner/src/skills.ts +150 -0
- package/runtime/sdk-runner/src/task-ledger.ts +244 -0
- package/runtime/sdk-runner/src/task-recovery.ts +203 -0
- package/runtime/sdk-runner/src/task-state.ts +77 -0
- package/runtime/sdk-runner/src/tool-proxy.ts +40 -0
- package/runtime/server.ts +1 -0
- package/runtime/stations.json +43 -0
- package/skills/MEMORY.md +78 -0
- package/skills/METRO.md +35 -0
- package/skills/STAGE.md +110 -0
- package/dist/bedrock-eventstream.js +0 -120
- package/dist/bedrock-proxy.js +0 -260
- package/dist/bedrock-upstream.js +0 -72
- package/dist/bedrock.js +0 -106
- package/dist/claude.js +0 -15
- package/dist/plugin.js +0 -82
- package/dist/prompt.js +0 -61
- package/dist/store.js +0 -93
- package/runtime/node_modules/@metro-labs/discord-bot/src/voice-speak.ts +0 -195
- package/runtime/node_modules/@metro-labs/discord-bot/src/voice-transcribe.ts +0 -292
- package/runtime/node_modules/@metro-labs/discord-bot/src/voice.ts +0 -197
- package/runtime/node_modules/@metro-labs/discord-bot/src/wire.ts +0 -5
- package/runtime/node_modules/@metro-labs/mcp/package.json +0 -67
- package/runtime/node_modules/@metro-labs/mcp/src/channels/dedupe.ts +0 -24
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/account-api.ts +0 -311
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/agent-api.ts +0 -333
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/agent-connector-api.ts +0 -150
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/agent-pair.ts +0 -20
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/api-http.ts +0 -153
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/boot.ts +0 -368
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/cli-pair-api.ts +0 -134
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-api.ts +0 -313
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-json.ts +0 -21
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-oauth-routes.ts +0 -157
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-oauth.ts +0 -127
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-tools.ts +0 -100
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-verify.ts +0 -333
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/identity.ts +0 -86
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/local-mode.ts +0 -158
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/local-secret.ts +0 -21
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/oauth-pending.ts +0 -65
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/pair-codes.ts +0 -58
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/project-api.ts +0 -214
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/relay.ts +0 -303
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/run-api.ts +0 -139
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/runtime-source.ts +0 -105
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/session-apis.ts +0 -52
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/session.ts +0 -218
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/siwe-auth.ts +0 -82
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/siwe-nonces.ts +0 -43
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/siwe-routes.ts +0 -89
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/tunnel.ts +0 -169
- package/runtime/node_modules/@metro-labs/mcp/src/db/account-attach.ts +0 -91
- package/runtime/node_modules/@metro-labs/mcp/src/db/agent-admin.ts +0 -214
- package/runtime/node_modules/@metro-labs/mcp/src/db/agent-connectors.ts +0 -143
- package/runtime/node_modules/@metro-labs/mcp/src/db/agent-map.ts +0 -71
- package/runtime/node_modules/@metro-labs/mcp/src/db/client.ts +0 -37
- package/runtime/node_modules/@metro-labs/mcp/src/db/connector-config.ts +0 -147
- package/runtime/node_modules/@metro-labs/mcp/src/db/connector-relay.ts +0 -126
- package/runtime/node_modules/@metro-labs/mcp/src/db/connectors.ts +0 -308
- package/runtime/node_modules/@metro-labs/mcp/src/db/file-admin.ts +0 -250
- package/runtime/node_modules/@metro-labs/mcp/src/db/projects.ts +0 -309
- package/runtime/node_modules/@metro-labs/mcp/src/db/runtime-admin.ts +0 -24
- package/runtime/node_modules/@metro-labs/mcp/src/db/runtimes.ts +0 -105
- package/runtime/node_modules/@metro-labs/mcp/src/db/schema.ts +0 -118
- package/runtime/node_modules/@metro-labs/mcp/src/db/token-carry.ts +0 -45
- package/runtime/node_modules/@metro-labs/mcp/src/db/users.ts +0 -72
- package/runtime/node_modules/@metro-labs/mcp/src/db/whatsapp-login.ts +0 -18
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/channel-owner.ts +0 -29
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/frame-scope.ts +0 -21
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/index.ts +0 -192
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/permission-relay.ts +0 -66
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/request-identity.ts +0 -73
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/session-registry.ts +0 -172
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/session-route.ts +0 -43
- package/runtime/node_modules/@metro-labs/mcp/src/monitor/api.ts +0 -240
- package/runtime/node_modules/@metro-labs/mcp/src/server.ts +0 -2
- package/runtime/node_modules/@metro-labs/mcp/src/stations/account-store.ts +0 -80
- package/runtime/node_modules/@metro-labs/mcp/src/stations/messaging-normalize.ts +0 -88
- package/runtime/node_modules/@metro-labs/telegram/src/normalize.ts +0 -22
- package/runtime/node_modules/@metro-labs/telegram/src/wire.ts +0 -1
- package/runtime/node_modules/@metro-labs/telegram-bot/src/wire.ts +0 -3
- package/runtime/node_modules/@metro-labs/whatsapp/src/normalize.ts +0 -22
- package/runtime/node_modules/@metro-labs/whatsapp/src/wire.ts +0 -5
- package/runtime/node_modules/@metro-labs/xmtp/src/actions-push.ts +0 -87
- package/runtime/node_modules/@metro-labs/xmtp/src/emit-core.ts +0 -55
- package/runtime/node_modules/@metro-labs/xmtp/src/push.ts +0 -349
- /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/log.ts +0 -0
- /package/runtime/node_modules/@metro-labs/{mcp/src/mcp → core/src}/str.ts +0 -0
- /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → core/src}/train-error.ts +0 -0
- /package/runtime/node_modules/@metro-labs/{mcp → daemon}/src/channels/webhook-note.ts +0 -0
- /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → http/src}/api-error.ts +0 -0
- /package/runtime/node_modules/@metro-labs/{mcp/src/daemon → http/src}/cors.ts +0 -0
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isRecord } from '@metro-labs/core/is-record';
|
|
2
|
+
import type { FetchLike } from '@metro-labs/core/stations/oauth';
|
|
3
|
+
import { stringOf } from './api-http.js';
|
|
4
|
+
import { parseConnectorUrl, refused } from './connector-url.js';
|
|
2
5
|
|
|
3
6
|
const DISCOVERY_TIMEOUT_MS = 10_000;
|
|
4
7
|
|
|
@@ -8,23 +11,18 @@ export interface OAuthServer {
|
|
|
8
11
|
tokenEndpoint: string;
|
|
9
12
|
registrationEndpoint: string | null;
|
|
10
13
|
supportsS256: boolean;
|
|
14
|
+
scopes: string[];
|
|
11
15
|
}
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
|
|
17
|
+
interface ResourceMetadata {
|
|
18
|
+
issuer: URL;
|
|
19
|
+
scopes: string[];
|
|
15
20
|
}
|
|
16
21
|
|
|
17
|
-
function
|
|
18
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const str = (value: unknown): string =>
|
|
22
|
-
typeof value === 'string' ? value : '';
|
|
23
|
-
|
|
24
|
-
async function getJson(url: URL): Promise<Record<string, unknown> | null> {
|
|
22
|
+
async function getJson(url: URL, fetchImpl: FetchLike): Promise<Record<string, unknown> | null> {
|
|
25
23
|
let res: Response;
|
|
26
24
|
try {
|
|
27
|
-
res = await
|
|
25
|
+
res = await fetchImpl(url.toString(), {
|
|
28
26
|
redirect: 'manual',
|
|
29
27
|
signal: AbortSignal.timeout(DISCOVERY_TIMEOUT_MS),
|
|
30
28
|
headers: { accept: 'application/json' },
|
|
@@ -58,9 +56,9 @@ export function resourceMetadataUrls(resource: URL): URL[] {
|
|
|
58
56
|
return urls;
|
|
59
57
|
}
|
|
60
58
|
|
|
61
|
-
export async function advertisesOAuth(resource: URL): Promise<boolean> {
|
|
59
|
+
export async function advertisesOAuth(resource: URL, fetchImpl: FetchLike = fetch): Promise<boolean> {
|
|
62
60
|
for (const candidate of resourceMetadataUrls(resource)) {
|
|
63
|
-
const body = await getJson(candidate);
|
|
61
|
+
const body = await getJson(candidate, fetchImpl);
|
|
64
62
|
const servers: unknown = body?.authorization_servers;
|
|
65
63
|
const first: unknown = Array.isArray(servers) ? servers[0] : undefined;
|
|
66
64
|
if (typeof first === 'string' && first !== '') return true;
|
|
@@ -68,32 +66,64 @@ export async function advertisesOAuth(resource: URL): Promise<boolean> {
|
|
|
68
66
|
return false;
|
|
69
67
|
}
|
|
70
68
|
|
|
71
|
-
|
|
69
|
+
function scopesOf(body: Record<string, unknown> | null): string[] {
|
|
70
|
+
const raw: unknown = body?.scopes_supported;
|
|
71
|
+
if (!Array.isArray(raw)) return [];
|
|
72
|
+
const out: string[] = [];
|
|
73
|
+
for (const entry of raw) {
|
|
74
|
+
const scope = stringOf(entry).trim();
|
|
75
|
+
if (scope !== '' && !/\s/.test(scope) && !out.includes(scope)) out.push(scope);
|
|
76
|
+
}
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async function resourceMetadata(resource: URL, fetchImpl: FetchLike): Promise<ResourceMetadata> {
|
|
72
81
|
for (const candidate of resourceMetadataUrls(resource)) {
|
|
73
|
-
const body = await getJson(candidate);
|
|
82
|
+
const body = await getJson(candidate, fetchImpl);
|
|
74
83
|
const servers: unknown = body?.authorization_servers;
|
|
75
84
|
const first: unknown = Array.isArray(servers) ? servers[0] : undefined;
|
|
76
85
|
if (typeof first === 'string' && first !== '')
|
|
77
|
-
return parseConnectorUrl(first);
|
|
86
|
+
return { issuer: parseConnectorUrl(first), scopes: scopesOf(body) };
|
|
78
87
|
}
|
|
79
|
-
return parseConnectorUrl(resource.origin);
|
|
88
|
+
return { issuer: parseConnectorUrl(resource.origin), scopes: [] };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const webAddress = (text: string): boolean => {
|
|
92
|
+
try {
|
|
93
|
+
parseConnectorUrl(text);
|
|
94
|
+
return true;
|
|
95
|
+
} catch {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
function endpointOf(raw: unknown, issuer: URL): string {
|
|
101
|
+
const text = stringOf(raw);
|
|
102
|
+
if (text !== '' && !webAddress(text)) throw refused(`${issuer.hostname} advertises a sign-in address Metro will not open.`);
|
|
103
|
+
return text;
|
|
80
104
|
}
|
|
81
105
|
|
|
82
|
-
function toServer(
|
|
83
|
-
|
|
84
|
-
|
|
106
|
+
function toServer(
|
|
107
|
+
body: Record<string, unknown>,
|
|
108
|
+
issuer: URL,
|
|
109
|
+
scopes: string[],
|
|
110
|
+
): OAuthServer {
|
|
111
|
+
const authorizationEndpoint = endpointOf(body.authorization_endpoint, issuer);
|
|
112
|
+
const tokenEndpoint = endpointOf(body.token_endpoint, issuer);
|
|
85
113
|
if (authorizationEndpoint === '' || tokenEndpoint === '')
|
|
86
114
|
throw refused(
|
|
87
115
|
`${issuer.hostname} advertises OAuth but not where to sign in.`,
|
|
88
116
|
);
|
|
89
117
|
const methods = body.code_challenge_methods_supported;
|
|
90
|
-
const
|
|
118
|
+
const offered = stringOf(body.registration_endpoint);
|
|
119
|
+
const registration = webAddress(offered) ? offered : '';
|
|
91
120
|
return {
|
|
92
|
-
issuer:
|
|
121
|
+
issuer: stringOf(body.issuer) === '' ? issuer.origin : stringOf(body.issuer),
|
|
93
122
|
authorizationEndpoint,
|
|
94
123
|
tokenEndpoint,
|
|
95
124
|
registrationEndpoint: registration === '' ? null : registration,
|
|
96
125
|
supportsS256: Array.isArray(methods) ? methods.includes('S256') : false,
|
|
126
|
+
scopes,
|
|
97
127
|
};
|
|
98
128
|
}
|
|
99
129
|
|
|
@@ -108,11 +138,11 @@ export function authServerMetadataUrls(issuer: URL): URL[] {
|
|
|
108
138
|
return [...aware, new URL(`${path}/.well-known/openid-configuration`, issuer.origin), ...urls];
|
|
109
139
|
}
|
|
110
140
|
|
|
111
|
-
export async function discoverOAuth(resource: URL): Promise<OAuthServer> {
|
|
112
|
-
const issuer = await
|
|
141
|
+
export async function discoverOAuth(resource: URL, fetchImpl: FetchLike = fetch): Promise<OAuthServer> {
|
|
142
|
+
const { issuer, scopes } = await resourceMetadata(resource, fetchImpl);
|
|
113
143
|
for (const candidate of authServerMetadataUrls(issuer)) {
|
|
114
|
-
const body = await getJson(candidate);
|
|
115
|
-
if (body !== null) return toServer(body, issuer);
|
|
144
|
+
const body = await getJson(candidate, fetchImpl);
|
|
145
|
+
if (body !== null) return toServer(body, issuer, scopes);
|
|
116
146
|
}
|
|
117
147
|
throw refused(
|
|
118
148
|
`${resource.hostname} needs authorization, but publishes no OAuth metadata Metro can use.`,
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { boundOAuthResource, parsePublicConnectorUrl } from './connector-public-url.js';
|
|
2
|
+
|
|
3
|
+
export function grantResource(target: string, raw: unknown): string {
|
|
4
|
+
const transport = parsePublicConnectorUrl(target);
|
|
5
|
+
const resource = parsePublicConnectorUrl(raw);
|
|
6
|
+
if (resource.toString() === transport.toString() && typeof raw === 'string') return raw;
|
|
7
|
+
return boundOAuthResource(target, raw);
|
|
8
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { ApiError } from './api-error.js';
|
|
2
|
+
import { stringOf } from './api-http.js';
|
|
3
|
+
import type { ConnectorAuth } from './connector-mcp.js';
|
|
4
|
+
import type { OAuthClient } from './connector-oauth.js';
|
|
5
|
+
|
|
6
|
+
const CONNECTOR_NAME_MAX = 64;
|
|
7
|
+
const HEADER_NAME_RE = /^[A-Za-z0-9!#$%&'*+.^_`|~-]{1,64}$/;
|
|
8
|
+
const HEADER_VALUE_RE = /^[\x20-\x7e]{1,4096}$/;
|
|
9
|
+
const CLIENT_ID_RE = /^[\x21-\x7e]{1,256}$/;
|
|
10
|
+
const CLIENT_SECRET_RE = /^[\x21-\x7e]{1,1024}$/;
|
|
11
|
+
const DEFAULT_HEADER = 'Authorization';
|
|
12
|
+
|
|
13
|
+
export class ConnectorError extends ApiError {}
|
|
14
|
+
|
|
15
|
+
function hasControlChar(value: string): boolean {
|
|
16
|
+
for (const ch of value) {
|
|
17
|
+
const code = ch.codePointAt(0) ?? 0;
|
|
18
|
+
if (code < 0x20 || code === 0x7f) return true;
|
|
19
|
+
}
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function connectorName(raw: unknown): string {
|
|
24
|
+
const name = typeof raw === 'string' ? raw.trim() : '';
|
|
25
|
+
if (name === '') throw new ConnectorError('a connector needs a name', 400);
|
|
26
|
+
if (name.length > CONNECTOR_NAME_MAX)
|
|
27
|
+
throw new ConnectorError(
|
|
28
|
+
`a connector name must be ${String(CONNECTOR_NAME_MAX)} characters or fewer`,
|
|
29
|
+
400,
|
|
30
|
+
);
|
|
31
|
+
if (hasControlChar(name))
|
|
32
|
+
throw new ConnectorError(
|
|
33
|
+
'a connector name must not contain control characters',
|
|
34
|
+
400,
|
|
35
|
+
);
|
|
36
|
+
return name;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function connectorAuth(
|
|
40
|
+
rawHeader: unknown,
|
|
41
|
+
rawValue: unknown,
|
|
42
|
+
): ConnectorAuth {
|
|
43
|
+
const header = stringOf(rawHeader).trim();
|
|
44
|
+
const value = stringOf(rawValue).trim();
|
|
45
|
+
if (header === '' && value === '') return { kind: 'none' };
|
|
46
|
+
if (value === '')
|
|
47
|
+
throw new ConnectorError(
|
|
48
|
+
'that header has no value. Give both a header name and its value, or neither.',
|
|
49
|
+
400,
|
|
50
|
+
);
|
|
51
|
+
const name = header === '' ? DEFAULT_HEADER : header;
|
|
52
|
+
if (!HEADER_NAME_RE.test(name) || ['__proto__', 'constructor', 'prototype'].includes(name))
|
|
53
|
+
throw new ConnectorError('that is not a valid HTTP header name', 400);
|
|
54
|
+
if (!HEADER_VALUE_RE.test(value))
|
|
55
|
+
throw new ConnectorError('that header value is not sendable', 400);
|
|
56
|
+
return { kind: 'header', name, value };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function connectorClient(
|
|
60
|
+
rawId: unknown,
|
|
61
|
+
rawSecret: unknown,
|
|
62
|
+
): OAuthClient | null {
|
|
63
|
+
const clientId = stringOf(rawId).trim();
|
|
64
|
+
const clientSecret = stringOf(rawSecret).trim();
|
|
65
|
+
if (clientId === '' && clientSecret === '') return null;
|
|
66
|
+
if (clientId === '')
|
|
67
|
+
throw new ConnectorError('a client secret needs the client ID it belongs to', 400);
|
|
68
|
+
if (!CLIENT_ID_RE.test(clientId))
|
|
69
|
+
throw new ConnectorError('that is not a client ID Metro can send', 400);
|
|
70
|
+
if (clientSecret !== '' && !CLIENT_SECRET_RE.test(clientSecret))
|
|
71
|
+
throw new ConnectorError('that client secret is not sendable', 400);
|
|
72
|
+
return { clientId, ...(clientSecret === '' ? {} : { clientSecret }) };
|
|
73
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { isRecord } from '@metro-labs/core/is-record';
|
|
2
|
+
import type { FetchLike } from '@metro-labs/core/stations/oauth';
|
|
3
|
+
import { ApiError } from './api-error.js';
|
|
4
|
+
import { whyUnreachable } from './connector-reach.js';
|
|
5
|
+
import { ConnectorUnauthorized, refused } from './connector-url.js';
|
|
6
|
+
|
|
7
|
+
export interface OAuthTokens {
|
|
8
|
+
accessToken: string;
|
|
9
|
+
refreshToken?: string;
|
|
10
|
+
expiresAt?: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface OAuthAuth extends OAuthTokens {
|
|
14
|
+
kind: 'oauth';
|
|
15
|
+
issuer: string;
|
|
16
|
+
tokenEndpoint: string;
|
|
17
|
+
clientId: string;
|
|
18
|
+
clientSecret?: string;
|
|
19
|
+
scope?: string;
|
|
20
|
+
resource?: string;
|
|
21
|
+
tokenEndpointAuthMethod?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type ConnectorAuth =
|
|
25
|
+
| { kind: 'none' }
|
|
26
|
+
| { kind: 'header'; name: string; value: string }
|
|
27
|
+
| OAuthAuth;
|
|
28
|
+
|
|
29
|
+
export interface VerifiedServer {
|
|
30
|
+
server: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface VerifiedRecord extends VerifiedServer {
|
|
34
|
+
at: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const PROBE_TIMEOUT_MS = 10_000;
|
|
38
|
+
|
|
39
|
+
export const INITIALIZE = {
|
|
40
|
+
jsonrpc: '2.0',
|
|
41
|
+
id: 1,
|
|
42
|
+
method: 'initialize',
|
|
43
|
+
params: { protocolVersion: '2025-11-25', capabilities: {}, clientInfo: { name: 'metro', version: '0.1.0' } },
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export function authHeaders(auth: ConnectorAuth): Record<string, string> {
|
|
47
|
+
if (auth.kind === 'header') return { [auth.name]: auth.value };
|
|
48
|
+
if (auth.kind === 'oauth') return { Authorization: `Bearer ${auth.accessToken}` };
|
|
49
|
+
return {};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function payloadOf(text: string, contentType: string): string {
|
|
53
|
+
if (!contentType.includes('text/event-stream')) return text;
|
|
54
|
+
for (const line of text.replace(/\r\n/g, '\n').split('\n')) if (line.startsWith('data:')) return line.slice(5).trim();
|
|
55
|
+
return '';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export async function mcpPost(
|
|
59
|
+
url: URL,
|
|
60
|
+
auth: ConnectorAuth,
|
|
61
|
+
body: unknown,
|
|
62
|
+
opts: { timeoutMs: number; headers?: Record<string, string>; fetch?: FetchLike },
|
|
63
|
+
): Promise<Response> {
|
|
64
|
+
const send = opts.fetch ?? fetch;
|
|
65
|
+
try {
|
|
66
|
+
return await send(url.toString(), {
|
|
67
|
+
method: 'POST',
|
|
68
|
+
redirect: 'manual',
|
|
69
|
+
signal: AbortSignal.timeout(opts.timeoutMs),
|
|
70
|
+
headers: { 'content-type': 'application/json', accept: 'application/json, text/event-stream', ...authHeaders(auth), ...opts.headers },
|
|
71
|
+
body: JSON.stringify(body),
|
|
72
|
+
});
|
|
73
|
+
} catch (err) {
|
|
74
|
+
if (err instanceof ApiError) throw err;
|
|
75
|
+
throw refused(`Metro could not reach ${url.hostname}: ${whyUnreachable(err)}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function serverNameOf(url: URL, text: string, contentType: string): string {
|
|
80
|
+
let parsed: unknown;
|
|
81
|
+
try {
|
|
82
|
+
parsed = JSON.parse(payloadOf(text, contentType));
|
|
83
|
+
} catch {
|
|
84
|
+
throw refused(`${url.hostname} answered, but it does not speak MCP.`);
|
|
85
|
+
}
|
|
86
|
+
const result = isRecord(parsed) && isRecord(parsed.result) ? parsed.result : null;
|
|
87
|
+
if (result === null || typeof result.protocolVersion !== 'string') throw refused(`${url.hostname} answered, but it does not speak MCP.`);
|
|
88
|
+
const info = isRecord(result.serverInfo) ? result.serverInfo : {};
|
|
89
|
+
const title = typeof info.title === 'string' ? info.title : '';
|
|
90
|
+
if (title !== '') return title;
|
|
91
|
+
return typeof info.name === 'string' ? info.name : url.hostname;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function refuseStatus(res: Response, url: URL, auth: ConnectorAuth): void {
|
|
95
|
+
if (res.status >= 300 && res.status < 400) throw refused('that url redirects. Use the url it redirects to.');
|
|
96
|
+
if (res.status === 401 || res.status === 403)
|
|
97
|
+
throw new ConnectorUnauthorized(auth.kind === 'none' ? `${url.hostname} requires authorization.` : `${url.hostname} rejected that credential.`, 400);
|
|
98
|
+
if (res.status === 404 || res.status === 405)
|
|
99
|
+
throw refused(`${url.hostname} did not accept an MCP initialize over HTTP POST. If it is a legacy SSE server, Metro cannot verify it yet.`);
|
|
100
|
+
if (!res.ok) throw refused(`${url.hostname} answered ${String(res.status)} instead of an MCP initialize.`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export async function verifyRemoteMcp(url: URL, auth: ConnectorAuth, fetchImpl: FetchLike = fetch): Promise<VerifiedServer> {
|
|
104
|
+
const res = await mcpPost(url, auth, INITIALIZE, { timeoutMs: PROBE_TIMEOUT_MS, fetch: fetchImpl });
|
|
105
|
+
const text = await res.text().catch(() => '');
|
|
106
|
+
refuseStatus(res, url, auth);
|
|
107
|
+
return { server: serverNameOf(url, text, res.headers.get('content-type') ?? '') };
|
|
108
|
+
}
|
|
@@ -1,26 +1,23 @@
|
|
|
1
1
|
import { createHash, randomBytes } from 'node:crypto';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
} from './connector-
|
|
6
|
-
import type {
|
|
2
|
+
import { isRecord } from '@metro-labs/core/is-record';
|
|
3
|
+
import type { FetchLike } from '@metro-labs/core/stations/oauth';
|
|
4
|
+
import { whyUnreachable } from './connector-reach.js';
|
|
5
|
+
import { ConnectorVerifyError, refused } from './connector-url.js';
|
|
6
|
+
import type { OAuthTokens } from './connector-mcp.js';
|
|
7
|
+
import type { OAuthServer } from './connector-discovery.js';
|
|
7
8
|
|
|
8
9
|
const TOKEN_TIMEOUT_MS = 15_000;
|
|
9
10
|
const CLIENT_NAME = 'Metro';
|
|
10
11
|
|
|
12
|
+
export class OAuthInvalidGrant extends ConnectorVerifyError {}
|
|
13
|
+
|
|
14
|
+
const SIGN_IN_AGAIN = new Set(['invalid_grant', 'invalid_client', 'unauthorized_client']);
|
|
15
|
+
|
|
11
16
|
export interface OAuthClient {
|
|
12
17
|
clientId: string;
|
|
13
18
|
clientSecret?: string;
|
|
14
19
|
}
|
|
15
20
|
|
|
16
|
-
function refused(message: string): ConnectorVerifyError {
|
|
17
|
-
return new ConnectorVerifyError(message, 400);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
21
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
21
|
export function newVerifier(): string {
|
|
25
22
|
return randomBytes(32).toString('base64url');
|
|
26
23
|
}
|
|
@@ -32,14 +29,17 @@ export function challengeOf(verifier: string): string {
|
|
|
32
29
|
export async function registerClient(
|
|
33
30
|
server: OAuthServer,
|
|
34
31
|
redirectUri: string,
|
|
32
|
+
fetchImpl: FetchLike = fetch,
|
|
35
33
|
): Promise<OAuthClient> {
|
|
36
34
|
if (server.registrationEndpoint === null)
|
|
37
35
|
throw refused(
|
|
38
|
-
'That server
|
|
36
|
+
'That server signs in with OAuth but registers no clients on its own. ' +
|
|
37
|
+
`Register an app with it yourself, with ${redirectUri} as its redirect URL, ` +
|
|
38
|
+
"and add the connector again with that app's client ID.",
|
|
39
39
|
);
|
|
40
40
|
let res: Response;
|
|
41
41
|
try {
|
|
42
|
-
res = await
|
|
42
|
+
res = await fetchImpl(server.registrationEndpoint, {
|
|
43
43
|
method: 'POST',
|
|
44
44
|
redirect: 'manual',
|
|
45
45
|
signal: AbortSignal.timeout(TOKEN_TIMEOUT_MS),
|
|
@@ -52,8 +52,8 @@ export async function registerClient(
|
|
|
52
52
|
token_endpoint_auth_method: 'none',
|
|
53
53
|
}),
|
|
54
54
|
});
|
|
55
|
-
} catch {
|
|
56
|
-
throw refused(
|
|
55
|
+
} catch (err) {
|
|
56
|
+
throw refused(`Metro could not reach that server to register: ${whyUnreachable(err)}`);
|
|
57
57
|
}
|
|
58
58
|
const body: unknown = await res.json().catch(() => null);
|
|
59
59
|
if (!res.ok || !isRecord(body) || typeof body.client_id !== 'string')
|
|
@@ -83,21 +83,37 @@ export function authorizeUrl(input: AuthorizeInput): string {
|
|
|
83
83
|
url.searchParams.set('code_challenge', challengeOf(input.verifier));
|
|
84
84
|
url.searchParams.set('code_challenge_method', 'S256');
|
|
85
85
|
url.searchParams.set('resource', input.resource);
|
|
86
|
+
if (input.server.scopes.length > 0)
|
|
87
|
+
url.searchParams.set('scope', input.server.scopes.join(' '));
|
|
86
88
|
return url.toString();
|
|
87
89
|
}
|
|
88
90
|
|
|
91
|
+
function validateOptionalTokens(body: Record<string, unknown>): void {
|
|
92
|
+
const refresh = body.refresh_token;
|
|
93
|
+
if (Object.hasOwn(body, 'refresh_token') && (typeof refresh !== 'string' || !/^[\x21-\x7e]{1,16384}$/.test(refresh))) throw refused('That server returned an invalid refresh token.');
|
|
94
|
+
if (Object.hasOwn(body, 'token_type') && (typeof body.token_type !== 'string' || body.token_type.toLowerCase() !== 'bearer')) throw refused('That server returned an unsupported token type.');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function expiryFrom(body: Record<string, unknown>): number | undefined {
|
|
98
|
+
if (!Object.hasOwn(body, 'expires_in')) return undefined;
|
|
99
|
+
const expires = body.expires_in;
|
|
100
|
+
if (typeof expires !== 'number' || !Number.isFinite(expires) || expires <= 0) throw refused('That server returned an invalid token expiry.');
|
|
101
|
+
const at = Date.now() + expires * 1000;
|
|
102
|
+
if (!Number.isSafeInteger(at)) throw refused('That server returned an invalid token expiry.');
|
|
103
|
+
return at;
|
|
104
|
+
}
|
|
105
|
+
|
|
89
106
|
function tokensFrom(body: Record<string, unknown>): OAuthTokens {
|
|
90
107
|
const access = body.access_token;
|
|
91
|
-
if (typeof access !== 'string' || access
|
|
92
|
-
throw refused('That server did not return
|
|
108
|
+
if (typeof access !== 'string' || !/^[\x21-\x7e]{1,16377}$/.test(access))
|
|
109
|
+
throw refused('That server did not return a sendable access token.');
|
|
110
|
+
validateOptionalTokens(body);
|
|
111
|
+
const expiresAt = expiryFrom(body);
|
|
93
112
|
const refresh = body.refresh_token;
|
|
94
|
-
const expires = body.expires_in;
|
|
95
113
|
return {
|
|
96
114
|
accessToken: access,
|
|
97
115
|
...(typeof refresh === 'string' ? { refreshToken: refresh } : {}),
|
|
98
|
-
...(
|
|
99
|
-
? { expiresAt: Date.now() + expires * 1000 }
|
|
100
|
-
: {}),
|
|
116
|
+
...(expiresAt === undefined ? {} : { expiresAt }),
|
|
101
117
|
};
|
|
102
118
|
}
|
|
103
119
|
|
|
@@ -105,6 +121,7 @@ async function postToken(
|
|
|
105
121
|
server: OAuthServer,
|
|
106
122
|
client: OAuthClient,
|
|
107
123
|
form: Record<string, string>,
|
|
124
|
+
fetchImpl: FetchLike,
|
|
108
125
|
): Promise<OAuthTokens> {
|
|
109
126
|
const params = new URLSearchParams({
|
|
110
127
|
...form,
|
|
@@ -115,7 +132,7 @@ async function postToken(
|
|
|
115
132
|
});
|
|
116
133
|
let res: Response;
|
|
117
134
|
try {
|
|
118
|
-
res = await
|
|
135
|
+
res = await fetchImpl(server.tokenEndpoint, {
|
|
119
136
|
method: 'POST',
|
|
120
137
|
redirect: 'manual',
|
|
121
138
|
signal: AbortSignal.timeout(TOKEN_TIMEOUT_MS),
|
|
@@ -125,12 +142,20 @@ async function postToken(
|
|
|
125
142
|
},
|
|
126
143
|
body: params.toString(),
|
|
127
144
|
});
|
|
128
|
-
} catch {
|
|
129
|
-
throw refused(
|
|
145
|
+
} catch (err) {
|
|
146
|
+
throw refused(`Metro could not reach that server to finish signing in: ${whyUnreachable(err)}`);
|
|
130
147
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
148
|
+
return tokenAnswer(form.grant_type === 'refresh_token', res.status, res.ok, await res.json().catch(() => null));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const errorCode = (body: unknown): string | null => (isRecord(body) && typeof body.error === 'string' && /^[a-z_]{1,64}$/.test(body.error) ? body.error : null);
|
|
152
|
+
|
|
153
|
+
const grantGone = (refreshing: boolean, status: number, code: string | null): boolean => refreshing && (status === 400 || status === 401) && code !== null && SIGN_IN_AGAIN.has(code);
|
|
154
|
+
|
|
155
|
+
function tokenAnswer(refreshing: boolean, status: number, ok: boolean, body: unknown): OAuthTokens {
|
|
156
|
+
const code = errorCode(body);
|
|
157
|
+
if (grantGone(refreshing, status, code)) throw new OAuthInvalidGrant('That server requires a new sign-in.', 400);
|
|
158
|
+
if (!ok || !isRecord(body)) throw refused(`That server refused to complete the sign-in (${String(status)}${code === null ? '' : ` ${code}`}).`);
|
|
134
159
|
return tokensFrom(body);
|
|
135
160
|
}
|
|
136
161
|
|
|
@@ -138,6 +163,7 @@ export function exchangeCode(
|
|
|
138
163
|
server: OAuthServer,
|
|
139
164
|
client: OAuthClient,
|
|
140
165
|
input: { code: string; redirectUri: string; verifier: string; resource: string },
|
|
166
|
+
fetchImpl: FetchLike = fetch,
|
|
141
167
|
): Promise<OAuthTokens> {
|
|
142
168
|
return postToken(server, client, {
|
|
143
169
|
grant_type: 'authorization_code',
|
|
@@ -145,7 +171,7 @@ export function exchangeCode(
|
|
|
145
171
|
redirect_uri: input.redirectUri,
|
|
146
172
|
code_verifier: input.verifier,
|
|
147
173
|
resource: input.resource,
|
|
148
|
-
});
|
|
174
|
+
}, fetchImpl);
|
|
149
175
|
}
|
|
150
176
|
|
|
151
177
|
export function refreshTokens(
|
|
@@ -153,10 +179,13 @@ export function refreshTokens(
|
|
|
153
179
|
client: OAuthClient,
|
|
154
180
|
refreshToken: string,
|
|
155
181
|
resource: string,
|
|
182
|
+
scope?: string,
|
|
183
|
+
fetchImpl: FetchLike = fetch,
|
|
156
184
|
): Promise<OAuthTokens> {
|
|
157
185
|
return postToken(server, client, {
|
|
158
186
|
grant_type: 'refresh_token',
|
|
159
187
|
refresh_token: refreshToken,
|
|
160
188
|
resource,
|
|
161
|
-
|
|
189
|
+
...(scope === undefined ? {} : { scope }),
|
|
190
|
+
}, fetchImpl);
|
|
162
191
|
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { isRecord } from '@metro-labs/core/is-record';
|
|
2
|
+
|
|
3
|
+
export type ConnectorDecision = 'allow' | 'ask' | 'deny';
|
|
4
|
+
|
|
5
|
+
type ToolGroup = 'read' | 'write';
|
|
6
|
+
|
|
7
|
+
export interface ConnectorPolicy {
|
|
8
|
+
read?: ConnectorDecision;
|
|
9
|
+
write?: ConnectorDecision;
|
|
10
|
+
tools?: Record<string, ConnectorDecision>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface ConnectorPolicyLayers {
|
|
14
|
+
organization: ConnectorPolicy;
|
|
15
|
+
agent: ConnectorPolicy;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const RANK: Record<ConnectorDecision, number> = { allow: 0, ask: 1, deny: 2 };
|
|
19
|
+
const TOOL_RE = /^[A-Za-z0-9_.:/-]{1,256}$/;
|
|
20
|
+
|
|
21
|
+
export const validConnectorToolName = (name: string): boolean => TOOL_RE.test(name) && !['__proto__', 'constructor', 'prototype'].includes(name);
|
|
22
|
+
|
|
23
|
+
const decision = (value: unknown): value is ConnectorDecision => value === 'allow' || value === 'ask' || value === 'deny';
|
|
24
|
+
|
|
25
|
+
export function connectorPolicyOf(value: unknown): ConnectorPolicy {
|
|
26
|
+
if (!isRecord(value) || Object.keys(value).some((key) => !['read', 'write', 'tools'].includes(key))) throw new Error('Invalid connector policy.');
|
|
27
|
+
const out: ConnectorPolicy = {};
|
|
28
|
+
for (const group of ['read', 'write'] as const) {
|
|
29
|
+
if (!Object.hasOwn(value, group)) continue;
|
|
30
|
+
const field = value[group];
|
|
31
|
+
if (!decision(field)) throw new Error('Invalid connector policy.');
|
|
32
|
+
out[group] = field;
|
|
33
|
+
}
|
|
34
|
+
if (Object.hasOwn(value, 'tools')) out.tools = toolPolicyOf(value.tools);
|
|
35
|
+
return out;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function toolPolicyOf(value: unknown): Record<string, ConnectorDecision> {
|
|
39
|
+
if (!isRecord(value) || Object.keys(value).length > 2000) throw new Error('Invalid connector policy.');
|
|
40
|
+
const out: Record<string, ConnectorDecision> = {};
|
|
41
|
+
for (const [name, rule] of Object.entries(value)) {
|
|
42
|
+
if (!validConnectorToolName(name) || !decision(rule)) throw new Error('Invalid connector policy.');
|
|
43
|
+
out[name] = rule;
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function connectorPolicyLayersOf(value: unknown): ConnectorPolicyLayers {
|
|
49
|
+
if (!isRecord(value) || Object.keys(value).some((key) => !['organization', 'agent'].includes(key))) throw new Error('Invalid connector policy layers.');
|
|
50
|
+
return { organization: connectorPolicyOf(value.organization), agent: connectorPolicyOf(value.agent) };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const strictest = (...values: (ConnectorDecision | undefined)[]): ConnectorDecision => values.reduce<ConnectorDecision>((held, next) => next !== undefined && RANK[next] > RANK[held] ? next : held, 'allow');
|
|
54
|
+
const toolRule = (policy: ConnectorPolicy, name: string): ConnectorDecision | undefined => policy.tools !== undefined && Object.hasOwn(policy.tools, name) ? policy.tools[name] : undefined;
|
|
55
|
+
const toolGroup = (groups: Record<string, ToolGroup>, name: string): ToolGroup => Object.hasOwn(groups, name) && groups[name] === 'read' ? 'read' : 'write';
|
|
56
|
+
const access = (policy: ConnectorPolicy, name: string, group: ToolGroup): ConnectorDecision => toolRule(policy, name) ?? policy[group] ?? 'allow';
|
|
57
|
+
|
|
58
|
+
export function combineConnectorPolicies(global: ConnectorPolicy, assignment: ConnectorPolicy, groups?: Record<string, ToolGroup>): ConnectorPolicy {
|
|
59
|
+
const policies = [connectorPolicyOf(global), connectorPolicyOf(assignment)];
|
|
60
|
+
const neutral = (policy: ConnectorPolicy): boolean => (policy.read ?? 'allow') === 'allow' && (policy.write ?? 'allow') === 'allow' && Object.keys(policy.tools ?? {}).length === 0;
|
|
61
|
+
if (neutral(assignment)) return connectorPolicyOf(global);
|
|
62
|
+
if (neutral(global)) return connectorPolicyOf(assignment);
|
|
63
|
+
const out: ConnectorPolicy = {
|
|
64
|
+
read: strictest(...policies.map((policy) => policy.read)),
|
|
65
|
+
write: strictest(...policies.map((policy) => policy.write)),
|
|
66
|
+
};
|
|
67
|
+
const names = new Set(policies.flatMap((policy) => Object.keys(policy.tools ?? {})));
|
|
68
|
+
if (groups === undefined && names.size > 2000) return { read: 'deny', write: 'deny' };
|
|
69
|
+
if (names.size > 0) {
|
|
70
|
+
out.tools = {};
|
|
71
|
+
for (const name of names) {
|
|
72
|
+
out.tools[name] = groups === undefined
|
|
73
|
+
? strictest(...policies.flatMap((policy) => [policy.read, policy.write, toolRule(policy, name)]))
|
|
74
|
+
: strictest(...policies.map((policy) => access(policy, name, toolGroup(groups, name))));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function effectiveConnectorPolicy(row: { policy: ConnectorPolicy; policyLayers?: ConnectorPolicyLayers }, groups: Record<string, ToolGroup>): ConnectorPolicy {
|
|
81
|
+
const layers = row.policyLayers;
|
|
82
|
+
return layers === undefined ? connectorPolicyOf(row.policy) : combineConnectorPolicies(layers.organization, layers.agent, groups);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function connectorPoliciesBlocked(layers: ConnectorPolicyLayers): boolean {
|
|
86
|
+
const policies = [layers.organization, layers.agent];
|
|
87
|
+
const names = new Set(policies.flatMap((policy) => Object.keys(policy.tools ?? {})));
|
|
88
|
+
return (['read', 'write'] as const).every((group) =>
|
|
89
|
+
strictest(...policies.map((policy) => policy[group])) === 'deny' &&
|
|
90
|
+
[...names].every((name) => strictest(...policies.map((policy) => access(policy, name, group))) === 'deny'),
|
|
91
|
+
);
|
|
92
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { BlockList, isIP } from 'node:net';
|
|
2
|
+
import { parseConnectorUrl, refused } from './connector-url.js';
|
|
3
|
+
|
|
4
|
+
const blocked = new BlockList();
|
|
5
|
+
for (const [address, prefix] of [
|
|
6
|
+
['0.0.0.0', 8], ['10.0.0.0', 8], ['100.64.0.0', 10], ['127.0.0.0', 8], ['169.254.0.0', 16], ['172.16.0.0', 12],
|
|
7
|
+
['192.0.0.0', 24], ['192.0.2.0', 24], ['192.88.99.0', 24], ['192.168.0.0', 16], ['198.18.0.0', 15],
|
|
8
|
+
['198.51.100.0', 24], ['203.0.113.0', 24], ['224.0.0.0', 4], ['240.0.0.0', 4],
|
|
9
|
+
] as const) blocked.addSubnet(address, prefix, 'ipv4');
|
|
10
|
+
for (const [address, prefix] of [
|
|
11
|
+
['2001::', 32], ['2001:10::', 28], ['2001:20::', 28], ['2001:db8::', 32], ['2002::', 16],
|
|
12
|
+
] as const) blocked.addSubnet(address, prefix, 'ipv6');
|
|
13
|
+
const globalV6 = new BlockList();
|
|
14
|
+
globalV6.addSubnet('2000::', 3, 'ipv6');
|
|
15
|
+
|
|
16
|
+
export function publicConnectorAddress(address: string, family: number): boolean {
|
|
17
|
+
if (family === 4) return isIP(address) === 4 && !blocked.check(address, 'ipv4');
|
|
18
|
+
return isIP(address) === 6 && globalV6.check(address, 'ipv6') && !blocked.check(address, 'ipv6');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function publicHost(host: string): boolean {
|
|
22
|
+
const family = isIP(host);
|
|
23
|
+
if (family !== 0) return publicConnectorAddress(host, family);
|
|
24
|
+
if (/(^|\.)(localhost|local|internal|lan|home|invalid|test|onion)$/.test(host)) return false;
|
|
25
|
+
return host.includes('.') && host.split('.').every((label) => /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(label));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function invalidText(raw: string): boolean {
|
|
29
|
+
return raw.length > 2048 || /[\s\\#]/.test(raw) || /%(?![0-9a-f]{2})/i.test(raw);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function parsePublicConnectorUrl(raw: unknown): URL {
|
|
33
|
+
const invalid = (): never => { throw refused('An organization endpoint must be a public HTTPS URL without user information or a fragment.'); };
|
|
34
|
+
if (typeof raw !== 'string' || invalidText(raw)) return invalid();
|
|
35
|
+
const authority = /^https:\/\/([^/ ?#]+)/i.exec(raw)?.[1];
|
|
36
|
+
if (authority === undefined || authority.includes('@')) return invalid();
|
|
37
|
+
let url: URL;
|
|
38
|
+
try { url = parseConnectorUrl(raw); } catch { return invalid(); }
|
|
39
|
+
if (url.toString().length > 2048 || !publicHost(url.hostname.replace(/^\[|\]$/g, ''))) return invalid();
|
|
40
|
+
return url;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function publicOAuthResource(raw: unknown): string {
|
|
44
|
+
try {
|
|
45
|
+
const url = parsePublicConnectorUrl(raw);
|
|
46
|
+
if (typeof raw === 'string' && !raw.includes('?') && url.search === '') return raw;
|
|
47
|
+
} catch {
|
|
48
|
+
throw refused('The public OAuth resource must be a public HTTPS identifier without a query, user information or a fragment. Do not enter credentials.');
|
|
49
|
+
}
|
|
50
|
+
throw refused('The public OAuth resource must be a public HTTPS identifier without a query, user information or a fragment. Do not enter credentials.');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function optionalOAuthResource(raw: unknown): string | undefined {
|
|
54
|
+
return raw === undefined || raw === '' ? undefined : publicOAuthResource(raw);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function boundOAuthResource(target: string, raw: unknown): string {
|
|
58
|
+
const resource = publicOAuthResource(raw);
|
|
59
|
+
const transport = parsePublicConnectorUrl(target);
|
|
60
|
+
const url = new URL(resource);
|
|
61
|
+
const path = url.pathname.replace(/\/$/, '');
|
|
62
|
+
if (url.origin !== transport.origin || !(path === '' || transport.pathname === path || transport.pathname.startsWith(`${path}/`))) throw refused('The public OAuth resource does not identify this endpoint. Check the provider’s documented resource.');
|
|
63
|
+
return resource;
|
|
64
|
+
}
|