@deadragdoll/tellymcp 0.0.9 → 0.0.11
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/.env.example.client +42 -50
- package/.env.example.gateway +49 -61
- package/CHANGELOG.md +3 -3
- package/README-ru.md +205 -384
- package/README.md +195 -1194
- package/TOOLS.md +294 -377
- package/VERSION.md +36 -10
- package/config/codex/plugins/telly-workflows/.codex-plugin/plugin.json +18 -0
- package/config/codex/plugins/telly-workflows/references/invariants.md +10 -0
- package/config/codex/plugins/telly-workflows/skills/telly-browser-screenshot/SKILL.md +27 -0
- package/config/codex/plugins/telly-workflows/skills/telly-collab-artifact/SKILL.md +22 -0
- package/config/codex/plugins/telly-workflows/skills/telly-human-telegram/SKILL.md +31 -0
- package/config/codex/plugins/telly-workflows/skills/telly-partner-note/SKILL.md +36 -0
- package/config/templates/env.both.template +40 -20
- package/config/templates/env.client.template +34 -18
- package/config/templates/env.gateway.template +38 -22
- package/dist/cli.js +322 -75
- package/dist/codexPluginInstaller.js +215 -0
- package/dist/lib/mixins/session.errors.js +34 -1
- package/dist/lib/pinoTargets.js +2 -2
- package/dist/moleculer.config.js +7 -5
- package/dist/services/features/telegram-mcp/approval.service.js +1 -1
- package/dist/services/features/telegram-mcp/browser.service.js +95 -2
- package/dist/services/features/telegram-mcp/collaboration.service.js +41 -4
- package/dist/services/features/telegram-mcp/ensuredb.service.js +145 -26
- package/dist/services/features/telegram-mcp/gateway-delivery.service.js +285 -103
- package/dist/services/features/telegram-mcp/gateway-rmq.service.js +3 -2
- package/dist/services/features/telegram-mcp/gateway-socket.service.js +905 -87
- package/dist/services/features/telegram-mcp/gateway.service.js +876 -81
- package/dist/services/features/telegram-mcp/mcp-http.service.js +9 -1
- package/dist/services/features/telegram-mcp/mcp-server.service.js +17 -26
- package/dist/services/features/telegram-mcp/notify.service.js +128 -2
- package/dist/services/features/telegram-mcp/runtime.service.js +27 -7
- package/dist/services/features/telegram-mcp/session-context.service.js +29 -2
- package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +133 -10
- package/dist/services/features/telegram-mcp/src/app/config/env.js +161 -51
- package/dist/services/features/telegram-mcp/src/app/http.js +375 -42
- package/dist/services/features/telegram-mcp/src/app/webapp/assets.js +386 -58
- package/dist/services/features/telegram-mcp/src/app/webapp/auth.js +3 -0
- package/dist/services/features/telegram-mcp/src/app/webapp/terminal.js +12 -0
- package/dist/services/features/telegram-mcp/src/entities/request/model/schema.js +116 -104
- package/dist/services/features/telegram-mcp/src/entities/xchange/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/features/ask-user/model/askUserTelegram.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserScreenshotTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserService.js +249 -19
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/gatewaySessionsService.js +71 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/listGatewaySessionsTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/localCollaborationBackend.js +93 -82
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileService.js +47 -5
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerNoteTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayClientAccess.js +82 -0
- package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayCollaborationBackend.js +22 -14
- package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayHttpService.js +649 -75
- package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/remoteConsoleActionClient.js +76 -0
- package/dist/services/features/telegram-mcp/src/features/embedded-runtime/model/embeddedRuntimeBroker.js +92 -0
- package/dist/services/features/telegram-mcp/src/features/foreground-terminal/model/foregroundTerminalRuntime.js +192 -0
- package/dist/services/features/telegram-mcp/src/features/notify/model/notifyService.js +382 -3
- package/dist/services/features/telegram-mcp/src/features/notify/model/notifyTelegramTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/notify/model/sendFileToTelegramTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/clearSessionContextTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/session-context/model/getSessionContextTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/session-context/model/renameSessionTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/session-context/model/sessionContextService.js +42 -200
- package/dist/services/features/telegram-mcp/src/features/session-context/model/setSessionContextTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/terminal-buffer/model/terminalBufferService.js +96 -0
- package/dist/services/features/telegram-mcp/src/features/terminal-input/model/terminalInputService.js +97 -0
- package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownService.js +107 -58
- package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/xchange/model/getXchangeRecordTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/xchange/model/listXchangeRecordsTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/xchange/model/markXchangeRecordReadTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/xchange/model/xchangeService.js +169 -0
- package/dist/services/features/telegram-mcp/src/processes/human-approval/model/orchestrator.js +5 -4
- package/dist/services/features/telegram-mcp/src/shared/i18n/index.js +46 -0
- package/dist/services/features/telegram-mcp/src/shared/i18n/resources/en.js +652 -0
- package/dist/services/features/telegram-mcp/src/shared/i18n/resources/ru.js +652 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/memory/processLocalSessionStore.js +27 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/object-storage/minioExchangeStore.js +11 -8
- package/dist/services/features/telegram-mcp/src/shared/integrations/redis/stateStore.js +51 -71
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/proxyFetch.js +21 -22
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +411 -6524
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportAttachmentStore.js +93 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportBroadcastActions.js +385 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConsoleRegistry.js +143 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConstructorWiring.js +633 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportContent.js +84 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportContext.js +78 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportDocumentActions.js +36 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportEventActions.js +292 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportFileHandoffActions.js +352 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportFormatting.js +75 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportGatewayActions.js +44 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLifecycleActions.js +161 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLive.js +56 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLiveActions.js +77 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuCallbacks.js +254 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFactories.js +538 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFingerprints.js +93 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFlow.js +344 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuShell.js +62 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuState.js +408 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuText.js +216 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMessageFlow.js +452 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportOutputActions.js +189 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportPartnerActions.js +286 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportPayloadState.js +101 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectActions.js +463 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectEntryActions.js +202 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectEvents.js +99 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectMenus.js +138 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectState.js +308 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectView.js +426 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportRequestFlow.js +278 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportSessionActions.js +143 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalActions.js +468 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalRuntime.js +171 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTypes.js +2 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportUtils.js +330 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportXchangeState.js +107 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/client.js +255 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/ptyRegistry.js +543 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/xchange/sqliteRecordStore.js +223 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/gatewayScope.js +24 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/logger/logger.js +6 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/project-identity/projectIdentity.js +147 -76
- package/dist/services/features/telegram-mcp/src/shared/lib/telegramXchangeRecords.js +72 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/terminalPromptDetection.js +237 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/version/versionHandshake.js +129 -1
- package/dist/services/features/telegram-mcp/src/shared/lib/xchangeRecordHints.js +98 -0
- package/dist/services/features/telegram-mcp/standalone-http.service.js +13 -1
- package/dist/services/features/telegram-mcp/terminal-buffer.service.js +42 -0
- package/dist/services/features/telegram-mcp/terminal-input.service.js +41 -0
- package/dist/services/features/telegram-mcp/tools-sync.service.js +16 -2
- package/dist/services/features/telegram-mcp/xchange.service.js +123 -0
- package/docs/STANDALONE-ru.md +172 -0
- package/docs/STANDALONE.md +172 -0
- package/package.json +11 -5
- package/scripts/build-package-artifact.sh +27 -0
- package/scripts/deploy-gateway.sh +64 -0
- package/scripts/deploy-onebot-branch.sh +27 -0
- package/scripts/postinstall.js +11 -36
- package/STANDALONE-ru.md +0 -274
- package/STANDALONE.md +0 -274
- package/dist/services/features/telegram-mcp/inbox.service.js +0 -33
- package/dist/services/features/telegram-mcp/pair.service.js +0 -33
- package/dist/services/features/telegram-mcp/src/app/webapp/tmux.js +0 -10
- package/dist/services/features/telegram-mcp/src/features/inbox/model/deleteTelegramInboxMessageTool.js +0 -33
- package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxCountTool.js +0 -33
- package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxTool.js +0 -33
- package/dist/services/features/telegram-mcp/src/features/inbox/model/inboxService.js +0 -77
- package/dist/services/features/telegram-mcp/src/features/pair-session/model/clearSessionPairingTool.js +0 -33
- package/dist/services/features/telegram-mcp/src/features/pair-session/model/createSessionPairCodeTool.js +0 -33
- package/dist/services/features/telegram-mcp/src/features/pair-session/model/generatePairCode.js +0 -202
- package/dist/services/features/telegram-mcp/src/features/session-context/model/getTmuxTargetTool.js +0 -33
- package/dist/services/features/telegram-mcp/src/features/session-context/model/setTmuxTargetTool.js +0 -33
- package/dist/services/features/telegram-mcp/src/shared/integrations/tmux/client.js +0 -363
|
@@ -1,18 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.createMcpHttpHandler = createMcpHttpHandler;
|
|
4
7
|
const node_crypto_1 = require("node:crypto");
|
|
5
8
|
const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
9
|
+
const ws_1 = __importDefault(require("ws"));
|
|
6
10
|
const auth_1 = require("./webapp/auth");
|
|
7
11
|
const relay_1 = require("./webapp/relay");
|
|
8
12
|
const assets_1 = require("./webapp/assets");
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
const client_1 = require("../shared/integrations/terminal/client");
|
|
14
|
+
const terminal_1 = require("./webapp/terminal");
|
|
15
|
+
function formatTerminalHttpError(error, fallback) {
|
|
16
|
+
if ((0, terminal_1.isTerminalUnavailableError)(error)) {
|
|
17
|
+
return "terminal runtime is unavailable";
|
|
13
18
|
}
|
|
14
19
|
return fallback;
|
|
15
20
|
}
|
|
21
|
+
function requireTelegramBotToken(runtime, purpose) {
|
|
22
|
+
const token = runtime.config.telegram.botToken?.trim();
|
|
23
|
+
if (!token) {
|
|
24
|
+
throw new Error(`Telegram bot token is unavailable on this node; cannot ${purpose}.`);
|
|
25
|
+
}
|
|
26
|
+
return token;
|
|
27
|
+
}
|
|
16
28
|
function isInitializeRequest(body) {
|
|
17
29
|
if (!body || typeof body !== "object") {
|
|
18
30
|
return false;
|
|
@@ -117,22 +129,233 @@ function normalizeBasePath(value) {
|
|
|
117
129
|
}
|
|
118
130
|
return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
119
131
|
}
|
|
120
|
-
function
|
|
132
|
+
function readWebhookSecretHeader(req) {
|
|
133
|
+
const value = req.headers["x-telegram-bot-api-secret-token"];
|
|
134
|
+
if (Array.isArray(value)) {
|
|
135
|
+
return value[0];
|
|
136
|
+
}
|
|
137
|
+
return value;
|
|
138
|
+
}
|
|
139
|
+
function isRelayTerminalUnavailableMessage(error) {
|
|
121
140
|
const text = error instanceof Error ? error.message : String(error);
|
|
122
|
-
return text.includes("
|
|
141
|
+
return text.includes("terminal runtime is unavailable");
|
|
123
142
|
}
|
|
124
143
|
function createMcpHttpHandler(runtime, input) {
|
|
125
144
|
const transports = new Map();
|
|
126
145
|
const webAppSessions = new auth_1.WebAppSessionRegistry();
|
|
146
|
+
const liveWsServer = new WebSocketServer({ noServer: true });
|
|
127
147
|
const webAppBasePath = runtime.config.webapp.basePath.replace(/\/+$/u, "") || "/webapp";
|
|
128
148
|
const rootPrefix = normalizeBasePath(process.env.ROOT_PREFIX || "/api");
|
|
129
149
|
const publicWebAppBasePath = rootPrefix === "/"
|
|
130
150
|
? webAppBasePath
|
|
131
151
|
: `${rootPrefix}${normalizeBasePath(webAppBasePath)}`;
|
|
152
|
+
const publicLiveWsPath = rootPrefix === "/" ? "/gateway/live/ws" : `${rootPrefix}/gateway/live/ws`;
|
|
132
153
|
const webAppLivePrefix = `${webAppBasePath}/live/`;
|
|
154
|
+
const telegramWebhookPath = runtime.config.telegram.webhook.path.replace(/\/+$/u, "") ||
|
|
155
|
+
"/telegram/webhook";
|
|
133
156
|
const closeSessionEntry = async (entry) => {
|
|
134
157
|
await entry.close();
|
|
135
158
|
};
|
|
159
|
+
const resolveAuthorizedWebAppSession = async (token) => {
|
|
160
|
+
const webAppSession = token ? webAppSessions.get(token) : null;
|
|
161
|
+
if (!webAppSession) {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
const relayTarget = (0, relay_1.parseLiveRelaySessionId)(webAppSession.sessionId);
|
|
165
|
+
if (relayTarget) {
|
|
166
|
+
return {
|
|
167
|
+
webAppSession,
|
|
168
|
+
relayTarget,
|
|
169
|
+
session: null,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
const binding = await runtime.bindingStore.getBinding(webAppSession.sessionId);
|
|
173
|
+
if (!binding || binding.telegramUserId !== webAppSession.telegramUserId) {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
const session = await runtime.sessionStore.getSession(webAppSession.sessionId);
|
|
177
|
+
if (!session?.terminalTarget) {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
webAppSession,
|
|
182
|
+
relayTarget: null,
|
|
183
|
+
session,
|
|
184
|
+
};
|
|
185
|
+
};
|
|
186
|
+
liveWsServer.on("connection", (socket, req) => {
|
|
187
|
+
const requestUrl = new URL(req.url ?? "/", "http://gateway.local");
|
|
188
|
+
const token = requestUrl.searchParams.get("token")?.trim() ?? "";
|
|
189
|
+
void (async () => {
|
|
190
|
+
const resolved = await resolveAuthorizedWebAppSession(token);
|
|
191
|
+
if (!resolved) {
|
|
192
|
+
socket.close(1008, "Unauthorized");
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
let closed = false;
|
|
196
|
+
let relayStreamClose = null;
|
|
197
|
+
let localUnsubscribe = null;
|
|
198
|
+
const cleanup = async () => {
|
|
199
|
+
if (closed) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
closed = true;
|
|
203
|
+
try {
|
|
204
|
+
localUnsubscribe?.();
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
// ignore cleanup errors during socket shutdown
|
|
208
|
+
}
|
|
209
|
+
localUnsubscribe = null;
|
|
210
|
+
if (relayStreamClose) {
|
|
211
|
+
await relayStreamClose().catch(() => undefined);
|
|
212
|
+
relayStreamClose = null;
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
const sendJson = (payload) => {
|
|
216
|
+
if (socket.readyState === 1) {
|
|
217
|
+
socket.send(JSON.stringify(payload));
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
socket.on("close", () => {
|
|
221
|
+
void cleanup();
|
|
222
|
+
});
|
|
223
|
+
socket.on("message", (raw) => {
|
|
224
|
+
void (async () => {
|
|
225
|
+
const parsed = raw && typeof raw === "string"
|
|
226
|
+
? JSON.parse(raw)
|
|
227
|
+
: JSON.parse(String(raw));
|
|
228
|
+
const type = parsed && typeof parsed === "object" && typeof parsed.type === "string"
|
|
229
|
+
? parsed.type
|
|
230
|
+
: "";
|
|
231
|
+
if (type === "input") {
|
|
232
|
+
const data = typeof parsed.data === "string" ? parsed.data : "";
|
|
233
|
+
if (!data) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
if (resolved.relayTarget) {
|
|
237
|
+
const gatewaySocketService = input.getGatewaySocketService?.();
|
|
238
|
+
await gatewaySocketService?.requestLiveRelay?.({
|
|
239
|
+
clientUuid: resolved.relayTarget.clientUuid,
|
|
240
|
+
localSessionId: resolved.relayTarget.localSessionId,
|
|
241
|
+
requestType: "action",
|
|
242
|
+
payload: {
|
|
243
|
+
action: "text",
|
|
244
|
+
text: data,
|
|
245
|
+
},
|
|
246
|
+
});
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
if (resolved.session?.terminalTarget && (0, client_1.isStreamableTerminalTarget)(resolved.session.terminalTarget)) {
|
|
250
|
+
(0, client_1.sendForegroundTerminalInput)(resolved.session.terminalTarget, data);
|
|
251
|
+
}
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if (type === "action") {
|
|
255
|
+
const action = typeof parsed.action === "string" ? parsed.action : "";
|
|
256
|
+
if (![
|
|
257
|
+
"up",
|
|
258
|
+
"down",
|
|
259
|
+
"enter",
|
|
260
|
+
"slash",
|
|
261
|
+
"delete",
|
|
262
|
+
"tab",
|
|
263
|
+
"escape",
|
|
264
|
+
"interrupt",
|
|
265
|
+
].includes(action)) {
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
if (resolved.relayTarget) {
|
|
269
|
+
const gatewaySocketService = input.getGatewaySocketService?.();
|
|
270
|
+
await gatewaySocketService?.requestLiveRelay?.({
|
|
271
|
+
clientUuid: resolved.relayTarget.clientUuid,
|
|
272
|
+
localSessionId: resolved.relayTarget.localSessionId,
|
|
273
|
+
requestType: "action",
|
|
274
|
+
payload: { action },
|
|
275
|
+
});
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
if (resolved.session?.terminalTarget) {
|
|
279
|
+
await (0, terminal_1.sendAllowedTerminalAction)(runtime.config.terminal, resolved.session.terminalTarget, action);
|
|
280
|
+
}
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
if (type === "resize") {
|
|
284
|
+
const cols = typeof parsed.cols === "number" ? parsed.cols : NaN;
|
|
285
|
+
const rows = typeof parsed.rows === "number" ? parsed.rows : NaN;
|
|
286
|
+
if (!Number.isFinite(cols) || !Number.isFinite(rows)) {
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
if (resolved.session?.terminalTarget && (0, client_1.isStreamableTerminalTarget)(resolved.session.terminalTarget)) {
|
|
290
|
+
(0, client_1.resizeForegroundTerminal)(resolved.session.terminalTarget, Math.max(20, Math.min(400, Math.round(cols))), Math.max(5, Math.min(200, Math.round(rows))));
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
})().catch((error) => {
|
|
294
|
+
runtime.logger.warn("Telegram WebApp live WS message handling failed", {
|
|
295
|
+
error: error instanceof Error ? (error.stack ?? error.message) : String(error),
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
if (resolved.relayTarget) {
|
|
300
|
+
const gatewaySocketService = input.getGatewaySocketService?.();
|
|
301
|
+
if (!gatewaySocketService?.openLiveRelayStream) {
|
|
302
|
+
socket.close(1011, "Relay live stream is unavailable");
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
const relayStream = await gatewaySocketService.openLiveRelayStream({
|
|
306
|
+
clientUuid: resolved.relayTarget.clientUuid,
|
|
307
|
+
localSessionId: resolved.relayTarget.localSessionId,
|
|
308
|
+
onEvent: (event) => {
|
|
309
|
+
sendJson({
|
|
310
|
+
type: event.event,
|
|
311
|
+
...event.payload,
|
|
312
|
+
});
|
|
313
|
+
},
|
|
314
|
+
});
|
|
315
|
+
relayStreamClose = relayStream.close;
|
|
316
|
+
sendJson({ type: "ready", mode: "stream" });
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
if (!resolved.session?.terminalTarget ||
|
|
320
|
+
!(0, client_1.isStreamableTerminalTarget)(resolved.session.terminalTarget)) {
|
|
321
|
+
socket.close(1011, "Local live stream is not supported for this terminal");
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
const terminalSize = await (0, terminal_1.getTerminalWindowSize)(runtime.config.terminal, resolved.session.terminalTarget);
|
|
325
|
+
const content = await (0, terminal_1.captureVisibleTerminal)(runtime.config.terminal, resolved.session.terminalTarget, runtime.config.terminal.captureLines, runtime.config.webapp.visibleScreens);
|
|
326
|
+
const ansi = await (0, terminal_1.captureVisibleTerminalAnsi)(runtime.config.terminal, resolved.session.terminalTarget, runtime.config.terminal.captureLines, runtime.config.webapp.visibleScreens);
|
|
327
|
+
sendJson({
|
|
328
|
+
type: "snapshot",
|
|
329
|
+
session_id: resolved.session.sessionId,
|
|
330
|
+
session_label: resolved.session.label ?? null,
|
|
331
|
+
captured_at: new Date().toISOString(),
|
|
332
|
+
content,
|
|
333
|
+
ansi,
|
|
334
|
+
...(terminalSize ? terminalSize : {}),
|
|
335
|
+
});
|
|
336
|
+
localUnsubscribe = (0, client_1.subscribeForegroundTerminal)(resolved.session.terminalTarget, {
|
|
337
|
+
onData: (data) => {
|
|
338
|
+
sendJson({
|
|
339
|
+
type: "data",
|
|
340
|
+
data,
|
|
341
|
+
});
|
|
342
|
+
},
|
|
343
|
+
onExit: (info) => {
|
|
344
|
+
sendJson({
|
|
345
|
+
type: "exit",
|
|
346
|
+
exitCode: typeof info.exitCode === "number" ? info.exitCode : null,
|
|
347
|
+
signal: typeof info.signal === "number" ? info.signal : null,
|
|
348
|
+
});
|
|
349
|
+
},
|
|
350
|
+
});
|
|
351
|
+
sendJson({ type: "ready", mode: "stream" });
|
|
352
|
+
})().catch((error) => {
|
|
353
|
+
runtime.logger.warn("Telegram WebApp live WS bootstrap failed", {
|
|
354
|
+
error: error instanceof Error ? (error.stack ?? error.message) : String(error),
|
|
355
|
+
});
|
|
356
|
+
socket.close(1011, "Live stream bootstrap failed");
|
|
357
|
+
});
|
|
358
|
+
});
|
|
136
359
|
const handleRequest = async (req, res, pathname) => {
|
|
137
360
|
const method = req.method ?? "GET";
|
|
138
361
|
const normalizedPathname = normalizePrefixedPathname(pathname);
|
|
@@ -146,6 +369,49 @@ function createMcpHttpHandler(runtime, input) {
|
|
|
146
369
|
});
|
|
147
370
|
return;
|
|
148
371
|
}
|
|
372
|
+
if (runtime.config.telegram.webhook.enabled &&
|
|
373
|
+
requestUrl.pathname === telegramWebhookPath) {
|
|
374
|
+
if (method !== "POST") {
|
|
375
|
+
writeText(res, 405, "Method not allowed");
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
const expectedSecret = runtime.config.telegram.webhook.secret?.trim();
|
|
379
|
+
const receivedSecret = readWebhookSecretHeader(req)?.trim();
|
|
380
|
+
if (!expectedSecret || receivedSecret !== expectedSecret) {
|
|
381
|
+
writeText(res, 401, "Unauthorized");
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
const body = await readJsonBody(req);
|
|
385
|
+
if (!body || typeof body !== "object") {
|
|
386
|
+
writeText(res, 400, "Telegram update body is required");
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
if (runtime.config.telegram.webhook.trace) {
|
|
390
|
+
runtime.logger.warn("Telegram webhook update received", {
|
|
391
|
+
path: requestUrl.pathname,
|
|
392
|
+
body,
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
runtime.logger.info("Telegram webhook update received", {
|
|
397
|
+
path: requestUrl.pathname,
|
|
398
|
+
method,
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
try {
|
|
402
|
+
await runtime.telegramTransport.handleWebhookUpdate(body);
|
|
403
|
+
writeText(res, 200, "OK");
|
|
404
|
+
}
|
|
405
|
+
catch (error) {
|
|
406
|
+
runtime.logger.error("Telegram webhook update handling failed", {
|
|
407
|
+
error: error instanceof Error
|
|
408
|
+
? (error.stack ?? error.message)
|
|
409
|
+
: String(error),
|
|
410
|
+
});
|
|
411
|
+
writeText(res, 500, error instanceof Error ? error.message : "Webhook handling failed");
|
|
412
|
+
}
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
149
415
|
if (await runtime.gatewayHttpService.handleRequest(req, res, requestUrl.pathname)) {
|
|
150
416
|
return;
|
|
151
417
|
}
|
|
@@ -161,6 +427,7 @@ function createMcpHttpHandler(runtime, input) {
|
|
|
161
427
|
runtime.config.webapp.launchMode;
|
|
162
428
|
writeHtml(res, 200, (0, assets_1.renderWebAppHtml)({
|
|
163
429
|
basePath: publicWebAppBasePath,
|
|
430
|
+
liveWsPath: publicLiveWsPath,
|
|
164
431
|
launchMode,
|
|
165
432
|
}));
|
|
166
433
|
return;
|
|
@@ -215,6 +482,7 @@ function createMcpHttpHandler(runtime, input) {
|
|
|
215
482
|
if (relayTarget) {
|
|
216
483
|
try {
|
|
217
484
|
let trustedTelegramUserId = null;
|
|
485
|
+
let launchRecord = null;
|
|
218
486
|
if (relayTarget.sourceClientUuid &&
|
|
219
487
|
relayTarget.sourceClientUuid !== relayTarget.clientUuid) {
|
|
220
488
|
const validation = await runtime.gatewayHttpService.requestLiveRelayBootstrapValidation({
|
|
@@ -226,9 +494,9 @@ function createMcpHttpHandler(runtime, input) {
|
|
|
226
494
|
}
|
|
227
495
|
else {
|
|
228
496
|
try {
|
|
229
|
-
const validated = (0, auth_1.validateTelegramWebAppInitData)(initDataRaw, initDataUnsafe, runtime
|
|
497
|
+
const validated = (0, auth_1.validateTelegramWebAppInitData)(initDataRaw, initDataUnsafe, requireTelegramBotToken(runtime, "validate local Telegram WebApp bootstrap"), runtime.config.webapp.initDataTtlSeconds);
|
|
230
498
|
trustedTelegramUserId = validated.user.id;
|
|
231
|
-
runtime.webAppLaunchRegistry.
|
|
499
|
+
launchRecord = runtime.webAppLaunchRegistry.getByUserId(validated.user.id);
|
|
232
500
|
}
|
|
233
501
|
catch {
|
|
234
502
|
trustedTelegramUserId = null;
|
|
@@ -240,22 +508,51 @@ function createMcpHttpHandler(runtime, input) {
|
|
|
240
508
|
...(trustedTelegramUserId !== null
|
|
241
509
|
? { telegramUserId: trustedTelegramUserId }
|
|
242
510
|
: {}),
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
511
|
+
// Relay sessions are already gateway-bound to a Telegram principal.
|
|
512
|
+
// Do not rely on the per-user launch registry here because it can be
|
|
513
|
+
// overwritten by other menu interactions before the WebApp opens.
|
|
514
|
+
allowForeignBinding: true,
|
|
247
515
|
initDataRaw,
|
|
248
516
|
initDataUnsafe,
|
|
249
517
|
});
|
|
518
|
+
runtime.logger.info("Telegram WebApp relay bootstrap forwarded", {
|
|
519
|
+
sessionId,
|
|
520
|
+
clientUuid: relayTarget.clientUuid,
|
|
521
|
+
localSessionId: relayTarget.localSessionId,
|
|
522
|
+
trustedTelegramUserId,
|
|
523
|
+
hasLaunchRecord: launchRecord !== null,
|
|
524
|
+
launchRecordAllowForeignBinding: launchRecord?.allowForeignBinding === true,
|
|
525
|
+
});
|
|
250
526
|
const record = webAppSessions.create(sessionId, relayBootstrap.telegram_user_id, runtime.config.webapp.sessionTtlSeconds);
|
|
251
527
|
writeJson(res, 200, {
|
|
252
528
|
token: record.token,
|
|
253
529
|
session_id: relayBootstrap.session_id,
|
|
254
530
|
session_label: relayBootstrap.session_label,
|
|
255
|
-
|
|
531
|
+
terminal_target: relayBootstrap.terminal_target,
|
|
256
532
|
poll_interval_ms: relayBootstrap.poll_interval_ms,
|
|
257
533
|
expires_at: new Date(record.expiresAtMs).toISOString(),
|
|
258
534
|
});
|
|
535
|
+
if (trustedTelegramUserId !== null) {
|
|
536
|
+
runtime.webAppLaunchRegistry.deleteByUserId(trustedTelegramUserId);
|
|
537
|
+
}
|
|
538
|
+
if (launchRecord?.telegramChatId !== undefined &&
|
|
539
|
+
launchRecord?.telegramMessageId !== undefined) {
|
|
540
|
+
void runtime.telegramTransport
|
|
541
|
+
.deleteMessage(launchRecord.telegramChatId, launchRecord.telegramMessageId)
|
|
542
|
+
.catch((deleteError) => {
|
|
543
|
+
runtime.logger.warn("Telegram WebApp relay launcher message deletion failed", {
|
|
544
|
+
sessionId,
|
|
545
|
+
clientUuid: relayTarget.clientUuid,
|
|
546
|
+
localSessionId: relayTarget.localSessionId,
|
|
547
|
+
telegramUserId: trustedTelegramUserId,
|
|
548
|
+
telegramChatId: launchRecord.telegramChatId,
|
|
549
|
+
telegramMessageId: launchRecord.telegramMessageId,
|
|
550
|
+
error: deleteError instanceof Error
|
|
551
|
+
? (deleteError.stack ?? deleteError.message)
|
|
552
|
+
: String(deleteError),
|
|
553
|
+
});
|
|
554
|
+
});
|
|
555
|
+
}
|
|
259
556
|
}
|
|
260
557
|
catch (error) {
|
|
261
558
|
runtime.logger.warn("Telegram WebApp relay bootstrap rejected", {
|
|
@@ -271,7 +568,7 @@ function createMcpHttpHandler(runtime, input) {
|
|
|
271
568
|
return;
|
|
272
569
|
}
|
|
273
570
|
try {
|
|
274
|
-
const validated = (0, auth_1.validateTelegramWebAppInitData)(initDataRaw, initDataUnsafe, runtime
|
|
571
|
+
const validated = (0, auth_1.validateTelegramWebAppInitData)(initDataRaw, initDataUnsafe, requireTelegramBotToken(runtime, "validate Telegram WebApp bootstrap"), runtime.config.webapp.initDataTtlSeconds);
|
|
275
572
|
runtime.logger.info("Telegram WebApp initData validation debug", {
|
|
276
573
|
sessionId: sessionId || null,
|
|
277
574
|
telegramUserId: validated.user.id,
|
|
@@ -310,14 +607,14 @@ function createMcpHttpHandler(runtime, input) {
|
|
|
310
607
|
runtime.logger.info("Telegram WebApp session bootstrapped", {
|
|
311
608
|
sessionId,
|
|
312
609
|
telegramUserId: validated.user.id,
|
|
313
|
-
|
|
610
|
+
hasTerminalTarget: Boolean(session?.terminalTarget),
|
|
314
611
|
});
|
|
315
612
|
runtime.webAppLaunchRegistry.deleteByUserId(validated.user.id);
|
|
316
613
|
writeJson(res, 200, {
|
|
317
614
|
token: record.token,
|
|
318
615
|
session_id: sessionId,
|
|
319
616
|
session_label: session?.label ?? null,
|
|
320
|
-
|
|
617
|
+
terminal_target: Boolean(session?.terminalTarget),
|
|
321
618
|
poll_interval_ms: runtime.config.webapp.pollIntervalMs,
|
|
322
619
|
expires_at: new Date(record.expiresAtMs).toISOString(),
|
|
323
620
|
});
|
|
@@ -383,7 +680,7 @@ function createMcpHttpHandler(runtime, input) {
|
|
|
383
680
|
? (error.stack ?? error.message)
|
|
384
681
|
: String(error),
|
|
385
682
|
});
|
|
386
|
-
writeText(res,
|
|
683
|
+
writeText(res, isRelayTerminalUnavailableMessage(error) ? 503 : 500, error instanceof Error ? error.message : "Failed to capture relay terminal buffer");
|
|
387
684
|
}
|
|
388
685
|
return;
|
|
389
686
|
}
|
|
@@ -394,17 +691,21 @@ function createMcpHttpHandler(runtime, input) {
|
|
|
394
691
|
return;
|
|
395
692
|
}
|
|
396
693
|
const session = await runtime.sessionStore.getSession(webAppSession.sessionId);
|
|
397
|
-
if (!session?.
|
|
398
|
-
writeText(res, 409, "
|
|
694
|
+
if (!session?.terminalTarget) {
|
|
695
|
+
writeText(res, 409, "terminal target is not configured for this session");
|
|
399
696
|
return;
|
|
400
697
|
}
|
|
401
698
|
try {
|
|
402
|
-
const
|
|
699
|
+
const terminalSize = await (0, terminal_1.getTerminalWindowSize)(runtime.config.terminal, session.terminalTarget);
|
|
700
|
+
const content = await (0, terminal_1.captureVisibleTerminal)(runtime.config.terminal, session.terminalTarget, runtime.config.terminal.captureLines, runtime.config.webapp.visibleScreens);
|
|
701
|
+
const ansi = await (0, terminal_1.captureVisibleTerminalAnsi)(runtime.config.terminal, session.terminalTarget, runtime.config.terminal.captureLines, runtime.config.webapp.visibleScreens);
|
|
403
702
|
writeJson(res, 200, {
|
|
404
703
|
session_id: session.sessionId,
|
|
405
704
|
session_label: session.label ?? null,
|
|
406
705
|
captured_at: new Date().toISOString(),
|
|
407
706
|
content,
|
|
707
|
+
ansi,
|
|
708
|
+
...(terminalSize ? terminalSize : {}),
|
|
408
709
|
});
|
|
409
710
|
}
|
|
410
711
|
catch (error) {
|
|
@@ -414,7 +715,7 @@ function createMcpHttpHandler(runtime, input) {
|
|
|
414
715
|
? (error.stack ?? error.message)
|
|
415
716
|
: String(error),
|
|
416
717
|
});
|
|
417
|
-
writeText(res, (0,
|
|
718
|
+
writeText(res, (0, terminal_1.isTerminalUnavailableError)(error) ? 503 : 500, formatTerminalHttpError(error, "Failed to capture visible terminal buffer"));
|
|
418
719
|
}
|
|
419
720
|
return;
|
|
420
721
|
}
|
|
@@ -478,7 +779,7 @@ function createMcpHttpHandler(runtime, input) {
|
|
|
478
779
|
? (error.stack ?? error.message)
|
|
479
780
|
: String(error),
|
|
480
781
|
});
|
|
481
|
-
writeText(res,
|
|
782
|
+
writeText(res, isRelayTerminalUnavailableMessage(error) ? 503 : 500, error instanceof Error ? error.message : "Failed to send relay terminal action");
|
|
482
783
|
}
|
|
483
784
|
return;
|
|
484
785
|
}
|
|
@@ -489,19 +790,19 @@ function createMcpHttpHandler(runtime, input) {
|
|
|
489
790
|
return;
|
|
490
791
|
}
|
|
491
792
|
const session = await runtime.sessionStore.getSession(webAppSession.sessionId);
|
|
492
|
-
if (!session?.
|
|
493
|
-
writeText(res, 409, "
|
|
793
|
+
if (!session?.terminalTarget) {
|
|
794
|
+
writeText(res, 409, "terminal target is not configured for this session");
|
|
494
795
|
return;
|
|
495
796
|
}
|
|
496
797
|
try {
|
|
497
798
|
if (action === "text") {
|
|
498
|
-
await (0,
|
|
799
|
+
await (0, terminal_1.sendTerminalLiteralText)(runtime.config.terminal, session.terminalTarget, text);
|
|
499
800
|
}
|
|
500
801
|
else {
|
|
501
|
-
await (0,
|
|
802
|
+
await (0, terminal_1.sendAllowedTerminalAction)(runtime.config.terminal, session.terminalTarget, action);
|
|
502
803
|
}
|
|
503
804
|
webAppSessions.touchAction(webAppSession.token, nowMs);
|
|
504
|
-
runtime.logger.info("Telegram WebApp action sent to
|
|
805
|
+
runtime.logger.info("Telegram WebApp action sent to terminal", {
|
|
505
806
|
sessionId: webAppSession.sessionId,
|
|
506
807
|
telegramUserId: webAppSession.telegramUserId,
|
|
507
808
|
action,
|
|
@@ -520,7 +821,7 @@ function createMcpHttpHandler(runtime, input) {
|
|
|
520
821
|
? (error.stack ?? error.message)
|
|
521
822
|
: String(error),
|
|
522
823
|
});
|
|
523
|
-
writeText(res, (0,
|
|
824
|
+
writeText(res, (0, terminal_1.isTerminalUnavailableError)(error) ? 503 : 500, formatTerminalHttpError(error, "Failed to send terminal action"));
|
|
524
825
|
}
|
|
525
826
|
return;
|
|
526
827
|
}
|
|
@@ -548,12 +849,10 @@ function createMcpHttpHandler(runtime, input) {
|
|
|
548
849
|
.sort((left, right) => left.sessionId.localeCompare(right.sessionId))
|
|
549
850
|
.map(async (session) => {
|
|
550
851
|
const binding = await runtime.bindingStore.getBinding(session.sessionId);
|
|
551
|
-
const inboxCount = await runtime.inboxStore.countInboxMessages(session.sessionId);
|
|
552
852
|
return {
|
|
553
853
|
session_id: session.sessionId,
|
|
554
854
|
session_label: session.label ?? null,
|
|
555
855
|
updated_at: session.updatedAt,
|
|
556
|
-
inbox_count: inboxCount,
|
|
557
856
|
binding: binding
|
|
558
857
|
? {
|
|
559
858
|
telegram_chat_id: binding.telegramChatId,
|
|
@@ -561,18 +860,9 @@ function createMcpHttpHandler(runtime, input) {
|
|
|
561
860
|
linked_at: binding.linkedAt,
|
|
562
861
|
}
|
|
563
862
|
: null,
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
tmux_window_index: typeof session.tmuxWindowIndex === "number"
|
|
568
|
-
? session.tmuxWindowIndex
|
|
569
|
-
: null,
|
|
570
|
-
tmux_pane_id: session.tmuxPaneId ?? null,
|
|
571
|
-
tmux_pane_index: typeof session.tmuxPaneIndex === "number"
|
|
572
|
-
? session.tmuxPaneIndex
|
|
573
|
-
: null,
|
|
574
|
-
tmux_target: session.tmuxTarget ?? null,
|
|
575
|
-
last_nudge_at: session.lastTmuxNudgeAt ?? null,
|
|
863
|
+
terminal: {
|
|
864
|
+
terminal_target: session.terminalTarget ?? null,
|
|
865
|
+
last_nudge_at: session.lastTerminalNudgeAt ?? null,
|
|
576
866
|
},
|
|
577
867
|
};
|
|
578
868
|
}));
|
|
@@ -601,13 +891,33 @@ function createMcpHttpHandler(runtime, input) {
|
|
|
601
891
|
return;
|
|
602
892
|
}
|
|
603
893
|
const result = await runtime.maintenanceStore.pruneAll();
|
|
894
|
+
let gatewayDeleted = null;
|
|
895
|
+
if (runtime.config.distributed.mode === "gateway" ||
|
|
896
|
+
runtime.config.distributed.mode === "both") {
|
|
897
|
+
try {
|
|
898
|
+
const gatewayResult = await runtime.callBroker("telegramMcp.gateway.pruneGatewayState", {}, {
|
|
899
|
+
meta: { internal_call: true },
|
|
900
|
+
});
|
|
901
|
+
gatewayDeleted =
|
|
902
|
+
gatewayResult?.deleted && typeof gatewayResult.deleted === "object"
|
|
903
|
+
? gatewayResult.deleted
|
|
904
|
+
: null;
|
|
905
|
+
}
|
|
906
|
+
catch (error) {
|
|
907
|
+
runtime.logger.warn("Gateway DB prune failed through HTTP endpoint", {
|
|
908
|
+
error: error instanceof Error ? error.message : String(error),
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
}
|
|
604
912
|
runtime.logger.warn("MCP service state pruned through HTTP endpoint", {
|
|
605
913
|
deletedKeys: result.deletedKeys,
|
|
914
|
+
gatewayDeleted,
|
|
606
915
|
remoteAddress: req.socket.remoteAddress,
|
|
607
916
|
});
|
|
608
917
|
writeJson(res, 200, {
|
|
609
918
|
ok: true,
|
|
610
919
|
deleted_keys: result.deletedKeys,
|
|
920
|
+
...(gatewayDeleted ? { gateway_deleted: gatewayDeleted } : {}),
|
|
611
921
|
});
|
|
612
922
|
return;
|
|
613
923
|
}
|
|
@@ -781,6 +1091,17 @@ function createMcpHttpHandler(runtime, input) {
|
|
|
781
1091
|
}
|
|
782
1092
|
};
|
|
783
1093
|
let shuttingDown = false;
|
|
1094
|
+
const handleUpgrade = async (req, socket, head, pathname) => {
|
|
1095
|
+
const normalizedPathname = normalizePrefixedPathname(pathname);
|
|
1096
|
+
if (normalizedPathname !== `${webAppBasePath}/api/live/ws` &&
|
|
1097
|
+
normalizedPathname !== "/gateway/live/ws") {
|
|
1098
|
+
return false;
|
|
1099
|
+
}
|
|
1100
|
+
liveWsServer.handleUpgrade(req, socket, head, (clientSocket) => {
|
|
1101
|
+
liveWsServer.emit("connection", clientSocket, req);
|
|
1102
|
+
});
|
|
1103
|
+
return true;
|
|
1104
|
+
};
|
|
784
1105
|
const shutdown = async () => {
|
|
785
1106
|
if (shuttingDown) {
|
|
786
1107
|
return;
|
|
@@ -789,9 +1110,21 @@ function createMcpHttpHandler(runtime, input) {
|
|
|
789
1110
|
runtime.logger.info("MCP HTTP handler shutdown requested");
|
|
790
1111
|
await Promise.all(Array.from(transports.values()).map((entry) => closeSessionEntry(entry)));
|
|
791
1112
|
transports.clear();
|
|
1113
|
+
await new Promise((resolve, reject) => {
|
|
1114
|
+
liveWsServer.close((error) => {
|
|
1115
|
+
if (error) {
|
|
1116
|
+
reject(error);
|
|
1117
|
+
return;
|
|
1118
|
+
}
|
|
1119
|
+
resolve();
|
|
1120
|
+
});
|
|
1121
|
+
});
|
|
792
1122
|
};
|
|
793
1123
|
return {
|
|
794
1124
|
handleRequest,
|
|
1125
|
+
handleUpgrade,
|
|
795
1126
|
close: shutdown,
|
|
796
1127
|
};
|
|
797
1128
|
}
|
|
1129
|
+
const wsLib = ws_1.default;
|
|
1130
|
+
const WebSocketServer = wsLib.WebSocketServer;
|