@deadragdoll/tellymcp 0.0.10 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/.env.example.client +42 -52
  2. package/.env.example.gateway +48 -62
  3. package/CHANGELOG.md +3 -3
  4. package/README-ru.md +226 -376
  5. package/README.md +213 -1184
  6. package/TOOLS.md +320 -377
  7. package/VERSION.md +13 -13
  8. package/config/codex/plugins/telly-workflows/.codex-plugin/plugin.json +18 -0
  9. package/config/codex/plugins/telly-workflows/references/invariants.md +10 -0
  10. package/config/codex/plugins/telly-workflows/skills/telly-browser-screenshot/SKILL.md +27 -0
  11. package/config/codex/plugins/telly-workflows/skills/telly-collab-artifact/SKILL.md +22 -0
  12. package/config/codex/plugins/telly-workflows/skills/telly-human-telegram/SKILL.md +31 -0
  13. package/config/codex/plugins/telly-workflows/skills/telly-partner-note/SKILL.md +36 -0
  14. package/config/templates/env.both.template +39 -20
  15. package/config/templates/env.client.template +34 -19
  16. package/config/templates/env.gateway.template +37 -22
  17. package/dist/cli.js +322 -75
  18. package/dist/codexPluginInstaller.js +215 -0
  19. package/dist/lib/mixins/session.errors.js +34 -1
  20. package/dist/lib/pinoTargets.js +2 -2
  21. package/dist/moleculer.config.js +7 -5
  22. package/dist/services/features/telegram-mcp/browser.service.js +94 -1
  23. package/dist/services/features/telegram-mcp/collaboration.service.js +40 -3
  24. package/dist/services/features/telegram-mcp/ensuredb.service.js +145 -26
  25. package/dist/services/features/telegram-mcp/gateway-delivery.service.js +285 -103
  26. package/dist/services/features/telegram-mcp/gateway-socket.service.js +907 -85
  27. package/dist/services/features/telegram-mcp/gateway.service.js +876 -81
  28. package/dist/services/features/telegram-mcp/mcp-http.service.js +8 -0
  29. package/dist/services/features/telegram-mcp/mcp-server.service.js +17 -26
  30. package/dist/services/features/telegram-mcp/notify.service.js +127 -1
  31. package/dist/services/features/telegram-mcp/session-context.service.js +28 -1
  32. package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +132 -10
  33. package/dist/services/features/telegram-mcp/src/app/config/env.js +158 -52
  34. package/dist/services/features/telegram-mcp/src/app/http.js +375 -42
  35. package/dist/services/features/telegram-mcp/src/app/webapp/assets.js +386 -58
  36. package/dist/services/features/telegram-mcp/src/app/webapp/auth.js +3 -0
  37. package/dist/services/features/telegram-mcp/src/app/webapp/terminal.js +12 -0
  38. package/dist/services/features/telegram-mcp/src/entities/request/model/schema.js +120 -104
  39. package/dist/services/features/telegram-mcp/src/entities/xchange/model/types.js +2 -0
  40. package/dist/services/features/telegram-mcp/src/features/ask-user/model/askUserTelegram.js +1 -1
  41. package/dist/services/features/telegram-mcp/src/features/browser/model/browserOpenTool.js +1 -1
  42. package/dist/services/features/telegram-mcp/src/features/browser/model/browserScreenshotTool.js +1 -1
  43. package/dist/services/features/telegram-mcp/src/features/browser/model/browserService.js +306 -26
  44. package/dist/services/features/telegram-mcp/src/features/collaboration/model/gatewaySessionsService.js +71 -0
  45. package/dist/services/features/telegram-mcp/src/features/collaboration/model/listGatewaySessionsTool.js +33 -0
  46. package/dist/services/features/telegram-mcp/src/features/collaboration/model/localCollaborationBackend.js +93 -82
  47. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileService.js +47 -5
  48. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileTool.js +1 -1
  49. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerNoteTool.js +1 -1
  50. package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayClientAccess.js +82 -0
  51. package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayCollaborationBackend.js +22 -14
  52. package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayHttpService.js +697 -75
  53. package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/remoteConsoleActionClient.js +76 -0
  54. package/dist/services/features/telegram-mcp/src/features/embedded-runtime/model/embeddedRuntimeBroker.js +92 -0
  55. package/dist/services/features/telegram-mcp/src/features/foreground-terminal/model/foregroundTerminalRuntime.js +192 -0
  56. package/dist/services/features/telegram-mcp/src/features/notify/model/notifyService.js +382 -3
  57. package/dist/services/features/telegram-mcp/src/features/notify/model/notifyTelegramTool.js +1 -1
  58. package/dist/services/features/telegram-mcp/src/features/notify/model/sendFileToTelegramTool.js +33 -0
  59. package/dist/services/features/telegram-mcp/src/features/session-context/model/clearSessionContextTool.js +1 -1
  60. package/dist/services/features/telegram-mcp/src/features/session-context/model/getSessionContextTool.js +1 -1
  61. package/dist/services/features/telegram-mcp/src/features/session-context/model/renameSessionTool.js +1 -1
  62. package/dist/services/features/telegram-mcp/src/features/session-context/model/sessionContextService.js +42 -200
  63. package/dist/services/features/telegram-mcp/src/features/session-context/model/setSessionContextTool.js +1 -1
  64. package/dist/services/features/telegram-mcp/src/features/terminal-buffer/model/terminalBufferService.js +96 -0
  65. package/dist/services/features/telegram-mcp/src/features/terminal-input/model/terminalInputService.js +97 -0
  66. package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownService.js +107 -58
  67. package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownTool.js +1 -1
  68. package/dist/services/features/telegram-mcp/src/features/xchange/model/getXchangeRecordTool.js +28 -0
  69. package/dist/services/features/telegram-mcp/src/features/xchange/model/listXchangeRecordsTool.js +28 -0
  70. package/dist/services/features/telegram-mcp/src/features/xchange/model/markXchangeRecordReadTool.js +28 -0
  71. package/dist/services/features/telegram-mcp/src/features/xchange/model/xchangeService.js +169 -0
  72. package/dist/services/features/telegram-mcp/src/processes/human-approval/model/orchestrator.js +5 -4
  73. package/dist/services/features/telegram-mcp/src/shared/i18n/resources/en.js +143 -42
  74. package/dist/services/features/telegram-mcp/src/shared/i18n/resources/ru.js +139 -38
  75. package/dist/services/features/telegram-mcp/src/shared/integrations/memory/processLocalSessionStore.js +27 -0
  76. package/dist/services/features/telegram-mcp/src/shared/integrations/object-storage/minioExchangeStore.js +11 -8
  77. package/dist/services/features/telegram-mcp/src/shared/integrations/redis/stateStore.js +69 -70
  78. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/proxyFetch.js +21 -22
  79. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +444 -7093
  80. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportAttachmentStore.js +93 -0
  81. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportBroadcastActions.js +385 -0
  82. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConsoleRegistry.js +149 -0
  83. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConstructorWiring.js +642 -0
  84. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportContent.js +84 -0
  85. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportContext.js +78 -0
  86. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportDocumentActions.js +36 -0
  87. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportEventActions.js +292 -0
  88. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportFileHandoffActions.js +352 -0
  89. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportFormatting.js +75 -0
  90. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportGatewayActions.js +44 -0
  91. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLifecycleActions.js +161 -0
  92. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLive.js +56 -0
  93. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLiveActions.js +77 -0
  94. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuCallbacks.js +254 -0
  95. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFactories.js +538 -0
  96. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFingerprints.js +93 -0
  97. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFlow.js +344 -0
  98. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuShell.js +65 -0
  99. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuState.js +408 -0
  100. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuText.js +216 -0
  101. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMessageFlow.js +452 -0
  102. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportOutputActions.js +189 -0
  103. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportPartnerActions.js +286 -0
  104. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportPayloadState.js +108 -0
  105. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectActions.js +463 -0
  106. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectEntryActions.js +202 -0
  107. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectEvents.js +99 -0
  108. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectMenus.js +138 -0
  109. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectState.js +308 -0
  110. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectView.js +426 -0
  111. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportRequestFlow.js +278 -0
  112. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportSessionActions.js +143 -0
  113. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalActions.js +665 -0
  114. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalRuntime.js +226 -0
  115. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTypes.js +2 -0
  116. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportUtils.js +330 -0
  117. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportXchangeState.js +107 -0
  118. package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/client.js +255 -0
  119. package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/ptyRegistry.js +543 -0
  120. package/dist/services/features/telegram-mcp/src/shared/integrations/xchange/sqliteRecordStore.js +223 -0
  121. package/dist/services/features/telegram-mcp/src/shared/lib/gatewayScope.js +24 -0
  122. package/dist/services/features/telegram-mcp/src/shared/lib/logger/logger.js +6 -0
  123. package/dist/services/features/telegram-mcp/src/shared/lib/project-identity/projectIdentity.js +147 -76
  124. package/dist/services/features/telegram-mcp/src/shared/lib/telegramXchangeRecords.js +72 -0
  125. package/dist/services/features/telegram-mcp/src/shared/lib/terminalPromptDetection.js +409 -0
  126. package/dist/services/features/telegram-mcp/src/shared/lib/version/versionHandshake.js +129 -1
  127. package/dist/services/features/telegram-mcp/src/shared/lib/xchangeRecordHints.js +98 -0
  128. package/dist/services/features/telegram-mcp/standalone-http.service.js +12 -0
  129. package/dist/services/features/telegram-mcp/terminal-buffer.service.js +42 -0
  130. package/dist/services/features/telegram-mcp/terminal-input.service.js +41 -0
  131. package/dist/services/features/telegram-mcp/tools-sync.service.js +15 -1
  132. package/dist/services/features/telegram-mcp/xchange.service.js +123 -0
  133. package/docs/STANDALONE-ru.md +172 -0
  134. package/docs/STANDALONE.md +172 -0
  135. package/package.json +10 -5
  136. package/scripts/build-package-artifact.sh +27 -0
  137. package/scripts/deploy-gateway.sh +64 -0
  138. package/scripts/deploy-onebot-branch.sh +27 -0
  139. package/scripts/postinstall.js +11 -36
  140. package/STANDALONE-ru.md +0 -274
  141. package/STANDALONE.md +0 -274
  142. package/dist/services/features/telegram-mcp/inbox.service.js +0 -33
  143. package/dist/services/features/telegram-mcp/pair.service.js +0 -33
  144. package/dist/services/features/telegram-mcp/src/app/webapp/tmux.js +0 -10
  145. package/dist/services/features/telegram-mcp/src/features/inbox/model/deleteTelegramInboxMessageTool.js +0 -33
  146. package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxCountTool.js +0 -33
  147. package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxTool.js +0 -33
  148. package/dist/services/features/telegram-mcp/src/features/inbox/model/inboxService.js +0 -77
  149. package/dist/services/features/telegram-mcp/src/features/pair-session/model/clearSessionPairingTool.js +0 -33
  150. package/dist/services/features/telegram-mcp/src/features/pair-session/model/createSessionPairCodeTool.js +0 -33
  151. package/dist/services/features/telegram-mcp/src/features/pair-session/model/generatePairCode.js +0 -202
  152. package/dist/services/features/telegram-mcp/src/features/session-context/model/getTmuxTargetTool.js +0 -33
  153. package/dist/services/features/telegram-mcp/src/features/session-context/model/setTmuxTargetTool.js +0 -33
  154. package/dist/services/features/telegram-mcp/src/shared/integrations/tmux/client.js +0 -363
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.BrowserService = void 0;
7
7
  const node_path_1 = __importDefault(require("node:path"));
