@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,99 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TransportProjectEvents = void 0;
4
+ class TransportProjectEvents {
5
+ host;
6
+ constructor(host) {
7
+ this.host = host;
8
+ }
9
+ async handleProjectMemberJoinedEvent(input) {
10
+ const rawMemberLabel = input.member_display_name?.trim() ||
11
+ (input.member_telegram_username?.trim()
12
+ ? `@${input.member_telegram_username.trim().replace(/^@/u, "")}`
13
+ : null);
14
+ const sessions = await this.host.sessionStore.listSessions();
15
+ const notifiedChats = new Set();
16
+ for (const session of sessions) {
17
+ const binding = await this.host.bindingStore.getBinding(session.sessionId);
18
+ if (!binding || notifiedChats.has(binding.telegramChatId)) {
19
+ continue;
20
+ }
21
+ const locale = await this.host.resolveLocaleForTelegramUserId(binding.telegramUserId);
22
+ const memberLabel = rawMemberLabel ?? this.host.t(locale, "menu:notices.project.new_member");
23
+ await this.host.sendNotification({
24
+ sessionId: session.sessionId,
25
+ ...(session.label ? { sessionLabel: session.label } : {}),
26
+ recipient: {
27
+ telegramChatId: binding.telegramChatId,
28
+ telegramUserId: binding.telegramUserId,
29
+ },
30
+ message: this.host.t(locale, "menu:notices.project.member_joined", {
31
+ projectName: input.project_name,
32
+ memberLabel,
33
+ }),
34
+ });
35
+ notifiedChats.add(binding.telegramChatId);
36
+ }
37
+ }
38
+ async handleProjectMemberLeftEvent(input) {
39
+ const rawMemberLabel = input.member_display_name?.trim() ||
40
+ (input.member_telegram_username?.trim()
41
+ ? `@${input.member_telegram_username.trim().replace(/^@/u, "")}`
42
+ : null);
43
+ const sessions = await this.host.sessionStore.listSessions();
44
+ const notifiedChats = new Set();
45
+ for (const session of sessions) {
46
+ const binding = await this.host.bindingStore.getBinding(session.sessionId);
47
+ if (!binding || notifiedChats.has(binding.telegramChatId)) {
48
+ continue;
49
+ }
50
+ const locale = await this.host.resolveLocaleForTelegramUserId(binding.telegramUserId);
51
+ const memberLabel = rawMemberLabel ?? this.host.t(locale, "menu:notices.project.member");
52
+ await this.host.sendNotification({
53
+ sessionId: session.sessionId,
54
+ ...(session.label ? { sessionLabel: session.label } : {}),
55
+ recipient: {
56
+ telegramChatId: binding.telegramChatId,
57
+ telegramUserId: binding.telegramUserId,
58
+ },
59
+ message: this.host.t(locale, "menu:notices.project.member_left", {
60
+ projectName: input.project_name,
61
+ memberLabel,
62
+ }),
63
+ });
64
+ notifiedChats.add(binding.telegramChatId);
65
+ }
66
+ }
67
+ async handleProjectDeletedEvent(input) {
68
+ const sessions = await this.host.sessionStore.listSessions();
69
+ const notifiedChats = new Set();
70
+ for (const session of sessions) {
71
+ if (session.activeProjectUuid === input.project_uuid) {
72
+ await this.host.sessionStore.setSession({
73
+ ...session,
74
+ activeProjectUuid: undefined,
75
+ activeProjectName: undefined,
76
+ updatedAt: new Date().toISOString(),
77
+ });
78
+ }
79
+ const binding = await this.host.bindingStore.getBinding(session.sessionId);
80
+ if (!binding || notifiedChats.has(binding.telegramChatId)) {
81
+ continue;
82
+ }
83
+ const locale = await this.host.resolveLocaleForTelegramUserId(binding.telegramUserId);
84
+ await this.host.sendNotification({
85
+ sessionId: session.sessionId,
86
+ ...(session.label ? { sessionLabel: session.label } : {}),
87
+ recipient: {
88
+ telegramChatId: binding.telegramChatId,
89
+ telegramUserId: binding.telegramUserId,
90
+ },
91
+ message: this.host.t(locale, "menu:notices.project.deleted", {
92
+ projectName: input.project_name,
93
+ }),
94
+ });
95
+ notifiedChats.add(binding.telegramChatId);
96
+ }
97
+ }
98
+ }
99
+ exports.TransportProjectEvents = TransportProjectEvents;
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TransportProjectMenus = void 0;
4
+ const menu_1 = require("@grammyjs/menu");
5
+ class TransportProjectMenus {
6
+ host;
7
+ constructor(host) {
8
+ this.host = host;
9
+ }
10
+ createProjectsMenu() {
11
+ return new menu_1.Menu("telegram-projects-menu", {
12
+ fingerprint: async (ctx) => this.host.buildProjectsFingerprint(ctx),
13
+ ...this.host.createMenuOptions((ctx) => this.host.showProjectsMenu(ctx)),
14
+ })
15
+ .dynamic(async (ctx) => {
16
+ const range = new menu_1.MenuRange();
17
+ const { session, projects } = await this.host.loadProjectsContext(ctx);
18
+ if (!session || !projects) {
19
+ range.text(await this.host.tForContext(ctx, "common:menu.gateway_unavailable"), async (innerCtx) => {
20
+ await innerCtx.answerCallbackQuery({
21
+ text: await this.host.tForContext(innerCtx, "menu:collab.actions.gateway_only"),
22
+ show_alert: true,
23
+ });
24
+ });
25
+ return range;
26
+ }
27
+ if (projects.length === 0) {
28
+ range
29
+ .text(await this.host.tForContext(ctx, "menu:collab.labels.no_projects"), async (innerCtx) => {
30
+ await innerCtx.answerCallbackQuery({
31
+ text: await this.host.tForContext(innerCtx, "menu:collab.actions.no_projects"),
32
+ });
33
+ })
34
+ .row();
35
+ return range;
36
+ }
37
+ for (const project of projects) {
38
+ const isActive = session.activeProjectUuid === project.project_uuid;
39
+ range
40
+ .text({
41
+ text: `${isActive ? "✅" : "📁"} ${project.name}`,
42
+ payload: async () => this.host.createProjectMenuPayload(session.sessionId, project.project_uuid, project.name),
43
+ }, async (innerCtx) => {
44
+ await this.host.handleProjectSelect(innerCtx);
45
+ })
46
+ .row();
47
+ }
48
+ return range;
49
+ })
50
+ .text(async (ctx) => this.host.tForContext(ctx, "menu:collab.buttons.create"), async (ctx) => {
51
+ await this.host.beginProjectMode(ctx, "create");
52
+ })
53
+ .text(async (ctx) => this.host.tForContext(ctx, "menu:collab.buttons.tools"), async (ctx) => {
54
+ await ctx.answerCallbackQuery({
55
+ text: await this.host.tForContext(ctx, "menu:collab.actions.open_tools"),
56
+ });
57
+ await this.host.showCollabToolsMenu(ctx);
58
+ })
59
+ .row()
60
+ .text(async (ctx) => this.host.tForContext(ctx, "menu:collab.buttons.join"), async (ctx) => {
61
+ await this.host.beginProjectMode(ctx, "join");
62
+ })
63
+ .text(async (ctx) => this.host.tForContext(ctx, "common:menu.back"), async (ctx) => {
64
+ await ctx.answerCallbackQuery({
65
+ text: await this.host.tForContext(ctx, "menu:collab.actions.back_to_session_menu"),
66
+ });
67
+ await this.host.showMainMenu(ctx);
68
+ });
69
+ }
70
+ createCollabToolsMenu() {
71
+ return new menu_1.Menu("telegram-collab-tools-menu", this.host.createMenuOptions((ctx) => this.host.showCollabToolsMenu(ctx)))
72
+ .text(async (ctx) => this.host.tForContext(ctx, "menu:collab.buttons.broadcast"), async (ctx) => {
73
+ await this.host.beginProjectBroadcast(ctx);
74
+ })
75
+ .text(async (ctx) => this.host.tForContext(ctx, "menu:collab.buttons.history"), async (ctx) => {
76
+ await this.host.handleCollabHistoryExport(ctx);
77
+ })
78
+ .row()
79
+ .text(async (ctx) => this.host.tForContext(ctx, "menu:collab.buttons.delete"), async (ctx) => {
80
+ await ctx.answerCallbackQuery({
81
+ text: await this.host.tForContext(ctx, "menu:collab.actions.open_delete"),
82
+ });
83
+ await this.host.showCollabDeleteMenu(ctx);
84
+ })
85
+ .row()
86
+ .text(async (ctx) => this.host.tForContext(ctx, "common:menu.back"), async (ctx) => {
87
+ await ctx.answerCallbackQuery({
88
+ text: await this.host.tForContext(ctx, "menu:collab.actions.back_to_collab"),
89
+ });
90
+ await this.host.showProjectsMenu(ctx);
91
+ });
92
+ }
93
+ createCollabDeleteMenu() {
94
+ return new menu_1.Menu("telegram-collab-delete-menu", {
95
+ fingerprint: async (ctx) => this.host.buildProjectsFingerprint(ctx),
96
+ ...this.host.createMenuOptions((ctx) => this.host.showCollabDeleteMenu(ctx)),
97
+ })
98
+ .dynamic(async (ctx) => {
99
+ const range = new menu_1.MenuRange();
100
+ const { session, projects } = await this.host.loadProjectsContext(ctx);
101
+ if (!session || !projects) {
102
+ range.text(await this.host.tForContext(ctx, "common:menu.gateway_unavailable"), async (innerCtx) => {
103
+ await innerCtx.answerCallbackQuery({
104
+ text: await this.host.tForContext(innerCtx, "menu:collab.actions.gateway_only"),
105
+ show_alert: true,
106
+ });
107
+ });
108
+ return range;
109
+ }
110
+ if (projects.length === 0) {
111
+ range.text(await this.host.tForContext(ctx, "menu:collab.labels.no_projects"), async (innerCtx) => {
112
+ await innerCtx.answerCallbackQuery({
113
+ text: await this.host.tForContext(innerCtx, "menu:collab.actions.no_projects"),
114
+ });
115
+ });
116
+ return range;
117
+ }
118
+ for (const project of projects.filter((item) => item.role === "owner")) {
119
+ range
120
+ .text({
121
+ text: `🗑 ${project.name}`,
122
+ payload: async () => this.host.createProjectDeleteMenuPayload(session.sessionId, project.project_uuid, project.name),
123
+ }, async (innerCtx) => {
124
+ await this.host.handleProjectDeleteSelect(innerCtx);
125
+ })
126
+ .row();
127
+ }
128
+ return range;
129
+ })
130
+ .text(async (ctx) => this.host.tForContext(ctx, "common:menu.back"), async (ctx) => {
131
+ await ctx.answerCallbackQuery({
132
+ text: await this.host.tForContext(ctx, "menu:collab.actions.back_to_tools"),
133
+ });
134
+ await this.host.showCollabToolsMenu(ctx);
135
+ });
136
+ }
137
+ }
138
+ exports.TransportProjectMenus = TransportProjectMenus;
@@ -0,0 +1,308 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TransportProjectState = void 0;
4
+ const relay_1 = require("../../../app/webapp/relay");
5
+ class TransportProjectState {
6
+ host;
7
+ constructor(host) {
8
+ this.host = host;
9
+ }
10
+ extractShortSessionLabel(session, fallback) {
11
+ const label = session.label?.trim() || fallback;
12
+ const separator = " · ";
13
+ const separatorIndex = label.indexOf(separator);
14
+ if (separatorIndex <= 0) {
15
+ return label;
16
+ }
17
+ return label.slice(0, separatorIndex).trim() || fallback;
18
+ }
19
+ async resolveProjectClientTarget(input) {
20
+ const resolvedSessionId = input.sessionId ??
21
+ (await this.host.bindingStore.getActiveSessionIdForPrincipal(input.principal));
22
+ if (resolvedSessionId) {
23
+ const relay = (0, relay_1.parseLiveRelaySessionId)(resolvedSessionId);
24
+ if (relay) {
25
+ return {
26
+ clientUuid: relay.clientUuid,
27
+ localSessionId: relay.localSessionId,
28
+ sessionId: resolvedSessionId,
29
+ };
30
+ }
31
+ }
32
+ return {
33
+ clientUuid: await this.ensureGatewayClientUuid(input.principal, input.actor),
34
+ localSessionId: resolvedSessionId ?? null,
35
+ sessionId: resolvedSessionId ?? null,
36
+ };
37
+ }
38
+ async ensureGatewayClientUuid(principal, actor) {
39
+ const existing = await this.host.maintenanceStore.getGatewayClientUuid();
40
+ if (existing && !actor) {
41
+ return existing;
42
+ }
43
+ const response = await this.host.callGatewayJson("/client/register", {
44
+ ...(existing ? { client_uuid: existing } : {}),
45
+ client_label: this.host.config.project.name ||
46
+ this.host.config.telegram.botUsername ||
47
+ "telegram-mcp client",
48
+ bot_username: this.host.config.telegram.botUsername,
49
+ ...(this.host.config.distributed.gatewayToken
50
+ ? { gateway_token: this.host.config.distributed.gatewayToken }
51
+ : {}),
52
+ meta: {
53
+ telegram_chat_id: principal.telegramChatId,
54
+ telegram_user_id: principal.telegramUserId,
55
+ ...(actor?.telegramUsername
56
+ ? { telegram_username: actor.telegramUsername }
57
+ : {}),
58
+ ...(actor?.telegramFirstName
59
+ ? { telegram_first_name: actor.telegramFirstName }
60
+ : {}),
61
+ ...(actor?.telegramLastName ? { telegram_last_name: actor.telegramLastName } : {}),
62
+ ...(actor?.telegramDisplayName
63
+ ? { telegram_display_name: actor.telegramDisplayName }
64
+ : {}),
65
+ },
66
+ });
67
+ await this.host.maintenanceStore.setGatewayClientUuid(response.client_uuid);
68
+ return response.client_uuid;
69
+ }
70
+ async listGatewayProjects(principal, actor) {
71
+ const target = await this.resolveProjectClientTarget({
72
+ principal,
73
+ ...(actor ? { actor } : {}),
74
+ });
75
+ const response = await this.host.callGatewayJson("/projects/list", {
76
+ client_uuid: target.clientUuid,
77
+ ...(target.localSessionId
78
+ ? { local_session_id: target.localSessionId }
79
+ : {}),
80
+ });
81
+ return response.projects;
82
+ }
83
+ async listGatewayProjectSessions(principal, projectUuid) {
84
+ const { clientUuid } = await this.resolveProjectClientTarget({
85
+ principal,
86
+ });
87
+ const response = await this.host.callGatewayJson("/projects/sessions", {
88
+ client_uuid: clientUuid,
89
+ project_uuid: projectUuid,
90
+ });
91
+ return response.sessions;
92
+ }
93
+ async listGatewaySessionHistory(principal, localSessionId) {
94
+ const { clientUuid } = await this.resolveProjectClientTarget({
95
+ principal,
96
+ });
97
+ const response = await this.host.callGatewayJson("/history/list", {
98
+ client_uuid: clientUuid,
99
+ local_session_id: localSessionId,
100
+ limit: 5,
101
+ });
102
+ return Array.isArray(response.history) ? response.history : [];
103
+ }
104
+ async ensureProjectSessionRegistered(input) {
105
+ const session = await this.host.sessionStore.getSession(input.sessionId);
106
+ if (!session) {
107
+ throw new Error("Active session not found.");
108
+ }
109
+ const target = await this.resolveProjectClientTarget({
110
+ principal: input.principal,
111
+ sessionId: input.sessionId,
112
+ });
113
+ const localSessionId = target.localSessionId ?? session.sessionId;
114
+ await this.host.callGatewayJson("/sessions/register", {
115
+ client_uuid: target.clientUuid,
116
+ project_uuid: input.projectUuid,
117
+ local_session_id: localSessionId,
118
+ label: this.extractShortSessionLabel(session, localSessionId),
119
+ cwd: session.cwd,
120
+ status: "active",
121
+ });
122
+ }
123
+ async loadProjectsContext(ctx) {
124
+ const principal = this.host.getPrincipalFromContext(ctx);
125
+ if (!principal || !this.host.config.distributed.gatewayPublicUrl) {
126
+ return { principal, session: null, projects: null };
127
+ }
128
+ const activeSessionId = await this.host.bindingStore.getActiveSessionIdForPrincipal(principal);
129
+ if (!activeSessionId) {
130
+ return { principal, session: null, projects: null };
131
+ }
132
+ const session = await this.host.sessionStore.getSession(activeSessionId);
133
+ if (!session) {
134
+ return { principal, session: null, projects: null };
135
+ }
136
+ const projects = await this.listGatewayProjects(principal, this.host.getGatewayActorFromContext(ctx));
137
+ return { principal, session, projects };
138
+ }
139
+ async activateProjectForSession(input) {
140
+ const session = await this.host.sessionStore.getSession(input.sessionId);
141
+ if (!session) {
142
+ throw new Error("Active session not found.");
143
+ }
144
+ await this.host.sessionStore.setSession({
145
+ ...session,
146
+ activeProjectUuid: input.projectUuid,
147
+ activeProjectName: input.projectName,
148
+ updatedAt: new Date().toISOString(),
149
+ });
150
+ }
151
+ async ensureOpenedProjectIsActive(input) {
152
+ const session = await this.host.sessionStore.getSession(input.sessionId);
153
+ if (session?.activeProjectUuid === input.projectUuid &&
154
+ session.activeProjectName === input.projectName) {
155
+ return;
156
+ }
157
+ await this.activateProjectForSession(input);
158
+ }
159
+ async buildProjectsFingerprint(ctx) {
160
+ const { session, projects } = await this.loadProjectsContext(ctx);
161
+ return `${session?.sessionId ?? "none"}:${session?.activeProjectUuid ?? "none"}:${projects?.map((item) => item.project_uuid).join(",") ?? "none"}`;
162
+ }
163
+ async getProjectPayloadByUuid(sessionId, projectUuid) {
164
+ const session = await this.host.sessionStore.getSession(sessionId);
165
+ if (!session) {
166
+ return null;
167
+ }
168
+ const principalBinding = await this.host.bindingStore.getBinding(sessionId);
169
+ if (!principalBinding) {
170
+ return null;
171
+ }
172
+ const projects = await this.listGatewayProjects({
173
+ telegramChatId: principalBinding.telegramChatId,
174
+ telegramUserId: principalBinding.telegramUserId,
175
+ });
176
+ const project = projects.find((item) => item.project_uuid === projectUuid);
177
+ if (!project) {
178
+ return null;
179
+ }
180
+ return {
181
+ sessionId,
182
+ projectUuid,
183
+ projectName: project.name,
184
+ inviteToken: project.invite_token,
185
+ };
186
+ }
187
+ async getProjectMemberPayloadByKey(payloadKey) {
188
+ const payload = await this.host.menuPayloadStore.getMenuPayload(payloadKey);
189
+ if (!payload ||
190
+ (payload.kind !== "project-member" &&
191
+ payload.kind !== "project-file-target") ||
192
+ !payload.sessionId ||
193
+ !payload.projectUuid ||
194
+ !payload.targetSessionId) {
195
+ return null;
196
+ }
197
+ const project = await this.getProjectPayloadByUuid(String(payload.sessionId), String(payload.projectUuid));
198
+ if (!project) {
199
+ return null;
200
+ }
201
+ return {
202
+ sessionId: String(payload.sessionId),
203
+ projectUuid: String(payload.projectUuid),
204
+ projectName: project.projectName,
205
+ inviteToken: project.inviteToken,
206
+ targetSessionId: String(payload.targetSessionId),
207
+ targetSessionLabel: String(payload.title ?? payload.targetSessionId),
208
+ ...(payload.targetClientUuid
209
+ ? { targetClientUuid: String(payload.targetClientUuid) }
210
+ : {}),
211
+ ...(payload.targetLocalSessionId
212
+ ? { targetLocalSessionId: String(payload.targetLocalSessionId) }
213
+ : {}),
214
+ ...(payload.filePath ? { filePath: String(payload.filePath) } : {}),
215
+ };
216
+ }
217
+ async getPartnerFileTargetPayloadByKey(payloadKey) {
218
+ const payload = await this.host.menuPayloadStore.getMenuPayload(payloadKey);
219
+ if (!payload ||
220
+ payload.kind !== "partner-file-target" ||
221
+ !payload.sessionId ||
222
+ !payload.targetSessionId ||
223
+ !payload.filePath) {
224
+ return null;
225
+ }
226
+ return {
227
+ sessionId: String(payload.sessionId),
228
+ targetSessionId: String(payload.targetSessionId),
229
+ targetSessionLabel: String(payload.title ?? payload.targetSessionId),
230
+ filePath: String(payload.filePath),
231
+ };
232
+ }
233
+ async getLiveApprovalPayloadByKey(payloadKey) {
234
+ const payload = await this.host.menuPayloadStore.getMenuPayload(payloadKey);
235
+ if (!payload ||
236
+ payload.kind !== "live-approval" ||
237
+ !payload.sessionId ||
238
+ !payload.sourceSessionId ||
239
+ !payload.sourceSessionLabel ||
240
+ !payload.sourceClientUuid ||
241
+ !payload.sourceLocalSessionId ||
242
+ !payload.targetSessionId ||
243
+ !payload.title ||
244
+ !payload.targetClientUuid ||
245
+ !payload.targetLocalSessionId) {
246
+ return null;
247
+ }
248
+ return {
249
+ sessionId: String(payload.sessionId),
250
+ sourceSessionId: String(payload.sourceSessionId),
251
+ sourceSessionLabel: String(payload.sourceSessionLabel),
252
+ sourceClientUuid: String(payload.sourceClientUuid),
253
+ sourceLocalSessionId: String(payload.sourceLocalSessionId),
254
+ targetSessionId: String(payload.targetSessionId),
255
+ targetSessionLabel: String(payload.title),
256
+ targetClientUuid: String(payload.targetClientUuid),
257
+ targetLocalSessionId: String(payload.targetLocalSessionId),
258
+ ...(payload.projectUuid ? { projectUuid: String(payload.projectUuid) } : {}),
259
+ ...(payload.projectName ? { projectName: String(payload.projectName) } : {}),
260
+ };
261
+ }
262
+ buildRelaySessionContext(input) {
263
+ const relaySessionId = (0, relay_1.buildLiveRelaySessionId)(input.targetClientUuid, input.targetLocalSessionId);
264
+ const now = new Date().toISOString();
265
+ return {
266
+ sessionId: relaySessionId,
267
+ label: input.targetSessionLabel,
268
+ ...(input.projectUuid ? { activeProjectUuid: input.projectUuid } : {}),
269
+ ...(input.projectName ? { activeProjectName: input.projectName } : {}),
270
+ updatedAt: now,
271
+ };
272
+ }
273
+ async bindRelaySessionToPrincipal(input) {
274
+ const session = this.buildRelaySessionContext(input.payload);
275
+ const existingSession = await this.host.sessionStore.getSession(session.sessionId);
276
+ await this.host.sessionStore.setSession({
277
+ ...(existingSession ?? session),
278
+ ...session,
279
+ ...(existingSession?.cwd ? { cwd: existingSession.cwd } : {}),
280
+ ...(existingSession?.task ? { task: existingSession.task } : {}),
281
+ ...(existingSession?.summary ? { summary: existingSession.summary } : {}),
282
+ ...(existingSession?.files ? { files: existingSession.files } : {}),
283
+ ...(existingSession?.decisions
284
+ ? { decisions: existingSession.decisions }
285
+ : {}),
286
+ ...(existingSession?.risks ? { risks: existingSession.risks } : {}),
287
+ ...(existingSession?.lastSeenToolsHash
288
+ ? { lastSeenToolsHash: existingSession.lastSeenToolsHash }
289
+ : {}),
290
+ ...(existingSession?.lastNotifiedToolsHash
291
+ ? { lastNotifiedToolsHash: existingSession.lastNotifiedToolsHash }
292
+ : {}),
293
+ updatedAt: new Date().toISOString(),
294
+ });
295
+ await this.host.bindingStore.setBinding({
296
+ sessionId: session.sessionId,
297
+ telegramChatId: input.principal.telegramChatId,
298
+ telegramUserId: input.principal.telegramUserId,
299
+ ...(input.ctx.from?.username
300
+ ? { telegramUsername: input.ctx.from.username }
301
+ : {}),
302
+ linkedAt: new Date().toISOString(),
303
+ });
304
+ await this.host.bindingStore.setActiveSessionIdForPrincipal(input.principal, session.sessionId);
305
+ return session;
306
+ }
307
+ }
308
+ exports.TransportProjectState = TransportProjectState;