@deadragdoll/tellymcp 0.0.9 → 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 (157) hide show
  1. package/.env.example.client +42 -50
  2. package/.env.example.gateway +49 -61
  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 +36 -10
  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 +40 -20
  15. package/config/templates/env.client.template +34 -18
  16. package/config/templates/env.gateway.template +38 -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/approval.service.js +1 -1
  23. package/dist/services/features/telegram-mcp/browser.service.js +95 -2
  24. package/dist/services/features/telegram-mcp/collaboration.service.js +41 -4
  25. package/dist/services/features/telegram-mcp/ensuredb.service.js +145 -26
  26. package/dist/services/features/telegram-mcp/gateway-delivery.service.js +285 -103
  27. package/dist/services/features/telegram-mcp/gateway-rmq.service.js +3 -2
  28. package/dist/services/features/telegram-mcp/gateway-socket.service.js +905 -87
  29. package/dist/services/features/telegram-mcp/gateway.service.js +876 -81
  30. package/dist/services/features/telegram-mcp/mcp-http.service.js +9 -1
  31. package/dist/services/features/telegram-mcp/mcp-server.service.js +17 -26
  32. package/dist/services/features/telegram-mcp/notify.service.js +128 -2
  33. package/dist/services/features/telegram-mcp/runtime.service.js +27 -7
  34. package/dist/services/features/telegram-mcp/session-context.service.js +29 -2
  35. package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +133 -10
  36. package/dist/services/features/telegram-mcp/src/app/config/env.js +161 -51
  37. package/dist/services/features/telegram-mcp/src/app/http.js +375 -42
  38. package/dist/services/features/telegram-mcp/src/app/webapp/assets.js +386 -58
  39. package/dist/services/features/telegram-mcp/src/app/webapp/auth.js +3 -0
  40. package/dist/services/features/telegram-mcp/src/app/webapp/terminal.js +12 -0
  41. package/dist/services/features/telegram-mcp/src/entities/request/model/schema.js +116 -104
  42. package/dist/services/features/telegram-mcp/src/entities/xchange/model/types.js +2 -0
  43. package/dist/services/features/telegram-mcp/src/features/ask-user/model/askUserTelegram.js +1 -1
  44. package/dist/services/features/telegram-mcp/src/features/browser/model/browserScreenshotTool.js +1 -1
  45. package/dist/services/features/telegram-mcp/src/features/browser/model/browserService.js +249 -19
  46. package/dist/services/features/telegram-mcp/src/features/collaboration/model/gatewaySessionsService.js +71 -0
  47. package/dist/services/features/telegram-mcp/src/features/collaboration/model/listGatewaySessionsTool.js +33 -0
  48. package/dist/services/features/telegram-mcp/src/features/collaboration/model/localCollaborationBackend.js +93 -82
  49. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileService.js +47 -5
  50. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileTool.js +1 -1
  51. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerNoteTool.js +1 -1
  52. package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayClientAccess.js +82 -0
  53. package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayCollaborationBackend.js +22 -14
  54. package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayHttpService.js +649 -75
  55. package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/remoteConsoleActionClient.js +76 -0
  56. package/dist/services/features/telegram-mcp/src/features/embedded-runtime/model/embeddedRuntimeBroker.js +92 -0
  57. package/dist/services/features/telegram-mcp/src/features/foreground-terminal/model/foregroundTerminalRuntime.js +192 -0
  58. package/dist/services/features/telegram-mcp/src/features/notify/model/notifyService.js +382 -3
  59. package/dist/services/features/telegram-mcp/src/features/notify/model/notifyTelegramTool.js +1 -1
  60. package/dist/services/features/telegram-mcp/src/features/notify/model/sendFileToTelegramTool.js +33 -0
  61. package/dist/services/features/telegram-mcp/src/features/session-context/model/clearSessionContextTool.js +1 -1
  62. package/dist/services/features/telegram-mcp/src/features/session-context/model/getSessionContextTool.js +1 -1
  63. package/dist/services/features/telegram-mcp/src/features/session-context/model/renameSessionTool.js +1 -1
  64. package/dist/services/features/telegram-mcp/src/features/session-context/model/sessionContextService.js +42 -200
  65. package/dist/services/features/telegram-mcp/src/features/session-context/model/setSessionContextTool.js +1 -1
  66. package/dist/services/features/telegram-mcp/src/features/terminal-buffer/model/terminalBufferService.js +96 -0
  67. package/dist/services/features/telegram-mcp/src/features/terminal-input/model/terminalInputService.js +97 -0
  68. package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownService.js +107 -58
  69. package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownTool.js +1 -1
  70. package/dist/services/features/telegram-mcp/src/features/xchange/model/getXchangeRecordTool.js +28 -0
  71. package/dist/services/features/telegram-mcp/src/features/xchange/model/listXchangeRecordsTool.js +28 -0
  72. package/dist/services/features/telegram-mcp/src/features/xchange/model/markXchangeRecordReadTool.js +28 -0
  73. package/dist/services/features/telegram-mcp/src/features/xchange/model/xchangeService.js +169 -0
  74. package/dist/services/features/telegram-mcp/src/processes/human-approval/model/orchestrator.js +5 -4
  75. package/dist/services/features/telegram-mcp/src/shared/i18n/index.js +46 -0
  76. package/dist/services/features/telegram-mcp/src/shared/i18n/resources/en.js +652 -0
  77. package/dist/services/features/telegram-mcp/src/shared/i18n/resources/ru.js +652 -0
  78. package/dist/services/features/telegram-mcp/src/shared/integrations/memory/processLocalSessionStore.js +27 -0
  79. package/dist/services/features/telegram-mcp/src/shared/integrations/object-storage/minioExchangeStore.js +11 -8
  80. package/dist/services/features/telegram-mcp/src/shared/integrations/redis/stateStore.js +51 -71
  81. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/proxyFetch.js +21 -22
  82. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +411 -6524
  83. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportAttachmentStore.js +93 -0
  84. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportBroadcastActions.js +385 -0
  85. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConsoleRegistry.js +143 -0
  86. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConstructorWiring.js +633 -0
  87. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportContent.js +84 -0
  88. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportContext.js +78 -0
  89. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportDocumentActions.js +36 -0
  90. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportEventActions.js +292 -0
  91. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportFileHandoffActions.js +352 -0
  92. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportFormatting.js +75 -0
  93. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportGatewayActions.js +44 -0
  94. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLifecycleActions.js +161 -0
  95. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLive.js +56 -0
  96. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportLiveActions.js +77 -0
  97. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuCallbacks.js +254 -0
  98. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFactories.js +538 -0
  99. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFingerprints.js +93 -0
  100. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuFlow.js +344 -0
  101. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuShell.js +62 -0
  102. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuState.js +408 -0
  103. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuText.js +216 -0
  104. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMessageFlow.js +452 -0
  105. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportOutputActions.js +189 -0
  106. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportPartnerActions.js +286 -0
  107. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportPayloadState.js +101 -0
  108. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectActions.js +463 -0
  109. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectEntryActions.js +202 -0
  110. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectEvents.js +99 -0
  111. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectMenus.js +138 -0
  112. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectState.js +308 -0
  113. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportProjectView.js +426 -0
  114. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportRequestFlow.js +278 -0
  115. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportSessionActions.js +143 -0
  116. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalActions.js +468 -0
  117. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalRuntime.js +171 -0
  118. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTypes.js +2 -0
  119. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportUtils.js +330 -0
  120. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportXchangeState.js +107 -0
  121. package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/client.js +255 -0
  122. package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/ptyRegistry.js +543 -0
  123. package/dist/services/features/telegram-mcp/src/shared/integrations/xchange/sqliteRecordStore.js +223 -0
  124. package/dist/services/features/telegram-mcp/src/shared/lib/gatewayScope.js +24 -0
  125. package/dist/services/features/telegram-mcp/src/shared/lib/logger/logger.js +6 -0
  126. package/dist/services/features/telegram-mcp/src/shared/lib/project-identity/projectIdentity.js +147 -76
  127. package/dist/services/features/telegram-mcp/src/shared/lib/telegramXchangeRecords.js +72 -0
  128. package/dist/services/features/telegram-mcp/src/shared/lib/terminalPromptDetection.js +237 -0
  129. package/dist/services/features/telegram-mcp/src/shared/lib/version/versionHandshake.js +129 -1
  130. package/dist/services/features/telegram-mcp/src/shared/lib/xchangeRecordHints.js +98 -0
  131. package/dist/services/features/telegram-mcp/standalone-http.service.js +13 -1
  132. package/dist/services/features/telegram-mcp/terminal-buffer.service.js +42 -0
  133. package/dist/services/features/telegram-mcp/terminal-input.service.js +41 -0
  134. package/dist/services/features/telegram-mcp/tools-sync.service.js +16 -2
  135. package/dist/services/features/telegram-mcp/xchange.service.js +123 -0
  136. package/docs/STANDALONE-ru.md +172 -0
  137. package/docs/STANDALONE.md +172 -0
  138. package/package.json +11 -5
  139. package/scripts/build-package-artifact.sh +27 -0
  140. package/scripts/deploy-gateway.sh +64 -0
  141. package/scripts/deploy-onebot-branch.sh +27 -0
  142. package/scripts/postinstall.js +11 -36
  143. package/STANDALONE-ru.md +0 -274
  144. package/STANDALONE.md +0 -274
  145. package/dist/services/features/telegram-mcp/inbox.service.js +0 -33
  146. package/dist/services/features/telegram-mcp/pair.service.js +0 -33
  147. package/dist/services/features/telegram-mcp/src/app/webapp/tmux.js +0 -10
  148. package/dist/services/features/telegram-mcp/src/features/inbox/model/deleteTelegramInboxMessageTool.js +0 -33
  149. package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxCountTool.js +0 -33
  150. package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxTool.js +0 -33
  151. package/dist/services/features/telegram-mcp/src/features/inbox/model/inboxService.js +0 -77
  152. package/dist/services/features/telegram-mcp/src/features/pair-session/model/clearSessionPairingTool.js +0 -33
  153. package/dist/services/features/telegram-mcp/src/features/pair-session/model/createSessionPairCodeTool.js +0 -33
  154. package/dist/services/features/telegram-mcp/src/features/pair-session/model/generatePairCode.js +0 -202
  155. package/dist/services/features/telegram-mcp/src/features/session-context/model/getTmuxTargetTool.js +0 -33
  156. package/dist/services/features/telegram-mcp/src/features/session-context/model/setTmuxTargetTool.js +0 -33
  157. package/dist/services/features/telegram-mcp/src/shared/integrations/tmux/client.js +0 -363
