@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
@@ -1,7 +1,15 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.NotifyService = void 0;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const schema_1 = require("../../../entities/request/model/schema");
4
9
  const redactSecrets_1 = require("../../../shared/lib/redact-secrets/redactSecrets");
10
+ const client_1 = require("../../../shared/integrations/terminal/client");
11
+ const relay_1 = require("../../../app/webapp/relay");
12
+ const gatewayClientAccess_1 = require("../../distributed-client/model/gatewayClientAccess");
5
13
  function mergeSavedContext(input, session) {
6
14
  const savedSections = [];
7
15
  if (input.use_saved_context && session?.summary) {
@@ -30,28 +38,111 @@ function mergeSavedContext(input, session) {
30
38
  ...(session?.label ? { sessionLabel: session.label } : {}),
31
39
  };
32
40
  }
41
+ function normalizeNotifyTelegramOutput(value) {
42
+ const candidate = value && typeof value === "object" && "structuredContent" in value
43
+ ? value.structuredContent
44
+ : value && typeof value === "object" && "result" in value
45
+ ? value.result
46
+ : value;
47
+ const parsed = schema_1.notifyTelegramOutputSchema.safeParse(candidate);
48
+ if (parsed.success) {
49
+ return parsed.data;
50
+ }
51
+ return null;
52
+ }
53
+ function normalizeSendFileToTelegramOutput(value) {
54
+ const candidate = value && typeof value === "object" && "structuredContent" in value
55
+ ? value.structuredContent
56
+ : value && typeof value === "object" && "result" in value
57
+ ? value.result
58
+ : value;
59
+ const parsed = schema_1.sendFileToTelegramOutputSchema.safeParse(candidate);
60
+ if (parsed.success) {
61
+ return parsed.data;
62
+ }
63
+ return null;
64
+ }
65
+ function resolveWorkspaceDir(input) {
66
+ if (input.inputCwd?.trim()) {
67
+ return node_path_1.default.resolve(input.inputCwd.trim());
68
+ }
69
+ if (input.sessionCwd?.trim()) {
70
+ return node_path_1.default.resolve(input.sessionCwd.trim());
71
+ }
72
+ return node_path_1.default.resolve(input.resolvedCwd);
73
+ }
74
+ function normalizeWorkspaceRelativePath(workspaceDir, filePath) {
75
+ const trimmed = filePath.trim();
76
+ if (!trimmed) {
77
+ throw new Error("file_path is required.");
78
+ }
79
+ const resolvedWorkspaceDir = node_path_1.default.resolve(workspaceDir);
80
+ const resolvedFilePath = node_path_1.default.isAbsolute(trimmed)
81
+ ? node_path_1.default.resolve(trimmed)
82
+ : node_path_1.default.resolve(resolvedWorkspaceDir, trimmed);
83
+ const relative = node_path_1.default.relative(resolvedWorkspaceDir, resolvedFilePath);
84
+ if (relative.startsWith("..") ||
85
+ node_path_1.default.isAbsolute(relative) ||
86
+ relative.trim() === "") {
87
+ throw new Error("File path is outside the workspace directory.");
88
+ }
89
+ return relative.split(node_path_1.default.sep).join("/");
90
+ }
33
91
  class NotifyService {
34
92
  _config;
35
93
  sessionStore;
36
94
  bindingStore;
95
+ maintenanceStore;
37
96
  transport;
38
97
  logger;
39
98
  projectIdentityResolver;
40
- constructor(_config, sessionStore, bindingStore, transport, logger, projectIdentityResolver) {
99
+ remoteConsoleInvoker;
100
+ gatewaySessionTargetResolver;
101
+ constructor(_config, sessionStore, bindingStore, maintenanceStore, transport, logger, projectIdentityResolver, remoteConsoleInvoker, gatewaySessionTargetResolver) {
41
102
  this._config = _config;
42
103
  this.sessionStore = sessionStore;
43
104
  this.bindingStore = bindingStore;
105
+ this.maintenanceStore = maintenanceStore;
44
106
  this.transport = transport;
45
107
  this.logger = logger;
46
108
  this.projectIdentityResolver = projectIdentityResolver;
109
+ this.remoteConsoleInvoker = remoteConsoleInvoker;
110
+ this.gatewaySessionTargetResolver = gatewaySessionTargetResolver;
47
111
  }
48
112
  async send(input) {
49
113
  const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
50
114
  const binding = await this.bindingStore.getBinding(resolved.sessionId);
51
115
  if (!binding) {
52
- throw new Error("Session is not linked to Telegram. Call create_session_pair_code first.");
116
+ const remoteTarget = this._config.distributed.mode !== "client" &&
117
+ this.gatewaySessionTargetResolver
118
+ ? await this.gatewaySessionTargetResolver(resolved.sessionId)
119
+ : null;
120
+ if (remoteTarget) {
121
+ return this.sendForGatewayBoundSession({
122
+ clientUuid: remoteTarget.client_uuid,
123
+ localSessionId: remoteTarget.local_session_id,
124
+ message: input.message,
125
+ sessionLabel: remoteTarget.session_label ??
126
+ resolved.sessionLabel ??
127
+ remoteTarget.local_session_id,
128
+ ...(input.task ? { task: input.task } : {}),
129
+ ...(input.context ? { context: input.context } : {}),
130
+ ...(input.risk_level ? { riskLevel: input.risk_level } : {}),
131
+ });
132
+ }
133
+ if (this._config.distributed.gatewayPublicUrl) {
134
+ return this.sendViaGatewayBoundSession({
135
+ sessionId: resolved.sessionId,
136
+ sessionLabel: resolved.sessionLabel,
137
+ message: input.message,
138
+ ...(input.task ? { task: input.task } : {}),
139
+ ...(input.context ? { context: input.context } : {}),
140
+ ...(input.risk_level ? { riskLevel: input.risk_level } : {}),
141
+ });
142
+ }
143
+ throw new Error("Session is not available through the gateway console registry yet. Open /menu in the gateway bot and select the console first.");
53
144
  }
54
- const session = await this.sessionStore.getSession(resolved.sessionId);
145
+ const session = await this.resolveSessionContextForNotification(resolved.sessionId);
55
146
  const merged = mergeSavedContext(input, session);
56
147
  this.logger.info("Telegram notification requested", {
57
148
  sessionId: resolved.sessionId,
@@ -89,5 +180,293 @@ class NotifyService {
89
180
  : {}),
90
181
  };
91
182
  }
183
+ async sendDocument(input) {
184
+ const resolved = this.projectIdentityResolver.resolveSessionDefaults(input);
185
+ const sessionId = await this.normalizeSessionIdForWorkspace(resolved.sessionId);
186
+ const remote = this._config.distributed.mode !== "client"
187
+ ? normalizeSendFileToTelegramOutput(await this.remoteConsoleInvoker?.invokeForRelaySession(sessionId, "telegramMcp.notify.sendDocumentRemote", {
188
+ ...input,
189
+ session_id: sessionId,
190
+ }))
191
+ : null;
192
+ if (remote) {
193
+ return remote;
194
+ }
195
+ const session = await this.sessionStore.getSession(sessionId);
196
+ const workspaceDir = resolveWorkspaceDir({
197
+ inputCwd: input.cwd,
198
+ sessionCwd: session?.cwd,
199
+ resolvedCwd: resolved.cwd,
200
+ });
201
+ const relativeFilePath = normalizeWorkspaceRelativePath(workspaceDir, input.file_path);
202
+ const fileContent = await (0, client_1.readWorkspaceFile)(this._config.terminal, workspaceDir, relativeFilePath);
203
+ const fileName = node_path_1.default.basename(relativeFilePath);
204
+ const caption = input.caption?.trim();
205
+ if (this._config.distributed.mode === "client") {
206
+ return this.sendDocumentViaGatewayBoundSession({
207
+ sessionId,
208
+ filePath: relativeFilePath,
209
+ fileName,
210
+ contentBase64: Buffer.from(fileContent).toString("base64"),
211
+ ...(caption ? { caption } : {}),
212
+ });
213
+ }
214
+ const binding = await this.bindingStore.getBinding(sessionId);
215
+ if (!binding) {
216
+ throw new Error("Session is not linked to Telegram, so the file cannot be sent there.");
217
+ }
218
+ const absoluteFilePath = node_path_1.default.resolve(workspaceDir, relativeFilePath);
219
+ const sent = await this.transport.sendDocumentToChat?.(binding.telegramChatId, absoluteFilePath, caption);
220
+ if (!sent) {
221
+ throw new Error("Telegram document transport is unavailable.");
222
+ }
223
+ return {
224
+ session_id: sessionId,
225
+ file_path: absoluteFilePath,
226
+ sent: true,
227
+ ...(typeof sent.messageId === "number"
228
+ ? { message_id: sent.messageId }
229
+ : {}),
230
+ };
231
+ }
232
+ async sendForGatewayBoundSession(input) {
233
+ const relaySessionId = (0, relay_1.buildLiveRelaySessionId)(input.clientUuid, input.localSessionId);
234
+ const binding = await this.bindingStore.getBinding(relaySessionId);
235
+ if (!binding) {
236
+ throw new Error(`Gateway relay session '${relaySessionId}' has no active Telegram route.`);
237
+ }
238
+ const session = await this.sessionStore.getSession(relaySessionId);
239
+ const sendResult = await this.transport.sendNotification({
240
+ sessionId: relaySessionId,
241
+ sessionLabel: input.sessionLabel ?? session?.label ?? input.localSessionId,
242
+ recipient: {
243
+ telegramChatId: binding.telegramChatId,
244
+ telegramUserId: binding.telegramUserId,
245
+ },
246
+ message: (0, redactSecrets_1.redactSecrets)(input.message),
247
+ ...(input.task ? { task: (0, redactSecrets_1.redactSecrets)(input.task) } : {}),
248
+ ...(input.context ? { context: (0, redactSecrets_1.redactSecrets)(input.context) } : {}),
249
+ ...(input.riskLevel ? { riskLevel: input.riskLevel } : {}),
250
+ });
251
+ return {
252
+ sent: true,
253
+ ...(typeof sendResult.externalMessageId === "number"
254
+ ? { message_id: sendResult.externalMessageId }
255
+ : {}),
256
+ };
257
+ }
258
+ async sendRequestForGatewayBoundSession(input) {
259
+ const relaySessionId = (0, relay_1.buildLiveRelaySessionId)(input.clientUuid, input.localSessionId);
260
+ const binding = await this.bindingStore.getBinding(relaySessionId);
261
+ if (!binding) {
262
+ throw new Error("Gateway relay session has no active Telegram route yet.");
263
+ }
264
+ const session = await this.sessionStore.getSession(relaySessionId);
265
+ const sendResult = await this.transport.sendRequestForGatewayBoundSession?.({
266
+ requestId: input.requestId,
267
+ sourceClientUuid: input.clientUuid,
268
+ sessionId: relaySessionId,
269
+ sessionLabel: input.sessionLabel ?? session?.label ?? input.localSessionId,
270
+ recipient: {
271
+ telegramChatId: binding.telegramChatId,
272
+ telegramUserId: binding.telegramUserId,
273
+ },
274
+ ...(input.task ? { task: input.task } : {}),
275
+ question: input.question,
276
+ ...(input.context ? { context: input.context } : {}),
277
+ ...(input.affectedFiles ? { affectedFiles: input.affectedFiles } : {}),
278
+ ...(input.options ? { options: input.options } : {}),
279
+ ...(input.recommendedOption
280
+ ? { recommendedOption: input.recommendedOption }
281
+ : {}),
282
+ ...(input.riskLevel ? { riskLevel: input.riskLevel } : {}),
283
+ ...(input.fallbackIfTimeout
284
+ ? { fallbackIfTimeout: input.fallbackIfTimeout }
285
+ : {}),
286
+ });
287
+ if (!sendResult) {
288
+ throw new Error("Gateway transport request proxy is unavailable.");
289
+ }
290
+ return {
291
+ request_id: input.requestId,
292
+ ...(typeof sendResult.externalMessageId === "number"
293
+ ? { message_id: sendResult.externalMessageId }
294
+ : {}),
295
+ };
296
+ }
297
+ async sendDocumentForGatewayBoundSession(input) {
298
+ const relaySessionId = (0, relay_1.buildLiveRelaySessionId)(input.clientUuid, input.localSessionId);
299
+ const binding = await this.bindingStore.getBinding(relaySessionId);
300
+ if (!binding) {
301
+ throw new Error("Gateway relay session has no active Telegram route yet.");
302
+ }
303
+ const sendResult = await this.transport.sendDocumentBufferToChat?.(binding.telegramChatId, input.fileName, Buffer.from(input.contentBase64, "base64"), input.caption);
304
+ if (!sendResult) {
305
+ throw new Error("Gateway transport document proxy is unavailable.");
306
+ }
307
+ return {
308
+ sent: true,
309
+ ...(typeof sendResult.messageId === "number"
310
+ ? { message_id: sendResult.messageId }
311
+ : {}),
312
+ };
313
+ }
314
+ async sendViaGatewayBoundSession(input) {
315
+ if (!this._config.distributed.gatewayPublicUrl) {
316
+ throw new Error("Gateway is not configured.");
317
+ }
318
+ const clientUuid = await (0, gatewayClientAccess_1.ensureGatewayClientUuid)({
319
+ maintenanceStore: this.maintenanceStore,
320
+ gatewayPublicUrl: this._config.distributed.gatewayPublicUrl,
321
+ ...(this._config.distributed.gatewayAuthToken
322
+ ? { gatewayAuthToken: this._config.distributed.gatewayAuthToken }
323
+ : {}),
324
+ ...(this._config.distributed.gatewayToken
325
+ ? { gatewayToken: this._config.distributed.gatewayToken }
326
+ : {}),
327
+ ...(this._config.project.name
328
+ ? { projectName: this._config.project.name }
329
+ : {}),
330
+ ...(this._config.telegram.botUsername
331
+ ? { botUsername: this._config.telegram.botUsername }
332
+ : {}),
333
+ });
334
+ const url = (0, gatewayClientAccess_1.normalizeGatewayBaseUrl)(this._config.distributed.gatewayPublicUrl);
335
+ url.pathname = `${url.pathname}/transport/notify`.replace(/\/{2,}/gu, "/");
336
+ const response = await fetch(url, {
337
+ method: "POST",
338
+ headers: {
339
+ "content-type": "application/json",
340
+ ...(this._config.distributed.gatewayAuthToken
341
+ ? {
342
+ authorization: `Bearer ${this._config.distributed.gatewayAuthToken}`,
343
+ }
344
+ : {}),
345
+ },
346
+ body: JSON.stringify({
347
+ client_uuid: clientUuid,
348
+ local_session_id: input.sessionId,
349
+ ...(input.sessionLabel ? { session_label: input.sessionLabel } : {}),
350
+ message: (0, redactSecrets_1.redactSecrets)(input.message),
351
+ ...(input.task ? { task: (0, redactSecrets_1.redactSecrets)(input.task) } : {}),
352
+ ...(input.context ? { context: (0, redactSecrets_1.redactSecrets)(input.context) } : {}),
353
+ ...(input.riskLevel ? { risk_level: input.riskLevel } : {}),
354
+ }),
355
+ });
356
+ if (!response.ok) {
357
+ const message = await response.text();
358
+ throw new Error(message || response.statusText);
359
+ }
360
+ const rawOutput = (await response.json());
361
+ const normalized = normalizeNotifyTelegramOutput(rawOutput);
362
+ if (normalized) {
363
+ return normalized;
364
+ }
365
+ this.logger.error("notify_telegram received invalid gateway output", {
366
+ sessionId: input.sessionId,
367
+ output: rawOutput,
368
+ });
369
+ throw new Error(`Invalid notify_telegram gateway output: ${JSON.stringify(rawOutput)}`);
370
+ }
371
+ async sendDocumentViaGatewayBoundSession(input) {
372
+ if (!this._config.distributed.gatewayPublicUrl) {
373
+ throw new Error("File delivery to Telegram on client nodes requires GATEWAY_PUBLIC_URL.");
374
+ }
375
+ const clientUuid = await (0, gatewayClientAccess_1.ensureGatewayClientUuid)({
376
+ maintenanceStore: this.maintenanceStore,
377
+ gatewayPublicUrl: this._config.distributed.gatewayPublicUrl,
378
+ ...(this._config.distributed.gatewayAuthToken
379
+ ? { gatewayAuthToken: this._config.distributed.gatewayAuthToken }
380
+ : {}),
381
+ ...(this._config.distributed.gatewayToken
382
+ ? { gatewayToken: this._config.distributed.gatewayToken }
383
+ : {}),
384
+ ...(this._config.project.name
385
+ ? { projectName: this._config.project.name }
386
+ : {}),
387
+ ...(this._config.telegram.botUsername
388
+ ? { botUsername: this._config.telegram.botUsername }
389
+ : {}),
390
+ ...(this._config.distributed.gatewayUserUuid
391
+ ? { gatewayUserUuid: this._config.distributed.gatewayUserUuid }
392
+ : {}),
393
+ });
394
+ const output = await (0, gatewayClientAccess_1.callGatewayJson)({
395
+ gatewayPublicUrl: this._config.distributed.gatewayPublicUrl,
396
+ ...(this._config.distributed.gatewayAuthToken
397
+ ? { gatewayAuthToken: this._config.distributed.gatewayAuthToken }
398
+ : {}),
399
+ endpointPath: "/transport/document",
400
+ body: {
401
+ client_uuid: clientUuid,
402
+ local_session_id: input.sessionId,
403
+ file_name: input.fileName,
404
+ content_base64: input.contentBase64,
405
+ ...(input.caption ? { caption: input.caption } : {}),
406
+ },
407
+ });
408
+ if (!output.sent) {
409
+ throw new Error("Gateway did not confirm Telegram document delivery for the file.");
410
+ }
411
+ return {
412
+ session_id: input.sessionId,
413
+ file_path: input.filePath,
414
+ sent: true,
415
+ ...(typeof output.message_id === "number"
416
+ ? { message_id: output.message_id }
417
+ : {}),
418
+ };
419
+ }
420
+ async normalizeSessionIdForWorkspace(sessionId) {
421
+ const trimmed = sessionId.trim();
422
+ if (!trimmed) {
423
+ return trimmed;
424
+ }
425
+ const direct = await this.sessionStore.getSession(trimmed);
426
+ if (direct) {
427
+ return trimmed;
428
+ }
429
+ const separatorIndex = trimmed.indexOf(":");
430
+ if (separatorIndex <= 0) {
431
+ return trimmed;
432
+ }
433
+ const localClientUuid = await this.maintenanceStore.getGatewayClientUuid();
434
+ const clientUuid = trimmed.slice(0, separatorIndex).trim();
435
+ const localSessionId = trimmed.slice(separatorIndex + 1).trim();
436
+ if (!localClientUuid || clientUuid !== localClientUuid || !localSessionId) {
437
+ return trimmed;
438
+ }
439
+ const localSession = await this.sessionStore.getSession(localSessionId);
440
+ return localSession ? localSessionId : trimmed;
441
+ }
442
+ async resolveSessionContextForNotification(sessionId) {
443
+ const remote = await this.remoteConsoleInvoker?.invokeForRelaySession(sessionId, "telegramMcp.sessionContext.getContextRemote", { session_id: sessionId });
444
+ if (remote?.context) {
445
+ return {
446
+ sessionId: remote.session_id,
447
+ ...(remote.context.session_label
448
+ ? { label: remote.context.session_label }
449
+ : {}),
450
+ ...(remote.context.cwd ? { cwd: remote.context.cwd } : {}),
451
+ ...(remote.context.active_project_uuid
452
+ ? { activeProjectUuid: remote.context.active_project_uuid }
453
+ : {}),
454
+ ...(remote.context.active_project_name
455
+ ? { activeProjectName: remote.context.active_project_name }
456
+ : {}),
457
+ ...(remote.context.task ? { task: remote.context.task } : {}),
458
+ ...(remote.context.summary ? { summary: remote.context.summary } : {}),
459
+ ...(remote.context.files ? { files: remote.context.files } : {}),
460
+ ...(remote.context.decisions
461
+ ? { decisions: remote.context.decisions }
462
+ : {}),
463
+ ...(remote.context.risks ? { risks: remote.context.risks } : {}),
464
+ ...(remote.context.updated_at
465
+ ? { updatedAt: remote.context.updated_at }
466
+ : { updatedAt: new Date().toISOString() }),
467
+ };
468
+ }
469
+ return this.sessionStore.getSession(sessionId);
470
+ }
92
471
  }
93
472
  exports.NotifyService = NotifyService;
@@ -18,7 +18,7 @@ class NotifyTelegramTool {
18
18
  register(server) {
19
19
  server.registerTool("notify_telegram", {
20
20
  title: "Notify Telegram",
21
- description: "Use this for one-way status or progress notifications to the human linked to the session. Pass session_id explicitly after pairing; do not rely on implicit defaults unless cwd is also correct for this agent workspace. This does not wait for a reply and does not create inbox work for the agent.",
21
+ description: "Use this for one-way status or progress notifications to the human linked to the current console. Pass session_id explicitly; do not rely on implicit defaults unless cwd is also correct for this agent workspace. This does not wait for a reply and does not create a new work item for the agent.",
22
22
  inputSchema: schema_1.notifyTelegramInputSchema,
23
23
  outputSchema: schema_1.notifyTelegramOutputSchema,
24
24
  }, async (args) => {
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SendFileToTelegramTool = 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 SendFileToTelegramTool {
14
+ notifyService;
15
+ constructor(notifyService) {
16
+ this.notifyService = notifyService;
17
+ }
18
+ register(server) {
19
+ server.registerTool("send_file_to_telegram", {
20
+ title: "Send File To Telegram",
21
+ description: "Send an existing local workspace file to the human linked to the current console in Telegram. Use this when another console returned a real artifact or file and the final human-facing result must be delivered to Telegram. Pass session_id explicitly for gateway-routed consoles.",
22
+ inputSchema: schema_1.sendFileToTelegramInputSchema,
23
+ outputSchema: schema_1.sendFileToTelegramOutputSchema,
24
+ }, async (args) => {
25
+ const output = await this.notifyService.sendDocument(args);
26
+ return {
27
+ content: createContent(output),
28
+ structuredContent: output,
29
+ };
30
+ });
31
+ }
32
+ }
33
+ exports.SendFileToTelegramTool = SendFileToTelegramTool;
@@ -18,7 +18,7 @@ class ClearSessionContextTool {
18
18
  register(server) {
19
19
  server.registerTool("clear_session_context", {
20
20
  title: "Clear Session Context",
21
- description: "Use this for full session cleanup/reset. It removes saved context, pairing, and related per-session state for the session.",
21
+ description: "Use this for full console cleanup/reset. It removes saved context and related per-console state for the target console.",
22
22
  inputSchema: schema_1.clearSessionContextInputSchema,
23
23
  outputSchema: schema_1.clearSessionContextOutputSchema,
24
24
  }, async (args) => {
@@ -18,7 +18,7 @@ class GetSessionContextTool {
18
18
  register(server) {
19
19
  server.registerTool("get_session_context", {
20
20
  title: "Get Session Context",
21
- description: "Debug/setup tool. Read the saved context and Telegram binding status for a session. Do not call this in the normal inbox-processing path after a tmux nudge unless you are diagnosing state.",
21
+ description: "Debug/setup tool. Read the saved context and routing status for the current console. Use this when you need to inspect stored task summary, files, risks, or gateway-facing route state. Do not call it in the normal xchange-processing path unless you are diagnosing state.",
22
22
  inputSchema: schema_1.getSessionContextInputSchema,
23
23
  outputSchema: schema_1.getSessionContextOutputSchema,
24
24
  }, async (args) => {
@@ -18,7 +18,7 @@ class RenameSessionTool {
18
18
  register(server) {
19
19
  server.registerTool("rename_session", {
20
20
  title: "Rename Session",
21
- description: "Rename only the human-readable session label. Use this when the user wants a clearer session name; it does not change session_id, pairing, tmux target, or saved context.",
21
+ description: "Rename only the human-readable console label. Use this when the user wants a clearer console name; it does not change session_id or saved context.",
22
22
  inputSchema: schema_1.renameSessionInputSchema,
23
23
  outputSchema: schema_1.renameSessionOutputSchema,
24
24
  }, async (args) => {