@deadragdoll/tellymcp 0.0.1

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 (124) hide show
  1. package/.env.example.client +93 -0
  2. package/.env.example.gateway +120 -0
  3. package/CHANGELOG.md +155 -0
  4. package/LICENSE +21 -0
  5. package/README-ru.md +338 -0
  6. package/README.md +1262 -0
  7. package/STANDALONE-ru.md +266 -0
  8. package/STANDALONE.md +266 -0
  9. package/TOOLS.md +1296 -0
  10. package/config/templates/env.both.template +83 -0
  11. package/config/templates/env.client.template +60 -0
  12. package/config/templates/env.gateway.template +82 -0
  13. package/dist/cli.js +636 -0
  14. package/dist/index.js +17 -0
  15. package/dist/lib/logfeed/store.js +52 -0
  16. package/dist/lib/middlewares/tracer.js +172 -0
  17. package/dist/lib/mixins/db.js +267 -0
  18. package/dist/lib/mixins/logfeed.js +34 -0
  19. package/dist/lib/mixins/session.errors.js +142 -0
  20. package/dist/lib/moleculer.js +2 -0
  21. package/dist/lib/trace.js +147 -0
  22. package/dist/lib/traceContext.js +116 -0
  23. package/dist/moleculer.config.js +274 -0
  24. package/dist/services/features/telegram-mcp/approval.service.js +33 -0
  25. package/dist/services/features/telegram-mcp/browser.service.js +42 -0
  26. package/dist/services/features/telegram-mcp/collaboration.service.js +53 -0
  27. package/dist/services/features/telegram-mcp/ensuredb.service.js +337 -0
  28. package/dist/services/features/telegram-mcp/gateway-delivery.service.js +378 -0
  29. package/dist/services/features/telegram-mcp/gateway-loopback.js +10 -0
  30. package/dist/services/features/telegram-mcp/gateway-rmq.service.js +294 -0
  31. package/dist/services/features/telegram-mcp/gateway-socket.service.js +1463 -0
  32. package/dist/services/features/telegram-mcp/gateway.service.js +1141 -0
  33. package/dist/services/features/telegram-mcp/inbox.service.js +33 -0
  34. package/dist/services/features/telegram-mcp/mcp-http.service.js +76 -0
  35. package/dist/services/features/telegram-mcp/mcp-server.service.js +127 -0
  36. package/dist/services/features/telegram-mcp/notify.service.js +33 -0
  37. package/dist/services/features/telegram-mcp/pair.service.js +33 -0
  38. package/dist/services/features/telegram-mcp/runtime.service.js +36 -0
  39. package/dist/services/features/telegram-mcp/session-context.service.js +33 -0
  40. package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +103 -0
  41. package/dist/services/features/telegram-mcp/src/app/config/env.js +317 -0
  42. package/dist/services/features/telegram-mcp/src/app/http.js +774 -0
  43. package/dist/services/features/telegram-mcp/src/app/index.js +2 -0
  44. package/dist/services/features/telegram-mcp/src/app/providers/mcp/server.js +13 -0
  45. package/dist/services/features/telegram-mcp/src/app/providers/redis/client.js +18 -0
  46. package/dist/services/features/telegram-mcp/src/app/webapp/assets.js +740 -0
  47. package/dist/services/features/telegram-mcp/src/app/webapp/auth.js +267 -0
  48. package/dist/services/features/telegram-mcp/src/app/webapp/relay.js +69 -0
  49. package/dist/services/features/telegram-mcp/src/app/webapp/tmux.js +9 -0
  50. package/dist/services/features/telegram-mcp/src/entities/auth/model/types.js +2 -0
  51. package/dist/services/features/telegram-mcp/src/entities/browser/model/types.js +2 -0
  52. package/dist/services/features/telegram-mcp/src/entities/collaboration/model/types.js +2 -0
  53. package/dist/services/features/telegram-mcp/src/entities/inbox/model/types.js +2 -0
  54. package/dist/services/features/telegram-mcp/src/entities/request/model/schema.js +545 -0
  55. package/dist/services/features/telegram-mcp/src/entities/request/model/types.js +2 -0
  56. package/dist/services/features/telegram-mcp/src/entities/session/model/types.js +2 -0
  57. package/dist/services/features/telegram-mcp/src/features/ask-user/model/askUserTelegram.js +33 -0
  58. package/dist/services/features/telegram-mcp/src/features/browser/model/browserClearLogsTool.js +28 -0
  59. package/dist/services/features/telegram-mcp/src/features/browser/model/browserClickTool.js +28 -0
  60. package/dist/services/features/telegram-mcp/src/features/browser/model/browserCloseTool.js +28 -0
  61. package/dist/services/features/telegram-mcp/src/features/browser/model/browserComputedStyleTool.js +28 -0
  62. package/dist/services/features/telegram-mcp/src/features/browser/model/browserConsoleTool.js +28 -0
  63. package/dist/services/features/telegram-mcp/src/features/browser/model/browserDomTool.js +28 -0
  64. package/dist/services/features/telegram-mcp/src/features/browser/model/browserErrorsTool.js +28 -0
  65. package/dist/services/features/telegram-mcp/src/features/browser/model/browserFillTool.js +28 -0
  66. package/dist/services/features/telegram-mcp/src/features/browser/model/browserNetworkFailuresTool.js +28 -0
  67. package/dist/services/features/telegram-mcp/src/features/browser/model/browserOpenTool.js +33 -0
  68. package/dist/services/features/telegram-mcp/src/features/browser/model/browserPressTool.js +28 -0
  69. package/dist/services/features/telegram-mcp/src/features/browser/model/browserReloadTool.js +28 -0
  70. package/dist/services/features/telegram-mcp/src/features/browser/model/browserScreenshotTool.js +28 -0
  71. package/dist/services/features/telegram-mcp/src/features/browser/model/browserService.js +689 -0
  72. package/dist/services/features/telegram-mcp/src/features/browser/model/browserWaitForTool.js +28 -0
  73. package/dist/services/features/telegram-mcp/src/features/browser/model/browserWaitForUrlTool.js +28 -0
  74. package/dist/services/features/telegram-mcp/src/features/collaboration/model/backend.js +2 -0
  75. package/dist/services/features/telegram-mcp/src/features/collaboration/model/collaborationService.js +26 -0
  76. package/dist/services/features/telegram-mcp/src/features/collaboration/model/localCollaborationBackend.js +390 -0
  77. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileService.js +102 -0
  78. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileTool.js +33 -0
  79. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerNoteTool.js +33 -0
  80. package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayCollaborationBackend.js +69 -0
  81. package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayHttpService.js +657 -0
  82. package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayReplyResolution.js +17 -0
  83. package/dist/services/features/telegram-mcp/src/features/inbox/model/deleteTelegramInboxMessageTool.js +33 -0
  84. package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxCountTool.js +33 -0
  85. package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxTool.js +33 -0
  86. package/dist/services/features/telegram-mcp/src/features/inbox/model/inboxService.js +77 -0
  87. package/dist/services/features/telegram-mcp/src/features/notify/model/notifyService.js +93 -0
  88. package/dist/services/features/telegram-mcp/src/features/notify/model/notifyTelegramTool.js +33 -0
  89. package/dist/services/features/telegram-mcp/src/features/pair-session/model/clearSessionPairingTool.js +33 -0
  90. package/dist/services/features/telegram-mcp/src/features/pair-session/model/createSessionPairCodeTool.js +33 -0
  91. package/dist/services/features/telegram-mcp/src/features/pair-session/model/generatePairCode.js +202 -0
  92. package/dist/services/features/telegram-mcp/src/features/session-context/model/clearSessionContextTool.js +33 -0
  93. package/dist/services/features/telegram-mcp/src/features/session-context/model/getSessionContextTool.js +33 -0
  94. package/dist/services/features/telegram-mcp/src/features/session-context/model/getTmuxTargetTool.js +33 -0
  95. package/dist/services/features/telegram-mcp/src/features/session-context/model/renameSessionTool.js +33 -0
  96. package/dist/services/features/telegram-mcp/src/features/session-context/model/sessionContextService.js +409 -0
  97. package/dist/services/features/telegram-mcp/src/features/session-context/model/setSessionContextTool.js +33 -0
  98. package/dist/services/features/telegram-mcp/src/features/session-context/model/setTmuxTargetTool.js +33 -0
  99. package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownService.js +123 -0
  100. package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownTool.js +33 -0
  101. package/dist/services/features/telegram-mcp/src/processes/human-approval/model/orchestrator.js +243 -0
  102. package/dist/services/features/telegram-mcp/src/shared/api/storage/contract.js +2 -0
  103. package/dist/services/features/telegram-mcp/src/shared/api/tool-registry/registry.js +8 -0
  104. package/dist/services/features/telegram-mcp/src/shared/api/tool-registry/types.js +2 -0
  105. package/dist/services/features/telegram-mcp/src/shared/api/transport/contract.js +2 -0
  106. package/dist/services/features/telegram-mcp/src/shared/integrations/object-storage/minioExchangeStore.js +86 -0
  107. package/dist/services/features/telegram-mcp/src/shared/integrations/redis/stateStore.js +436 -0
  108. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/collabSemantics.js +21 -0
  109. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/collabUi.js +87 -0
  110. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/messageFormat.js +60 -0
  111. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/proxyFetch.js +46 -0
  112. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +6534 -0
  113. package/dist/services/features/telegram-mcp/src/shared/integrations/tmux/client.js +280 -0
  114. package/dist/services/features/telegram-mcp/src/shared/lib/ids/ids.js +34 -0
  115. package/dist/services/features/telegram-mcp/src/shared/lib/logger/logger.js +68 -0
  116. package/dist/services/features/telegram-mcp/src/shared/lib/project-identity/projectIdentity.js +223 -0
  117. package/dist/services/features/telegram-mcp/src/shared/lib/redact-secrets/redactSecrets.js +22 -0
  118. package/dist/services/features/telegram-mcp/src/shared/lib/truncate/truncate.js +12 -0
  119. package/dist/services/features/telegram-mcp/src/shared/lib/version/versionHandshake.js +124 -0
  120. package/dist/services/features/telegram-mcp/src/shared/types/common.js +2 -0
  121. package/dist/services/features/telegram-mcp/standalone-http.service.js +113 -0
  122. package/dist/services/features/telegram-mcp/tools-sync.service.js +33 -0
  123. package/package.json +110 -0
  124. package/scripts/postinstall.js +60 -0
