chrome-bridge-mcp 1.8.0
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/LICENSE +21 -0
- package/README.md +185 -0
- package/extension/console-capture.js +46 -0
- package/extension/icons/icon-128.png +0 -0
- package/extension/icons/icon-16.png +0 -0
- package/extension/icons/icon-48.png +0 -0
- package/extension/manifest.json +44 -0
- package/extension/page-instrumentation.js +115 -0
- package/extension/popup.css +128 -0
- package/extension/popup.html +64 -0
- package/extension/popup.js +142 -0
- package/extension/service-worker.js +3711 -0
- package/extension/stack-detect.js +54 -0
- package/extension/telemetry.js +29 -0
- package/install.sh +70 -0
- package/package.json +57 -0
- package/server/assertions.js +81 -0
- package/server/cli.js +380 -0
- package/server/formatters.js +35 -0
- package/server/har.js +22 -0
- package/server/index.js +107 -0
- package/server/launcher.js +97 -0
- package/server/link-checker.js +57 -0
- package/server/protocol.js +135 -0
- package/server/security-headers.js +68 -0
- package/server/stub-server.js +81 -0
- package/server/tools.js +1728 -0
- package/server/ws-manager.js +655 -0
- package/tools/measure-schema.mjs +108 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
const $ = (id) => document.getElementById(id);
|
|
2
|
+
|
|
3
|
+
const stateLabels = {
|
|
4
|
+
connected: 'Connesso',
|
|
5
|
+
connecting: 'Connessione…',
|
|
6
|
+
disconnected: 'Disconnesso',
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
function renderState(state) {
|
|
10
|
+
$('indicator').className = `dot ${state}`;
|
|
11
|
+
$('status-text').textContent = stateLabels[state] || state;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function agoLabel(ts) {
|
|
15
|
+
if (!ts) return 'ultimo';
|
|
16
|
+
const s = Math.round((Date.now() - ts) / 1000);
|
|
17
|
+
if (s < 60) return `ultimo · ${s}s fa`;
|
|
18
|
+
if (s < 3600) return `ultimo · ${Math.round(s / 60)}m fa`;
|
|
19
|
+
return `ultimo · ${Math.round(s / 3600)}h fa`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let lastData = null;
|
|
23
|
+
|
|
24
|
+
function renderPopupData(d) {
|
|
25
|
+
lastData = d;
|
|
26
|
+
renderState(d.state);
|
|
27
|
+
$('ws-url').textContent = `ws://localhost:${d.port}`;
|
|
28
|
+
$('versions').textContent = d.serverVersion
|
|
29
|
+
? `ext ${d.extensionVersion} · srv ${d.serverVersion}`
|
|
30
|
+
: `v${d.extensionVersion}`;
|
|
31
|
+
|
|
32
|
+
const st = d.stats || { toolCallCount: 0, lastTool: null, lastToolTs: null, recentErrors: [] };
|
|
33
|
+
$('st-calls').textContent = st.toolCallCount;
|
|
34
|
+
$('st-last').textContent = st.lastTool || '—';
|
|
35
|
+
$('st-last-ago').textContent = agoLabel(st.lastToolTs);
|
|
36
|
+
$('st-errors').textContent = st.recentErrors.length;
|
|
37
|
+
$('st-errors').classList.toggle('bad', st.recentErrors.length > 0);
|
|
38
|
+
|
|
39
|
+
const errList = $('err-list');
|
|
40
|
+
if (st.recentErrors.length) {
|
|
41
|
+
errList.hidden = false;
|
|
42
|
+
$('err-items').replaceChildren(...st.recentErrors.slice().reverse().map((e) => {
|
|
43
|
+
const li = document.createElement('li');
|
|
44
|
+
const tool = document.createElement('b');
|
|
45
|
+
tool.textContent = e.tool;
|
|
46
|
+
li.append(tool, ` ${new Date(e.ts).toLocaleTimeString()} — ${e.message}`);
|
|
47
|
+
return li;
|
|
48
|
+
}));
|
|
49
|
+
} else {
|
|
50
|
+
errList.hidden = true;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function renderPageInfo(info) {
|
|
55
|
+
const body = $('page-body');
|
|
56
|
+
const unavailable = $('page-unavailable');
|
|
57
|
+
if (!info || !info.available) {
|
|
58
|
+
body.hidden = true;
|
|
59
|
+
unavailable.hidden = false;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
body.hidden = false;
|
|
63
|
+
unavailable.hidden = true;
|
|
64
|
+
|
|
65
|
+
const hasInstrument = info.consoleErrors !== null;
|
|
66
|
+
$('pg-hint').hidden = hasInstrument;
|
|
67
|
+
if (hasInstrument) {
|
|
68
|
+
$('pg-errors').textContent = info.consoleErrors;
|
|
69
|
+
$('pg-errors').classList.toggle('bad', info.consoleErrors > 0);
|
|
70
|
+
$('pg-vitals').textContent = info.vitals
|
|
71
|
+
? `${info.vitals.lcp != null ? (info.vitals.lcp / 1000).toFixed(1) + 's' : '—'} · ${info.vitals.cls}`
|
|
72
|
+
: '—';
|
|
73
|
+
} else {
|
|
74
|
+
$('pg-errors').textContent = '—';
|
|
75
|
+
$('pg-vitals').textContent = '—';
|
|
76
|
+
}
|
|
77
|
+
$('pg-stack').textContent = info.stack?.length ? info.stack.join(' · ') : '—';
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// --- Caricamento iniziale ---
|
|
81
|
+
chrome.runtime.sendMessage({ type: 'getPopupData' }, (d) => { if (d) renderPopupData(d); });
|
|
82
|
+
chrome.runtime.sendMessage({ type: 'getPageInfo' }, (info) => renderPageInfo(info));
|
|
83
|
+
|
|
84
|
+
// Stato live mentre il popup è aperto
|
|
85
|
+
chrome.runtime.onMessage.addListener((msg) => {
|
|
86
|
+
if (msg.type === 'connectionState') renderState(msg.state);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// --- Warning userScripts ---
|
|
90
|
+
let userScriptsEnabled = true;
|
|
91
|
+
try {
|
|
92
|
+
chrome.userScripts.getScripts;
|
|
93
|
+
} catch {
|
|
94
|
+
userScriptsEnabled = false;
|
|
95
|
+
$('us-warning').hidden = false;
|
|
96
|
+
}
|
|
97
|
+
$('us-fix').addEventListener('click', () => {
|
|
98
|
+
chrome.tabs.create({ url: `chrome://extensions/?id=${chrome.runtime.id}` });
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// --- Azioni ---
|
|
102
|
+
$('reconnect').addEventListener('click', () => {
|
|
103
|
+
chrome.runtime.sendMessage({ type: 'reconnect' }, () => {});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
$('diagnostics').addEventListener('click', async () => {
|
|
107
|
+
const d = lastData || {};
|
|
108
|
+
const report = globalThis.__cbTelemetry.buildDiagnostics({
|
|
109
|
+
extensionVersion: d.extensionVersion || chrome.runtime.getManifest().version,
|
|
110
|
+
serverVersion: d.serverVersion || null,
|
|
111
|
+
chromeVersion: navigator.userAgent.match(/Chrome\/([\d.]+)/)?.[1] || 'unknown',
|
|
112
|
+
state: d.state || 'unknown',
|
|
113
|
+
port: d.port || null,
|
|
114
|
+
userScriptsEnabled,
|
|
115
|
+
instrument: d.instrument ?? null,
|
|
116
|
+
toolCallCount: d.stats?.toolCallCount ?? 0,
|
|
117
|
+
lastTool: d.stats?.lastTool ?? null,
|
|
118
|
+
recentErrors: d.stats?.recentErrors ?? [],
|
|
119
|
+
});
|
|
120
|
+
await navigator.clipboard.writeText(report);
|
|
121
|
+
$('diagnostics').textContent = '✓ Copiato';
|
|
122
|
+
setTimeout(() => { $('diagnostics').textContent = '⧉ Diagnostica'; }, 1500);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// --- Config (collassata dietro ⚙) ---
|
|
126
|
+
$('toggle-config').addEventListener('click', () => {
|
|
127
|
+
$('config').hidden = !$('config').hidden;
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
chrome.storage.local.get({ port: 8765, token: '', instrument: true }, (cfg) => {
|
|
131
|
+
$('port').value = cfg.port;
|
|
132
|
+
$('token').value = cfg.token;
|
|
133
|
+
$('instrument').checked = cfg.instrument;
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
$('save').addEventListener('click', () => {
|
|
137
|
+
const p = parseInt($('port').value, 10);
|
|
138
|
+
const port = (p >= 1 && p <= 65535) ? p : 8765;
|
|
139
|
+
chrome.storage.local.set({ port, token: $('token').value.trim(), instrument: $('instrument').checked });
|
|
140
|
+
$('ws-url').textContent = `ws://localhost:${port}`;
|
|
141
|
+
chrome.runtime.sendMessage({ type: 'reconnect' }, () => {});
|
|
142
|
+
});
|