@deadragdoll/tellymcp 0.0.8 → 0.0.10

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 (33) hide show
  1. package/.env.example.client +2 -0
  2. package/.env.example.gateway +2 -0
  3. package/README-ru.md +21 -1
  4. package/README.md +5 -1
  5. package/TOOLS.md +3 -1
  6. package/VERSION.md +58 -0
  7. package/config/templates/env.both.template +1 -0
  8. package/config/templates/env.client.template +1 -0
  9. package/config/templates/env.gateway.template +1 -0
  10. package/dist/services/features/telegram-mcp/approval.service.js +1 -1
  11. package/dist/services/features/telegram-mcp/browser.service.js +1 -1
  12. package/dist/services/features/telegram-mcp/collaboration.service.js +1 -1
  13. package/dist/services/features/telegram-mcp/gateway-rmq.service.js +3 -2
  14. package/dist/services/features/telegram-mcp/gateway-socket.service.js +8 -2
  15. package/dist/services/features/telegram-mcp/inbox.service.js +1 -1
  16. package/dist/services/features/telegram-mcp/mcp-http.service.js +1 -1
  17. package/dist/services/features/telegram-mcp/notify.service.js +1 -1
  18. package/dist/services/features/telegram-mcp/pair.service.js +1 -1
  19. package/dist/services/features/telegram-mcp/runtime.service.js +27 -7
  20. package/dist/services/features/telegram-mcp/session-context.service.js +1 -1
  21. package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +2 -1
  22. package/dist/services/features/telegram-mcp/src/app/config/env.js +4 -0
  23. package/dist/services/features/telegram-mcp/src/app/http.js +8 -1
  24. package/dist/services/features/telegram-mcp/src/app/providers/mcp/server.js +2 -1
  25. package/dist/services/features/telegram-mcp/src/app/webapp/assets.js +201 -60
  26. package/dist/services/features/telegram-mcp/src/shared/i18n/index.js +46 -0
  27. package/dist/services/features/telegram-mcp/src/shared/i18n/resources/en.js +555 -0
  28. package/dist/services/features/telegram-mcp/src/shared/i18n/resources/ru.js +555 -0
  29. package/dist/services/features/telegram-mcp/src/shared/integrations/redis/stateStore.js +9 -0
  30. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +1227 -567
  31. package/dist/services/features/telegram-mcp/standalone-http.service.js +1 -1
  32. package/dist/services/features/telegram-mcp/tools-sync.service.js +1 -1
  33. package/package.json +2 -1
