@deadragdoll/tellymcp 0.0.12 → 0.0.14

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 (83) hide show
  1. package/.env.example.client +5 -1
  2. package/.env.example.gateway +16 -1
  3. package/CHANGELOG.md +30 -0
  4. package/README-ru.md +33 -0
  5. package/README.md +33 -0
  6. package/TOOLS.md +384 -9
  7. package/config/templates/env.both.template +15 -2
  8. package/config/templates/env.client.template +5 -2
  9. package/config/templates/env.gateway.template +15 -2
  10. package/dist/cli.js +137 -2
  11. package/dist/services/features/telegram-mcp/browser.service.js +56 -1
  12. package/dist/services/features/telegram-mcp/file-content.service.js +94 -0
  13. package/dist/services/features/telegram-mcp/gateway-delivery.service.js +5 -1
  14. package/dist/services/features/telegram-mcp/gateway-socket.service.js +43 -11
  15. package/dist/services/features/telegram-mcp/mcp-http.service.js +1 -0
  16. package/dist/services/features/telegram-mcp/mcp-server.service.js +30 -0
  17. package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +23 -1
  18. package/dist/services/features/telegram-mcp/src/app/config/env.js +132 -2
  19. package/dist/services/features/telegram-mcp/src/app/http.js +139 -99
  20. package/dist/services/features/telegram-mcp/src/app/oauthFacade.js +642 -0
  21. package/dist/services/features/telegram-mcp/src/app/webapp/assets.js +151 -170
  22. package/dist/services/features/telegram-mcp/src/app/webapp/auth.js +96 -99
  23. package/dist/services/features/telegram-mcp/src/entities/request/model/schema.js +205 -17
  24. package/dist/services/features/telegram-mcp/src/features/browser/model/browserAttachActiveTabTool.js +28 -0
  25. package/dist/services/features/telegram-mcp/src/features/browser/model/browserAttachTabTool.js +28 -0
  26. package/dist/services/features/telegram-mcp/src/features/browser/model/browserClickTool.js +1 -1
  27. package/dist/services/features/telegram-mcp/src/features/browser/model/browserDetachTabTool.js +28 -0
  28. package/dist/services/features/telegram-mcp/src/features/browser/model/browserDomTool.js +1 -1
  29. package/dist/services/features/telegram-mcp/src/features/browser/model/browserFillTool.js +1 -1
  30. package/dist/services/features/telegram-mcp/src/features/browser/model/browserInjectScriptTool.js +28 -0
  31. package/dist/services/features/telegram-mcp/src/features/browser/model/browserListAttachedInstancesTool.js +33 -0
  32. package/dist/services/features/telegram-mcp/src/features/browser/model/browserListTabsTool.js +33 -0
  33. package/dist/services/features/telegram-mcp/src/features/browser/model/browserPressTool.js +1 -1
  34. package/dist/services/features/telegram-mcp/src/features/browser/model/browserRecordingStartTool.js +28 -0
  35. package/dist/services/features/telegram-mcp/src/features/browser/model/browserRecordingStatusTool.js +28 -0
  36. package/dist/services/features/telegram-mcp/src/features/browser/model/browserRecordingStopTool.js +28 -0
  37. package/dist/services/features/telegram-mcp/src/features/browser/model/browserScreenshotTool.js +1 -1
  38. package/dist/services/features/telegram-mcp/src/features/browser/model/browserService.js +890 -23
  39. package/dist/services/features/telegram-mcp/src/features/browser-attach/model/browserRecordingBundle.js +536 -0
  40. package/dist/services/features/telegram-mcp/src/features/browser-attach/model/firefoxAttachRegistry.js +80 -0
  41. package/dist/services/features/telegram-mcp/src/features/browser-attach/model/firefoxAttachServer.js +736 -0
  42. package/dist/services/features/telegram-mcp/src/features/browser-attach/model/types.js +188 -0
  43. package/dist/services/features/telegram-mcp/src/features/collaboration/model/collaborationService.js +2 -0
  44. package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileService.js +6 -3
  45. package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayClientAccess.js +4 -1
  46. package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayHttpService.js +33 -35
  47. package/dist/services/features/telegram-mcp/src/features/file-content/model/getFileListTool.js +33 -0
  48. package/dist/services/features/telegram-mcp/src/features/file-content/model/getFileService.js +327 -0
  49. package/dist/services/features/telegram-mcp/src/features/file-content/model/getFileTool.js +81 -0
  50. package/dist/services/features/telegram-mcp/src/features/file-content/model/temporaryFileLinkStore.js +307 -0
  51. package/dist/services/features/telegram-mcp/src/features/file-content/model/workspaceFilePolicy.js +115 -0
  52. package/dist/services/features/telegram-mcp/src/features/notify/model/notifyService.js +5 -1
  53. package/dist/services/features/telegram-mcp/src/shared/integrations/redis/stateStore.js +28 -0
  54. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +3 -0
  55. package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportFileHandoffActions.js +6 -3
  56. package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/client.js +29 -6
  57. package/dist/services/features/telegram-mcp/src/shared/integrations/terminal/ptyRegistry.js +100 -2
  58. package/dist/services/features/telegram-mcp/src/shared/lib/bodyLimits.js +63 -0
  59. package/dist/services/features/telegram-mcp/src/shared/lib/gatewayAuth.js +13 -0
  60. package/dist/services/features/telegram-mcp/src/shared/lib/time/localTimestamp.js +21 -0
  61. package/docs/CHAT_CONNECTOR.md +134 -0
  62. package/docs/STANDALONE-ru.md +55 -6
  63. package/docs/STANDALONE.md +55 -6
  64. package/package.json +10 -5
  65. package/packages/chrome-attach-extension/dist/background.js +1735 -0
  66. package/packages/chrome-attach-extension/dist/icon.svg +6 -0
  67. package/packages/chrome-attach-extension/dist/manifest.json +37 -0
  68. package/packages/chrome-attach-extension/dist/options.html +312 -0
  69. package/packages/chrome-attach-extension/dist/options.js +606 -0
  70. package/packages/chrome-attach-extension/dist/popup.html +93 -0
  71. package/packages/chrome-attach-extension/dist/popup.js +79 -0
  72. package/packages/chrome-attach-extension/dist/recorder-content.js +96 -0
  73. package/packages/chrome-attach-extension/dist/recorder-page.js +282 -0
  74. package/packages/firefox-attach-extension/README.md +13 -0
  75. package/packages/firefox-attach-extension/dist/background.js +1622 -0
  76. package/packages/firefox-attach-extension/dist/icon.svg +6 -0
  77. package/packages/firefox-attach-extension/dist/manifest.json +44 -0
  78. package/packages/firefox-attach-extension/dist/options.html +312 -0
  79. package/packages/firefox-attach-extension/dist/options.js +540 -0
  80. package/packages/firefox-attach-extension/dist/popup.html +93 -0
  81. package/packages/firefox-attach-extension/dist/popup.js +64 -0
  82. package/packages/firefox-attach-extension/dist/recorder-content.js +90 -0
  83. package/packages/firefox-attach-extension/dist/recorder-page.js +318 -0
