@deadragdoll/tellymcp 0.0.10 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) 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 +205 -384
  5. package/README.md +195 -1194
  6. package/TOOLS.md +294 -377
  7. package/VERSION.md +11 -11
  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 +897 -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 +116 -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/browserScreenshotTool.js +1 -1
  42. package/dist/services/features/telegram-mcp/src/features/browser/model/browserService.js +249 -19
  43. package/dist/services/features/telegram-mcp/src/features/collaboration/model/gatewaySessionsService.js +71 -0
  44. package/dist/services/features/telegram-mcp/src/features/collaboration/model/listGatewaySessionsTool.js +33 -0
  45. package/dist/services/features/telegram-mcp/src/features/collaboration/model/localCollaborationBackend.js +93 -82
  46. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileService.js +47 -5
  47. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileTool.js +1 -1
  48. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerNoteTool.js +1 -1
  49. package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayClientAccess.js +82 -0
  50. package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayCollaborationBackend.js +22 -14
  51. package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayHttpService.js +649 -75
  52. package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/remoteConsoleActionClient.js +76 -0
  53. package/dist/services/features/telegram-mcp/src/features/embedded-runtime/model/embeddedRuntimeBroker.js +92 -0
  54. package/dist/services/features/telegram-mcp/src/features/foreground-terminal/model/foregroundTerminalRuntime.js +192 -0
  55. package/dist/services/features/telegram-mcp/src/features/notify/model/notifyService.js +382 -3
  56. package/dist/services/features/telegram-mcp/src/features/notify/model/notifyTelegramTool.js +1 -1
  57. package/dist/services/features/telegram-mcp/src/features/notify/model/sendFileToTelegramTool.js +33 -0
  58. package/dist/services/features/telegram-mcp/src/features/session-context/model/clearSessionContextTool.js +1 -1
  59. package/dist/services/features/telegram-mcp/src/features/session-context/model/getSessionContextTool.js +1 -1
  60. package/dist/services/features/telegram-mcp/src/features/session-context/model/renameSessionTool.js +1 -1
  61. package/dist/services/features/telegram-mcp/src/features/session-context/model/sessionContextService.js +42 -200
  62. package/dist/services/features/telegram-mcp/src/features/session-context/model/setSessionContextTool.js +1 -1
  63. package/dist/services/features/telegram-mcp/src/features/terminal-buffer/model/terminalBufferService.js +96 -0
  64. package/dist/services/features/telegram-mcp/src/features/terminal-input/model/terminalInputService.js +97 -0
  65. package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownService.js +107 -58
  66. package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownTool.js +1 -1
  67. package/dist/services/features/telegram-mcp/src/features/xchange/model/getXchangeRecordTool.js +28 -0
  68. package/dist/services/features/telegram-mcp/src/features/xchange/model/listXchangeRecordsTool.js +28 -0
  69. package/dist/services/features/telegram-mcp/src/features/xchange/model/markXchangeRecordReadTool.js +28 -0
  70. package/dist/services/features/telegram-mcp/src/features/xchange/model/xchangeService.js +169 -0
  71. package/dist/services/features/telegram-mcp/src/processes/human-approval/model/orchestrator.js +5 -4
  72. package/dist/services/features/telegram-mcp/src/shared/i18n/resources/en.js +139 -42
  73. package/dist/services/features/telegram-mcp/src/shared/i18n/resources/ru.js +135 -38
  74. package/dist/services/features/telegram-mcp/src/shared/integrations/memory/processLocalSessionStore.js +27 -0
  75. package/dist/services/features/telegram-mcp/src/shared/integrations/object-storage/minioExchangeStore.js +11 -8
  76. package/dist/services/features/telegram-mcp/src/shared/integrations/redis/stateStore.js +42 -71
  77. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/proxyFetch.js +21 -22
  78. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +415 -7101
  79. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportAttachmentStore.js +93 -0
  80. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportBroadcastActions.js +385 -0
  81. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConsoleRegistry.js +143 -0
  82. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConstructorWiring.js +633 -0
  83. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportContent.js +84 -0
  84. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportContext.js +78 -0
  85. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportDocumentActions.js +36 -0
  86. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportEventActions.js +292 -0
  87. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportFileHandoffActions.js +352 -0
  88. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportFormatting.js +75 -0
  89. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportGatewayActions.js +44 -0
  90. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLifecycleActions.js +161 -0
  91. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLive.js +56 -0
  92. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLiveActions.js +77 -0
  93. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuCallbacks.js +254 -0
  94. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFactories.js +538 -0
  95. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFingerprints.js +93 -0
  96. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFlow.js +344 -0
  97. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuShell.js +62 -0
  98. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuState.js +408 -0
  99. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuText.js +216 -0
  100. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMessageFlow.js +452 -0
  101. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportOutputActions.js +189 -0
  102. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportPartnerActions.js +286 -0
  103. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportPayloadState.js +101 -0
  104. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectActions.js +463 -0
  105. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectEntryActions.js +202 -0
  106. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectEvents.js +99 -0
  107. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectMenus.js +138 -0
  108. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectState.js +308 -0
  109. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectView.js +426 -0
  110. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportRequestFlow.js +278 -0
  111. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportSessionActions.js +143 -0
  112. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalActions.js +468 -0
  113. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalRuntime.js +171 -0
  114. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTypes.js +2 -0
  115. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportUtils.js +330 -0
  116. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportXchangeState.js +107 -0
  117. package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/client.js +255 -0
  118. package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/ptyRegistry.js +543 -0
  119. package/dist/services/features/telegram-mcp/src/shared/integrations/xchange/sqliteRecordStore.js +223 -0
  120. package/dist/services/features/telegram-mcp/src/shared/lib/gatewayScope.js +24 -0
  121. package/dist/services/features/telegram-mcp/src/shared/lib/logger/logger.js +6 -0
  122. package/dist/services/features/telegram-mcp/src/shared/lib/project-identity/projectIdentity.js +147 -76
  123. package/dist/services/features/telegram-mcp/src/shared/lib/telegramXchangeRecords.js +72 -0
  124. package/dist/services/features/telegram-mcp/src/shared/lib/terminalPromptDetection.js +237 -0
  125. package/dist/services/features/telegram-mcp/src/shared/lib/version/versionHandshake.js +129 -1
  126. package/dist/services/features/telegram-mcp/src/shared/lib/xchangeRecordHints.js +98 -0
  127. package/dist/services/features/telegram-mcp/standalone-http.service.js +12 -0
  128. package/dist/services/features/telegram-mcp/terminal-buffer.service.js +42 -0
  129. package/dist/services/features/telegram-mcp/terminal-input.service.js +41 -0
  130. package/dist/services/features/telegram-mcp/tools-sync.service.js +15 -1
  131. package/dist/services/features/telegram-mcp/xchange.service.js +123 -0
  132. package/docs/STANDALONE-ru.md +172 -0
  133. package/docs/STANDALONE.md +172 -0
  134. package/package.json +10 -5
  135. package/scripts/build-package-artifact.sh +27 -0
  136. package/scripts/deploy-gateway.sh +64 -0
  137. package/scripts/deploy-onebot-branch.sh +27 -0
  138. package/scripts/postinstall.js +11 -36
  139. package/STANDALONE-ru.md +0 -274
  140. package/STANDALONE.md +0 -274
  141. package/dist/services/features/telegram-mcp/inbox.service.js +0 -33
  142. package/dist/services/features/telegram-mcp/pair.service.js +0 -33
  143. package/dist/services/features/telegram-mcp/src/app/webapp/tmux.js +0 -10
  144. package/dist/services/features/telegram-mcp/src/features/inbox/model/deleteTelegramInboxMessageTool.js +0 -33
  145. package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxCountTool.js +0 -33
  146. package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxTool.js +0 -33
  147. package/dist/services/features/telegram-mcp/src/features/inbox/model/inboxService.js +0 -77
  148. package/dist/services/features/telegram-mcp/src/features/pair-session/model/clearSessionPairingTool.js +0 -33
  149. package/dist/services/features/telegram-mcp/src/features/pair-session/model/createSessionPairCodeTool.js +0 -33
  150. package/dist/services/features/telegram-mcp/src/features/pair-session/model/generatePairCode.js +0 -202
  151. package/dist/services/features/telegram-mcp/src/features/session-context/model/getTmuxTargetTool.js +0 -33
  152. package/dist/services/features/telegram-mcp/src/features/session-context/model/setTmuxTargetTool.js +0 -33
  153. package/dist/services/features/telegram-mcp/src/shared/integrations/tmux/client.js +0 -363
