@jobshimo/browser-link 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 (106) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -0
  3. package/dist/auth/allowlist.d.ts +2 -0
  4. package/dist/auth/allowlist.js +53 -0
  5. package/dist/auth/allowlist.js.map +1 -0
  6. package/dist/auth/process-identity.d.ts +19 -0
  7. package/dist/auth/process-identity.js +106 -0
  8. package/dist/auth/process-identity.js.map +1 -0
  9. package/dist/cli.d.ts +2 -0
  10. package/dist/cli.js +116 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/commands/about.d.ts +23 -0
  13. package/dist/commands/about.js +248 -0
  14. package/dist/commands/about.js.map +1 -0
  15. package/dist/commands/doctor.d.ts +29 -0
  16. package/dist/commands/doctor.js +110 -0
  17. package/dist/commands/doctor.js.map +1 -0
  18. package/dist/commands/extension.d.ts +12 -0
  19. package/dist/commands/extension.js +76 -0
  20. package/dist/commands/extension.js.map +1 -0
  21. package/dist/commands/install.d.ts +19 -0
  22. package/dist/commands/install.js +52 -0
  23. package/dist/commands/install.js.map +1 -0
  24. package/dist/commands/menu.d.ts +26 -0
  25. package/dist/commands/menu.js +187 -0
  26. package/dist/commands/menu.js.map +1 -0
  27. package/dist/commands/tty.d.ts +51 -0
  28. package/dist/commands/tty.js +148 -0
  29. package/dist/commands/tty.js.map +1 -0
  30. package/dist/commands/uninstall.d.ts +8 -0
  31. package/dist/commands/uninstall.js +10 -0
  32. package/dist/commands/uninstall.js.map +1 -0
  33. package/dist/commands/welcome.d.ts +33 -0
  34. package/dist/commands/welcome.js +177 -0
  35. package/dist/commands/welcome.js.map +1 -0
  36. package/dist/config.d.ts +11 -0
  37. package/dist/config.js +35 -0
  38. package/dist/config.js.map +1 -0
  39. package/dist/entry-info.d.ts +12 -0
  40. package/dist/entry-info.js +15 -0
  41. package/dist/entry-info.js.map +1 -0
  42. package/dist/extension/background.d.ts +1 -0
  43. package/dist/extension/background.js +490 -0
  44. package/dist/extension/background.js.map +1 -0
  45. package/dist/extension/icons/icon-128.png +0 -0
  46. package/dist/extension/icons/icon-16.png +0 -0
  47. package/dist/extension/icons/icon-32.png +0 -0
  48. package/dist/extension/icons/icon-48.png +0 -0
  49. package/dist/extension/icons/icon.svg +14 -0
  50. package/dist/extension/manifest.json +28 -0
  51. package/dist/extension/popup.d.ts +13 -0
  52. package/dist/extension/popup.html +88 -0
  53. package/dist/extension/popup.js +78 -0
  54. package/dist/extension/popup.js.map +1 -0
  55. package/dist/index.d.ts +1 -0
  56. package/dist/index.js +6 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/installers/claude.d.ts +2 -0
  59. package/dist/installers/claude.js +77 -0
  60. package/dist/installers/claude.js.map +1 -0
  61. package/dist/installers/index.d.ts +9 -0
  62. package/dist/installers/index.js +14 -0
  63. package/dist/installers/index.js.map +1 -0
  64. package/dist/installers/opencode.d.ts +2 -0
  65. package/dist/installers/opencode.js +39 -0
  66. package/dist/installers/opencode.js.map +1 -0
  67. package/dist/installers/types.d.ts +30 -0
  68. package/dist/installers/types.js +2 -0
  69. package/dist/installers/types.js.map +1 -0
  70. package/dist/map/db.d.ts +3 -0
  71. package/dist/map/db.js +81 -0
  72. package/dist/map/db.js.map +1 -0
  73. package/dist/map/paths.d.ts +12 -0
  74. package/dist/map/paths.js +22 -0
  75. package/dist/map/paths.js.map +1 -0
  76. package/dist/map/queries.d.ts +72 -0
  77. package/dist/map/queries.js +162 -0
  78. package/dist/map/queries.js.map +1 -0
  79. package/dist/map/tools.d.ts +8 -0
  80. package/dist/map/tools.js +143 -0
  81. package/dist/map/tools.js.map +1 -0
  82. package/dist/messages.d.ts +42 -0
  83. package/dist/messages.js +9 -0
  84. package/dist/messages.js.map +1 -0
  85. package/dist/server.d.ts +6 -0
  86. package/dist/server.js +217 -0
  87. package/dist/server.js.map +1 -0
  88. package/dist/tools/browser-definitions.d.ts +7 -0
  89. package/dist/tools/browser-definitions.js +127 -0
  90. package/dist/tools/browser-definitions.js.map +1 -0
  91. package/dist/tools/browser-dispatch.d.ts +20 -0
  92. package/dist/tools/browser-dispatch.js +75 -0
  93. package/dist/tools/browser-dispatch.js.map +1 -0
  94. package/dist/tools/responses.d.ts +19 -0
  95. package/dist/tools/responses.js +27 -0
  96. package/dist/tools/responses.js.map +1 -0
  97. package/dist/tools/server-instructions.d.ts +3 -0
  98. package/dist/tools/server-instructions.js +50 -0
  99. package/dist/tools/server-instructions.js.map +1 -0
  100. package/dist/tools/types.d.ts +6 -0
  101. package/dist/tools/types.js +2 -0
  102. package/dist/tools/types.js.map +1 -0
  103. package/dist/utils/open-url.d.ts +4 -0
  104. package/dist/utils/open-url.js +37 -0
  105. package/dist/utils/open-url.js.map +1 -0
  106. package/package.json +61 -0
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Small per-user config persisted next to the map DB. Only meant for UX
3
+ * preferences (e.g. "don't show me the welcome screen every time").
4
+ * No domain data ever lives here.
5
+ */
6
+ export interface BrowserLinkConfig {
7
+ skipWelcome?: boolean;
8
+ language?: 'en' | 'es';
9
+ }
10
+ export declare function loadConfig(): BrowserLinkConfig;
11
+ export declare function saveConfig(patch: Partial<BrowserLinkConfig>): BrowserLinkConfig;
package/dist/config.js ADDED
@@ -0,0 +1,35 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { getDataDir } from './map/paths.js';
4
+ function configFile() {
5
+ return join(getDataDir(), 'config.json');
6
+ }
7
+ export function loadConfig() {
8
+ const path = configFile();
9
+ if (!existsSync(path))
10
+ return {};
11
+ try {
12
+ const raw = readFileSync(path, 'utf8');
13
+ const parsed = JSON.parse(raw);
14
+ if (parsed && typeof parsed === 'object')
15
+ return parsed;
16
+ return {};
17
+ }
18
+ catch (err) {
19
+ // Surface corruption rather than silently masking it: the file is
20
+ // small and user-owned, so a one-line stderr warning is the right
21
+ // signal. We still fall back to defaults so the CLI keeps working.
22
+ const message = err instanceof Error ? err.message : String(err);
23
+ console.warn(`[browser-link] could not read config at ${path}: ${message}. Using defaults.`);
24
+ return {};
25
+ }
26
+ }
27
+ export function saveConfig(patch) {
28
+ const path = configFile();
29
+ mkdirSync(dirname(path), { recursive: true });
30
+ const current = loadConfig();
31
+ const next = { ...current, ...patch };
32
+ writeFileSync(path, JSON.stringify(next, null, 2) + '\n', 'utf8');
33
+ return next;
34
+ }
35
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAY5C,SAAS,UAAU;IACjB,OAAO,IAAI,CAAC,UAAU,EAAE,EAAE,aAAa,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;IAC1B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;QAC1C,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,OAAO,MAA2B,CAAC;QAC7E,OAAO,EAAE,CAAC;IACZ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,kEAAkE;QAClE,kEAAkE;QAClE,mEAAmE;QACnE,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO,CAAC,IAAI,CAAC,2CAA2C,IAAI,KAAK,OAAO,mBAAmB,CAAC,CAAC;QAC7F,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAiC;IAC1D,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;IAC1B,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAsB,EAAE,GAAG,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC;IACzD,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;IAClE,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Absolute filesystem path of the MCP server entry file (`dist/index.js`
3
+ * after build).
4
+ *
5
+ * Resolved relative to *this* module's own location at runtime, so the
6
+ * value is correct regardless of where the package is installed and
7
+ * regardless of where in the dist tree future refactors place individual
8
+ * commands. The only assumption is that `entry-info.js` and `index.js`
9
+ * ship as siblings under `dist/` — they live next to each other in `src/`
10
+ * and `tsc` preserves that relationship.
11
+ */
12
+ export declare const SERVER_ENTRY_PATH: string;
@@ -0,0 +1,15 @@
1
+ import { fileURLToPath } from 'node:url';
2
+ import { dirname, join } from 'node:path';
3
+ /**
4
+ * Absolute filesystem path of the MCP server entry file (`dist/index.js`
5
+ * after build).
6
+ *
7
+ * Resolved relative to *this* module's own location at runtime, so the
8
+ * value is correct regardless of where the package is installed and
9
+ * regardless of where in the dist tree future refactors place individual
10
+ * commands. The only assumption is that `entry-info.js` and `index.js`
11
+ * ship as siblings under `dist/` — they live next to each other in `src/`
12
+ * and `tsc` preserves that relationship.
13
+ */
14
+ export const SERVER_ENTRY_PATH = join(dirname(fileURLToPath(import.meta.url)), 'index.js');
15
+ //# sourceMappingURL=entry-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entry-info.js","sourceRoot":"","sources":["../src/entry-info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,490 @@
1
+ const WS_URL = 'ws://127.0.0.1:17529';
2
+ const CDP_VERSION = '1.3';
3
+ const CONSOLE_BUFFER_MAX = 200;
4
+ const NETWORK_BUFFER_MAX = 200;
5
+ const tabStates = new Map();
6
+ function send(ws, msg) {
7
+ ws.send(JSON.stringify(msg));
8
+ }
9
+ function safeParse(raw) {
10
+ try {
11
+ return JSON.parse(raw);
12
+ }
13
+ catch {
14
+ return null;
15
+ }
16
+ }
17
+ function cdp(tabId, method, params = {}) {
18
+ return chrome.debugger.sendCommand({ tabId }, method, params);
19
+ }
20
+ function pushConsole(state, entry) {
21
+ state.consoleBuffer.push(entry);
22
+ if (state.consoleBuffer.length > CONSOLE_BUFFER_MAX) {
23
+ state.consoleBuffer.shift();
24
+ }
25
+ }
26
+ function ensureNetworkEntry(state, requestId) {
27
+ let entry = state.networkBuffer.get(requestId);
28
+ if (!entry) {
29
+ entry = { request_id: requestId, url: '', method: '', started_at: Date.now() };
30
+ state.networkBuffer.set(requestId, entry);
31
+ state.networkOrder.push(requestId);
32
+ while (state.networkOrder.length > NETWORK_BUFFER_MAX) {
33
+ const oldId = state.networkOrder.shift();
34
+ state.networkBuffer.delete(oldId);
35
+ }
36
+ }
37
+ return entry;
38
+ }
39
+ function attachDebuggerListener(state) {
40
+ const listener = (method, params) => {
41
+ const p = params;
42
+ if (method === 'Runtime.consoleAPICalled') {
43
+ const args = (p.args ?? []);
44
+ const text = args
45
+ .map((a) => (a.value !== undefined ? String(a.value) : (a.description ?? '')))
46
+ .join(' ');
47
+ pushConsole(state, {
48
+ timestamp: p.timestamp ?? Date.now(),
49
+ level: p.type ?? 'log',
50
+ text,
51
+ source: 'console',
52
+ });
53
+ return;
54
+ }
55
+ if (method === 'Log.entryAdded') {
56
+ const e = p.entry;
57
+ pushConsole(state, {
58
+ timestamp: e.timestamp ?? Date.now(),
59
+ level: e.level ?? 'log',
60
+ text: e.text ?? '',
61
+ source: 'log',
62
+ url: e.url,
63
+ line: e.lineNumber,
64
+ });
65
+ return;
66
+ }
67
+ if (method === 'Network.requestWillBeSent') {
68
+ const entry = ensureNetworkEntry(state, p.requestId);
69
+ entry.url = p.request?.url ?? entry.url;
70
+ entry.method = p.request?.method ?? entry.method;
71
+ entry.resource_type = p.type ?? entry.resource_type;
72
+ entry.request_headers = p.request?.headers ?? entry.request_headers;
73
+ entry.request_post_data = p.request?.postData ?? entry.request_post_data;
74
+ return;
75
+ }
76
+ if (method === 'Network.responseReceived') {
77
+ const entry = ensureNetworkEntry(state, p.requestId);
78
+ entry.status = p.response?.status;
79
+ entry.status_text = p.response?.statusText;
80
+ entry.mime_type = p.response?.mimeType;
81
+ entry.response_headers = p.response?.headers;
82
+ return;
83
+ }
84
+ if (method === 'Network.loadingFinished') {
85
+ const entry = ensureNetworkEntry(state, p.requestId);
86
+ entry.finished_at = Date.now();
87
+ entry.encoded_data_length = p.encodedDataLength;
88
+ return;
89
+ }
90
+ if (method === 'Network.loadingFailed') {
91
+ const entry = ensureNetworkEntry(state, p.requestId);
92
+ entry.finished_at = Date.now();
93
+ entry.failed = p.errorText ?? 'failed';
94
+ return;
95
+ }
96
+ };
97
+ state.debuggerListener = listener;
98
+ }
99
+ const SNAPSHOT_JS = `
100
+ (() => {
101
+ function isVisible(el) {
102
+ if (!(el instanceof HTMLElement)) return true;
103
+ const style = getComputedStyle(el);
104
+ if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') return false;
105
+ if (el.offsetParent === null && style.position !== 'fixed') return false;
106
+ return true;
107
+ }
108
+ function shortText(el) {
109
+ const t = (el.innerText || el.textContent || '').trim();
110
+ return t.length > 120 ? t.slice(0, 120) + '...' : t;
111
+ }
112
+ function safeCss(s) {
113
+ return s.replace(/"/g, '\\\\"');
114
+ }
115
+ function genSelector(el) {
116
+ if (el.id && !/^[\\d]/.test(el.id) && !/\\s/.test(el.id)) {
117
+ try { if (document.querySelectorAll('#' + CSS.escape(el.id)).length === 1) return '#' + CSS.escape(el.id); } catch (_) {}
118
+ }
119
+ const tid = el.getAttribute('data-testid');
120
+ if (tid) return '[data-testid="' + safeCss(tid) + '"]';
121
+ const al = el.getAttribute('aria-label');
122
+ if (al && al.length < 60) return el.tagName.toLowerCase() + '[aria-label="' + safeCss(al) + '"]';
123
+ const name = el.getAttribute('name');
124
+ if (name && (el.tagName === 'INPUT' || el.tagName === 'SELECT' || el.tagName === 'TEXTAREA')) {
125
+ return el.tagName.toLowerCase() + '[name="' + safeCss(name) + '"]';
126
+ }
127
+ const parts = [];
128
+ let cur = el;
129
+ while (cur && cur.nodeType === 1 && cur !== document.body && parts.length < 6) {
130
+ let part = cur.tagName.toLowerCase();
131
+ const parent = cur.parentElement;
132
+ if (parent) {
133
+ const sib = Array.from(parent.children).filter(s => s.tagName === cur.tagName);
134
+ if (sib.length > 1) {
135
+ part += ':nth-of-type(' + (sib.indexOf(cur) + 1) + ')';
136
+ }
137
+ }
138
+ parts.unshift(part);
139
+ cur = parent;
140
+ }
141
+ return parts.join(' > ');
142
+ }
143
+ const sel = 'a[href], button, input, select, textarea, [role=button], [role=link], [role=checkbox], [role=tab], [role=menuitem], [contenteditable=true]';
144
+ const interactive = [];
145
+ document.querySelectorAll(sel).forEach((el) => {
146
+ if (!isVisible(el)) return;
147
+ interactive.push({
148
+ tag: el.tagName.toLowerCase(),
149
+ role: el.getAttribute('role') || el.tagName.toLowerCase(),
150
+ text: shortText(el),
151
+ value: 'value' in el ? (el.value || '') : '',
152
+ placeholder: el.getAttribute('placeholder') || '',
153
+ aria_label: el.getAttribute('aria-label') || '',
154
+ name: el.getAttribute('name') || '',
155
+ type: el.getAttribute('type') || '',
156
+ href: el.getAttribute('href') || '',
157
+ disabled: 'disabled' in el ? !!el.disabled : false,
158
+ selector: genSelector(el),
159
+ });
160
+ });
161
+ const headings = [];
162
+ document.querySelectorAll('h1, h2, h3').forEach((h) => {
163
+ if (!isVisible(h)) return;
164
+ headings.push({ level: h.tagName, text: shortText(h) });
165
+ });
166
+ const visibleText = (document.body && document.body.innerText) ? document.body.innerText.slice(0, 4000) : '';
167
+ return {
168
+ title: document.title,
169
+ url: location.href,
170
+ headings: headings.slice(0, 30),
171
+ text: visibleText,
172
+ interactive: interactive.slice(0, 120),
173
+ };
174
+ })()
175
+ `;
176
+ async function evaluateInTab(tabId, expression) {
177
+ const result = (await cdp(tabId, 'Runtime.evaluate', {
178
+ expression,
179
+ returnByValue: true,
180
+ awaitPromise: true,
181
+ userGesture: true,
182
+ }));
183
+ if (result.exceptionDetails) {
184
+ const ex = result.exceptionDetails;
185
+ throw new Error(ex.exception?.description ?? ex.text ?? 'Evaluation failed');
186
+ }
187
+ return result.result.value;
188
+ }
189
+ async function waitForLoad(tabId, timeoutMs = 20_000) {
190
+ return new Promise((resolve, reject) => {
191
+ const t = setTimeout(() => {
192
+ chrome.tabs.onUpdated.removeListener(handler);
193
+ reject(new Error('navigation timed out'));
194
+ }, timeoutMs);
195
+ const handler = (updatedId, info) => {
196
+ if (updatedId === tabId && info.status === 'complete') {
197
+ clearTimeout(t);
198
+ chrome.tabs.onUpdated.removeListener(handler);
199
+ resolve();
200
+ }
201
+ };
202
+ chrome.tabs.onUpdated.addListener(handler);
203
+ });
204
+ }
205
+ async function handleTool(state, msg) {
206
+ const tabId = state.tabId;
207
+ const p = (msg.params ?? {});
208
+ try {
209
+ switch (msg.tool) {
210
+ case 'ping': {
211
+ const tab = await chrome.tabs.get(tabId);
212
+ return {
213
+ kind: 'tool.response',
214
+ id: msg.id,
215
+ ok: true,
216
+ result: { title: tab.title ?? '', url: tab.url ?? '' },
217
+ };
218
+ }
219
+ case 'navigate': {
220
+ const url = String(p.url);
221
+ const waitForLoadFlag = p.wait_for_load !== false;
222
+ await cdp(tabId, 'Page.navigate', { url });
223
+ if (waitForLoadFlag)
224
+ await waitForLoad(tabId);
225
+ const tab = await chrome.tabs.get(tabId);
226
+ return {
227
+ kind: 'tool.response',
228
+ id: msg.id,
229
+ ok: true,
230
+ result: { url: tab.url ?? '', title: tab.title ?? '' },
231
+ };
232
+ }
233
+ case 'snapshot': {
234
+ const value = await evaluateInTab(tabId, SNAPSHOT_JS);
235
+ return { kind: 'tool.response', id: msg.id, ok: true, result: value };
236
+ }
237
+ case 'console': {
238
+ const level = p.level;
239
+ const entries = level
240
+ ? state.consoleBuffer.filter((e) => e.level === level)
241
+ : state.consoleBuffer;
242
+ return { kind: 'tool.response', id: msg.id, ok: true, result: entries };
243
+ }
244
+ case 'network': {
245
+ const filter = p.url_filter?.toLowerCase();
246
+ const list = state.networkOrder
247
+ .map((id) => state.networkBuffer.get(id))
248
+ .filter((e) => (filter ? e.url.toLowerCase().includes(filter) : true));
249
+ return { kind: 'tool.response', id: msg.id, ok: true, result: list };
250
+ }
251
+ case 'network_body': {
252
+ const requestId = String(p.request_id);
253
+ const body = (await cdp(tabId, 'Network.getResponseBody', { requestId }));
254
+ return { kind: 'tool.response', id: msg.id, ok: true, result: body };
255
+ }
256
+ case 'click': {
257
+ const selector = String(p.selector);
258
+ const expr = `
259
+ (() => {
260
+ const el = document.querySelector(${JSON.stringify(selector)});
261
+ if (!el) return null;
262
+ el.scrollIntoView({ block: 'center', inline: 'center' });
263
+ const r = el.getBoundingClientRect();
264
+ return { x: r.left + r.width / 2, y: r.top + r.height / 2, tag: el.tagName.toLowerCase() };
265
+ })()`;
266
+ const coords = (await evaluateInTab(tabId, expr));
267
+ if (!coords) {
268
+ return {
269
+ kind: 'tool.response',
270
+ id: msg.id,
271
+ ok: false,
272
+ error: `Element not found: ${selector}`,
273
+ };
274
+ }
275
+ await cdp(tabId, 'Input.dispatchMouseEvent', {
276
+ type: 'mouseMoved',
277
+ x: coords.x,
278
+ y: coords.y,
279
+ });
280
+ await cdp(tabId, 'Input.dispatchMouseEvent', {
281
+ type: 'mousePressed',
282
+ x: coords.x,
283
+ y: coords.y,
284
+ button: 'left',
285
+ clickCount: 1,
286
+ });
287
+ await cdp(tabId, 'Input.dispatchMouseEvent', {
288
+ type: 'mouseReleased',
289
+ x: coords.x,
290
+ y: coords.y,
291
+ button: 'left',
292
+ clickCount: 1,
293
+ });
294
+ return {
295
+ kind: 'tool.response',
296
+ id: msg.id,
297
+ ok: true,
298
+ result: { clicked: selector, tag: coords.tag },
299
+ };
300
+ }
301
+ case 'type': {
302
+ const selector = String(p.selector);
303
+ const text = String(p.text);
304
+ const clear = !!p.clear;
305
+ const focusExpr = `
306
+ (() => {
307
+ const el = document.querySelector(${JSON.stringify(selector)});
308
+ if (!el) return false;
309
+ el.focus();
310
+ ${clear ? "if ('value' in el) { el.value = ''; el.dispatchEvent(new Event('input', { bubbles: true })); }" : ''}
311
+ return true;
312
+ })()`;
313
+ const focused = await evaluateInTab(tabId, focusExpr);
314
+ if (!focused) {
315
+ return {
316
+ kind: 'tool.response',
317
+ id: msg.id,
318
+ ok: false,
319
+ error: `Element not found: ${selector}`,
320
+ };
321
+ }
322
+ await cdp(tabId, 'Input.insertText', { text });
323
+ return {
324
+ kind: 'tool.response',
325
+ id: msg.id,
326
+ ok: true,
327
+ result: { typed: text.length, selector },
328
+ };
329
+ }
330
+ case 'evaluate': {
331
+ const expression = String(p.expression);
332
+ const value = await evaluateInTab(tabId, expression);
333
+ return { kind: 'tool.response', id: msg.id, ok: true, result: value };
334
+ }
335
+ default:
336
+ return { kind: 'tool.response', id: msg.id, ok: false, error: `Unknown tool: ${msg.tool}` };
337
+ }
338
+ }
339
+ catch (err) {
340
+ return {
341
+ kind: 'tool.response',
342
+ id: msg.id,
343
+ ok: false,
344
+ error: err instanceof Error ? err.message : String(err),
345
+ };
346
+ }
347
+ }
348
+ async function cleanup(tabId) {
349
+ const state = tabStates.get(tabId);
350
+ if (!state)
351
+ return;
352
+ if (state.ws && state.ws.readyState !== WebSocket.CLOSED) {
353
+ try {
354
+ state.ws.close();
355
+ }
356
+ catch { }
357
+ }
358
+ if (state.debuggerAttached) {
359
+ try {
360
+ await chrome.debugger.detach({ tabId });
361
+ }
362
+ catch { }
363
+ }
364
+ tabStates.delete(tabId);
365
+ }
366
+ chrome.debugger.onEvent.addListener((source, method, params) => {
367
+ if (source.tabId === undefined)
368
+ return;
369
+ const state = tabStates.get(source.tabId);
370
+ if (!state?.debuggerListener)
371
+ return;
372
+ state.debuggerListener(method, params);
373
+ });
374
+ async function connectTab(tabId) {
375
+ if (tabStates.has(tabId)) {
376
+ return { ok: false, error: 'Esta pestaña ya está conectada' };
377
+ }
378
+ const tab = await chrome.tabs.get(tabId);
379
+ if (!tab.url || !tab.title) {
380
+ return { ok: false, error: 'La pestaña no tiene URL o título' };
381
+ }
382
+ try {
383
+ await chrome.debugger.attach({ tabId }, CDP_VERSION);
384
+ }
385
+ catch (err) {
386
+ return {
387
+ ok: false,
388
+ error: `No se pudo attachar el debugger: ${err instanceof Error ? err.message : String(err)}`,
389
+ };
390
+ }
391
+ const state = {
392
+ tabId,
393
+ debuggerAttached: true,
394
+ consoleBuffer: [],
395
+ networkBuffer: new Map(),
396
+ networkOrder: [],
397
+ };
398
+ tabStates.set(tabId, state);
399
+ attachDebuggerListener(state);
400
+ try {
401
+ await cdp(tabId, 'Page.enable');
402
+ await cdp(tabId, 'Runtime.enable');
403
+ await cdp(tabId, 'Log.enable');
404
+ await cdp(tabId, 'Network.enable');
405
+ await cdp(tabId, 'DOM.enable');
406
+ }
407
+ catch (err) {
408
+ await cleanup(tabId);
409
+ return {
410
+ ok: false,
411
+ error: `No se pudo habilitar CDP: ${err instanceof Error ? err.message : String(err)}`,
412
+ };
413
+ }
414
+ const ws = new WebSocket(WS_URL);
415
+ state.ws = ws;
416
+ return new Promise((resolve) => {
417
+ let settled = false;
418
+ const settle = (result) => {
419
+ if (settled)
420
+ return;
421
+ settled = true;
422
+ resolve(result);
423
+ };
424
+ ws.addEventListener('open', () => {
425
+ send(ws, { kind: 'tab.register', payload: { url: tab.url, title: tab.title } });
426
+ });
427
+ ws.addEventListener('message', async (ev) => {
428
+ const msg = safeParse(typeof ev.data === 'string' ? ev.data : '');
429
+ if (!msg)
430
+ return;
431
+ if (msg.kind === 'tab.registered') {
432
+ state.serverTabId = msg.payload.tabId;
433
+ settle({ ok: true, serverTabId: msg.payload.tabId });
434
+ return;
435
+ }
436
+ if (msg.kind === 'tool.request') {
437
+ const response = await handleTool(state, msg);
438
+ if (ws.readyState === WebSocket.OPEN)
439
+ send(ws, response);
440
+ }
441
+ });
442
+ ws.addEventListener('error', () => {
443
+ cleanup(tabId).catch(() => { });
444
+ settle({ ok: false, error: 'WebSocket connection failed. ¿Está corriendo el servidor MCP?' });
445
+ });
446
+ ws.addEventListener('close', () => {
447
+ cleanup(tabId).catch(() => { });
448
+ settle({ ok: false, error: 'WebSocket closed before registration' });
449
+ });
450
+ });
451
+ }
452
+ async function disconnectTab(tabId) {
453
+ await cleanup(tabId);
454
+ return { ok: true };
455
+ }
456
+ function getTabStatus(tabId) {
457
+ const state = tabStates.get(tabId);
458
+ if (!state)
459
+ return { connected: false };
460
+ return { connected: true, serverTabId: state.serverTabId };
461
+ }
462
+ chrome.runtime.onMessage.addListener((msg, _sender, sendResponse) => {
463
+ if (msg?.action === 'connect' && typeof msg.tabId === 'number') {
464
+ connectTab(msg.tabId).then(sendResponse);
465
+ return true;
466
+ }
467
+ if (msg?.action === 'disconnect' && typeof msg.tabId === 'number') {
468
+ disconnectTab(msg.tabId).then(sendResponse);
469
+ return true;
470
+ }
471
+ if (msg?.action === 'status' && typeof msg.tabId === 'number') {
472
+ sendResponse(getTabStatus(msg.tabId));
473
+ return false;
474
+ }
475
+ return false;
476
+ });
477
+ chrome.tabs.onRemoved.addListener((tabId) => {
478
+ cleanup(tabId).catch(() => { });
479
+ });
480
+ chrome.debugger.onDetach.addListener((source) => {
481
+ if (source.tabId === undefined)
482
+ return;
483
+ const state = tabStates.get(source.tabId);
484
+ if (!state)
485
+ return;
486
+ state.debuggerAttached = false;
487
+ cleanup(source.tabId).catch(() => { });
488
+ });
489
+ export {};
490
+ //# sourceMappingURL=background.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"background.js","sourceRoot":"","sources":["../src/background.ts"],"names":[],"mappings":"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"}
Binary file
Binary file
Binary file
@@ -0,0 +1,14 @@
1
+ <svg viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
2
+ <defs>
3
+ <linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
4
+ <stop offset="0%" stop-color="#3b82f6" />
5
+ <stop offset="100%" stop-color="#1d4ed8" />
6
+ </linearGradient>
7
+ </defs>
8
+ <rect width="128" height="128" rx="26" fill="url(#bg)" />
9
+ <g fill="none" stroke="#ffffff" stroke-width="11" stroke-linecap="round" stroke-linejoin="round">
10
+ <path d="M52 78 L36 78 A22 22 0 0 1 36 34 L52 34" />
11
+ <path d="M76 34 L92 34 A22 22 0 0 1 92 78 L76 78" />
12
+ <line x1="44" y1="56" x2="84" y2="56" />
13
+ </g>
14
+ </svg>
@@ -0,0 +1,28 @@
1
+ {
2
+ "manifest_version": 3,
3
+ "name": "browser-link",
4
+ "version": "0.0.1",
5
+ "description": "Bridge between Chrome and an MCP client (Claude Code). Per-tab manual activation.",
6
+ "permissions": ["debugger", "activeTab", "storage", "tabs"],
7
+ "host_permissions": [],
8
+ "icons": {
9
+ "16": "icons/icon-16.png",
10
+ "32": "icons/icon-32.png",
11
+ "48": "icons/icon-48.png",
12
+ "128": "icons/icon-128.png"
13
+ },
14
+ "background": {
15
+ "service_worker": "background.js",
16
+ "type": "module"
17
+ },
18
+ "action": {
19
+ "default_popup": "popup.html",
20
+ "default_title": "browser-link",
21
+ "default_icon": {
22
+ "16": "icons/icon-16.png",
23
+ "32": "icons/icon-32.png",
24
+ "48": "icons/icon-48.png",
25
+ "128": "icons/icon-128.png"
26
+ }
27
+ }
28
+ }