@deadragdoll/tellymcp 0.0.10 → 0.0.12
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 -52
- package/.env.example.gateway +48 -62
- package/CHANGELOG.md +3 -3
- package/README-ru.md +226 -376
- package/README.md +213 -1184
- package/TOOLS.md +320 -377
- package/VERSION.md +13 -13
- 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 +39 -20
- package/config/templates/env.client.template +34 -19
- package/config/templates/env.gateway.template +37 -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/browser.service.js +94 -1
- package/dist/services/features/telegram-mcp/collaboration.service.js +40 -3
- 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-socket.service.js +907 -85
- package/dist/services/features/telegram-mcp/gateway.service.js +876 -81
- package/dist/services/features/telegram-mcp/mcp-http.service.js +8 -0
- package/dist/services/features/telegram-mcp/mcp-server.service.js +17 -26
- package/dist/services/features/telegram-mcp/notify.service.js +127 -1
- package/dist/services/features/telegram-mcp/session-context.service.js +28 -1
- package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +132 -10
- package/dist/services/features/telegram-mcp/src/app/config/env.js +158 -52
- 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 +120 -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/browserOpenTool.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 +306 -26
- 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 +697 -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/resources/en.js +143 -42
- package/dist/services/features/telegram-mcp/src/shared/i18n/resources/ru.js +139 -38
- 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 +69 -70
- 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 +444 -7093
- 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 +149 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConstructorWiring.js +642 -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 +65 -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 +108 -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 +665 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalRuntime.js +226 -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 +409 -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 +12 -0
- 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 +15 -1
- 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 +10 -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
|
@@ -4,6 +4,8 @@ exports.GatewayHttpService = void 0;
|
|
|
4
4
|
const node_fs_1 = require("node:fs");
|
|
5
5
|
const node_path_1 = require("node:path");
|
|
6
6
|
const schema_1 = require("../../../entities/request/model/schema");
|
|
7
|
+
const relay_1 = require("../../../app/webapp/relay");
|
|
8
|
+
const versionHandshake_1 = require("../../../shared/lib/version/versionHandshake");
|
|
7
9
|
function readHeader(req, headerName) {
|
|
8
10
|
const value = req.headers[headerName];
|
|
9
11
|
return Array.isArray(value) ? value[0] : value;
|
|
@@ -18,6 +20,28 @@ function writeText(res, statusCode, message) {
|
|
|
18
20
|
res.setHeader("content-type", "text/plain; charset=utf-8");
|
|
19
21
|
res.end(message);
|
|
20
22
|
}
|
|
23
|
+
function isBackendErrorLike(value) {
|
|
24
|
+
return Boolean(value &&
|
|
25
|
+
typeof value === "object" &&
|
|
26
|
+
typeof value.statusCode === "number" &&
|
|
27
|
+
typeof value.code === "string");
|
|
28
|
+
}
|
|
29
|
+
function parseCanonicalGatewaySessionId(value) {
|
|
30
|
+
const trimmed = value?.trim();
|
|
31
|
+
if (!trimmed) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
const separatorIndex = trimmed.indexOf(":");
|
|
35
|
+
if (separatorIndex <= 0 || separatorIndex === trimmed.length - 1) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
const clientUuid = trimmed.slice(0, separatorIndex).trim();
|
|
39
|
+
const localSessionId = trimmed.slice(separatorIndex + 1).trim();
|
|
40
|
+
if (!clientUuid || !localSessionId) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
return { clientUuid, localSessionId };
|
|
44
|
+
}
|
|
21
45
|
function unwrapLiveRelayResult(response) {
|
|
22
46
|
if (!response || typeof response !== "object") {
|
|
23
47
|
return null;
|
|
@@ -48,50 +72,20 @@ function normalizeLiveRelayBootstrapResult(response) {
|
|
|
48
72
|
return {
|
|
49
73
|
session_id: sessionId,
|
|
50
74
|
session_label: typeof record.session_label === "string" ? record.session_label : null,
|
|
51
|
-
|
|
75
|
+
terminal_target: record.terminal_target === true,
|
|
52
76
|
poll_interval_ms: typeof record.poll_interval_ms === "number" && record.poll_interval_ms > 0
|
|
53
77
|
? record.poll_interval_ms
|
|
54
78
|
: 2000,
|
|
55
79
|
telegram_user_id: telegramUserId,
|
|
56
80
|
};
|
|
57
81
|
}
|
|
58
|
-
function
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
: input.session_id ?? "unknown-session",
|
|
66
|
-
partner_session_id: typeof outputRecord.partner_session_id === "string"
|
|
67
|
-
? outputRecord.partner_session_id
|
|
68
|
-
: input.target_session_id ?? "unknown-partner-session",
|
|
69
|
-
kind: typeof outputRecord.kind === "string"
|
|
70
|
-
? outputRecord.kind
|
|
71
|
-
: input.kind,
|
|
72
|
-
share_id: typeof outputRecord.share_id === "string"
|
|
73
|
-
? outputRecord.share_id
|
|
74
|
-
: `gateway-${Date.now()}`,
|
|
75
|
-
delivery_status: outputRecord.delivery_status === "delivered" ? "delivered" : "queued",
|
|
76
|
-
note_path: typeof outputRecord.note_path === "string"
|
|
77
|
-
? outputRecord.note_path
|
|
78
|
-
: "gateway://shares/pending.md",
|
|
79
|
-
share_index_path: typeof outputRecord.share_index_path === "string"
|
|
80
|
-
? outputRecord.share_index_path
|
|
81
|
-
: "gateway://SHARED_INDEX.md",
|
|
82
|
-
copied_artifacts: Array.isArray(outputRecord.copied_artifacts)
|
|
83
|
-
? outputRecord.copied_artifacts.filter((item) => typeof item === "string")
|
|
84
|
-
: [
|
|
85
|
-
...(input.artifact_refs?.map((item) => item.original_name ?? item.relative_path ?? item.file_path) ?? []),
|
|
86
|
-
...(input.artifacts ?? []),
|
|
87
|
-
],
|
|
88
|
-
inbox_message_id: typeof outputRecord.inbox_message_id === "string"
|
|
89
|
-
? outputRecord.inbox_message_id
|
|
90
|
-
: `gateway-${Date.now()}`,
|
|
91
|
-
requires_reply: typeof outputRecord.requires_reply === "boolean"
|
|
92
|
-
? outputRecord.requires_reply
|
|
93
|
-
: Boolean(input.requires_reply ?? (input.kind === "question" || input.kind === "request")),
|
|
94
|
-
};
|
|
82
|
+
function slugifyGatewayFilenamePart(value) {
|
|
83
|
+
return value
|
|
84
|
+
.trim()
|
|
85
|
+
.toLowerCase()
|
|
86
|
+
.replace(/[^a-z0-9._-]+/gu, "-")
|
|
87
|
+
.replace(/-+/gu, "-")
|
|
88
|
+
.replace(/^-|-$/gu, "");
|
|
95
89
|
}
|
|
96
90
|
class GatewayHttpService {
|
|
97
91
|
config;
|
|
@@ -207,6 +201,27 @@ class GatewayHttpService {
|
|
|
207
201
|
}
|
|
208
202
|
return fallback;
|
|
209
203
|
}
|
|
204
|
+
async resolveConnectedConsoleTarget(sessionId) {
|
|
205
|
+
const relayTarget = (0, relay_1.parseLiveRelaySessionId)(sessionId);
|
|
206
|
+
if (relayTarget) {
|
|
207
|
+
return {
|
|
208
|
+
clientUuid: relayTarget.clientUuid,
|
|
209
|
+
localSessionId: relayTarget.localSessionId,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
const trimmedSessionId = sessionId.trim();
|
|
213
|
+
if (!trimmedSessionId) {
|
|
214
|
+
throw new Error("relay or canonical session_id is required");
|
|
215
|
+
}
|
|
216
|
+
const resolved = await this.callBroker("telegramMcp.gatewaySocket.resolveConnectedSessionTarget", { sessionId: trimmedSessionId }, { meta: { internal_call: true } });
|
|
217
|
+
if (!resolved) {
|
|
218
|
+
throw new Error(`Could not resolve live console target for session_id '${trimmedSessionId}'.`);
|
|
219
|
+
}
|
|
220
|
+
return {
|
|
221
|
+
clientUuid: resolved.client_uuid,
|
|
222
|
+
localSessionId: resolved.local_session_id,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
210
225
|
async readJsonBody(req) {
|
|
211
226
|
const knownBody = req.body;
|
|
212
227
|
if (knownBody !== undefined) {
|
|
@@ -258,7 +273,11 @@ class GatewayHttpService {
|
|
|
258
273
|
return true;
|
|
259
274
|
}
|
|
260
275
|
try {
|
|
261
|
-
const
|
|
276
|
+
const packageRoot = (0, versionHandshake_1.getTellyMcpPackageRoot)(__dirname);
|
|
277
|
+
if (!packageRoot) {
|
|
278
|
+
throw new Error("Could not resolve installed package root for TOOLS.md.");
|
|
279
|
+
}
|
|
280
|
+
const toolsPath = (0, node_path_1.join)(packageRoot, "TOOLS.md");
|
|
262
281
|
res.statusCode = 200;
|
|
263
282
|
res.setHeader("content-type", "text/markdown; charset=utf-8");
|
|
264
283
|
res.end((0, node_fs_1.readFileSync)(toolsPath, "utf8"));
|
|
@@ -279,16 +298,90 @@ class GatewayHttpService {
|
|
|
279
298
|
try {
|
|
280
299
|
const body = await this.readJsonBody(req);
|
|
281
300
|
const input = schema_1.sendPartnerNoteInputSchema.parse(body);
|
|
282
|
-
const
|
|
301
|
+
const canonicalSource = parseCanonicalGatewaySessionId(input.session_id);
|
|
302
|
+
const relaySource = (0, relay_1.parseLiveRelaySessionId)(input.session_id);
|
|
303
|
+
const resolvedSourceClientUuid = canonicalSource?.clientUuid ||
|
|
304
|
+
relaySource?.clientUuid ||
|
|
305
|
+
(typeof body?.client_uuid === "string"
|
|
306
|
+
? String(body.client_uuid).trim()
|
|
307
|
+
: "");
|
|
308
|
+
const resolvedSourceLocalSessionId = canonicalSource?.localSessionId ||
|
|
309
|
+
relaySource?.localSessionId ||
|
|
310
|
+
input.session_id?.trim() ||
|
|
311
|
+
"";
|
|
312
|
+
const explicitTargetClientUuid = typeof body?.target_client_uuid ===
|
|
313
|
+
"string"
|
|
314
|
+
? String(body.target_client_uuid).trim()
|
|
315
|
+
: "";
|
|
316
|
+
const explicitTargetLocalSessionId = typeof body
|
|
317
|
+
?.target_local_session_id === "string"
|
|
318
|
+
? String(body.target_local_session_id).trim()
|
|
319
|
+
: "";
|
|
320
|
+
const canonicalTarget = parseCanonicalGatewaySessionId(input.target_session_id);
|
|
321
|
+
const resolvedTargetClientUuid = explicitTargetClientUuid || canonicalTarget?.clientUuid || "";
|
|
322
|
+
const resolvedTargetLocalSessionId = explicitTargetLocalSessionId || canonicalTarget?.localSessionId || "";
|
|
323
|
+
const useDirectGatewayDelivery = Boolean(resolvedSourceClientUuid) &&
|
|
324
|
+
Boolean(resolvedSourceLocalSessionId) &&
|
|
325
|
+
Boolean(resolvedTargetClientUuid) &&
|
|
326
|
+
Boolean(resolvedTargetLocalSessionId);
|
|
327
|
+
const useQueuedGatewayDelivery = !useDirectGatewayDelivery &&
|
|
328
|
+
Boolean(resolvedSourceClientUuid) &&
|
|
329
|
+
Boolean(resolvedSourceLocalSessionId) &&
|
|
283
330
|
typeof input.target_session_id === "string" &&
|
|
284
331
|
input.target_session_id.trim().length > 0;
|
|
285
|
-
const output =
|
|
286
|
-
? await this.callBroker("telegramMcp.
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
:
|
|
290
|
-
|
|
291
|
-
|
|
332
|
+
const output = useDirectGatewayDelivery
|
|
333
|
+
? await this.callBroker("telegramMcp.gatewaySocket.sendDirectPartnerNote", {
|
|
334
|
+
clientUuid: resolvedSourceClientUuid,
|
|
335
|
+
localSessionId: resolvedSourceLocalSessionId,
|
|
336
|
+
targetClientUuid: resolvedTargetClientUuid,
|
|
337
|
+
targetLocalSessionId: resolvedTargetLocalSessionId,
|
|
338
|
+
kind: input.kind,
|
|
339
|
+
summary: input.summary,
|
|
340
|
+
message: input.message,
|
|
341
|
+
...(input.expected_reply?.trim()
|
|
342
|
+
? { expectedReply: input.expected_reply.trim() }
|
|
343
|
+
: {}),
|
|
344
|
+
...(typeof input.requires_reply === "boolean"
|
|
345
|
+
? { requiresReply: input.requires_reply }
|
|
346
|
+
: {}),
|
|
347
|
+
...(input.in_reply_to?.trim()
|
|
348
|
+
? { inReplyTo: input.in_reply_to.trim() }
|
|
349
|
+
: {}),
|
|
350
|
+
...(Array.isArray(input.artifact_refs)
|
|
351
|
+
? { artifactRefs: input.artifact_refs }
|
|
352
|
+
: {}),
|
|
353
|
+
}, { meta: { internal_call: true } })
|
|
354
|
+
: useQueuedGatewayDelivery
|
|
355
|
+
? await this.callBroker("telegramMcp.gateway.sendPartnerNote", {
|
|
356
|
+
...body,
|
|
357
|
+
client_uuid: resolvedSourceClientUuid,
|
|
358
|
+
session_id: resolvedSourceLocalSessionId,
|
|
359
|
+
}, { meta: { internal_call: true } })
|
|
360
|
+
: this.partnerNoteRelayHandler
|
|
361
|
+
? await this.partnerNoteRelayHandler(input)
|
|
362
|
+
: (() => {
|
|
363
|
+
throw new Error("Gateway partner relay handler is not configured.");
|
|
364
|
+
})();
|
|
365
|
+
if (isBackendErrorLike(output)) {
|
|
366
|
+
const detail = typeof output.data !== "undefined"
|
|
367
|
+
? (() => {
|
|
368
|
+
try {
|
|
369
|
+
return JSON.stringify(output.data);
|
|
370
|
+
}
|
|
371
|
+
catch {
|
|
372
|
+
return String(output.data);
|
|
373
|
+
}
|
|
374
|
+
})()
|
|
375
|
+
: "";
|
|
376
|
+
throw new Error([
|
|
377
|
+
typeof output.message === "string" && output.message.trim()
|
|
378
|
+
? output.message.trim()
|
|
379
|
+
: `${output.name ?? "BackendError"} (${output.code})`,
|
|
380
|
+
`code=${output.code}`,
|
|
381
|
+
`statusCode=${output.statusCode}`,
|
|
382
|
+
...(detail ? [`data=${detail}`] : []),
|
|
383
|
+
].join("\n"));
|
|
384
|
+
}
|
|
292
385
|
if (useQueuedGatewayDelivery &&
|
|
293
386
|
output &&
|
|
294
387
|
typeof output === "object" &&
|
|
@@ -309,22 +402,22 @@ class GatewayHttpService {
|
|
|
309
402
|
}
|
|
310
403
|
const parsedOutput = schema_1.sendPartnerNoteOutputSchema.safeParse(output);
|
|
311
404
|
if (!parsedOutput.success) {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
}
|
|
320
|
-
const fallback = buildPartnerNoteOutputFallback(input, output);
|
|
321
|
-
writeJson(res, 200, fallback);
|
|
405
|
+
writeJson(res, 500, {
|
|
406
|
+
error: useQueuedGatewayDelivery
|
|
407
|
+
? "Invalid queued gateway partner-note response"
|
|
408
|
+
: "Invalid direct gateway partner-note response",
|
|
409
|
+
details: parsedOutput.error.issues,
|
|
410
|
+
output,
|
|
411
|
+
});
|
|
322
412
|
return true;
|
|
323
413
|
}
|
|
324
414
|
writeJson(res, 200, parsedOutput.data);
|
|
325
415
|
return true;
|
|
326
416
|
}
|
|
327
417
|
catch (error) {
|
|
418
|
+
console.error("Gateway partner-note request failed", {
|
|
419
|
+
error: error instanceof Error ? (error.stack ?? error.message) : String(error),
|
|
420
|
+
});
|
|
328
421
|
writeJson(res, 400, {
|
|
329
422
|
error: error instanceof Error ? error.message : String(error),
|
|
330
423
|
});
|
|
@@ -354,6 +447,111 @@ class GatewayHttpService {
|
|
|
354
447
|
return true;
|
|
355
448
|
}
|
|
356
449
|
catch (error) {
|
|
450
|
+
console.error("Gateway live approval request failed", {
|
|
451
|
+
error: error instanceof Error ? (error.stack ?? error.message) : String(error),
|
|
452
|
+
});
|
|
453
|
+
writeJson(res, 400, {
|
|
454
|
+
error: error instanceof Error ? error.message : String(error),
|
|
455
|
+
});
|
|
456
|
+
return true;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
if (pathname === "/gateway/storage/list") {
|
|
460
|
+
if (req.method !== "POST") {
|
|
461
|
+
writeText(res, 405, "Method not allowed");
|
|
462
|
+
return true;
|
|
463
|
+
}
|
|
464
|
+
try {
|
|
465
|
+
const body = (await this.readJsonBody(req));
|
|
466
|
+
const sessionId = typeof body.session_id === "string" ? body.session_id.trim() : "";
|
|
467
|
+
const source = typeof body.source === "string" ? body.source.trim() : "";
|
|
468
|
+
const target = await this.resolveConnectedConsoleTarget(sessionId);
|
|
469
|
+
const output = await this.callBroker("telegramMcp.gatewaySocket.requestClientAction", {
|
|
470
|
+
clientUuid: target.clientUuid,
|
|
471
|
+
actionName: "telegramMcp.xchange.listFileMetasRemote",
|
|
472
|
+
params: {
|
|
473
|
+
session_id: target.localSessionId,
|
|
474
|
+
...(source ? { source } : {}),
|
|
475
|
+
},
|
|
476
|
+
}, { meta: { internal_call: true } });
|
|
477
|
+
if (isBackendErrorLike(output)) {
|
|
478
|
+
throw new Error(this.extractActionErrorMessage(output, "Storage list failed"));
|
|
479
|
+
}
|
|
480
|
+
writeJson(res, 200, output);
|
|
481
|
+
return true;
|
|
482
|
+
}
|
|
483
|
+
catch (error) {
|
|
484
|
+
console.error("Gateway storage list request failed", {
|
|
485
|
+
error: error instanceof Error ? (error.stack ?? error.message) : String(error),
|
|
486
|
+
});
|
|
487
|
+
writeJson(res, 400, {
|
|
488
|
+
error: error instanceof Error ? error.message : String(error),
|
|
489
|
+
});
|
|
490
|
+
return true;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
if (pathname === "/gateway/storage/meta") {
|
|
494
|
+
if (req.method !== "POST") {
|
|
495
|
+
writeText(res, 405, "Method not allowed");
|
|
496
|
+
return true;
|
|
497
|
+
}
|
|
498
|
+
try {
|
|
499
|
+
const body = (await this.readJsonBody(req));
|
|
500
|
+
const sessionId = typeof body.session_id === "string" ? body.session_id.trim() : "";
|
|
501
|
+
const filePath = typeof body.file_path === "string" ? body.file_path.trim() : "";
|
|
502
|
+
const target = await this.resolveConnectedConsoleTarget(sessionId);
|
|
503
|
+
const output = await this.callBroker("telegramMcp.gatewaySocket.requestClientAction", {
|
|
504
|
+
clientUuid: target.clientUuid,
|
|
505
|
+
actionName: "telegramMcp.xchange.getFileMetaRemote",
|
|
506
|
+
params: {
|
|
507
|
+
session_id: target.localSessionId,
|
|
508
|
+
file_path: filePath,
|
|
509
|
+
},
|
|
510
|
+
}, { meta: { internal_call: true } });
|
|
511
|
+
if (isBackendErrorLike(output)) {
|
|
512
|
+
throw new Error(this.extractActionErrorMessage(output, "Storage meta fetch failed"));
|
|
513
|
+
}
|
|
514
|
+
writeJson(res, 200, output);
|
|
515
|
+
return true;
|
|
516
|
+
}
|
|
517
|
+
catch (error) {
|
|
518
|
+
console.error("Gateway storage meta request failed", {
|
|
519
|
+
error: error instanceof Error ? (error.stack ?? error.message) : String(error),
|
|
520
|
+
});
|
|
521
|
+
writeJson(res, 400, {
|
|
522
|
+
error: error instanceof Error ? error.message : String(error),
|
|
523
|
+
});
|
|
524
|
+
return true;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
if (pathname === "/gateway/storage/delete-meta") {
|
|
528
|
+
if (req.method !== "POST") {
|
|
529
|
+
writeText(res, 405, "Method not allowed");
|
|
530
|
+
return true;
|
|
531
|
+
}
|
|
532
|
+
try {
|
|
533
|
+
const body = (await this.readJsonBody(req));
|
|
534
|
+
const sessionId = typeof body.session_id === "string" ? body.session_id.trim() : "";
|
|
535
|
+
const filePath = typeof body.file_path === "string" ? body.file_path.trim() : "";
|
|
536
|
+
const target = await this.resolveConnectedConsoleTarget(sessionId);
|
|
537
|
+
const output = await this.callBroker("telegramMcp.gatewaySocket.requestClientAction", {
|
|
538
|
+
clientUuid: target.clientUuid,
|
|
539
|
+
actionName: "telegramMcp.xchange.deleteFileMetaRemote",
|
|
540
|
+
params: {
|
|
541
|
+
session_id: target.localSessionId,
|
|
542
|
+
file_path: filePath,
|
|
543
|
+
},
|
|
544
|
+
}, { meta: { internal_call: true } });
|
|
545
|
+
if (isBackendErrorLike(output)) {
|
|
546
|
+
throw new Error(this.extractActionErrorMessage(output, "Storage meta delete failed"));
|
|
547
|
+
}
|
|
548
|
+
writeJson(res, 200, output);
|
|
549
|
+
return true;
|
|
550
|
+
}
|
|
551
|
+
catch (error) {
|
|
552
|
+
console.error("Gateway storage delete-meta request failed", {
|
|
553
|
+
error: error instanceof Error ? (error.stack ?? error.message) : String(error),
|
|
554
|
+
});
|
|
357
555
|
writeJson(res, 400, {
|
|
358
556
|
error: error instanceof Error ? error.message : String(error),
|
|
359
557
|
});
|
|
@@ -384,7 +582,142 @@ class GatewayHttpService {
|
|
|
384
582
|
writeJson(res, 200, { delivered: Boolean(result?.delivered) });
|
|
385
583
|
return true;
|
|
386
584
|
}
|
|
585
|
+
catch (error) {
|
|
586
|
+
console.error("Gateway live approval resolution failed", {
|
|
587
|
+
error: error instanceof Error ? (error.stack ?? error.message) : String(error),
|
|
588
|
+
});
|
|
589
|
+
writeJson(res, 400, {
|
|
590
|
+
error: error instanceof Error ? error.message : String(error),
|
|
591
|
+
});
|
|
592
|
+
return true;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
if (pathname === "/gateway/live/capture-buffer") {
|
|
596
|
+
if (req.method !== "POST") {
|
|
597
|
+
writeText(res, 405, "Method not allowed");
|
|
598
|
+
return true;
|
|
599
|
+
}
|
|
600
|
+
try {
|
|
601
|
+
const body = (await this.readJsonBody(req));
|
|
602
|
+
const sessionId = typeof body.session_id === "string" ? body.session_id.trim() : "";
|
|
603
|
+
const relayTarget = (0, relay_1.parseLiveRelaySessionId)(sessionId);
|
|
604
|
+
const scope = body.scope && typeof body.scope === "object"
|
|
605
|
+
? body.scope
|
|
606
|
+
: null;
|
|
607
|
+
if (!relayTarget || !scope) {
|
|
608
|
+
writeJson(res, 400, {
|
|
609
|
+
error: "relay session_id and scope are required",
|
|
610
|
+
});
|
|
611
|
+
return true;
|
|
612
|
+
}
|
|
613
|
+
if (scope.mode === "visible") {
|
|
614
|
+
const rawResponse = await this.callBroker("telegramMcp.gatewaySocket.requestLiveRelay", {
|
|
615
|
+
clientUuid: relayTarget.clientUuid,
|
|
616
|
+
localSessionId: relayTarget.localSessionId,
|
|
617
|
+
requestType: "view",
|
|
618
|
+
payload: {},
|
|
619
|
+
}, { meta: { internal_call: true } });
|
|
620
|
+
const response = unwrapLiveRelayResult(rawResponse);
|
|
621
|
+
if (!response ||
|
|
622
|
+
typeof response !== "object" ||
|
|
623
|
+
typeof response.content !== "string") {
|
|
624
|
+
throw new Error("Invalid live relay view response");
|
|
625
|
+
}
|
|
626
|
+
const capturedAt = new Date().toISOString();
|
|
627
|
+
const titleBase = typeof response.session_label === "string" && response.session_label.trim()
|
|
628
|
+
? response.session_label.trim()
|
|
629
|
+
: relayTarget.localSessionId;
|
|
630
|
+
const filenameBase = slugifyGatewayFilenamePart(titleBase) || "session-buffer";
|
|
631
|
+
const timestamp = capturedAt.replace(/[:.]/g, "-");
|
|
632
|
+
writeJson(res, 200, {
|
|
633
|
+
session_id: sessionId,
|
|
634
|
+
...(typeof response.session_label === "string" &&
|
|
635
|
+
response.session_label.trim()
|
|
636
|
+
? { session_label: response.session_label.trim() }
|
|
637
|
+
: {}),
|
|
638
|
+
terminal_target: `relay:${relayTarget.clientUuid}/${relayTarget.localSessionId}`,
|
|
639
|
+
filename: `${filenameBase}-${timestamp}.md`,
|
|
640
|
+
markdown_content: [
|
|
641
|
+
"# Terminal Buffer",
|
|
642
|
+
"",
|
|
643
|
+
`- Session: ${titleBase}`,
|
|
644
|
+
`- Session ID: ${sessionId}`,
|
|
645
|
+
`- terminal target: relay:${relayTarget.clientUuid}/${relayTarget.localSessionId}`,
|
|
646
|
+
"- Capture scope: visible pane",
|
|
647
|
+
`- Captured at: ${capturedAt}`,
|
|
648
|
+
"",
|
|
649
|
+
"```text",
|
|
650
|
+
response.content.replaceAll("\u0000", ""),
|
|
651
|
+
"```",
|
|
652
|
+
"",
|
|
653
|
+
].join("\n"),
|
|
654
|
+
capture_mode: "visible",
|
|
655
|
+
scope_description: "visible pane",
|
|
656
|
+
});
|
|
657
|
+
return true;
|
|
658
|
+
}
|
|
659
|
+
const result = await this.callBroker("telegramMcp.gatewaySocket.requestClientAction", {
|
|
660
|
+
clientUuid: relayTarget.clientUuid,
|
|
661
|
+
actionName: "telegramMcp.terminalBuffer.captureBufferRemote",
|
|
662
|
+
params: {
|
|
663
|
+
session_id: relayTarget.localSessionId,
|
|
664
|
+
scope,
|
|
665
|
+
},
|
|
666
|
+
}, { meta: { internal_call: true } });
|
|
667
|
+
writeJson(res, 200, result);
|
|
668
|
+
return true;
|
|
669
|
+
}
|
|
387
670
|
catch (error) {
|
|
671
|
+
writeJson(res, 400, {
|
|
672
|
+
error: error instanceof Error
|
|
673
|
+
? error.message
|
|
674
|
+
: `Failed to capture remote buffer. Update the client agent if it is not on the latest build. Cause: ${String(error)}`,
|
|
675
|
+
});
|
|
676
|
+
return true;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
if (pathname === "/gateway/live/action") {
|
|
680
|
+
if (req.method !== "POST") {
|
|
681
|
+
writeText(res, 405, "Method not allowed");
|
|
682
|
+
return true;
|
|
683
|
+
}
|
|
684
|
+
try {
|
|
685
|
+
const body = (await this.readJsonBody(req));
|
|
686
|
+
const sessionId = typeof body.session_id === "string" ? body.session_id.trim() : "";
|
|
687
|
+
const action = typeof body.action === "string" ? body.action.trim() : "";
|
|
688
|
+
const text = typeof body.text === "string" ? body.text : "";
|
|
689
|
+
const relayTarget = (0, relay_1.parseLiveRelaySessionId)(sessionId);
|
|
690
|
+
if (!relayTarget) {
|
|
691
|
+
writeJson(res, 400, {
|
|
692
|
+
error: "relay session_id is required",
|
|
693
|
+
});
|
|
694
|
+
return true;
|
|
695
|
+
}
|
|
696
|
+
if (!["enter", "escape", "text"].includes(action)) {
|
|
697
|
+
writeJson(res, 400, {
|
|
698
|
+
error: "action must be one of: enter, escape, text",
|
|
699
|
+
});
|
|
700
|
+
return true;
|
|
701
|
+
}
|
|
702
|
+
if (action === "text" && (!text || text.length > 16)) {
|
|
703
|
+
writeJson(res, 400, {
|
|
704
|
+
error: "text payload is required and must be <= 16 characters",
|
|
705
|
+
});
|
|
706
|
+
return true;
|
|
707
|
+
}
|
|
708
|
+
await this.requestLiveRelayAction({
|
|
709
|
+
clientUuid: relayTarget.clientUuid,
|
|
710
|
+
localSessionId: relayTarget.localSessionId,
|
|
711
|
+
action: action,
|
|
712
|
+
...(action === "text" ? { text } : {}),
|
|
713
|
+
});
|
|
714
|
+
writeJson(res, 200, { ok: true });
|
|
715
|
+
return true;
|
|
716
|
+
}
|
|
717
|
+
catch (error) {
|
|
718
|
+
console.error("Gateway live action request failed", {
|
|
719
|
+
error: error instanceof Error ? (error.stack ?? error.message) : String(error),
|
|
720
|
+
});
|
|
388
721
|
writeJson(res, 400, {
|
|
389
722
|
error: error instanceof Error ? error.message : String(error),
|
|
390
723
|
});
|
|
@@ -409,6 +742,298 @@ class GatewayHttpService {
|
|
|
409
742
|
return true;
|
|
410
743
|
}
|
|
411
744
|
}
|
|
745
|
+
if (pathname === "/gateway/user/auth") {
|
|
746
|
+
if (req.method !== "POST") {
|
|
747
|
+
writeText(res, 405, "Method not allowed");
|
|
748
|
+
return true;
|
|
749
|
+
}
|
|
750
|
+
try {
|
|
751
|
+
const body = (await this.readJsonBody(req));
|
|
752
|
+
const result = await this.callBroker("telegramMcp.gateway.upsertGatewayUser", body, { meta: { internal_call: true } });
|
|
753
|
+
writeJson(res, 200, result);
|
|
754
|
+
return true;
|
|
755
|
+
}
|
|
756
|
+
catch (error) {
|
|
757
|
+
writeJson(res, 400, {
|
|
758
|
+
error: error instanceof Error ? error.message : String(error),
|
|
759
|
+
});
|
|
760
|
+
return true;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
if (pathname === "/gateway/user/route") {
|
|
764
|
+
if (req.method !== "POST") {
|
|
765
|
+
writeText(res, 405, "Method not allowed");
|
|
766
|
+
return true;
|
|
767
|
+
}
|
|
768
|
+
try {
|
|
769
|
+
const body = (await this.readJsonBody(req));
|
|
770
|
+
const result = await this.callBroker("telegramMcp.gateway.resolveGatewayUserRoute", body, { meta: { internal_call: true } });
|
|
771
|
+
writeJson(res, 200, result ?? {});
|
|
772
|
+
return true;
|
|
773
|
+
}
|
|
774
|
+
catch (error) {
|
|
775
|
+
writeJson(res, 400, {
|
|
776
|
+
error: error instanceof Error ? error.message : String(error),
|
|
777
|
+
});
|
|
778
|
+
return true;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
if (pathname === "/gateway/admin/prune-state") {
|
|
782
|
+
if (req.method !== "POST") {
|
|
783
|
+
writeText(res, 405, "Method not allowed");
|
|
784
|
+
return true;
|
|
785
|
+
}
|
|
786
|
+
try {
|
|
787
|
+
const result = await this.callBroker("telegramMcp.gateway.pruneGatewayState", {}, { meta: { internal_call: true } });
|
|
788
|
+
writeJson(res, 200, result);
|
|
789
|
+
return true;
|
|
790
|
+
}
|
|
791
|
+
catch (error) {
|
|
792
|
+
writeJson(res, 400, {
|
|
793
|
+
error: error instanceof Error ? error.message : String(error),
|
|
794
|
+
});
|
|
795
|
+
return true;
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
if (pathname === "/gateway/relay/console-message") {
|
|
799
|
+
if (req.method !== "POST") {
|
|
800
|
+
writeText(res, 405, "Method not allowed");
|
|
801
|
+
return true;
|
|
802
|
+
}
|
|
803
|
+
try {
|
|
804
|
+
const body = (await this.readJsonBody(req));
|
|
805
|
+
const targetClientUuid = typeof body.target_client_uuid === "string"
|
|
806
|
+
? body.target_client_uuid.trim()
|
|
807
|
+
: "";
|
|
808
|
+
const targetLocalSessionId = typeof body.target_local_session_id === "string"
|
|
809
|
+
? body.target_local_session_id.trim()
|
|
810
|
+
: "";
|
|
811
|
+
const text = typeof body.message === "string" ? body.message.trim() : "";
|
|
812
|
+
const attachments = Array.isArray(body.attachments)
|
|
813
|
+
? body.attachments.filter((item) => typeof item === "string" && item.trim().length > 0)
|
|
814
|
+
: [];
|
|
815
|
+
const sourceLabel = typeof body.source_actor_label === "string"
|
|
816
|
+
? body.source_actor_label.trim()
|
|
817
|
+
: undefined;
|
|
818
|
+
if (!targetClientUuid || !targetLocalSessionId || !text) {
|
|
819
|
+
writeJson(res, 400, {
|
|
820
|
+
error: "target_client_uuid, target_local_session_id, and message are required",
|
|
821
|
+
});
|
|
822
|
+
return true;
|
|
823
|
+
}
|
|
824
|
+
const submittedText = attachments.length > 0
|
|
825
|
+
? `${text} [attachments saved: ${attachments.join(", ")}]`.trim()
|
|
826
|
+
: text;
|
|
827
|
+
await this.requestLiveRelayAction({
|
|
828
|
+
clientUuid: targetClientUuid,
|
|
829
|
+
localSessionId: targetLocalSessionId,
|
|
830
|
+
action: "text",
|
|
831
|
+
text: submittedText,
|
|
832
|
+
});
|
|
833
|
+
await this.requestLiveRelayAction({
|
|
834
|
+
clientUuid: targetClientUuid,
|
|
835
|
+
localSessionId: targetLocalSessionId,
|
|
836
|
+
action: "enter",
|
|
837
|
+
});
|
|
838
|
+
writeJson(res, 200, {
|
|
839
|
+
ok: true,
|
|
840
|
+
session_id: targetLocalSessionId,
|
|
841
|
+
submitted_text: submittedText,
|
|
842
|
+
...(sourceLabel ? { source_label: sourceLabel } : {}),
|
|
843
|
+
});
|
|
844
|
+
return true;
|
|
845
|
+
}
|
|
846
|
+
catch (error) {
|
|
847
|
+
writeJson(res, 400, {
|
|
848
|
+
error: error instanceof Error ? error.message : String(error),
|
|
849
|
+
});
|
|
850
|
+
return true;
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
if (pathname === "/gateway/transport/notify") {
|
|
854
|
+
if (req.method !== "POST") {
|
|
855
|
+
writeText(res, 405, "Method not allowed");
|
|
856
|
+
return true;
|
|
857
|
+
}
|
|
858
|
+
try {
|
|
859
|
+
const body = await this.readJsonBody(req);
|
|
860
|
+
const output = await this.callBroker("telegramMcp.notify.sendForGatewaySession", body, { meta: { internal_call: true } });
|
|
861
|
+
writeJson(res, 200, output);
|
|
862
|
+
}
|
|
863
|
+
catch (error) {
|
|
864
|
+
writeText(res, 500, error instanceof Error ? error.message : String(error));
|
|
865
|
+
}
|
|
866
|
+
return true;
|
|
867
|
+
}
|
|
868
|
+
if (pathname === "/gateway/transport/document") {
|
|
869
|
+
if (req.method !== "POST") {
|
|
870
|
+
writeText(res, 405, "Method not allowed");
|
|
871
|
+
return true;
|
|
872
|
+
}
|
|
873
|
+
try {
|
|
874
|
+
const body = await this.readJsonBody(req);
|
|
875
|
+
const output = await this.callBroker("telegramMcp.notify.sendDocumentForGatewaySession", body, { meta: { internal_call: true } });
|
|
876
|
+
writeJson(res, 200, output);
|
|
877
|
+
}
|
|
878
|
+
catch (error) {
|
|
879
|
+
writeText(res, 500, error instanceof Error ? error.message : String(error));
|
|
880
|
+
}
|
|
881
|
+
return true;
|
|
882
|
+
}
|
|
883
|
+
if (pathname === "/gateway/transport/send-file") {
|
|
884
|
+
if (req.method !== "POST") {
|
|
885
|
+
writeText(res, 405, "Method not allowed");
|
|
886
|
+
return true;
|
|
887
|
+
}
|
|
888
|
+
try {
|
|
889
|
+
const body = (await this.readJsonBody(req));
|
|
890
|
+
const sessionId = typeof body.session_id === "string" ? body.session_id.trim() : "";
|
|
891
|
+
const filePath = typeof body.file_path === "string" ? body.file_path.trim() : "";
|
|
892
|
+
const caption = typeof body.caption === "string" && body.caption.trim()
|
|
893
|
+
? body.caption.trim()
|
|
894
|
+
: undefined;
|
|
895
|
+
const target = await this.resolveConnectedConsoleTarget(sessionId);
|
|
896
|
+
const output = await this.callBroker("telegramMcp.gatewaySocket.requestClientAction", {
|
|
897
|
+
clientUuid: target.clientUuid,
|
|
898
|
+
actionName: "telegramMcp.notify.sendDocumentRemote",
|
|
899
|
+
params: {
|
|
900
|
+
session_id: target.localSessionId,
|
|
901
|
+
file_path: filePath,
|
|
902
|
+
...(caption ? { caption } : {}),
|
|
903
|
+
},
|
|
904
|
+
}, { meta: { internal_call: true } });
|
|
905
|
+
if (isBackendErrorLike(output)) {
|
|
906
|
+
throw new Error(this.extractActionErrorMessage(output, "Storage file send failed"));
|
|
907
|
+
}
|
|
908
|
+
writeJson(res, 200, output);
|
|
909
|
+
}
|
|
910
|
+
catch (error) {
|
|
911
|
+
writeText(res, 500, error instanceof Error ? error.message : String(error));
|
|
912
|
+
}
|
|
913
|
+
return true;
|
|
914
|
+
}
|
|
915
|
+
if (pathname === "/gateway/transport/request") {
|
|
916
|
+
if (req.method !== "POST") {
|
|
917
|
+
writeText(res, 405, "Method not allowed");
|
|
918
|
+
return true;
|
|
919
|
+
}
|
|
920
|
+
try {
|
|
921
|
+
const body = await this.readJsonBody(req);
|
|
922
|
+
const output = await this.callBroker("telegramMcp.notify.sendRequestForGatewaySession", body, { meta: { internal_call: true } });
|
|
923
|
+
writeJson(res, 200, output);
|
|
924
|
+
}
|
|
925
|
+
catch (error) {
|
|
926
|
+
writeText(res, 500, error instanceof Error ? error.message : String(error));
|
|
927
|
+
}
|
|
928
|
+
return true;
|
|
929
|
+
}
|
|
930
|
+
if (pathname === "/gateway/transport/reply") {
|
|
931
|
+
if (req.method !== "POST") {
|
|
932
|
+
writeText(res, 405, "Method not allowed");
|
|
933
|
+
return true;
|
|
934
|
+
}
|
|
935
|
+
try {
|
|
936
|
+
const body = await this.readJsonBody(req);
|
|
937
|
+
const output = await this.callBroker("telegramMcp.gatewaySocket.notifyTransportReply", body, { meta: { internal_call: true } });
|
|
938
|
+
writeJson(res, 200, output);
|
|
939
|
+
}
|
|
940
|
+
catch (error) {
|
|
941
|
+
writeText(res, 500, error instanceof Error ? error.message : String(error));
|
|
942
|
+
}
|
|
943
|
+
return true;
|
|
944
|
+
}
|
|
945
|
+
if (pathname === "/gateway/clients/list") {
|
|
946
|
+
if (req.method !== "POST") {
|
|
947
|
+
writeText(res, 405, "Method not allowed");
|
|
948
|
+
return true;
|
|
949
|
+
}
|
|
950
|
+
try {
|
|
951
|
+
const body = (await this.readJsonBody(req));
|
|
952
|
+
const result = await this.callBroker("telegramMcp.gateway.listClients", body, { meta: { internal_call: true } });
|
|
953
|
+
writeJson(res, 200, result);
|
|
954
|
+
return true;
|
|
955
|
+
}
|
|
956
|
+
catch (error) {
|
|
957
|
+
writeJson(res, 400, {
|
|
958
|
+
error: error instanceof Error ? error.message : String(error),
|
|
959
|
+
});
|
|
960
|
+
return true;
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
if (pathname === "/gateway/clients/connected") {
|
|
964
|
+
if (req.method !== "POST") {
|
|
965
|
+
writeText(res, 405, "Method not allowed");
|
|
966
|
+
return true;
|
|
967
|
+
}
|
|
968
|
+
try {
|
|
969
|
+
const body = (await this.readJsonBody(req));
|
|
970
|
+
const result = await this.callBroker("telegramMcp.gateway.listLiveClients", body, { meta: { internal_call: true } });
|
|
971
|
+
writeJson(res, 200, result);
|
|
972
|
+
return true;
|
|
973
|
+
}
|
|
974
|
+
catch (error) {
|
|
975
|
+
writeJson(res, 400, {
|
|
976
|
+
error: error instanceof Error ? error.message : String(error),
|
|
977
|
+
});
|
|
978
|
+
return true;
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
if (pathname === "/gateway/sessions/known") {
|
|
982
|
+
if (req.method !== "POST") {
|
|
983
|
+
writeText(res, 405, "Method not allowed");
|
|
984
|
+
return true;
|
|
985
|
+
}
|
|
986
|
+
try {
|
|
987
|
+
const body = (await this.readJsonBody(req));
|
|
988
|
+
const filterClientUuid = typeof body.client_uuid === "string" && body.client_uuid.trim()
|
|
989
|
+
? body.client_uuid.trim()
|
|
990
|
+
: null;
|
|
991
|
+
const ownerUserUuid = typeof body.owner_user_uuid === "string" && body.owner_user_uuid.trim()
|
|
992
|
+
? body.owner_user_uuid.trim()
|
|
993
|
+
: null;
|
|
994
|
+
const telegramUserId = typeof body.telegram_user_id === "number"
|
|
995
|
+
? String(body.telegram_user_id)
|
|
996
|
+
: typeof body.telegram_user_id === "string" && body.telegram_user_id.trim()
|
|
997
|
+
? body.telegram_user_id.trim()
|
|
998
|
+
: null;
|
|
999
|
+
const connectedOnly = typeof body.connected_only === "boolean"
|
|
1000
|
+
? body.connected_only
|
|
1001
|
+
: false;
|
|
1002
|
+
const [liveResult, scopedClientsResult] = await Promise.all([
|
|
1003
|
+
this.callBroker("telegramMcp.gateway.listLiveConsoles", body, { meta: { internal_call: true } }),
|
|
1004
|
+
this.callBroker("telegramMcp.gateway.listClients", body, { meta: { internal_call: true } }),
|
|
1005
|
+
]);
|
|
1006
|
+
const allowedClientUuids = ownerUserUuid || telegramUserId
|
|
1007
|
+
? new Set((Array.isArray(scopedClientsResult.clients)
|
|
1008
|
+
? scopedClientsResult.clients
|
|
1009
|
+
: [])
|
|
1010
|
+
.map((client) => typeof client.client_uuid === "string"
|
|
1011
|
+
? client.client_uuid.trim()
|
|
1012
|
+
: "")
|
|
1013
|
+
.filter(Boolean))
|
|
1014
|
+
: null;
|
|
1015
|
+
const sessions = (Array.isArray(liveResult.sessions) ? liveResult.sessions : [])
|
|
1016
|
+
.filter((session) => allowedClientUuids ? allowedClientUuids.has(session.client_uuid) : true)
|
|
1017
|
+
.filter((session) => filterClientUuid ? session.client_uuid === filterClientUuid : true)
|
|
1018
|
+
.filter((session) => (connectedOnly ? session.connected : true))
|
|
1019
|
+
.sort((left, right) => {
|
|
1020
|
+
const leftLabel = left.session_label?.trim() || left.local_session_id;
|
|
1021
|
+
const rightLabel = right.session_label?.trim() || right.local_session_id;
|
|
1022
|
+
return `${left.client_uuid}:${leftLabel}`.localeCompare(`${right.client_uuid}:${rightLabel}`);
|
|
1023
|
+
});
|
|
1024
|
+
writeJson(res, 200, {
|
|
1025
|
+
total: sessions.length,
|
|
1026
|
+
sessions,
|
|
1027
|
+
});
|
|
1028
|
+
return true;
|
|
1029
|
+
}
|
|
1030
|
+
catch (error) {
|
|
1031
|
+
writeJson(res, 400, {
|
|
1032
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1033
|
+
});
|
|
1034
|
+
return true;
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
412
1037
|
if (pathname === "/gateway/projects/create") {
|
|
413
1038
|
if (req.method !== "POST") {
|
|
414
1039
|
writeText(res, 405, "Method not allowed");
|
|
@@ -417,6 +1042,11 @@ class GatewayHttpService {
|
|
|
417
1042
|
try {
|
|
418
1043
|
const body = (await this.readJsonBody(req));
|
|
419
1044
|
const result = await this.callBroker("telegramMcp.gateway.createProject", body, { meta: { internal_call: true } });
|
|
1045
|
+
if (isBackendErrorLike(result)) {
|
|
1046
|
+
throw new Error(result.message
|
|
1047
|
+
? `${result.message}${result.code ? ` [${result.code}]` : ""}`
|
|
1048
|
+
: `Gateway createProject failed [${result.code}]`);
|
|
1049
|
+
}
|
|
420
1050
|
writeJson(res, 200, result);
|
|
421
1051
|
return true;
|
|
422
1052
|
}
|
|
@@ -435,6 +1065,11 @@ class GatewayHttpService {
|
|
|
435
1065
|
try {
|
|
436
1066
|
const body = (await this.readJsonBody(req));
|
|
437
1067
|
const result = await this.callBroker("telegramMcp.gateway.joinProject", body, { meta: { internal_call: true } });
|
|
1068
|
+
if (isBackendErrorLike(result)) {
|
|
1069
|
+
throw new Error(result.message
|
|
1070
|
+
? `${result.message}${result.code ? ` [${result.code}]` : ""}`
|
|
1071
|
+
: `Gateway joinProject failed [${result.code}]`);
|
|
1072
|
+
}
|
|
438
1073
|
if (Array.isArray(result.notify_client_uuids) &&
|
|
439
1074
|
result.notify_client_uuids.length > 0 &&
|
|
440
1075
|
typeof result.project_uuid === "string" &&
|
|
@@ -482,24 +1117,11 @@ class GatewayHttpService {
|
|
|
482
1117
|
try {
|
|
483
1118
|
const body = (await this.readJsonBody(req));
|
|
484
1119
|
const result = await this.callBroker("telegramMcp.gateway.registerSession", body, { meta: { internal_call: true } });
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
error: error instanceof Error ? error.message : String(error),
|
|
491
|
-
});
|
|
492
|
-
return true;
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
if (pathname === "/gateway/sessions/unregister") {
|
|
496
|
-
if (req.method !== "POST") {
|
|
497
|
-
writeText(res, 405, "Method not allowed");
|
|
498
|
-
return true;
|
|
499
|
-
}
|
|
500
|
-
try {
|
|
501
|
-
const body = (await this.readJsonBody(req));
|
|
502
|
-
const result = await this.callBroker("telegramMcp.gateway.unregisterSession", body, { meta: { internal_call: true } });
|
|
1120
|
+
if (isBackendErrorLike(result)) {
|
|
1121
|
+
throw new Error(result.message
|
|
1122
|
+
? `${result.message}${result.code ? ` [${result.code}]` : ""}`
|
|
1123
|
+
: `Gateway registerSession failed [${result.code}]`);
|
|
1124
|
+
}
|
|
503
1125
|
writeJson(res, 200, result);
|
|
504
1126
|
return true;
|
|
505
1127
|
}
|