@stage-labs/metro 0.1.0-beta.2 → 0.1.0-beta.200
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/api.js +11 -0
- package/dist/claude-settings.js +40 -0
- package/dist/claude.js +163 -0
- package/dist/cli.js +77 -567
- package/dist/control.js +74 -0
- package/dist/hold.js +211 -0
- package/dist/local.js +43 -0
- package/dist/mcp-config.js +25 -0
- package/dist/node-name.js +71 -0
- package/dist/onboarding.js +44 -0
- package/dist/provider-flags.js +9 -0
- package/dist/route.js +58 -0
- package/dist/runtime-install.js +97 -0
- package/dist/runtime.js +74 -0
- package/dist/serve.js +158 -0
- package/dist/service.js +243 -0
- package/dist/tail.js +102 -144
- package/dist/update.js +45 -0
- package/dist/version.js +97 -0
- package/package.json +14 -23
- package/runtime/marketplace/.claude-plugin/marketplace.json +12 -0
- package/runtime/marketplace/plugin/.claude-plugin/plugin.json +17 -0
- package/runtime/marketplace/plugin/.mcp.json +1 -0
- package/runtime/marketplace/plugin/bin/guard.mjs +71 -0
- package/runtime/marketplace/plugin/bin/metro-plugin.mjs +30 -0
- package/runtime/marketplace/plugin/bin/policy.mjs +97 -0
- package/runtime/marketplace/plugin/bin/session-start.mjs +31 -0
- package/runtime/marketplace/plugin/hooks/hooks.json +25 -0
- package/runtime/marketplace/plugin/orchestrator.md +24 -0
- package/runtime/node_modules/@metro-labs/core/package.json +47 -0
- package/runtime/node_modules/@metro-labs/core/src/endpoints.ts +7 -0
- package/runtime/node_modules/@metro-labs/core/src/events.ts +119 -0
- package/runtime/node_modules/@metro-labs/core/src/identity.ts +7 -0
- package/runtime/node_modules/@metro-labs/core/src/ids.ts +24 -0
- package/runtime/node_modules/@metro-labs/core/src/is-record.ts +2 -0
- package/runtime/node_modules/@metro-labs/core/src/lines.ts +91 -0
- package/runtime/node_modules/@metro-labs/core/src/log.ts +42 -0
- package/runtime/node_modules/@metro-labs/core/src/protocol.ts +227 -0
- package/runtime/node_modules/@metro-labs/core/src/secure-fs.ts +74 -0
- package/runtime/node_modules/@metro-labs/core/src/station-names.ts +13 -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-store.ts +60 -0
- package/runtime/node_modules/@metro-labs/core/src/stations/attachments.ts +196 -0
- package/runtime/node_modules/@metro-labs/core/src/stations/messaging-normalize.ts +88 -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/core/src/stations/station-runtime.ts +61 -0
- package/runtime/node_modules/@metro-labs/core/src/stations/train-boot.ts +42 -0
- package/runtime/node_modules/@metro-labs/core/src/stations/train-events.ts +89 -0
- package/runtime/node_modules/@metro-labs/core/src/stations/types.ts +123 -0
- package/runtime/node_modules/@metro-labs/core/src/str.ts +5 -0
- package/runtime/node_modules/@metro-labs/core/src/tickets.ts +37 -0
- package/runtime/node_modules/@metro-labs/core/src/train-error.ts +53 -0
- package/runtime/node_modules/@metro-labs/core/src/version.ts +2 -0
- package/runtime/node_modules/@metro-labs/daemon/package.json +48 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/agent-fs.ts +134 -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 +119 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/home-fs.ts +113 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/job-env.ts +51 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/provision.ts +91 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/schedule-detail.ts +100 -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 +252 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/unit-files.ts +61 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/user.ts +91 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agent-user/view.ts +87 -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 +76 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agents/accounts-api.ts +357 -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 +131 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agents/bundle.ts +132 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agents/file-admin.ts +305 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agents/files.ts +168 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agents/keys.ts +35 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agents/map.ts +128 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agents/policy-route.ts +27 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agents/scope.ts +64 -0
- package/runtime/node_modules/@metro-labs/daemon/src/agents/sender-cards.ts +86 -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/needs.ts +2 -0
- package/runtime/node_modules/@metro-labs/daemon/src/approvals/pending.ts +149 -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 +221 -0
- package/runtime/node_modules/@metro-labs/daemon/src/boot/connect-hint.ts +39 -0
- package/runtime/node_modules/@metro-labs/daemon/src/boot/crash-guard.ts +49 -0
- package/runtime/node_modules/@metro-labs/daemon/src/boot/local-owner.ts +21 -0
- package/runtime/node_modules/@metro-labs/daemon/src/boot/paths.ts +106 -0
- package/runtime/node_modules/@metro-labs/daemon/src/channels/addressed.ts +26 -0
- package/runtime/node_modules/@metro-labs/daemon/src/channels/dedupe.ts +12 -0
- package/runtime/node_modules/@metro-labs/daemon/src/channels/inbound.ts +370 -0
- package/runtime/node_modules/@metro-labs/daemon/src/channels/media-note.ts +90 -0
- package/runtime/node_modules/@metro-labs/daemon/src/channels/pending.ts +78 -0
- package/runtime/node_modules/@metro-labs/daemon/src/channels/react-note.ts +13 -0
- package/runtime/node_modules/@metro-labs/daemon/src/channels/relay.ts +129 -0
- package/runtime/node_modules/@metro-labs/daemon/src/channels/reply-id.ts +1 -0
- package/runtime/node_modules/@metro-labs/daemon/src/channels/webhook-note.ts +51 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/api.ts +355 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/files.ts +359 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/login.ts +208 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/memory.ts +82 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/onboarding.ts +60 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/plugin-install.ts +149 -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 +283 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/settings.ts +109 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/setup.ts +271 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/skills.ts +120 -0
- package/runtime/node_modules/@metro-labs/daemon/src/claude/version.ts +113 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/api.ts +306 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/config.ts +176 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/gates.ts +72 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/health.ts +18 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/oauth-client.ts +159 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/oauth-discovery.ts +135 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/oauth-routes.ts +158 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/oauth.ts +166 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/plugin-sync.ts +131 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/reach.ts +27 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/relay-policy.ts +90 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/relay-target.ts +29 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/relay.ts +348 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/store.ts +358 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/tools.ts +81 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/url.ts +37 -0
- package/runtime/node_modules/@metro-labs/daemon/src/connectors/verify.ts +106 -0
- package/runtime/node_modules/@metro-labs/daemon/src/files/attach-grant.ts +99 -0
- package/runtime/node_modules/@metro-labs/daemon/src/files/attach-owner.ts +32 -0
- package/runtime/node_modules/@metro-labs/daemon/src/files/attach-reaper.ts +174 -0
- package/runtime/node_modules/@metro-labs/daemon/src/files/attach-serve.ts +123 -0
- package/runtime/node_modules/@metro-labs/daemon/src/files/upload-api.ts +278 -0
- package/runtime/node_modules/@metro-labs/daemon/src/files/upload-store.ts +181 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/bedrock.ts +233 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-auth.ts +208 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-device.ts +91 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-stream.ts +173 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex-translate.ts +194 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/codex.ts +137 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/effort.ts +77 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/eventstream.ts +123 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/forward.ts +237 -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 +274 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/gemini-auth.ts +160 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/gemini-client.ts +46 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/gemini-setup.ts +150 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/gemini-stream.ts +139 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/gemini-translate.ts +223 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/gemini.ts +208 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/model-api.ts +199 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/model-config.ts +299 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/model-signin.ts +193 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/model-store.ts +70 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/openrouter.ts +90 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/pkce.ts +36 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/provider-models.ts +66 -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 +120 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/text.ts +15 -0
- package/runtime/node_modules/@metro-labs/daemon/src/gateway/usage.ts +244 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/accounts.ts +156 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/attachment-schema.ts +91 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/call-tools.ts +226 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/ctx.ts +62 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/event-store.ts +90 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/group-tools.ts +129 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/index.ts +137 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/instructions.ts +19 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/member-tools.ts +72 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/permission-prompt.ts +87 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/permission-relay.ts +79 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/policy-gate.ts +83 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/policy-snapshot.ts +79 -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/daemon/src/mcp/raw-get-stream.ts +207 -0
- 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 +46 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/session-slot.ts +48 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/session.ts +202 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/tool-catalog.ts +88 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/tool-def.ts +9 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/tool-dispatch.ts +225 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/tool-schemas.ts +333 -0
- package/runtime/node_modules/@metro-labs/daemon/src/mcp/upload-tool.ts +61 -0
- package/runtime/node_modules/@metro-labs/daemon/src/metro-user/api.ts +43 -0
- package/runtime/node_modules/@metro-labs/daemon/src/metro-user/helper-script.ts +126 -0
- package/runtime/node_modules/@metro-labs/daemon/src/metro-user/move.ts +165 -0
- package/runtime/node_modules/@metro-labs/daemon/src/metro-user/privilege.ts +48 -0
- package/runtime/node_modules/@metro-labs/daemon/src/monitor/api.ts +132 -0
- package/runtime/node_modules/@metro-labs/daemon/src/net/tunnel.ts +316 -0
- package/runtime/node_modules/@metro-labs/daemon/src/policy/policy.ts +118 -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/http.ts +365 -0
- package/runtime/node_modules/@metro-labs/daemon/src/routes/local-mode.ts +208 -0
- package/runtime/node_modules/@metro-labs/daemon/src/routes/session-apis.ts +71 -0
- package/runtime/node_modules/@metro-labs/daemon/src/routes/session.ts +29 -0
- package/runtime/node_modules/@metro-labs/daemon/src/routes/threema-callback.ts +103 -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-driver.ts +42 -0
- package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-inline.ts +128 -0
- package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-interactive.ts +134 -0
- package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-outlook.ts +63 -0
- package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-resolve.ts +225 -0
- package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-session.ts +288 -0
- package/runtime/node_modules/@metro-labs/daemon/src/stations/attach-xmtp.ts +111 -0
- package/runtime/node_modules/@metro-labs/daemon/src/stations/attach.ts +248 -0
- package/runtime/node_modules/@metro-labs/daemon/src/stations/materialize.ts +265 -0
- package/runtime/node_modules/@metro-labs/daemon/src/stations/registry.ts +51 -0
- package/runtime/node_modules/@metro-labs/daemon/src/stations/runtime-deps.ts +82 -0
- package/runtime/node_modules/@metro-labs/daemon/src/stations/supervisor-io.ts +97 -0
- package/runtime/node_modules/@metro-labs/daemon/src/stations/supervisor.ts +320 -0
- package/runtime/node_modules/@metro-labs/daemon/src/stations/threema-callbacks.ts +32 -0
- package/runtime/node_modules/@metro-labs/daemon/src/stations/train-call.ts +22 -0
- 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/vault/api.ts +45 -0
- package/runtime/node_modules/@metro-labs/daemon/src/vault/config.ts +51 -0
- package/runtime/node_modules/@metro-labs/daemon/src/vault/firewall.ts +48 -0
- package/runtime/node_modules/@metro-labs/daemon/src/vault/index.ts +96 -0
- package/runtime/node_modules/@metro-labs/daemon/src/vault/install.ts +56 -0
- package/runtime/node_modules/@metro-labs/daemon/src/vault/paths.ts +26 -0
- package/runtime/node_modules/@metro-labs/daemon/src/vault/proxy.ts +148 -0
- package/runtime/node_modules/@metro-labs/daemon/src/vault/store.ts +130 -0
- package/runtime/node_modules/@metro-labs/daemon/src/vault/trust.ts +61 -0
- package/runtime/node_modules/@metro-labs/discord-bot/package.json +26 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/accounts.ts +117 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/actions.ts +240 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/api-base.ts +1 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/attachments.ts +29 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/format.ts +174 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/group-actions.ts +50 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/group.ts +115 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/index.ts +122 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/members.ts +215 -0
- 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 +43 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/station.ts +22 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/verify.ts +82 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/wire.ts +1 -0
- package/runtime/node_modules/@metro-labs/http/package.json +29 -0
- package/runtime/node_modules/@metro-labs/http/src/api-error.ts +8 -0
- package/runtime/node_modules/@metro-labs/http/src/api-http.ts +138 -0
- package/runtime/node_modules/@metro-labs/http/src/cors.ts +29 -0
- package/runtime/node_modules/@metro-labs/http/src/mode-api.ts +32 -0
- package/runtime/node_modules/@metro-labs/http/src/return-to.ts +21 -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 +107 -0
- package/runtime/node_modules/@metro-labs/outlook/src/actions.ts +20 -0
- package/runtime/node_modules/@metro-labs/outlook/src/attachments.ts +97 -0
- package/runtime/node_modules/@metro-labs/outlook/src/auth.ts +150 -0
- package/runtime/node_modules/@metro-labs/outlook/src/browser.ts +53 -0
- package/runtime/node_modules/@metro-labs/outlook/src/config.ts +36 -0
- package/runtime/node_modules/@metro-labs/outlook/src/format.ts +141 -0
- package/runtime/node_modules/@metro-labs/outlook/src/graph.ts +60 -0
- package/runtime/node_modules/@metro-labs/outlook/src/html.ts +72 -0
- package/runtime/node_modules/@metro-labs/outlook/src/inbound.ts +104 -0
- package/runtime/node_modules/@metro-labs/outlook/src/index.ts +12 -0
- package/runtime/node_modules/@metro-labs/outlook/src/login.ts +150 -0
- package/runtime/node_modules/@metro-labs/outlook/src/me.ts +41 -0
- package/runtime/node_modules/@metro-labs/outlook/src/outbound.ts +116 -0
- package/runtime/node_modules/@metro-labs/outlook/src/query.ts +119 -0
- package/runtime/node_modules/@metro-labs/outlook/src/state.ts +43 -0
- package/runtime/node_modules/@metro-labs/outlook/src/station.ts +15 -0
- package/runtime/node_modules/@metro-labs/outlook/src/trust.ts +70 -0
- package/runtime/node_modules/@metro-labs/telegram/package.json +26 -0
- package/runtime/node_modules/@metro-labs/telegram/src/accounts.ts +80 -0
- package/runtime/node_modules/@metro-labs/telegram/src/actions.ts +256 -0
- package/runtime/node_modules/@metro-labs/telegram/src/attachments.ts +87 -0
- package/runtime/node_modules/@metro-labs/telegram/src/client.ts +77 -0
- package/runtime/node_modules/@metro-labs/telegram/src/format.ts +128 -0
- package/runtime/node_modules/@metro-labs/telegram/src/group.ts +261 -0
- package/runtime/node_modules/@metro-labs/telegram/src/history.ts +52 -0
- package/runtime/node_modules/@metro-labs/telegram/src/inbound.ts +57 -0
- package/runtime/node_modules/@metro-labs/telegram/src/index.ts +7 -0
- package/runtime/node_modules/@metro-labs/telegram/src/login.ts +166 -0
- package/runtime/node_modules/@metro-labs/telegram/src/media-actions.ts +80 -0
- package/runtime/node_modules/@metro-labs/telegram/src/members.ts +75 -0
- package/runtime/node_modules/@metro-labs/telegram/src/normalize.ts +22 -0
- package/runtime/node_modules/@metro-labs/telegram/src/profile.ts +70 -0
- package/runtime/node_modules/@metro-labs/telegram/src/reactions.ts +167 -0
- package/runtime/node_modules/@metro-labs/telegram/src/station.ts +27 -0
- package/runtime/node_modules/@metro-labs/telegram/src/types.ts +6 -0
- package/runtime/node_modules/@metro-labs/telegram/src/wire.ts +1 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/package.json +25 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/accounts.ts +119 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/actions.ts +246 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/attachments.ts +128 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/format.ts +173 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/index.ts +103 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/media-actions.ts +95 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/members.ts +47 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/profile.ts +65 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/station.ts +20 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/types.ts +56 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/verify.ts +38 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/wire.ts +1 -0
- package/runtime/node_modules/@metro-labs/threema/package.json +26 -0
- package/runtime/node_modules/@metro-labs/threema/src/accounts.ts +106 -0
- package/runtime/node_modules/@metro-labs/threema/src/actions.ts +134 -0
- package/runtime/node_modules/@metro-labs/threema/src/api.ts +152 -0
- package/runtime/node_modules/@metro-labs/threema/src/crypto.ts +100 -0
- package/runtime/node_modules/@metro-labs/threema/src/files.ts +58 -0
- package/runtime/node_modules/@metro-labs/threema/src/format.ts +169 -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 +89 -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 +160 -0
- package/runtime/node_modules/@metro-labs/threema/src/station.ts +13 -0
- package/runtime/node_modules/@metro-labs/threema/src/verify.ts +117 -0
- package/runtime/node_modules/@metro-labs/webhook/package.json +23 -0
- package/runtime/node_modules/@metro-labs/webhook/src/station.ts +37 -0
- package/runtime/node_modules/@metro-labs/whatsapp/package.json +27 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/accounts.ts +66 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/ack.ts +101 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/actions.ts +213 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/attachments.ts +72 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/auth-state.ts +129 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/client.ts +388 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/delivery.ts +49 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/format.ts +83 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/inbound.ts +40 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/index.ts +7 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/keys.ts +59 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/logger.ts +60 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/login.ts +176 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/media.ts +84 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/names.ts +28 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/normalize.ts +22 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/outbox.ts +38 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/parse.ts +185 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/resolve.ts +52 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/station.ts +24 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/token-store.ts +94 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/types.ts +5 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/wire.ts +1 -0
- package/runtime/node_modules/@metro-labs/xmtp/package.json +34 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/accounts.ts +114 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/actions-close.ts +110 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/actions-conv.ts +101 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/actions-meta.ts +118 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/actions.ts +244 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/attachments.ts +107 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/codecs.ts +171 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/conv-helpers.ts +239 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/emit-payloads.ts +316 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/emit.ts +69 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/group-members.ts +34 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/group.ts +56 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/identity.ts +47 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/index.ts +122 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/labels.ts +139 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/member-args.ts +40 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/names.ts +61 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/profile.ts +153 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/sender.ts +112 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/smart.ts +72 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/station.ts +17 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/tools-handlers.ts +79 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/tools.ts +198 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/transcribe.ts +88 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/verify.ts +98 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/wire.ts +51 -0
- package/runtime/runtime.json +3 -0
- package/runtime/server.ts +1 -0
- package/runtime/stations.json +37 -0
- package/runtime/trains/.keep +0 -0
- package/LICENSE +0 -21
- package/README.md +0 -78
- package/dist/channels/discord.js +0 -148
- package/dist/channels/telegram.js +0 -137
- package/dist/lib/address.js +0 -21
- package/dist/lib/codex-rc.js +0 -274
- package/dist/lib/dotenv.js +0 -31
- package/dist/log.js +0 -12
- package/dist/paths.js +0 -45
- package/skills/metro/SKILL.md +0 -122
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { Line } from '@metro-labs/core/lines';
|
|
3
|
+
import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
4
|
+
import {
|
|
5
|
+
ListToolsRequestSchema,
|
|
6
|
+
CallToolRequestSchema,
|
|
7
|
+
} from '@modelcontextprotocol/sdk/types.js';
|
|
8
|
+
import { gatherAccounts } from './accounts.js';
|
|
9
|
+
import {
|
|
10
|
+
STATIONS,
|
|
11
|
+
accountStationCapabilities,
|
|
12
|
+
} from '../stations/registry.js';
|
|
13
|
+
import type { Station, StationTool, ToolResult } from '@metro-labs/core/stations/types';
|
|
14
|
+
import { listedTools, stationForTool, type PublishedTool } from './tool-catalog.js';
|
|
15
|
+
import { policyGate, withEffectivePolicy } from './policy-gate.js';
|
|
16
|
+
import { settlePromptsFor } from '../approvals/pending.js';
|
|
17
|
+
import { errResult, makeCtx, okJson, toErr } from './ctx.js';
|
|
18
|
+
import { dispatchMessageTool, type ToolHooks } from './call-tools.js';
|
|
19
|
+
import { dispatchListMembers } from './member-tools.js';
|
|
20
|
+
import {
|
|
21
|
+
dispatchAddMembers,
|
|
22
|
+
dispatchCreateGroup,
|
|
23
|
+
dispatchInviteLink,
|
|
24
|
+
dispatchRemoveMembers,
|
|
25
|
+
} from './group-tools.js';
|
|
26
|
+
import { dispatchCreateUpload } from './upload-tool.js';
|
|
27
|
+
import { dispatchSetProfile, profileCapabilities } from './profile-tool.js';
|
|
28
|
+
import { dispatchGetProfile, profileScopeLine } from './profile-lookup.js';
|
|
29
|
+
import { callTargetDenied, lineTargetDenied } from '../agents/scope.js';
|
|
30
|
+
import { SOURCE_KEYS } from '../stations/attach-resolve.js';
|
|
31
|
+
import { decodedLengthOf } from '../stations/attach-inline.js';
|
|
32
|
+
import { log } from '@metro-labs/core/log';
|
|
33
|
+
import {
|
|
34
|
+
allowedAgents,
|
|
35
|
+
currentIdentity,
|
|
36
|
+
type RequestIdentity,
|
|
37
|
+
} from './request-identity.js';
|
|
38
|
+
import { str } from '@metro-labs/core/str';
|
|
39
|
+
import { linelessRead, stationOfAccount } from './read-tool.js';
|
|
40
|
+
|
|
41
|
+
const STATION_TOOLS = new Map<
|
|
42
|
+
string,
|
|
43
|
+
{ station: Station; tool: StationTool }
|
|
44
|
+
>();
|
|
45
|
+
for (const s of STATIONS)
|
|
46
|
+
for (const t of s.tools) STATION_TOOLS.set(t.name, { station: s, tool: t });
|
|
47
|
+
|
|
48
|
+
const CORE_DISPATCH: Record<
|
|
49
|
+
string,
|
|
50
|
+
(a: Record<string, unknown>) => Promise<ToolResult>
|
|
51
|
+
> = {
|
|
52
|
+
list_members: dispatchListMembers,
|
|
53
|
+
create_group: dispatchCreateGroup,
|
|
54
|
+
add_members: dispatchAddMembers,
|
|
55
|
+
remove_members: dispatchRemoveMembers,
|
|
56
|
+
export_invite: dispatchInviteLink,
|
|
57
|
+
create_upload: dispatchCreateUpload,
|
|
58
|
+
set_profile: dispatchSetProfile,
|
|
59
|
+
get_profile: dispatchGetProfile,
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export const toolList = (): { tools: PublishedTool[] } => ({ tools: listedTools() });
|
|
63
|
+
|
|
64
|
+
let schemaSignature: string | undefined;
|
|
65
|
+
|
|
66
|
+
export const toolSchemaSignature = (): string => {
|
|
67
|
+
schemaSignature ??= createHash('sha256')
|
|
68
|
+
.update(JSON.stringify(toolList()))
|
|
69
|
+
.digest('hex')
|
|
70
|
+
.slice(0, 16);
|
|
71
|
+
return schemaSignature;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
async function handleListAccounts(
|
|
75
|
+
identity: RequestIdentity | undefined,
|
|
76
|
+
): Promise<ToolResult> {
|
|
77
|
+
try {
|
|
78
|
+
return okJson({
|
|
79
|
+
accounts: withEffectivePolicy(await gatherAccounts(allowedAgents(identity))),
|
|
80
|
+
capabilities: accountStationCapabilities(),
|
|
81
|
+
profiles: profileCapabilities(),
|
|
82
|
+
});
|
|
83
|
+
} catch (e) {
|
|
84
|
+
return errResult(`metro list_accounts failed: ${String(e)}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function scopeDenied(
|
|
89
|
+
identity: RequestIdentity | undefined,
|
|
90
|
+
name: string,
|
|
91
|
+
args: Record<string, unknown>,
|
|
92
|
+
): boolean {
|
|
93
|
+
const allowed = allowedAgents(identity);
|
|
94
|
+
if (name === 'read' && !str(args.line)) {
|
|
95
|
+
const account = str(args.account);
|
|
96
|
+
if (!account) return false;
|
|
97
|
+
const station = stationOfAccount(account);
|
|
98
|
+
return station === undefined || callTargetDenied(allowed, station, args);
|
|
99
|
+
}
|
|
100
|
+
if (name === 'get_profile') {
|
|
101
|
+
const line = profileScopeLine(args);
|
|
102
|
+
return line === undefined || callTargetDenied(allowed, Line.station(line) ?? '', { line });
|
|
103
|
+
}
|
|
104
|
+
const station = stationForTool(name, args);
|
|
105
|
+
if (station !== undefined) return callTargetDenied(allowed, station, args);
|
|
106
|
+
return lineTargetDenied(allowed, args);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const sourceOf = (entry: unknown): string => {
|
|
110
|
+
const att = (entry ?? {}) as Record<string, unknown>;
|
|
111
|
+
const named = SOURCE_KEYS.filter(
|
|
112
|
+
(k) => typeof att[k] === 'string' && att[k] !== '',
|
|
113
|
+
);
|
|
114
|
+
if (named.length === 0) return 'none';
|
|
115
|
+
return named
|
|
116
|
+
.map((k) =>
|
|
117
|
+
k === 'data' ? `data(${decodedLengthOf(String(att.data))}B)` : k,
|
|
118
|
+
)
|
|
119
|
+
.join('+');
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export const attachmentShape = (
|
|
123
|
+
a: Record<string, unknown>,
|
|
124
|
+
): string[] | undefined =>
|
|
125
|
+
Array.isArray(a.attachments) ? a.attachments.map(sourceOf) : undefined;
|
|
126
|
+
|
|
127
|
+
function logToolFailure(
|
|
128
|
+
name: string,
|
|
129
|
+
a: Record<string, unknown>,
|
|
130
|
+
result: ToolResult,
|
|
131
|
+
): void {
|
|
132
|
+
log.warn(
|
|
133
|
+
{
|
|
134
|
+
tool: name,
|
|
135
|
+
agents: [...allowedAgents(currentIdentity())],
|
|
136
|
+
line: str(a.line),
|
|
137
|
+
attachments: attachmentShape(a),
|
|
138
|
+
err: result.content[0]?.text,
|
|
139
|
+
},
|
|
140
|
+
'mcp: tool call failed',
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async function runTool(
|
|
145
|
+
req: { params: { name: string; arguments?: Record<string, unknown> } },
|
|
146
|
+
hooks: ToolHooks,
|
|
147
|
+
): Promise<ToolResult> {
|
|
148
|
+
const name = req.params.name;
|
|
149
|
+
const a = req.params.arguments ?? {};
|
|
150
|
+
|
|
151
|
+
const identity = currentIdentity();
|
|
152
|
+
if (name !== 'list_accounts' && scopeDenied(identity, name, a))
|
|
153
|
+
return errResult('metro: this account is outside your authorized scope');
|
|
154
|
+
|
|
155
|
+
const blocked = policyGate(name, a);
|
|
156
|
+
if (blocked) return blocked;
|
|
157
|
+
settlePromptsFor(name, a);
|
|
158
|
+
|
|
159
|
+
return dispatchTool(name, a, identity, hooks);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async function dispatchTool(
|
|
163
|
+
name: string,
|
|
164
|
+
a: Record<string, unknown>,
|
|
165
|
+
identity: RequestIdentity | undefined,
|
|
166
|
+
hooks: ToolHooks,
|
|
167
|
+
): Promise<ToolResult> {
|
|
168
|
+
const owned = STATION_TOOLS.get(name);
|
|
169
|
+
if (owned) {
|
|
170
|
+
try {
|
|
171
|
+
return await owned.tool.handle(a, makeCtx(owned.station.name));
|
|
172
|
+
} catch (e) {
|
|
173
|
+
return toErr(name, e);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
const core = CORE_DISPATCH[name];
|
|
177
|
+
if (core) return core(a);
|
|
178
|
+
if (name === 'list_accounts') return handleListAccounts(identity);
|
|
179
|
+
if (name === 'read' && !str(a.line)) return linelessRead(a);
|
|
180
|
+
return dispatchMessageTool(name, a, hooks);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export async function callToolHandler(
|
|
184
|
+
req: { params: { name: string; arguments?: Record<string, unknown> } },
|
|
185
|
+
hooks: ToolHooks = {},
|
|
186
|
+
): Promise<ToolResult> {
|
|
187
|
+
const result = await runTool(req, hooks);
|
|
188
|
+
if (result.isError === true)
|
|
189
|
+
logToolFailure(req.params.name, req.params.arguments ?? {}, result);
|
|
190
|
+
return result;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const TOOL_LIST_CHANGED = 'notifications/tools/list_changed';
|
|
194
|
+
|
|
195
|
+
export interface SchemaNotice {
|
|
196
|
+
markCurrent: () => void;
|
|
197
|
+
deliver: (send: () => Promise<void>) => void;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
interface NotifyingExtra {
|
|
201
|
+
sendNotification: (n: { method: string }) => Promise<void>;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export function registerToolHandlers(
|
|
205
|
+
server: Server,
|
|
206
|
+
notice?: SchemaNotice,
|
|
207
|
+
hooks: ToolHooks = {},
|
|
208
|
+
): void {
|
|
209
|
+
server.setRequestHandler(ListToolsRequestSchema, () => {
|
|
210
|
+
notice?.markCurrent();
|
|
211
|
+
return toolList();
|
|
212
|
+
});
|
|
213
|
+
server.setRequestHandler(
|
|
214
|
+
CallToolRequestSchema,
|
|
215
|
+
((
|
|
216
|
+
req: { params: { name: string; arguments?: Record<string, unknown> } },
|
|
217
|
+
extra: NotifyingExtra,
|
|
218
|
+
): Promise<ToolResult> => {
|
|
219
|
+
notice?.deliver(() =>
|
|
220
|
+
extra.sendNotification({ method: TOOL_LIST_CHANGED }),
|
|
221
|
+
);
|
|
222
|
+
return callToolHandler(req, hooks);
|
|
223
|
+
}) as Parameters<typeof server.setRequestHandler>[1],
|
|
224
|
+
);
|
|
225
|
+
}
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import type { ToolDef } from './tool-def.js';
|
|
2
|
+
import { attachmentItem, CREATE_UPLOAD_TOOL } from './attachment-schema.js';
|
|
3
|
+
|
|
4
|
+
const lineProp = {
|
|
5
|
+
type: 'string',
|
|
6
|
+
description:
|
|
7
|
+
'The metro:// line (from the inbound <channel> tag). The station is derived from it.',
|
|
8
|
+
} as const;
|
|
9
|
+
const msgIdProp = {
|
|
10
|
+
type: 'string',
|
|
11
|
+
description: 'The target message_id.',
|
|
12
|
+
} as const;
|
|
13
|
+
|
|
14
|
+
export const COMMON_TOOLS: ToolDef[] = [
|
|
15
|
+
{
|
|
16
|
+
name: 'reply',
|
|
17
|
+
group: 'write',
|
|
18
|
+
description:
|
|
19
|
+
'Reply to a specific message in a Metro conversation (text quotes the target). Args: ' +
|
|
20
|
+
"line, message_id, text. The station is derived from the line. Returns the daemon's " +
|
|
21
|
+
'reason if the station does not support replies.',
|
|
22
|
+
inputSchema: {
|
|
23
|
+
type: 'object',
|
|
24
|
+
properties: {
|
|
25
|
+
line: lineProp,
|
|
26
|
+
message_id: msgIdProp,
|
|
27
|
+
text: { type: 'string', description: 'The reply text.' },
|
|
28
|
+
},
|
|
29
|
+
required: ['line', 'message_id', 'text'],
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'send',
|
|
34
|
+
group: 'write',
|
|
35
|
+
description:
|
|
36
|
+
'Send a message (and/or media) to a Metro conversation. Args: line, text?, reply_to?, ' +
|
|
37
|
+
'subject?, attachments?. The station is derived from the line. Outlook: send to ' +
|
|
38
|
+
'metro://outlook/<account>/<email address> to start a new email (subject defaults to the ' +
|
|
39
|
+
'first line of text); the result names the new thread line. Each attachment names EXACTLY ONE ' +
|
|
40
|
+
'source, and the choice matters: `upload` (an `upload_id` from `create_upload`, the ' +
|
|
41
|
+
'route for any real file on your own machine, confidential or not, up to 64 MiB); ' +
|
|
42
|
+
'`data` (base64 inline -- TINY FILES ONLY, a few KB, because the base64 has to be ' +
|
|
43
|
+
'written out verbatim in the call and longer than that it corrupts); `url` (the daemon ' +
|
|
44
|
+
'fetches it, so the file must already be public); `path` (resolved on the DAEMON host, ' +
|
|
45
|
+
'which is not your machine). At least one of text/attachments is required. ' +
|
|
46
|
+
'The success line names each attachment the station actually delivered; a station that ' +
|
|
47
|
+
'cannot carry a file errors instead of reporting success.',
|
|
48
|
+
inputSchema: {
|
|
49
|
+
type: 'object',
|
|
50
|
+
properties: {
|
|
51
|
+
line: lineProp,
|
|
52
|
+
text: {
|
|
53
|
+
type: 'string',
|
|
54
|
+
description: 'The message text (optional if sending only media).',
|
|
55
|
+
},
|
|
56
|
+
reply_to: {
|
|
57
|
+
type: 'string',
|
|
58
|
+
description: 'Optional message_id to quote/reply to.',
|
|
59
|
+
},
|
|
60
|
+
subject: {
|
|
61
|
+
type: 'string',
|
|
62
|
+
description: 'Outlook only: the subject of a new email.',
|
|
63
|
+
},
|
|
64
|
+
attachments: {
|
|
65
|
+
type: 'array',
|
|
66
|
+
description: 'Optional files to attach.',
|
|
67
|
+
items: attachmentItem,
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
required: ['line'],
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: 'react',
|
|
75
|
+
group: 'write',
|
|
76
|
+
description:
|
|
77
|
+
'Add an emoji reaction to a message. Args: line, message_id, emoji. The station is derived from the line.',
|
|
78
|
+
inputSchema: {
|
|
79
|
+
type: 'object',
|
|
80
|
+
properties: {
|
|
81
|
+
line: lineProp,
|
|
82
|
+
message_id: msgIdProp,
|
|
83
|
+
emoji: { type: 'string', description: 'The emoji to react with.' },
|
|
84
|
+
},
|
|
85
|
+
required: ['line', 'message_id', 'emoji'],
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: 'unreact',
|
|
90
|
+
group: 'write',
|
|
91
|
+
description:
|
|
92
|
+
'Remove an emoji reaction from a message. Args: line, message_id, emoji. The station is derived from the line.',
|
|
93
|
+
inputSchema: {
|
|
94
|
+
type: 'object',
|
|
95
|
+
properties: {
|
|
96
|
+
line: lineProp,
|
|
97
|
+
message_id: msgIdProp,
|
|
98
|
+
emoji: {
|
|
99
|
+
type: 'string',
|
|
100
|
+
description: 'The emoji reaction to remove.',
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
required: ['line', 'message_id', 'emoji'],
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: 'edit',
|
|
108
|
+
group: 'write',
|
|
109
|
+
description:
|
|
110
|
+
'Edit the text of a message you sent. Args: line, message_id, text. The station is ' +
|
|
111
|
+
"derived from the line. Returns the daemon's reason if the station does not support edits.",
|
|
112
|
+
inputSchema: {
|
|
113
|
+
type: 'object',
|
|
114
|
+
properties: {
|
|
115
|
+
line: lineProp,
|
|
116
|
+
message_id: msgIdProp,
|
|
117
|
+
text: { type: 'string', description: 'The new message text.' },
|
|
118
|
+
},
|
|
119
|
+
required: ['line', 'message_id', 'text'],
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: 'delete',
|
|
124
|
+
group: 'write',
|
|
125
|
+
destructive: true,
|
|
126
|
+
description:
|
|
127
|
+
'Delete a message you sent. Args: line, message_id. The station is derived from the line. ' +
|
|
128
|
+
"Returns the daemon's reason if the station does not support deletes.",
|
|
129
|
+
inputSchema: {
|
|
130
|
+
type: 'object',
|
|
131
|
+
properties: { line: lineProp, message_id: msgIdProp },
|
|
132
|
+
required: ['line', 'message_id'],
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
name: 'read',
|
|
137
|
+
group: 'read',
|
|
138
|
+
description:
|
|
139
|
+
'Read message history. Args: line?, account?, limit?, before?, since?, until?, query?, ' +
|
|
140
|
+
'from?, unread_only?, message_id?. Give a line to read one conversation, or an account ' +
|
|
141
|
+
'(from list_accounts) instead of a line to read across that whole account, where the ' +
|
|
142
|
+
'station allows it. `message_id` returns that one message in full, with its files saved ' +
|
|
143
|
+
'like inbound media (url and local_path). Each station applies the filters it supports; ' +
|
|
144
|
+
'the answer lists any it did not apply in `ignored`, so check it. Returns the raw JSON ' +
|
|
145
|
+
"(shapes differ per station), or the daemon's reason if the station does not support " +
|
|
146
|
+
'reads. Outlook: `query` is a Microsoft search over all mail (with `from` folded into it; ' +
|
|
147
|
+
'line, since, until and unread_only then narrow what the search found), and without ' +
|
|
148
|
+
'`query` every filter is applied by Outlook itself, newest first.',
|
|
149
|
+
inputSchema: {
|
|
150
|
+
type: 'object',
|
|
151
|
+
properties: {
|
|
152
|
+
line: lineProp,
|
|
153
|
+
account: {
|
|
154
|
+
type: 'string',
|
|
155
|
+
description: 'An account id from list_accounts, to read the whole account when you give no line.',
|
|
156
|
+
},
|
|
157
|
+
limit: { type: 'number', description: 'Max messages to return.' },
|
|
158
|
+
before: {
|
|
159
|
+
type: 'string',
|
|
160
|
+
description: 'Return messages before this message_id.',
|
|
161
|
+
},
|
|
162
|
+
since: {
|
|
163
|
+
type: 'string',
|
|
164
|
+
description: 'Return messages since this timestamp.',
|
|
165
|
+
},
|
|
166
|
+
until: {
|
|
167
|
+
type: 'string',
|
|
168
|
+
description: 'Return messages before this timestamp.',
|
|
169
|
+
},
|
|
170
|
+
query: { type: 'string', description: 'Free text to search for.' },
|
|
171
|
+
from: { type: 'string', description: 'Only messages from this sender (an id or an address).' },
|
|
172
|
+
unread_only: { type: 'boolean', description: 'Only messages not read yet.' },
|
|
173
|
+
message_id: { type: 'string', description: 'Return this one message in full.' },
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
name: 'list_members',
|
|
179
|
+
group: 'read',
|
|
180
|
+
description:
|
|
181
|
+
'List the members of a Metro group/channel in a station-agnostic shape. Args: line, ' +
|
|
182
|
+
'limit?. The station is derived from the line. Returns {line, station, memberCount, ' +
|
|
183
|
+
'members:[{id, name?, display_name?, address?, roles?, is_admin?, is_bot?}], capability:' +
|
|
184
|
+
'{supported, complete, reason?, total?}}. Each station fills the fields it has (xmtp: id=' +
|
|
185
|
+
'inboxId + address; discord-bot: id + username/nick + roles + is_bot; telegram-bot/telegram: ' +
|
|
186
|
+
'id + username/first_name). Never throws on "not supported": stations that cannot ' +
|
|
187
|
+
'enumerate (e.g. the Telegram Bot API) return an empty or partial list with a reason in ' +
|
|
188
|
+
'`capability`. Check `capability.complete` before assuming the roster is exhaustive.',
|
|
189
|
+
inputSchema: {
|
|
190
|
+
type: 'object',
|
|
191
|
+
properties: {
|
|
192
|
+
line: lineProp,
|
|
193
|
+
limit: {
|
|
194
|
+
type: 'number',
|
|
195
|
+
description: 'Max members to return (best-effort; capped per station).',
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
required: ['line'],
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
name: 'create_group',
|
|
203
|
+
group: 'write',
|
|
204
|
+
description:
|
|
205
|
+
'Create a new group/channel on a station and add members, in a station-agnostic shape. ' +
|
|
206
|
+
'Args: station (required, xmtp|telegram|discord-bot|telegram-bot), name (required), members? ' +
|
|
207
|
+
'(string[]; xmtp: 0x address or inboxId, telegram: @username or user id, discord-bot: ' +
|
|
208
|
+
'user id), account? (which station account), parent? (discord-bot only: the metro:// line of ' +
|
|
209
|
+
'the channel to open the thread under). Returns {op, line (the NEW group line), station, ' +
|
|
210
|
+
'supported, reason?, id?, name?, members:[{id, status: added|invited|removed|failed, ' +
|
|
211
|
+
'reason?}], inviteLink?}. Never throws on "not supported": stations that lack the op ' +
|
|
212
|
+
'(e.g. the Telegram Bot API) return {supported:false, reason}. Telegram direct-add is ' +
|
|
213
|
+
'limited to mutual contacts / permissive privacy — members who cannot be added come back ' +
|
|
214
|
+
'as status "invited" and an `inviteLink` is returned to share with them.',
|
|
215
|
+
inputSchema: {
|
|
216
|
+
type: 'object',
|
|
217
|
+
properties: {
|
|
218
|
+
station: {
|
|
219
|
+
type: 'string',
|
|
220
|
+
description: 'The station to create the group on (xmtp|telegram|discord-bot).',
|
|
221
|
+
},
|
|
222
|
+
name: { type: 'string', description: 'The group/channel name.' },
|
|
223
|
+
members: {
|
|
224
|
+
type: 'array',
|
|
225
|
+
description: 'Members to seed the group with (station-specific identifiers).',
|
|
226
|
+
items: { type: 'string' },
|
|
227
|
+
},
|
|
228
|
+
account: {
|
|
229
|
+
type: 'string',
|
|
230
|
+
description: 'Station account to create under (defaults to the station default).',
|
|
231
|
+
},
|
|
232
|
+
parent: {
|
|
233
|
+
type: 'string',
|
|
234
|
+
description:
|
|
235
|
+
'Discord only: the metro:// line of the channel to create the thread under.',
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
required: ['station', 'name'],
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
name: 'add_members',
|
|
243
|
+
group: 'write',
|
|
244
|
+
description:
|
|
245
|
+
'Add members to an existing Metro group, in a station-agnostic shape. Args: line ' +
|
|
246
|
+
'(required), members? (string[]; station-specific identifiers). xmtp also accepts ' +
|
|
247
|
+
'addresses? (0x[]) and inboxIds? (string[]) for backward compatibility. The station is ' +
|
|
248
|
+
'derived from the line. Returns {op, line, station, supported, reason?, members:[{id, ' +
|
|
249
|
+
'status, reason?}], inviteLink?}. Never throws on "not supported". On Telegram, members ' +
|
|
250
|
+
'who cannot be direct-added come back status "invited" with an `inviteLink`.',
|
|
251
|
+
inputSchema: {
|
|
252
|
+
type: 'object',
|
|
253
|
+
properties: {
|
|
254
|
+
line: lineProp,
|
|
255
|
+
members: {
|
|
256
|
+
type: 'array',
|
|
257
|
+
description: 'Members to add (station-specific identifiers).',
|
|
258
|
+
items: { type: 'string' },
|
|
259
|
+
},
|
|
260
|
+
addresses: {
|
|
261
|
+
type: 'array',
|
|
262
|
+
description: 'xmtp only: Ethereum 0x addresses to add.',
|
|
263
|
+
items: { type: 'string' },
|
|
264
|
+
},
|
|
265
|
+
inboxIds: {
|
|
266
|
+
type: 'array',
|
|
267
|
+
description: 'xmtp only: XMTP inboxIds to add.',
|
|
268
|
+
items: { type: 'string' },
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
required: ['line'],
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
name: 'remove_members',
|
|
276
|
+
group: 'write',
|
|
277
|
+
destructive: true,
|
|
278
|
+
description:
|
|
279
|
+
'Remove members from an existing Metro group, in a station-agnostic shape. Args: line ' +
|
|
280
|
+
'(required), members? (string[]). xmtp also accepts addresses?/inboxIds? for backward ' +
|
|
281
|
+
'compatibility. The station is derived from the line. Returns {op, line, station, ' +
|
|
282
|
+
'supported, reason?, members:[{id, status, reason?}]}. Never throws on "not supported".',
|
|
283
|
+
inputSchema: {
|
|
284
|
+
type: 'object',
|
|
285
|
+
properties: {
|
|
286
|
+
line: lineProp,
|
|
287
|
+
members: {
|
|
288
|
+
type: 'array',
|
|
289
|
+
description: 'Members to remove (station-specific identifiers).',
|
|
290
|
+
items: { type: 'string' },
|
|
291
|
+
},
|
|
292
|
+
addresses: {
|
|
293
|
+
type: 'array',
|
|
294
|
+
description: 'xmtp only: Ethereum 0x addresses to remove.',
|
|
295
|
+
items: { type: 'string' },
|
|
296
|
+
},
|
|
297
|
+
inboxIds: {
|
|
298
|
+
type: 'array',
|
|
299
|
+
description: 'xmtp only: XMTP inboxIds to remove.',
|
|
300
|
+
items: { type: 'string' },
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
required: ['line'],
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
name: 'export_invite',
|
|
308
|
+
group: 'write',
|
|
309
|
+
description:
|
|
310
|
+
'Get a join/invite link for a Metro group, for platforms where direct-add is not always ' +
|
|
311
|
+
'permitted. Args: line (required). The station is derived from the line. Returns {op, ' +
|
|
312
|
+
'line, station, supported, reason?, inviteLink?}. Only telegram supports this today; ' +
|
|
313
|
+
'other stations return {supported:false, reason}. Never throws on "not supported".',
|
|
314
|
+
inputSchema: {
|
|
315
|
+
type: 'object',
|
|
316
|
+
properties: { line: lineProp },
|
|
317
|
+
required: ['line'],
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
CREATE_UPLOAD_TOOL,
|
|
321
|
+
];
|
|
322
|
+
|
|
323
|
+
export const LIST_ACCOUNTS_TOOL: ToolDef = {
|
|
324
|
+
name: 'list_accounts',
|
|
325
|
+
group: 'read',
|
|
326
|
+
description:
|
|
327
|
+
'List the configured messaging accounts across all stations (PUBLIC identity only: ' +
|
|
328
|
+
'addresses, bot ids/usernames). No args. Never returns tokens, private keys, or the ' +
|
|
329
|
+
'mnemonic. Also returns `capabilities`: the ' +
|
|
330
|
+
'message verbs (send/reply/react/unreact/edit/delete/read) each station honors, so a ' +
|
|
331
|
+
'verb need not be discovered by trial and error.',
|
|
332
|
+
inputSchema: { type: 'object', properties: {} },
|
|
333
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { publicBaseOrDefault } from '../files/attach-serve.js';
|
|
2
|
+
import { safeFileName } from '../stations/attach-inline.js';
|
|
3
|
+
import { guessMime } from '@metro-labs/core/stations/attachments';
|
|
4
|
+
import {
|
|
5
|
+
createUploadSlot,
|
|
6
|
+
issueUploadTicket,
|
|
7
|
+
MAX_UPLOAD_BYTES,
|
|
8
|
+
removeUpload,
|
|
9
|
+
UPLOAD_TTL_MS,
|
|
10
|
+
} from '../files/upload-store.js';
|
|
11
|
+
import type { ToolResult } from '@metro-labs/core/stations/types';
|
|
12
|
+
import { errResult, okJson } from './ctx.js';
|
|
13
|
+
import { allowedAgents, currentIdentity } from './request-identity.js';
|
|
14
|
+
import { str } from '@metro-labs/core/str';
|
|
15
|
+
|
|
16
|
+
const ttlMinutes = (): number => Math.round(UPLOAD_TTL_MS / 60_000);
|
|
17
|
+
|
|
18
|
+
const NO_AGENT =
|
|
19
|
+
'create_upload needs an agent credential; this session is not scoped to one agent';
|
|
20
|
+
|
|
21
|
+
type OwnerAgent = { agentId: string } | { error: string };
|
|
22
|
+
|
|
23
|
+
function ownerAgent(): OwnerAgent {
|
|
24
|
+
const allowed = allowedAgents(currentIdentity());
|
|
25
|
+
const [only] = [...allowed];
|
|
26
|
+
return allowed.size === 1 && only !== undefined ? { agentId: only } : { error: NO_AGENT };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function dispatchCreateUpload(
|
|
30
|
+
a: Record<string, unknown>,
|
|
31
|
+
): Promise<ToolResult> {
|
|
32
|
+
const owner = ownerAgent();
|
|
33
|
+
if ('error' in owner) return Promise.resolve(errResult(owner.error));
|
|
34
|
+
const agentId = owner.agentId;
|
|
35
|
+
const name = safeFileName(str(a.name) || undefined);
|
|
36
|
+
const mime = str(a.mime) || guessMime(name);
|
|
37
|
+
const id = createUploadSlot(agentId, { name, mime });
|
|
38
|
+
const token = issueUploadTicket(id, agentId);
|
|
39
|
+
if (token === undefined) {
|
|
40
|
+
removeUpload(id);
|
|
41
|
+
return Promise.resolve(errResult('metro could not reserve an upload slot'));
|
|
42
|
+
}
|
|
43
|
+
const url = `${publicBaseOrDefault()}/api/uploads/${id}?token=${token}`;
|
|
44
|
+
return Promise.resolve(
|
|
45
|
+
okJson({
|
|
46
|
+
upload_id: id,
|
|
47
|
+
upload_url: url,
|
|
48
|
+
curl: `curl -sS -T '<the file on your own machine>' '${url}'`,
|
|
49
|
+
name,
|
|
50
|
+
mime,
|
|
51
|
+
max_bytes: MAX_UPLOAD_BYTES,
|
|
52
|
+
expires_in_minutes: ttlMinutes(),
|
|
53
|
+
next:
|
|
54
|
+
'Run that command in a shell, then attach the file with ' +
|
|
55
|
+
`send({line, attachments:[{upload:'${id}'}]}). The url is single-use, is good ` +
|
|
56
|
+
`only for this one file, and expires in ${ttlMinutes()} minutes. If you have no ` +
|
|
57
|
+
'shell, delegate the one command to a subagent that does and keep the upload_id; ' +
|
|
58
|
+
'the slot belongs to this metro agent, not to whoever runs the command.',
|
|
59
|
+
}),
|
|
60
|
+
);
|
|
61
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { sessionRoute } from '@metro-labs/http/api-http';
|
|
4
|
+
import { MOVE_LOG, moveState, startMove } from './move.js';
|
|
5
|
+
import { rootHelper, runningAsMetro, runningAsRoot } from './privilege.js';
|
|
6
|
+
import { HELPER_VERSION } from './helper-script.js';
|
|
7
|
+
|
|
8
|
+
const PATH = '/api/server/metro-user';
|
|
9
|
+
const LOG_TAIL = 40;
|
|
10
|
+
|
|
11
|
+
function logTail(): string {
|
|
12
|
+
try {
|
|
13
|
+
return readFileSync(MOVE_LOG, 'utf8').split('\n').slice(-LOG_TAIL).join('\n');
|
|
14
|
+
} catch {
|
|
15
|
+
return '';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function helperVersion(): number | null {
|
|
20
|
+
if (!runningAsMetro()) return null;
|
|
21
|
+
const v = Number(rootHelper(['version']).stdout.trim());
|
|
22
|
+
return Number.isInteger(v) ? v : null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function view(): unknown {
|
|
26
|
+
const runningAs = runningAsRoot() ? 'root' : runningAsMetro() ? 'metro' : 'other';
|
|
27
|
+
const helper = helperVersion();
|
|
28
|
+
return {
|
|
29
|
+
runningAs,
|
|
30
|
+
canMove: runningAs === 'root',
|
|
31
|
+
move: moveState(),
|
|
32
|
+
log: logTail(),
|
|
33
|
+
helper,
|
|
34
|
+
helperCurrent: runningAs !== 'metro' || helper === HELPER_VERSION,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function handleMetroUserRequest(req: IncomingMessage, res: ServerResponse): boolean {
|
|
39
|
+
return sessionRoute(req, res, { methods: { [PATH]: ['GET', 'POST'] }, admin: true, label: 'metro-user-api' }, () => {
|
|
40
|
+
if (req.method === 'POST') startMove();
|
|
41
|
+
return Promise.resolve(view());
|
|
42
|
+
});
|
|
43
|
+
}
|