@@ -0,0 +1,408 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TransportMenuState = void 0;
4
+ const node_crypto_1 = require("node:crypto");
5
+ const node_fs_1 = require("node:fs");
6
+ const node_path_1 = require("node:path");
7
+ const versionHandshake_1 = require("../../lib/version/versionHandshake");
8
+ const transportMenuText_1 = require("./transportMenuText");
9
+ const transportUtils_1 = require("./transportUtils");
10
+ class TransportMenuState {
11
+ host;
12
+ constructor(host) {
13
+ this.host = host;
14
+ }
15
+ async collectDeveloperInfo(ctx) {
16
+ const principal = this.host.getPrincipalFromContext(ctx);
17
+ if (!principal) {
18
+ return {
19
+ headerMarkdown: (0, transportUtils_1.renderMarkdownChunk)("Gateway Info", "No Telegram identity."),
20
+ clientMarkdownChunks: [],
21
+ };
22
+ }
23
+ const clientsResult = await this.host.callGatewayJson("/clients/list", {
24
+ telegram_user_id: principal.telegramUserId,
25
+ });
26
+ const connectedResult = await this.host.callGatewayJson("/clients/connected", {});
27
+ const ownedClientUuids = new Set(clientsResult.clients.map((client) => client.client_uuid));
28
+ const connectedClients = connectedResult.clients.filter((client) => ownedClientUuids.has(client.client_uuid));
29
+ const packageVersion = (0, versionHandshake_1.getTellyMcpPackageVersion)(__dirname);
30
+ const toolsHash = this.getGatewayToolsHash();
31
+ const connectedClientCount = new Set(connectedClients.map((client) => client.client_uuid)).size;
32
+ const connectedSessionCount = connectedClients.reduce((total, client) => total + client.session_tools.length, 0);
33
+ const headerLines = [
34
+ `Gateway package: ${packageVersion}`,
35
+ `Gateway TOOLS hash: ${toolsHash ?? "unknown"}`,
36
+ `Clients: ${clientsResult.clients.length}`,
37
+ `Connected clients: ${connectedClientCount}`,
38
+ `Connected sessions: ${connectedSessionCount}`,
39
+ ];
40
+ const clientByUuid = new Map(clientsResult.clients.map((client) => [client.client_uuid, client]));
41
+ const clientMarkdownChunks = connectedClients.flatMap((connectedClient) => {
42
+ const client = clientByUuid.get(connectedClient.client_uuid);
43
+ if (!client) {
44
+ return [];
45
+ }
46
+ return connectedClient.session_tools.map((sessionTool) => {
47
+ const owner = client.telegram_display_name ||
48
+ (client.telegram_username
49
+ ? `@${client.telegram_username}`
50
+ : client.system_username || client.client_label || client.node_id || client.client_uuid);
51
+ const sessionName = sessionTool.session_label?.trim() || sessionTool.local_session_id;
52
+ const title = `${owner} / ${sessionName}`;
53
+ const bodyLines = [
54
+ `client_uuid: ${client.client_uuid}`,
55
+ `session_id: ${sessionTool.local_session_id}`,
56
+ `node: ${client.node_id || client.client_label || "unknown"}`,
57
+ ...(sessionTool.tools_hash
58
+ ? [`tools_hash: ${sessionTool.tools_hash}`]
59
+ : []),
60
+ ...(connectedClient.package_version
61
+ ? [`agent_version: ${connectedClient.package_version}`]
62
+ : []),
63
+ ...(client.last_seen_at ? [`last_seen_at: ${client.last_seen_at}`] : []),
64
+ ];
65
+ return (0, transportUtils_1.renderMarkdownChunk)(title, bodyLines.join("\n"));
66
+ });
67
+ });
68
+ return {
69
+ headerMarkdown: (0, transportUtils_1.renderMarkdownChunk)("Gateway Info", headerLines.join("\n")),
70
+ clientMarkdownChunks,
71
+ };
72
+ }
73
+ getGatewayToolsHash() {
74
+ const packageRoot = (0, versionHandshake_1.getTellyMcpPackageRoot)(__dirname);
75
+ if (!packageRoot) {
76
+ return null;
77
+ }
78
+ try {
79
+ const content = (0, node_fs_1.readFileSync)((0, node_path_1.join)(packageRoot, "TOOLS.md"), "utf8");
80
+ return (0, node_crypto_1.createHash)("sha256").update(content).digest("hex");
81
+ }
82
+ catch {
83
+ return null;
84
+ }
85
+ }
86
+ async showMainMenu(ctx, introText) {
87
+ this.host.setCurrentAttachmentTargetForContext(ctx, null);
88
+ const text = await this.buildMainMenuText(ctx);
89
+ const intro = introText ? (0, transportUtils_1.escapeHtml)(introText) : null;
90
+ await this.host.renderMenuHtmlScreen(ctx, intro ? `${intro}\n\n${text}` : text, { kind: "menu" }, this.host.getMainMenu());
91
+ }
92
+ async buildMainMenuText(ctx) {
93
+ const locale = await this.host.resolveLocaleForContext(ctx);
94
+ const principal = this.host.getPrincipalFromContext(ctx);
95
+ if (!principal) {
96
+ return this.host.t(locale, "common:errors.no_telegram_identity");
97
+ }
98
+ const activeSessionId = await this.host.bindingStore.getActiveSessionIdForPrincipal(principal);
99
+ if (!activeSessionId) {
100
+ return this.host.t(locale, "common:errors.no_active_session");
101
+ }
102
+ const session = await this.host.sessionStore.getSession(activeSessionId);
103
+ const sessionName = (0, transportUtils_1.escapeHtml)(session?.label ?? activeSessionId);
104
+ const projectName = session?.activeProjectName
105
+ ? (0, transportUtils_1.escapeHtml)(session.activeProjectName)
106
+ : null;
107
+ return (0, transportMenuText_1.buildMainMenuText)({
108
+ title: this.host.t(locale, "menu:main.screen.title", { sessionName }),
109
+ projectLine: projectName
110
+ ? this.host.t(locale, "menu:main.screen.project", { projectName })
111
+ : null,
112
+ });
113
+ }
114
+ async showSessionsMenu(ctx, introText) {
115
+ this.host.setCurrentAttachmentTargetForContext(ctx, null);
116
+ const principal = this.host.getPrincipalFromContext(ctx);
117
+ if (principal) {
118
+ await this.host.bindingStore.clearActiveSessionIdForPrincipal(principal);
119
+ }
120
+ try {
121
+ const text = await this.buildSessionsMenuText(ctx);
122
+ const intro = introText ? (0, transportUtils_1.escapeHtml)(introText) : null;
123
+ await this.host.renderMenuHtmlScreen(ctx, intro ? `${intro}\n\n${text}` : text, { kind: "menu" }, this.host.getSessionsMenu());
124
+ }
125
+ catch (error) {
126
+ this.host.logger.error("Failed to render Telegram sessions menu", {
127
+ chatId: ctx.chat?.id,
128
+ userId: ctx.from?.id,
129
+ error: error instanceof Error ? (error.stack ?? error.message) : String(error),
130
+ });
131
+ await this.host.replyText(ctx, this.host.t(await this.host.resolveLocaleForContext(ctx), "menu:system.sessions_menu_unavailable"), { kind: "menu" });
132
+ }
133
+ }
134
+ async buildSessionsMenuText(ctx) {
135
+ const locale = await this.host.resolveLocaleForContext(ctx);
136
+ const principal = this.host.getPrincipalFromContext(ctx);
137
+ if (!principal) {
138
+ return this.host.t(locale, "common:errors.no_telegram_identity");
139
+ }
140
+ const sessionIds = (await this.host.bindingStore.listBoundSessionIdsForPrincipal(principal)).sort();
141
+ if (sessionIds.length === 0) {
142
+ return this.host.t(locale, "menu:sessions.screen.no_linked_sessions");
143
+ }
144
+ let lastWorkedSession;
145
+ for (const sessionId of sessionIds) {
146
+ const session = await this.host.sessionStore.getSession(sessionId);
147
+ const sessionUpdatedAtMs = session?.updatedAt
148
+ ? Date.parse(session.updatedAt)
149
+ : Number.NEGATIVE_INFINITY;
150
+ const lastWorkedUpdatedAtMs = lastWorkedSession?.updatedAt
151
+ ? Date.parse(lastWorkedSession.updatedAt)
152
+ : Number.NEGATIVE_INFINITY;
153
+ if (sessionUpdatedAtMs >= lastWorkedUpdatedAtMs) {
154
+ lastWorkedSession = {
155
+ sessionId,
156
+ label: session?.label,
157
+ updatedAt: session?.updatedAt,
158
+ };
159
+ }
160
+ }
161
+ const lines = [this.host.t(locale, "menu:sessions.screen.title"), ""];
162
+ if (lastWorkedSession) {
163
+ lines.push(this.host.t(locale, "menu:sessions.screen.last_worked", {
164
+ sessionName: (0, transportUtils_1.escapeHtml)(lastWorkedSession.label ?? lastWorkedSession.sessionId),
165
+ }));
166
+ const formattedUpdatedAt = (0, transportUtils_1.formatMenuTimestamp)(lastWorkedSession.updatedAt);
167
+ if (formattedUpdatedAt) {
168
+ lines.push(this.host.t(locale, "menu:sessions.screen.updated", {
169
+ timestamp: (0, transportUtils_1.escapeHtml)(formattedUpdatedAt),
170
+ }));
171
+ }
172
+ lines.push("");
173
+ }
174
+ const currentPayloadKey = (0, transportUtils_1.readMenuPayloadKey)(ctx);
175
+ let selectedOwnerTitle = null;
176
+ if (currentPayloadKey) {
177
+ const payload = await this.host.getMenuPayloadByKey(currentPayloadKey);
178
+ if (payload &&
179
+ (payload.kind === "session-group" || payload.kind === "active-session") &&
180
+ typeof payload.ownerKey === "string") {
181
+ selectedOwnerTitle =
182
+ typeof payload.ownerLabel === "string" && payload.ownerLabel.trim()
183
+ ? payload.ownerLabel.trim()
184
+ : null;
185
+ }
186
+ }
187
+ if (selectedOwnerTitle) {
188
+ lines[0] = (0, transportUtils_1.escapeHtml)(selectedOwnerTitle);
189
+ }
190
+ return lines.join("\n");
191
+ }
192
+ async showStorageMenu(ctx, introText) {
193
+ const text = await this.buildStorageMenuText(ctx);
194
+ await this.host.renderMenuScreen(ctx, introText ? `${introText}\n\n${text}` : text, { kind: "menu" }, this.host.getStorageMenu());
195
+ }
196
+ async buildStorageMenuText(ctx) {
197
+ const locale = await this.host.resolveLocaleForContext(ctx);
198
+ const principal = this.host.getPrincipalFromContext(ctx);
199
+ if (!principal) {
200
+ return this.host.t(locale, "common:errors.no_telegram_identity");
201
+ }
202
+ const activeSessionId = await this.host.bindingStore.getActiveSessionIdForPrincipal(principal);
203
+ if (!activeSessionId) {
204
+ return this.host.t(locale, "common:errors.no_active_session");
205
+ }
206
+ const session = await this.host.sessionStore.getSession(activeSessionId);
207
+ const entries = await this.host.listActiveSessionStorageEntries(activeSessionId);
208
+ return (0, transportMenuText_1.buildStorageMenuText)({
209
+ title: this.host.t(locale, "menu:storage.screen.title"),
210
+ activeSessionLine: this.host.t(locale, "menu:storage.screen.active_session", {
211
+ sessionName: session?.label ?? activeSessionId,
212
+ }),
213
+ storedFilesLine: this.host.t(locale, "menu:storage.screen.stored_files", {
214
+ count: entries.length,
215
+ }),
216
+ chooseFileLine: this.host.t(locale, "menu:storage.screen.choose_file"),
217
+ emptyLine: this.host.t(locale, "menu:storage.screen.empty"),
218
+ total: entries.length,
219
+ });
220
+ }
221
+ async showBrowserMenu(ctx, introText) {
222
+ const text = await this.buildBrowserMenuText(ctx);
223
+ await this.host.renderMenuScreen(ctx, introText ? `${introText}\n\n${text}` : text, { kind: "menu" }, this.host.getBrowserMenu());
224
+ }
225
+ async buildBrowserMenuText(ctx) {
226
+ const locale = await this.host.resolveLocaleForContext(ctx);
227
+ const principal = this.host.getPrincipalFromContext(ctx);
228
+ if (!principal) {
229
+ return this.host.t(locale, "common:errors.no_telegram_identity");
230
+ }
231
+ const activeSessionId = await this.host.bindingStore.getActiveSessionIdForPrincipal(principal);
232
+ if (!activeSessionId) {
233
+ return this.host.t(locale, "common:errors.no_active_session");
234
+ }
235
+ const session = await this.host.sessionStore.getSession(activeSessionId);
236
+ const screenshots = await this.host.listActiveSessionScreenshots(activeSessionId);
237
+ return (0, transportMenuText_1.buildBrowserMenuText)({
238
+ title: this.host.t(locale, "menu:browser.screen.title"),
239
+ activeSessionLine: this.host.t(locale, "menu:browser.screen.active_session", {
240
+ sessionName: session?.label ?? activeSessionId,
241
+ }),
242
+ storedScreenshotsLine: this.host.t(locale, "menu:browser.screen.stored_screenshots", { count: screenshots.length }),
243
+ chooseActionLine: this.host.t(locale, "menu:browser.screen.choose_action"),
244
+ });
245
+ }
246
+ async showScreenshotsMenu(ctx, introText) {
247
+ const text = await this.buildScreenshotsMenuText(ctx);
248
+ await this.host.renderMenuScreen(ctx, introText ? `${introText}\n\n${text}` : text, { kind: "menu" }, this.host.getScreenshotsMenu());
249
+ }
250
+ async buildScreenshotsMenuText(ctx) {
251
+ const locale = await this.host.resolveLocaleForContext(ctx);
252
+ const principal = this.host.getPrincipalFromContext(ctx);
253
+ if (!principal) {
254
+ return this.host.t(locale, "common:errors.no_telegram_identity");
255
+ }
256
+ const activeSessionId = await this.host.bindingStore.getActiveSessionIdForPrincipal(principal);
257
+ if (!activeSessionId) {
258
+ return this.host.t(locale, "common:errors.no_active_session");
259
+ }
260
+ const session = await this.host.sessionStore.getSession(activeSessionId);
261
+ const files = await this.host.listActiveSessionScreenshots(activeSessionId);
262
+ return (0, transportMenuText_1.buildScreenshotsMenuText)({
263
+ title: this.host.t(locale, "menu:screenshots.screen.title"),
264
+ activeSessionLine: this.host.t(locale, "menu:screenshots.screen.active_session", {
265
+ sessionName: session?.label ?? activeSessionId,
266
+ }),
267
+ storedScreenshotsLine: this.host.t(locale, "menu:screenshots.screen.stored_screenshots", { count: files.length }),
268
+ chooseScreenshotLine: this.host.t(locale, "menu:screenshots.screen.choose_screenshot"),
269
+ emptyLine: this.host.t(locale, "menu:screenshots.screen.empty"),
270
+ total: files.length,
271
+ });
272
+ }
273
+ async showSettingsMenu(ctx, introText) {
274
+ const text = await this.buildSettingsMenuText(ctx);
275
+ await this.host.renderMenuScreen(ctx, introText ? `${introText}\n\n${text}` : text, { kind: "menu" }, this.host.getSettingsMenu());
276
+ }
277
+ async buildSettingsMenuText(ctx) {
278
+ const locale = await this.host.resolveLocaleForContext(ctx);
279
+ const principal = this.host.getPrincipalFromContext(ctx);
280
+ if (!principal) {
281
+ return this.host.t(locale, "common:errors.no_telegram_identity");
282
+ }
283
+ const activeSessionId = await this.host.bindingStore.getActiveSessionIdForPrincipal(principal);
284
+ if (!activeSessionId) {
285
+ return this.host.t(locale, "common:errors.no_active_session");
286
+ }
287
+ const session = await this.host.sessionStore.getSession(activeSessionId);
288
+ return (0, transportMenuText_1.buildSettingsMenuText)({
289
+ title: this.host.t(locale, "menu:settings.screen.title"),
290
+ activeSessionLine: this.host.t(locale, "menu:settings.screen.active_session", {
291
+ sessionName: session?.label ?? activeSessionId,
292
+ }),
293
+ hintLine: this.host.t(locale, "menu:settings.screen.hint"),
294
+ });
295
+ }
296
+ async showBufferMenu(ctx, introText) {
297
+ const text = await this.buildBufferMenuText(ctx);
298
+ await this.host.renderMenuScreen(ctx, introText ? `${introText}\n\n${text}` : text, { kind: "menu" }, this.host.getBufferMenu());
299
+ }
300
+ async buildBufferMenuText(ctx) {
301
+ const locale = await this.host.resolveLocaleForContext(ctx);
302
+ const principal = this.host.getPrincipalFromContext(ctx);
303
+ if (!principal) {
304
+ return this.host.t(locale, "common:errors.no_telegram_identity");
305
+ }
306
+ const activeSessionId = await this.host.bindingStore.getActiveSessionIdForPrincipal(principal);
307
+ if (!activeSessionId) {
308
+ return this.host.t(locale, "common:errors.no_active_session");
309
+ }
310
+ const session = await this.host.sessionStore.getSession(activeSessionId);
311
+ return (0, transportMenuText_1.buildBufferMenuText)({
312
+ title: this.host.t(locale, "menu:buffer.screen.title"),
313
+ activeSessionLine: this.host.t(locale, "menu:buffer.screen.active_session", {
314
+ sessionName: session?.label ?? activeSessionId,
315
+ }),
316
+ terminalTargetLine: this.host.t(locale, "menu:buffer.screen.terminal_target", {
317
+ terminalTarget: session?.terminalTarget ?? "not set",
318
+ }),
319
+ exportHintLine: this.host.t(locale, "menu:buffer.screen.export_hint"),
320
+ exportModesLine: this.host.t(locale, "menu:buffer.screen.export_modes"),
321
+ });
322
+ }
323
+ async showDeveloperMenu(ctx, introText) {
324
+ const text = await this.buildDeveloperMenuText(ctx);
325
+ await this.host.renderMenuScreen(ctx, introText ? `${introText}\n\n${text}` : text, { kind: "menu" }, this.host.getDeveloperMenu());
326
+ }
327
+ async showDeveloperInfo(ctx, introText) {
328
+ const info = await this.collectDeveloperInfo(ctx);
329
+ const headerText = introText
330
+ ? `${(0, transportUtils_1.renderMarkdownChunk)("Gateway Info", introText)}\n\n${info.headerMarkdown}`
331
+ : info.headerMarkdown;
332
+ await this.host.renderMenuMarkdownScreen(ctx, headerText, { kind: "menu" }, this.host.getDeveloperMenu());
333
+ for (const clientMarkdown of info.clientMarkdownChunks) {
334
+ await this.host.replyText(ctx, clientMarkdown, { kind: "menu" }, { parse_mode: "MarkdownV2" });
335
+ }
336
+ }
337
+ async buildDeveloperMenuText(ctx) {
338
+ const locale = await this.host.resolveLocaleForContext(ctx);
339
+ const principal = this.host.getPrincipalFromContext(ctx);
340
+ if (!principal) {
341
+ return this.host.t(locale, "common:errors.no_telegram_identity");
342
+ }
343
+ const sessionIds = await this.host.bindingStore.listBoundSessionIdsForPrincipal(principal);
344
+ return [
345
+ this.host.t(locale, "menu:developer.screen.title"),
346
+ "",
347
+ this.host.t(locale, "menu:developer.screen.linked_sessions", {
348
+ count: sessionIds.length,
349
+ }),
350
+ "",
351
+ this.host.t(locale, "menu:developer.screen.broadcast_help"),
352
+ this.host.t(locale, "menu:developer.screen.prune_help"),
353
+ ].join("\n");
354
+ }
355
+ async buildDeveloperInfoMarkdown(ctx) {
356
+ const info = await this.collectDeveloperInfo(ctx);
357
+ return info.headerMarkdown;
358
+ }
359
+ async showUnpairConfirmMenu(ctx, introText) {
360
+ const text = await this.buildUnpairConfirmText(ctx);
361
+ await this.host.renderMenuScreen(ctx, introText ? `${introText}\n\n${text}` : text, { kind: "menu" }, this.host.getUnpairConfirmMenu());
362
+ }
363
+ async buildUnpairConfirmText(ctx) {
364
+ const locale = await this.host.resolveLocaleForContext(ctx);
365
+ const principal = this.host.getPrincipalFromContext(ctx);
366
+ if (!principal) {
367
+ return this.host.t(locale, "common:errors.no_telegram_identity");
368
+ }
369
+ const activeSessionId = await this.host.bindingStore.getActiveSessionIdForPrincipal(principal);
370
+ if (!activeSessionId) {
371
+ return this.host.t(locale, "common:errors.no_active_session");
372
+ }
373
+ const session = await this.host.sessionStore.getSession(activeSessionId);
374
+ return [
375
+ this.host.t(locale, "menu:unpair.title"),
376
+ "",
377
+ this.host.t(locale, "menu:unpair.active_session", {
378
+ sessionName: session?.label ?? activeSessionId,
379
+ }),
380
+ "",
381
+ this.host.t(locale, "menu:unpair.body_1"),
382
+ this.host.t(locale, "menu:unpair.body_2"),
383
+ ].join("\n");
384
+ }
385
+ async showPruneConfirmMenu(ctx, introText) {
386
+ const text = await this.buildPruneConfirmText(ctx);
387
+ await this.host.renderMenuScreen(ctx, introText ? `${introText}\n\n${text}` : text, { kind: "menu" }, this.host.getPruneConfirmMenu());
388
+ }
389
+ async buildPruneConfirmText(ctx) {
390
+ const locale = await this.host.resolveLocaleForContext(ctx);
391
+ const principal = this.host.getPrincipalFromContext(ctx);
392
+ if (!principal) {
393
+ return this.host.t(locale, "common:errors.no_telegram_identity");
394
+ }
395
+ const sessionIds = await this.host.bindingStore.listBoundSessionIdsForPrincipal(principal);
396
+ return [
397
+ this.host.t(locale, "menu:prune.title"),
398
+ "",
399
+ this.host.t(locale, "menu:prune.linked_sessions", {
400
+ count: sessionIds.length,
401
+ }),
402
+ "",
403
+ this.host.t(locale, "menu:prune.body_1"),
404
+ this.host.t(locale, "menu:prune.body_2"),
405
+ ].join("\n");
406
+ }
407
+ }
408
+ exports.TransportMenuState = TransportMenuState;
@@ -0,0 +1,216 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildLinkMenuText = buildLinkMenuText;
4
+ exports.buildMainMenuText = buildMainMenuText;
5
+ exports.buildAdminMainMenuText = buildAdminMainMenuText;
6
+ exports.buildBufferMenuText = buildBufferMenuText;
7
+ exports.buildBrowserMenuText = buildBrowserMenuText;
8
+ exports.buildSettingsMenuText = buildSettingsMenuText;
9
+ exports.buildScreenshotsMenuText = buildScreenshotsMenuText;
10
+ exports.buildStorageMenuText = buildStorageMenuText;
11
+ exports.buildPartnerMenuText = buildPartnerMenuText;
12
+ exports.buildLocalMenuText = buildLocalMenuText;
13
+ exports.buildProjectsMenuText = buildProjectsMenuText;
14
+ exports.buildCollabToolsMenuText = buildCollabToolsMenuText;
15
+ exports.buildCollabDeleteMenuText = buildCollabDeleteMenuText;
16
+ exports.buildAdminClientSessionsMenuText = buildAdminClientSessionsMenuText;
17
+ exports.buildAdminClientSessionListText = buildAdminClientSessionListText;
18
+ exports.buildAdminClientSessionDetailText = buildAdminClientSessionDetailText;
19
+ exports.buildAdminToolsMenuText = buildAdminToolsMenuText;
20
+ function buildLinkMenuText(input) {
21
+ return [
22
+ input.title,
23
+ "",
24
+ input.activeSessionLine,
25
+ "",
26
+ input.choosePartnerLine,
27
+ input.hintLine,
28
+ ].join("\n");
29
+ }
30
+ function buildMainMenuText(input) {
31
+ return [
32
+ input.title,
33
+ ...(input.projectLine ? [input.projectLine] : []),
34
+ ]
35
+ .filter((line) => Boolean(line))
36
+ .join("\n");
37
+ }
38
+ function buildAdminMainMenuText(input) {
39
+ return [
40
+ input.title,
41
+ "",
42
+ ...(input.unavailableLine
43
+ ? [input.unavailableLine]
44
+ : [
45
+ input.gatewayClientsLine,
46
+ input.connectedClientsLine,
47
+ input.registeredClientsLine,
48
+ ]),
49
+ "",
50
+ input.hintLine,
51
+ ]
52
+ .filter((line) => Boolean(line))
53
+ .join("\n");
54
+ }
55
+ function buildBufferMenuText(input) {
56
+ return [
57
+ input.title,
58
+ "",
59
+ input.activeSessionLine,
60
+ input.terminalTargetLine,
61
+ "",
62
+ input.exportHintLine,
63
+ input.exportModesLine,
64
+ ].join("\n");
65
+ }
66
+ function buildBrowserMenuText(input) {
67
+ return [
68
+ input.title,
69
+ "",
70
+ input.activeSessionLine,
71
+ input.storedScreenshotsLine,
72
+ "",
73
+ input.chooseActionLine,
74
+ ].join("\n");
75
+ }
76
+ function buildSettingsMenuText(input) {
77
+ return [
78
+ input.title,
79
+ "",
80
+ input.activeSessionLine,
81
+ "",
82
+ input.hintLine,
83
+ ].join("\n");
84
+ }
85
+ function buildScreenshotsMenuText(input) {
86
+ return [
87
+ input.title,
88
+ "",
89
+ input.activeSessionLine,
90
+ input.storedScreenshotsLine,
91
+ "",
92
+ input.total > 0 ? input.chooseScreenshotLine : input.emptyLine,
93
+ ].join("\n");
94
+ }
95
+ function buildStorageMenuText(input) {
96
+ return [
97
+ input.title,
98
+ "",
99
+ input.activeSessionLine,
100
+ input.storedFilesLine,
101
+ "",
102
+ input.total > 0 ? input.chooseFileLine : input.emptyLine,
103
+ ].join("\n");
104
+ }
105
+ function buildPartnerMenuText(input) {
106
+ if (!input.linkedPartnerLine) {
107
+ return [
108
+ input.title,
109
+ "",
110
+ input.activeSessionLine,
111
+ "",
112
+ input.noPartnerLine,
113
+ input.useLinkFirstLine,
114
+ ]
115
+ .filter((line) => Boolean(line))
116
+ .join("\n");
117
+ }
118
+ return [
119
+ input.title,
120
+ "",
121
+ input.activeSessionLine,
122
+ input.linkedPartnerLine,
123
+ "",
124
+ input.promptHintLine,
125
+ input.promptFormatLine,
126
+ ]
127
+ .filter((line) => Boolean(line))
128
+ .join("\n");
129
+ }
130
+ function buildLocalMenuText(input) {
131
+ return [
132
+ input.title,
133
+ "",
134
+ input.activeSessionLine,
135
+ input.linkStatusLine,
136
+ "",
137
+ input.hintTitleLine,
138
+ input.hintBodyLine,
139
+ ].join("\n");
140
+ }
141
+ function buildProjectsMenuText(input) {
142
+ if (input.gatewayNotConfiguredLine) {
143
+ return [
144
+ input.title,
145
+ "",
146
+ input.gatewayNotConfiguredLine,
147
+ input.useLocalInsteadLine,
148
+ ]
149
+ .filter((line) => Boolean(line))
150
+ .join("\n");
151
+ }
152
+ return [
153
+ input.title,
154
+ "",
155
+ input.activeSessionLine,
156
+ input.openProjectLine,
157
+ input.projectCountLine,
158
+ "",
159
+ input.inviteHintLine,
160
+ ]
161
+ .filter((line) => Boolean(line))
162
+ .join("\n");
163
+ }
164
+ function buildCollabToolsMenuText(input) {
165
+ return [
166
+ input.title,
167
+ "",
168
+ input.activeSessionLine,
169
+ input.projectCountLine,
170
+ input.sessionCountLine,
171
+ "",
172
+ input.broadcastLine,
173
+ input.historyLine,
174
+ input.hintLine,
175
+ ].join("\n");
176
+ }
177
+ function buildCollabDeleteMenuText(input) {
178
+ return [
179
+ input.title,
180
+ "",
181
+ input.activeSessionLine,
182
+ input.totalCountLine,
183
+ input.ownerCountLine,
184
+ "",
185
+ input.chooseLine,
186
+ input.bodyLine,
187
+ input.ownerHintLine,
188
+ ].join("\n");
189
+ }
190
+ function buildAdminClientSessionsMenuText(input) {
191
+ return [input.title, "", input.clientLine, "", input.chooseScopeLine].join("\n");
192
+ }
193
+ function buildAdminClientSessionListText(input) {
194
+ return [
195
+ input.title,
196
+ "",
197
+ input.scopeLine,
198
+ input.clientLine,
199
+ "",
200
+ input.emptyLine ?? input.chooseLine,
201
+ ]
202
+ .filter((line) => Boolean(line))
203
+ .join("\n");
204
+ }
205
+ function buildAdminClientSessionDetailText(input) {
206
+ return [
207
+ input.title,
208
+ "",
209
+ input.sessionLine,
210
+ `ID: <code>${input.localSessionId}</code>`,
211
+ ...(input.projectLine ? [input.projectLine] : []),
212
+ ].join("\n");
213
+ }
214
+ function buildAdminToolsMenuText(input) {
215
+ return [input.title, "", input.clientEnvHelpLine].join("\n");
216
+ }