@deadragdoll/tellymcp 0.0.1
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 +93 -0
- package/.env.example.gateway +120 -0
- package/CHANGELOG.md +155 -0
- package/LICENSE +21 -0
- package/README-ru.md +338 -0
- package/README.md +1262 -0
- package/STANDALONE-ru.md +266 -0
- package/STANDALONE.md +266 -0
- package/TOOLS.md +1296 -0
- package/config/templates/env.both.template +83 -0
- package/config/templates/env.client.template +60 -0
- package/config/templates/env.gateway.template +82 -0
- package/dist/cli.js +636 -0
- package/dist/index.js +17 -0
- package/dist/lib/logfeed/store.js +52 -0
- package/dist/lib/middlewares/tracer.js +172 -0
- package/dist/lib/mixins/db.js +267 -0
- package/dist/lib/mixins/logfeed.js +34 -0
- package/dist/lib/mixins/session.errors.js +142 -0
- package/dist/lib/moleculer.js +2 -0
- package/dist/lib/trace.js +147 -0
- package/dist/lib/traceContext.js +116 -0
- package/dist/moleculer.config.js +274 -0
- package/dist/services/features/telegram-mcp/approval.service.js +33 -0
- package/dist/services/features/telegram-mcp/browser.service.js +42 -0
- package/dist/services/features/telegram-mcp/collaboration.service.js +53 -0
- package/dist/services/features/telegram-mcp/ensuredb.service.js +337 -0
- package/dist/services/features/telegram-mcp/gateway-delivery.service.js +378 -0
- package/dist/services/features/telegram-mcp/gateway-loopback.js +10 -0
- package/dist/services/features/telegram-mcp/gateway-rmq.service.js +294 -0
- package/dist/services/features/telegram-mcp/gateway-socket.service.js +1463 -0
- package/dist/services/features/telegram-mcp/gateway.service.js +1141 -0
- package/dist/services/features/telegram-mcp/inbox.service.js +33 -0
- package/dist/services/features/telegram-mcp/mcp-http.service.js +76 -0
- package/dist/services/features/telegram-mcp/mcp-server.service.js +127 -0
- package/dist/services/features/telegram-mcp/notify.service.js +33 -0
- package/dist/services/features/telegram-mcp/pair.service.js +33 -0
- package/dist/services/features/telegram-mcp/runtime.service.js +36 -0
- package/dist/services/features/telegram-mcp/session-context.service.js +33 -0
- package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +103 -0
- package/dist/services/features/telegram-mcp/src/app/config/env.js +317 -0
- package/dist/services/features/telegram-mcp/src/app/http.js +774 -0
- package/dist/services/features/telegram-mcp/src/app/index.js +2 -0
- package/dist/services/features/telegram-mcp/src/app/providers/mcp/server.js +13 -0
- package/dist/services/features/telegram-mcp/src/app/providers/redis/client.js +18 -0
- package/dist/services/features/telegram-mcp/src/app/webapp/assets.js +740 -0
- package/dist/services/features/telegram-mcp/src/app/webapp/auth.js +267 -0
- package/dist/services/features/telegram-mcp/src/app/webapp/relay.js +69 -0
- package/dist/services/features/telegram-mcp/src/app/webapp/tmux.js +9 -0
- package/dist/services/features/telegram-mcp/src/entities/auth/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/entities/browser/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/entities/collaboration/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/entities/inbox/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/entities/request/model/schema.js +545 -0
- package/dist/services/features/telegram-mcp/src/entities/request/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/entities/session/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/features/ask-user/model/askUserTelegram.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserClearLogsTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserClickTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserCloseTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserComputedStyleTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserConsoleTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserDomTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserErrorsTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserFillTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserNetworkFailuresTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserOpenTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserPressTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserReloadTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserScreenshotTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserService.js +689 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserWaitForTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserWaitForUrlTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/backend.js +2 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/collaborationService.js +26 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/localCollaborationBackend.js +390 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileService.js +102 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerNoteTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayCollaborationBackend.js +69 -0
- package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayHttpService.js +657 -0
- package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayReplyResolution.js +17 -0
- package/dist/services/features/telegram-mcp/src/features/inbox/model/deleteTelegramInboxMessageTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxCountTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/inbox/model/inboxService.js +77 -0
- package/dist/services/features/telegram-mcp/src/features/notify/model/notifyService.js +93 -0
- package/dist/services/features/telegram-mcp/src/features/notify/model/notifyTelegramTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/pair-session/model/clearSessionPairingTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/pair-session/model/createSessionPairCodeTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/pair-session/model/generatePairCode.js +202 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/clearSessionContextTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/getSessionContextTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/getTmuxTargetTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/renameSessionTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/sessionContextService.js +409 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/setSessionContextTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/setTmuxTargetTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownService.js +123 -0
- package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/processes/human-approval/model/orchestrator.js +243 -0
- package/dist/services/features/telegram-mcp/src/shared/api/storage/contract.js +2 -0
- package/dist/services/features/telegram-mcp/src/shared/api/tool-registry/registry.js +8 -0
- package/dist/services/features/telegram-mcp/src/shared/api/tool-registry/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/shared/api/transport/contract.js +2 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/object-storage/minioExchangeStore.js +86 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/redis/stateStore.js +436 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/collabSemantics.js +21 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/collabUi.js +87 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/messageFormat.js +60 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/proxyFetch.js +46 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +6534 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/tmux/client.js +280 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/ids/ids.js +34 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/logger/logger.js +68 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/project-identity/projectIdentity.js +223 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/redact-secrets/redactSecrets.js +22 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/truncate/truncate.js +12 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/version/versionHandshake.js +124 -0
- package/dist/services/features/telegram-mcp/src/shared/types/common.js +2 -0
- package/dist/services/features/telegram-mcp/standalone-http.service.js +113 -0
- package/dist/services/features/telegram-mcp/tools-sync.service.js +33 -0
- package/package.json +110 -0
- package/scripts/postinstall.js +60 -0
|
@@ -0,0 +1,657 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GatewayHttpService = void 0;
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
const schema_1 = require("../../../entities/request/model/schema");
|
|
7
|
+
function readHeader(req, headerName) {
|
|
8
|
+
const value = req.headers[headerName];
|
|
9
|
+
return Array.isArray(value) ? value[0] : value;
|
|
10
|
+
}
|
|
11
|
+
function writeJson(res, statusCode, payload) {
|
|
12
|
+
res.statusCode = statusCode;
|
|
13
|
+
res.setHeader("content-type", "application/json");
|
|
14
|
+
res.end(JSON.stringify(payload));
|
|
15
|
+
}
|
|
16
|
+
function writeText(res, statusCode, message) {
|
|
17
|
+
res.statusCode = statusCode;
|
|
18
|
+
res.setHeader("content-type", "text/plain; charset=utf-8");
|
|
19
|
+
res.end(message);
|
|
20
|
+
}
|
|
21
|
+
function unwrapLiveRelayResult(response) {
|
|
22
|
+
if (!response || typeof response !== "object") {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
if ("result" in response) {
|
|
26
|
+
const wrapped = response;
|
|
27
|
+
if (wrapped.result && typeof wrapped.result === "object") {
|
|
28
|
+
return wrapped.result;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return response;
|
|
32
|
+
}
|
|
33
|
+
function normalizeLiveRelayBootstrapResult(response) {
|
|
34
|
+
if (!response || typeof response !== "object") {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const record = response;
|
|
38
|
+
const sessionId = typeof record.session_id === "string" ? record.session_id.trim() : "";
|
|
39
|
+
const telegramUserId = typeof record.telegram_user_id === "number"
|
|
40
|
+
? record.telegram_user_id
|
|
41
|
+
: typeof record.telegram_user_id === "string" &&
|
|
42
|
+
/^\d+$/u.test(record.telegram_user_id.trim())
|
|
43
|
+
? Number(record.telegram_user_id.trim())
|
|
44
|
+
: NaN;
|
|
45
|
+
if (!sessionId || !Number.isFinite(telegramUserId)) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
session_id: sessionId,
|
|
50
|
+
session_label: typeof record.session_label === "string" ? record.session_label : null,
|
|
51
|
+
tmux_target: record.tmux_target === true,
|
|
52
|
+
poll_interval_ms: typeof record.poll_interval_ms === "number" && record.poll_interval_ms > 0
|
|
53
|
+
? record.poll_interval_ms
|
|
54
|
+
: 2000,
|
|
55
|
+
telegram_user_id: telegramUserId,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function buildPartnerNoteOutputFallback(input, rawOutput) {
|
|
59
|
+
const outputRecord = rawOutput && typeof rawOutput === "object"
|
|
60
|
+
? rawOutput
|
|
61
|
+
: {};
|
|
62
|
+
return {
|
|
63
|
+
session_id: typeof outputRecord.session_id === "string"
|
|
64
|
+
? outputRecord.session_id
|
|
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
|
+
};
|
|
95
|
+
}
|
|
96
|
+
class GatewayHttpService {
|
|
97
|
+
config;
|
|
98
|
+
callBroker;
|
|
99
|
+
constructor(config, callBroker) {
|
|
100
|
+
this.config = config;
|
|
101
|
+
this.callBroker = callBroker;
|
|
102
|
+
}
|
|
103
|
+
partnerNoteRelayHandler = null;
|
|
104
|
+
setPartnerNoteRelayHandler(handler) {
|
|
105
|
+
this.partnerNoteRelayHandler = handler;
|
|
106
|
+
}
|
|
107
|
+
isEnabled() {
|
|
108
|
+
return (this.config.distributed.mode === "gateway" ||
|
|
109
|
+
this.config.distributed.mode === "both");
|
|
110
|
+
}
|
|
111
|
+
matches(pathname) {
|
|
112
|
+
return pathname === "/gateway/healthz" || pathname.startsWith("/gateway/");
|
|
113
|
+
}
|
|
114
|
+
async requestLiveRelayBootstrap(input) {
|
|
115
|
+
const payload = typeof input.telegramUserId === "number"
|
|
116
|
+
? {
|
|
117
|
+
telegramUserId: input.telegramUserId,
|
|
118
|
+
...(input.allowForeignBinding ? { allowForeignBinding: true } : {}),
|
|
119
|
+
}
|
|
120
|
+
: {
|
|
121
|
+
initDataRaw: input.initDataRaw,
|
|
122
|
+
initDataUnsafe: input.initDataUnsafe,
|
|
123
|
+
};
|
|
124
|
+
const rawResponse = await this.callBroker("telegramMcp.gatewaySocket.requestLiveRelay", {
|
|
125
|
+
clientUuid: input.clientUuid,
|
|
126
|
+
localSessionId: input.localSessionId,
|
|
127
|
+
requestType: "bootstrap",
|
|
128
|
+
payload,
|
|
129
|
+
}, { meta: { internal_call: true } });
|
|
130
|
+
const response = normalizeLiveRelayBootstrapResult(unwrapLiveRelayResult(rawResponse));
|
|
131
|
+
if (!response) {
|
|
132
|
+
throw new Error(`Invalid live relay bootstrap response: ${JSON.stringify(rawResponse)}`);
|
|
133
|
+
}
|
|
134
|
+
return response;
|
|
135
|
+
}
|
|
136
|
+
async requestLiveRelayBootstrapValidation(input) {
|
|
137
|
+
const rawResponse = await this.callBroker("telegramMcp.gatewaySocket.requestLiveRelay", {
|
|
138
|
+
clientUuid: input.clientUuid,
|
|
139
|
+
localSessionId: "",
|
|
140
|
+
requestType: "bootstrap_validate",
|
|
141
|
+
payload: {
|
|
142
|
+
initDataRaw: input.initDataRaw,
|
|
143
|
+
initDataUnsafe: input.initDataUnsafe,
|
|
144
|
+
},
|
|
145
|
+
}, { meta: { internal_call: true } });
|
|
146
|
+
const response = unwrapLiveRelayResult(rawResponse);
|
|
147
|
+
if (!response ||
|
|
148
|
+
typeof response !== "object" ||
|
|
149
|
+
typeof response.telegram_user_id !== "number") {
|
|
150
|
+
throw new Error(`Invalid live relay bootstrap validation response: ${JSON.stringify(rawResponse)}`);
|
|
151
|
+
}
|
|
152
|
+
return response;
|
|
153
|
+
}
|
|
154
|
+
async requestLiveRelayView(input) {
|
|
155
|
+
const rawResponse = await this.callBroker("telegramMcp.gatewaySocket.requestLiveRelay", {
|
|
156
|
+
clientUuid: input.clientUuid,
|
|
157
|
+
localSessionId: input.localSessionId,
|
|
158
|
+
requestType: "view",
|
|
159
|
+
payload: {},
|
|
160
|
+
}, { meta: { internal_call: true } });
|
|
161
|
+
const response = unwrapLiveRelayResult(rawResponse);
|
|
162
|
+
if (!response ||
|
|
163
|
+
typeof response !== "object" ||
|
|
164
|
+
typeof response.content !== "string") {
|
|
165
|
+
throw new Error("Invalid live relay view response");
|
|
166
|
+
}
|
|
167
|
+
return response;
|
|
168
|
+
}
|
|
169
|
+
async requestLiveRelayAction(input) {
|
|
170
|
+
const rawResponse = await this.callBroker("telegramMcp.gatewaySocket.requestLiveRelay", {
|
|
171
|
+
clientUuid: input.clientUuid,
|
|
172
|
+
localSessionId: input.localSessionId,
|
|
173
|
+
requestType: "action",
|
|
174
|
+
payload: {
|
|
175
|
+
action: input.action,
|
|
176
|
+
},
|
|
177
|
+
}, { meta: { internal_call: true } });
|
|
178
|
+
const response = unwrapLiveRelayResult(rawResponse);
|
|
179
|
+
if (!response ||
|
|
180
|
+
typeof response !== "object" ||
|
|
181
|
+
response.ok !== true) {
|
|
182
|
+
throw new Error("Invalid live relay action response");
|
|
183
|
+
}
|
|
184
|
+
return response;
|
|
185
|
+
}
|
|
186
|
+
isAuthorized(req) {
|
|
187
|
+
if (!this.config.distributed.gatewayAuthToken) {
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
const authorization = readHeader(req, "authorization");
|
|
191
|
+
return authorization === `Bearer ${this.config.distributed.gatewayAuthToken}`;
|
|
192
|
+
}
|
|
193
|
+
extractActionErrorMessage(value, fallback) {
|
|
194
|
+
if (value && typeof value === "object") {
|
|
195
|
+
const record = value;
|
|
196
|
+
if (typeof record.message === "string" && record.message.trim()) {
|
|
197
|
+
return record.message;
|
|
198
|
+
}
|
|
199
|
+
const extensions = record.extensions;
|
|
200
|
+
if (extensions && typeof extensions === "object") {
|
|
201
|
+
const extRecord = extensions;
|
|
202
|
+
if (typeof extRecord.message === "string" && extRecord.message.trim()) {
|
|
203
|
+
return extRecord.message;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return fallback;
|
|
208
|
+
}
|
|
209
|
+
async readJsonBody(req) {
|
|
210
|
+
const knownBody = req.body;
|
|
211
|
+
if (knownBody !== undefined) {
|
|
212
|
+
return knownBody;
|
|
213
|
+
}
|
|
214
|
+
const knownParams = req.$params;
|
|
215
|
+
if (knownParams &&
|
|
216
|
+
typeof knownParams === "object" &&
|
|
217
|
+
("kind" in knownParams ||
|
|
218
|
+
"summary" in knownParams ||
|
|
219
|
+
"message" in knownParams ||
|
|
220
|
+
"session_id" in knownParams)) {
|
|
221
|
+
return knownParams;
|
|
222
|
+
}
|
|
223
|
+
const chunks = [];
|
|
224
|
+
for await (const chunk of req) {
|
|
225
|
+
chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
226
|
+
}
|
|
227
|
+
if (chunks.length === 0) {
|
|
228
|
+
return undefined;
|
|
229
|
+
}
|
|
230
|
+
const raw = Buffer.concat(chunks).toString("utf8").trim();
|
|
231
|
+
if (!raw) {
|
|
232
|
+
return undefined;
|
|
233
|
+
}
|
|
234
|
+
return JSON.parse(raw);
|
|
235
|
+
}
|
|
236
|
+
async handleRequest(req, res, pathname) {
|
|
237
|
+
if (!this.isEnabled() || !this.matches(pathname)) {
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
if (pathname === "/gateway/healthz") {
|
|
241
|
+
writeJson(res, 200, {
|
|
242
|
+
ok: true,
|
|
243
|
+
service: "telegram-human-mcp-gateway",
|
|
244
|
+
mode: this.config.distributed.mode,
|
|
245
|
+
databaseConfigured: Boolean(process.env.DB_HOST && process.env.DB_NAME),
|
|
246
|
+
s3Configured: Boolean(this.config.distributed.gatewayS3Bucket),
|
|
247
|
+
});
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
250
|
+
if (!this.isAuthorized(req)) {
|
|
251
|
+
writeText(res, 401, "Unauthorized");
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
254
|
+
if (pathname === "/gateway/tools-md") {
|
|
255
|
+
if (req.method !== "GET") {
|
|
256
|
+
writeText(res, 405, "Method not allowed");
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
try {
|
|
260
|
+
const toolsPath = (0, node_path_1.join)(process.cwd(), "TOOLS.md");
|
|
261
|
+
res.statusCode = 200;
|
|
262
|
+
res.setHeader("content-type", "text/markdown; charset=utf-8");
|
|
263
|
+
res.end((0, node_fs_1.readFileSync)(toolsPath, "utf8"));
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
266
|
+
catch (error) {
|
|
267
|
+
writeJson(res, 404, {
|
|
268
|
+
error: error instanceof Error ? error.message : String(error),
|
|
269
|
+
});
|
|
270
|
+
return true;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
if (pathname === "/gateway/partner-note") {
|
|
274
|
+
if (req.method !== "POST") {
|
|
275
|
+
writeText(res, 405, "Method not allowed");
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
try {
|
|
279
|
+
const body = await this.readJsonBody(req);
|
|
280
|
+
const input = schema_1.sendPartnerNoteInputSchema.parse(body);
|
|
281
|
+
const useQueuedGatewayDelivery = typeof body?.client_uuid === "string" &&
|
|
282
|
+
typeof input.target_session_id === "string" &&
|
|
283
|
+
input.target_session_id.trim().length > 0;
|
|
284
|
+
const output = useQueuedGatewayDelivery
|
|
285
|
+
? await this.callBroker("telegramMcp.gateway.sendPartnerNote", body, { meta: { internal_call: true } })
|
|
286
|
+
: this.partnerNoteRelayHandler
|
|
287
|
+
? await this.partnerNoteRelayHandler(input)
|
|
288
|
+
: (() => {
|
|
289
|
+
throw new Error("Gateway partner relay handler is not configured.");
|
|
290
|
+
})();
|
|
291
|
+
if (useQueuedGatewayDelivery &&
|
|
292
|
+
output &&
|
|
293
|
+
typeof output === "object" &&
|
|
294
|
+
typeof output.target_client_uuid ===
|
|
295
|
+
"string" &&
|
|
296
|
+
output.delivery &&
|
|
297
|
+
typeof output.delivery === "object") {
|
|
298
|
+
const publishResult = await this.callBroker("telegramMcp.gatewayRmq.publishDeliveryQueued", {
|
|
299
|
+
clientUuid: output.target_client_uuid,
|
|
300
|
+
delivery: output.delivery,
|
|
301
|
+
}, { meta: { internal_call: true } });
|
|
302
|
+
if (!publishResult?.published) {
|
|
303
|
+
await this.callBroker("telegramMcp.gatewaySocket.notifyDeliveryQueued", {
|
|
304
|
+
clientUuid: output.target_client_uuid,
|
|
305
|
+
delivery: output.delivery,
|
|
306
|
+
}, { meta: { internal_call: true } });
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
const parsedOutput = schema_1.sendPartnerNoteOutputSchema.safeParse(output);
|
|
310
|
+
if (!parsedOutput.success) {
|
|
311
|
+
if (useQueuedGatewayDelivery) {
|
|
312
|
+
writeJson(res, 500, {
|
|
313
|
+
error: "Invalid queued gateway partner-note response",
|
|
314
|
+
details: parsedOutput.error.issues,
|
|
315
|
+
output,
|
|
316
|
+
});
|
|
317
|
+
return true;
|
|
318
|
+
}
|
|
319
|
+
const fallback = buildPartnerNoteOutputFallback(input, output);
|
|
320
|
+
writeJson(res, 200, fallback);
|
|
321
|
+
return true;
|
|
322
|
+
}
|
|
323
|
+
writeJson(res, 200, parsedOutput.data);
|
|
324
|
+
return true;
|
|
325
|
+
}
|
|
326
|
+
catch (error) {
|
|
327
|
+
writeJson(res, 400, {
|
|
328
|
+
error: error instanceof Error ? error.message : String(error),
|
|
329
|
+
});
|
|
330
|
+
return true;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
if (pathname === "/gateway/live/request-approval") {
|
|
334
|
+
if (req.method !== "POST") {
|
|
335
|
+
writeText(res, 405, "Method not allowed");
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
try {
|
|
339
|
+
const body = (await this.readJsonBody(req));
|
|
340
|
+
const clientUuid = typeof body.client_uuid === "string" ? body.client_uuid.trim() : "";
|
|
341
|
+
const payload = body.payload && typeof body.payload === "object"
|
|
342
|
+
? body.payload
|
|
343
|
+
: null;
|
|
344
|
+
if (!clientUuid || !payload) {
|
|
345
|
+
writeJson(res, 400, { error: "client_uuid and payload are required" });
|
|
346
|
+
return true;
|
|
347
|
+
}
|
|
348
|
+
const result = await this.callBroker("telegramMcp.gatewaySocket.notifyLiveApprovalRequest", {
|
|
349
|
+
clientUuid,
|
|
350
|
+
payload,
|
|
351
|
+
}, { meta: { internal_call: true } });
|
|
352
|
+
writeJson(res, 200, { delivered: Boolean(result?.delivered) });
|
|
353
|
+
return true;
|
|
354
|
+
}
|
|
355
|
+
catch (error) {
|
|
356
|
+
writeJson(res, 400, {
|
|
357
|
+
error: error instanceof Error ? error.message : String(error),
|
|
358
|
+
});
|
|
359
|
+
return true;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
if (pathname === "/gateway/live/resolve-approval") {
|
|
363
|
+
if (req.method !== "POST") {
|
|
364
|
+
writeText(res, 405, "Method not allowed");
|
|
365
|
+
return true;
|
|
366
|
+
}
|
|
367
|
+
try {
|
|
368
|
+
const body = (await this.readJsonBody(req));
|
|
369
|
+
const clientUuid = typeof body.client_uuid === "string" ? body.client_uuid.trim() : "";
|
|
370
|
+
const approved = body.approved === true;
|
|
371
|
+
const payload = body.payload && typeof body.payload === "object"
|
|
372
|
+
? body.payload
|
|
373
|
+
: null;
|
|
374
|
+
if (!clientUuid || !payload) {
|
|
375
|
+
writeJson(res, 400, { error: "client_uuid and payload are required" });
|
|
376
|
+
return true;
|
|
377
|
+
}
|
|
378
|
+
const result = await this.callBroker("telegramMcp.gatewaySocket.notifyLiveApprovalResolved", {
|
|
379
|
+
clientUuid,
|
|
380
|
+
approved,
|
|
381
|
+
payload,
|
|
382
|
+
}, { meta: { internal_call: true } });
|
|
383
|
+
writeJson(res, 200, { delivered: Boolean(result?.delivered) });
|
|
384
|
+
return true;
|
|
385
|
+
}
|
|
386
|
+
catch (error) {
|
|
387
|
+
writeJson(res, 400, {
|
|
388
|
+
error: error instanceof Error ? error.message : String(error),
|
|
389
|
+
});
|
|
390
|
+
return true;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
if (pathname === "/gateway/client/register") {
|
|
394
|
+
if (req.method !== "POST") {
|
|
395
|
+
writeText(res, 405, "Method not allowed");
|
|
396
|
+
return true;
|
|
397
|
+
}
|
|
398
|
+
try {
|
|
399
|
+
const body = (await this.readJsonBody(req));
|
|
400
|
+
const result = await this.callBroker("telegramMcp.gateway.registerClient", body, { meta: { internal_call: true } });
|
|
401
|
+
writeJson(res, 200, result);
|
|
402
|
+
return true;
|
|
403
|
+
}
|
|
404
|
+
catch (error) {
|
|
405
|
+
writeJson(res, 400, {
|
|
406
|
+
error: error instanceof Error ? error.message : String(error),
|
|
407
|
+
});
|
|
408
|
+
return true;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
if (pathname === "/gateway/projects/create") {
|
|
412
|
+
if (req.method !== "POST") {
|
|
413
|
+
writeText(res, 405, "Method not allowed");
|
|
414
|
+
return true;
|
|
415
|
+
}
|
|
416
|
+
try {
|
|
417
|
+
const body = (await this.readJsonBody(req));
|
|
418
|
+
const result = await this.callBroker("telegramMcp.gateway.createProject", body, { meta: { internal_call: true } });
|
|
419
|
+
writeJson(res, 200, result);
|
|
420
|
+
return true;
|
|
421
|
+
}
|
|
422
|
+
catch (error) {
|
|
423
|
+
writeJson(res, 400, {
|
|
424
|
+
error: error instanceof Error ? error.message : String(error),
|
|
425
|
+
});
|
|
426
|
+
return true;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
if (pathname === "/gateway/projects/join") {
|
|
430
|
+
if (req.method !== "POST") {
|
|
431
|
+
writeText(res, 405, "Method not allowed");
|
|
432
|
+
return true;
|
|
433
|
+
}
|
|
434
|
+
try {
|
|
435
|
+
const body = (await this.readJsonBody(req));
|
|
436
|
+
const result = await this.callBroker("telegramMcp.gateway.joinProject", body, { meta: { internal_call: true } });
|
|
437
|
+
if (Array.isArray(result.notify_client_uuids) &&
|
|
438
|
+
result.notify_client_uuids.length > 0 &&
|
|
439
|
+
typeof result.project_uuid === "string" &&
|
|
440
|
+
typeof result.name === "string") {
|
|
441
|
+
const publishResult = await this.callBroker("telegramMcp.gatewayRmq.publishProjectMemberJoined", {
|
|
442
|
+
clientUuids: result.notify_client_uuids,
|
|
443
|
+
projectUuid: result.project_uuid,
|
|
444
|
+
projectName: result.name,
|
|
445
|
+
memberDisplayName: typeof result.member_display_name === "string"
|
|
446
|
+
? result.member_display_name
|
|
447
|
+
: undefined,
|
|
448
|
+
memberTelegramUsername: typeof result.member_telegram_username === "string"
|
|
449
|
+
? result.member_telegram_username
|
|
450
|
+
: undefined,
|
|
451
|
+
}, { meta: { internal_call: true } });
|
|
452
|
+
if (!publishResult?.published) {
|
|
453
|
+
await this.callBroker("telegramMcp.gatewaySocket.notifyProjectMemberJoined", {
|
|
454
|
+
clientUuids: result.notify_client_uuids,
|
|
455
|
+
projectUuid: result.project_uuid,
|
|
456
|
+
projectName: result.name,
|
|
457
|
+
memberDisplayName: typeof result.member_display_name === "string"
|
|
458
|
+
? result.member_display_name
|
|
459
|
+
: undefined,
|
|
460
|
+
memberTelegramUsername: typeof result.member_telegram_username === "string"
|
|
461
|
+
? result.member_telegram_username
|
|
462
|
+
: undefined,
|
|
463
|
+
}, { meta: { internal_call: true } });
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
writeJson(res, 200, result);
|
|
467
|
+
return true;
|
|
468
|
+
}
|
|
469
|
+
catch (error) {
|
|
470
|
+
writeJson(res, 400, {
|
|
471
|
+
error: error instanceof Error ? error.message : String(error),
|
|
472
|
+
});
|
|
473
|
+
return true;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
if (pathname === "/gateway/sessions/register") {
|
|
477
|
+
if (req.method !== "POST") {
|
|
478
|
+
writeText(res, 405, "Method not allowed");
|
|
479
|
+
return true;
|
|
480
|
+
}
|
|
481
|
+
try {
|
|
482
|
+
const body = (await this.readJsonBody(req));
|
|
483
|
+
const result = await this.callBroker("telegramMcp.gateway.registerSession", body, { meta: { internal_call: true } });
|
|
484
|
+
writeJson(res, 200, result);
|
|
485
|
+
return true;
|
|
486
|
+
}
|
|
487
|
+
catch (error) {
|
|
488
|
+
writeJson(res, 400, {
|
|
489
|
+
error: error instanceof Error ? error.message : String(error),
|
|
490
|
+
});
|
|
491
|
+
return true;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
if (pathname === "/gateway/sessions/unregister") {
|
|
495
|
+
if (req.method !== "POST") {
|
|
496
|
+
writeText(res, 405, "Method not allowed");
|
|
497
|
+
return true;
|
|
498
|
+
}
|
|
499
|
+
try {
|
|
500
|
+
const body = (await this.readJsonBody(req));
|
|
501
|
+
const result = await this.callBroker("telegramMcp.gateway.unregisterSession", body, { meta: { internal_call: true } });
|
|
502
|
+
writeJson(res, 200, result);
|
|
503
|
+
return true;
|
|
504
|
+
}
|
|
505
|
+
catch (error) {
|
|
506
|
+
writeJson(res, 400, {
|
|
507
|
+
error: error instanceof Error ? error.message : String(error),
|
|
508
|
+
});
|
|
509
|
+
return true;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
if (pathname === "/gateway/projects/list") {
|
|
513
|
+
if (req.method !== "POST") {
|
|
514
|
+
writeText(res, 405, "Method not allowed");
|
|
515
|
+
return true;
|
|
516
|
+
}
|
|
517
|
+
try {
|
|
518
|
+
const body = (await this.readJsonBody(req));
|
|
519
|
+
const result = await this.callBroker("telegramMcp.gateway.listProjects", body, { meta: { internal_call: true } });
|
|
520
|
+
writeJson(res, 200, result);
|
|
521
|
+
return true;
|
|
522
|
+
}
|
|
523
|
+
catch (error) {
|
|
524
|
+
writeJson(res, 400, {
|
|
525
|
+
error: error instanceof Error ? error.message : String(error),
|
|
526
|
+
});
|
|
527
|
+
return true;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
if (pathname === "/gateway/history/list") {
|
|
531
|
+
if (req.method !== "POST") {
|
|
532
|
+
writeText(res, 405, "Method not allowed");
|
|
533
|
+
return true;
|
|
534
|
+
}
|
|
535
|
+
try {
|
|
536
|
+
const body = (await this.readJsonBody(req));
|
|
537
|
+
const result = await this.callBroker("telegramMcp.gateway.listSessionHistory", body, { meta: { internal_call: true } });
|
|
538
|
+
writeJson(res, 200, result);
|
|
539
|
+
return true;
|
|
540
|
+
}
|
|
541
|
+
catch (error) {
|
|
542
|
+
writeJson(res, 400, {
|
|
543
|
+
error: error instanceof Error ? error.message : String(error),
|
|
544
|
+
});
|
|
545
|
+
return true;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
if (pathname === "/gateway/projects/leave") {
|
|
549
|
+
if (req.method !== "POST") {
|
|
550
|
+
writeText(res, 405, "Method not allowed");
|
|
551
|
+
return true;
|
|
552
|
+
}
|
|
553
|
+
try {
|
|
554
|
+
const body = (await this.readJsonBody(req));
|
|
555
|
+
const result = await this.callBroker("telegramMcp.gateway.leaveProject", body, { meta: { internal_call: true } });
|
|
556
|
+
if (result.left === true &&
|
|
557
|
+
Array.isArray(result.notify_client_uuids) &&
|
|
558
|
+
result.notify_client_uuids.length > 0 &&
|
|
559
|
+
typeof result.project_uuid === "string" &&
|
|
560
|
+
typeof result.project_name === "string") {
|
|
561
|
+
const publishResult = await this.callBroker("telegramMcp.gatewayRmq.publishProjectMemberLeft", {
|
|
562
|
+
clientUuids: result.notify_client_uuids,
|
|
563
|
+
projectUuid: result.project_uuid,
|
|
564
|
+
projectName: result.project_name,
|
|
565
|
+
memberDisplayName: typeof result.member_display_name === "string"
|
|
566
|
+
? result.member_display_name
|
|
567
|
+
: undefined,
|
|
568
|
+
memberTelegramUsername: typeof result.member_telegram_username === "string"
|
|
569
|
+
? result.member_telegram_username
|
|
570
|
+
: undefined,
|
|
571
|
+
}, { meta: { internal_call: true } });
|
|
572
|
+
if (!publishResult?.published) {
|
|
573
|
+
await this.callBroker("telegramMcp.gatewaySocket.notifyProjectMemberLeft", {
|
|
574
|
+
clientUuids: result.notify_client_uuids,
|
|
575
|
+
projectUuid: result.project_uuid,
|
|
576
|
+
projectName: result.project_name,
|
|
577
|
+
memberDisplayName: typeof result.member_display_name === "string"
|
|
578
|
+
? result.member_display_name
|
|
579
|
+
: undefined,
|
|
580
|
+
memberTelegramUsername: typeof result.member_telegram_username === "string"
|
|
581
|
+
? result.member_telegram_username
|
|
582
|
+
: undefined,
|
|
583
|
+
}, { meta: { internal_call: true } });
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
writeJson(res, 200, result);
|
|
587
|
+
return true;
|
|
588
|
+
}
|
|
589
|
+
catch (error) {
|
|
590
|
+
writeJson(res, 400, {
|
|
591
|
+
error: error instanceof Error ? error.message : String(error),
|
|
592
|
+
});
|
|
593
|
+
return true;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
if (pathname === "/gateway/projects/delete") {
|
|
597
|
+
if (req.method !== "POST") {
|
|
598
|
+
writeText(res, 405, "Method not allowed");
|
|
599
|
+
return true;
|
|
600
|
+
}
|
|
601
|
+
try {
|
|
602
|
+
const body = (await this.readJsonBody(req));
|
|
603
|
+
const result = await this.callBroker("telegramMcp.gateway.deleteProject", body, { meta: { internal_call: true } });
|
|
604
|
+
if (result.deleted === true &&
|
|
605
|
+
Array.isArray(result.notify_client_uuids) &&
|
|
606
|
+
result.notify_client_uuids.length > 0 &&
|
|
607
|
+
typeof result.project_uuid === "string" &&
|
|
608
|
+
typeof result.project_name === "string") {
|
|
609
|
+
const publishResult = await this.callBroker("telegramMcp.gatewayRmq.publishProjectDeleted", {
|
|
610
|
+
clientUuids: result.notify_client_uuids,
|
|
611
|
+
projectUuid: result.project_uuid,
|
|
612
|
+
projectName: result.project_name,
|
|
613
|
+
}, { meta: { internal_call: true } });
|
|
614
|
+
if (!publishResult?.published) {
|
|
615
|
+
await this.callBroker("telegramMcp.gatewaySocket.notifyProjectDeleted", {
|
|
616
|
+
clientUuids: result.notify_client_uuids,
|
|
617
|
+
projectUuid: result.project_uuid,
|
|
618
|
+
projectName: result.project_name,
|
|
619
|
+
}, { meta: { internal_call: true } });
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
writeJson(res, 200, result);
|
|
623
|
+
return true;
|
|
624
|
+
}
|
|
625
|
+
catch (error) {
|
|
626
|
+
writeJson(res, 400, {
|
|
627
|
+
error: error instanceof Error ? error.message : String(error),
|
|
628
|
+
});
|
|
629
|
+
return true;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
if (pathname === "/gateway/projects/sessions") {
|
|
633
|
+
if (req.method !== "POST") {
|
|
634
|
+
writeText(res, 405, "Method not allowed");
|
|
635
|
+
return true;
|
|
636
|
+
}
|
|
637
|
+
try {
|
|
638
|
+
const body = (await this.readJsonBody(req));
|
|
639
|
+
const result = await this.callBroker("telegramMcp.gateway.listProjectSessions", body, { meta: { internal_call: true } });
|
|
640
|
+
writeJson(res, 200, result);
|
|
641
|
+
return true;
|
|
642
|
+
}
|
|
643
|
+
catch (error) {
|
|
644
|
+
writeJson(res, 400, {
|
|
645
|
+
error: error instanceof Error ? error.message : String(error),
|
|
646
|
+
});
|
|
647
|
+
return true;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
writeJson(res, 501, {
|
|
651
|
+
error: "Distributed gateway relay is scaffolded but not implemented yet in this build.",
|
|
652
|
+
mode: this.config.distributed.mode,
|
|
653
|
+
});
|
|
654
|
+
return true;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
exports.GatewayHttpService = GatewayHttpService;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveGatewayInReplyTo = resolveGatewayInReplyTo;
|
|
4
|
+
function normalizeOptionalText(value) {
|
|
5
|
+
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
6
|
+
}
|
|
7
|
+
async function resolveGatewayInReplyTo(inReplyTo, deps) {
|
|
8
|
+
const candidate = normalizeOptionalText(inReplyTo);
|
|
9
|
+
if (!candidate) {
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
const direct = normalizeOptionalText(await deps.findMessageUuidByMessageUuid(candidate));
|
|
13
|
+
if (direct) {
|
|
14
|
+
return direct;
|
|
15
|
+
}
|
|
16
|
+
return normalizeOptionalText(await deps.findMessageUuidByShareId(candidate));
|
|
17
|
+
}
|