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 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: {
@@ -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(r => ({
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 result = { ...entry }
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 {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "Ghost Bridge",
4
- "version": "0.6.0",
4
+ "version": "0.6.2",
5
5
  "description": "Zero-restart Chrome debugger bridge for Claude MCP, optimized for no-sourcemap production debugging.",
6
6
  "permissions": [
7
7
  "debugger",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ghost-bridge",
3
- "version": "0.6.0",
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
  }