@deadragdoll/tellymcp 0.0.13 → 0.0.15

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.
Files changed (86) hide show
  1. package/.env.example.client +23 -39
  2. package/.env.example.gateway +52 -61
  3. package/CHANGELOG.md +57 -0
  4. package/README-ru.md +80 -6
  5. package/README.md +80 -6
  6. package/TOOLS.md +219 -10
  7. package/config/templates/env.both.template +19 -7
  8. package/config/templates/env.client.template +9 -19
  9. package/config/templates/env.gateway.template +19 -31
  10. package/dist/cli.js +252 -47
  11. package/dist/configureServer.js +966 -0
  12. package/dist/envMigration.js +316 -0
  13. package/dist/moleculer.config.js +1 -3
  14. package/dist/services/features/telegram-mcp/approval.service.js +1 -1
  15. package/dist/services/features/telegram-mcp/browser.service.js +18 -0
  16. package/dist/services/features/telegram-mcp/collaboration.service.js +2 -2
  17. package/dist/services/features/telegram-mcp/ensuredb.service.js +1 -1
  18. package/dist/services/features/telegram-mcp/file-content.service.js +94 -0
  19. package/dist/services/features/telegram-mcp/gateway-delivery.service.js +5 -1
  20. package/dist/services/features/telegram-mcp/gateway-socket.service.js +43 -11
  21. package/dist/services/features/telegram-mcp/gateway.service.js +1 -1
  22. package/dist/services/features/telegram-mcp/mcp-http.service.js +1 -0
  23. package/dist/services/features/telegram-mcp/mcp-server.service.js +20 -0
  24. package/dist/services/features/telegram-mcp/session-context.service.js +25 -1
  25. package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +79 -67
  26. package/dist/services/features/telegram-mcp/src/app/config/env.js +129 -38
  27. package/dist/services/features/telegram-mcp/src/app/config/environmentContract.js +66 -0
  28. package/dist/services/features/telegram-mcp/src/app/http.js +139 -99
  29. package/dist/services/features/telegram-mcp/src/app/oauthFacade.js +642 -0
  30. package/dist/services/features/telegram-mcp/src/app/webapp/assets.js +151 -170
  31. package/dist/services/features/telegram-mcp/src/app/webapp/auth.js +96 -99
  32. package/dist/services/features/telegram-mcp/src/entities/request/model/schema.js +88 -19
  33. package/dist/services/features/telegram-mcp/src/features/browser/model/browserAttachActiveTabTool.js +28 -0
  34. package/dist/services/features/telegram-mcp/src/features/browser/model/browserAttachTabTool.js +28 -0
  35. package/dist/services/features/telegram-mcp/src/features/browser/model/browserDetachTabTool.js +28 -0
  36. package/dist/services/features/telegram-mcp/src/features/browser/model/browserListAttachedInstancesTool.js +1 -1
  37. package/dist/services/features/telegram-mcp/src/features/browser/model/browserListTabsTool.js +1 -1
  38. package/dist/services/features/telegram-mcp/src/features/browser/model/browserService.js +412 -29
  39. package/dist/services/features/telegram-mcp/src/features/browser-attach/model/browserRecordingBundle.js +37 -3
  40. package/dist/services/features/telegram-mcp/src/features/browser-attach/model/firefoxAttachRegistry.js +7 -6
  41. package/dist/services/features/telegram-mcp/src/features/browser-attach/model/firefoxAttachServer.js +214 -37
  42. package/dist/services/features/telegram-mcp/src/features/browser-attach/model/types.js +186 -0
  43. package/dist/services/features/telegram-mcp/src/features/collaboration/model/collaborationService.js +2 -0
  44. package/dist/services/features/telegram-mcp/src/features/collaboration/model/gatewaySessionsService.js +5 -5
  45. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileService.js +6 -3
  46. package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayClientAccess.js +5 -2
  47. package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayCollaborationBackend.js +4 -4
  48. package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayHttpService.js +33 -36
  49. package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/remoteConsoleActionClient.js +4 -3
  50. package/dist/services/features/telegram-mcp/src/features/file-content/model/getFileListTool.js +33 -0
  51. package/dist/services/features/telegram-mcp/src/features/file-content/model/getFileService.js +327 -0
  52. package/dist/services/features/telegram-mcp/src/features/file-content/model/getFileTool.js +81 -0
  53. package/dist/services/features/telegram-mcp/src/features/file-content/model/temporaryFileLinkStore.js +307 -0
  54. package/dist/services/features/telegram-mcp/src/features/file-content/model/workspaceFilePolicy.js +115 -0
  55. package/dist/services/features/telegram-mcp/src/features/notify/model/notifyService.js +9 -5
  56. package/dist/services/features/telegram-mcp/src/features/session-context/model/getRuntimeDiagnosticsTool.js +30 -0
  57. package/dist/services/features/telegram-mcp/src/features/session-context/model/sessionContextService.js +169 -7
  58. package/dist/services/features/telegram-mcp/src/shared/integrations/memory/processLocalStateStore.js +260 -0
  59. package/dist/services/features/telegram-mcp/src/shared/integrations/object-storage/minioExchangeStore.js +1 -1
  60. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +4 -1
  61. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConsoleRegistry.js +2 -2
  62. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportFileHandoffActions.js +6 -3
  63. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMessageFlow.js +1 -1
  64. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectState.js +2 -2
  65. package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/client.js +29 -6
  66. package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/ptyRegistry.js +100 -2
  67. package/dist/services/features/telegram-mcp/src/shared/lib/bodyLimits.js +63 -0
  68. package/dist/services/features/telegram-mcp/src/shared/lib/gatewayAuth.js +13 -0
  69. package/dist/services/features/telegram-mcp/src/shared/lib/gatewayScope.js +5 -5
  70. package/dist/services/features/telegram-mcp/src/shared/lib/project-identity/projectIdentity.js +10 -0
  71. package/dist/services/features/telegram-mcp/src/shared/lib/time/localTimestamp.js +21 -0
  72. package/docs/CHAT_CONNECTOR.md +134 -0
  73. package/docs/STANDALONE-ru.md +41 -3
  74. package/docs/STANDALONE.md +41 -3
  75. package/package.json +5 -3
  76. package/packages/chrome-attach-extension/dist/background.js +572 -163
  77. package/packages/chrome-attach-extension/dist/manifest.json +2 -1
  78. package/packages/chrome-attach-extension/dist/options.js +15 -2
  79. package/packages/chrome-attach-extension/dist/recorder-content.js +14 -1
  80. package/packages/chrome-attach-extension/dist/recorder-page.js +34 -18
  81. package/packages/firefox-attach-extension/dist/background.js +413 -33
  82. package/packages/firefox-attach-extension/dist/manifest.json +0 -12
  83. package/packages/firefox-attach-extension/dist/options.js +14 -1
  84. package/packages/firefox-attach-extension/dist/recorder-content.js +14 -1
  85. package/packages/firefox-attach-extension/dist/recorder-page.js +34 -18
  86. package/scripts/postinstall.js +33 -1
