ghost-bridge 0.6.0 → 0.6.2
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.md +8 -0
- package/dist/server.js +2 -2
- package/extension/background.js +90 -15
- package/extension/manifest.json +1 -1
- package/package.json +1 -4
package/README.md
CHANGED
|
@@ -18,6 +18,10 @@ Most browser-capable AI tools start a separate browser. Ghost Bridge connects AI
|
|
|
18
18
|
- Click, type, scroll, and submit forms on the current page
|
|
19
19
|
- Share one Chrome transport across multiple MCP clients
|
|
20
20
|
|
|
21
|
+
## What's New in 0.6.1
|
|
22
|
+
|
|
23
|
+
- `list_network_requests` and `get_network_detail` now summarize `data:` URLs and oversized URLs so inline images and long query strings do not overwhelm model context
|
|
24
|
+
|
|
21
25
|
## What's New in 0.6.0
|
|
22
26
|
|
|
23
27
|
- `inspect_page` now collects structured page data and interactive elements in one browser-side snapshot, reducing duplicate DOM scans and cutting one round-trip from the hot path
|
|
@@ -117,6 +121,10 @@ Recommended flow:
|
|
|
117
121
|
3. Use `get_page_content` for DOM or text extraction
|
|
118
122
|
4. Use `get_interactive_snapshot` before `dispatch_action`
|
|
119
123
|
|
|
124
|
+
Notes:
|
|
125
|
+
|
|
126
|
+
- `list_network_requests` and `get_network_detail` automatically summarize `data:` URLs and very long URLs so inline images or oversized query strings do not overwhelm model context
|
|
127
|
+
|
|
120
128
|
## Configuration
|
|
121
129
|
|
|
122
130
|
| Setting | Default | Notes |
|
package/dist/server.js
CHANGED
|
@@ -29024,7 +29024,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
29024
29024
|
},
|
|
29025
29025
|
{
|
|
29026
29026
|
name: "list_network_requests",
|
|
29027
|
-
description: "\u5217\u51FA\u6355\u83B7\u7684\u7F51\u7EDC\u8BF7\u6C42\uFF0C\u652F\u6301\u6309 URL\u3001\u65B9\u6CD5\u3001\u72B6\u6001\u3001\u7C7B\u578B\u8FC7\u6EE4\u3002\u9ED8\u8BA4\u6309\u6392\u969C\u4F18\u5148\u7EA7\u6392\u5E8F\uFF1A\u5931\u8D25\u8BF7\u6C42\u3001\u8FDB\u884C\u4E2D\u8BF7\u6C42\u3001XHR/Fetch \u4F1A\u4F18\u5148\u5C55\u793A\u3002",
|
|
29027
|
+
description: "\u5217\u51FA\u6355\u83B7\u7684\u7F51\u7EDC\u8BF7\u6C42\uFF0C\u652F\u6301\u6309 URL\u3001\u65B9\u6CD5\u3001\u72B6\u6001\u3001\u7C7B\u578B\u8FC7\u6EE4\u3002\u9ED8\u8BA4\u6309\u6392\u969C\u4F18\u5148\u7EA7\u6392\u5E8F\uFF1A\u5931\u8D25\u8BF7\u6C42\u3001\u8FDB\u884C\u4E2D\u8BF7\u6C42\u3001XHR/Fetch \u4F1A\u4F18\u5148\u5C55\u793A\u3002\u4E3A\u907F\u514D\u4E0A\u4E0B\u6587\u81A8\u80C0\uFF0Cdata URL \u548C\u8D85\u957F URL \u4F1A\u81EA\u52A8\u6458\u8981\u5316\u3002",
|
|
29028
29028
|
inputSchema: {
|
|
29029
29029
|
type: "object",
|
|
29030
29030
|
properties: {
|
|
@@ -29043,7 +29043,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
29043
29043
|
},
|
|
29044
29044
|
{
|
|
29045
29045
|
name: "get_network_detail",
|
|
29046
|
-
description: "\u83B7\u53D6\u5355\u4E2A\u7F51\u7EDC\u8BF7\u6C42\u7684\u8BE6\u7EC6\u4FE1\u606F\uFF0C\u5305\u62EC\u8BF7\u6C42\u5934\u3001\u54CD\u5E94\u5934\uFF0C\u53EF\u9009\u83B7\u53D6\u54CD\u5E94\u4F53",
|
|
29046
|
+
description: "\u83B7\u53D6\u5355\u4E2A\u7F51\u7EDC\u8BF7\u6C42\u7684\u8BE6\u7EC6\u4FE1\u606F\uFF0C\u5305\u62EC\u8BF7\u6C42\u5934\u3001\u54CD\u5E94\u5934\uFF0C\u53EF\u9009\u83B7\u53D6\u54CD\u5E94\u4F53\u3002\u4E3A\u907F\u514D\u4E0A\u4E0B\u6587\u81A8\u80C0\uFF0Cdata URL \u548C\u8D85\u957F URL \u4F1A\u81EA\u52A8\u6458\u8981\u5316\u3002",
|
|
29047
29047
|
inputSchema: {
|
|
29048
29048
|
type: "object",
|
|
29049
29049
|
properties: {
|
package/extension/background.js
CHANGED
|
@@ -315,6 +315,81 @@ function compareNetworkEntries(a, b, mode = 'debug') {
|
|
|
315
315
|
return (b.timestamp || 0) - (a.timestamp || 0)
|
|
316
316
|
}
|
|
317
317
|
|
|
318
|
+
const MAX_NETWORK_URL_OUTPUT_LENGTH = 240
|
|
319
|
+
const NETWORK_URL_HEAD_LENGTH = 180
|
|
320
|
+
const NETWORK_URL_TAIL_LENGTH = 40
|
|
321
|
+
const MAX_DATA_URL_OUTPUT_LENGTH = 256
|
|
322
|
+
|
|
323
|
+
function summarizeNetworkUrl(url) {
|
|
324
|
+
if (!url) return { displayUrl: url }
|
|
325
|
+
|
|
326
|
+
const urlOriginalLength = url.length
|
|
327
|
+
const schemeMatch = /^([a-z][a-z0-9+.-]*):/i.exec(url)
|
|
328
|
+
const urlScheme = schemeMatch?.[1]?.toLowerCase()
|
|
329
|
+
|
|
330
|
+
if (urlScheme === 'data') {
|
|
331
|
+
const commaIndex = url.indexOf(',')
|
|
332
|
+
const meta = commaIndex >= 0 ? url.slice(5, commaIndex) : url.slice(5)
|
|
333
|
+
const dataUrlMimeType = (meta.split(';')[0] || 'text/plain').toLowerCase()
|
|
334
|
+
const isBase64 = meta.includes(';base64')
|
|
335
|
+
|
|
336
|
+
if (!isBase64 && urlOriginalLength <= MAX_DATA_URL_OUTPUT_LENGTH) {
|
|
337
|
+
return {
|
|
338
|
+
displayUrl: url,
|
|
339
|
+
urlOriginalLength,
|
|
340
|
+
urlScheme,
|
|
341
|
+
urlTruncated: false,
|
|
342
|
+
dataUrlMimeType,
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
return {
|
|
347
|
+
displayUrl: `data:${dataUrlMimeType}${isBase64 ? ';base64' : ''},<omitted ${urlOriginalLength} chars>`,
|
|
348
|
+
urlOriginalLength,
|
|
349
|
+
urlScheme,
|
|
350
|
+
urlTruncated: true,
|
|
351
|
+
dataUrlMimeType,
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if (urlOriginalLength > MAX_NETWORK_URL_OUTPUT_LENGTH) {
|
|
356
|
+
return {
|
|
357
|
+
displayUrl: `${url.slice(0, NETWORK_URL_HEAD_LENGTH)}...${url.slice(-NETWORK_URL_TAIL_LENGTH)}`,
|
|
358
|
+
urlOriginalLength,
|
|
359
|
+
urlScheme,
|
|
360
|
+
urlTruncated: true,
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return {
|
|
365
|
+
displayUrl: url,
|
|
366
|
+
urlOriginalLength,
|
|
367
|
+
urlScheme,
|
|
368
|
+
urlTruncated: false,
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function buildNetworkRequestSummary(entry) {
|
|
373
|
+
const urlMeta = summarizeNetworkUrl(entry.url)
|
|
374
|
+
return {
|
|
375
|
+
requestId: entry.requestId,
|
|
376
|
+
url: urlMeta.displayUrl,
|
|
377
|
+
...(urlMeta.urlTruncated ? { urlTruncated: true, urlOriginalLength: urlMeta.urlOriginalLength } : {}),
|
|
378
|
+
...(urlMeta.urlScheme ? { urlScheme: urlMeta.urlScheme } : {}),
|
|
379
|
+
...(urlMeta.dataUrlMimeType ? { dataUrlMimeType: urlMeta.dataUrlMimeType } : {}),
|
|
380
|
+
method: entry.method,
|
|
381
|
+
status: entry.status,
|
|
382
|
+
statusCode: entry.statusCode,
|
|
383
|
+
resourceType: entry.resourceType,
|
|
384
|
+
mimeType: entry.mimeType,
|
|
385
|
+
duration: entry.duration,
|
|
386
|
+
encodedDataLength: entry.encodedDataLength,
|
|
387
|
+
fromCache: entry.fromCache,
|
|
388
|
+
timestamp: entry.timestamp,
|
|
389
|
+
errorText: entry.errorText,
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
318
393
|
function trimNetworkRequests() {
|
|
319
394
|
while (networkRequests.length > CONFIG.maxRequestsTracked) {
|
|
320
395
|
let worstIndex = 0
|
|
@@ -677,20 +752,7 @@ async function handleListNetworkRequests(params = {}) {
|
|
|
677
752
|
total: networkRequests.length + requestMap.size,
|
|
678
753
|
filtered: results.length,
|
|
679
754
|
priorityMode,
|
|
680
|
-
requests: results.map(
|
|
681
|
-
requestId: r.requestId,
|
|
682
|
-
url: r.url,
|
|
683
|
-
method: r.method,
|
|
684
|
-
status: r.status,
|
|
685
|
-
statusCode: r.statusCode,
|
|
686
|
-
resourceType: r.resourceType,
|
|
687
|
-
mimeType: r.mimeType,
|
|
688
|
-
duration: r.duration,
|
|
689
|
-
encodedDataLength: r.encodedDataLength,
|
|
690
|
-
fromCache: r.fromCache,
|
|
691
|
-
timestamp: r.timestamp,
|
|
692
|
-
errorText: r.errorText,
|
|
693
|
-
})),
|
|
755
|
+
requests: results.map(buildNetworkRequestSummary),
|
|
694
756
|
}
|
|
695
757
|
}
|
|
696
758
|
|
|
@@ -703,7 +765,20 @@ async function handleGetNetworkDetail(params = {}) {
|
|
|
703
765
|
if (!entry) entry = networkRequests.find(r => r.requestId === requestId)
|
|
704
766
|
if (!entry) throw new Error(`未找到请求: ${requestId}`)
|
|
705
767
|
|
|
706
|
-
const
|
|
768
|
+
const urlMeta = summarizeNetworkUrl(entry.url)
|
|
769
|
+
const result = {
|
|
770
|
+
...entry,
|
|
771
|
+
url: urlMeta.displayUrl,
|
|
772
|
+
...(urlMeta.urlTruncated ? { urlTruncated: true, urlOriginalLength: urlMeta.urlOriginalLength } : {}),
|
|
773
|
+
...(urlMeta.urlScheme ? { urlScheme: urlMeta.urlScheme } : {}),
|
|
774
|
+
...(urlMeta.dataUrlMimeType ? { dataUrlMimeType: urlMeta.dataUrlMimeType } : {}),
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
if (urlMeta.urlTruncated) {
|
|
778
|
+
result.urlNote = urlMeta.urlScheme === 'data'
|
|
779
|
+
? '为避免上下文膨胀,data URL 已摘要化展示。'
|
|
780
|
+
: '为避免上下文膨胀,超长 URL 已摘要化展示。'
|
|
781
|
+
}
|
|
707
782
|
|
|
708
783
|
if (includeBody && entry.status !== "pending" && entry.status !== "failed") {
|
|
709
784
|
try {
|
package/extension/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ghost-bridge",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Ghost Bridge: Zero-restart Chrome debugger bridge for Claude MCP. Includes CLI for easy setup.",
|
|
@@ -48,8 +48,5 @@
|
|
|
48
48
|
"fs-extra": "^11.1.1",
|
|
49
49
|
"js-beautify": "^1.14.11",
|
|
50
50
|
"ws": "^8.14.2"
|
|
51
|
-
},
|
|
52
|
-
"dependencies": {
|
|
53
|
-
"ghost-bridge": "^0.5.2"
|
|
54
51
|
}
|
|
55
52
|
}
|