@browserbridge/bbx 1.0.0 → 1.1.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/README.md +6 -4
- package/package.json +53 -53
- package/packages/agent-client/src/cli-helpers.js +43 -5
- package/packages/agent-client/src/cli.js +176 -171
- package/packages/agent-client/src/client.js +66 -21
- package/packages/agent-client/src/command-registry.js +104 -69
- package/packages/agent-client/src/detect.js +162 -54
- package/packages/agent-client/src/install.js +34 -28
- package/packages/agent-client/src/mcp-config.js +40 -40
- package/packages/agent-client/src/runtime.js +41 -20
- package/packages/agent-client/src/setup-status.js +23 -30
- package/packages/mcp-server/src/bin.js +57 -5
- package/packages/mcp-server/src/handlers.js +573 -256
- package/packages/mcp-server/src/server.js +568 -257
- package/packages/native-host/bin/bridge-daemon.js +39 -6
- package/packages/native-host/bin/install-manifest.js +26 -4
- package/packages/native-host/bin/postinstall.js +4 -2
- package/packages/native-host/src/config.js +142 -13
- package/packages/native-host/src/daemon-process.js +396 -0
- package/packages/native-host/src/daemon.js +350 -150
- package/packages/native-host/src/framing.js +131 -11
- package/packages/native-host/src/install-manifest.js +194 -29
- package/packages/native-host/src/native-host.js +154 -102
- package/packages/protocol/src/budget.js +3 -7
- package/packages/protocol/src/capabilities.js +6 -3
- package/packages/protocol/src/defaults.js +1 -0
- package/packages/protocol/src/errors.js +15 -11
- package/packages/protocol/src/payload-cost.js +19 -6
- package/packages/protocol/src/protocol.js +242 -73
- package/packages/protocol/src/registry.js +311 -45
- package/packages/protocol/src/summary.js +260 -109
- package/packages/protocol/src/types.js +29 -4
- package/skills/browser-bridge/SKILL.md +3 -2
- package/skills/browser-bridge/agents/openai.yaml +3 -3
- package/skills/browser-bridge/references/interaction.md +34 -11
- package/skills/browser-bridge/references/patch-workflow.md +3 -0
- package/skills/browser-bridge/references/protocol.md +127 -71
- package/skills/browser-bridge/references/tailwind.md +12 -11
- package/skills/browser-bridge/references/token-efficiency.md +23 -22
- package/skills/browser-bridge/references/ui-workflows.md +8 -0
- package/CHANGELOG.md +0 -55
- package/assets/banner.jpg +0 -0
- package/assets/logo.png +0 -0
- package/assets/logo.svg +0 -65
- package/docs/api-reference.md +0 -157
- package/docs/cli-guide.md +0 -128
- package/docs/index.md +0 -25
- package/docs/manual-setup.md +0 -140
- package/docs/mcp-vs-cli.md +0 -258
- package/docs/publishing.md +0 -114
- package/docs/quickstart.md +0 -104
- package/docs/troubleshooting.md +0 -59
- package/docs/usage-scenarios.md +0 -136
- package/manifest.json +0 -52
- package/packages/extension/assets/icon-128.png +0 -0
- package/packages/extension/assets/icon-16.png +0 -0
- package/packages/extension/assets/icon-32.png +0 -0
- package/packages/extension/assets/icon-48.png +0 -0
- package/packages/extension/src/background-helpers.js +0 -459
- package/packages/extension/src/background-routing.js +0 -91
- package/packages/extension/src/background.js +0 -3227
- package/packages/extension/src/content-script-helpers.js +0 -281
- package/packages/extension/src/content-script.js +0 -1977
- package/packages/extension/src/debugger-coordinator.js +0 -188
- package/packages/extension/src/sidepanel-helpers.js +0 -102
- package/packages/extension/ui/offscreen.html +0 -6
- package/packages/extension/ui/offscreen.js +0 -61
- package/packages/extension/ui/popup.html +0 -35
- package/packages/extension/ui/popup.js +0 -279
- package/packages/extension/ui/sidepanel.html +0 -102
- package/packages/extension/ui/sidepanel.js +0 -1854
- package/packages/extension/ui/ui.css +0 -1159
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
estimateJsonPayloadCost,
|
|
5
|
-
getCostClass,
|
|
6
|
-
} from './index.js';
|
|
3
|
+
import { estimateSerializedPayloadCost, getCostClass, serializeJsonPayload } from './index.js';
|
|
7
4
|
|
|
8
5
|
/** @typedef {import('./types.js').BridgeResponse} BridgeResponse */
|
|
9
6
|
/** @typedef {import('./types.js').BridgeMethod} SummaryMethod */
|
|
@@ -53,16 +50,44 @@ import {
|
|
|
53
50
|
|
|
54
51
|
/** @type {Record<string, ActionSummary>} */
|
|
55
52
|
const ACTION_SUMMARIES = {
|
|
56
|
-
hovered:
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
53
|
+
hovered: {
|
|
54
|
+
text: (r) => `Hover ${r.hovered ? 'active' : 'failed'} on ${r.elementRef}.`,
|
|
55
|
+
evidence: (r) => r,
|
|
56
|
+
},
|
|
57
|
+
dragged: {
|
|
58
|
+
text: (r) =>
|
|
59
|
+
`Drag ${r.dragged ? 'completed' : 'failed'}: ${r.sourceRef} → ${r.destinationRef}.`,
|
|
60
|
+
evidence: (r) => r,
|
|
61
|
+
},
|
|
62
|
+
closed: { text: (r) => `Tab ${r.tabId} closed.`, evidence: (r) => r },
|
|
63
|
+
clicked: {
|
|
64
|
+
text: (r) => `Clicked ${r.elementRef ?? 'element'}.`,
|
|
65
|
+
evidence: (r) => ({ elementRef: r.elementRef }),
|
|
66
|
+
},
|
|
67
|
+
focused: {
|
|
68
|
+
text: (r) => `Focused ${r.elementRef ?? 'element'}.`,
|
|
69
|
+
evidence: (r) => ({ elementRef: r.elementRef }),
|
|
70
|
+
},
|
|
71
|
+
typed: {
|
|
72
|
+
text: (r) => `Typed into ${r.elementRef ?? 'element'}.`,
|
|
73
|
+
evidence: (r) => ({ elementRef: r.elementRef }),
|
|
74
|
+
},
|
|
75
|
+
pressed: {
|
|
76
|
+
text: (r) => `Key pressed${r.key ? ` (${r.key})` : ''}.`,
|
|
77
|
+
evidence: (r) => r,
|
|
78
|
+
},
|
|
79
|
+
navigated: {
|
|
80
|
+
text: (r) => `Navigated to ${r.url ?? 'page'}.`,
|
|
81
|
+
evidence: (r) => ({ url: r.url }),
|
|
82
|
+
},
|
|
83
|
+
scrolled: {
|
|
84
|
+
text: (r) => `Scrolled to (${r.x ?? 0}, ${r.y ?? 0}).`,
|
|
85
|
+
evidence: (r) => r,
|
|
86
|
+
},
|
|
87
|
+
resized: {
|
|
88
|
+
text: (r) => `Viewport resized to ${r.width ?? '?'}×${r.height ?? '?'}.`,
|
|
89
|
+
evidence: (r) => r,
|
|
90
|
+
},
|
|
66
91
|
};
|
|
67
92
|
|
|
68
93
|
/**
|
|
@@ -74,21 +99,30 @@ const ACTION_SUMMARIES = {
|
|
|
74
99
|
* @returns {AnnotatedBridgeSummary}
|
|
75
100
|
*/
|
|
76
101
|
export function annotateBridgeSummary(summary, response) {
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const
|
|
102
|
+
const metaTransportBytes =
|
|
103
|
+
getNumericMetaField(response.meta, 'transport_bytes') ??
|
|
104
|
+
getNumericMetaField(response.meta, 'response_bytes');
|
|
105
|
+
const metaTransportTokens =
|
|
106
|
+
getNumericMetaField(response.meta, 'transport_approx_tokens') ??
|
|
107
|
+
getNumericMetaField(response.meta, 'approx_tokens');
|
|
108
|
+
const transportCost =
|
|
109
|
+
metaTransportBytes == null || metaTransportTokens == null
|
|
110
|
+
? estimateSerializedPayloadCost(
|
|
111
|
+
serializeJsonPayload(response.ok ? response.result : { error: response.error })
|
|
112
|
+
)
|
|
113
|
+
: null;
|
|
114
|
+
const transportBytes = metaTransportBytes ?? transportCost?.bytes ?? 0;
|
|
115
|
+
const transportTokens = metaTransportTokens ?? transportCost?.approxTokens ?? 0;
|
|
116
|
+
const summaryCost = estimateSerializedPayloadCost(serializeJsonPayload(summary));
|
|
84
117
|
|
|
85
118
|
return {
|
|
86
119
|
...summary,
|
|
87
120
|
transportBytes,
|
|
88
121
|
transportTokens,
|
|
89
|
-
transportCostClass:
|
|
90
|
-
|
|
91
|
-
|
|
122
|
+
transportCostClass:
|
|
123
|
+
getMetaCostClass(response.meta, 'transport_cost_class') ??
|
|
124
|
+
getMetaCostClass(response.meta, 'cost_class') ??
|
|
125
|
+
getCostClass(transportTokens),
|
|
92
126
|
summaryBytes: summaryCost.bytes,
|
|
93
127
|
summaryTokens: summaryCost.approxTokens,
|
|
94
128
|
summaryCostClass: summaryCost.costClass,
|
|
@@ -132,28 +166,32 @@ export function summarizeBridgeResponse(response, method) {
|
|
|
132
166
|
`${response.error.code}: ${response.error.message}${hint ? ` ${hint}` : ''}`,
|
|
133
167
|
protocolWarning
|
|
134
168
|
),
|
|
135
|
-
evidence: response.error.details ?? null
|
|
169
|
+
evidence: response.error.details ?? null,
|
|
136
170
|
};
|
|
137
171
|
}
|
|
138
172
|
|
|
139
173
|
const result = toRecord(response.result);
|
|
140
174
|
if (typeof result.daemon === 'string') {
|
|
141
|
-
const access =
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
?
|
|
148
|
-
:
|
|
175
|
+
const access =
|
|
176
|
+
result.access && typeof result.access === 'object'
|
|
177
|
+
? /** @type {Record<string, unknown>} */ (result.access)
|
|
178
|
+
: null;
|
|
179
|
+
const accessSummary =
|
|
180
|
+
access == null
|
|
181
|
+
? ''
|
|
182
|
+
: access.enabled
|
|
183
|
+
? ` Access: ${access.routeReady ? `ready on tab ${access.routeTabId}.` : `enabled${typeof access.reason === 'string' ? ` (${access.reason})` : '.'}`}`
|
|
184
|
+
: ' Access: disabled.';
|
|
149
185
|
const connectedExtensions = Array.isArray(result.connectedExtensions)
|
|
150
186
|
? /** @type {Array<Record<string, unknown>>} */ (result.connectedExtensions)
|
|
151
187
|
: [];
|
|
152
188
|
const extensionSummary = result.extensionConnected
|
|
153
|
-
? `connected (${connectedExtensions.length}: ${connectedExtensions
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
189
|
+
? `connected (${connectedExtensions.length}: ${connectedExtensions
|
|
190
|
+
.map((ext) => {
|
|
191
|
+
const label = `${ext.browserName ?? 'unknown'}${ext.profileLabel ? '/' + ext.profileLabel : ''}`;
|
|
192
|
+
return ext.accessEnabled ? `${label}*` : label;
|
|
193
|
+
})
|
|
194
|
+
.join(', ')})`
|
|
157
195
|
: 'disconnected';
|
|
158
196
|
return {
|
|
159
197
|
ok: true,
|
|
@@ -161,22 +199,36 @@ export function summarizeBridgeResponse(response, method) {
|
|
|
161
199
|
`Daemon: ${result.daemon}. Extension: ${extensionSummary}.${accessSummary}`,
|
|
162
200
|
protocolWarning
|
|
163
201
|
),
|
|
164
|
-
evidence: result
|
|
202
|
+
evidence: result,
|
|
165
203
|
};
|
|
166
204
|
}
|
|
167
205
|
if (Array.isArray(result.mcpClients) && Array.isArray(result.skillTargets)) {
|
|
168
|
-
const configuredMcp = result.mcpClients.filter(
|
|
169
|
-
|
|
206
|
+
const configuredMcp = result.mcpClients.filter(
|
|
207
|
+
(entry) =>
|
|
208
|
+
entry &&
|
|
209
|
+
typeof entry === 'object' &&
|
|
210
|
+
/** @type {Record<string, unknown>} */ (entry).configured
|
|
211
|
+
).length;
|
|
212
|
+
const installedSkills = result.skillTargets.filter(
|
|
213
|
+
(entry) =>
|
|
214
|
+
entry &&
|
|
215
|
+
typeof entry === 'object' &&
|
|
216
|
+
/** @type {Record<string, unknown>} */ (entry).installed
|
|
217
|
+
).length;
|
|
170
218
|
return {
|
|
171
219
|
ok: true,
|
|
172
220
|
summary: appendProtocolWarning(
|
|
173
221
|
`Setup: MCP configured for ${configuredMcp}/${result.mcpClients.length} clients; skill installed for ${installedSkills}/${result.skillTargets.length} targets.`,
|
|
174
222
|
protocolWarning
|
|
175
223
|
),
|
|
176
|
-
evidence: result
|
|
224
|
+
evidence: result,
|
|
177
225
|
};
|
|
178
226
|
}
|
|
179
|
-
if (
|
|
227
|
+
if (
|
|
228
|
+
typeof result.url === 'string' &&
|
|
229
|
+
typeof result.title === 'string' &&
|
|
230
|
+
typeof result.origin === 'string'
|
|
231
|
+
) {
|
|
180
232
|
/** @type {string[]} */
|
|
181
233
|
const hints = [];
|
|
182
234
|
if (result.hints && typeof result.hints === 'object') {
|
|
@@ -190,10 +242,18 @@ export function summarizeBridgeResponse(response, method) {
|
|
|
190
242
|
`Page: ${result.title} (${result.origin})${hints.length ? ` [${hints.join(', ')}]` : ''}.`,
|
|
191
243
|
protocolWarning
|
|
192
244
|
),
|
|
193
|
-
evidence: {
|
|
245
|
+
evidence: {
|
|
246
|
+
url: result.url,
|
|
247
|
+
origin: result.origin,
|
|
248
|
+
title: result.title,
|
|
249
|
+
hints: result.hints,
|
|
250
|
+
},
|
|
194
251
|
};
|
|
195
252
|
}
|
|
196
|
-
if (
|
|
253
|
+
if (
|
|
254
|
+
(typeof result.text === 'string' || typeof result.value === 'string') &&
|
|
255
|
+
typeof result.truncated === 'boolean'
|
|
256
|
+
) {
|
|
197
257
|
const text = /** @type {string} */ (result.text ?? result.value);
|
|
198
258
|
const len = typeof result.length === 'number' ? result.length : text.length;
|
|
199
259
|
const label = method === 'dom.get_text' ? 'Element text' : 'Page text';
|
|
@@ -203,7 +263,11 @@ export function summarizeBridgeResponse(response, method) {
|
|
|
203
263
|
`${label}: ${len} chars${result.truncated ? ' (truncated)' : ''}.`,
|
|
204
264
|
protocolWarning
|
|
205
265
|
),
|
|
206
|
-
evidence: {
|
|
266
|
+
evidence: {
|
|
267
|
+
text: text.slice(0, 500),
|
|
268
|
+
length: len,
|
|
269
|
+
truncated: result.truncated,
|
|
270
|
+
},
|
|
207
271
|
};
|
|
208
272
|
}
|
|
209
273
|
if (Array.isArray(result.tabs)) {
|
|
@@ -215,14 +279,24 @@ export function summarizeBridgeResponse(response, method) {
|
|
|
215
279
|
tabId: tab.tabId,
|
|
216
280
|
active: tab.active,
|
|
217
281
|
origin: tab.origin,
|
|
218
|
-
title: tab.title
|
|
219
|
-
}))
|
|
282
|
+
title: tab.title,
|
|
283
|
+
})),
|
|
220
284
|
};
|
|
221
285
|
}
|
|
222
|
-
if (
|
|
286
|
+
if (
|
|
287
|
+
Array.isArray(result.nodes) &&
|
|
288
|
+
typeof result.total === 'number' &&
|
|
289
|
+
result.nodes[0]?.role !== undefined
|
|
290
|
+
) {
|
|
223
291
|
const nodes = /** @type {Array<Record<string, unknown>>} */ (result.nodes);
|
|
224
292
|
const interactive = nodes.filter((/** @type {Record<string, unknown>} */ n) => n.interactive);
|
|
225
|
-
const shown =
|
|
293
|
+
const shown =
|
|
294
|
+
interactive.length > 0
|
|
295
|
+
? interactive
|
|
296
|
+
: nodes.filter(
|
|
297
|
+
(/** @type {Record<string, unknown>} */ n) =>
|
|
298
|
+
n.role && n.role !== 'none' && n.role !== 'generic'
|
|
299
|
+
);
|
|
226
300
|
return {
|
|
227
301
|
ok: true,
|
|
228
302
|
summary: appendProtocolWarning(
|
|
@@ -235,7 +309,7 @@ export function summarizeBridgeResponse(response, method) {
|
|
|
235
309
|
if (n.interactive) entry.interactive = true;
|
|
236
310
|
if (n.value) entry.value = n.value;
|
|
237
311
|
return entry;
|
|
238
|
-
})
|
|
312
|
+
}),
|
|
239
313
|
};
|
|
240
314
|
}
|
|
241
315
|
if (Array.isArray(result.nodes)) {
|
|
@@ -247,14 +321,20 @@ export function summarizeBridgeResponse(response, method) {
|
|
|
247
321
|
if (typeof n.attrs === 'object' && n.attrs !== null) {
|
|
248
322
|
const attrs = /** @type {Record<string, unknown>} */ (n.attrs);
|
|
249
323
|
if (attrs.id) entry.id = attrs.id;
|
|
250
|
-
if (typeof attrs.class === 'string')
|
|
324
|
+
if (typeof attrs.class === 'string')
|
|
325
|
+
entry.cls = attrs.class.split(' ').slice(0, 3).join(' ');
|
|
251
326
|
if (attrs.role) entry.role = attrs.role;
|
|
252
327
|
if (attrs['aria-label']) entry.label = attrs['aria-label'];
|
|
253
328
|
if (attrs['data-testid']) entry.testId = attrs['data-testid'];
|
|
254
329
|
}
|
|
255
330
|
if (!entry.role && n.role) entry.role = n.role;
|
|
256
331
|
if (!entry.label && n.name) entry.label = n.name;
|
|
257
|
-
const text =
|
|
332
|
+
const text =
|
|
333
|
+
typeof n.textExcerpt === 'string'
|
|
334
|
+
? n.textExcerpt
|
|
335
|
+
: typeof n.text === 'string'
|
|
336
|
+
? n.text
|
|
337
|
+
: '';
|
|
258
338
|
if (text) {
|
|
259
339
|
entry.text = text.length > 80 ? `${text.slice(0, 79)}\u2026` : text;
|
|
260
340
|
}
|
|
@@ -275,21 +355,21 @@ export function summarizeBridgeResponse(response, method) {
|
|
|
275
355
|
`${label} ${nodes.length} element(s)${nodes.length > 15 ? '; showing first 15' : ''}.`,
|
|
276
356
|
protocolWarning
|
|
277
357
|
),
|
|
278
|
-
evidence: compact
|
|
358
|
+
evidence: compact,
|
|
279
359
|
};
|
|
280
360
|
}
|
|
281
361
|
if (typeof result.rolledBack === 'boolean' || typeof result.rolled_back === 'boolean') {
|
|
282
362
|
return {
|
|
283
363
|
ok: true,
|
|
284
364
|
summary: appendProtocolWarning('Patch rolled back.', protocolWarning),
|
|
285
|
-
evidence: result
|
|
365
|
+
evidence: result,
|
|
286
366
|
};
|
|
287
367
|
}
|
|
288
368
|
if (typeof result.patchId === 'string') {
|
|
289
369
|
return {
|
|
290
370
|
ok: true,
|
|
291
371
|
summary: appendProtocolWarning(`Patch ${result.patchId} applied.`, protocolWarning),
|
|
292
|
-
evidence: result
|
|
372
|
+
evidence: result,
|
|
293
373
|
};
|
|
294
374
|
}
|
|
295
375
|
if (typeof result.found === 'boolean') {
|
|
@@ -301,7 +381,10 @@ export function summarizeBridgeResponse(response, method) {
|
|
|
301
381
|
: `Element not found (timed out after ${result.duration ?? 0}ms).`,
|
|
302
382
|
protocolWarning
|
|
303
383
|
),
|
|
304
|
-
evidence: {
|
|
384
|
+
evidence: {
|
|
385
|
+
elementRef: result.elementRef ?? null,
|
|
386
|
+
duration: result.duration,
|
|
387
|
+
},
|
|
305
388
|
};
|
|
306
389
|
}
|
|
307
390
|
if (typeof result.value !== 'undefined' && typeof result.type === 'string') {
|
|
@@ -313,7 +396,11 @@ export function summarizeBridgeResponse(response, method) {
|
|
|
313
396
|
repr = '';
|
|
314
397
|
} else if (typeof result.value === 'string') {
|
|
315
398
|
repr = result.value.length > 200 ? `${result.value.slice(0, 199)}\u2026` : result.value;
|
|
316
|
-
} else if (
|
|
399
|
+
} else if (
|
|
400
|
+
typeof result.value === 'object' &&
|
|
401
|
+
result.value !== null &&
|
|
402
|
+
Object.keys(result.value).length === 0
|
|
403
|
+
) {
|
|
317
404
|
repr = '(empty - may be a Promise, Map, or non-serializable value)';
|
|
318
405
|
} else {
|
|
319
406
|
repr = JSON.stringify(result.value);
|
|
@@ -325,20 +412,33 @@ export function summarizeBridgeResponse(response, method) {
|
|
|
325
412
|
repr ? `Evaluated to ${typeLabel}: ${repr}` : `Evaluated to ${typeLabel}.`,
|
|
326
413
|
protocolWarning
|
|
327
414
|
),
|
|
328
|
-
evidence: result
|
|
415
|
+
evidence: result,
|
|
329
416
|
};
|
|
330
417
|
}
|
|
331
|
-
if (
|
|
418
|
+
if (
|
|
419
|
+
Array.isArray(result.entries) &&
|
|
420
|
+
result.entries.length > 0 &&
|
|
421
|
+
typeof result.entries[0]?.at === 'string' &&
|
|
422
|
+
typeof result.entries[0]?.method === 'string'
|
|
423
|
+
) {
|
|
332
424
|
const entries = /** @type {Array<Record<string, unknown>>} */ (result.entries);
|
|
333
425
|
return {
|
|
334
426
|
ok: true,
|
|
335
427
|
summary: appendProtocolWarning(`Log: ${entries.length} entries.`, protocolWarning),
|
|
336
428
|
evidence: entries.slice(-10).map((/** @type {Record<string, unknown>} */ e) => ({
|
|
337
|
-
at: e.at,
|
|
338
|
-
|
|
429
|
+
at: e.at,
|
|
430
|
+
method: e.method,
|
|
431
|
+
ok: e.ok,
|
|
432
|
+
...(typeof e.source === 'string' && e.source ? { source: e.source } : {}),
|
|
433
|
+
})),
|
|
339
434
|
};
|
|
340
435
|
}
|
|
341
|
-
if (
|
|
436
|
+
if (
|
|
437
|
+
Array.isArray(result.entries) &&
|
|
438
|
+
(result.entries.length > 0
|
|
439
|
+
? result.entries[0]?.type === 'fetch' || result.entries[0]?.type === 'xhr'
|
|
440
|
+
: method === 'page.get_network')
|
|
441
|
+
) {
|
|
342
442
|
const entries = /** @type {Array<Record<string, unknown>>} */ (result.entries);
|
|
343
443
|
return {
|
|
344
444
|
ok: true,
|
|
@@ -347,8 +447,11 @@ export function summarizeBridgeResponse(response, method) {
|
|
|
347
447
|
protocolWarning
|
|
348
448
|
),
|
|
349
449
|
evidence: entries.slice(0, 20).map((/** @type {Record<string, unknown>} */ e) => ({
|
|
350
|
-
method: e.method,
|
|
351
|
-
|
|
450
|
+
method: e.method,
|
|
451
|
+
url: truncateUrl(/** @type {string} */ (e.url)),
|
|
452
|
+
status: e.status,
|
|
453
|
+
duration: e.duration,
|
|
454
|
+
})),
|
|
352
455
|
};
|
|
353
456
|
}
|
|
354
457
|
if (Array.isArray(result.entries)) {
|
|
@@ -366,7 +469,7 @@ export function summarizeBridgeResponse(response, method) {
|
|
|
366
469
|
entry.ago = formatRelativeTime(e.ts);
|
|
367
470
|
}
|
|
368
471
|
return entry;
|
|
369
|
-
})
|
|
472
|
+
}),
|
|
370
473
|
};
|
|
371
474
|
}
|
|
372
475
|
if (typeof result.html === 'string') {
|
|
@@ -376,7 +479,10 @@ export function summarizeBridgeResponse(response, method) {
|
|
|
376
479
|
`HTML fragment: ${result.html.length} chars${result.truncated ? ' (truncated)' : ''}.`,
|
|
377
480
|
protocolWarning
|
|
378
481
|
),
|
|
379
|
-
evidence: {
|
|
482
|
+
evidence: {
|
|
483
|
+
html: result.html.slice(0, 500),
|
|
484
|
+
truncated: result.truncated,
|
|
485
|
+
},
|
|
380
486
|
};
|
|
381
487
|
}
|
|
382
488
|
for (const [field, handler] of Object.entries(ACTION_SUMMARIES)) {
|
|
@@ -384,13 +490,12 @@ export function summarizeBridgeResponse(response, method) {
|
|
|
384
490
|
return {
|
|
385
491
|
ok: true,
|
|
386
492
|
summary: appendProtocolWarning(handler.text(result), protocolWarning),
|
|
387
|
-
evidence: handler.evidence(result)
|
|
493
|
+
evidence: handler.evidence(result),
|
|
388
494
|
};
|
|
389
495
|
}
|
|
390
496
|
}
|
|
391
497
|
if (typeof result.tabId === 'number' && typeof result.url === 'string') {
|
|
392
|
-
const actionMethod =
|
|
393
|
-
typeof result.method === 'string' ? result.method : method;
|
|
498
|
+
const actionMethod = typeof result.method === 'string' ? result.method : method;
|
|
394
499
|
if (actionMethod === 'navigation.navigate') {
|
|
395
500
|
return {
|
|
396
501
|
ok: true,
|
|
@@ -405,16 +510,22 @@ export function summarizeBridgeResponse(response, method) {
|
|
|
405
510
|
}
|
|
406
511
|
return {
|
|
407
512
|
ok: true,
|
|
408
|
-
summary: appendProtocolWarning(
|
|
409
|
-
|
|
513
|
+
summary: appendProtocolWarning(
|
|
514
|
+
`Tab ${result.tabId} created${result.url ? ` (${result.url})` : ''}.`,
|
|
515
|
+
protocolWarning
|
|
516
|
+
),
|
|
517
|
+
evidence: result,
|
|
410
518
|
};
|
|
411
519
|
}
|
|
412
520
|
if (typeof result.metrics === 'object' && result.metrics !== null) {
|
|
413
521
|
const keys = Object.keys(result.metrics);
|
|
414
522
|
return {
|
|
415
523
|
ok: true,
|
|
416
|
-
summary: appendProtocolWarning(
|
|
417
|
-
|
|
524
|
+
summary: appendProtocolWarning(
|
|
525
|
+
`Performance: ${keys.length} metrics collected.`,
|
|
526
|
+
protocolWarning
|
|
527
|
+
),
|
|
528
|
+
evidence: result.metrics,
|
|
418
529
|
};
|
|
419
530
|
}
|
|
420
531
|
if (typeof result.count === 'number' && typeof result.type === 'string' && result.entries) {
|
|
@@ -427,16 +538,26 @@ export function summarizeBridgeResponse(response, method) {
|
|
|
427
538
|
}
|
|
428
539
|
return {
|
|
429
540
|
ok: true,
|
|
430
|
-
summary: appendProtocolWarning(
|
|
431
|
-
|
|
541
|
+
summary: appendProtocolWarning(
|
|
542
|
+
`Storage (${result.type}): ${result.count} entries.`,
|
|
543
|
+
protocolWarning
|
|
544
|
+
),
|
|
545
|
+
evidence: safe,
|
|
432
546
|
};
|
|
433
547
|
}
|
|
434
|
-
if (
|
|
548
|
+
if (
|
|
549
|
+
typeof result.tag === 'string' &&
|
|
550
|
+
typeof result.elementRef === 'string' &&
|
|
551
|
+
typeof result.bbox === 'object'
|
|
552
|
+
) {
|
|
435
553
|
const desc = [result.tag];
|
|
436
554
|
if (result.id) desc[0] += `#${result.id}`;
|
|
437
|
-
const textValue =
|
|
438
|
-
|
|
439
|
-
|
|
555
|
+
const textValue =
|
|
556
|
+
typeof result.text === 'object' && result.text !== null && 'value' in result.text
|
|
557
|
+
? /** @type {{ value: string }} */ (result.text).value
|
|
558
|
+
: typeof result.text === 'string'
|
|
559
|
+
? result.text
|
|
560
|
+
: '';
|
|
440
561
|
if (textValue) desc.push(String(textValue).slice(0, 60));
|
|
441
562
|
const bbox = /** @type {Record<string, number>} */ (result.bbox);
|
|
442
563
|
if (bbox.width && bbox.height) {
|
|
@@ -445,15 +566,29 @@ export function summarizeBridgeResponse(response, method) {
|
|
|
445
566
|
return {
|
|
446
567
|
ok: true,
|
|
447
568
|
summary: appendProtocolWarning(`Element ${desc.join(', ')}.`, protocolWarning),
|
|
448
|
-
evidence: {
|
|
569
|
+
evidence: {
|
|
570
|
+
elementRef: result.elementRef,
|
|
571
|
+
tag: result.tag,
|
|
572
|
+
id: result.id,
|
|
573
|
+
role: result.role,
|
|
574
|
+
text: textValue,
|
|
575
|
+
bbox: result.bbox,
|
|
576
|
+
},
|
|
449
577
|
};
|
|
450
578
|
}
|
|
451
|
-
if (
|
|
579
|
+
if (
|
|
580
|
+
typeof result.properties === 'object' &&
|
|
581
|
+
result.properties !== null &&
|
|
582
|
+
typeof result.elementRef === 'string'
|
|
583
|
+
) {
|
|
452
584
|
const props = Object.keys(/** @type {object} */ (result.properties));
|
|
453
585
|
return {
|
|
454
586
|
ok: true,
|
|
455
|
-
summary: appendProtocolWarning(
|
|
456
|
-
|
|
587
|
+
summary: appendProtocolWarning(
|
|
588
|
+
`Computed ${props.length} style(s) for ${result.elementRef}.`,
|
|
589
|
+
protocolWarning
|
|
590
|
+
),
|
|
591
|
+
evidence: result.properties,
|
|
457
592
|
};
|
|
458
593
|
}
|
|
459
594
|
if (method === 'styles.get_computed') {
|
|
@@ -461,23 +596,41 @@ export function summarizeBridgeResponse(response, method) {
|
|
|
461
596
|
return {
|
|
462
597
|
ok: true,
|
|
463
598
|
summary: appendProtocolWarning(`Computed ${props.length} style(s).`, protocolWarning),
|
|
464
|
-
evidence: result
|
|
599
|
+
evidence: result,
|
|
465
600
|
};
|
|
466
601
|
}
|
|
467
602
|
if (typeof result.content === 'object' && typeof result.border === 'object') {
|
|
468
603
|
const c = /** @type {Record<string, number>} */ (result.content);
|
|
469
604
|
return {
|
|
470
605
|
ok: true,
|
|
471
|
-
summary: appendProtocolWarning(
|
|
472
|
-
|
|
606
|
+
summary: appendProtocolWarning(
|
|
607
|
+
`Box model: ${c.width ?? '?'}×${c.height ?? '?'} at (${c.x ?? 0}, ${c.y ?? 0}).`,
|
|
608
|
+
protocolWarning
|
|
609
|
+
),
|
|
610
|
+
evidence: result,
|
|
473
611
|
};
|
|
474
612
|
}
|
|
475
|
-
if (
|
|
476
|
-
|
|
613
|
+
if (
|
|
614
|
+
typeof result.x === 'number' &&
|
|
615
|
+
typeof result.y === 'number' &&
|
|
616
|
+
typeof result.width === 'number' &&
|
|
617
|
+
typeof result.height === 'number' &&
|
|
618
|
+
!(
|
|
619
|
+
'clicked' in result ||
|
|
620
|
+
'hovered' in result ||
|
|
621
|
+
'focused' in result ||
|
|
622
|
+
'resized' in result ||
|
|
623
|
+
'tag' in result ||
|
|
624
|
+
'elementRef' in result
|
|
625
|
+
)
|
|
626
|
+
) {
|
|
477
627
|
return {
|
|
478
628
|
ok: true,
|
|
479
|
-
summary: appendProtocolWarning(
|
|
480
|
-
|
|
629
|
+
summary: appendProtocolWarning(
|
|
630
|
+
`Box model: ${result.width}×${result.height} at (${result.x}, ${result.y}).`,
|
|
631
|
+
protocolWarning
|
|
632
|
+
),
|
|
633
|
+
evidence: result,
|
|
481
634
|
};
|
|
482
635
|
}
|
|
483
636
|
if (Array.isArray(response.result) && looksLikePatchArray(response.result, method)) {
|
|
@@ -485,21 +638,24 @@ export function summarizeBridgeResponse(response, method) {
|
|
|
485
638
|
return {
|
|
486
639
|
ok: true,
|
|
487
640
|
summary: appendProtocolWarning(`${patches.length} active patch(es).`, protocolWarning),
|
|
488
|
-
evidence: patches.slice(0, 10)
|
|
641
|
+
evidence: patches.slice(0, 10),
|
|
489
642
|
};
|
|
490
643
|
}
|
|
491
644
|
if (Array.isArray(result.patches)) {
|
|
492
645
|
return {
|
|
493
646
|
ok: true,
|
|
494
647
|
summary: appendProtocolWarning(`${result.patches.length} active patch(es).`, protocolWarning),
|
|
495
|
-
evidence: result.patches.slice(0, 10)
|
|
648
|
+
evidence: result.patches.slice(0, 10),
|
|
496
649
|
};
|
|
497
650
|
}
|
|
498
651
|
const keys = Object.keys(result);
|
|
499
652
|
return {
|
|
500
653
|
ok: true,
|
|
501
|
-
summary: appendProtocolWarning(
|
|
502
|
-
|
|
654
|
+
summary: appendProtocolWarning(
|
|
655
|
+
`Bridge method succeeded with ${keys.length} top-level fields.`,
|
|
656
|
+
protocolWarning
|
|
657
|
+
),
|
|
658
|
+
evidence: keys.slice(0, 10),
|
|
503
659
|
};
|
|
504
660
|
}
|
|
505
661
|
|
|
@@ -509,16 +665,15 @@ export function summarizeBridgeResponse(response, method) {
|
|
|
509
665
|
*/
|
|
510
666
|
export function summarizeBatchResponseItem({ method, tabId, response, durationMs }) {
|
|
511
667
|
const summary = annotateBridgeSummary(summarizeBridgeResponse(response, method), response);
|
|
512
|
-
const cost = estimateJsonPayloadCost(response.ok ? response.result : { error: response.error });
|
|
513
668
|
return {
|
|
514
669
|
method,
|
|
515
670
|
tabId,
|
|
516
671
|
...summary,
|
|
517
672
|
durationMs,
|
|
518
|
-
approxTokens:
|
|
673
|
+
approxTokens: summary.transportTokens,
|
|
519
674
|
meta: response.meta,
|
|
520
675
|
error: response.ok ? null : response.error,
|
|
521
|
-
response: response.ok ? response.result : null
|
|
676
|
+
response: response.ok ? response.result : null,
|
|
522
677
|
};
|
|
523
678
|
}
|
|
524
679
|
|
|
@@ -535,9 +690,9 @@ export function summarizeBatchErrorItem({ method, tabId, error, durationMs }) {
|
|
|
535
690
|
error: {
|
|
536
691
|
code: 'INTERNAL_ERROR',
|
|
537
692
|
message,
|
|
538
|
-
details: null
|
|
693
|
+
details: null,
|
|
539
694
|
},
|
|
540
|
-
meta: { protocol_version: '1.0' }
|
|
695
|
+
meta: { protocol_version: '1.0' },
|
|
541
696
|
});
|
|
542
697
|
const summary = annotateBridgeSummary(summarizeBridgeResponse(response, method), response);
|
|
543
698
|
return {
|
|
@@ -548,7 +703,7 @@ export function summarizeBatchErrorItem({ method, tabId, error, durationMs }) {
|
|
|
548
703
|
approxTokens: 0,
|
|
549
704
|
meta: response.meta,
|
|
550
705
|
error: response.error,
|
|
551
|
-
response: null
|
|
706
|
+
response: null,
|
|
552
707
|
};
|
|
553
708
|
}
|
|
554
709
|
|
|
@@ -557,9 +712,7 @@ export function summarizeBatchErrorItem({ method, tabId, error, durationMs }) {
|
|
|
557
712
|
* @returns {Record<string, unknown>}
|
|
558
713
|
*/
|
|
559
714
|
function toRecord(value) {
|
|
560
|
-
return value && typeof value === 'object'
|
|
561
|
-
? /** @type {Record<string, unknown>} */ (value)
|
|
562
|
-
: {};
|
|
715
|
+
return value && typeof value === 'object' ? /** @type {Record<string, unknown>} */ (value) : {};
|
|
563
716
|
}
|
|
564
717
|
|
|
565
718
|
/**
|
|
@@ -608,6 +761,9 @@ function summarizeErrorHint(code) {
|
|
|
608
761
|
if (code === 'ELEMENT_STALE') {
|
|
609
762
|
return 'Re-query the current page after navigation or DOM updates.';
|
|
610
763
|
}
|
|
764
|
+
if (code === 'RESULT_TRUNCATED') {
|
|
765
|
+
return 'Narrow the query or raise the relevant budget if more detail is required.';
|
|
766
|
+
}
|
|
611
767
|
return '';
|
|
612
768
|
}
|
|
613
769
|
|
|
@@ -623,12 +779,7 @@ function looksLikePatchArray(arr, method) {
|
|
|
623
779
|
if (!Array.isArray(arr)) return false;
|
|
624
780
|
if (arr.length === 0) return method === 'patch.list';
|
|
625
781
|
const first = arr[0];
|
|
626
|
-
return
|
|
627
|
-
first !== null &&
|
|
628
|
-
typeof first === 'object' &&
|
|
629
|
-
'patchId' in first &&
|
|
630
|
-
'kind' in first
|
|
631
|
-
);
|
|
782
|
+
return first !== null && typeof first === 'object' && 'patchId' in first && 'kind' in first;
|
|
632
783
|
}
|
|
633
784
|
|
|
634
785
|
/**
|