@@ -0,0 +1,463 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TransportProjectActions = void 0;
4
+ const relay_1 = require("../../../app/webapp/relay");
5
+ class TransportProjectActions {
6
+ host;
7
+ constructor(host) {
8
+ this.host = host;
9
+ }
10
+ async handleProjectSetCallback(ctx) {
11
+ const locale = await this.host.resolveLocaleForContext(ctx);
12
+ const projectUuid = this.host.extractCallbackSuffix(ctx, "project-set:");
13
+ const principal = this.host.getPrincipalFromContext(ctx);
14
+ if (!projectUuid || !principal) {
15
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.invalid_action"), show_alert: true });
16
+ return;
17
+ }
18
+ const sessionId = await this.host.bindingStore.getActiveSessionIdForPrincipal(principal);
19
+ if (!sessionId) {
20
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "common:errors.no_active_session"), show_alert: true });
21
+ return;
22
+ }
23
+ const payload = await this.host.getProjectPayloadByUuid(sessionId, projectUuid);
24
+ if (!payload) {
25
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.not_found"), show_alert: true });
26
+ return;
27
+ }
28
+ await this.host.ensureProjectSessionRegistered({
29
+ principal,
30
+ sessionId,
31
+ projectUuid: payload.projectUuid,
32
+ });
33
+ await this.host.activateProjectForSession({
34
+ principal,
35
+ sessionId,
36
+ projectUuid: payload.projectUuid,
37
+ projectName: payload.projectName,
38
+ });
39
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.opening_members") });
40
+ await this.host.showProjectMembers(ctx, payload);
41
+ }
42
+ async handleProjectDetailCallback(ctx) {
43
+ const locale = await this.host.resolveLocaleForContext(ctx);
44
+ const projectUuid = this.host.extractCallbackSuffix(ctx, "project-detail:");
45
+ const principal = this.host.getPrincipalFromContext(ctx);
46
+ if (!projectUuid || !principal) {
47
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.invalid_action"), show_alert: true });
48
+ return;
49
+ }
50
+ const sessionId = await this.host.bindingStore.getActiveSessionIdForPrincipal(principal);
51
+ if (!sessionId) {
52
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "common:errors.no_active_session"), show_alert: true });
53
+ return;
54
+ }
55
+ const payload = await this.host.getProjectPayloadByUuid(sessionId, projectUuid);
56
+ if (!payload) {
57
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.not_found"), show_alert: true });
58
+ return;
59
+ }
60
+ await this.host.ensureProjectSessionRegistered({
61
+ principal,
62
+ sessionId,
63
+ projectUuid: payload.projectUuid,
64
+ });
65
+ await this.host.ensureOpenedProjectIsActive({
66
+ principal,
67
+ sessionId,
68
+ projectUuid: payload.projectUuid,
69
+ projectName: payload.projectName,
70
+ });
71
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.opening_members") });
72
+ await this.host.showProjectMembers(ctx, payload);
73
+ }
74
+ async handleProjectDeleteCallback(ctx) {
75
+ const locale = await this.host.resolveLocaleForContext(ctx);
76
+ const projectUuid = this.host.extractCallbackSuffix(ctx, "project-delete:");
77
+ if (!projectUuid) {
78
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.invalid_action"), show_alert: true });
79
+ return;
80
+ }
81
+ await this.handleProjectDeleteByUuid(ctx, projectUuid);
82
+ }
83
+ async handleProjectMemberOpenCallback(ctx) {
84
+ const locale = await this.host.resolveLocaleForContext(ctx);
85
+ const payloadKey = this.host.extractCallbackSuffix(ctx, "project-member-open:");
86
+ if (!payloadKey) {
87
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.invalid_member_payload"), show_alert: true });
88
+ return;
89
+ }
90
+ const payload = await this.host.getProjectMemberPayloadByKey(payloadKey);
91
+ if (!payload) {
92
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.stale_member_payload"), show_alert: true });
93
+ await ctx.deleteMessage().catch(() => undefined);
94
+ return;
95
+ }
96
+ if (payload.filePath) {
97
+ await this.host.beginFileHandoffModeForTarget(ctx, {
98
+ sessionId: payload.sessionId,
99
+ filePath: payload.filePath,
100
+ targetSessionId: payload.targetSessionId,
101
+ targetSessionLabel: payload.targetSessionLabel,
102
+ projectUuid: payload.projectUuid,
103
+ });
104
+ return;
105
+ }
106
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.opening_session") });
107
+ await this.host.showProjectMemberDetail(ctx, payload);
108
+ }
109
+ async handleProjectMemberNoteCallback(ctx) {
110
+ const locale = await this.host.resolveLocaleForContext(ctx);
111
+ const data = ctx.callbackQuery?.data ?? "";
112
+ const match = data.match(/^project-member-note:(question|share):(.+)$/u);
113
+ if (!match) {
114
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.invalid_member_action"), show_alert: true });
115
+ return;
116
+ }
117
+ const [, kind, payloadKeyRaw] = match;
118
+ const payloadKey = payloadKeyRaw?.trim();
119
+ if (!payloadKey) {
120
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.invalid_member_payload"), show_alert: true });
121
+ return;
122
+ }
123
+ const payload = await this.host.getProjectMemberPayloadByKey(payloadKey);
124
+ if (!payload) {
125
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.stale_member_payload"), show_alert: true });
126
+ await ctx.deleteMessage().catch(() => undefined);
127
+ return;
128
+ }
129
+ await this.host.beginPartnerNoteMode(ctx, kind, {
130
+ targetSessionId: payload.targetSessionId,
131
+ targetSessionLabel: payload.targetSessionLabel,
132
+ projectUuid: payload.projectUuid,
133
+ });
134
+ }
135
+ async handleProjectMemberLiveCallback(ctx) {
136
+ const locale = await this.host.resolveLocaleForContext(ctx);
137
+ const payloadKey = this.host.extractCallbackSuffix(ctx, "project-member-live:");
138
+ if (!payloadKey) {
139
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.invalid_live_payload"), show_alert: true });
140
+ return;
141
+ }
142
+ const payload = await this.host.getProjectMemberPayloadByKey(payloadKey);
143
+ if (!payload || !payload.targetClientUuid || !payload.targetLocalSessionId) {
144
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.stale_live_payload"), show_alert: true });
145
+ await ctx.deleteMessage().catch(() => undefined);
146
+ return;
147
+ }
148
+ const principal = this.host.getPrincipalFromContext(ctx);
149
+ if (!principal) {
150
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.no_telegram_user"), show_alert: true });
151
+ return;
152
+ }
153
+ const sourceRelay = (0, relay_1.parseLiveRelaySessionId)(payload.sessionId);
154
+ const session = await this.host.sessionStore.getSession(payload.sessionId);
155
+ const actor = this.host.getGatewayActorFromContext(ctx);
156
+ const sourceClientUuid = sourceRelay?.clientUuid ??
157
+ (await this.host.ensureGatewayClientUuid(principal, actor));
158
+ const sourceLocalSessionId = sourceRelay?.localSessionId ?? payload.sessionId;
159
+ const result = await this.host.callGatewayJson("/live/request-approval", {
160
+ client_uuid: payload.targetClientUuid,
161
+ payload: {
162
+ ...(payload.projectUuid ? { project_uuid: payload.projectUuid } : {}),
163
+ ...(payload.projectName ? { project_name: payload.projectName } : {}),
164
+ source_session_id: payload.sessionId,
165
+ source_session_label: session?.label ?? payload.sessionId,
166
+ source_client_uuid: sourceClientUuid,
167
+ source_local_session_id: sourceLocalSessionId,
168
+ target_session_id: payload.targetSessionId,
169
+ target_session_label: payload.targetSessionLabel,
170
+ target_client_uuid: payload.targetClientUuid,
171
+ target_local_session_id: payload.targetLocalSessionId,
172
+ },
173
+ });
174
+ await ctx.answerCallbackQuery({
175
+ text: result?.delivered
176
+ ? this.host.t(locale, "menu:project.request_live_sent")
177
+ : this.host.t(locale, "menu:live.actions.approval_unavailable"),
178
+ ...(result?.delivered ? {} : { show_alert: true }),
179
+ });
180
+ }
181
+ async handleLiveApprovalCallback(ctx) {
182
+ const locale = await this.host.resolveLocaleForContext(ctx);
183
+ const data = ctx.callbackQuery?.data ?? "";
184
+ const match = data.match(/^live-approval:(approve|deny):(.+)$/u);
185
+ if (!match) {
186
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.invalid_approval"), show_alert: true });
187
+ return;
188
+ }
189
+ const [, decision, payloadKeyRaw] = match;
190
+ const payloadKey = payloadKeyRaw?.trim();
191
+ if (!payloadKey) {
192
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.invalid_approval_data"), show_alert: true });
193
+ return;
194
+ }
195
+ const payload = await this.host.getLiveApprovalPayloadByKey(payloadKey);
196
+ if (!payload) {
197
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.approval_stale"), show_alert: true });
198
+ await ctx.deleteMessage().catch(() => undefined);
199
+ return;
200
+ }
201
+ const approved = decision === "approve";
202
+ const result = await this.host.callGatewayJson("/live/resolve-approval", {
203
+ client_uuid: payload.sourceClientUuid,
204
+ approved,
205
+ payload: {
206
+ ...(payload.projectUuid ? { project_uuid: payload.projectUuid } : {}),
207
+ ...(payload.projectName ? { project_name: payload.projectName } : {}),
208
+ source_session_id: payload.sourceSessionId,
209
+ source_session_label: payload.sourceSessionLabel,
210
+ source_client_uuid: payload.sourceClientUuid,
211
+ source_local_session_id: payload.sourceLocalSessionId,
212
+ target_session_id: payload.targetSessionId,
213
+ target_session_label: payload.targetSessionLabel,
214
+ target_client_uuid: payload.targetClientUuid,
215
+ target_local_session_id: payload.targetLocalSessionId,
216
+ },
217
+ });
218
+ await ctx.answerCallbackQuery({
219
+ text: approved
220
+ ? this.host.t(locale, "menu:live.approval.approved")
221
+ : this.host.t(locale, "menu:live.approval.denied"),
222
+ });
223
+ if (ctx.callbackQuery?.message) {
224
+ await this.host.editText(ctx, [
225
+ approved
226
+ ? this.host.t(locale, "menu:live.approval.approved")
227
+ : this.host.t(locale, "menu:live.approval.denied"),
228
+ "",
229
+ ...(payload.projectName
230
+ ? [this.host.t(locale, "menu:live.approval.project", { projectName: payload.projectName })]
231
+ : []),
232
+ this.host.t(locale, "menu:live.approval.route", {
233
+ sourceSessionName: payload.sourceSessionLabel,
234
+ targetSessionName: payload.targetSessionLabel,
235
+ }),
236
+ "",
237
+ result?.delivered
238
+ ? approved
239
+ ? this.host.t(locale, "menu:live.approval.source_open")
240
+ : this.host.t(locale, "menu:live.approval.result_denied", {
241
+ sourceSessionName: payload.sourceSessionLabel,
242
+ targetSessionName: payload.targetSessionLabel,
243
+ })
244
+ : this.host.t(locale, "menu:live.actions.approval_unavailable"),
245
+ ].join("\n"), { kind: "menu", sessionId: payload.sessionId });
246
+ }
247
+ }
248
+ async handleProjectMemberFilesCallback(ctx) {
249
+ const locale = await this.host.resolveLocaleForContext(ctx);
250
+ const payloadKey = this.host.extractCallbackSuffix(ctx, "project-member-files:");
251
+ if (!payloadKey) {
252
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.invalid_member_payload"), show_alert: true });
253
+ return;
254
+ }
255
+ const payload = await this.host.getProjectMemberPayloadByKey(payloadKey);
256
+ if (!payload) {
257
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.stale_member_payload"), show_alert: true });
258
+ await ctx.deleteMessage().catch(() => undefined);
259
+ return;
260
+ }
261
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.opening_files") });
262
+ await this.host.showProjectMemberFiles(ctx, payload);
263
+ }
264
+ async handlePartnerFileOpenCallback(ctx) {
265
+ const locale = await this.host.resolveLocaleForContext(ctx);
266
+ const payloadKey = this.host.extractCallbackSuffix(ctx, "partner-file-open:");
267
+ if (!payloadKey) {
268
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.invalid_member_payload"), show_alert: true });
269
+ return;
270
+ }
271
+ const payload = await this.host.getPartnerFileTargetPayloadByKey(payloadKey);
272
+ if (!payload) {
273
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.data_stale"), show_alert: true });
274
+ return;
275
+ }
276
+ await this.host.beginFileHandoffModeForTarget(ctx, {
277
+ sessionId: payload.sessionId,
278
+ filePath: payload.filePath,
279
+ targetSessionId: payload.targetSessionId,
280
+ targetSessionLabel: payload.targetSessionLabel,
281
+ });
282
+ }
283
+ async handleProjectMembersCallback(ctx) {
284
+ const locale = await this.host.resolveLocaleForContext(ctx);
285
+ const projectUuid = this.host.extractCallbackSuffix(ctx, "project-members:");
286
+ const principal = this.host.getPrincipalFromContext(ctx);
287
+ if (!projectUuid || !principal) {
288
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.invalid_action"), show_alert: true });
289
+ return;
290
+ }
291
+ const sessionId = await this.host.bindingStore.getActiveSessionIdForPrincipal(principal);
292
+ if (!sessionId) {
293
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "common:errors.no_active_session"), show_alert: true });
294
+ return;
295
+ }
296
+ const payload = await this.host.getProjectPayloadByUuid(sessionId, projectUuid);
297
+ if (!payload) {
298
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.not_found"), show_alert: true });
299
+ return;
300
+ }
301
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.loading_members") });
302
+ await this.host.showProjectMembers(ctx, payload);
303
+ }
304
+ async handleProjectLeaveCallback(ctx) {
305
+ const locale = await this.host.resolveLocaleForContext(ctx);
306
+ const projectUuid = this.host.extractCallbackSuffix(ctx, "project-leave:");
307
+ const principal = this.host.getPrincipalFromContext(ctx);
308
+ if (!projectUuid || !principal) {
309
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.invalid_action"), show_alert: true });
310
+ return;
311
+ }
312
+ const sessionId = await this.host.bindingStore.getActiveSessionIdForPrincipal(principal);
313
+ if (!sessionId) {
314
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "common:errors.no_active_session"), show_alert: true });
315
+ return;
316
+ }
317
+ const session = await this.host.sessionStore.getSession(sessionId);
318
+ const sourceRelay = (0, relay_1.parseLiveRelaySessionId)(sessionId);
319
+ const clientUuid = sourceRelay?.clientUuid ??
320
+ (await this.host.ensureGatewayClientUuid(principal));
321
+ await this.host.callGatewayJson("/projects/leave", {
322
+ client_uuid: clientUuid,
323
+ project_uuid: projectUuid,
324
+ });
325
+ if (session?.activeProjectUuid === projectUuid) {
326
+ await this.host.sessionStore.setSession({
327
+ ...session,
328
+ activeProjectUuid: undefined,
329
+ activeProjectName: undefined,
330
+ updatedAt: new Date().toISOString(),
331
+ });
332
+ }
333
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.left_callback") });
334
+ await this.host.showProjectsMenu(ctx, this.host.t(locale, "menu:project.left_screen"));
335
+ }
336
+ async handleProjectDeleteByUuid(ctx, projectUuid) {
337
+ const locale = await this.host.resolveLocaleForContext(ctx);
338
+ const principal = this.host.getPrincipalFromContext(ctx);
339
+ if (!principal) {
340
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "common:errors.no_telegram_identity"), show_alert: true });
341
+ return;
342
+ }
343
+ const sessionId = await this.host.bindingStore.getActiveSessionIdForPrincipal(principal);
344
+ if (!sessionId) {
345
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "common:errors.no_active_session"), show_alert: true });
346
+ return;
347
+ }
348
+ const projects = await this.host.listGatewayProjects(principal);
349
+ const project = projects.find((item) => item.project_uuid === projectUuid);
350
+ if (!project) {
351
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.not_found"), show_alert: true });
352
+ await ctx.deleteMessage().catch(() => undefined);
353
+ return;
354
+ }
355
+ if (project.role !== "owner") {
356
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.delete_only_owner"), show_alert: true });
357
+ return;
358
+ }
359
+ const sourceRelay = (0, relay_1.parseLiveRelaySessionId)(sessionId);
360
+ const clientUuid = sourceRelay?.clientUuid ??
361
+ (await this.host.ensureGatewayClientUuid(principal));
362
+ await this.host.callGatewayJson("/projects/delete", {
363
+ client_uuid: clientUuid,
364
+ project_uuid: projectUuid,
365
+ });
366
+ const session = await this.host.sessionStore.getSession(sessionId);
367
+ if (session?.activeProjectUuid === projectUuid) {
368
+ await this.host.sessionStore.setSession({
369
+ ...session,
370
+ activeProjectUuid: undefined,
371
+ activeProjectName: undefined,
372
+ updatedAt: new Date().toISOString(),
373
+ });
374
+ }
375
+ await ctx.answerCallbackQuery({ text: this.host.t(locale, "menu:project.deleted_callback") });
376
+ await this.host.showCollabDeleteMenu(ctx, this.host.t(locale, "menu:project.deleted_screen", { projectName: project.name }));
377
+ }
378
+ async handlePendingProject(ctx, text) {
379
+ const locale = await this.host.resolveLocaleForContext(ctx);
380
+ const principal = this.host.getPrincipalFromContext(ctx);
381
+ if (!principal) {
382
+ return false;
383
+ }
384
+ const principalKey = `${principal.telegramChatId}:${principal.telegramUserId}`;
385
+ const pending = this.host.pendingProjects.get(principalKey);
386
+ if (!pending) {
387
+ return false;
388
+ }
389
+ if (text.startsWith("/")) {
390
+ this.host.pendingProjects.delete(principalKey);
391
+ return false;
392
+ }
393
+ const value = text.trim();
394
+ if (!value) {
395
+ return true;
396
+ }
397
+ const sourceRelay = (0, relay_1.parseLiveRelaySessionId)(pending.sessionId);
398
+ const clientUuid = sourceRelay?.clientUuid ??
399
+ (await this.host.ensureGatewayClientUuid(principal));
400
+ let projectName = "";
401
+ let projectUuid = "";
402
+ const activeSession = await this.host.sessionStore.getSession(pending.sessionId);
403
+ const localSessionId = sourceRelay?.localSessionId ?? activeSession?.sessionId ?? null;
404
+ const shortLabel = activeSession?.label?.trim() || localSessionId || pending.sessionId;
405
+ const sessionRegistrationPayload = localSessionId
406
+ ? {
407
+ local_session_id: localSessionId,
408
+ label: shortLabel,
409
+ ...(activeSession?.cwd ? { cwd: activeSession.cwd } : {}),
410
+ status: "active",
411
+ }
412
+ : {};
413
+ if (pending.mode === "create") {
414
+ const created = await this.host.callGatewayJson("/projects/create", {
415
+ client_uuid: clientUuid,
416
+ name: value,
417
+ ...sessionRegistrationPayload,
418
+ });
419
+ projectUuid = created.project_uuid;
420
+ projectName = created.name;
421
+ await this.host.ensureProjectSessionRegistered({
422
+ principal,
423
+ sessionId: pending.sessionId,
424
+ projectUuid,
425
+ });
426
+ await this.host.activateProjectForSession({
427
+ principal,
428
+ sessionId: pending.sessionId,
429
+ projectUuid,
430
+ projectName,
431
+ });
432
+ await this.host.replyText(ctx, this.host.t(locale, "menu:project.created", {
433
+ projectName,
434
+ inviteToken: created.invite_token,
435
+ }), { kind: "menu", sessionId: pending.sessionId });
436
+ }
437
+ else {
438
+ const joined = await this.host.callGatewayJson("/projects/join", {
439
+ client_uuid: clientUuid,
440
+ invite_token: value,
441
+ ...sessionRegistrationPayload,
442
+ });
443
+ projectUuid = joined.project_uuid;
444
+ projectName = joined.name;
445
+ await this.host.ensureProjectSessionRegistered({
446
+ principal,
447
+ sessionId: pending.sessionId,
448
+ projectUuid,
449
+ });
450
+ await this.host.activateProjectForSession({
451
+ principal,
452
+ sessionId: pending.sessionId,
453
+ projectUuid,
454
+ projectName,
455
+ });
456
+ await this.host.replyText(ctx, this.host.t(locale, "menu:project.joined", { projectName }), { kind: "menu", sessionId: pending.sessionId });
457
+ }
458
+ this.host.pendingProjects.delete(principalKey);
459
+ await this.host.showProjectsMenu(ctx, this.host.t(locale, "menu:project.opened", { projectName }));
460
+ return true;
461
+ }
462
+ }
463
+ exports.TransportProjectActions = TransportProjectActions;
@@ -0,0 +1,202 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TransportProjectEntryActions = void 0;
4
+ const relay_1 = require("../../../app/webapp/relay");
5
+ const transportUtils_1 = require("./transportUtils");
6
+ class TransportProjectEntryActions {
7
+ host;
8
+ constructor(host) {
9
+ this.host = host;
10
+ }
11
+ async beginProjectMode(ctx, mode) {
12
+ const locale = await this.host.resolveLocaleForContext(ctx);
13
+ const principal = this.host.getPrincipalFromContext(ctx);
14
+ if (!principal) {
15
+ await ctx.answerCallbackQuery({
16
+ text: this.host.t(locale, "common:errors.no_telegram_identity"),
17
+ show_alert: true,
18
+ });
19
+ return;
20
+ }
21
+ const sessionId = await this.host.bindingStore.getActiveSessionIdForPrincipal(principal);
22
+ if (!sessionId) {
23
+ await ctx.answerCallbackQuery({
24
+ text: this.host.t(locale, "common:errors.no_active_session"),
25
+ show_alert: true,
26
+ });
27
+ return;
28
+ }
29
+ const sent = await this.host.replyText(ctx, mode === "create"
30
+ ? [
31
+ this.host.t(locale, "menu:project.create_prompt_title"),
32
+ "",
33
+ this.host.t(locale, "menu:project.create_prompt_body"),
34
+ this.host.t(locale, "menu:project.prompt_cancel"),
35
+ ].join("\n")
36
+ : [
37
+ this.host.t(locale, "menu:project.join_prompt_title"),
38
+ "",
39
+ this.host.t(locale, "menu:project.join_prompt_body"),
40
+ this.host.t(locale, "menu:project.prompt_cancel"),
41
+ ].join("\n"), { kind: "menu", sessionId });
42
+ this.host.pendingProjects.set((0, transportUtils_1.buildPrincipalKey)(principal), {
43
+ sessionId,
44
+ mode,
45
+ initiatedAt: new Date().toISOString(),
46
+ ...(sent ? { promptMessageId: sent.message_id } : {}),
47
+ });
48
+ await ctx.answerCallbackQuery({
49
+ text: mode === "create"
50
+ ? this.host.t(locale, "menu:project.start_create")
51
+ : this.host.t(locale, "menu:project.start_join"),
52
+ });
53
+ }
54
+ async handleProjectSelect(ctx) {
55
+ const locale = await this.host.resolveLocaleForContext(ctx);
56
+ const payloadKey = (0, transportUtils_1.readMenuPayloadKey)(ctx);
57
+ if (!payloadKey) {
58
+ await ctx.answerCallbackQuery({
59
+ text: this.host.t(locale, "menu:project.data_missing"),
60
+ show_alert: true,
61
+ });
62
+ return;
63
+ }
64
+ const payload = await this.host.menuPayloadStore.getMenuPayload(payloadKey);
65
+ if (!payload ||
66
+ payload.kind !== "project-entry" ||
67
+ !payload.sessionId ||
68
+ !payload.projectUuid) {
69
+ await ctx.answerCallbackQuery({
70
+ text: this.host.t(locale, "menu:project.data_stale"),
71
+ show_alert: true,
72
+ });
73
+ return;
74
+ }
75
+ const principal = this.host.getPrincipalFromContext(ctx);
76
+ if (!principal) {
77
+ await ctx.answerCallbackQuery({
78
+ text: this.host.t(locale, "common:errors.no_telegram_identity"),
79
+ show_alert: true,
80
+ });
81
+ return;
82
+ }
83
+ const project = await this.host.getProjectPayloadByUuid(payload.sessionId, payload.projectUuid);
84
+ if (!project) {
85
+ await ctx.answerCallbackQuery({
86
+ text: this.host.t(locale, "menu:project.not_found"),
87
+ show_alert: true,
88
+ });
89
+ return;
90
+ }
91
+ await this.host.ensureOpenedProjectIsActive({
92
+ principal,
93
+ sessionId: project.sessionId,
94
+ projectUuid: project.projectUuid,
95
+ projectName: project.projectName,
96
+ });
97
+ await ctx.answerCallbackQuery({
98
+ text: this.host.t(locale, "menu:project.opening_members"),
99
+ });
100
+ await this.host.showProjectMembers(ctx, project);
101
+ }
102
+ async handleProjectDeleteSelect(ctx) {
103
+ const locale = await this.host.resolveLocaleForContext(ctx);
104
+ const payloadKey = (0, transportUtils_1.readMenuPayloadKey)(ctx);
105
+ if (!payloadKey) {
106
+ await ctx.answerCallbackQuery({
107
+ text: this.host.t(locale, "menu:project.data_missing"),
108
+ show_alert: true,
109
+ });
110
+ return;
111
+ }
112
+ const payload = await this.host.menuPayloadStore.getMenuPayload(payloadKey);
113
+ if (!payload ||
114
+ payload.kind !== "project-delete-entry" ||
115
+ !payload.sessionId ||
116
+ !payload.projectUuid) {
117
+ await ctx.answerCallbackQuery({
118
+ text: this.host.t(locale, "menu:project.data_stale"),
119
+ show_alert: true,
120
+ });
121
+ await ctx.deleteMessage().catch(() => undefined);
122
+ return;
123
+ }
124
+ const principal = this.host.getPrincipalFromContext(ctx);
125
+ if (!principal) {
126
+ await ctx.answerCallbackQuery({
127
+ text: this.host.t(locale, "common:errors.no_telegram_identity"),
128
+ show_alert: true,
129
+ });
130
+ return;
131
+ }
132
+ const projects = await this.host.listGatewayProjects(principal);
133
+ const project = projects.find((item) => item.project_uuid === payload.projectUuid);
134
+ if (!project) {
135
+ await ctx.answerCallbackQuery({
136
+ text: this.host.t(locale, "menu:project.not_found"),
137
+ show_alert: true,
138
+ });
139
+ await ctx.deleteMessage().catch(() => undefined);
140
+ return;
141
+ }
142
+ if (project.role !== "owner") {
143
+ await ctx.answerCallbackQuery({
144
+ text: this.host.t(locale, "menu:project.delete_only_owner"),
145
+ show_alert: true,
146
+ });
147
+ return;
148
+ }
149
+ await this.host.callGatewayJson("/projects/delete", {
150
+ project_uuid: payload.projectUuid,
151
+ });
152
+ await ctx.answerCallbackQuery({
153
+ text: this.host.t(locale, "menu:project.deleted"),
154
+ });
155
+ await this.host.showProjectsMenu(ctx, this.host.t(locale, "menu:project.deleted_screen"));
156
+ }
157
+ async leaveActiveProject(ctx) {
158
+ const locale = await this.host.resolveLocaleForContext(ctx);
159
+ const principal = this.host.getPrincipalFromContext(ctx);
160
+ if (!principal) {
161
+ await ctx.answerCallbackQuery({
162
+ text: this.host.t(locale, "common:errors.no_telegram_identity"),
163
+ show_alert: true,
164
+ });
165
+ return;
166
+ }
167
+ const sessionId = await this.host.bindingStore.getActiveSessionIdForPrincipal(principal);
168
+ if (!sessionId) {
169
+ await ctx.answerCallbackQuery({
170
+ text: this.host.t(locale, "common:errors.no_active_session"),
171
+ show_alert: true,
172
+ });
173
+ return;
174
+ }
175
+ const session = await this.host.sessionStore.getSession(sessionId);
176
+ if (!session?.activeProjectUuid) {
177
+ await ctx.answerCallbackQuery({
178
+ text: this.host.t(locale, "menu:project.no_active_project"),
179
+ show_alert: true,
180
+ });
181
+ return;
182
+ }
183
+ const sourceRelay = (0, relay_1.parseLiveRelaySessionId)(sessionId);
184
+ const clientUuid = sourceRelay?.clientUuid ??
185
+ (await this.host.ensureGatewayClientUuid(principal));
186
+ await this.host.callGatewayJson("/projects/leave", {
187
+ client_uuid: clientUuid,
188
+ project_uuid: session.activeProjectUuid,
189
+ });
190
+ await this.host.sessionStore.setSession({
191
+ ...session,
192
+ activeProjectUuid: undefined,
193
+ activeProjectName: undefined,
194
+ updatedAt: new Date().toISOString(),
195
+ });
196
+ await ctx.answerCallbackQuery({
197
+ text: this.host.t(locale, "menu:project.left_current"),
198
+ });
199
+ await this.host.showProjectsMenu(ctx, this.host.t(locale, "menu:project.left_current_screen"));
200
+ }
201
+ }
202
+ exports.TransportProjectEntryActions = TransportProjectEntryActions;