@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
|
@@ -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
|
});
|
|
@@ -385,12 +583,99 @@ class GatewayHttpService {
|
|
|
385
583
|
return true;
|
|
386
584
|
}
|
|
387
585
|
catch (error) {
|
|
586
|
+
console.error("Gateway live approval resolution failed", {
|
|
587
|
+
error: error instanceof Error ? (error.stack ?? error.message) : String(error),
|
|
588
|
+
});
|
|
388
589
|
writeJson(res, 400, {
|
|
389
590
|
error: error instanceof Error ? error.message : String(error),
|
|
390
591
|
});
|
|
391
592
|
return true;
|
|
392
593
|
}
|
|
393
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
|
+
}
|
|
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
|
+
}
|
|
394
679
|
if (pathname === "/gateway/client/register") {
|
|
395
680
|
if (req.method !== "POST") {
|
|
396
681
|
writeText(res, 405, "Method not allowed");
|
|
@@ -409,6 +694,298 @@ class GatewayHttpService {
|
|
|
409
694
|
return true;
|
|
410
695
|
}
|
|
411
696
|
}
|
|
697
|
+
if (pathname === "/gateway/user/auth") {
|
|
698
|
+
if (req.method !== "POST") {
|
|
699
|
+
writeText(res, 405, "Method not allowed");
|
|
700
|
+
return true;
|
|
701
|
+
}
|
|
702
|
+
try {
|
|
703
|
+
const body = (await this.readJsonBody(req));
|
|
704
|
+
const result = await this.callBroker("telegramMcp.gateway.upsertGatewayUser", body, { meta: { internal_call: true } });
|
|
705
|
+
writeJson(res, 200, result);
|
|
706
|
+
return true;
|
|
707
|
+
}
|
|
708
|
+
catch (error) {
|
|
709
|
+
writeJson(res, 400, {
|
|
710
|
+
error: error instanceof Error ? error.message : String(error),
|
|
711
|
+
});
|
|
712
|
+
return true;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
if (pathname === "/gateway/user/route") {
|
|
716
|
+
if (req.method !== "POST") {
|
|
717
|
+
writeText(res, 405, "Method not allowed");
|
|
718
|
+
return true;
|
|
719
|
+
}
|
|
720
|
+
try {
|
|
721
|
+
const body = (await this.readJsonBody(req));
|
|
722
|
+
const result = await this.callBroker("telegramMcp.gateway.resolveGatewayUserRoute", body, { meta: { internal_call: true } });
|
|
723
|
+
writeJson(res, 200, result ?? {});
|
|
724
|
+
return true;
|
|
725
|
+
}
|
|
726
|
+
catch (error) {
|
|
727
|
+
writeJson(res, 400, {
|
|
728
|
+
error: error instanceof Error ? error.message : String(error),
|
|
729
|
+
});
|
|
730
|
+
return true;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
if (pathname === "/gateway/admin/prune-state") {
|
|
734
|
+
if (req.method !== "POST") {
|
|
735
|
+
writeText(res, 405, "Method not allowed");
|
|
736
|
+
return true;
|
|
737
|
+
}
|
|
738
|
+
try {
|
|
739
|
+
const result = await this.callBroker("telegramMcp.gateway.pruneGatewayState", {}, { meta: { internal_call: true } });
|
|
740
|
+
writeJson(res, 200, result);
|
|
741
|
+
return true;
|
|
742
|
+
}
|
|
743
|
+
catch (error) {
|
|
744
|
+
writeJson(res, 400, {
|
|
745
|
+
error: error instanceof Error ? error.message : String(error),
|
|
746
|
+
});
|
|
747
|
+
return true;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
if (pathname === "/gateway/relay/console-message") {
|
|
751
|
+
if (req.method !== "POST") {
|
|
752
|
+
writeText(res, 405, "Method not allowed");
|
|
753
|
+
return true;
|
|
754
|
+
}
|
|
755
|
+
try {
|
|
756
|
+
const body = (await this.readJsonBody(req));
|
|
757
|
+
const targetClientUuid = typeof body.target_client_uuid === "string"
|
|
758
|
+
? body.target_client_uuid.trim()
|
|
759
|
+
: "";
|
|
760
|
+
const targetLocalSessionId = typeof body.target_local_session_id === "string"
|
|
761
|
+
? body.target_local_session_id.trim()
|
|
762
|
+
: "";
|
|
763
|
+
const text = typeof body.message === "string" ? body.message.trim() : "";
|
|
764
|
+
const attachments = Array.isArray(body.attachments)
|
|
765
|
+
? body.attachments.filter((item) => typeof item === "string" && item.trim().length > 0)
|
|
766
|
+
: [];
|
|
767
|
+
const sourceLabel = typeof body.source_actor_label === "string"
|
|
768
|
+
? body.source_actor_label.trim()
|
|
769
|
+
: undefined;
|
|
770
|
+
if (!targetClientUuid || !targetLocalSessionId || !text) {
|
|
771
|
+
writeJson(res, 400, {
|
|
772
|
+
error: "target_client_uuid, target_local_session_id, and message are required",
|
|
773
|
+
});
|
|
774
|
+
return true;
|
|
775
|
+
}
|
|
776
|
+
const submittedText = attachments.length > 0
|
|
777
|
+
? `${text} [attachments saved: ${attachments.join(", ")}]`.trim()
|
|
778
|
+
: text;
|
|
779
|
+
await this.requestLiveRelayAction({
|
|
780
|
+
clientUuid: targetClientUuid,
|
|
781
|
+
localSessionId: targetLocalSessionId,
|
|
782
|
+
action: "text",
|
|
783
|
+
text: submittedText,
|
|
784
|
+
});
|
|
785
|
+
await this.requestLiveRelayAction({
|
|
786
|
+
clientUuid: targetClientUuid,
|
|
787
|
+
localSessionId: targetLocalSessionId,
|
|
788
|
+
action: "enter",
|
|
789
|
+
});
|
|
790
|
+
writeJson(res, 200, {
|
|
791
|
+
ok: true,
|
|
792
|
+
session_id: targetLocalSessionId,
|
|
793
|
+
submitted_text: submittedText,
|
|
794
|
+
...(sourceLabel ? { source_label: sourceLabel } : {}),
|
|
795
|
+
});
|
|
796
|
+
return true;
|
|
797
|
+
}
|
|
798
|
+
catch (error) {
|
|
799
|
+
writeJson(res, 400, {
|
|
800
|
+
error: error instanceof Error ? error.message : String(error),
|
|
801
|
+
});
|
|
802
|
+
return true;
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
if (pathname === "/gateway/transport/notify") {
|
|
806
|
+
if (req.method !== "POST") {
|
|
807
|
+
writeText(res, 405, "Method not allowed");
|
|
808
|
+
return true;
|
|
809
|
+
}
|
|
810
|
+
try {
|
|
811
|
+
const body = await this.readJsonBody(req);
|
|
812
|
+
const output = await this.callBroker("telegramMcp.notify.sendForGatewaySession", body, { meta: { internal_call: true } });
|
|
813
|
+
writeJson(res, 200, output);
|
|
814
|
+
}
|
|
815
|
+
catch (error) {
|
|
816
|
+
writeText(res, 500, error instanceof Error ? error.message : String(error));
|
|
817
|
+
}
|
|
818
|
+
return true;
|
|
819
|
+
}
|
|
820
|
+
if (pathname === "/gateway/transport/document") {
|
|
821
|
+
if (req.method !== "POST") {
|
|
822
|
+
writeText(res, 405, "Method not allowed");
|
|
823
|
+
return true;
|
|
824
|
+
}
|
|
825
|
+
try {
|
|
826
|
+
const body = await this.readJsonBody(req);
|
|
827
|
+
const output = await this.callBroker("telegramMcp.notify.sendDocumentForGatewaySession", body, { meta: { internal_call: true } });
|
|
828
|
+
writeJson(res, 200, output);
|
|
829
|
+
}
|
|
830
|
+
catch (error) {
|
|
831
|
+
writeText(res, 500, error instanceof Error ? error.message : String(error));
|
|
832
|
+
}
|
|
833
|
+
return true;
|
|
834
|
+
}
|
|
835
|
+
if (pathname === "/gateway/transport/send-file") {
|
|
836
|
+
if (req.method !== "POST") {
|
|
837
|
+
writeText(res, 405, "Method not allowed");
|
|
838
|
+
return true;
|
|
839
|
+
}
|
|
840
|
+
try {
|
|
841
|
+
const body = (await this.readJsonBody(req));
|
|
842
|
+
const sessionId = typeof body.session_id === "string" ? body.session_id.trim() : "";
|
|
843
|
+
const filePath = typeof body.file_path === "string" ? body.file_path.trim() : "";
|
|
844
|
+
const caption = typeof body.caption === "string" && body.caption.trim()
|
|
845
|
+
? body.caption.trim()
|
|
846
|
+
: undefined;
|
|
847
|
+
const target = await this.resolveConnectedConsoleTarget(sessionId);
|
|
848
|
+
const output = await this.callBroker("telegramMcp.gatewaySocket.requestClientAction", {
|
|
849
|
+
clientUuid: target.clientUuid,
|
|
850
|
+
actionName: "telegramMcp.notify.sendDocumentRemote",
|
|
851
|
+
params: {
|
|
852
|
+
session_id: target.localSessionId,
|
|
853
|
+
file_path: filePath,
|
|
854
|
+
...(caption ? { caption } : {}),
|
|
855
|
+
},
|
|
856
|
+
}, { meta: { internal_call: true } });
|
|
857
|
+
if (isBackendErrorLike(output)) {
|
|
858
|
+
throw new Error(this.extractActionErrorMessage(output, "Storage file send failed"));
|
|
859
|
+
}
|
|
860
|
+
writeJson(res, 200, output);
|
|
861
|
+
}
|
|
862
|
+
catch (error) {
|
|
863
|
+
writeText(res, 500, error instanceof Error ? error.message : String(error));
|
|
864
|
+
}
|
|
865
|
+
return true;
|
|
866
|
+
}
|
|
867
|
+
if (pathname === "/gateway/transport/request") {
|
|
868
|
+
if (req.method !== "POST") {
|
|
869
|
+
writeText(res, 405, "Method not allowed");
|
|
870
|
+
return true;
|
|
871
|
+
}
|
|
872
|
+
try {
|
|
873
|
+
const body = await this.readJsonBody(req);
|
|
874
|
+
const output = await this.callBroker("telegramMcp.notify.sendRequestForGatewaySession", body, { meta: { internal_call: true } });
|
|
875
|
+
writeJson(res, 200, output);
|
|
876
|
+
}
|
|
877
|
+
catch (error) {
|
|
878
|
+
writeText(res, 500, error instanceof Error ? error.message : String(error));
|
|
879
|
+
}
|
|
880
|
+
return true;
|
|
881
|
+
}
|
|
882
|
+
if (pathname === "/gateway/transport/reply") {
|
|
883
|
+
if (req.method !== "POST") {
|
|
884
|
+
writeText(res, 405, "Method not allowed");
|
|
885
|
+
return true;
|
|
886
|
+
}
|
|
887
|
+
try {
|
|
888
|
+
const body = await this.readJsonBody(req);
|
|
889
|
+
const output = await this.callBroker("telegramMcp.gatewaySocket.notifyTransportReply", body, { meta: { internal_call: true } });
|
|
890
|
+
writeJson(res, 200, output);
|
|
891
|
+
}
|
|
892
|
+
catch (error) {
|
|
893
|
+
writeText(res, 500, error instanceof Error ? error.message : String(error));
|
|
894
|
+
}
|
|
895
|
+
return true;
|
|
896
|
+
}
|
|
897
|
+
if (pathname === "/gateway/clients/list") {
|
|
898
|
+
if (req.method !== "POST") {
|
|
899
|
+
writeText(res, 405, "Method not allowed");
|
|
900
|
+
return true;
|
|
901
|
+
}
|
|
902
|
+
try {
|
|
903
|
+
const body = (await this.readJsonBody(req));
|
|
904
|
+
const result = await this.callBroker("telegramMcp.gateway.listClients", body, { meta: { internal_call: true } });
|
|
905
|
+
writeJson(res, 200, result);
|
|
906
|
+
return true;
|
|
907
|
+
}
|
|
908
|
+
catch (error) {
|
|
909
|
+
writeJson(res, 400, {
|
|
910
|
+
error: error instanceof Error ? error.message : String(error),
|
|
911
|
+
});
|
|
912
|
+
return true;
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
if (pathname === "/gateway/clients/connected") {
|
|
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 result = await this.callBroker("telegramMcp.gateway.listLiveClients", body, { meta: { internal_call: true } });
|
|
923
|
+
writeJson(res, 200, result);
|
|
924
|
+
return true;
|
|
925
|
+
}
|
|
926
|
+
catch (error) {
|
|
927
|
+
writeJson(res, 400, {
|
|
928
|
+
error: error instanceof Error ? error.message : String(error),
|
|
929
|
+
});
|
|
930
|
+
return true;
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
if (pathname === "/gateway/sessions/known") {
|
|
934
|
+
if (req.method !== "POST") {
|
|
935
|
+
writeText(res, 405, "Method not allowed");
|
|
936
|
+
return true;
|
|
937
|
+
}
|
|
938
|
+
try {
|
|
939
|
+
const body = (await this.readJsonBody(req));
|
|
940
|
+
const filterClientUuid = typeof body.client_uuid === "string" && body.client_uuid.trim()
|
|
941
|
+
? body.client_uuid.trim()
|
|
942
|
+
: null;
|
|
943
|
+
const ownerUserUuid = typeof body.owner_user_uuid === "string" && body.owner_user_uuid.trim()
|
|
944
|
+
? body.owner_user_uuid.trim()
|
|
945
|
+
: null;
|
|
946
|
+
const telegramUserId = typeof body.telegram_user_id === "number"
|
|
947
|
+
? String(body.telegram_user_id)
|
|
948
|
+
: typeof body.telegram_user_id === "string" && body.telegram_user_id.trim()
|
|
949
|
+
? body.telegram_user_id.trim()
|
|
950
|
+
: null;
|
|
951
|
+
const connectedOnly = typeof body.connected_only === "boolean"
|
|
952
|
+
? body.connected_only
|
|
953
|
+
: false;
|
|
954
|
+
const [liveResult, scopedClientsResult] = await Promise.all([
|
|
955
|
+
this.callBroker("telegramMcp.gateway.listLiveConsoles", body, { meta: { internal_call: true } }),
|
|
956
|
+
this.callBroker("telegramMcp.gateway.listClients", body, { meta: { internal_call: true } }),
|
|
957
|
+
]);
|
|
958
|
+
const allowedClientUuids = ownerUserUuid || telegramUserId
|
|
959
|
+
? new Set((Array.isArray(scopedClientsResult.clients)
|
|
960
|
+
? scopedClientsResult.clients
|
|
961
|
+
: [])
|
|
962
|
+
.map((client) => typeof client.client_uuid === "string"
|
|
963
|
+
? client.client_uuid.trim()
|
|
964
|
+
: "")
|
|
965
|
+
.filter(Boolean))
|
|
966
|
+
: null;
|
|
967
|
+
const sessions = (Array.isArray(liveResult.sessions) ? liveResult.sessions : [])
|
|
968
|
+
.filter((session) => allowedClientUuids ? allowedClientUuids.has(session.client_uuid) : true)
|
|
969
|
+
.filter((session) => filterClientUuid ? session.client_uuid === filterClientUuid : true)
|
|
970
|
+
.filter((session) => (connectedOnly ? session.connected : true))
|
|
971
|
+
.sort((left, right) => {
|
|
972
|
+
const leftLabel = left.session_label?.trim() || left.local_session_id;
|
|
973
|
+
const rightLabel = right.session_label?.trim() || right.local_session_id;
|
|
974
|
+
return `${left.client_uuid}:${leftLabel}`.localeCompare(`${right.client_uuid}:${rightLabel}`);
|
|
975
|
+
});
|
|
976
|
+
writeJson(res, 200, {
|
|
977
|
+
total: sessions.length,
|
|
978
|
+
sessions,
|
|
979
|
+
});
|
|
980
|
+
return true;
|
|
981
|
+
}
|
|
982
|
+
catch (error) {
|
|
983
|
+
writeJson(res, 400, {
|
|
984
|
+
error: error instanceof Error ? error.message : String(error),
|
|
985
|
+
});
|
|
986
|
+
return true;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
412
989
|
if (pathname === "/gateway/projects/create") {
|
|
413
990
|
if (req.method !== "POST") {
|
|
414
991
|
writeText(res, 405, "Method not allowed");
|
|
@@ -417,6 +994,11 @@ class GatewayHttpService {
|
|
|
417
994
|
try {
|
|
418
995
|
const body = (await this.readJsonBody(req));
|
|
419
996
|
const result = await this.callBroker("telegramMcp.gateway.createProject", body, { meta: { internal_call: true } });
|
|
997
|
+
if (isBackendErrorLike(result)) {
|
|
998
|
+
throw new Error(result.message
|
|
999
|
+
? `${result.message}${result.code ? ` [${result.code}]` : ""}`
|
|
1000
|
+
: `Gateway createProject failed [${result.code}]`);
|
|
1001
|
+
}
|
|
420
1002
|
writeJson(res, 200, result);
|
|
421
1003
|
return true;
|
|
422
1004
|
}
|
|
@@ -435,6 +1017,11 @@ class GatewayHttpService {
|
|
|
435
1017
|
try {
|
|
436
1018
|
const body = (await this.readJsonBody(req));
|
|
437
1019
|
const result = await this.callBroker("telegramMcp.gateway.joinProject", body, { meta: { internal_call: true } });
|
|
1020
|
+
if (isBackendErrorLike(result)) {
|
|
1021
|
+
throw new Error(result.message
|
|
1022
|
+
? `${result.message}${result.code ? ` [${result.code}]` : ""}`
|
|
1023
|
+
: `Gateway joinProject failed [${result.code}]`);
|
|
1024
|
+
}
|
|
438
1025
|
if (Array.isArray(result.notify_client_uuids) &&
|
|
439
1026
|
result.notify_client_uuids.length > 0 &&
|
|
440
1027
|
typeof result.project_uuid === "string" &&
|
|
@@ -482,24 +1069,11 @@ class GatewayHttpService {
|
|
|
482
1069
|
try {
|
|
483
1070
|
const body = (await this.readJsonBody(req));
|
|
484
1071
|
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 } });
|
|
1072
|
+
if (isBackendErrorLike(result)) {
|
|
1073
|
+
throw new Error(result.message
|
|
1074
|
+
? `${result.message}${result.code ? ` [${result.code}]` : ""}`
|
|
1075
|
+
: `Gateway registerSession failed [${result.code}]`);
|
|
1076
|
+
}
|
|
503
1077
|
writeJson(res, 200, result);
|
|
504
1078
|
return true;
|
|
505
1079
|
}
|