@@ -0,0 +1,316 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.migrateEnvironmentContent = migrateEnvironmentContent;
4
+ const dotenv_1 = require("dotenv");
5
+ const environmentContract_1 = require("./services/features/telegram-mcp/src/app/config/environmentContract");
6
+ const allRoles = ["client", "gateway", "both"];
7
+ const gatewayRoles = ["gateway", "both"];
8
+ const clientRoles = ["client", "both"];
9
+ const environmentSections = [
10
+ {
11
+ title: "Runtime role and request policy",
12
+ roles: allRoles,
13
+ keys: ["DISTRIBUTED_MODE", "TELEGRAM_REQUEST_MODE"],
14
+ },
15
+ {
16
+ title: "Workspace identity",
17
+ roles: clientRoles,
18
+ keys: [
19
+ "PROJECT_NAME",
20
+ "TELLYMCP_SESSION_ID",
21
+ "TELLYMCP_SESSION_LABEL",
22
+ "GATEWAY_USER_UUID",
23
+ ],
24
+ },
25
+ {
26
+ title: "Gateway connection and scope",
27
+ roles: allRoles,
28
+ keys: [
29
+ "GATEWAY_PUBLIC_URL",
30
+ "GATEWAY_WS_URL",
31
+ "GATEWAY_WS_PATH",
32
+ "GATEWAY_SCOPE_TOKEN",
33
+ "GATEWAY_AUTH_TOKEN",
34
+ ],
35
+ },
36
+ {
37
+ title: "Telegram gateway",
38
+ roles: gatewayRoles,
39
+ keys: [
40
+ "TELEGRAM_BOT_TOKEN",
41
+ "TELEGRAM_BOT_USERNAME",
42
+ "ADMIN_TOKEN",
43
+ "DEBUG_LANGUAGE",
44
+ "TELEGRAM_POLL_INTERVAL_MS",
45
+ "TELEGRAM_DEFAULT_TIMEOUT_SECONDS",
46
+ "TELEGRAM_MAX_CONTEXT_CHARS",
47
+ "TELEGRAM_MAX_QUESTION_CHARS",
48
+ "TELEGRAM_MAX_MESSAGE_CHARS",
49
+ "TELEGRAM_MENU_PAYLOAD_TTL_SECONDS",
50
+ "TELEGRAM_WEBHOOK_ENABLED",
51
+ "TELEGRAM_WEBHOOK_PATH",
52
+ "TELEGRAM_WEBHOOK_PUBLIC_URL",
53
+ "TELEGRAM_WEBHOOK_SECRET",
54
+ "TELEGRAM_WEBHOOK_TRACE",
55
+ "TELEGRAM_WEBHOOK_DROP_PENDING_UPDATES",
56
+ ],
57
+ },
58
+ {
59
+ title: "Redis",
60
+ roles: gatewayRoles,
61
+ keys: [
62
+ "REDIS_HOST",
63
+ "REDIS_PORT",
64
+ "REDIS_DB",
65
+ "REDIS_USERNAME",
66
+ "REDIS_PASSWORD",
67
+ ],
68
+ },
69
+ {
70
+ title: "PostgreSQL gateway metadata",
71
+ roles: gatewayRoles,
72
+ keys: [
73
+ "DB_HOST",
74
+ "DB_PORT",
75
+ "DB_USER",
76
+ "DB_PASSWORD",
77
+ "DB_NAME",
78
+ "DB_SCHEMA",
79
+ ],
80
+ },
81
+ {
82
+ title: "Standalone HTTP and MCP",
83
+ roles: allRoles,
84
+ keys: [
85
+ "ROOT_PREFIX",
86
+ "PORT",
87
+ "MCP_HTTP_HOST",
88
+ "MCP_HTTP_PORT",
89
+ "MCP_HTTP_PATH",
90
+ "MCP_HTTP_BEARER_TOKEN",
91
+ "MCP_HTTP_ENABLE_DEBUG_ROUTES",
92
+ "MCP_HTTP_ENABLE_PRUNE_ROUTE",
93
+ "MCP_XCHANGE_DIR",
94
+ ],
95
+ },
96
+ {
97
+ title: "Chat connector OAuth",
98
+ roles: gatewayRoles,
99
+ keys: [
100
+ "TELLYMCP_PUBLIC_URL",
101
+ "TELLYMCP_OAUTH_ISSUER",
102
+ "TELLYMCP_OAUTH_AUDIENCE",
103
+ "TELLYMCP_MAGIC_TOKEN",
104
+ "TELLYMCP_MAGIC_TOKEN_HASH",
105
+ "TELLYMCP_OAUTH_CLIENT_ID",
106
+ "TELLYMCP_OAUTH_CLIENT_SECRET",
107
+ "TELLYMCP_ALLOWED_REDIRECT_URIS",
108
+ "TELLYMCP_OAUTH_PRIVATE_KEY_PEM",
109
+ "TELLYMCP_AUTH_CODE_TTL_SECONDS",
110
+ "TELLYMCP_OAUTH_SCOPES",
111
+ "TELLYMCP_OAUTH_KEY_ID",
112
+ ],
113
+ },
114
+ {
115
+ title: "RabbitMQ fanout",
116
+ roles: gatewayRoles,
117
+ keys: [
118
+ "RMQ_HOST",
119
+ "RMQ_PORT",
120
+ "RMQ_USER",
121
+ "RMQ_PASSWORD",
122
+ "RMQ_VHOST",
123
+ "RMQ_EXCHANGE",
124
+ ],
125
+ },
126
+ {
127
+ title: "Telegram Mini App",
128
+ roles: gatewayRoles,
129
+ keys: [
130
+ "WEBAPP_ENABLED",
131
+ "WEBAPP_BASE_PATH",
132
+ "WEBAPP_PUBLIC_URL",
133
+ "WEBAPP_INITDATA_TTL_SECONDS",
134
+ "WEBAPP_SESSION_TTL_SECONDS",
135
+ "WEBAPP_LAUNCH_MODE",
136
+ "WEBAPP_VISIBLE_SCREENS",
137
+ "WEBAPP_ACTION_COOLDOWN_MS",
138
+ ],
139
+ },
140
+ {
141
+ title: "Built-in PTY terminal",
142
+ roles: clientRoles,
143
+ keys: [
144
+ "TERMINAL_SHELL",
145
+ "TERMINAL_COLS",
146
+ "TERMINAL_ROWS",
147
+ "TERMINAL_SCROLLBACK_LINES",
148
+ "TERMINAL_NUDGE_ENABLED",
149
+ "TERMINAL_NUDGE_DEBOUNCE_SECONDS",
150
+ "TERMINAL_NUDGE_COOLDOWN_SECONDS",
151
+ "TERMINAL_NUDGE_MESSAGE",
152
+ "TERMINAL_PARTNER_NUDGE_MESSAGE",
153
+ "TERMINAL_PARTNER_REPLY_NUDGE_MESSAGE",
154
+ "TERMINAL_CAPTURE_MODE",
155
+ "TERMINAL_CAPTURE_LINES",
156
+ "TERMINAL_PROMPT_SCAN_ENABLED",
157
+ "TERMINAL_PROMPT_SCAN_INTERVAL_SECONDS",
158
+ "TERMINAL_PROMPT_SCAN_COOLDOWN_SECONDS",
159
+ "TERMINAL_PROMPT_SCAN_STRATEGY",
160
+ "TERMINAL_PROMPT_SCAN_MIN_SCORE",
161
+ ],
162
+ },
163
+ {
164
+ title: "Gateway-side prompt detection",
165
+ roles: ["gateway"],
166
+ keys: [
167
+ "TERMINAL_PROMPT_SCAN_ENABLED",
168
+ "TERMINAL_PROMPT_SCAN_INTERVAL_SECONDS",
169
+ "TERMINAL_PROMPT_SCAN_COOLDOWN_SECONDS",
170
+ "TERMINAL_PROMPT_SCAN_STRATEGY",
171
+ "TERMINAL_PROMPT_SCAN_MIN_SCORE",
172
+ ],
173
+ },
174
+ {
175
+ title: "Browser automation",
176
+ roles: clientRoles,
177
+ keys: [
178
+ "BROWSER_ENABLED",
179
+ "BROWSER_HEADLESS",
180
+ "BROWSER_DEVTOOLS",
181
+ "BROWSER_ADDRESS",
182
+ "BROWSER_TIMEOUT_MS",
183
+ "BROWSER_MAX_EVENTS",
184
+ "BROWSER_WAIT_UNTIL",
185
+ "BROWSER_EXECUTABLE_PATH",
186
+ "BROWSER_CHANNEL",
187
+ "BROWSER_SLOW_MO_MS",
188
+ "BROWSER_ATTACH_ENABLED",
189
+ "BROWSER_ATTACH_WS_HOST",
190
+ "BROWSER_ATTACH_WS_PORT",
191
+ "BROWSER_ATTACH_WS_PATH",
192
+ ],
193
+ },
194
+ {
195
+ title: "Outbound proxy",
196
+ roles: allRoles,
197
+ keys: ["PROXY_USE", "HTTP_PROXY", "SOCKS5_PROXY", "NO_PROXY"],
198
+ },
199
+ {
200
+ title: "Moleculer identity and diagnostics",
201
+ roles: allRoles,
202
+ keys: [
203
+ "NAMESPACE",
204
+ "NODE_ID",
205
+ "TRANSPORT",
206
+ "MOLECULER_TRACE",
207
+ "MOLECULER_METRICS",
208
+ "METRICS_PORT",
209
+ "METRICS_PATH",
210
+ ],
211
+ },
212
+ {
213
+ title: "Logging",
214
+ roles: allRoles,
215
+ keys: [
216
+ "LOG_LEVEL",
217
+ "LOG_STDERR_LEVEL",
218
+ "LOG_FILE_ENABLED",
219
+ "LOG_FILE_LEVEL",
220
+ "LOG_FILE_PATH",
221
+ "LOGFEED_ENABLED",
222
+ "LOGFEED_LEVEL",
223
+ "LOGFEED_BUFFER_SIZE",
224
+ ],
225
+ },
226
+ ];
227
+ function inferRole(environment) {
228
+ const configuredMode = environment.DISTRIBUTED_MODE?.trim();
229
+ if (configuredMode === "client" ||
230
+ configuredMode === "gateway" ||
231
+ configuredMode === "both") {
232
+ return configuredMode;
233
+ }
234
+ if (configuredMode) {
235
+ throw new Error(`DISTRIBUTED_MODE must be client, gateway, or both; received ${configuredMode}.`);
236
+ }
237
+ return environment.TELEGRAM_BOT_TOKEN ||
238
+ environment.DB_HOST ||
239
+ environment.ROOT_PREFIX ||
240
+ environment.PORT
241
+ ? "gateway"
242
+ : "client";
243
+ }
244
+ function formatEnvironmentValue(value) {
245
+ if (/^[A-Za-z0-9_./:@%+,?&=-]*$/u.test(value)) {
246
+ return value;
247
+ }
248
+ return JSON.stringify(value);
249
+ }
250
+ function migrateEnvironmentContent(source) {
251
+ const parsed = (0, dotenv_1.parse)(source);
252
+ const normalized = { ...parsed };
253
+ const renamedKeys = [];
254
+ const handledLegacyKeys = new Set();
255
+ for (const [from, to] of Object.entries(environmentContract_1.LEGACY_ENV_RENAMES)) {
256
+ if (!(from in parsed)) {
257
+ continue;
258
+ }
259
+ if (!(to in parsed)) {
260
+ normalized[to] = parsed[from] ?? "";
261
+ }
262
+ delete normalized[from];
263
+ handledLegacyKeys.add(from);
264
+ renamedKeys.push({ from, to });
265
+ }
266
+ for (const [name, value] of Object.entries(parsed)) {
267
+ if (!name.startsWith("TMUX_")) {
268
+ continue;
269
+ }
270
+ const replacement = (0, environmentContract_1.getTmuxReplacement)(name);
271
+ if (replacement && !(replacement in parsed)) {
272
+ normalized[replacement] = value;
273
+ renamedKeys.push({ from: name, to: replacement });
274
+ }
275
+ delete normalized[name];
276
+ handledLegacyKeys.add(name);
277
+ }
278
+ for (const name of environmentContract_1.REMOVED_ENV_KEYS) {
279
+ delete normalized[name];
280
+ }
281
+ const role = inferRole(normalized);
282
+ normalized.DISTRIBUTED_MODE = role;
283
+ const emitted = new Set();
284
+ const keptKeys = [];
285
+ const output = [
286
+ "# Generated by tellymcp migrate-env.",
287
+ `# Role: ${role}`,
288
+ "",
289
+ ];
290
+ for (const section of environmentSections) {
291
+ if (!section.roles.includes(role)) {
292
+ continue;
293
+ }
294
+ const sectionKeys = section.keys.filter((key) => key in normalized && !emitted.has(key));
295
+ if (sectionKeys.length === 0) {
296
+ continue;
297
+ }
298
+ output.push(`# ${section.title}`);
299
+ for (const key of sectionKeys) {
300
+ output.push(`${key}=${formatEnvironmentValue(normalized[key] ?? "")}`);
301
+ emitted.add(key);
302
+ keptKeys.push(key);
303
+ }
304
+ output.push("");
305
+ }
306
+ const droppedKeys = Object.keys(parsed)
307
+ .filter((key) => !emitted.has(key) && !handledLegacyKeys.has(key))
308
+ .sort();
309
+ return {
310
+ role,
311
+ content: `${output.join("\n").trimEnd()}\n`,
312
+ keptKeys,
313
+ renamedKeys,
314
+ droppedKeys,
315
+ };
316
+ }
@@ -67,9 +67,7 @@ const logger = [
67
67
  const metricsEnabled = process.env.MOLECULER_METRICS === "true";
68
68
  const metricsPort = +(process.env.METRICS_PORT || 3030);
69
69
  const metricsPath = process.env.METRICS_PATH || "/metrics";
70
- const logFeedEnabled = process.env.ENABLE_LOGFEED != null
71
- ? !["0", "false", "no", "off"].includes(process.env.ENABLE_LOGFEED.toLowerCase())
72
- : process.env.LOGFEED_ENABLED !== "false";
70
+ const logFeedEnabled = !["0", "false", "no", "off"].includes((process.env.LOGFEED_ENABLED ?? "true").toLowerCase());
73
71
  if (logFeedEnabled) {
74
72
  logger.push(new logfeed_1.LogFeedLogger({
75
73
  level: process.env.LOGFEED_LEVEL || process.env.LOG_LEVEL || "info",
@@ -26,7 +26,7 @@ const TelegramMcpApprovalService = {
26
26
  }
27
27
  const runtime = await runtimeService.waitUntilReady();
28
28
  this.logger.info("Starting telegram_mcp approval service");
29
- this.approvalOrchestrator = new orchestrator_1.HumanApprovalOrchestrator(runtime.config, runtime.stateStore, runtime.stateStore, runtime.stateStore, runtime.telegramTransport, runtime.logger, runtime.projectIdentityResolver);
29
+ this.approvalOrchestrator = new orchestrator_1.HumanApprovalOrchestrator(runtime.config, runtime.sessionStore, runtime.stateStore, runtime.stateStore, runtime.telegramTransport, runtime.logger, runtime.projectIdentityResolver);
30
30
  this.logger.info("telegram_mcp approval service is ready");
31
31
  },
32
32
  };
@@ -33,6 +33,24 @@ const TelegramMcpBrowserService = {
33
33
  return this.getBrowserService().listTabs(ctx.params);
34
34
  },
35
35
  },
36
+ attachActiveTabRemote: {
37
+ params: { $$strict: false },
38
+ async handler(ctx) {
39
+ return this.getBrowserService().attachActiveTab(ctx.params);
40
+ },
41
+ },
42
+ attachTabRemote: {
43
+ params: { $$strict: false },
44
+ async handler(ctx) {
45
+ return this.getBrowserService().attachTab(ctx.params);
46
+ },
47
+ },
48
+ detachTabRemote: {
49
+ params: { $$strict: false },
50
+ async handler(ctx) {
51
+ return this.getBrowserService().detachTab(ctx.params);
52
+ },
53
+ },
36
54
  startRecordingRemote: {
37
55
  params: { $$strict: false },
38
56
  async handler(ctx) {
@@ -78,11 +78,11 @@ const TelegramMcpCollaborationService = {
78
78
  return localBackend.sendPartnerNote(input, resolved);
79
79
  });
80
80
  const backend = runtime.config.distributed.gatewayPublicUrl
81
- ? new gatewayCollaborationBackend_1.GatewayCollaborationBackend(runtime.logger, runtime.stateStore, runtime.config.distributed.gatewayPublicUrl, runtime.config.distributed.gatewayAuthToken, runtime.config.distributed.gatewayToken, runtime.config.distributed.gatewayUserUuid, runtime.config.project.name, runtime.config.telegram.botUsername)
81
+ ? new gatewayCollaborationBackend_1.GatewayCollaborationBackend(runtime.logger, runtime.stateStore, runtime.config.distributed.gatewayPublicUrl, runtime.config.distributed.gatewayAuthToken, runtime.config.distributed.gatewayScopeToken, runtime.config.distributed.gatewayUserUuid, runtime.config.project.name, runtime.config.telegram.botUsername)
82
82
  : localBackend;
83
83
  this.collaborationService = new collaborationService_1.CollaborationService(backend, runtime.logger, runtime.projectIdentityResolver);
84
84
  this.sendPartnerFileService = new sendPartnerFileService_1.SendPartnerFileService(runtime.config, runtime.sessionStore, runtime.stateStore, runtime.logger, runtime.projectIdentityResolver, this.collaborationService, new remoteConsoleActionClient_1.RemoteConsoleActionClient((actionName, params) => this.broker.call(actionName, params, { meta: { internal_call: true } })));
85
- this.gatewaySessionsService = new gatewaySessionsService_1.GatewaySessionsService(runtime.logger, runtime.stateStore, runtime.config.distributed.gatewayPublicUrl, runtime.config.distributed.gatewayAuthToken, runtime.config.distributed.gatewayToken, runtime.config.distributed.gatewayUserUuid, runtime.config.project.name, runtime.config.telegram.botUsername);
85
+ this.gatewaySessionsService = new gatewaySessionsService_1.GatewaySessionsService(runtime.logger, runtime.stateStore, runtime.config.distributed.gatewayPublicUrl, runtime.config.distributed.gatewayAuthToken, runtime.config.distributed.gatewayScopeToken, runtime.config.distributed.gatewayUserUuid, runtime.config.project.name, runtime.config.telegram.botUsername);
86
86
  runtime.telegramTransport.setCollaborationService(this.collaborationService);
87
87
  this.logger.info("telegram_mcp collaboration service is ready");
88
88
  },
@@ -5,7 +5,7 @@ const db_1 = require("../../../lib/mixins/db");
5
5
  exports.TELEGRAM_MCP_ENSUREDB_SERVICE_NAME = "telegramMcp.ensuredb";
6
6
  const DISTRIBUTED_MODE = process.env.DISTRIBUTED_MODE || "client";
7
7
  const GATEWAY_ENABLED = DISTRIBUTED_MODE === "gateway" || DISTRIBUTED_MODE === "both";
8
- const MCP_SCHEMA = process.env.DB_SCHEME || "mcp";
8
+ const MCP_SCHEMA = process.env.DB_SCHEMA || "mcp";
9
9
  const TelegramMcpEnsureDbService = {
10
10
  name: exports.TELEGRAM_MCP_ENSUREDB_SERVICE_NAME,
11
11
  mixins: [db_1.DBMixin],
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TELEGRAM_MCP_FILE_CONTENT_SERVICE_NAME = void 0;
4
+ const runtime_service_1 = require("./runtime.service");
5
+ const remoteConsoleActionClient_1 = require("./src/features/distributed-gateway/model/remoteConsoleActionClient");
6
+ const getFileService_1 = require("./src/features/file-content/model/getFileService");
7
+ exports.TELEGRAM_MCP_FILE_CONTENT_SERVICE_NAME = "telegramMcp.fileContent";
8
+ const TelegramMcpFileContentService = {
9
+ name: exports.TELEGRAM_MCP_FILE_CONTENT_SERVICE_NAME,
10
+ dependencies: [runtime_service_1.TELEGRAM_MCP_RUNTIME_SERVICE_NAME],
11
+ actions: {
12
+ listFilesRemote: {
13
+ params: {
14
+ $$strict: false,
15
+ session_id: { type: "string", optional: true, trim: true, min: 1 },
16
+ source: {
17
+ type: "enum",
18
+ optional: true,
19
+ values: ["telegram-upload", "browser-screenshot", "partner-artifact"],
20
+ },
21
+ limit: {
22
+ type: "number",
23
+ optional: true,
24
+ integer: true,
25
+ positive: true,
26
+ max: 200,
27
+ },
28
+ },
29
+ async handler(ctx) {
30
+ return this.getGetFileService().list(ctx.params);
31
+ },
32
+ },
33
+ getFileRemote: {
34
+ params: {
35
+ $$strict: false,
36
+ session_id: { type: "string", optional: true, trim: true, min: 1 },
37
+ file_path: { type: "string", optional: true, trim: true, min: 1 },
38
+ selector: {
39
+ type: "enum",
40
+ optional: true,
41
+ values: ["latest_screenshot"],
42
+ },
43
+ type: {
44
+ type: "enum",
45
+ optional: true,
46
+ values: ["text", "base64"],
47
+ },
48
+ },
49
+ async handler(ctx) {
50
+ return this.getGetFileService().get(ctx.params);
51
+ },
52
+ },
53
+ uploadFileRemote: {
54
+ params: {
55
+ $$strict: false,
56
+ session_id: { type: "string", optional: true, trim: true, min: 1 },
57
+ file_path: { type: "string", optional: true, trim: true, min: 1 },
58
+ selector: {
59
+ type: "enum",
60
+ optional: true,
61
+ values: ["latest_screenshot"],
62
+ },
63
+ type: { type: "enum", values: ["url"] },
64
+ upload_url: { type: "string", trim: true, min: 1 },
65
+ },
66
+ async handler(ctx) {
67
+ return this.getGetFileService().upload(ctx.params);
68
+ },
69
+ },
70
+ },
71
+ created() {
72
+ this.getFileService = null;
73
+ },
74
+ methods: {
75
+ getGetFileService() {
76
+ if (!this.getFileService) {
77
+ throw new Error("telegram_mcp file content service is not initialized yet");
78
+ }
79
+ return this.getFileService;
80
+ },
81
+ },
82
+ async started() {
83
+ await this.broker.waitForServices([runtime_service_1.TELEGRAM_MCP_RUNTIME_SERVICE_NAME]);
84
+ const runtimeService = this.broker.getLocalService(runtime_service_1.TELEGRAM_MCP_RUNTIME_SERVICE_NAME);
85
+ if (!runtimeService) {
86
+ throw new Error(`Local Moleculer service '${runtime_service_1.TELEGRAM_MCP_RUNTIME_SERVICE_NAME}' is unavailable`);
87
+ }
88
+ const runtime = await runtimeService.waitUntilReady();
89
+ this.logger.info("Starting telegram_mcp file content service");
90
+ this.getFileService = new getFileService_1.GetFileService(runtime.config, runtime.sessionStore, runtime.stateStore, runtime.stateStore, runtime.logger, runtime.projectIdentityResolver, new remoteConsoleActionClient_1.RemoteConsoleActionClient((actionName, params) => this.broker.call(actionName, params, { meta: { internal_call: true } })), runtime.temporaryFileLinkStore);
91
+ this.logger.info("telegram_mcp file content service is ready");
92
+ },
93
+ };
94
+ exports.default = TelegramMcpFileContentService;
@@ -9,6 +9,7 @@ const runtime_service_1 = require("./runtime.service");
9
9
  const xchangeRecordHints_1 = require("./src/shared/lib/xchangeRecordHints");
10
10
  const client_1 = require("./src/shared/integrations/terminal/client");
11
11
  const sqliteRecordStore_1 = require("./src/shared/integrations/xchange/sqliteRecordStore");
12
+ const bodyLimits_1 = require("./src/shared/lib/bodyLimits");
12
13
  exports.TELEGRAM_MCP_GATEWAY_DELIVERY_SERVICE_NAME = "telegramMcp.gatewayDelivery";
13
14
  function renderYamlArray(values) {
14
15
  if (values.length === 0) {
@@ -319,7 +320,10 @@ const TelegramMcpGatewayDeliveryService = {
319
320
  `shares/files/${delivery.share_id}/${artifact.original_name}`;
320
321
  let localArtifactPath;
321
322
  if (artifact.content_base64) {
322
- localArtifactPath = await (0, client_1.writeXchangeRelativeFile)(runtime.config.terminal, workspaceDir, runtime.config.exchange.dir, relativePath, Buffer.from(artifact.content_base64, "base64"));
323
+ (0, bodyLimits_1.assertStringBodySize)(artifact.content_base64);
324
+ const decodedContent = Buffer.from(artifact.content_base64, "base64");
325
+ (0, bodyLimits_1.assertBodySize)(decodedContent.byteLength);
326
+ localArtifactPath = await (0, client_1.writeXchangeRelativeFile)(runtime.config.terminal, workspaceDir, runtime.config.exchange.dir, relativePath, decodedContent);
323
327
  }
324
328
  else {
325
329
  localArtifactPath = await runtime.objectStore.ensureLocalFile({
@@ -11,6 +11,8 @@ const auth_1 = require("./src/app/webapp/auth");
11
11
  const terminal_1 = require("./src/app/webapp/terminal");
12
12
  const client_1 = require("./src/shared/integrations/terminal/client");
13
13
  const gateway_loopback_1 = require("./gateway-loopback");
14
+ const gatewayAuth_1 = require("./src/shared/lib/gatewayAuth");
15
+ const bodyLimits_1 = require("./src/shared/lib/bodyLimits");
14
16
  const versionHandshake_1 = require("./src/shared/lib/version/versionHandshake");
15
17
  const wsLib = require("ws");
16
18
  const WebSocketServer = wsLib.WebSocketServer;
@@ -226,6 +228,7 @@ const TelegramMcpGatewaySocketService = {
226
228
  "bootstrap_validate",
227
229
  "view",
228
230
  "action",
231
+ "resize",
229
232
  "stream_subscribe",
230
233
  "stream_unsubscribe",
231
234
  ],
@@ -941,7 +944,6 @@ const TelegramMcpGatewaySocketService = {
941
944
  session_id: sessionId,
942
945
  session_label: session?.label ?? null,
943
946
  terminal_target: Boolean(session?.terminalTarget),
944
- poll_interval_ms: runtime.config.webapp.pollIntervalMs,
945
947
  telegram_user_id: telegramUserId,
946
948
  },
947
949
  };
@@ -1002,6 +1004,25 @@ const TelegramMcpGatewaySocketService = {
1002
1004
  },
1003
1005
  };
1004
1006
  }
1007
+ if (request.request_type === "resize") {
1008
+ const cols = typeof request.payload?.cols === "number" ? request.payload.cols : NaN;
1009
+ const rows = typeof request.payload?.rows === "number" ? request.payload.rows : NaN;
1010
+ if (!Number.isFinite(cols) || !Number.isFinite(rows)) {
1011
+ throw new Error("Terminal cols and rows are required");
1012
+ }
1013
+ const sessionId = request.local_session_id.trim();
1014
+ const session = await runtime.sessionStore.getSession(sessionId);
1015
+ if (!session?.terminalTarget || !(0, client_1.isStreamableTerminalTarget)(session.terminalTarget)) {
1016
+ throw new Error("Terminal target does not support resize");
1017
+ }
1018
+ (0, client_1.resizeForegroundTerminal)(session.terminalTarget, Math.max(20, Math.min(400, Math.round(cols))), Math.max(5, Math.min(200, Math.round(rows))));
1019
+ return {
1020
+ type: "live_response",
1021
+ request_id: request.request_id,
1022
+ ok: true,
1023
+ result: { ok: true },
1024
+ };
1025
+ }
1005
1026
  if (request.request_type === "stream_subscribe") {
1006
1027
  const streamId = typeof request.payload?.stream_id === "string"
1007
1028
  ? request.payload.stream_id.trim()
@@ -1582,7 +1603,9 @@ const TelegramMcpGatewaySocketService = {
1582
1603
  requestId,
1583
1604
  actionName,
1584
1605
  error: formattedError,
1585
- payload: parsed.payload ?? {},
1606
+ payload: actionName === "telegramMcp.fileContent.uploadFileRemote"
1607
+ ? { ...(parsed.payload ?? {}), upload_url: "[redacted]" }
1608
+ : (parsed.payload ?? {}),
1586
1609
  });
1587
1610
  this.wsClient?.send(JSON.stringify({
1588
1611
  type: "action_response",
@@ -1956,16 +1979,11 @@ const TelegramMcpGatewaySocketService = {
1956
1979
  }
1957
1980
  const httpServer = await this.waitForHttpServer?.();
1958
1981
  const wsPath = runtime.config.distributed.gatewayWsPath.replace(/\/+$/u, "") || "/";
1959
- const wsServer = new WebSocketServer({ noServer: true });
1982
+ const wsServer = new WebSocketServer({
1983
+ noServer: true,
1984
+ maxPayload: bodyLimits_1.MAX_BODY_SIZE_BYTES,
1985
+ });
1960
1986
  wsServer.on("connection", (socket, req) => {
1961
- if (runtime.config.distributed.gatewayAuthToken) {
1962
- const authorization = req.headers?.authorization;
1963
- if (authorization !==
1964
- `Bearer ${runtime.config.distributed.gatewayAuthToken}`) {
1965
- socket.close(1008, "Unauthorized");
1966
- return;
1967
- }
1968
- }
1969
1987
  runtime.logger.warn("Gateway WS client connected", {
1970
1988
  remoteAddress: req.socket.remoteAddress,
1971
1989
  path: req.url,
@@ -1977,6 +1995,11 @@ const TelegramMcpGatewaySocketService = {
1977
1995
  });
1978
1996
  });
1979
1997
  });
1998
+ socket.on("error", (error) => {
1999
+ runtime.logger.warn("Gateway WS server socket error", {
2000
+ error: error instanceof Error ? error.message : String(error),
2001
+ });
2002
+ });
1980
2003
  socket.on("close", () => {
1981
2004
  const hello = this.connectedClients?.get(socket);
1982
2005
  if (hello?.connection_id) {
@@ -2026,6 +2049,14 @@ const TelegramMcpGatewaySocketService = {
2026
2049
  if (requestPath !== wsPath) {
2027
2050
  return;
2028
2051
  }
2052
+ if (!(0, gatewayAuth_1.isGatewayAuthorizationValid)(req.headers.authorization, runtime.config.distributed.gatewayAuthToken)) {
2053
+ socket.write("HTTP/1.1 401 Unauthorized\r\n" +
2054
+ "Connection: close\r\n" +
2055
+ "Content-Length: 0\r\n" +
2056
+ "\r\n");
2057
+ socket.destroy();
2058
+ return;
2059
+ }
2029
2060
  wsServer.handleUpgrade(req, socket, head, (clientSocket) => {
2030
2061
  wsServer.emit("connection", clientSocket, req);
2031
2062
  });
@@ -2082,6 +2113,7 @@ const TelegramMcpGatewaySocketService = {
2082
2113
  const normalizedUrl = normalizeWebSocketUrl(wsUrl, runtime.config.distributed.gatewayWsPath);
2083
2114
  this.wsConnectionId = (0, node_crypto_1.randomUUID)();
2084
2115
  const socket = new wsLib.WebSocket(normalizedUrl, {
2116
+ maxPayload: bodyLimits_1.MAX_BODY_SIZE_BYTES,
2085
2117
  headers: runtime.config.distributed.gatewayAuthToken
2086
2118
  ? {
2087
2119
  authorization: `Bearer ${runtime.config.distributed.gatewayAuthToken}`,
@@ -11,7 +11,7 @@ const gatewayReplyResolution_1 = require("./src/features/distributed-gateway/mod
11
11
  const gatewayScope_1 = require("./src/shared/lib/gatewayScope");
12
12
  const ensuredb_service_1 = require("./ensuredb.service");
13
13
  exports.TELEGRAM_MCP_GATEWAY_SERVICE_NAME = "telegramMcp.gateway";
14
- const MCP_SCHEMA = process.env.DB_SCHEME || "mcp";
14
+ const MCP_SCHEMA = process.env.DB_SCHEMA || "mcp";
15
15
  const DISTRIBUTED_MODE = process.env.DISTRIBUTED_MODE || "client";
16
16
  const GATEWAY_ENABLED = DISTRIBUTED_MODE === "gateway" || DISTRIBUTED_MODE === "both";
17
17
  function trimOptionalText(value) {
@@ -69,6 +69,7 @@ const TelegramMcpHttpService = {
69
69
  path: runtime.config.mcp.httpPath,
70
70
  webappBasePath: runtime.config.webapp.basePath,
71
71
  bearerAuthEnabled: Boolean(runtime.config.mcp.bearerToken),
72
+ oauthConnectorEnabled: Boolean(runtime.config.oauth),
72
73
  });
73
74
  },
74
75
  async stopped() {