@stage-labs/metro 0.1.0-beta.3 → 0.1.0-beta.31
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 +131 -0
- package/dist/bedrock-eventstream.js +120 -0
- package/dist/bedrock-proxy.js +260 -0
- package/dist/bedrock-upstream.js +72 -0
- package/dist/bedrock.js +106 -0
- package/dist/claude.js +15 -0
- package/dist/cli.js +164 -253
- package/dist/control.js +158 -0
- package/dist/plugin.js +82 -0
- package/dist/prompt.js +61 -0
- package/dist/runtime.js +94 -0
- package/dist/store.js +93 -0
- package/dist/tail.js +120 -0
- package/dist/update.js +33 -0
- package/dist/version.js +97 -0
- package/package.json +34 -21
- package/runtime/node_modules/@metro-labs/discord-bot/package.json +28 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/accounts.ts +119 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/actions.ts +388 -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 +210 -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 +127 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/members.ts +215 -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 +19 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/verify.ts +82 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/voice-speak.ts +195 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/voice-transcribe.ts +292 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/voice.ts +197 -0
- package/runtime/node_modules/@metro-labs/discord-bot/src/wire.ts +5 -0
- package/runtime/node_modules/@metro-labs/mcp/package.json +66 -0
- package/runtime/node_modules/@metro-labs/mcp/src/channels/dedupe.ts +24 -0
- package/runtime/node_modules/@metro-labs/mcp/src/channels/inbound.ts +367 -0
- package/runtime/node_modules/@metro-labs/mcp/src/channels/media-note.ts +85 -0
- package/runtime/node_modules/@metro-labs/mcp/src/channels/pending.ts +75 -0
- package/runtime/node_modules/@metro-labs/mcp/src/channels/relay.ts +129 -0
- package/runtime/node_modules/@metro-labs/mcp/src/channels/webhook-note.ts +51 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/account-api.ts +311 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/agent-api.ts +332 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/agent-connector-api.ts +150 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/agent-pair.ts +20 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/api-error.ts +8 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/api-http.ts +152 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/attach-grant.ts +99 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/attach-owner.ts +32 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/attach-serve.ts +129 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/attach-session.ts +278 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/boot.ts +330 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/cli-pair-api.ts +125 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-api.ts +313 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-json.ts +21 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-oauth-routes.ts +157 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-oauth.ts +127 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-tools.ts +100 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-url.ts +57 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-verify.ts +333 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/cors.ts +29 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/crash-guard.ts +49 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/events.ts +117 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/google-auth.ts +164 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/google-oauth.ts +208 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/http.ts +359 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/identity.ts +79 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/log.ts +42 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/oauth-client.ts +162 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/oauth-discovery.ts +120 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/oauth-pending.ts +65 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/pair-codes.ts +58 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/paths.ts +134 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/project-api.ts +214 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/protocol.ts +224 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/relay.ts +303 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/run-api.ts +139 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/runtime-source.ts +105 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/secure-fs.ts +57 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/session-api.ts +27 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/session-apis.ts +48 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/session.ts +218 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/supervisor-io.ts +97 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/supervisor.ts +323 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/train-call.ts +22 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/train-error.ts +53 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/tunnel.ts +169 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/upload-api.ts +295 -0
- package/runtime/node_modules/@metro-labs/mcp/src/daemon/upload-store.ts +181 -0
- package/runtime/node_modules/@metro-labs/mcp/src/db/account-attach.ts +91 -0
- package/runtime/node_modules/@metro-labs/mcp/src/db/agent-admin.ts +215 -0
- package/runtime/node_modules/@metro-labs/mcp/src/db/agent-connectors.ts +143 -0
- package/runtime/node_modules/@metro-labs/mcp/src/db/agent-map.ts +71 -0
- package/runtime/node_modules/@metro-labs/mcp/src/db/agent-scope.ts +64 -0
- package/runtime/node_modules/@metro-labs/mcp/src/db/client.ts +37 -0
- package/runtime/node_modules/@metro-labs/mcp/src/db/connector-config.ts +147 -0
- package/runtime/node_modules/@metro-labs/mcp/src/db/connector-relay.ts +126 -0
- package/runtime/node_modules/@metro-labs/mcp/src/db/connectors.ts +308 -0
- package/runtime/node_modules/@metro-labs/mcp/src/db/ids.ts +19 -0
- package/runtime/node_modules/@metro-labs/mcp/src/db/key-map.ts +45 -0
- package/runtime/node_modules/@metro-labs/mcp/src/db/materialize.ts +382 -0
- package/runtime/node_modules/@metro-labs/mcp/src/db/projects.ts +300 -0
- package/runtime/node_modules/@metro-labs/mcp/src/db/runtime-admin.ts +24 -0
- package/runtime/node_modules/@metro-labs/mcp/src/db/runtimes.ts +105 -0
- package/runtime/node_modules/@metro-labs/mcp/src/db/schema.ts +117 -0
- package/runtime/node_modules/@metro-labs/mcp/src/db/token-carry.ts +45 -0
- package/runtime/node_modules/@metro-labs/mcp/src/db/users.ts +62 -0
- package/runtime/node_modules/@metro-labs/mcp/src/db/whatsapp-login.ts +18 -0
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/accounts.ts +145 -0
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/call-tools.ts +203 -0
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/channel-owner.ts +29 -0
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/ctx.ts +62 -0
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/event-store.ts +91 -0
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/frame-scope.ts +21 -0
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/group-tools.ts +129 -0
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/index.ts +192 -0
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/member-tools.ts +72 -0
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/permission-relay.ts +66 -0
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/raw-get-stream.ts +207 -0
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/request-identity.ts +73 -0
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/session-registry.ts +172 -0
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/session-route.ts +43 -0
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/session.ts +211 -0
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/str.ts +5 -0
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/tool-dispatch.ts +212 -0
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/tool-schemas.ts +397 -0
- package/runtime/node_modules/@metro-labs/mcp/src/mcp/upload-tool.ts +66 -0
- package/runtime/node_modules/@metro-labs/mcp/src/monitor/api.ts +240 -0
- package/runtime/node_modules/@metro-labs/mcp/src/server.ts +2 -0
- package/runtime/node_modules/@metro-labs/mcp/src/stations/account-store.ts +80 -0
- package/runtime/node_modules/@metro-labs/mcp/src/stations/attach-inline.ts +100 -0
- package/runtime/node_modules/@metro-labs/mcp/src/stations/attach-interactive.ts +161 -0
- package/runtime/node_modules/@metro-labs/mcp/src/stations/attach-resolve.ts +200 -0
- package/runtime/node_modules/@metro-labs/mcp/src/stations/attach-xmtp.ts +111 -0
- package/runtime/node_modules/@metro-labs/mcp/src/stations/attach.ts +182 -0
- package/runtime/node_modules/@metro-labs/mcp/src/stations/attachments.ts +196 -0
- package/runtime/node_modules/@metro-labs/mcp/src/stations/lines.ts +82 -0
- package/runtime/node_modules/@metro-labs/mcp/src/stations/messaging-normalize.ts +88 -0
- package/runtime/node_modules/@metro-labs/mcp/src/stations/registry.ts +35 -0
- package/runtime/node_modules/@metro-labs/mcp/src/stations/station-runtime.ts +64 -0
- package/runtime/node_modules/@metro-labs/mcp/src/stations/types.ts +107 -0
- package/runtime/node_modules/@metro-labs/telegram/package.json +28 -0
- package/runtime/node_modules/@metro-labs/telegram/src/accounts.ts +81 -0
- package/runtime/node_modules/@metro-labs/telegram/src/actions.ts +254 -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 +141 -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 +78 -0
- package/runtime/node_modules/@metro-labs/telegram/src/index.ts +46 -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/reactions.ts +167 -0
- package/runtime/node_modules/@metro-labs/telegram/src/station.ts +24 -0
- package/runtime/node_modules/@metro-labs/telegram/src/types.ts +7 -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 +120 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/actions.ts +295 -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 +172 -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 +166 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/members.ts +47 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/station.ts +17 -0
- package/runtime/node_modules/@metro-labs/telegram-bot/src/types.ts +48 -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 +3 -0
- package/runtime/node_modules/@metro-labs/webhook/package.json +23 -0
- package/runtime/node_modules/@metro-labs/webhook/src/station.ts +40 -0
- package/runtime/node_modules/@metro-labs/whatsapp/package.json +29 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/accounts.ts +67 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/ack.ts +101 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/actions.ts +178 -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 +318 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/delivery.ts +49 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/format.ts +132 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/inbound.ts +57 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/index.ts +40 -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/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 +141 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/station.ts +17 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/token-store.ts +98 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/types.ts +6 -0
- package/runtime/node_modules/@metro-labs/whatsapp/src/wire.ts +5 -0
- package/runtime/node_modules/@metro-labs/xmtp/package.json +33 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/accounts.ts +113 -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 +299 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/actions-meta.ts +157 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/actions-push.ts +87 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/actions.ts +375 -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-core.ts +55 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/emit-payloads.ts +333 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/emit.ts +78 -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 +33 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/index.ts +125 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/labels.ts +157 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/member-args.ts +40 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/push.ts +349 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/station.ts +13 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/tools-handlers.ts +126 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/tools.ts +212 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/transcribe.ts +90 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/verify.ts +84 -0
- package/runtime/node_modules/@metro-labs/xmtp/src/wire.ts +39 -0
- package/runtime/runtime.json +3 -0
- package/runtime/trains/.keep +0 -0
- package/LICENSE +0 -21
- package/README.md +0 -114
- package/dist/agents/claude.js +0 -229
- package/dist/agents/codex.js +0 -282
- package/dist/agents/types.js +0 -3
- package/dist/channels/discord.js +0 -142
- package/dist/channels/telegram.js +0 -209
- package/dist/lib/dotenv.js +0 -31
- package/dist/lib/scope-cache.js +0 -85
- package/dist/lib/streaming.js +0 -207
- package/dist/log.js +0 -12
- package/dist/orchestrator.js +0 -399
- package/dist/paths.js +0 -33
package/dist/lib/scope-cache.js
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
// Per-machine cache of `scope_key → { agent thread ids, last-used }`.
|
|
2
|
-
// Lets orchestrator restarts rejoin the same agent conversation in the
|
|
3
|
-
// same Discord thread instead of starting from scratch. JSON file at
|
|
4
|
-
// $STATE_DIR/scopes.json.
|
|
5
|
-
//
|
|
6
|
-
// One Discord thread can have up to one session per agent kind — when a
|
|
7
|
-
// user explicitly switches via "with claude" / "with codex", a fresh
|
|
8
|
-
// session is allocated for the new kind and stored alongside.
|
|
9
|
-
//
|
|
10
|
-
// Scope keys are platform-prefixed so the same store handles Discord and
|
|
11
|
-
// Telegram without collisions:
|
|
12
|
-
// discord:<thread_channel_id>
|
|
13
|
-
// telegram:<chat_id>:<topic_id>
|
|
14
|
-
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
15
|
-
import { join } from 'node:path';
|
|
16
|
-
import { errMsg, log } from '../log.js';
|
|
17
|
-
import { STATE_DIR } from '../paths.js';
|
|
18
|
-
const cacheFile = join(STATE_DIR, 'scopes.json');
|
|
19
|
-
function read() {
|
|
20
|
-
if (!existsSync(cacheFile))
|
|
21
|
-
return {};
|
|
22
|
-
try {
|
|
23
|
-
return JSON.parse(readFileSync(cacheFile, 'utf8'));
|
|
24
|
-
}
|
|
25
|
-
catch (err) {
|
|
26
|
-
log.warn({ err: errMsg(err), path: cacheFile }, 'scope cache read failed; treating as empty');
|
|
27
|
-
return {};
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
function write(cache) {
|
|
31
|
-
try {
|
|
32
|
-
writeFileSync(cacheFile, JSON.stringify(cache, null, 2));
|
|
33
|
-
}
|
|
34
|
-
catch (err) {
|
|
35
|
-
log.warn({ err: errMsg(err), path: cacheFile }, 'scope cache write failed');
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
function ensure(cache, scopeKey) {
|
|
39
|
-
if (!cache[scopeKey])
|
|
40
|
-
cache[scopeKey] = { createdAt: new Date().toISOString(), agents: {} };
|
|
41
|
-
if (!cache[scopeKey].agents)
|
|
42
|
-
cache[scopeKey].agents = {};
|
|
43
|
-
return cache[scopeKey];
|
|
44
|
-
}
|
|
45
|
-
export function getAgentThread(scopeKey, kind) {
|
|
46
|
-
return read()[scopeKey]?.agents?.[kind];
|
|
47
|
-
}
|
|
48
|
-
export function setAgentThread(scopeKey, kind, threadId) {
|
|
49
|
-
const cache = read();
|
|
50
|
-
const entry = ensure(cache, scopeKey);
|
|
51
|
-
entry.agents[kind] = threadId;
|
|
52
|
-
entry.lastAgent = kind;
|
|
53
|
-
write(cache);
|
|
54
|
-
}
|
|
55
|
-
export function getLastAgent(scopeKey) {
|
|
56
|
-
return read()[scopeKey]?.lastAgent;
|
|
57
|
-
}
|
|
58
|
-
export function setLastAgent(scopeKey, kind) {
|
|
59
|
-
const cache = read();
|
|
60
|
-
if (!cache[scopeKey])
|
|
61
|
-
return;
|
|
62
|
-
cache[scopeKey].lastAgent = kind;
|
|
63
|
-
write(cache);
|
|
64
|
-
}
|
|
65
|
-
export function setLastSeen(scopeKey, messageId) {
|
|
66
|
-
const cache = read();
|
|
67
|
-
if (!cache[scopeKey])
|
|
68
|
-
return;
|
|
69
|
-
cache[scopeKey].lastSeenMessageId = messageId;
|
|
70
|
-
write(cache);
|
|
71
|
-
}
|
|
72
|
-
export function listScopes() {
|
|
73
|
-
return Object.entries(read()).map(([scopeKey, entry]) => ({ scopeKey, entry }));
|
|
74
|
-
}
|
|
75
|
-
export function discordScopeKey(threadChannelId) {
|
|
76
|
-
return `discord:${threadChannelId}`;
|
|
77
|
-
}
|
|
78
|
-
export function discordChannelFromScopeKey(scopeKey) {
|
|
79
|
-
return scopeKey.startsWith('discord:') ? scopeKey.slice('discord:'.length) : null;
|
|
80
|
-
}
|
|
81
|
-
// Telegram scope: chat + optional forum-topic id. Use a sentinel ('main')
|
|
82
|
-
// for non-topic chats so the key shape stays predictable.
|
|
83
|
-
export function telegramScopeKey(chatId, topicId) {
|
|
84
|
-
return `telegram:${chatId}:${topicId ?? 'main'}`;
|
|
85
|
-
}
|
package/dist/lib/streaming.js
DELETED
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
// Accumulates streaming response deltas + tool-call status lines from a
|
|
2
|
-
// running agent turn and pushes them to a chat platform (Discord / Telegram)
|
|
3
|
-
// via debounced message edits. Smooth visible progress without hammering
|
|
4
|
-
// rate limits.
|
|
5
|
-
//
|
|
6
|
-
// The debounce is owned by a per-bot `StreamScheduler`, not by individual
|
|
7
|
-
// streams. One tick (e.g. every 1500ms) flushes every dirty stream the bot
|
|
8
|
-
// has accumulated, so two concurrent threads don't compound into 2× the
|
|
9
|
-
// edit rate on the same bot token.
|
|
10
|
-
//
|
|
11
|
-
// When the agent's response grows past the platform's per-message content
|
|
12
|
-
// cap, the body is split across multiple messages: the prior segment is
|
|
13
|
-
// frozen at its final text, and a fresh message holds the continuation
|
|
14
|
-
// (with the live status line, which always anchors to the latest segment).
|
|
15
|
-
//
|
|
16
|
-
// On agent turn completion, call finalize() to flush a final edit with the
|
|
17
|
-
// status cleared.
|
|
18
|
-
import { errMsg, log } from '../log.js';
|
|
19
|
-
// Steady-state cadence: 1500ms keeps us comfortably under Discord's ~5/5s
|
|
20
|
-
// per-channel edit cap even after the transport adds its own retry-on-429
|
|
21
|
-
// jitter. After a quiet period, the next flush is leading-edge (LEADING_MS)
|
|
22
|
-
// so short responses don't appear as one final dump.
|
|
23
|
-
const DEFAULT_DEBOUNCE_MS = 1500;
|
|
24
|
-
const LEADING_MS = 500;
|
|
25
|
-
// Discord's bot content cap is 2000 by default (4000 for boosted/Nitro).
|
|
26
|
-
// 1900 is universally safe and leaves headroom for the status suffix.
|
|
27
|
-
const MAX_BODY_LEN = 1900;
|
|
28
|
-
// Reserve for "\n\n_<status>_" + a continuation hint.
|
|
29
|
-
const STATUS_RESERVE = 80;
|
|
30
|
-
/**
|
|
31
|
-
* One scheduler per bot. Coalesces edits across every active stream the
|
|
32
|
-
* bot is serving — Discord's per-channel rate limit doesn't compound when
|
|
33
|
-
* we run multiple threads concurrently this way.
|
|
34
|
-
*/
|
|
35
|
-
export class StreamScheduler {
|
|
36
|
-
debounceMs;
|
|
37
|
-
leadingMs;
|
|
38
|
-
dirty = new Set();
|
|
39
|
-
timer = null;
|
|
40
|
-
lastFlushAt = 0;
|
|
41
|
-
constructor(debounceMs = DEFAULT_DEBOUNCE_MS, leadingMs = LEADING_MS) {
|
|
42
|
-
this.debounceMs = debounceMs;
|
|
43
|
-
this.leadingMs = leadingMs;
|
|
44
|
-
}
|
|
45
|
-
request(stream) {
|
|
46
|
-
this.dirty.add(stream);
|
|
47
|
-
if (this.timer)
|
|
48
|
-
return;
|
|
49
|
-
// Leading-edge: if we haven't flushed recently, fire fast so the first
|
|
50
|
-
// visible content lands within `leadingMs` of the agent's first delta.
|
|
51
|
-
// Otherwise stay at the steady-state cadence to respect rate limits.
|
|
52
|
-
const sinceLast = Date.now() - this.lastFlushAt;
|
|
53
|
-
const delay = sinceLast >= this.debounceMs ? this.leadingMs : this.debounceMs - sinceLast;
|
|
54
|
-
this.timer = setTimeout(() => {
|
|
55
|
-
this.timer = null;
|
|
56
|
-
this.lastFlushAt = Date.now();
|
|
57
|
-
const batch = [...this.dirty];
|
|
58
|
-
this.dirty.clear();
|
|
59
|
-
// Fire all in parallel — distinct channels are in distinct rate-limit
|
|
60
|
-
// buckets, so they don't queue behind each other.
|
|
61
|
-
for (const s of batch)
|
|
62
|
-
void s._flushFromScheduler();
|
|
63
|
-
}, delay);
|
|
64
|
-
}
|
|
65
|
-
/** Drop a stream from the queue (called when it finalizes). */
|
|
66
|
-
forget(stream) {
|
|
67
|
-
this.dirty.delete(stream);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
export class StreamingMessage {
|
|
71
|
-
adapter;
|
|
72
|
-
scheduler;
|
|
73
|
-
segments = [{ id: null, text: '', dirty: false }];
|
|
74
|
-
statusLine = null;
|
|
75
|
-
flushing = false;
|
|
76
|
-
flushAgain = false;
|
|
77
|
-
finalized = false;
|
|
78
|
-
constructor(adapter, scheduler) {
|
|
79
|
-
this.adapter = adapter;
|
|
80
|
-
this.scheduler = scheduler;
|
|
81
|
-
}
|
|
82
|
-
appendDelta(delta) {
|
|
83
|
-
if (this.finalized || !delta)
|
|
84
|
-
return;
|
|
85
|
-
this.appendToLast(delta);
|
|
86
|
-
this.scheduler.request(this);
|
|
87
|
-
}
|
|
88
|
-
setStatus(status) {
|
|
89
|
-
if (this.finalized)
|
|
90
|
-
return;
|
|
91
|
-
this.statusLine = status;
|
|
92
|
-
this.markLastDirty();
|
|
93
|
-
this.scheduler.request(this);
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Append an error notice to the visible message. Renders as `⚠️ <msg>`
|
|
97
|
-
* either on its own (no prior text) or after a blank line (preserves
|
|
98
|
-
* whatever streamed before the failure). Clears any pending status
|
|
99
|
-
* line since 'Thinking…' is meaningless after an error.
|
|
100
|
-
*/
|
|
101
|
-
appendError(message) {
|
|
102
|
-
if (this.finalized)
|
|
103
|
-
return;
|
|
104
|
-
const last = this.segments[this.segments.length - 1];
|
|
105
|
-
const sep = last.text ? '\n\n' : '';
|
|
106
|
-
this.statusLine = null;
|
|
107
|
-
this.appendToLast(`${sep}⚠️ ${message}`);
|
|
108
|
-
this.scheduler.request(this);
|
|
109
|
-
}
|
|
110
|
-
async finalize() {
|
|
111
|
-
if (this.finalized)
|
|
112
|
-
return;
|
|
113
|
-
this.finalized = true;
|
|
114
|
-
this.scheduler.forget(this);
|
|
115
|
-
this.statusLine = null;
|
|
116
|
-
this.markLastDirty();
|
|
117
|
-
await this.flush();
|
|
118
|
-
}
|
|
119
|
-
/** Internal — called by the scheduler tick. */
|
|
120
|
-
async _flushFromScheduler() {
|
|
121
|
-
await this.flush();
|
|
122
|
-
}
|
|
123
|
-
appendToLast(delta) {
|
|
124
|
-
const cap = MAX_BODY_LEN - STATUS_RESERVE;
|
|
125
|
-
let remaining = delta;
|
|
126
|
-
while (remaining) {
|
|
127
|
-
let last = this.segments[this.segments.length - 1];
|
|
128
|
-
const room = cap - last.text.length;
|
|
129
|
-
if (room <= 0) {
|
|
130
|
-
// Previous last loses status anchor — re-edit without it.
|
|
131
|
-
last.dirty = true;
|
|
132
|
-
last = { id: null, text: '', dirty: false };
|
|
133
|
-
this.segments.push(last);
|
|
134
|
-
continue;
|
|
135
|
-
}
|
|
136
|
-
const take = this.sliceAtBoundary(remaining, room);
|
|
137
|
-
last.text += take;
|
|
138
|
-
last.dirty = true;
|
|
139
|
-
remaining = remaining.slice(take.length);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
// Prefer splitting at the last newline / space / sentence end within the
|
|
143
|
-
// allowed slice, so continuation messages don't cut words in half. Falls
|
|
144
|
-
// back to a hard slice if no boundary is in reach.
|
|
145
|
-
sliceAtBoundary(s, room) {
|
|
146
|
-
if (s.length <= room)
|
|
147
|
-
return s;
|
|
148
|
-
const candidate = s.slice(0, room);
|
|
149
|
-
const breakers = ['\n\n', '\n', '. ', ' '];
|
|
150
|
-
for (const b of breakers) {
|
|
151
|
-
const i = candidate.lastIndexOf(b);
|
|
152
|
-
if (i > room * 0.5)
|
|
153
|
-
return candidate.slice(0, i + b.length);
|
|
154
|
-
}
|
|
155
|
-
return candidate;
|
|
156
|
-
}
|
|
157
|
-
markLastDirty() {
|
|
158
|
-
this.segments[this.segments.length - 1].dirty = true;
|
|
159
|
-
}
|
|
160
|
-
async flush() {
|
|
161
|
-
if (this.flushing) {
|
|
162
|
-
this.flushAgain = true;
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
this.flushing = true;
|
|
166
|
-
try {
|
|
167
|
-
do {
|
|
168
|
-
this.flushAgain = false;
|
|
169
|
-
for (let i = 0; i < this.segments.length; i++) {
|
|
170
|
-
const s = this.segments[i];
|
|
171
|
-
const isLast = i === this.segments.length - 1;
|
|
172
|
-
const body = this.render(s, isLast);
|
|
173
|
-
if (!body)
|
|
174
|
-
continue;
|
|
175
|
-
try {
|
|
176
|
-
if (s.id === null) {
|
|
177
|
-
s.id = await this.adapter.send(body);
|
|
178
|
-
s.dirty = false;
|
|
179
|
-
}
|
|
180
|
-
else if (s.dirty) {
|
|
181
|
-
await this.adapter.edit(s.id, body);
|
|
182
|
-
s.dirty = false;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
catch (err) {
|
|
186
|
-
log.warn({ err: errMsg(err) }, 'streaming edit failed');
|
|
187
|
-
// Leave dirty=true so the next tick retries.
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
} while (this.flushAgain);
|
|
191
|
-
}
|
|
192
|
-
finally {
|
|
193
|
-
this.flushing = false;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
render(s, isLast) {
|
|
197
|
-
const body = s.text;
|
|
198
|
-
const showStatus = isLast && !!this.statusLine;
|
|
199
|
-
if (!body && !showStatus)
|
|
200
|
-
return ''; // nothing to show yet — skip the flush
|
|
201
|
-
if (!body)
|
|
202
|
-
return this.statusLine;
|
|
203
|
-
if (showStatus)
|
|
204
|
-
return `${body}\n\n${this.statusLine}`;
|
|
205
|
-
return body;
|
|
206
|
-
}
|
|
207
|
-
}
|
package/dist/log.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
// Pino → stderr. Stdout is reserved for command output (`metro`'s inbound
|
|
2
|
-
// JSON lines, subcommand results, --json) — any stray write there breaks
|
|
3
|
-
// parsing. Override level with METRO_LOG_LEVEL.
|
|
4
|
-
import pino from 'pino';
|
|
5
|
-
export const log = pino({ name: 'metro', level: process.env.METRO_LOG_LEVEL || 'info' }, pino.destination(2));
|
|
6
|
-
export const errMsg = (err) => {
|
|
7
|
-
if (err instanceof Error)
|
|
8
|
-
return err.message;
|
|
9
|
-
if (err && typeof err === 'object' && 'message' in err)
|
|
10
|
-
return String(err.message);
|
|
11
|
-
return String(err);
|
|
12
|
-
};
|