@deadragdoll/tellymcp 0.0.11 → 0.0.13
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.
- package/README-ru.md +48 -0
- package/README.md +47 -0
- package/TOOLS.md +232 -3
- package/VERSION.md +2 -2
- package/dist/cli.js +109 -1
- package/dist/services/features/telegram-mcp/browser.service.js +38 -1
- package/dist/services/features/telegram-mcp/gateway-socket.service.js +10 -0
- package/dist/services/features/telegram-mcp/mcp-server.service.js +12 -0
- package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +14 -0
- package/dist/services/features/telegram-mcp/src/app/config/env.js +13 -0
- package/dist/services/features/telegram-mcp/src/entities/request/model/schema.js +151 -2
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserClickTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserDomTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserFillTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserInjectScriptTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserListAttachedInstancesTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserListTabsTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserOpenTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserPressTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserRecordingStartTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserRecordingStatusTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserRecordingStopTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserScreenshotTool.js +1 -1
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserService.js +543 -9
- package/dist/services/features/telegram-mcp/src/features/browser-attach/model/browserRecordingBundle.js +502 -0
- package/dist/services/features/telegram-mcp/src/features/browser-attach/model/firefoxAttachRegistry.js +79 -0
- package/dist/services/features/telegram-mcp/src/features/browser-attach/model/firefoxAttachServer.js +559 -0
- package/dist/services/features/telegram-mcp/src/features/browser-attach/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayHttpService.js +48 -0
- package/dist/services/features/telegram-mcp/src/shared/i18n/resources/en.js +5 -1
- package/dist/services/features/telegram-mcp/src/shared/i18n/resources/ru.js +5 -1
- package/dist/services/features/telegram-mcp/src/shared/integrations/redis/stateStore.js +56 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +37 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConsoleRegistry.js +13 -7
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportConstructorWiring.js +9 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportMenuShell.js +3 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportPayloadState.js +7 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalActions.js +231 -34
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transportTerminalRuntime.js +61 -6
- package/dist/services/features/telegram-mcp/src/shared/lib/terminalPromptDetection.js +200 -28
- package/docs/STANDALONE-ru.md +42 -6
- package/docs/STANDALONE.md +42 -6
- package/package.json +6 -3
- package/packages/chrome-attach-extension/dist/background.js +1326 -0
- package/packages/chrome-attach-extension/dist/icon.svg +6 -0
- package/packages/chrome-attach-extension/dist/manifest.json +36 -0
- package/packages/chrome-attach-extension/dist/options.html +312 -0
- package/packages/chrome-attach-extension/dist/options.js +593 -0
- package/packages/chrome-attach-extension/dist/popup.html +93 -0
- package/packages/chrome-attach-extension/dist/popup.js +79 -0
- package/packages/chrome-attach-extension/dist/recorder-content.js +83 -0
- package/packages/chrome-attach-extension/dist/recorder-page.js +266 -0
- package/packages/firefox-attach-extension/README.md +13 -0
- package/packages/firefox-attach-extension/dist/background.js +1242 -0
- package/packages/firefox-attach-extension/dist/icon.svg +6 -0
- package/packages/firefox-attach-extension/dist/manifest.json +56 -0
- package/packages/firefox-attach-extension/dist/options.html +312 -0
- package/packages/firefox-attach-extension/dist/options.js +527 -0
- package/packages/firefox-attach-extension/dist/popup.html +93 -0
- package/packages/firefox-attach-extension/dist/popup.js +64 -0
- package/packages/firefox-attach-extension/dist/recorder-content.js +77 -0
- package/packages/firefox-attach-extension/dist/recorder-page.js +302 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const browser = globalThis.browser ?? globalThis.chrome;
|
|
2
|
+
|
|
3
|
+
const DEFAULT_CONNECTION_STATUS = {
|
|
4
|
+
state: "disconnected",
|
|
5
|
+
text: "Disconnected",
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const ATTACHED_TAB_KEY = "attach_selected_tab";
|
|
9
|
+
|
|
10
|
+
function storageGet(defaults) {
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
browser.storage.local.get(defaults, (result) => {
|
|
13
|
+
const error = browser.runtime?.lastError;
|
|
14
|
+
if (error) {
|
|
15
|
+
reject(new Error(error.message));
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
resolve(result);
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function setStatus(state, text) {
|
|
24
|
+
const node = document.getElementById("connection-status");
|
|
25
|
+
if (!node) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
node.textContent = text;
|
|
29
|
+
node.style.color =
|
|
30
|
+
state === "connected"
|
|
31
|
+
? "var(--accent)"
|
|
32
|
+
: state === "connecting"
|
|
33
|
+
? "var(--warn)"
|
|
34
|
+
: "var(--soft)";
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function setText(id, text) {
|
|
38
|
+
const node = document.getElementById(id);
|
|
39
|
+
if (!node) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
node.textContent = text;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function render() {
|
|
46
|
+
const stored = await storageGet({
|
|
47
|
+
attach_connection_status: DEFAULT_CONNECTION_STATUS,
|
|
48
|
+
[ATTACHED_TAB_KEY]: null,
|
|
49
|
+
});
|
|
50
|
+
const status = stored.attach_connection_status ?? DEFAULT_CONNECTION_STATUS;
|
|
51
|
+
setStatus(status.state, status.text || DEFAULT_CONNECTION_STATUS.text);
|
|
52
|
+
setText(
|
|
53
|
+
"session",
|
|
54
|
+
`Session: ${status.session_label || status.session_id || "-"}`,
|
|
55
|
+
);
|
|
56
|
+
setText(
|
|
57
|
+
"attached-tab",
|
|
58
|
+
stored[ATTACHED_TAB_KEY]?.title
|
|
59
|
+
? `Attached: ${stored[ATTACHED_TAB_KEY].title}`
|
|
60
|
+
: "Attached: -",
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
document.getElementById("open-settings").addEventListener("click", () => {
|
|
65
|
+
void browser.tabs.create({
|
|
66
|
+
url: browser.runtime.getURL("options.html"),
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
browser.storage.onChanged.addListener((changes, areaName) => {
|
|
71
|
+
if (areaName !== "local") {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (changes.attach_connection_status || changes[ATTACHED_TAB_KEY]) {
|
|
75
|
+
void render();
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
void render();
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
(() => {
|
|
2
|
+
const browser = globalThis.browser ?? globalThis.chrome;
|
|
3
|
+
|
|
4
|
+
function sendRuntimeMessage(message) {
|
|
5
|
+
return new Promise((resolve, reject) => {
|
|
6
|
+
browser.runtime.sendMessage(message, (response) => {
|
|
7
|
+
const error = browser.runtime?.lastError;
|
|
8
|
+
if (error) {
|
|
9
|
+
reject(new Error(error.message));
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
resolve(response);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (window.__tellyRecorderContentInstalled === true) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
window.__tellyRecorderContentInstalled = true;
|
|
21
|
+
|
|
22
|
+
function emit(payload) {
|
|
23
|
+
void sendRuntimeMessage({
|
|
24
|
+
type: "telly_recording_page_event",
|
|
25
|
+
event: payload,
|
|
26
|
+
}).catch(() => {});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function snapshot(reason) {
|
|
30
|
+
emit({
|
|
31
|
+
kind: "page_snapshot",
|
|
32
|
+
source: "content",
|
|
33
|
+
reason,
|
|
34
|
+
at: new Date().toISOString(),
|
|
35
|
+
url: location.href,
|
|
36
|
+
title: document.title,
|
|
37
|
+
ready_state: document.readyState,
|
|
38
|
+
html: document.documentElement?.outerHTML || "",
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
window.addEventListener("message", (event) => {
|
|
43
|
+
if (event.source !== window) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (!event.data || event.data.__tellyRecorderPageEvent !== true) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
emit(event.data.payload);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const injection = document.createElement("script");
|
|
53
|
+
injection.src = browser.runtime.getURL("recorder-page.js");
|
|
54
|
+
injection.async = false;
|
|
55
|
+
(document.documentElement || document.head || document.body).appendChild(injection);
|
|
56
|
+
injection.addEventListener(
|
|
57
|
+
"load",
|
|
58
|
+
() => {
|
|
59
|
+
injection.remove();
|
|
60
|
+
},
|
|
61
|
+
{ once: true },
|
|
62
|
+
);
|
|
63
|
+
injection.addEventListener(
|
|
64
|
+
"error",
|
|
65
|
+
() => {
|
|
66
|
+
emit({
|
|
67
|
+
kind: "console_event",
|
|
68
|
+
source: "content",
|
|
69
|
+
level: "error",
|
|
70
|
+
text: "Failed to load recorder-page.js",
|
|
71
|
+
url: location.href,
|
|
72
|
+
title: document.title,
|
|
73
|
+
});
|
|
74
|
+
injection.remove();
|
|
75
|
+
},
|
|
76
|
+
{ once: true },
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
snapshot("recording-script-installed");
|
|
80
|
+
window.addEventListener("load", () => {
|
|
81
|
+
snapshot("window-load");
|
|
82
|
+
});
|
|
83
|
+
})();
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
(() => {
|
|
2
|
+
if (window.__tellyRecorderPageInstalled === true) {
|
|
3
|
+
return;
|
|
4
|
+
}
|
|
5
|
+
window.__tellyRecorderPageInstalled = true;
|
|
6
|
+
|
|
7
|
+
const MAX_TEXT_CHARS = 64 * 1024;
|
|
8
|
+
const truncateText = (value) => {
|
|
9
|
+
const text = String(value ?? "");
|
|
10
|
+
return text.length > MAX_TEXT_CHARS ? text.slice(0, MAX_TEXT_CHARS) : text;
|
|
11
|
+
};
|
|
12
|
+
const serializeValue = (value, depth = 0) => {
|
|
13
|
+
if (depth >= 2) return truncateText(value);
|
|
14
|
+
if (value === null || value === undefined) return value;
|
|
15
|
+
if (typeof value === "string") return truncateText(value);
|
|
16
|
+
if (typeof value === "number" || typeof value === "boolean") return value;
|
|
17
|
+
if (value instanceof Error) {
|
|
18
|
+
return {
|
|
19
|
+
name: value.name,
|
|
20
|
+
message: truncateText(value.message),
|
|
21
|
+
stack: truncateText(value.stack || ""),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if (Array.isArray(value)) {
|
|
25
|
+
return value.slice(0, 20).map((item) => serializeValue(item, depth + 1));
|
|
26
|
+
}
|
|
27
|
+
if (typeof value === "object") {
|
|
28
|
+
const output = {};
|
|
29
|
+
for (const [key, nested] of Object.entries(value).slice(0, 20)) {
|
|
30
|
+
output[key] = serializeValue(nested, depth + 1);
|
|
31
|
+
}
|
|
32
|
+
return output;
|
|
33
|
+
}
|
|
34
|
+
return truncateText(value);
|
|
35
|
+
};
|
|
36
|
+
const emit = (payload) => {
|
|
37
|
+
window.postMessage({ __tellyRecorderPageEvent: true, payload }, "*");
|
|
38
|
+
};
|
|
39
|
+
const headersToArray = (headers) => {
|
|
40
|
+
try {
|
|
41
|
+
return Array.from(headers.entries()).map(([name, value]) => ({ name, value }));
|
|
42
|
+
} catch {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const serializeRequestBody = async (request) => {
|
|
47
|
+
try {
|
|
48
|
+
const text = await request.clone().text();
|
|
49
|
+
if (!text) return { body_text: "" };
|
|
50
|
+
return {
|
|
51
|
+
body_text: truncateText(text),
|
|
52
|
+
body_truncated: text.length > MAX_TEXT_CHARS,
|
|
53
|
+
};
|
|
54
|
+
} catch {
|
|
55
|
+
return {};
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
for (const level of ["log", "info", "warn", "error", "debug"]) {
|
|
60
|
+
const original = console[level];
|
|
61
|
+
console[level] = function patchedConsole(...args) {
|
|
62
|
+
try {
|
|
63
|
+
emit({
|
|
64
|
+
kind: "console_event",
|
|
65
|
+
source: "page",
|
|
66
|
+
at: new Date().toISOString(),
|
|
67
|
+
level,
|
|
68
|
+
text: truncateText(
|
|
69
|
+
args
|
|
70
|
+
.map((item) => {
|
|
71
|
+
if (typeof item === "string") return item;
|
|
72
|
+
try {
|
|
73
|
+
return JSON.stringify(item);
|
|
74
|
+
} catch {
|
|
75
|
+
return String(item);
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
.join(" "),
|
|
79
|
+
),
|
|
80
|
+
args: args.map((item) => serializeValue(item)),
|
|
81
|
+
url: location.href,
|
|
82
|
+
title: document.title,
|
|
83
|
+
});
|
|
84
|
+
} catch {
|
|
85
|
+
// ignore
|
|
86
|
+
}
|
|
87
|
+
return original.apply(this, args);
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
window.addEventListener("error", (event) => {
|
|
92
|
+
emit({
|
|
93
|
+
kind: "console_event",
|
|
94
|
+
source: "page",
|
|
95
|
+
at: new Date().toISOString(),
|
|
96
|
+
level: "error",
|
|
97
|
+
text: truncateText(event.message || "window error"),
|
|
98
|
+
args: [
|
|
99
|
+
{
|
|
100
|
+
filename: event.filename || "",
|
|
101
|
+
lineno: event.lineno || 0,
|
|
102
|
+
colno: event.colno || 0,
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
url: location.href,
|
|
106
|
+
title: document.title,
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
window.addEventListener("unhandledrejection", (event) => {
|
|
111
|
+
emit({
|
|
112
|
+
kind: "console_event",
|
|
113
|
+
source: "page",
|
|
114
|
+
at: new Date().toISOString(),
|
|
115
|
+
level: "error",
|
|
116
|
+
text: "Unhandled promise rejection",
|
|
117
|
+
args: [serializeValue(event.reason)],
|
|
118
|
+
url: location.href,
|
|
119
|
+
title: document.title,
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
const originalFetch = window.fetch.bind(window);
|
|
124
|
+
window.fetch = async (...args) => {
|
|
125
|
+
const startedAt = new Date().toISOString();
|
|
126
|
+
const request = new Request(...args);
|
|
127
|
+
const requestId = `page-fetch-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
128
|
+
const body = await serializeRequestBody(request);
|
|
129
|
+
emit({
|
|
130
|
+
kind: "network_request",
|
|
131
|
+
source: "page",
|
|
132
|
+
at: startedAt,
|
|
133
|
+
request_id: requestId,
|
|
134
|
+
url: request.url,
|
|
135
|
+
method: request.method,
|
|
136
|
+
resource_type: "fetch",
|
|
137
|
+
headers: headersToArray(request.headers),
|
|
138
|
+
...body,
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
const response = await originalFetch(...args);
|
|
142
|
+
emit({
|
|
143
|
+
kind: "network_response_complete",
|
|
144
|
+
source: "page",
|
|
145
|
+
at: new Date().toISOString(),
|
|
146
|
+
request_id: requestId,
|
|
147
|
+
url: request.url,
|
|
148
|
+
method: request.method,
|
|
149
|
+
resource_type: "fetch",
|
|
150
|
+
status_code: response.status,
|
|
151
|
+
headers: headersToArray(response.headers),
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
const bodyText = await response.clone().text();
|
|
156
|
+
emit({
|
|
157
|
+
kind: "network_response_body",
|
|
158
|
+
source: "page",
|
|
159
|
+
at: new Date().toISOString(),
|
|
160
|
+
request_id: requestId,
|
|
161
|
+
url: request.url,
|
|
162
|
+
body_text: truncateText(bodyText),
|
|
163
|
+
body_truncated: bodyText.length > MAX_TEXT_CHARS,
|
|
164
|
+
});
|
|
165
|
+
} catch {
|
|
166
|
+
// ignore
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return response;
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const originalOpen = XMLHttpRequest.prototype.open;
|
|
173
|
+
const originalSend = XMLHttpRequest.prototype.send;
|
|
174
|
+
const originalSetHeader = XMLHttpRequest.prototype.setRequestHeader;
|
|
175
|
+
XMLHttpRequest.prototype.open = function patchedOpen(method, url, async, user, password) {
|
|
176
|
+
this.__tellyRecorder = {
|
|
177
|
+
request_id: `page-xhr-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`,
|
|
178
|
+
method: String(method || "GET"),
|
|
179
|
+
url: String(url || ""),
|
|
180
|
+
headers: [],
|
|
181
|
+
};
|
|
182
|
+
return originalOpen.call(this, method, url, async, user, password);
|
|
183
|
+
};
|
|
184
|
+
XMLHttpRequest.prototype.setRequestHeader = function patchedSetHeader(name, value) {
|
|
185
|
+
if (this.__tellyRecorder?.headers) {
|
|
186
|
+
this.__tellyRecorder.headers.push({ name: String(name), value: String(value) });
|
|
187
|
+
}
|
|
188
|
+
return originalSetHeader.call(this, name, value);
|
|
189
|
+
};
|
|
190
|
+
XMLHttpRequest.prototype.send = function patchedSend(body) {
|
|
191
|
+
const startedAt = new Date().toISOString();
|
|
192
|
+
const meta = this.__tellyRecorder || {
|
|
193
|
+
request_id: `page-xhr-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`,
|
|
194
|
+
method: "GET",
|
|
195
|
+
url: "",
|
|
196
|
+
headers: [],
|
|
197
|
+
};
|
|
198
|
+
const bodyText =
|
|
199
|
+
typeof body === "string"
|
|
200
|
+
? body
|
|
201
|
+
: body instanceof URLSearchParams
|
|
202
|
+
? body.toString()
|
|
203
|
+
: body instanceof FormData
|
|
204
|
+
? Array.from(body.entries())
|
|
205
|
+
.map(([k, v]) => `${String(k)}=${String(v)}`)
|
|
206
|
+
.join("&")
|
|
207
|
+
: "";
|
|
208
|
+
emit({
|
|
209
|
+
kind: "network_request",
|
|
210
|
+
source: "page",
|
|
211
|
+
at: startedAt,
|
|
212
|
+
request_id: meta.request_id,
|
|
213
|
+
url: meta.url,
|
|
214
|
+
method: meta.method,
|
|
215
|
+
resource_type: "xmlhttprequest",
|
|
216
|
+
headers: meta.headers,
|
|
217
|
+
body_text: truncateText(bodyText),
|
|
218
|
+
body_truncated: bodyText.length > MAX_TEXT_CHARS,
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
this.addEventListener(
|
|
222
|
+
"loadend",
|
|
223
|
+
() => {
|
|
224
|
+
const headersRaw = this.getAllResponseHeaders() || "";
|
|
225
|
+
const headers = headersRaw
|
|
226
|
+
.split(/\r?\n/)
|
|
227
|
+
.map((line) => line.trim())
|
|
228
|
+
.filter(Boolean)
|
|
229
|
+
.map((line) => {
|
|
230
|
+
const separatorIndex = line.indexOf(":");
|
|
231
|
+
return separatorIndex <= 0
|
|
232
|
+
? { name: line, value: "" }
|
|
233
|
+
: {
|
|
234
|
+
name: line.slice(0, separatorIndex).trim(),
|
|
235
|
+
value: line.slice(separatorIndex + 1).trim(),
|
|
236
|
+
};
|
|
237
|
+
});
|
|
238
|
+
emit({
|
|
239
|
+
kind: "network_response_complete",
|
|
240
|
+
source: "page",
|
|
241
|
+
at: new Date().toISOString(),
|
|
242
|
+
request_id: meta.request_id,
|
|
243
|
+
url: meta.url,
|
|
244
|
+
method: meta.method,
|
|
245
|
+
resource_type: "xmlhttprequest",
|
|
246
|
+
status_code: this.status,
|
|
247
|
+
headers,
|
|
248
|
+
});
|
|
249
|
+
if (typeof this.responseText === "string") {
|
|
250
|
+
emit({
|
|
251
|
+
kind: "network_response_body",
|
|
252
|
+
source: "page",
|
|
253
|
+
at: new Date().toISOString(),
|
|
254
|
+
request_id: meta.request_id,
|
|
255
|
+
url: meta.url,
|
|
256
|
+
body_text: truncateText(this.responseText),
|
|
257
|
+
body_truncated: this.responseText.length > MAX_TEXT_CHARS,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
{ once: true },
|
|
262
|
+
);
|
|
263
|
+
|
|
264
|
+
return originalSend.call(this, body);
|
|
265
|
+
};
|
|
266
|
+
})();
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# TellyMCP Firefox Attach Extension
|
|
2
|
+
|
|
3
|
+
Firefox extension that lets `telegram_mcp` attach to an already running user browser session through a local WebSocket bridge.
|
|
4
|
+
|
|
5
|
+
Current scope of this package:
|
|
6
|
+
|
|
7
|
+
- extension options for host / port
|
|
8
|
+
- background WebSocket client
|
|
9
|
+
- browser instance hello handshake
|
|
10
|
+
- tab listing
|
|
11
|
+
- active-tab reporting
|
|
12
|
+
|
|
13
|
+
This package is intentionally separate from the main `@deadragdoll/tellymcp` runtime package.
|