@@ -0,0 +1,90 @@
1
+ (() => {
2
+ if (window.__tellyRecorderContentInstalled === true) {
3
+ return;
4
+ }
5
+ window.__tellyRecorderContentInstalled = true;
6
+
7
+ function padNumber(value, length = 2) {
8
+ return String(value).padStart(length, "0");
9
+ }
10
+
11
+ function formatLocalTimestamp(date = new Date()) {
12
+ return `${date.getFullYear()}-${padNumber(date.getMonth() + 1)}-${padNumber(date.getDate())}T${padNumber(
13
+ date.getHours(),
14
+ )}:${padNumber(date.getMinutes())}:${padNumber(date.getSeconds())}.${padNumber(
15
+ date.getMilliseconds(),
16
+ 3,
17
+ )}`;
18
+ }
19
+
20
+ function emit(payload) {
21
+ try {
22
+ browser.runtime.sendMessage({
23
+ type: "telly_recording_page_event",
24
+ event: payload,
25
+ });
26
+ } catch {
27
+ // ignore
28
+ }
29
+ }
30
+
31
+ function snapshot(reason) {
32
+ if (window.top !== window) {
33
+ return;
34
+ }
35
+ emit({
36
+ kind: "page_snapshot",
37
+ source: "content",
38
+ reason,
39
+ at: formatLocalTimestamp(new Date()),
40
+ url: location.href,
41
+ title: document.title,
42
+ ready_state: document.readyState,
43
+ html: document.documentElement?.outerHTML || "",
44
+ });
45
+ }
46
+
47
+ window.addEventListener("message", (event) => {
48
+ if (event.source !== window) {
49
+ return;
50
+ }
51
+ if (!event.data || event.data.__tellyRecorderPageEvent !== true) {
52
+ return;
53
+ }
54
+ emit(event.data.payload);
55
+ });
56
+
57
+ const injection = document.createElement("script");
58
+ injection.src = browser.runtime.getURL("recorder-page.js");
59
+ injection.async = false;
60
+ (document.documentElement || document.head || document.body).appendChild(injection);
61
+ injection.addEventListener(
62
+ "load",
63
+ () => {
64
+ injection.remove();
65
+ },
66
+ { once: true },
67
+ );
68
+ injection.addEventListener(
69
+ "error",
70
+ () => {
71
+ emit({
72
+ kind: "console_event",
73
+ source: "content",
74
+ level: "error",
75
+ text: "Failed to load recorder-page.js",
76
+ url: location.href,
77
+ title: document.title,
78
+ });
79
+ injection.remove();
80
+ },
81
+ { once: true },
82
+ );
83
+
84
+ snapshot("recording-script-installed");
85
+ if (window.top === window) {
86
+ window.addEventListener("load", () => {
87
+ snapshot("window-load");
88
+ });
89
+ }
90
+ })();
@@ -0,0 +1,318 @@
1
+ (() => {
2
+ if (window.__tellyRecorderPageInstalled === true) {
3
+ return;
4
+ }
5
+ window.__tellyRecorderPageInstalled = true;
6
+
7
+ const MAX_TEXT_CHARS = 64 * 1024;
8
+ const padNumber = (value, length = 2) => String(value).padStart(length, "0");
9
+ const formatLocalTimestamp = (date = new Date()) => {
10
+ return `${date.getFullYear()}-${padNumber(date.getMonth() + 1)}-${padNumber(date.getDate())}T${padNumber(
11
+ date.getHours(),
12
+ )}:${padNumber(date.getMinutes())}:${padNumber(date.getSeconds())}.${padNumber(
13
+ date.getMilliseconds(),
14
+ 3,
15
+ )}`;
16
+ };
17
+ const truncateText = (value) => {
18
+ const text = String(value ?? "");
19
+ return text.length > MAX_TEXT_CHARS ? text.slice(0, MAX_TEXT_CHARS) : text;
20
+ };
21
+ const serializeValue = (value, depth = 0) => {
22
+ if (depth >= 2) return truncateText(value);
23
+ if (value === null || value === undefined) return value;
24
+ if (typeof value === "string") return truncateText(value);
25
+ if (typeof value === "number" || typeof value === "boolean") return value;
26
+ if (value instanceof Error) {
27
+ return {
28
+ name: value.name,
29
+ message: truncateText(value.message),
30
+ stack: truncateText(value.stack || ""),
31
+ };
32
+ }
33
+ if (Array.isArray(value)) {
34
+ return value.slice(0, 20).map((item) => serializeValue(item, depth + 1));
35
+ }
36
+ if (typeof value === "object") {
37
+ const output = {};
38
+ for (const [key, nested] of Object.entries(value).slice(0, 20)) {
39
+ output[key] = serializeValue(nested, depth + 1);
40
+ }
41
+ return output;
42
+ }
43
+ return truncateText(value);
44
+ };
45
+ const emit = (payload) => {
46
+ window.postMessage({ __tellyRecorderPageEvent: true, payload }, "*");
47
+ };
48
+ const emitConsole = (level, args, textOverride) => {
49
+ emit({
50
+ kind: "console_event",
51
+ source: "page",
52
+ at: formatLocalTimestamp(new Date()),
53
+ level,
54
+ text:
55
+ textOverride ||
56
+ truncateText(
57
+ args
58
+ .map((item) => {
59
+ if (typeof item === "string") return item;
60
+ try {
61
+ return JSON.stringify(item);
62
+ } catch {
63
+ return String(item);
64
+ }
65
+ })
66
+ .join(" "),
67
+ ),
68
+ args: args.map((item) => serializeValue(item)),
69
+ url: location.href,
70
+ title: document.title,
71
+ });
72
+ };
73
+ const headersToArray = (headers) => {
74
+ try {
75
+ return Array.from(headers.entries()).map(([name, value]) => ({ name, value }));
76
+ } catch {
77
+ return [];
78
+ }
79
+ };
80
+ const serializeRequestBody = async (request) => {
81
+ try {
82
+ const text = await request.clone().text();
83
+ if (!text) return { body_text: "" };
84
+ return {
85
+ body_text: truncateText(text),
86
+ body_truncated: text.length > MAX_TEXT_CHARS,
87
+ };
88
+ } catch {
89
+ return {};
90
+ }
91
+ };
92
+
93
+ for (const level of [
94
+ "log",
95
+ "info",
96
+ "warn",
97
+ "error",
98
+ "debug",
99
+ "trace",
100
+ "dir",
101
+ "dirxml",
102
+ "table",
103
+ ]) {
104
+ const original = console[level];
105
+ if (typeof original !== "function") {
106
+ continue;
107
+ }
108
+ console[level] = function patchedConsole(...args) {
109
+ try {
110
+ const textOverride =
111
+ level === "trace"
112
+ ? truncateText(new Error(args[0] ? String(args[0]) : "console.trace").stack || "")
113
+ : undefined;
114
+ emitConsole(level, args, textOverride);
115
+ } catch {
116
+ // ignore
117
+ }
118
+ return original.apply(this, args);
119
+ };
120
+ }
121
+
122
+ if (typeof console.assert === "function") {
123
+ const originalAssert = console.assert;
124
+ console.assert = function patchedAssert(condition, ...args) {
125
+ try {
126
+ if (!condition) {
127
+ emitConsole("assert", args, truncateText(args[0] ? String(args[0]) : "Assertion failed"));
128
+ }
129
+ } catch {
130
+ // ignore
131
+ }
132
+ return originalAssert.call(this, condition, ...args);
133
+ };
134
+ }
135
+
136
+ window.addEventListener("error", (event) => {
137
+ emit({
138
+ kind: "console_event",
139
+ source: "page",
140
+ at: formatLocalTimestamp(new Date()),
141
+ level: "error",
142
+ text: truncateText(event.message || "window error"),
143
+ args: [
144
+ {
145
+ filename: event.filename || "",
146
+ lineno: event.lineno || 0,
147
+ colno: event.colno || 0,
148
+ },
149
+ ],
150
+ url: location.href,
151
+ title: document.title,
152
+ });
153
+ });
154
+
155
+ window.addEventListener("unhandledrejection", (event) => {
156
+ emit({
157
+ kind: "console_event",
158
+ source: "page",
159
+ at: formatLocalTimestamp(new Date()),
160
+ level: "error",
161
+ text: "Unhandled promise rejection",
162
+ args: [serializeValue(event.reason)],
163
+ url: location.href,
164
+ title: document.title,
165
+ });
166
+ });
167
+
168
+ const originalFetch = window.fetch.bind(window);
169
+ window.fetch = async (...args) => {
170
+ const startedAt = formatLocalTimestamp(new Date());
171
+ const request = new Request(...args);
172
+ const requestId = `page-fetch-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
173
+ const body = await serializeRequestBody(request);
174
+ emit({
175
+ kind: "network_request",
176
+ source: "page",
177
+ at: startedAt,
178
+ request_id: requestId,
179
+ url: request.url,
180
+ method: request.method,
181
+ resource_type: "fetch",
182
+ headers: headersToArray(request.headers),
183
+ ...body,
184
+ });
185
+
186
+ const response = await originalFetch(...args);
187
+ emit({
188
+ kind: "network_response_complete",
189
+ source: "page",
190
+ at: formatLocalTimestamp(new Date()),
191
+ request_id: requestId,
192
+ url: request.url,
193
+ method: request.method,
194
+ resource_type: "fetch",
195
+ status_code: response.status,
196
+ headers: headersToArray(response.headers),
197
+ });
198
+
199
+ try {
200
+ void response
201
+ .clone()
202
+ .text()
203
+ .then((bodyText) => {
204
+ emit({
205
+ kind: "network_response_body",
206
+ source: "page",
207
+ at: formatLocalTimestamp(new Date()),
208
+ request_id: requestId,
209
+ url: request.url,
210
+ body_text: truncateText(bodyText),
211
+ body_truncated: bodyText.length > MAX_TEXT_CHARS,
212
+ });
213
+ })
214
+ .catch(() => {
215
+ // ignore
216
+ });
217
+ } catch {
218
+ // ignore
219
+ }
220
+
221
+ return response;
222
+ };
223
+
224
+ const originalOpen = XMLHttpRequest.prototype.open;
225
+ const originalSend = XMLHttpRequest.prototype.send;
226
+ const originalSetHeader = XMLHttpRequest.prototype.setRequestHeader;
227
+ XMLHttpRequest.prototype.open = function patchedOpen(method, url, async, user, password) {
228
+ this.__tellyRecorder = {
229
+ request_id: `page-xhr-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`,
230
+ method: String(method || "GET"),
231
+ url: String(url || ""),
232
+ headers: [],
233
+ };
234
+ return originalOpen.call(this, method, url, async, user, password);
235
+ };
236
+ XMLHttpRequest.prototype.setRequestHeader = function patchedSetHeader(name, value) {
237
+ if (this.__tellyRecorder?.headers) {
238
+ this.__tellyRecorder.headers.push({ name: String(name), value: String(value) });
239
+ }
240
+ return originalSetHeader.call(this, name, value);
241
+ };
242
+ XMLHttpRequest.prototype.send = function patchedSend(body) {
243
+ const startedAt = formatLocalTimestamp(new Date());
244
+ const meta = this.__tellyRecorder || {
245
+ request_id: `page-xhr-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`,
246
+ method: "GET",
247
+ url: "",
248
+ headers: [],
249
+ };
250
+ const bodyText =
251
+ typeof body === "string"
252
+ ? body
253
+ : body instanceof URLSearchParams
254
+ ? body.toString()
255
+ : body instanceof FormData
256
+ ? Array.from(body.entries())
257
+ .map(([k, v]) => `${String(k)}=${String(v)}`)
258
+ .join("&")
259
+ : "";
260
+ emit({
261
+ kind: "network_request",
262
+ source: "page",
263
+ at: startedAt,
264
+ request_id: meta.request_id,
265
+ url: meta.url,
266
+ method: meta.method,
267
+ resource_type: "xmlhttprequest",
268
+ headers: meta.headers,
269
+ body_text: truncateText(bodyText),
270
+ body_truncated: bodyText.length > MAX_TEXT_CHARS,
271
+ });
272
+
273
+ this.addEventListener(
274
+ "loadend",
275
+ () => {
276
+ const headersRaw = this.getAllResponseHeaders() || "";
277
+ const headers = headersRaw
278
+ .split(/\r?\n/)
279
+ .map((line) => line.trim())
280
+ .filter(Boolean)
281
+ .map((line) => {
282
+ const separatorIndex = line.indexOf(":");
283
+ return separatorIndex <= 0
284
+ ? { name: line, value: "" }
285
+ : {
286
+ name: line.slice(0, separatorIndex).trim(),
287
+ value: line.slice(separatorIndex + 1).trim(),
288
+ };
289
+ });
290
+ emit({
291
+ kind: "network_response_complete",
292
+ source: "page",
293
+ at: formatLocalTimestamp(new Date()),
294
+ request_id: meta.request_id,
295
+ url: meta.url,
296
+ method: meta.method,
297
+ resource_type: "xmlhttprequest",
298
+ status_code: this.status,
299
+ headers,
300
+ });
301
+ if (typeof this.responseText === "string") {
302
+ emit({
303
+ kind: "network_response_body",
304
+ source: "page",
305
+ at: formatLocalTimestamp(new Date()),
306
+ request_id: meta.request_id,
307
+ url: meta.url,
308
+ body_text: truncateText(this.responseText),
309
+ body_truncated: this.responseText.length > MAX_TEXT_CHARS,
310
+ });
311
+ }
312
+ },
313
+ { once: true },
314
+ );
315
+
316
+ return originalSend.call(this, body);
317
+ };
318
+ })();