@@ -0,0 +1,555 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.enMenu = exports.enCommon = void 0;
4
+ exports.enCommon = {
5
+ errors: {
6
+ no_telegram_identity: "Telegram identity is unavailable for this chat.",
7
+ no_active_session: "No active session is linked yet. Pair a session via /start <code>.",
8
+ missing_telegram_context: "Telegram user or chat is missing.",
9
+ },
10
+ menu: {
11
+ refreshed: "Menu refreshed.",
12
+ gateway_unavailable: "Gateway unavailable",
13
+ no_telegram_identity_label: "No Telegram identity",
14
+ no_active_session_label: "No active session",
15
+ back: "⬅ Back",
16
+ refresh: "🔄 Refresh",
17
+ close: "✖ Close",
18
+ delete: "🗑 Delete",
19
+ get: "📥 Get",
20
+ },
21
+ };
22
+ exports.enMenu = {
23
+ main: {
24
+ buttons: {
25
+ live: "🖥 Live",
26
+ content: "📄 Content",
27
+ browser: "🌐 Browser",
28
+ local: "🏠 Local",
29
+ collab: "👥 Collab",
30
+ storage: "📦 Storage",
31
+ settings: "⚙ Settings",
32
+ back: "⬅ Back",
33
+ },
34
+ actions: {
35
+ open_content: "Opening content menu.",
36
+ open_browser: "Opening browser menu.",
37
+ open_inbox: "Opening inbox.",
38
+ open_storage: "Opening storage.",
39
+ open_settings: "Opening settings.",
40
+ back_to_sessions: "Back to sessions.",
41
+ },
42
+ screen: {
43
+ title: "🎛 Session: {{sessionName}}",
44
+ inbox_messages: "📥 Inbox messages: {{count}}",
45
+ project: "📦 Project: <b>{{projectName}}</b>",
46
+ partner: "🤝 Partner: <b><i>{{partnerName}}</i></b>",
47
+ partner_hint: "Share API details, what's new, errors, and git changes with your teammate.",
48
+ link_hint: "🔗 Link a partner session to coordinate through shared notes and files.",
49
+ tmux_mode_direct: "🖧 TMUX mode: direct",
50
+ },
51
+ },
52
+ sessions: {
53
+ screen: {
54
+ title: "🗂 Choose active session",
55
+ last_worked: "🕘 Last worked: <i>{{sessionName}}</i>",
56
+ updated: "⏱ Updated: <i>{{timestamp}}</i>",
57
+ current_active: "📌 Current active: <b>{{sessionName}}</b>",
58
+ no_linked_sessions: "No linked sessions found for this Telegram identity.",
59
+ },
60
+ labels: {
61
+ no_linked_sessions: "🫥 No linked sessions",
62
+ unavailable: "⚠ Sessions unavailable",
63
+ tools: "🛠 Tools",
64
+ },
65
+ actions: {
66
+ no_linked_sessions: "No linked sessions found for this Telegram identity.",
67
+ unavailable: "Sessions menu is temporarily unavailable.",
68
+ refreshed: "Sessions refreshed.",
69
+ open_tools: "Opening tools menu.",
70
+ },
71
+ },
72
+ inbox: {
73
+ button: "📥 Inbox",
74
+ button_count: "📥 Inbox ({{count}})",
75
+ screen: {
76
+ title: "📥 Inbox",
77
+ active_session: "📌 Active session: {{sessionName}}",
78
+ stored_messages: "📨 Stored messages: {{count}}",
79
+ choose_message: "Choose a message below to inspect or delete it.",
80
+ empty: "No stored unsolicited Telegram messages for this session.",
81
+ },
82
+ labels: {
83
+ empty: "📭 Inbox is empty",
84
+ },
85
+ actions: {
86
+ empty: "No unsolicited Telegram messages are stored.",
87
+ refreshed: "Inbox refreshed.",
88
+ },
89
+ },
90
+ buffer: {
91
+ buttons: {
92
+ visible: "👁 Visible",
93
+ full: "🧾 Full",
94
+ last_300: "📄 Last 300",
95
+ last_1000: "📄 Last 1000",
96
+ },
97
+ screen: {
98
+ title: "📄 Content",
99
+ active_session: "📌 Active session: {{sessionName}}",
100
+ tmux_target: "🖥 tmux target: {{tmuxTarget}}",
101
+ export_hint: "Choose how much pane history to export as a Markdown file.",
102
+ export_modes: "Visible is the current pane viewport. Full exports the whole available tmux history.",
103
+ },
104
+ },
105
+ browser: {
106
+ buttons: {
107
+ screenshots: "📸 Screenshots",
108
+ screenshots_count: "📸 Screenshots ({{count}})",
109
+ },
110
+ actions: {
111
+ open_screenshots: "Opening screenshots.",
112
+ back_to_session_menu: "Back to session menu.",
113
+ refreshed: "Screenshots refreshed.",
114
+ back_to_browser_menu: "Back to browser menu.",
115
+ },
116
+ screen: {
117
+ title: "🌐 Browser",
118
+ active_session: "📌 Active session: {{sessionName}}",
119
+ stored_screenshots: "📸 Stored screenshots: {{count}}",
120
+ choose_action: "Choose a browser-related action below.",
121
+ },
122
+ },
123
+ screenshots: {
124
+ screen: {
125
+ title: "📸 Screenshots",
126
+ active_session: "📌 Active session: {{sessionName}}",
127
+ stored_screenshots: "📦 Stored screenshots: {{count}}",
128
+ choose_screenshot: "Choose a screenshot below to get it in Telegram or delete it.",
129
+ empty: "No browser screenshots are stored for this session.",
130
+ },
131
+ labels: {
132
+ empty: "📭 No screenshots",
133
+ },
134
+ actions: {
135
+ empty: "No screenshots are stored for this session.",
136
+ refreshed: "Screenshots refreshed.",
137
+ back_to_screenshots: "Back to screenshots.",
138
+ },
139
+ },
140
+ storage: {
141
+ buttons: {
142
+ get: "📥 Get",
143
+ delete: "🗑 Delete",
144
+ },
145
+ actions: {
146
+ back_to_storage: "Back to storage.",
147
+ refreshed: "Storage refreshed.",
148
+ empty: "No files are stored in .mcp-xchange for this session yet.",
149
+ },
150
+ screen: {
151
+ title: "📦 Storage",
152
+ active_session: "📌 Active session: {{sessionName}}",
153
+ stored_files: "📦 Stored files: {{count}}",
154
+ choose_file: "Choose a file below to inspect it or send it to Telegram.",
155
+ empty: "No .mcp-xchange files are stored for this session.",
156
+ },
157
+ labels: {
158
+ empty: "📭 Storage is empty",
159
+ },
160
+ },
161
+ settings: {
162
+ buttons: {
163
+ info: "ℹ Info",
164
+ rename: "✏ Rename",
165
+ unpair: "🗑 Unpair",
166
+ confirm_unpair: "⚠ Confirm unpair",
167
+ },
168
+ actions: {
169
+ confirm_unpair: "Confirm unpair.",
170
+ back_to_settings: "Back to settings.",
171
+ rename_prompt: "Send the new session title.",
172
+ rename_body: "Send the next text message as the new title for the active session.\nCommands like /menu or /help cancel rename mode.",
173
+ },
174
+ screen: {
175
+ title: "⚙ Settings",
176
+ active_session: "📌 Active session: {{sessionName}}",
177
+ hint: "Open session info, rename it, or unpair it from Telegram.",
178
+ },
179
+ },
180
+ local: {
181
+ buttons: {
182
+ partner: "🤝 Partner",
183
+ link: "🔗 Link",
184
+ unlink: "🔓 Unlink",
185
+ },
186
+ actions: {
187
+ open_local: "Opening local collaboration.",
188
+ back_to_session_menu: "Back to session menu.",
189
+ },
190
+ screen: {
191
+ title: "🏠 Local",
192
+ active_session: "📌 Active session: {{sessionName}}",
193
+ link_status: "🤝 Link: {{linkedSessionName}}",
194
+ link_status_none: "🤝 Link: not configured",
195
+ hint_title: "Local collaboration inside one bot lives here:",
196
+ hint_body: "session pairing, note exchange, and file handoff without a gateway.",
197
+ unavailable: "Local collaboration is unavailable for this chat.",
198
+ no_active_session: "No active session is selected. Pair it first via /start.",
199
+ },
200
+ },
201
+ link: {
202
+ buttons: {
203
+ link: "🔗 Link",
204
+ unlink_with_name: "🔓 Unlink {{sessionName}}",
205
+ unlink: "🔓 Unlink",
206
+ },
207
+ labels: {
208
+ no_partner_sessions: "🫥 No partner sessions",
209
+ },
210
+ actions: {
211
+ no_partner_sessions: "No other linked sessions are available.",
212
+ back_to_session_menu: "Back to session menu.",
213
+ unlinked: "Partner session unlinked.",
214
+ choose_partner: "Choose a partner session.",
215
+ },
216
+ screen: {
217
+ title: "🔗 Link partner",
218
+ active_session: "📌 Active session: {{sessionName}}",
219
+ choose_partner: "Choose another session to link as a teammate.",
220
+ hint: "Use this partnership to share API summaries, what's new, errors, and relevant git changes through .mcp-xchange notes and files.",
221
+ },
222
+ },
223
+ partner: {
224
+ buttons: {
225
+ ask: "❓ Ask",
226
+ share: "📤 Share",
227
+ unlink: "🔓 Unlink",
228
+ },
229
+ actions: {
230
+ back_to_session_menu: "Back to session menu.",
231
+ open_partner_menu: "Opening partner menu.",
232
+ back_to_partner: "Back to partner.",
233
+ cancel_note_input: "Partner note input cancelled.",
234
+ no_pending_note_input: "No active partner note input.",
235
+ task_sent: "Task was sent to the selected session.",
236
+ inbox_queued: "Task was placed into the current session inbox.",
237
+ },
238
+ screen: {
239
+ title: "🤝 Partner",
240
+ active_session: "📌 Active session: {{sessionName}}",
241
+ linked_partner: "👥 Linked partner: {{partnerName}}",
242
+ no_partner: "No partner is linked yet.",
243
+ use_link_first: "Use Link in the session menu first.",
244
+ prompt_hint: "Ask for API details or share what changed.",
245
+ prompt_format: "Prompt format: first line is summary. Add a blank line and then the main message body if needed.",
246
+ default_partner: "partner",
247
+ executor: "Executor: {{label}}",
248
+ route_result: "Result route: {{source}} -> {{target}}",
249
+ route_send: "Send route: {{source}} -> {{target}}",
250
+ type: "Type: {{kind}}",
251
+ summary: "Summary: {{summary}}",
252
+ status: "Status: {{status}}",
253
+ delivered: "delivered",
254
+ queued: "queued",
255
+ current_session_handles: "The current session will prepare the result and send it itself.",
256
+ },
257
+ },
258
+ collab: {
259
+ buttons: {
260
+ tools: "🛠 Tools",
261
+ create: "➕ Create",
262
+ join: "🔑 Join",
263
+ broadcast: "📣 Broadcast",
264
+ history: "🕘 History",
265
+ delete: "🗑 Delete",
266
+ },
267
+ actions: {
268
+ gateway_only: "Projects are available only through the gateway.",
269
+ open_tools: "Opening project tools.",
270
+ open_collab: "Opening Collab.",
271
+ open_delete: "Opening project deletion.",
272
+ back_to_collab: "Back to Collab.",
273
+ back_to_tools: "Back to tools.",
274
+ back_to_session_menu: "Back to session menu.",
275
+ no_projects: "No projects yet. Create one or join an existing project.",
276
+ },
277
+ labels: {
278
+ no_projects: "🫥 No projects",
279
+ },
280
+ screen: {
281
+ title: "👥 Collab",
282
+ gateway_not_configured: "Gateway is not configured for this runtime.",
283
+ use_local_instead: "Use Local for collaboration inside one bot.",
284
+ unavailable: "Collab is unavailable for the current session.",
285
+ active_session: "📌 Active session: {{sessionName}}",
286
+ open_project: "📦 Open project: {{projectName}}",
287
+ open_project_none: "📦 Open project: not selected",
288
+ project_count: "🗂 Available projects: {{count}}",
289
+ invite_hint: "Open a project, create a new one, or join by invite code.",
290
+ tools_title: "🛠 Collab Tools",
291
+ tools_empty: "Create a project or join an existing one first.",
292
+ tools_project_count: "🗂 Collab projects: {{count}}",
293
+ tools_session_count: "👥 Unique sessions: {{count}}",
294
+ tools_broadcast: "Broadcast sends your next text message to every unique Collab session across bots without duplication.",
295
+ tools_history: "History sends a .md file with the latest 5 Collab events for the current session.",
296
+ },
297
+ },
298
+ help: {
299
+ title: "❓ TellyMCP help",
300
+ menu: "/menu - open the sessions list",
301
+ help: "/help - show this help",
302
+ how_it_works: "How it works:",
303
+ step_choose: "- choose the active session",
304
+ step_inbox: "- ordinary Telegram messages go to that session inbox",
305
+ step_nudge: "- if a tmux target is configured, the service nudges the agent automatically",
306
+ step_tools: "- the agent then reads the inbox batch through MCP tools",
307
+ },
308
+ live: {
309
+ buttons: {
310
+ fullscreen: "Fullscreen",
311
+ expand: "Expand",
312
+ default: "Default",
313
+ },
314
+ actions: {
315
+ opening: "Opening Live View.",
316
+ choose_mode: "Choose a launch mode:",
317
+ opened_info: "Live view opened.",
318
+ approval_unavailable: "This session is unavailable for approval right now.",
319
+ },
320
+ errors: {
321
+ identity_unavailable: "Telegram identity is unavailable.",
322
+ no_active_session: "No active session selected.",
323
+ webapp_disabled: "WebApp is not enabled on the server.",
324
+ public_url_missing: "WebApp public URL is not configured.",
325
+ },
326
+ screen: {
327
+ launcher_title: "🖥 Live: {{sessionName}}",
328
+ },
329
+ approval: {
330
+ request_title: "🖥 Live view request",
331
+ request_message: "Session {{sourceSessionName}} requests access to the Live view of your session.",
332
+ route: "Session: {{sourceSessionName}} -> {{targetSessionName}}",
333
+ project: "Project: {{projectName}}",
334
+ approve: "Approve",
335
+ deny: "Deny",
336
+ approved: "✅ Live access approved.",
337
+ denied: "❌ Live access denied.",
338
+ source_open: "Open Live",
339
+ result_approved: "Live view was approved for {{sourceSessionName}} -> {{targetSessionName}}.",
340
+ result_denied: "Live view was denied for {{sourceSessionName}} -> {{targetSessionName}}.",
341
+ },
342
+ },
343
+ notices: {
344
+ startup: {
345
+ title: "✅ TellyMCP is running.",
346
+ version: "Version: {{packageVersion}}",
347
+ protocol: "Protocol: {{protocolVersion}}",
348
+ mode: "Mode: {{mode}}",
349
+ bot: "Bot: @{{botUsername}}",
350
+ sessions: "Linked sessions: {{count}}",
351
+ session_list: "Sessions: {{sessions}}",
352
+ mcp: "MCP: {{url}}",
353
+ webapp: "WebApp: {{url}}",
354
+ gateway: "Gateway: {{url}}",
355
+ gateway_ws: "Gateway WS: {{url}}",
356
+ browser: "Browser: {{status}}",
357
+ hint: "Send /menu to open the session menu.",
358
+ },
359
+ project: {
360
+ member_joined: "A participant joined project “{{projectName}}”: {{memberLabel}}.",
361
+ member_left: "A participant left project “{{projectName}}”: {{memberLabel}}.",
362
+ deleted: "Project “{{projectName}}” was deleted. Local project bindings were cleared.",
363
+ new_member: "New participant",
364
+ member: "Participant",
365
+ },
366
+ tools: {
367
+ changed: "Gateway TOOLS.md changed or is missing locally.",
368
+ session: "Session: {{sessionName}}",
369
+ action_required: "Action required: call refresh_tools_markdown, then re-read the local TOOLS.md and apply it before continuing work.",
370
+ },
371
+ version: {
372
+ reject: "Gateway and client are protocol-incompatible. Transport for this session is blocked.",
373
+ warn: "Gateway and client versions differ.",
374
+ session: "Session: {{sessionName}}",
375
+ client: "Client: {{packageVersion}} / protocol {{protocolVersion}}",
376
+ gateway: "Gateway: {{packageVersion}} / protocol {{protocolVersion}}",
377
+ },
378
+ tmux: {
379
+ target_invalid_title: "⚠ Automatic tmux nudge failed for session {{sessionName}}.",
380
+ target_invalid_target: "Saved tmux target is no longer valid: {{tmuxTarget}}",
381
+ target_invalid_action: "Rebind the tmux target for this session.",
382
+ unavailable_title: "⚠ Automatic tmux nudge was skipped for session {{sessionName}}.",
383
+ unavailable_body: "tmux is unavailable on this machine right now.",
384
+ unavailable_target: "tmux target: {{tmuxTarget}}",
385
+ unavailable_reason: "This usually means the tmux session/server is not running or is unreachable via the current socket path.",
386
+ unavailable_action: "Start tmux and the agent inside it, or update/remove the tmux target for this session.",
387
+ },
388
+ },
389
+ developer: {
390
+ screen: {
391
+ title: "🛠 Tools",
392
+ linked_sessions: "🔗 Linked sessions: {{count}}",
393
+ broadcast_help: "Broadcast writes your next text message into every linked session inbox and nudges every configured tmux target.",
394
+ prune_help: "Prune all clears every Redis key under this Telegram MCP namespace.",
395
+ },
396
+ },
397
+ session_info: {
398
+ opened: "Session info opened.",
399
+ title: "ℹ Session info",
400
+ label: "📌 Label: {{value}}",
401
+ session_id: "🆔 Session ID: {{value}}",
402
+ inbox_count: "📥 Inbox count: {{count}}",
403
+ paired: "🔗 Paired: {{value}}",
404
+ partner: "🤝 Partner: {{value}}",
405
+ tmux_target: "🖥 tmux target: {{value}}",
406
+ tmux_session: "📺 tmux session: {{value}}",
407
+ tmux_window: "🪟 tmux window: {{value}}",
408
+ tmux_pane: "🔹 tmux pane: {{value}}",
409
+ yes: "yes",
410
+ no: "no",
411
+ not_linked: "not linked",
412
+ not_set: "not set",
413
+ },
414
+ unpair: {
415
+ title: "⚠ Confirm unpair",
416
+ active_session: "📌 Active session: {{sessionName}}",
417
+ body_1: "This removes the Telegram binding for the active session.",
418
+ body_2: "Session metadata and inbox records remain in Redis until you delete them separately.",
419
+ done: "Unpaired: {{sessionName}}",
420
+ shown: "Session unpaired: {{sessionName}}",
421
+ },
422
+ prune: {
423
+ title: "⚠ Confirm prune",
424
+ linked_sessions: "🔗 Linked sessions visible here: {{count}}",
425
+ body_1: "This clears every Redis key under the telegram-mcp namespace.",
426
+ body_2: "Pair codes, bindings, sessions, inbox, menu payloads, and pending requests will all be deleted.",
427
+ done: "Prune complete. Deleted {{count}} Redis keys.",
428
+ },
429
+ history: {
430
+ title: "# Collab History",
431
+ session: "Session: {{sessionName}}",
432
+ empty: "No recent Collab events were found for this session.",
433
+ project: "Project: {{projectName}}",
434
+ caption: "Collab history for {{sessionName}}",
435
+ },
436
+ broadcast: {
437
+ begin: "Broadcast to {{count}} sessions.",
438
+ title: "📣 Broadcast",
439
+ body: "Send the next text message to broadcast it to all {{count}} linked sessions.",
440
+ hint: "The message will be stored in every session inbox and the service will nudge every configured tmux target.",
441
+ cancel_hint: "Commands like /menu or /help cancel broadcast mode.",
442
+ collab_begin: "Broadcast to {{count}} collab sessions.",
443
+ collab_title: "📣 Collab Broadcast",
444
+ collab_projects: "Collab projects: {{count}}",
445
+ collab_sessions: "Unique sessions: {{count}}",
446
+ collab_body: "Send the next text message to broadcast it to all Collab sessions across bots without duplication.",
447
+ collab_hint: "Local sessions receive an inbox message, remote sessions receive a gateway delivery.",
448
+ no_linked_sessions: "No linked sessions found.",
449
+ no_collab_targets: "No Collab sessions are available for broadcast.",
450
+ no_projects_first: "Create a project or join an existing one first.",
451
+ mode_not_active: "Broadcast mode is not active.",
452
+ cancelled: "Broadcast cancelled.",
453
+ cancelled_no_sessions: "Broadcast was cancelled because no linked sessions were found.",
454
+ completed_linked: "Broadcast completed for {{count}} linked sessions.",
455
+ completed_collab: "Broadcast completed for {{count}} Collab sessions.",
456
+ completed_collab_local: "Local inbox: {{count}}",
457
+ completed_collab_remote: "Remote deliveries: {{count}}",
458
+ completed_collab_total: "Total sessions: {{count}}",
459
+ },
460
+ project: {
461
+ not_found: "Project not found.",
462
+ left_callback: "Left the project.",
463
+ left_screen: "You left the selected project.",
464
+ deleted_callback: "Project deleted.",
465
+ deleted_screen: "Project “{{projectName}}” was deleted. Participants were unbound and project state was cleared.",
466
+ delete_only_owner: "Only the owner can delete a project.",
467
+ delete_menu_title: "🗑 Delete Project",
468
+ active_session: "📌 Active session: {{sessionName}}",
469
+ total_count: "🗂 Collab projects: {{count}}",
470
+ owner_count: "👑 Projects where you are owner: {{count}}",
471
+ delete_choose: "Choose a project for complete deletion.",
472
+ delete_body: "Participants will be unbound, project sessions removed, and the project record deleted.",
473
+ delete_owner_hint: "Only the owner can delete a project.",
474
+ created: "Project created: {{projectName}}\nInvite: {{inviteToken}}",
475
+ joined: "Joined project: {{projectName}}",
476
+ opened: "Opened project: {{projectName}}",
477
+ invalid_action: "Invalid project action.",
478
+ invalid_member_action: "Invalid project member action.",
479
+ invalid_member_payload: "Invalid project member data.",
480
+ stale_member_payload: "Project member data is invalid or outdated.",
481
+ invalid_live_payload: "Invalid Live View data.",
482
+ stale_live_payload: "Live View data is invalid or outdated.",
483
+ no_telegram_user: "Unable to determine Telegram user.",
484
+ request_live_sent: "Live request sent for approval.",
485
+ loading_members: "Loading members.",
486
+ opening_members: "Opening project members.",
487
+ opening_session: "Opening session.",
488
+ opening_files: "Opening files.",
489
+ create_prompt_title: "📦 Create project",
490
+ create_prompt_body: "Send the project name in your next message.",
491
+ join_prompt_title: "🔑 Join project",
492
+ join_prompt_body: "Send the project invite token in your next message.",
493
+ prompt_cancel: "Commands like /menu or /help cancel this mode.",
494
+ start_create: "Creating project.",
495
+ start_join: "Joining project.",
496
+ data_missing: "Project data was not found.",
497
+ data_stale: "Project data is outdated or invalid.",
498
+ no_active_project: "No active project.",
499
+ left_current: "Project left.",
500
+ left_current_screen: "You left the current project.",
501
+ members_title: "👥 Members of {{projectName}}",
502
+ current_session: "Session: {{sessionName}}",
503
+ other_sessions: "Other sessions: {{count}}",
504
+ choose_file_target: "Choose who should receive this file.",
505
+ choose_member_action: "Choose a session to ask, share with, reply to, or send a file to.",
506
+ no_other_active: "There are no other active sessions in this project yet.",
507
+ leave: "🚪 Leave",
508
+ back_to_projects: "⬅ To projects",
509
+ ask: "❓ Ask",
510
+ share_button: "📤 Share",
511
+ back_to_members: "⬅ To members",
512
+ back_to_session: "⬅ To session",
513
+ file_title: "📎 Choose file",
514
+ file_project: "Project: {{projectName}}",
515
+ file_recipient: "Recipient: {{label}}",
516
+ file_choose: "Choose a file to send.",
517
+ file_none: "There are no uploaded files in this session.",
518
+ invalid_approval: "Invalid Live View approval.",
519
+ invalid_approval_data: "Invalid approval data.",
520
+ approval_stale: "The Live View request has expired.",
521
+ },
522
+ handoff: {
523
+ no_pending: "No pending file handoff prompt.",
524
+ cancelled: "File handoff cancelled.",
525
+ delivered_agent: "File delivered to the agent.",
526
+ queued_partner: "File was queued for delivery to the partner.",
527
+ project: "Project: {{projectName}}",
528
+ recipient: "Recipient: {{label}}",
529
+ session: "Session: {{label}}",
530
+ status: "Status: {{status}}",
531
+ share: "Share: {{shareId}}",
532
+ delivered: "delivered",
533
+ queued: "queued",
534
+ prompt_title: "🤝 Send to participant",
535
+ route: "Session: {{sourceSessionName}} -> {{targetSessionName}}",
536
+ file: "File: {{fileName}}",
537
+ prompt_body: "Send the file description or instructions in your next message.",
538
+ prompt_hint: "This text will be attached to the handoff.",
539
+ choose_title: "📎 Choose file",
540
+ choose_recipient: "Recipient: {{label}}",
541
+ choose_local: "Choose a file to send to the local partner.",
542
+ choose_project: "Choose a file to send.",
543
+ no_files: "No uploaded files are available in this session.",
544
+ cancel: "Cancel",
545
+ uploaded_to_session: "File sent to session {{label}}.",
546
+ uploaded_to_partner: "File sent to partner {{label}}.",
547
+ delivered_one: "File delivered to session {{label}}.",
548
+ delivered_many: "Files delivered to session {{label}}: {{count}}.",
549
+ },
550
+ system: {
551
+ sessions_menu_unavailable: "Sessions menu is temporarily unavailable. Try /menu again.",
552
+ error_prefix: "Error: {{message}}",
553
+ tmux_recreated_hint: "This usually means the pane/window/session was recreated.",
554
+ },
555
+ };