package/TOOLS.md ADDED
@@ -0,0 +1,1296 @@
1
+ # Tools
2
+
3
+ Version: `2026-05-17.1`
4
+
5
+ Gateway/client runtime compatibility:
6
+
7
+ - `TOOLS.md` hash sync and runtime version handshake are separate checks.
8
+ - `TOOLS.md` sync tells the agent to refresh instructions.
9
+ - `ws hello/hello_ack` checks `package_version`, `protocol_version`, and `capabilities`.
10
+ - If protocol major versions differ, gateway transport is blocked until the older side is upgraded.
11
+ - If you receive a system inbox message about gateway/client version mismatch, treat it as operational priority before continuing collaboration or live-relay work.
12
+
13
+ This MCP server currently exposes the following tools.
14
+
15
+ Browser tools:
16
+
17
+ - `browser_open`
18
+ - `browser_reload`
19
+ - `browser_click`
20
+ - `browser_fill`
21
+ - `browser_press`
22
+ - `browser_wait_for`
23
+ - `browser_wait_for_url`
24
+ - `browser_console`
25
+ - `browser_errors`
26
+ - `browser_network_failures`
27
+ - `browser_clear_logs`
28
+ - `browser_dom`
29
+ - `browser_computed_style`
30
+ - `browser_screenshot`
31
+ - `browser_close`
32
+
33
+ Collaboration tools:
34
+
35
+ - `send_partner_note`
36
+ - `send_partner_file`
37
+
38
+ Utility tools:
39
+
40
+ - `refresh_tools_markdown`
41
+
42
+ ## `create_session_pair_code`
43
+
44
+ Purpose:
45
+
46
+ - Create a short-lived Telegram pairing code for a session.
47
+
48
+ Typical use:
49
+
50
+ - first-time session linking
51
+ - re-linking after `clear_session_pairing`
52
+ - any request like "register me in Telegram", "link this session to Telegram", "pair this agent", or similar
53
+
54
+ Input:
55
+
56
+ - `session_id?`
57
+ - `session_label?`
58
+ - `cwd?`
59
+ - `expires_in_seconds?`
60
+ - `tmux_session_name?`
61
+ - `tmux_window_name?`
62
+ - `tmux_window_index?`
63
+ - `tmux_pane_id?`
64
+ - `tmux_pane_index?`
65
+
66
+ Output:
67
+
68
+ - `session_id`
69
+ - `code`
70
+ - `expires_at`
71
+ - `status`
72
+ - `status_message`
73
+ - `telegram_link_hint?`
74
+
75
+ Behavior:
76
+
77
+ - generated pairing codes are short numeric 3-digit one-time codes
78
+ - if `session_id` is omitted, the server derives it automatically
79
+ - if `cwd` is provided, the server uses it as the agent workspace root for default session identity and for `.mcp-xchange` file downloads
80
+ - `.mcp-xchange` is the active local exchange workspace for files, screenshots, notes, and handoffs
81
+ - one directory now maps to one logical session by default
82
+ - the service stores that logical identity in `.mcpsession.json` inside the workspace
83
+ - tmux attributes are runtime metadata only and no longer change `session_id`
84
+ - if tmux attributes are not provided here, the Telegram session can still pair successfully, but tmux nudges, Mini App controls, and other tmux-driven features will remain unavailable until `set_tmux_target` is called later
85
+
86
+ Required agent practice:
87
+
88
+ This is mandatory for the agent:
89
+
90
+ - when the user asks to register, link, pair, or connect the current agent/session to Telegram, do not call `create_session_pair_code` immediately from memory
91
+ - first determine the correct workspace `cwd`
92
+ - if tmux is available, collect the current tmux attributes too
93
+ - then call `create_session_pair_code` with them
94
+
95
+ Required order:
96
+
97
+ 1. Determine the agent workspace `cwd`.
98
+ 2. If running inside tmux, collect tmux attributes:
99
+
100
+ ```bash
101
+ tmux display-message -p '#{session_name} #{window_name} #{window_index} #{pane_id} #{pane_index}'
102
+ ```
103
+
104
+ 3. Call `create_session_pair_code` and pass:
105
+ - `cwd`
106
+ - tmux attributes when available
107
+ 4. Use `set_tmux_target` later only as a repair, refresh, or override path.
108
+
109
+ Do not skip `cwd`. It is now the anchor for the stable session marker.
110
+
111
+ After `create_session_pair_code` succeeds:
112
+
113
+ - treat the returned `session_id` as the canonical session identity for this agent
114
+ - remember it in the current task context
115
+ - pass it explicitly to later session-scoped tools
116
+ - do not rely on implicit session defaults unless you also know that `cwd` is already correct for this exact agent workspace
117
+
118
+ Why this matters:
119
+
120
+ - many MCP tools resolve `session_id` from explicit input first
121
+ - if it is omitted, the server may derive it from `cwd`
122
+ - if the agent did not pass the correct `cwd`, or the MCP client does not preserve it, a later tool call can hit the wrong session
123
+
124
+ Mandatory rule:
125
+
126
+ - after pairing, prefer:
127
+ - `session_id: "<returned value>"`
128
+ - for tools like:
129
+ - `ask_user_telegram`
130
+ - `notify_telegram`
131
+ - `get_telegram_inbox_count`
132
+ - `get_telegram_inbox`
133
+ - `delete_telegram_inbox_message`
134
+ - browser/session-context tools
135
+ - do not assume Telegram "active session" in the bot menu affects MCP tool defaults.
136
+
137
+ If you skip `cwd`:
138
+
139
+ - the service may create or reuse the wrong `.mcpsession.json`
140
+ - Telegram file exchange into `.mcp-xchange` may not know the correct agent workspace
141
+
142
+ If you skip tmux attributes:
143
+
144
+ - pairing may still succeed
145
+ - but tmux nudges and Mini App controls may not work until repaired later
146
+
147
+ ## `clear_session_pairing`
148
+
149
+ Purpose:
150
+
151
+ - Remove the Telegram binding for a session.
152
+
153
+ Input:
154
+
155
+ - `session_id?`
156
+
157
+ Output:
158
+
159
+ - `cleared`
160
+ - `session_id`
161
+
162
+ ## `set_session_context`
163
+
164
+ Purpose:
165
+
166
+ - Save compact reusable session context in Redis.
167
+
168
+ Input:
169
+
170
+ - `session_id?`
171
+ - `session_label?`
172
+ - `task?`
173
+ - `summary`
174
+ - `files?`
175
+ - `decisions?`
176
+ - `risks?`
177
+
178
+ Output:
179
+
180
+ - `saved`
181
+ - `session_id`
182
+ - `updated_at`
183
+ - `has_binding`
184
+
185
+ ## `rename_session`
186
+
187
+ Purpose:
188
+
189
+ - Rename the session title/label only.
190
+
191
+ Rules:
192
+
193
+ - this changes only the human-readable title
194
+ - it does not change `session_id`
195
+ - it does not change pairing, tmux target, inbox, or saved context
196
+
197
+ Input:
198
+
199
+ - `session_id?`
200
+ - `title`
201
+
202
+ Output:
203
+
204
+ - `renamed`
205
+ - `session_id`
206
+ - `session_label`
207
+ - `updated_at`
208
+
209
+ ## `set_tmux_target`
210
+
211
+ Purpose:
212
+
213
+ - Save the tmux pane target for a session so the long-running service can nudge the agent when new non-reply Telegram messages arrive for that paired session.
214
+
215
+ Recommended use:
216
+
217
+ - run this while still at the workstation
218
+ - do not treat this as the source of session identity
219
+ - use it immediately after pairing only if you need to repair, override, or refresh the target
220
+ - prefer a pane id such as `%7`
221
+
222
+ How to obtain tmux attributes:
223
+
224
+ ```bash
225
+ tmux display-message -p '#{session_name} #{window_name} #{window_index} #{pane_id} #{pane_index}'
226
+ ```
227
+
228
+ Input:
229
+
230
+ - `session_id?`
231
+ - `tmux_session_name?`
232
+ - `tmux_window_name?`
233
+ - `tmux_window_index?`
234
+ - `tmux_pane_id?`
235
+ - `tmux_pane_index?`
236
+ - `tmux_target`
237
+
238
+ Output:
239
+
240
+ - `session_id`
241
+ - `tmux_target`
242
+ - `tmux_session_name?`
243
+ - `tmux_window_name?`
244
+ - `tmux_window_index?`
245
+ - `tmux_pane_id?`
246
+ - `tmux_pane_index?`
247
+ - `status_message`
248
+
249
+ ## `get_tmux_target`
250
+
251
+ Purpose:
252
+
253
+ - Check whether a tmux target is configured for the current session and when it was last nudged.
254
+
255
+ Recommended use:
256
+
257
+ - setup/debug only
258
+ - use this when configuring tmux delivery or diagnosing why nudges do not happen
259
+ - do not call this in the normal inbox-processing path after a tmux nudge
260
+
261
+ Input:
262
+
263
+ - `session_id?`
264
+
265
+ Output:
266
+
267
+ - `session_id`
268
+ - `configured`
269
+ - `tmux_target?`
270
+ - `tmux_session_name?`
271
+ - `last_nudge_at?`
272
+ - `status_message`
273
+
274
+ ## `get_session_context`
275
+
276
+ Purpose:
277
+
278
+ - Read saved session context and Telegram binding status.
279
+
280
+ Recommended use:
281
+
282
+ - setup/debug only
283
+ - use this while pairing, diagnosing state, or inspecting saved metadata
284
+ - do not call this in the normal inbox-processing path after a tmux nudge
285
+
286
+ Input:
287
+
288
+ - `session_id?`
289
+
290
+ Output:
291
+
292
+ - `session_id`
293
+ - `exists`
294
+ - `has_binding`
295
+ - `status_message`
296
+ - `context?`
297
+ - `binding?`
298
+ - `tmux?`
299
+
300
+ ## `refresh_tools_markdown`
301
+
302
+ Purpose:
303
+
304
+ - Download the canonical `TOOLS.md` from the configured gateway.
305
+ - Overwrite the local `TOOLS.md` so the agent can refresh instructions without manual copying.
306
+
307
+ Input:
308
+
309
+ - `save_locally?`
310
+
311
+ Output:
312
+
313
+ - `source`
314
+ - `saved`
315
+ - `bytes`
316
+ - `path?`
317
+
318
+ Behavior:
319
+
320
+ - if `GATEWAY_PUBLIC_URL` is configured, the tool fetches `GET /api/gateway/tools-md`
321
+ - if no gateway is configured, the tool falls back to the local file
322
+ - on the gateway node, the local `TOOLS.md` is the canonical source and should always be kept current
323
+ - after successful refresh, treat the local `TOOLS.md` as updated state for this session and re-read it before continuing
324
+
325
+ ## `clear_session_context`
326
+
327
+ Purpose:
328
+
329
+ - Remove saved session context and Telegram pairing for the session.
330
+
331
+ Input:
332
+
333
+ - `session_id?`
334
+
335
+ Output:
336
+
337
+ - `cleared`
338
+ - `session_id`
339
+ - `cleared_pairing`
340
+
341
+ ## `send_partner_note`
342
+
343
+ Purpose:
344
+
345
+ - Send a structured collaboration note to another session.
346
+ - Write a note file into the partner workspace under `.mcp-xchange/shares/`.
347
+ - Append a line to the partner `.mcp-xchange/SHARED_INDEX.md`.
348
+ - Optionally copy listed artifacts from the current workspace into the partner `.mcp-xchange/shares/files/<share_id>/`.
349
+ - Create an inbox message for the partner agent and trigger the normal tmux nudge path.
350
+
351
+ Input:
352
+
353
+ - `session_id?`
354
+ - `target_session_id?`
355
+ - `project_uuid?`
356
+ - `kind`
357
+ - `share`
358
+ - `question`
359
+ - `reply`
360
+ - `request`
361
+ - `handoff`
362
+ - `summary`
363
+ - `message`
364
+ - `expected_reply?`
365
+ - `requires_reply?`
366
+ - `in_reply_to?`
367
+ - `artifacts?`
368
+
369
+ Output:
370
+
371
+ - `session_id`
372
+ - `partner_session_id`
373
+ - `kind`
374
+ - `share_id`
375
+ - `note_path`
376
+ - `share_index_path`
377
+ - `copied_artifacts`
378
+ - `inbox_message_id`
379
+ - `requires_reply`
380
+
381
+ Required agent practice:
382
+
383
+ - use this tool whenever the current session is linked to a partner and you need to communicate project-relevant information
384
+ - prefer structured note kinds over ad-hoc Telegram chat wording
385
+ - if the user asks things like:
386
+ - "ask backend what APIs it has"
387
+ - "tell frontend what changed"
388
+ - "send the error to your teammate"
389
+ - "tell the other agent what's new"
390
+ then the correct path is `send_partner_note`
391
+
392
+ How to find the partner correctly:
393
+
394
+ - never guess the target session from labels, menu text, or memory
395
+ - there are two valid targeting modes:
396
+ - local linked mode:
397
+ - call `get_session_context`
398
+ - use `context.linked_session_id`
399
+ - project / collab mode:
400
+ - use the explicit `target_session_id` that came from the project note, Telegram prompt, or task context
401
+ - if available, also pass `project_uuid`
402
+ - for project replies, do not fall back to `linked_session_id`
403
+ - if `target_session_id` is explicitly known, it has priority over any linked partner
404
+ - if neither `target_session_id` nor `linked_session_id` is available:
405
+ - do not retry blindly
406
+ - tell the user the target session is unknown
407
+ - ask them to relink locally or reopen the project target flow in Telegram
408
+
409
+ Minimal safe sequence:
410
+
411
+ 1. Call `get_session_context`.
412
+ 2. Resolve the target:
413
+ - prefer explicit `target_session_id` for project/collab work
414
+ - otherwise use `linked_session_id` for local partner work
415
+ 3. Decide the correct note kind: `question`, `reply`, `share`, `request`, or `handoff`.
416
+ 4. Call `send_partner_note`.
417
+
418
+ File transfer rule:
419
+
420
+ - if the requested result is an existing local file, send the actual file as an artifact
421
+ - prefer `send_partner_file` for this
422
+ - if you must stay on `send_partner_note`, use `artifact_refs`
423
+ - do not treat a sentence like "I am sending sample.txt" as completed delivery
424
+ - mentioning a filename in `message` is not enough; the receiver must get the real artifact
425
+
426
+ Minimal expectation for file delivery:
427
+
428
+ - include the normal text fields:
429
+ - `summary`
430
+ - `message`
431
+ - and also attach the file in `artifact_refs`
432
+ - if you can read the file locally, prefer embedding it immediately instead of asking the receiver to reconstruct it from text
433
+
434
+ Reply rule for project asks:
435
+
436
+ - when a collaboration note or `.mcp-xchange/shares/*.md` note contains:
437
+ - `Reply message_uuid: ...`
438
+ - `Reply target_session_id: ...`
439
+ - `Reply project_uuid: ...`
440
+ or a `Reply Params` section with the same data
441
+ - then reply with those exact values
442
+ - if `in_reply_to` is available, prefer `Reply message_uuid`
443
+ - if only the note `share_id` is available, gateway now also accepts that value in `in_reply_to`
444
+ - do not use `linked_session_id` for that reply
445
+ - if the note contains an `Action Required` section, treat it as mandatory execution guidance, not as optional commentary
446
+ - do not stop after local analysis when `Action Required` says to reply
447
+ - when `Reply Params` are present, prefer an explicit `send_partner_note(...)` call with those exact values
448
+
449
+ Mandatory completion rule:
450
+
451
+ - if a partner note says `requires_reply: true`, or contains `Reply Params`, or contains `Action Required` telling you to reply:
452
+ - your task is not complete after local analysis
453
+ - your task is not complete after writing an explanation into chat
454
+ - your task is complete only after `send_partner_note(...)` succeeds
455
+ - if `send_partner_note(...)` fails:
456
+ - treat that as an active blocker
457
+ - report the failure
458
+ - retry only with corrected routing parameters
459
+ - do not pretend the reply was sent
460
+ - never replace a required reply with:
461
+ - a local summary
462
+ - a chat-only explanation
463
+ - "I prepared the answer"
464
+ - "I am ready to answer"
465
+
466
+ Execution order for required replies:
467
+
468
+ 1. Read the partner note and extract `Reply Params`.
469
+ 2. Do the requested inspection or work locally.
470
+ 3. Call `send_partner_note(...)` with the explicit routing params.
471
+ 4. Only after the tool succeeds, say that the reply was sent.
472
+
473
+ ## `send_partner_file`
474
+
475
+ Purpose:
476
+
477
+ - Send a real existing local workspace file to another session.
478
+ - Wrap the normal partner note flow and attach the file artifact automatically.
479
+
480
+ Input:
481
+
482
+ - `session_id?`
483
+ - `target_session_id?`
484
+ - `project_uuid?`
485
+ - `cwd?`
486
+ - `file_path`
487
+ - `kind?`
488
+ - `summary?`
489
+ - `message?`
490
+ - `expected_reply?`
491
+ - `requires_reply?`
492
+ - `in_reply_to?`
493
+
494
+ Rules:
495
+
496
+ - use this when you already have a real file like `sample.txt`, `report.pdf`, `page.png`, `dump.log`
497
+ - prefer this over trying to hand-build `artifact_refs`
498
+ - `file_path` must point to a real file inside the current session workspace
499
+ - do not replace this with a plain note that only mentions the filename
500
+
501
+ Minimal file-delivery rule:
502
+
503
+ 1. Confirm the file exists in the local workspace.
504
+ 2. Call `send_partner_file(...)`.
505
+ 3. Only after the tool succeeds, say that the file was sent.
506
+
507
+ Routing priority:
508
+
509
+ 1. explicit `Reply target_session_id`
510
+ 2. explicit `target_session_id` from the current project/task context
511
+ 3. local `linked_session_id`
512
+
513
+ For project/collab traffic, step 3 is fallback only when no explicit target exists.
514
+
515
+ Canonical example for a project reply:
516
+
517
+ ```json
518
+ {
519
+ "session_id": "backend",
520
+ "in_reply_to": "29587d1e-2aaf-4663-a87c-a51581176cb4",
521
+ "target_session_id": "9df1ad2e-88d4-4b01-b706-72d60f79f7cb",
522
+ "project_uuid": "42a8ff66-....",
523
+ "kind": "reply",
524
+ "summary": "Описание REST API",
525
+ "message": "Подготовил краткое описание REST API и основных endpoints."
526
+ }
527
+ ```
528
+
529
+ How the receiving agent must react:
530
+
531
+ - partner collaboration wake-ups are not ordinary Telegram inbox wake-ups
532
+ - if the tmux nudge says things like:
533
+ - `прочитай SHARED_INDEX.md`
534
+ - `partner note`
535
+ - `partner notes`
536
+ then do not start with `get_telegram_inbox`
537
+ - instead:
538
+ 1. open `.mcp-xchange/SHARED_INDEX.md`
539
+ 2. find the newest partner note
540
+ 3. open that note file
541
+ 4. read any copied artifacts referenced there
542
+ - only use `get_telegram_inbox` for the normal Telegram human-message path
543
+ - do not confuse partner collaboration notes with human Telegram inbox traffic
544
+
545
+ What to do after reading the note:
546
+
547
+ - do not stop at summarizing the note back to the user
548
+ - choose behavior from `kind`
549
+ - if the note requires a reply, do the work and send the reply before declaring completion
550
+
551
+ Required behavior by note kind:
552
+
553
+ - `question`
554
+ - answer the partner's question
555
+ - if needed, inspect your workspace first
556
+ - then send a `reply`
557
+ - `reply`
558
+ - use the answer in your current work
559
+ - continue execution
560
+ - `share`
561
+ - update your assumptions/context
562
+ - continue execution if the update affects your task
563
+ - `request`
564
+ - treat it as an actionable task from the partner
565
+ - start doing the requested work unless it is clearly impossible or blocked
566
+ - when done, respond with `reply` or `handoff`
567
+ - `handoff`
568
+ - treat it as material to consume and continue from
569
+ - if the handoff asks for a concrete follow-up, start that work
570
+
571
+ Default rule:
572
+
573
+ - if the partner note contains a concrete ask, task, or follow-up, begin executing it
574
+ - do not merely report "I read the note" unless the user explicitly asked only for inspection
575
+ - if the note requires a reply, do not stop at "I prepared the answer"
576
+ - send the actual `reply` through `send_partner_note`
577
+
578
+ Recommended mapping:
579
+
580
+ - `question`
581
+ - ask for API summaries
582
+ - ask "what's new?"
583
+ - ask for error details
584
+ - `reply`
585
+ - answer a previous `question`
586
+ - set `in_reply_to`
587
+ - `share`
588
+ - communicate what changed without asking for action
589
+ - `request`
590
+ - ask the partner to do or verify something
591
+ - `handoff`
592
+ - transfer a result, contract, artifact, or completion note
593
+
594
+ Note contract:
595
+
596
+ - the service writes one note per message to:
597
+ - `.mcp-xchange/shares/<share_id>.md`
598
+ - the partner index is append-only:
599
+ - `.mcp-xchange/SHARED_INDEX.md`
600
+ - artifacts are copied into:
601
+ - `.mcp-xchange/shares/files/<share_id>/...`
602
+
603
+ What the source agent should include:
604
+
605
+ - `summary`
606
+ - one-line high-signal description
607
+ - `message`
608
+ - the actual explanation, question, request, or handoff content
609
+ - `expected_reply`
610
+ - when you need a concrete answer back
611
+ - `artifacts`
612
+ - paths to files from the current workspace that should be copied to the partner
613
+
614
+ Artifact rule:
615
+
616
+ - do not attach raw source files to partner notes
617
+ - this includes files such as:
618
+ - `.ts`, `.tsx`, `.js`, `.jsx`
619
+ - `.go`, `.py`, `.java`, `.rs`, `.php`
620
+ - `.html`, `.css`, `.scss`, `.vue`, `.svelte`
621
+ - shell scripts and similar source-like files
622
+ - instead send:
623
+ - API summaries
624
+ - endpoint signatures
625
+ - OpenAPI/spec files
626
+ - sample payloads
627
+ - logs
628
+ - screenshots
629
+ - Markdown notes
630
+
631
+ If a source file seems necessary, summarize the relevant contract in the note instead of copying the full implementation file.
632
+
633
+ What to communicate:
634
+
635
+ - API summaries and endpoint changes
636
+ - what changed since the last handoff
637
+ - current errors and how to reproduce them
638
+ - payload examples and specs
639
+ - relevant git context from the current workspace
640
+ - changed files
641
+ - branch-specific behavior
642
+ - important diffs or migration notes
643
+
644
+ If you mention git changes:
645
+
646
+ - summarize them in `message`
647
+ - attach the concrete files only when the partner really needs them
648
+ - do not assume the partner can infer your branch state without the note
649
+
650
+ ## `notify_telegram`
651
+
652
+ Purpose:
653
+
654
+ - Send a one-way Telegram message without waiting for a reply.
655
+
656
+ Input:
657
+
658
+ - `session_id?`
659
+ - `message`
660
+ - `task?`
661
+ - `context?`
662
+ - `risk_level?`
663
+ - `use_saved_context?`
664
+
665
+ Output:
666
+
667
+ - `sent`
668
+ - `message_id?`
669
+
670
+ ## `get_telegram_inbox_count`
671
+
672
+ Purpose:
673
+
674
+ - Fast inbox check.
675
+ - Returns only the number of stored unsolicited Telegram messages.
676
+
677
+ Recommended use:
678
+
679
+ - use this for lightweight passive checks
680
+ - use this when no tmux nudge path is configured
681
+ - after a tmux nudge, prefer calling `get_telegram_inbox` directly instead of spending an extra step on count
682
+
683
+ Input:
684
+
685
+ - `session_id?`
686
+
687
+ Output:
688
+
689
+ - `session_id`
690
+ - `total`
691
+
692
+ ## `get_telegram_inbox`
693
+
694
+ Purpose:
695
+
696
+ - Read unsolicited Telegram inbox messages stored for a session.
697
+ - Return a bounded batch rather than forcing the agent to pull the whole backlog at once.
698
+
699
+ Input:
700
+
701
+ - `session_id?`
702
+
703
+ Notes:
704
+
705
+ - the server always uses `TELEGRAM_INBOX_BATCH_SIZE`
706
+ - the agent should not try to choose its own batch size
707
+
708
+ Output:
709
+
710
+ - `session_id`
711
+ - `total`
712
+ - `has_more`
713
+ - `messages`
714
+
715
+ Per-message fields:
716
+
717
+ - `message_id`
718
+ - `source = "telegram"`
719
+ - `message_kind`
720
+ - `human`
721
+ - `system`
722
+ - `telegram_message_id`
723
+ - `telegram_chat_id`
724
+ - `telegram_user_id`
725
+ - `text`
726
+ - `attachments?`
727
+ - `received_at`
728
+
729
+ Meaning:
730
+
731
+ - when a task starts from one of these inbox items, treat it as a Telegram-originated task
732
+ - use `notify_telegram` for progress updates and `ask_user_telegram` for clarifications during that task
733
+ - if `message_kind = "system"`:
734
+ - treat it as an operational instruction from the service
735
+ - do not reinterpret it as a normal user request
736
+ - if it contains `Action Required`, follow that operational flow first
737
+ - for example, a `TOOLS.md updated` system message means:
738
+ 1. call `refresh_tools_markdown`
739
+ 2. re-read the local `TOOLS.md`
740
+ 3. apply the updated rules before continuing
741
+ - do not answer this kind of message with a normal human-facing reply unless the instruction explicitly says to notify the user
742
+ - process the batch one message at a time
743
+ - move to the next inbox item only if the current one did not create a blocker
744
+ - if the current message leads to a clarification wait or another blocking condition, stop batch processing there and leave the remaining inbox items pending
745
+ - if `attachments` is present, those are local paths inside `.mcp-xchange` that the agent can read from the workspace
746
+ - those paths are ordinary local workspace paths inside `.mcp-xchange`
747
+ - file upload itself is now the handoff action when the user is inside a target context
748
+ - there is no separate Telegram `Files` menu anymore
749
+ - browser screenshots created by `browser_screenshot` are tracked separately and appear under Telegram `Browser -> Screenshots`
750
+
751
+ ## `delete_telegram_inbox_message`
752
+
753
+ Purpose:
754
+
755
+ - Remove a processed inbox message so it is not handled again.
756
+
757
+ Input:
758
+
759
+ - `session_id?`
760
+ - `message_id`
761
+
762
+ Output:
763
+
764
+ - `deleted`
765
+ - `session_id`
766
+ - `message_id`
767
+
768
+ ## `browser_open`
769
+
770
+ Purpose:
771
+
772
+ - open or reuse a Playwright tab for the current session
773
+ - keep browser state isolated per `session_id`
774
+
775
+ Input:
776
+
777
+ - `session_id?`
778
+ - `url`
779
+ - `wait_until?`
780
+ - `reset_context?`
781
+
782
+ Output:
783
+
784
+ - `session_id`
785
+ - `opened`
786
+ - `created_context`
787
+ - `url`
788
+ - `title?`
789
+
790
+ Notes:
791
+
792
+ - each session gets its own isolated browser context and page
793
+ - call this first before reading console, DOM, styles, or screenshots
794
+ - `url` may be an absolute URL, or a relative path when `BROWSER_ADDRESS` is configured
795
+
796
+ ## `browser_console`
797
+
798
+ Purpose:
799
+
800
+ - read recent console output from the session browser tab
801
+
802
+ Input:
803
+
804
+ - `session_id?`
805
+ - `limit?`
806
+
807
+ Output:
808
+
809
+ - `session_id`
810
+ - `total`
811
+ - `messages`
812
+
813
+ ## `browser_reload`
814
+
815
+ Purpose:
816
+
817
+ - reload the current session browser page after code changes or state drift
818
+
819
+ Input:
820
+
821
+ - `session_id?`
822
+ - `wait_until?`
823
+
824
+ Output:
825
+
826
+ - `session_id`
827
+ - `reloaded`
828
+ - `url`
829
+ - `title?`
830
+
831
+ ## `browser_click`
832
+
833
+ Purpose:
834
+
835
+ - click an element in the current session page
836
+
837
+ Input:
838
+
839
+ - `session_id?`
840
+ - `ai_tag?`
841
+ - `selector?`
842
+ - `text?`
843
+ - `exact?`
844
+ - `timeout_ms?`
845
+
846
+ Output:
847
+
848
+ - `session_id`
849
+ - `clicked`
850
+ - `ai_tag?`
851
+ - `selector?`
852
+ - `text?`
853
+ - `url`
854
+ - `title?`
855
+
856
+ ## `browser_fill`
857
+
858
+ Purpose:
859
+
860
+ - fill an input or textarea in the current session page
861
+
862
+ Input:
863
+
864
+ - `session_id?`
865
+ - `ai_tag?`
866
+ - `selector?`
867
+ - `text?`
868
+ - `exact?`
869
+ - `timeout_ms?`
870
+ - `value`
871
+
872
+ Output:
873
+
874
+ - `session_id`
875
+ - `filled`
876
+ - `ai_tag?`
877
+ - `selector?`
878
+ - `text?`
879
+ - `value_length`
880
+ - `url`
881
+ - `title?`
882
+
883
+ ## `browser_press`
884
+
885
+ Purpose:
886
+
887
+ - send a key press to the page or a targeted element
888
+
889
+ Input:
890
+
891
+ - `session_id?`
892
+ - `ai_tag?`
893
+ - `selector?`
894
+ - `text?`
895
+ - `exact?`
896
+ - `timeout_ms?`
897
+ - `key`
898
+
899
+ Output:
900
+
901
+ - `session_id`
902
+ - `pressed`
903
+ - `key`
904
+ - `ai_tag?`
905
+ - `selector?`
906
+ - `text?`
907
+ - `url`
908
+ - `title?`
909
+
910
+ ## `browser_wait_for`
911
+
912
+ Purpose:
913
+
914
+ - wait until an element in the current session page reaches a requested state
915
+
916
+ Input:
917
+
918
+ - `session_id?`
919
+ - `ai_tag?`
920
+ - `selector?`
921
+ - `text?`
922
+ - `exact?`
923
+ - `timeout_ms?`
924
+ - `state?`
925
+
926
+ Output:
927
+
928
+ - `session_id`
929
+ - `waited`
930
+ - `state`
931
+ - `ai_tag?`
932
+ - `selector?`
933
+ - `text?`
934
+ - `url`
935
+ - `title?`
936
+
937
+ Browser target rules for `browser_click`, `browser_fill`, `browser_press`, `browser_wait_for`:
938
+
939
+ - prefer `ai_tag` first when the frontend provides it
940
+ - supported markup:
941
+ - `data-drive-tag="save-button"`
942
+ - `ai-tag="save-button"`
943
+ - recommended usage is an attribute with a value, not a bare presence-only attribute
944
+ - prefer `selector` when you have a stable target:
945
+ - `#id`
946
+ - `.class`
947
+ - `button[type="submit"]`
948
+ - `div[data-testid="save"]`
949
+ - use `text` only when there is no reliable selector
950
+ - do not mix ambiguous hashed CSS classes with fuzzy text guessing when a stable selector exists
951
+
952
+ ## `browser_wait_for_url`
953
+
954
+ Purpose:
955
+
956
+ - wait until the current session page navigates to an exact URL or to a URL containing a fragment
957
+
958
+ Input:
959
+
960
+ - `session_id?`
961
+ - `url?`
962
+ - `url_contains?`
963
+ - `timeout_ms?`
964
+
965
+ Output:
966
+
967
+ - `session_id`
968
+ - `waited`
969
+ - `matched`
970
+ - `url?`
971
+ - `url_contains?`
972
+ - `current_url`
973
+ - `title?`
974
+
975
+ ## `browser_errors`
976
+
977
+ Purpose:
978
+
979
+ - read recent page runtime errors from the session browser tab
980
+
981
+ Input:
982
+
983
+ - `session_id?`
984
+ - `limit?`
985
+
986
+ Output:
987
+
988
+ - `session_id`
989
+ - `total`
990
+ - `errors`
991
+
992
+ ## `browser_network_failures`
993
+
994
+ Purpose:
995
+
996
+ - read recent failed or HTTP-error requests from the session browser tab
997
+
998
+ Input:
999
+
1000
+ - `session_id?`
1001
+ - `limit?`
1002
+
1003
+ Output:
1004
+
1005
+ - `session_id`
1006
+ - `total`
1007
+ - `failures`
1008
+
1009
+ ## `browser_clear_logs`
1010
+
1011
+ Purpose:
1012
+
1013
+ - clear accumulated browser console, runtime error, and network failure buffers for the current session
1014
+
1015
+ Input:
1016
+
1017
+ - `session_id?`
1018
+
1019
+ Output:
1020
+
1021
+ - `session_id`
1022
+ - `cleared`
1023
+ - `console_messages_cleared`
1024
+ - `page_errors_cleared`
1025
+ - `network_failures_cleared`
1026
+
1027
+ ## `browser_dom`
1028
+
1029
+ Purpose:
1030
+
1031
+ - inspect a DOM element in the session browser tab
1032
+
1033
+ Input:
1034
+
1035
+ - `session_id?`
1036
+ - `selector?`
1037
+ - `include_html?`
1038
+ - `include_text?`
1039
+
1040
+ Output:
1041
+
1042
+ - `session_id`
1043
+ - `selector`
1044
+ - `found`
1045
+ - `url?`
1046
+ - `title?`
1047
+ - `outer_html?`
1048
+ - `text_content?`
1049
+ - `visible?`
1050
+ - `attributes?`
1051
+
1052
+ ## `browser_computed_style`
1053
+
1054
+ Purpose:
1055
+
1056
+ - inspect computed styles and box metrics for a DOM element in the session browser tab
1057
+
1058
+ Input:
1059
+
1060
+ - `session_id?`
1061
+ - `selector`
1062
+ - `properties?`
1063
+
1064
+ Output:
1065
+
1066
+ - `session_id`
1067
+ - `selector`
1068
+ - `found`
1069
+ - `url?`
1070
+ - `title?`
1071
+ - `visible?`
1072
+ - `styles?`
1073
+ - `box?`
1074
+
1075
+ ## `browser_screenshot`
1076
+
1077
+ Purpose:
1078
+
1079
+ - capture a screenshot from the session browser tab
1080
+
1081
+ Input:
1082
+
1083
+ - `session_id?`
1084
+ - `selector?`
1085
+ - `full_page?`
1086
+ - `file_name?`
1087
+ - `send_to_telegram?`
1088
+ - `caption?`
1089
+
1090
+ Output:
1091
+
1092
+ - `session_id`
1093
+ - `file_path`
1094
+ - `workspace_dir`
1095
+ - `exchange_dir`
1096
+ - `telegram_message_id?`
1097
+ - `url?`
1098
+ - `title?`
1099
+
1100
+ Notes:
1101
+
1102
+ - screenshots are written into `.mcp-xchange`
1103
+ - they are tracked separately from Telegram-uploaded files
1104
+ - they appear under Telegram `Browser -> Screenshots`
1105
+ - if `send_to_telegram=true`, the saved screenshot is also sent into the bound Telegram chat for that session
1106
+
1107
+ ## `browser_close`
1108
+
1109
+ Purpose:
1110
+
1111
+ - close the isolated browser context for the current session
1112
+
1113
+ Input:
1114
+
1115
+ - `session_id?`
1116
+
1117
+ Output:
1118
+
1119
+ - `session_id`
1120
+ - `closed`
1121
+
1122
+ ## Operational notes
1123
+
1124
+ Telegram UI summary:
1125
+
1126
+ - `/menu` is the only top-level Telegram command for session navigation
1127
+ - root menu shows one session button per row
1128
+ - root menu also shows tmux bridge status
1129
+ - session menu uses:
1130
+ - `Live | Content | Browser`
1131
+ - `Local | Collab`
1132
+ - `Inbox | Storage | Settings`
1133
+ - `Back`
1134
+ - default logical session identity comes from `.mcpsession.json` in the workspace
1135
+ - changing tmux session/window/pane does not change `session_id`
1136
+ - `Browser -> Screenshots` lists screenshots created by `browser_screenshot`
1137
+ - `Storage` browses `.mcp-xchange` for the active session and can send stored notes/files back into Telegram
1138
+ - `Settings` contains `Info`, `Rename`, `Unpair`, `Back`
1139
+ - `Link` creates a mutual partner relationship between two sessions visible to the same Telegram identity
1140
+ - `Local` is the Telegram UI wrapper over same-bot partner collaboration
1141
+ - `Collab` is the project-based multi-machine collaboration flow
1142
+ - inside `Collab -> Project -> Member`, action semantics differ:
1143
+ - first row is `Ask | Share`
1144
+ - second row is `Live`
1145
+ - `Ask` sends a task to the selected member session
1146
+ - expected reply route is `member -> current session`
1147
+ - `Share` creates a task for the current session
1148
+ - expected send route is `current session -> member`
1149
+ - `Live` first sends an approval request to the selected member session
1150
+ - after approval, the requester receives a fresh `Open Live View` button in Telegram
1151
+ - partner-note prompt format is:
1152
+ - first line = summary
1153
+ - optional blank line
1154
+ - remaining text = full message body
1155
+ - if an old project-member menu message becomes stale, clicking it deletes that outdated Telegram message
1156
+ - partner-note wake-up means:
1157
+ - read `.mcp-xchange/SHARED_INDEX.md`
1158
+ - then read the newest partner note
1159
+ - not `get_telegram_inbox`
1160
+
1161
+ Distributed mode scaffold:
1162
+
1163
+ - `DISTRIBUTED_MODE=client|gateway|both`
1164
+ - `/gateway/healthz` is available when mode is `gateway` or `both`
1165
+ - `/gateway/partner-note` is available when mode is `gateway` or `both`
1166
+ - if `GATEWAY_PUBLIC_URL` is configured, `send_partner_note` and Telegram `Collab` delivery use the gateway HTTP surface for note creation
1167
+ - in `DISTRIBUTED_MODE=both`, same-bot local delivery should still go through the gateway path transparently
1168
+ - gateway/client online transport now uses `ws`
1169
+ - optional gateway-side `RabbitMQ` fanout can be enabled through `RMQ_*`
1170
+ - `TOOLS.md` sync is hash-based:
1171
+ - client sends `session_tools` in `ws hello`
1172
+ - gateway compares them with canonical gateway `TOOLS.md`
1173
+ - mismatch produces `tools_event`
1174
+ - client also self-checks after `hello_ack`
1175
+ - once linked, agents should use `.mcp-xchange/SHARED_INDEX.md` plus separate files in `.mcp-xchange/shares/` for collaboration
1176
+ - recommended collaboration note kinds are:
1177
+ - `share`
1178
+ - `question`
1179
+ - `reply`
1180
+ - `request`
1181
+ - `handoff`
1182
+ - useful collaboration content includes API summaries, what changed, current errors, sample payloads, and relevant git changes from the agent workspace
1183
+ - `Tools` contains `Broadcast` and `Prune all`
1184
+ - `Collab -> Tools` contains:
1185
+ - `Broadcast`
1186
+ - `History`
1187
+ - `Delete`
1188
+ - `History` sends a markdown export of the last 5 Collab events for the current active session
1189
+
1190
+ Current remaining operational gaps are tracked in [docs/TODO.md](/home/code4bones/Devs/coding/mcp/telegram_mcp/docs/TODO.md).
1191
+
1192
+ ## `ask_user_telegram`
1193
+
1194
+ Purpose:
1195
+
1196
+ - Send a Telegram clarification request and wait for a reply.
1197
+
1198
+ Input:
1199
+
1200
+ - `question`
1201
+ - `task?`
1202
+ - `context?`
1203
+ - `affected_files?`
1204
+ - `options?`
1205
+ - `recommended_option?`
1206
+ - `risk_level?`
1207
+ - `timeout_seconds?`
1208
+ - `fallback_if_timeout?`
1209
+ - `session_id?`
1210
+ - `use_saved_context?`
1211
+
1212
+ Output:
1213
+
1214
+ - `request_id`
1215
+ - `answer`
1216
+ - `timed_out`
1217
+ - `received_at?`
1218
+ - `fallback_used?`
1219
+
1220
+ ## Telegram inbox protocol
1221
+
1222
+ The inbox may contain new user instructions sent from Telegram.
1223
+
1224
+ If a paired session has a configured `tmux_target`, the preferred path is event-driven: Telegram stores the message, the service nudges tmux, and the agent then fetches `get_telegram_inbox`.
1225
+
1226
+ If no tmux nudge path exists, use passive inbox checks with `get_telegram_inbox_count`.
1227
+
1228
+ ## Telegram transition protocol
1229
+
1230
+ When the user says they are leaving the workstation and wants to continue through Telegram:
1231
+
1232
+ 1. If running inside tmux, obtain full tmux attributes:
1233
+
1234
+ ```bash
1235
+ tmux display-message -p '#{session_name} #{window_name} #{window_index} #{pane_id} #{pane_index}'
1236
+ ```
1237
+
1238
+ 2. Call `create_session_pair_code` with these attributes so the session identity is derived distinctly for this agent.
1239
+ 3. Complete pairing in Telegram.
1240
+ 4. If needed, call `set_tmux_target` only to override or refresh the stored target later.
1241
+ 5. Continue work normally.
1242
+ 6. If the long-running service nudges the tmux pane with `проверь inbox`, treat that as the signal to fetch the next inbox batch.
1243
+ 7. Read actual inbox content only through MCP tools.
1244
+
1245
+ The service does not inject Telegram message text into tmux. It only sends the wake-up phrase. Telegram messages remain stored in Redis inbox until the agent explicitly reads and deletes them. Multiple close-together Telegram messages are debounced into a single tmux wake-up.
1246
+
1247
+ ## Telegram session switching
1248
+
1249
+ The Telegram side supports an active-session context per Telegram identity.
1250
+
1251
+ Rules:
1252
+
1253
+ - ordinary Telegram messages are stored in the inbox of the currently active session
1254
+ - `/menu` opens a menu with all sessions linked to the current Telegram identity
1255
+ - selecting a session makes it the new active session
1256
+ - the main menu also provides a session-switch entry point
1257
+ - the list contains every distinct `session_id` paired to this Telegram identity, so multi-agent setups depend on deriving different session ids during pairing
1258
+
1259
+ If tmux nudging is configured, the preferred behavior is event-driven:
1260
+
1261
+ 1. Wait for the tmux nudge.
1262
+ 2. Call `get_telegram_inbox`.
1263
+ 3. Process the returned batch one message at a time.
1264
+ 4. Move to the next message only if the current message did not create a blocker, follow-up question, or execution error.
1265
+ 5. If the current message requires clarification or cannot be completed safely, stop batch progression, enter the `ask_user_telegram` branch, and leave the remaining inbox items pending.
1266
+ 6. Call `delete_telegram_inbox_message` only for messages that were actually handled.
1267
+ 7. If `has_more = true` and the current batch finished cleanly, call `get_telegram_inbox` again for the next batch.
1268
+
1269
+ Do not add extra diagnostic calls in that path:
1270
+
1271
+ - do not call `get_tmux_target` before `get_telegram_inbox`
1272
+ - do not call `get_session_context` before `get_telegram_inbox`
1273
+ - do not call `get_telegram_inbox_count` before `get_telegram_inbox` when the wake-up already came from tmux
1274
+
1275
+ ## Presence model
1276
+
1277
+ Current truth:
1278
+
1279
+ - gateway can know whether a client node is online through active `ws`
1280
+ - gateway also stores `gateway_clients.last_seen_at`
1281
+ - this is not the same thing as a live coding-agent heartbeat inside each session
1282
+
1283
+ Rule:
1284
+
1285
+ - do not claim that a session agent is definitely `offline` unless a dedicated agent heartbeat exists
1286
+ - today the honest distinction is:
1287
+ - client node `online/offline`
1288
+ - session bound/unbound
1289
+ - tmux target configured/not configured
1290
+
1291
+ If no tmux target is configured, use passive inbox checks:
1292
+
1293
+ 1. Call `get_telegram_inbox_count`.
1294
+ 2. If `total > 0`, call `get_telegram_inbox`.
1295
+ 3. Process messages.
1296
+ 4. Call `delete_telegram_inbox_message` for handled items.