8
+ const gatewayClientAccess_1 = require("../../distributed-client/model/gatewayClientAccess");
8
9
  function pushBounded(list, entry, max) {
9
10
  list.push(entry);
10
11
  if (list.length > max) {
@@ -46,38 +47,66 @@ function formatConsoleLocation(message) {
46
47
  function escapeCssAttributeValue(value) {
47
48
  return value.replace(/\\/gu, "\\\\").replace(/"/gu, '\\"');
48
49
  }
50
+ const DEFAULT_BROWSER_VIEWPORT_WIDTH = 1720;
51
+ const DEFAULT_BROWSER_VIEWPORT_HEIGHT = 980;
49
52
  class BrowserService {
50
53
  config;
51
54
  sessionStore;
55
+ maintenanceStore;
52
56
  bindingStore;
53
57
  xchangeFileMetaStore;
54
58
  objectStore;
55
59
  telegramTransport;
56
60
  logger;
57
61
  projectIdentityResolver;
62
+ remoteConsoleInvoker;
58
63
  playwrightModulePromise;
59
64
  browserPromise;
60
65
  sessionStates = new Map();
61
- constructor(config, sessionStore, bindingStore, xchangeFileMetaStore, objectStore, telegramTransport, logger, projectIdentityResolver) {
66
+ constructor(config, sessionStore, maintenanceStore, bindingStore, xchangeFileMetaStore, objectStore, telegramTransport, logger, projectIdentityResolver, remoteConsoleInvoker) {
62
67
  this.config = config;
63
68
  this.sessionStore = sessionStore;
69
+ this.maintenanceStore = maintenanceStore;
64
70
  this.bindingStore = bindingStore;
65
71
  this.xchangeFileMetaStore = xchangeFileMetaStore;
66
72
  this.objectStore = objectStore;
67
73
  this.telegramTransport = telegramTransport;
68
74
  this.logger = logger;
69
75
  this.projectIdentityResolver = projectIdentityResolver;
76
+ this.remoteConsoleInvoker = remoteConsoleInvoker;
70
77
  }
71
78
  async open(input) {
72
- this.ensureEnabled();
73
79
  const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
74
- const existingState = this.sessionStates.get(resolved.sessionId);
75
- const shouldReset = input.reset_context === true;
80
+ const normalizedSessionId = await this.normalizeSessionIdForAccess(resolved.sessionId);
81
+ const remote = await this.invokeRemote(normalizedSessionId, "telegramMcp.browser.openRemote", {
82
+ ...input,
83
+ session_id: normalizedSessionId,
84
+ });
85
+ if (remote) {
86
+ return remote;
87
+ }
88
+ this.ensureEnabled();
89
+ const existingState = this.sessionStates.get(normalizedSessionId);
90
+ const requestedViewport = this.resolveRequestedViewport(input);
91
+ const shouldUpgradeLegacyViewport = this.config.browser.headless === false &&
92
+ input.reset_context !== true &&
93
+ !requestedViewport &&
94
+ Boolean(existingState?.page.viewportSize());
95
+ const shouldReset = input.reset_context === true || shouldUpgradeLegacyViewport;
76
96
  const targetUrl = this.resolveBrowserUrl(input.url);
77
97
  if (shouldReset && existingState) {
78
- await this.closeState(resolved.sessionId, existingState);
98
+ await this.closeState(normalizedSessionId, existingState);
99
+ }
100
+ const { state, createdContext } = await this.ensureSessionState(normalizedSessionId, shouldReset, input);
101
+ if (requestedViewport) {
102
+ await state.page.setViewportSize(requestedViewport);
103
+ }
104
+ else if (this.config.browser.headless !== false) {
105
+ await state.page.setViewportSize({
106
+ width: DEFAULT_BROWSER_VIEWPORT_WIDTH,
107
+ height: DEFAULT_BROWSER_VIEWPORT_HEIGHT,
108
+ });
79
109
  }
80
- const { state, createdContext } = await this.ensureSessionState(resolved.sessionId, shouldReset);
81
110
  const waitUntil = (input.wait_until ??
82
111
  this.config.browser.waitUntil);
83
112
  await state.page.goto(targetUrl, {
@@ -89,21 +118,36 @@ class BrowserService {
89
118
  state.lastUsedAt = new Date().toISOString();
90
119
  this.logger.info("Browser page opened", {
91
120
  sessionId: resolved.sessionId,
121
+ normalizedSessionId,
92
122
  url: state.currentUrl,
93
123
  title: state.title,
94
124
  createdContext,
95
125
  waitUntil,
96
126
  headless: this.config.browser.headless,
127
+ viewportWidth: state.page.viewportSize()?.width ?? requestedViewport?.width,
128
+ viewportHeight: state.page.viewportSize()?.height ?? requestedViewport?.height,
97
129
  });
130
+ const viewport = state.page.viewportSize();
98
131
  return {
99
- session_id: resolved.sessionId,
132
+ session_id: normalizedSessionId,
100
133
  opened: true,
101
134
  created_context: createdContext,
102
135
  url: state.currentUrl,
103
136
  ...(state.title ? { title: state.title } : {}),
137
+ ...(viewport?.width ? { viewport_width: viewport.width } : {}),
138
+ ...(viewport?.height ? { viewport_height: viewport.height } : {}),
104
139
  };
105
140
  }
106
141
  async getConsole(input) {
142
+ const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
143
+ const normalizedSessionId = await this.normalizeSessionIdForAccess(resolved.sessionId);
144
+ const remote = await this.invokeRemote(normalizedSessionId, "telegramMcp.browser.getConsoleRemote", {
145
+ ...input,
146
+ session_id: normalizedSessionId,
147
+ });
148
+ if (remote) {
149
+ return remote;
150
+ }
107
151
  this.ensureEnabled();
108
152
  const { sessionId, state } = await this.requireSessionState(input);
109
153
  state.lastUsedAt = new Date().toISOString();
@@ -119,6 +163,15 @@ class BrowserService {
119
163
  };
120
164
  }
121
165
  async click(input) {
166
+ const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
167
+ const normalizedSessionId = await this.normalizeSessionIdForAccess(resolved.sessionId);
168
+ const remote = await this.invokeRemote(normalizedSessionId, "telegramMcp.browser.clickRemote", {
169
+ ...input,
170
+ session_id: normalizedSessionId,
171
+ });
172
+ if (remote) {
173
+ return remote;
174
+ }
122
175
  this.ensureEnabled();
123
176
  const { sessionId, state } = await this.requireSessionState(input);
124
177
  const locator = this.resolveLocator(state.page, input);
@@ -139,6 +192,15 @@ class BrowserService {
139
192
  };
140
193
  }
141
194
  async fill(input) {
195
+ const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
196
+ const normalizedSessionId = await this.normalizeSessionIdForAccess(resolved.sessionId);
197
+ const remote = await this.invokeRemote(normalizedSessionId, "telegramMcp.browser.fillRemote", {
198
+ ...input,
199
+ session_id: normalizedSessionId,
200
+ });
201
+ if (remote) {
202
+ return remote;
203
+ }
142
204
  this.ensureEnabled();
143
205
  const { sessionId, state } = await this.requireSessionState(input);
144
206
  const locator = this.resolveLocator(state.page, input);
@@ -160,6 +222,15 @@ class BrowserService {
160
222
  };
161
223
  }
162
224
  async press(input) {
225
+ const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
226
+ const normalizedSessionId = await this.normalizeSessionIdForAccess(resolved.sessionId);
227
+ const remote = await this.invokeRemote(normalizedSessionId, "telegramMcp.browser.pressRemote", {
228
+ ...input,
229
+ session_id: normalizedSessionId,
230
+ });
231
+ if (remote) {
232
+ return remote;
233
+ }
163
234
  this.ensureEnabled();
164
235
  const { sessionId, state } = await this.requireSessionState(input);
165
236
  if (input.selector || input.text) {
@@ -186,6 +257,15 @@ class BrowserService {
186
257
  };
187
258
  }
188
259
  async reload(input) {
260
+ const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
261
+ const normalizedSessionId = await this.normalizeSessionIdForAccess(resolved.sessionId);
262
+ const remote = await this.invokeRemote(normalizedSessionId, "telegramMcp.browser.reloadRemote", {
263
+ ...input,
264
+ session_id: normalizedSessionId,
265
+ });
266
+ if (remote) {
267
+ return remote;
268
+ }
189
269
  this.ensureEnabled();
190
270
  const { sessionId, state } = await this.requireSessionState(input);
191
271
  const waitUntil = (input.wait_until ??
@@ -211,6 +291,15 @@ class BrowserService {
211
291
  };
212
292
  }
213
293
  async waitFor(input) {
294
+ const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
295
+ const normalizedSessionId = await this.normalizeSessionIdForAccess(resolved.sessionId);
296
+ const remote = await this.invokeRemote(normalizedSessionId, "telegramMcp.browser.waitForRemote", {
297
+ ...input,
298
+ session_id: normalizedSessionId,
299
+ });
300
+ if (remote) {
301
+ return remote;
302
+ }
214
303
  this.ensureEnabled();
215
304
  const { sessionId, state } = await this.requireSessionState(input);
216
305
  const locator = this.resolveLocator(state.page, input);
@@ -234,6 +323,15 @@ class BrowserService {
234
323
  };
235
324
  }
236
325
  async waitForUrl(input) {
326
+ const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
327
+ const normalizedSessionId = await this.normalizeSessionIdForAccess(resolved.sessionId);
328
+ const remote = await this.invokeRemote(normalizedSessionId, "telegramMcp.browser.waitForUrlRemote", {
329
+ ...input,
330
+ session_id: normalizedSessionId,
331
+ });
332
+ if (remote) {
333
+ return remote;
334
+ }
237
335
  this.ensureEnabled();
238
336
  const { sessionId, state } = await this.requireSessionState(input);
239
337
  const timeout = this.resolveTimeoutMs(input.timeout_ms);
@@ -267,6 +365,15 @@ class BrowserService {
267
365
  };
268
366
  }
269
367
  async getErrors(input) {
368
+ const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
369
+ const normalizedSessionId = await this.normalizeSessionIdForAccess(resolved.sessionId);
370
+ const remote = await this.invokeRemote(normalizedSessionId, "telegramMcp.browser.getErrorsRemote", {
371
+ ...input,
372
+ session_id: normalizedSessionId,
373
+ });
374
+ if (remote) {
375
+ return remote;
376
+ }
270
377
  this.ensureEnabled();
271
378
  const { sessionId, state } = await this.requireSessionState(input);
272
379
  state.lastUsedAt = new Date().toISOString();
@@ -281,6 +388,15 @@ class BrowserService {
281
388
  };
282
389
  }
283
390
  async getNetworkFailures(input) {
391
+ const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
392
+ const normalizedSessionId = await this.normalizeSessionIdForAccess(resolved.sessionId);
393
+ const remote = await this.invokeRemote(normalizedSessionId, "telegramMcp.browser.getNetworkFailuresRemote", {
394
+ ...input,
395
+ session_id: normalizedSessionId,
396
+ });
397
+ if (remote) {
398
+ return remote;
399
+ }
284
400
  this.ensureEnabled();
285
401
  const { sessionId, state } = await this.requireSessionState(input);
286
402
  state.lastUsedAt = new Date().toISOString();
@@ -300,6 +416,15 @@ class BrowserService {
300
416
  };
301
417
  }
302
418
  async clearLogs(input) {
419
+ const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
420
+ const normalizedSessionId = await this.normalizeSessionIdForAccess(resolved.sessionId);
421
+ const remote = await this.invokeRemote(normalizedSessionId, "telegramMcp.browser.clearLogsRemote", {
422
+ ...input,
423
+ session_id: normalizedSessionId,
424
+ });
425
+ if (remote) {
426
+ return remote;
427
+ }
303
428
  this.ensureEnabled();
304
429
  const { sessionId, state } = await this.requireSessionState(input);
305
430
  const consoleMessagesCleared = state.consoleMessages.length;
@@ -318,6 +443,15 @@ class BrowserService {
318
443
  };
319
444
  }
320
445
  async getDom(input) {
446
+ const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
447
+ const normalizedSessionId = await this.normalizeSessionIdForAccess(resolved.sessionId);
448
+ const remote = await this.invokeRemote(normalizedSessionId, "telegramMcp.browser.getDomRemote", {
449
+ ...input,
450
+ session_id: normalizedSessionId,
451
+ });
452
+ if (remote) {
453
+ return remote;
454
+ }
321
455
  this.ensureEnabled();
322
456
  const { sessionId, state } = await this.requireSessionState(input);
323
457
  const selector = input.selector?.trim() || "body";
@@ -373,6 +507,15 @@ class BrowserService {
373
507
  };
374
508
  }
375
509
  async getComputedStyle(input) {
510
+ const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
511
+ const normalizedSessionId = await this.normalizeSessionIdForAccess(resolved.sessionId);
512
+ const remote = await this.invokeRemote(normalizedSessionId, "telegramMcp.browser.getComputedStyleRemote", {
513
+ ...input,
514
+ session_id: normalizedSessionId,
515
+ });
516
+ if (remote) {
517
+ return remote;
518
+ }
376
519
  this.ensureEnabled();
377
520
  const { sessionId, state } = await this.requireSessionState(input);
378
521
  const properties = input.properties?.length
@@ -430,6 +573,15 @@ class BrowserService {
430
573
  };
431
574
  }
432
575
  async screenshot(input) {
576
+ const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
577
+ const normalizedSessionId = await this.normalizeSessionIdForAccess(resolved.sessionId);
578
+ const remote = await this.invokeRemote(normalizedSessionId, "telegramMcp.browser.screenshotRemote", {
579
+ ...input,
580
+ session_id: normalizedSessionId,
581
+ });
582
+ if (remote) {
583
+ return remote;
584
+ }
433
585
  this.ensureEnabled();
434
586
  const { sessionId, state, session } = await this.requireSessionState(input);
435
587
  const fileName = sanitizeScreenshotName(input.file_name);
@@ -472,18 +624,34 @@ class BrowserService {
472
624
  relativePath: storedFile.relativePath,
473
625
  source: "browser-screenshot",
474
626
  uploadedAt: new Date().toISOString(),
627
+ storageRef: storedFile.storageRef,
628
+ bucketName: storedFile.bucketName,
629
+ objectName: storedFile.objectName,
630
+ vfsNodeId: storedFile.vfsNodeId,
631
+ vfsPublicUrl: storedFile.vfsPublicUrl,
632
+ vfsParentId: storedFile.vfsParentId,
475
633
  mimeType: "image/png",
476
634
  sizeBytes: storedFile.sizeBytes,
477
635
  ...(input.caption ? { caption: input.caption } : {}),
478
636
  });
479
637
  let telegramMessageId;
480
638
  if (input.send_to_telegram === true) {
481
- const binding = await this.bindingStore.getBinding(sessionId);
482
- if (!binding) {
483
- throw new Error("Session is not linked to Telegram, so screenshot cannot be sent there.");
639
+ if (this.config.distributed.mode === "client") {
640
+ telegramMessageId = await this.sendScreenshotToGatewayTelegramRoute({
641
+ sessionId,
642
+ fileName,
643
+ pngBuffer,
644
+ ...(input.caption ? { caption: input.caption } : {}),
645
+ });
646
+ }
647
+ else {
648
+ const binding = await this.bindingStore.getBinding(sessionId);
649
+ if (!binding) {
650
+ throw new Error("Session is not linked to Telegram, so screenshot cannot be sent there.");
651
+ }
652
+ const sent = await this.telegramTransport.sendDocumentToChat(binding.telegramChatId, filePath, input.caption);
653
+ telegramMessageId = sent.messageId;
484
654
  }
485
- const sent = await this.telegramTransport.sendDocumentToChat(binding.telegramChatId, filePath, input.caption);
486
- telegramMessageId = sent.messageId;
487
655
  }
488
656
  return {
489
657
  session_id: sessionId,
@@ -498,14 +666,22 @@ class BrowserService {
498
666
  };
499
667
  }
500
668
  async close(input) {
501
- this.ensureEnabled();
502
669
  const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
503
- const state = this.sessionStates.get(resolved.sessionId);
670
+ const normalizedSessionId = await this.normalizeSessionIdForAccess(resolved.sessionId);
671
+ const remote = await this.invokeRemote(normalizedSessionId, "telegramMcp.browser.closeRemote", {
672
+ ...input,
673
+ session_id: normalizedSessionId,
674
+ });
675
+ if (remote) {
676
+ return remote;
677
+ }
678
+ this.ensureEnabled();
679
+ const state = this.sessionStates.get(normalizedSessionId);
504
680
  if (state) {
505
- await this.closeState(resolved.sessionId, state);
681
+ await this.closeState(normalizedSessionId, state);
506
682
  }
507
683
  return {
508
- session_id: resolved.sessionId,
684
+ session_id: normalizedSessionId,
509
685
  closed: Boolean(state),
510
686
  };
511
687
  }
@@ -535,10 +711,13 @@ class BrowserService {
535
711
  async ensureBrowser() {
536
712
  this.browserPromise ??= (async () => {
537
713
  const playwright = await this.ensurePlaywright();
538
- const launchArgs = this.config.browser.headless === false &&
539
- this.config.browser.devtools === true
540
- ? ["--auto-open-devtools-for-tabs"]
541
- : [];
714
+ const launchArgs = [];
715
+ if (this.config.browser.headless === false) {
716
+ launchArgs.push("--start-maximized");
717
+ if (this.config.browser.devtools === true) {
718
+ launchArgs.push("--auto-open-devtools-for-tabs");
719
+ }
720
+ }
542
721
  const browser = await playwright.chromium.launch({
543
722
  headless: this.config.browser.headless,
544
723
  slowMo: this.config.browser.slowMoMs,
@@ -562,13 +741,13 @@ class BrowserService {
562
741
  })();
563
742
  return this.browserPromise;
564
743
  }
565
- async ensureSessionState(sessionId, forceNewContext) {
744
+ async ensureSessionState(sessionId, forceNewContext, openInput) {
566
745
  const existing = this.sessionStates.get(sessionId);
567
746
  if (existing && !forceNewContext) {
568
747
  return { state: existing, createdContext: false };
569
748
  }
570
749
  const browser = await this.ensureBrowser();
571
- const context = await browser.newContext();
750
+ const context = await browser.newContext(this.buildContextOptions(openInput));
572
751
  const page = await context.newPage();
573
752
  const createdAt = new Date().toISOString();
574
753
  const state = {
@@ -608,6 +787,32 @@ class BrowserService {
608
787
  this.sessionStates.set(sessionId, state);
609
788
  return { state, createdContext: true };
610
789
  }
790
+ resolveRequestedViewport(input) {
791
+ const width = input?.width;
792
+ const height = input?.height;
793
+ if (!width && !height) {
794
+ return null;
795
+ }
796
+ if (!width || !height) {
797
+ throw new Error("Browser viewport requires both width and height together.");
798
+ }
799
+ return { width, height };
800
+ }
801
+ buildContextOptions(input) {
802
+ const requestedViewport = this.resolveRequestedViewport(input);
803
+ if (requestedViewport) {
804
+ return {
805
+ viewport: requestedViewport,
806
+ screen: requestedViewport,
807
+ };
808
+ }
809
+ if (this.config.browser.headless === false) {
810
+ return {
811
+ viewport: null,
812
+ };
813
+ }
814
+ return {};
815
+ }
611
816
  recordNetworkFailure(state, request, response) {
612
817
  const failure = request.failure();
613
818
  pushBounded(state.networkFailures, {
@@ -623,19 +828,94 @@ class BrowserService {
623
828
  }
624
829
  async requireSessionState(input) {
625
830
  const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
626
- const state = this.sessionStates.get(resolved.sessionId);
831
+ const sessionId = await this.normalizeSessionIdForAccess(resolved.sessionId);
832
+ const state = this.sessionStates.get(sessionId);
627
833
  if (!state) {
628
834
  throw new Error("Browser session is not open. Call browser_open first for this session.");
629
835
  }
630
- const session = await this.sessionStore.getSession(resolved.sessionId);
836
+ const session = await this.sessionStore.getSession(sessionId);
631
837
  return {
632
- sessionId: resolved.sessionId,
838
+ sessionId,
633
839
  session,
634
840
  state,
635
841
  };
636
842
  }
637
843
  resolveWorkspaceDir(session) {
638
- return session?.cwd?.trim() || process.cwd();
844
+ const workspaceDir = session?.cwd?.trim();
845
+ if (!workspaceDir) {
846
+ throw new Error("Workspace cwd is not registered for this browser console.");
847
+ }
848
+ return workspaceDir;
849
+ }
850
+ async invokeRemote(sessionId, actionName, input) {
851
+ if (this.config.distributed.mode === "client") {
852
+ return undefined;
853
+ }
854
+ return await this.remoteConsoleInvoker?.invokeForRelaySession(sessionId, actionName, input);
855
+ }
856
+ async normalizeSessionIdForAccess(sessionId) {
857
+ const trimmed = sessionId.trim();
858
+ if (!trimmed) {
859
+ return trimmed;
860
+ }
861
+ const direct = await this.sessionStore.getSession(trimmed);
862
+ if (direct) {
863
+ return trimmed;
864
+ }
865
+ const separatorIndex = trimmed.indexOf(":");
866
+ if (separatorIndex <= 0) {
867
+ return trimmed;
868
+ }
869
+ const localClientUuid = await this.maintenanceStore.getGatewayClientUuid();
870
+ const clientUuid = trimmed.slice(0, separatorIndex).trim();
871
+ const localSessionId = trimmed.slice(separatorIndex + 1).trim();
872
+ if (!localClientUuid || clientUuid !== localClientUuid || !localSessionId) {
873
+ return trimmed;
874
+ }
875
+ const localSession = await this.sessionStore.getSession(localSessionId);
876
+ return localSession ? localSessionId : trimmed;
877
+ }
878
+ async sendScreenshotToGatewayTelegramRoute(input) {
879
+ if (!this.config.distributed.gatewayPublicUrl) {
880
+ throw new Error("send_to_telegram on client nodes requires GATEWAY_PUBLIC_URL.");
881
+ }
882
+ const clientUuid = await (0, gatewayClientAccess_1.ensureGatewayClientUuid)({
883
+ maintenanceStore: this.maintenanceStore,
884
+ gatewayPublicUrl: this.config.distributed.gatewayPublicUrl,
885
+ ...(this.config.distributed.gatewayAuthToken
886
+ ? { gatewayAuthToken: this.config.distributed.gatewayAuthToken }
887
+ : {}),
888
+ ...(this.config.distributed.gatewayToken
889
+ ? { gatewayToken: this.config.distributed.gatewayToken }
890
+ : {}),
891
+ ...(this.config.project.name
892
+ ? { projectName: this.config.project.name }
893
+ : {}),
894
+ ...(this.config.telegram.botUsername
895
+ ? { botUsername: this.config.telegram.botUsername }
896
+ : {}),
897
+ ...(this.config.distributed.gatewayUserUuid
898
+ ? { gatewayUserUuid: this.config.distributed.gatewayUserUuid }
899
+ : {}),
900
+ });
901
+ const output = await (0, gatewayClientAccess_1.callGatewayJson)({
902
+ gatewayPublicUrl: this.config.distributed.gatewayPublicUrl,
903
+ ...(this.config.distributed.gatewayAuthToken
904
+ ? { gatewayAuthToken: this.config.distributed.gatewayAuthToken }
905
+ : {}),
906
+ endpointPath: "/transport/document",
907
+ body: {
908
+ client_uuid: clientUuid,
909
+ local_session_id: input.sessionId,
910
+ file_name: input.fileName,
911
+ content_base64: input.pngBuffer.toString("base64"),
912
+ ...(input.caption?.trim() ? { caption: input.caption.trim() } : {}),
913
+ },
914
+ });
915
+ if (!output.sent) {
916
+ throw new Error("Gateway did not confirm Telegram document delivery for the screenshot.");
917
+ }
918
+ return typeof output.message_id === "number" ? output.message_id : undefined;
639
919
  }
640
920
  ensureEnabled() {
641
921
  if (!this.config.browser.enabled) {
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GatewaySessionsService = void 0;
4
+ const gatewayClientAccess_1 = require("../../distributed-client/model/gatewayClientAccess");
5
+ class GatewaySessionsService {
6
+ logger;
7
+ maintenanceStore;
8
+ gatewayPublicUrl;
9
+ gatewayAuthToken;
10
+ gatewayToken;
11
+ gatewayUserUuid;
12
+ projectName;
13
+ botUsername;
14
+ constructor(logger, maintenanceStore, gatewayPublicUrl, gatewayAuthToken, gatewayToken, gatewayUserUuid, projectName, botUsername) {
15
+ this.logger = logger;
16
+ this.maintenanceStore = maintenanceStore;
17
+ this.gatewayPublicUrl = gatewayPublicUrl;
18
+ this.gatewayAuthToken = gatewayAuthToken;
19
+ this.gatewayToken = gatewayToken;
20
+ this.gatewayUserUuid = gatewayUserUuid;
21
+ this.projectName = projectName;
22
+ this.botUsername = botUsername;
23
+ }
24
+ async listKnownSessions(input = {}) {
25
+ if (!this.gatewayPublicUrl) {
26
+ throw new Error("Gateway session listing requires GATEWAY_PUBLIC_URL.");
27
+ }
28
+ await (0, gatewayClientAccess_1.ensureGatewayClientUuid)({
29
+ maintenanceStore: this.maintenanceStore,
30
+ gatewayPublicUrl: this.gatewayPublicUrl,
31
+ ...(this.gatewayAuthToken
32
+ ? { gatewayAuthToken: this.gatewayAuthToken }
33
+ : {}),
34
+ ...(this.gatewayToken ? { gatewayToken: this.gatewayToken } : {}),
35
+ ...(this.gatewayUserUuid ? { gatewayUserUuid: this.gatewayUserUuid } : {}),
36
+ ...(this.projectName ? { projectName: this.projectName } : {}),
37
+ ...(this.botUsername ? { botUsername: this.botUsername } : {}),
38
+ });
39
+ const response = await (0, gatewayClientAccess_1.callGatewayJson)({
40
+ gatewayPublicUrl: this.gatewayPublicUrl,
41
+ ...(this.gatewayAuthToken
42
+ ? { gatewayAuthToken: this.gatewayAuthToken }
43
+ : {}),
44
+ endpointPath: "/sessions/known",
45
+ body: {
46
+ ...(input.client_uuid?.trim()
47
+ ? { client_uuid: input.client_uuid.trim() }
48
+ : {}),
49
+ ...(this.gatewayToken ? { gateway_token: this.gatewayToken } : {}),
50
+ ...(this.gatewayUserUuid
51
+ ? { owner_user_uuid: this.gatewayUserUuid }
52
+ : {}),
53
+ ...(typeof input.connected_only === "boolean"
54
+ ? { connected_only: input.connected_only }
55
+ : {}),
56
+ },
57
+ });
58
+ const sessions = Array.isArray(response.sessions) ? response.sessions : [];
59
+ this.logger.info("Known gateway sessions listed", {
60
+ total: sessions.length,
61
+ connectedOnly: input.connected_only ?? false,
62
+ });
63
+ return {
64
+ total: typeof response.total === "number" && Number.isFinite(response.total)
65
+ ? response.total
66
+ : sessions.length,
67
+ sessions,
68
+ };
69
+ }
70
+ }
71
+ exports.GatewaySessionsService = GatewaySessionsService;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ListGatewaySessionsTool = void 0;
4
+ const schema_1 = require("../../../entities/request/model/schema");
5
+ function createContent(output) {
6
+ return [
7
+ {
8
+ type: "text",
9
+ text: JSON.stringify(output, null, 2),
10
+ },
11
+ ];
12
+ }
13
+ class ListGatewaySessionsTool {
14
+ gatewaySessionsService;
15
+ constructor(gatewaySessionsService) {
16
+ this.gatewaySessionsService = gatewaySessionsService;
17
+ }
18
+ register(server) {
19
+ server.registerTool("list_gateway_sessions", {
20
+ title: "List Gateway Sessions",
21
+ description: "List all known consoles from the configured gateway. Use this before direct cross-console communication outside a single collab project, or when you need to discover a console id once. The result includes live connected consoles and project-registered consoles known to the gateway. The canonical gateway-facing session_id is the composite value client_uuid:local_session_id from this list. Reuse that exact session_id in later gateway-routed tools instead of reconstructing it, stripping it, or re-listing sessions when the current console id is already known. target_client_uuid and target_local_session_id are also returned for direct routing APIs that need them.",
22
+ inputSchema: schema_1.listGatewaySessionsInputSchema,
23
+ outputSchema: schema_1.listGatewaySessionsOutputSchema,
24
+ }, async (args) => {
25
+ const output = await this.gatewaySessionsService.listKnownSessions(args);
26
+ return {
27
+ content: createContent(output),
28
+ structuredContent: output,
29
+ };
30
+ });
31
+ }
32
+ }
33
+ exports.ListGatewaySessionsTool = ListGatewaySessionsTool;