browser-debug-mcp-bridge 1.5.0 → 1.6.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 +122 -26
- package/apps/mcp-server/dist/db/events-repository.js +61 -23
- package/apps/mcp-server/dist/db/events-repository.js.map +1 -1
- package/apps/mcp-server/dist/db/migrations.js +104 -1
- package/apps/mcp-server/dist/db/migrations.js.map +1 -1
- package/apps/mcp-server/dist/db/schema.js +1 -1
- package/apps/mcp-server/dist/main.js +3 -2
- package/apps/mcp-server/dist/main.js.map +1 -1
- package/apps/mcp-server/dist/mcp/server.js +183 -33
- package/apps/mcp-server/dist/mcp/server.js.map +1 -1
- package/apps/mcp-server/dist/retention.js +34 -8
- package/apps/mcp-server/dist/retention.js.map +1 -1
- package/apps/mcp-server/dist/websocket/messages.js +5 -0
- package/apps/mcp-server/dist/websocket/messages.js.map +1 -1
- package/apps/mcp-server/dist/websocket/websocket-server.js +2 -0
- package/apps/mcp-server/dist/websocket/websocket-server.js.map +1 -1
- package/package.json +1 -1
- package/scripts/mcp-start.cjs +178 -18
|
@@ -38,9 +38,9 @@ const TOOL_SCHEMAS = {
|
|
|
38
38
|
},
|
|
39
39
|
get_recent_events: {
|
|
40
40
|
type: 'object',
|
|
41
|
-
required: ['sessionId'],
|
|
42
41
|
properties: {
|
|
43
42
|
sessionId: { type: 'string' },
|
|
43
|
+
url: { type: 'string' },
|
|
44
44
|
eventTypes: { type: 'array', items: { type: 'string' } },
|
|
45
45
|
limit: { type: 'number' },
|
|
46
46
|
offset: { type: 'number' },
|
|
@@ -48,18 +48,18 @@ const TOOL_SCHEMAS = {
|
|
|
48
48
|
},
|
|
49
49
|
get_navigation_history: {
|
|
50
50
|
type: 'object',
|
|
51
|
-
required: ['sessionId'],
|
|
52
51
|
properties: {
|
|
53
52
|
sessionId: { type: 'string' },
|
|
53
|
+
url: { type: 'string' },
|
|
54
54
|
limit: { type: 'number' },
|
|
55
55
|
offset: { type: 'number' },
|
|
56
56
|
},
|
|
57
57
|
},
|
|
58
58
|
get_console_events: {
|
|
59
59
|
type: 'object',
|
|
60
|
-
required: ['sessionId'],
|
|
61
60
|
properties: {
|
|
62
61
|
sessionId: { type: 'string' },
|
|
62
|
+
url: { type: 'string' },
|
|
63
63
|
level: { type: 'string' },
|
|
64
64
|
limit: { type: 'number' },
|
|
65
65
|
offset: { type: 'number' },
|
|
@@ -78,6 +78,7 @@ const TOOL_SCHEMAS = {
|
|
|
78
78
|
type: 'object',
|
|
79
79
|
properties: {
|
|
80
80
|
sessionId: { type: 'string' },
|
|
81
|
+
url: { type: 'string' },
|
|
81
82
|
errorType: { type: 'string' },
|
|
82
83
|
groupBy: { type: 'string' },
|
|
83
84
|
limit: { type: 'number' },
|
|
@@ -143,6 +144,20 @@ const TOOL_SCHEMAS = {
|
|
|
143
144
|
maxAncestors: { type: 'number' },
|
|
144
145
|
},
|
|
145
146
|
},
|
|
147
|
+
get_live_console_logs: {
|
|
148
|
+
type: 'object',
|
|
149
|
+
required: ['sessionId'],
|
|
150
|
+
properties: {
|
|
151
|
+
sessionId: { type: 'string' },
|
|
152
|
+
url: { type: 'string' },
|
|
153
|
+
tabId: { type: 'number' },
|
|
154
|
+
levels: { type: 'array', items: { type: 'string' } },
|
|
155
|
+
contains: { type: 'string' },
|
|
156
|
+
sinceTs: { type: 'number' },
|
|
157
|
+
includeRuntimeErrors: { type: 'boolean' },
|
|
158
|
+
limit: { type: 'number' },
|
|
159
|
+
},
|
|
160
|
+
},
|
|
146
161
|
explain_last_failure: {
|
|
147
162
|
type: 'object',
|
|
148
163
|
required: ['sessionId'],
|
|
@@ -208,6 +223,7 @@ const TOOL_DESCRIPTIONS = {
|
|
|
208
223
|
get_computed_styles: 'Read computed CSS styles for an element',
|
|
209
224
|
get_layout_metrics: 'Read viewport and element layout metrics',
|
|
210
225
|
capture_ui_snapshot: 'Capture redacted UI snapshot (DOM/styles/optional PNG) and persist it',
|
|
226
|
+
get_live_console_logs: 'Read in-memory live console logs for a connected session',
|
|
211
227
|
explain_last_failure: 'Explain the latest failure timeline',
|
|
212
228
|
get_event_correlation: 'Correlate related events by window',
|
|
213
229
|
list_snapshots: 'List snapshot metadata by session/time/trigger',
|
|
@@ -303,6 +319,65 @@ function parseRequestedTypes(value) {
|
|
|
303
319
|
.map((entry) => mapRequestedEventType(entry));
|
|
304
320
|
return Array.from(new Set(normalized));
|
|
305
321
|
}
|
|
322
|
+
function normalizeRequestedOrigin(value) {
|
|
323
|
+
if (value === undefined || value === null || value === '') {
|
|
324
|
+
return undefined;
|
|
325
|
+
}
|
|
326
|
+
if (typeof value !== 'string') {
|
|
327
|
+
throw new Error('url must be a string');
|
|
328
|
+
}
|
|
329
|
+
try {
|
|
330
|
+
const parsed = new URL(value);
|
|
331
|
+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
|
|
332
|
+
throw new Error('url must use http:// or https://');
|
|
333
|
+
}
|
|
334
|
+
return parsed.origin;
|
|
335
|
+
}
|
|
336
|
+
catch {
|
|
337
|
+
throw new Error('url must be a valid absolute http(s) URL');
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
function ensureSessionOrOriginFilter(sessionId, origin) {
|
|
341
|
+
if (!sessionId && !origin) {
|
|
342
|
+
throw new Error('sessionId or url is required');
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
function resolveUrlPrefixFromOrigin(origin) {
|
|
346
|
+
return origin.endsWith('/') ? origin : origin + '/';
|
|
347
|
+
}
|
|
348
|
+
function appendEventOriginFilter(where, params, origin) {
|
|
349
|
+
if (!origin) {
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
const prefix = resolveUrlPrefixFromOrigin(origin);
|
|
353
|
+
where.push(`
|
|
354
|
+
(
|
|
355
|
+
origin = ?
|
|
356
|
+
OR (
|
|
357
|
+
origin IS NULL AND (
|
|
358
|
+
json_extract(payload_json, '$.origin') = ?
|
|
359
|
+
OR json_extract(payload_json, '$.url') = ?
|
|
360
|
+
OR json_extract(payload_json, '$.url') LIKE ?
|
|
361
|
+
OR json_extract(payload_json, '$.to') = ?
|
|
362
|
+
OR json_extract(payload_json, '$.to') LIKE ?
|
|
363
|
+
OR json_extract(payload_json, '$.href') = ?
|
|
364
|
+
OR json_extract(payload_json, '$.href') LIKE ?
|
|
365
|
+
OR json_extract(payload_json, '$.location') = ?
|
|
366
|
+
OR json_extract(payload_json, '$.location') LIKE ?
|
|
367
|
+
)
|
|
368
|
+
)
|
|
369
|
+
)
|
|
370
|
+
`);
|
|
371
|
+
params.push(origin, origin, origin, `${prefix}%`, origin, `${prefix}%`, origin, `${prefix}%`, origin, `${prefix}%`);
|
|
372
|
+
}
|
|
373
|
+
function appendNetworkOriginFilter(where, params, origin) {
|
|
374
|
+
if (!origin) {
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
const prefix = resolveUrlPrefixFromOrigin(origin);
|
|
378
|
+
where.push('(origin = ? OR (origin IS NULL AND (url = ? OR url LIKE ?)))');
|
|
379
|
+
params.push(origin, origin, `${prefix}%`);
|
|
380
|
+
}
|
|
306
381
|
function resolveLastUrl(payload) {
|
|
307
382
|
const candidates = [payload.url, payload.to, payload.href, payload.location];
|
|
308
383
|
for (const candidate of candidates) {
|
|
@@ -313,12 +388,17 @@ function resolveLastUrl(payload) {
|
|
|
313
388
|
return undefined;
|
|
314
389
|
}
|
|
315
390
|
function mapEventRecord(row) {
|
|
391
|
+
const payload = readJsonPayload(row.payload_json);
|
|
316
392
|
return {
|
|
317
393
|
eventId: row.event_id,
|
|
318
394
|
sessionId: row.session_id,
|
|
319
395
|
timestamp: row.ts,
|
|
320
396
|
type: row.type,
|
|
321
|
-
|
|
397
|
+
tabId: row.tab_id ?? (typeof payload.tabId === 'number' ? payload.tabId : undefined),
|
|
398
|
+
origin: row.origin
|
|
399
|
+
?? (typeof payload.origin === 'string' ? payload.origin : undefined)
|
|
400
|
+
?? undefined,
|
|
401
|
+
payload,
|
|
322
402
|
};
|
|
323
403
|
}
|
|
324
404
|
function classifyNetworkFailure(status, errorClass) {
|
|
@@ -528,6 +608,26 @@ function asStringArray(value, maxItems) {
|
|
|
528
608
|
.filter((entry) => typeof entry === 'string' && entry.length > 0)
|
|
529
609
|
.slice(0, maxItems);
|
|
530
610
|
}
|
|
611
|
+
const LIVE_CONSOLE_LEVELS = new Set(['log', 'info', 'warn', 'error', 'debug', 'trace']);
|
|
612
|
+
function resolveLiveConsoleLevels(value) {
|
|
613
|
+
const levels = asStringArray(value, 16)
|
|
614
|
+
.map((entry) => entry.trim().toLowerCase())
|
|
615
|
+
.filter((entry) => LIVE_CONSOLE_LEVELS.has(entry));
|
|
616
|
+
return Array.from(new Set(levels));
|
|
617
|
+
}
|
|
618
|
+
function resolveOptionalTabId(value) {
|
|
619
|
+
if (value === undefined || value === null || value === '') {
|
|
620
|
+
return undefined;
|
|
621
|
+
}
|
|
622
|
+
if (typeof value !== 'number' || !Number.isFinite(value)) {
|
|
623
|
+
throw new Error('tabId must be an integer');
|
|
624
|
+
}
|
|
625
|
+
const tabId = Math.floor(value);
|
|
626
|
+
if (!Number.isInteger(tabId) || tabId < 0) {
|
|
627
|
+
throw new Error('tabId must be an integer');
|
|
628
|
+
}
|
|
629
|
+
return tabId;
|
|
630
|
+
}
|
|
531
631
|
function isLiveSessionDisconnectedMessage(message) {
|
|
532
632
|
const normalized = message.toLowerCase();
|
|
533
633
|
return normalized.includes('no active extension connection')
|
|
@@ -713,14 +813,18 @@ export function createV1ToolHandlers(getDb, getSessionConnectionState) {
|
|
|
713
813
|
get_recent_events: async (input) => {
|
|
714
814
|
const db = getDb();
|
|
715
815
|
const sessionId = getSessionId(input);
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
}
|
|
816
|
+
const origin = normalizeRequestedOrigin(input.url);
|
|
817
|
+
ensureSessionOrOriginFilter(sessionId, origin);
|
|
719
818
|
const limit = resolveLimit(input.limit, DEFAULT_EVENT_LIMIT);
|
|
720
819
|
const offset = resolveOffset(input.offset);
|
|
721
820
|
const requestedTypes = parseRequestedTypes(input.types ?? input.eventTypes);
|
|
722
|
-
const params = [
|
|
723
|
-
const where = [
|
|
821
|
+
const params = [];
|
|
822
|
+
const where = [];
|
|
823
|
+
if (sessionId) {
|
|
824
|
+
where.push('session_id = ?');
|
|
825
|
+
params.push(sessionId);
|
|
826
|
+
}
|
|
827
|
+
appendEventOriginFilter(where, params, origin);
|
|
724
828
|
if (requestedTypes.length > 0) {
|
|
725
829
|
const placeholders = requestedTypes.map(() => '?').join(', ');
|
|
726
830
|
where.push(`type IN (${placeholders})`);
|
|
@@ -728,7 +832,7 @@ export function createV1ToolHandlers(getDb, getSessionConnectionState) {
|
|
|
728
832
|
}
|
|
729
833
|
const rows = db
|
|
730
834
|
.prepare(`
|
|
731
|
-
SELECT event_id, session_id, ts, type, payload_json
|
|
835
|
+
SELECT event_id, session_id, ts, type, payload_json, tab_id, origin
|
|
732
836
|
FROM events
|
|
733
837
|
WHERE ${where.join(' AND ')}
|
|
734
838
|
ORDER BY ts DESC
|
|
@@ -752,20 +856,26 @@ export function createV1ToolHandlers(getDb, getSessionConnectionState) {
|
|
|
752
856
|
get_navigation_history: async (input) => {
|
|
753
857
|
const db = getDb();
|
|
754
858
|
const sessionId = getSessionId(input);
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
}
|
|
859
|
+
const origin = normalizeRequestedOrigin(input.url);
|
|
860
|
+
ensureSessionOrOriginFilter(sessionId, origin);
|
|
758
861
|
const limit = resolveLimit(input.limit, DEFAULT_EVENT_LIMIT);
|
|
759
862
|
const offset = resolveOffset(input.offset);
|
|
863
|
+
const params = [];
|
|
864
|
+
const where = ["type = 'nav'"];
|
|
865
|
+
if (sessionId) {
|
|
866
|
+
where.push('session_id = ?');
|
|
867
|
+
params.push(sessionId);
|
|
868
|
+
}
|
|
869
|
+
appendEventOriginFilter(where, params, origin);
|
|
760
870
|
const rows = db
|
|
761
871
|
.prepare(`
|
|
762
|
-
SELECT event_id, session_id, ts, type, payload_json
|
|
872
|
+
SELECT event_id, session_id, ts, type, payload_json, tab_id, origin
|
|
763
873
|
FROM events
|
|
764
|
-
WHERE
|
|
874
|
+
WHERE ${where.join(' AND ')}
|
|
765
875
|
ORDER BY ts DESC
|
|
766
876
|
LIMIT ? OFFSET ?
|
|
767
877
|
`)
|
|
768
|
-
.all(
|
|
878
|
+
.all(...params, limit + 1, offset);
|
|
769
879
|
const truncated = rows.length > limit;
|
|
770
880
|
return {
|
|
771
881
|
...createBaseResponse(sessionId),
|
|
@@ -783,23 +893,27 @@ export function createV1ToolHandlers(getDb, getSessionConnectionState) {
|
|
|
783
893
|
get_console_events: async (input) => {
|
|
784
894
|
const db = getDb();
|
|
785
895
|
const sessionId = getSessionId(input);
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
}
|
|
896
|
+
const origin = normalizeRequestedOrigin(input.url);
|
|
897
|
+
ensureSessionOrOriginFilter(sessionId, origin);
|
|
789
898
|
const level = typeof input.level === 'string' ? input.level : undefined;
|
|
790
899
|
const limit = resolveLimit(input.limit, DEFAULT_EVENT_LIMIT);
|
|
791
900
|
const offset = resolveOffset(input.offset);
|
|
792
|
-
const params = [
|
|
793
|
-
|
|
901
|
+
const params = [];
|
|
902
|
+
const where = ["type = 'console'"];
|
|
903
|
+
if (sessionId) {
|
|
904
|
+
where.push('session_id = ?');
|
|
905
|
+
params.push(sessionId);
|
|
906
|
+
}
|
|
907
|
+
appendEventOriginFilter(where, params, origin);
|
|
794
908
|
if (level) {
|
|
795
|
-
|
|
909
|
+
where.push("json_extract(payload_json, '$.level') = ?");
|
|
796
910
|
params.push(level);
|
|
797
911
|
}
|
|
798
912
|
const rows = db
|
|
799
913
|
.prepare(`
|
|
800
|
-
SELECT event_id, session_id, ts, type, payload_json
|
|
914
|
+
SELECT event_id, session_id, ts, type, payload_json, tab_id, origin
|
|
801
915
|
FROM events
|
|
802
|
-
WHERE
|
|
916
|
+
WHERE ${where.join(' AND ')}
|
|
803
917
|
ORDER BY ts DESC
|
|
804
918
|
LIMIT ? OFFSET ?
|
|
805
919
|
`)
|
|
@@ -871,6 +985,8 @@ export function createV1ToolHandlers(getDb, getSessionConnectionState) {
|
|
|
871
985
|
get_network_failures: async (input) => {
|
|
872
986
|
const db = getDb();
|
|
873
987
|
const sessionId = typeof input.sessionId === 'string' ? input.sessionId : undefined;
|
|
988
|
+
const origin = normalizeRequestedOrigin(input.url);
|
|
989
|
+
ensureSessionOrOriginFilter(sessionId, origin);
|
|
874
990
|
const groupBy = typeof input.groupBy === 'string' ? input.groupBy : undefined;
|
|
875
991
|
const errorType = typeof input.errorType === 'string' ? input.errorType : undefined;
|
|
876
992
|
const limit = resolveLimit(input.limit, DEFAULT_LIST_LIMIT);
|
|
@@ -882,6 +998,7 @@ export function createV1ToolHandlers(getDb, getSessionConnectionState) {
|
|
|
882
998
|
where.push('session_id = ?');
|
|
883
999
|
params.push(sessionId);
|
|
884
1000
|
}
|
|
1001
|
+
appendNetworkOriginFilter(where, params, origin);
|
|
885
1002
|
where.push(errorFilter);
|
|
886
1003
|
if (errorFilter === 'error_class = ?' && errorType) {
|
|
887
1004
|
params.push(errorType);
|
|
@@ -929,7 +1046,7 @@ export function createV1ToolHandlers(getDb, getSessionConnectionState) {
|
|
|
929
1046
|
}
|
|
930
1047
|
const rows = db
|
|
931
1048
|
.prepare(`
|
|
932
|
-
SELECT request_id, session_id, ts_start, duration_ms, method, url, status, initiator, error_class
|
|
1049
|
+
SELECT request_id, session_id, ts_start, duration_ms, method, url, origin, status, initiator, error_class
|
|
933
1050
|
FROM network
|
|
934
1051
|
${whereClause}
|
|
935
1052
|
ORDER BY ts_start DESC
|
|
@@ -954,6 +1071,7 @@ export function createV1ToolHandlers(getDb, getSessionConnectionState) {
|
|
|
954
1071
|
durationMs: row.duration_ms ?? undefined,
|
|
955
1072
|
method: row.method,
|
|
956
1073
|
url: row.url,
|
|
1074
|
+
origin: row.origin ?? undefined,
|
|
957
1075
|
status: row.status ?? undefined,
|
|
958
1076
|
initiator: row.initiator ?? undefined,
|
|
959
1077
|
errorType: classifyNetworkFailure(row.status, row.error_class),
|
|
@@ -974,7 +1092,7 @@ export function createV1ToolHandlers(getDb, getSessionConnectionState) {
|
|
|
974
1092
|
const offset = resolveOffset(input.offset);
|
|
975
1093
|
const rows = db
|
|
976
1094
|
.prepare(`
|
|
977
|
-
SELECT event_id, session_id, ts, type, payload_json
|
|
1095
|
+
SELECT event_id, session_id, ts, type, payload_json, tab_id, origin
|
|
978
1096
|
FROM events
|
|
979
1097
|
WHERE session_id = ?
|
|
980
1098
|
AND type IN ('ui', 'element_ref')
|
|
@@ -1008,7 +1126,7 @@ export function createV1ToolHandlers(getDb, getSessionConnectionState) {
|
|
|
1008
1126
|
const windowMs = lookbackSeconds * 1000;
|
|
1009
1127
|
const latestErrorEvent = db
|
|
1010
1128
|
.prepare(`
|
|
1011
|
-
SELECT event_id, session_id, ts, type, payload_json
|
|
1129
|
+
SELECT event_id, session_id, ts, type, payload_json, tab_id, origin
|
|
1012
1130
|
FROM events
|
|
1013
1131
|
WHERE session_id = ?
|
|
1014
1132
|
AND (type = 'error' OR (type = 'console' AND json_extract(payload_json, '$.level') = 'error'))
|
|
@@ -1018,7 +1136,7 @@ export function createV1ToolHandlers(getDb, getSessionConnectionState) {
|
|
|
1018
1136
|
.get(sessionId);
|
|
1019
1137
|
const latestNetworkFailure = db
|
|
1020
1138
|
.prepare(`
|
|
1021
|
-
SELECT request_id, session_id, ts_start, duration_ms, method, url, status, initiator, error_class
|
|
1139
|
+
SELECT request_id, session_id, ts_start, duration_ms, method, url, origin, status, initiator, error_class
|
|
1022
1140
|
FROM network
|
|
1023
1141
|
WHERE session_id = ?
|
|
1024
1142
|
AND (error_class IS NOT NULL OR COALESCE(status, 0) >= 400)
|
|
@@ -1046,7 +1164,7 @@ export function createV1ToolHandlers(getDb, getSessionConnectionState) {
|
|
|
1046
1164
|
const windowEnd = anchorTs + 1_000;
|
|
1047
1165
|
const eventRows = db
|
|
1048
1166
|
.prepare(`
|
|
1049
|
-
SELECT event_id, session_id, ts, type, payload_json
|
|
1167
|
+
SELECT event_id, session_id, ts, type, payload_json, tab_id, origin
|
|
1050
1168
|
FROM events
|
|
1051
1169
|
WHERE session_id = ?
|
|
1052
1170
|
AND ts BETWEEN ? AND ?
|
|
@@ -1055,7 +1173,7 @@ export function createV1ToolHandlers(getDb, getSessionConnectionState) {
|
|
|
1055
1173
|
.all(sessionId, windowStart, windowEnd);
|
|
1056
1174
|
const networkRows = db
|
|
1057
1175
|
.prepare(`
|
|
1058
|
-
SELECT request_id, session_id, ts_start, duration_ms, method, url, status, initiator, error_class
|
|
1176
|
+
SELECT request_id, session_id, ts_start, duration_ms, method, url, origin, status, initiator, error_class
|
|
1059
1177
|
FROM network
|
|
1060
1178
|
WHERE session_id = ?
|
|
1061
1179
|
AND ts_start BETWEEN ? AND ?
|
|
@@ -1138,7 +1256,7 @@ export function createV1ToolHandlers(getDb, getSessionConnectionState) {
|
|
|
1138
1256
|
}
|
|
1139
1257
|
const anchorEvent = db
|
|
1140
1258
|
.prepare(`
|
|
1141
|
-
SELECT event_id, session_id, ts, type, payload_json
|
|
1259
|
+
SELECT event_id, session_id, ts, type, payload_json, tab_id, origin
|
|
1142
1260
|
FROM events
|
|
1143
1261
|
WHERE session_id = ? AND event_id = ?
|
|
1144
1262
|
LIMIT 1
|
|
@@ -1153,7 +1271,7 @@ export function createV1ToolHandlers(getDb, getSessionConnectionState) {
|
|
|
1153
1271
|
const windowEnd = anchorEvent.ts + windowMs;
|
|
1154
1272
|
const nearbyEvents = db
|
|
1155
1273
|
.prepare(`
|
|
1156
|
-
SELECT event_id, session_id, ts, type, payload_json
|
|
1274
|
+
SELECT event_id, session_id, ts, type, payload_json, tab_id, origin
|
|
1157
1275
|
FROM events
|
|
1158
1276
|
WHERE session_id = ?
|
|
1159
1277
|
AND event_id != ?
|
|
@@ -1162,7 +1280,7 @@ export function createV1ToolHandlers(getDb, getSessionConnectionState) {
|
|
|
1162
1280
|
.all(sessionId, eventId, windowStart, windowEnd);
|
|
1163
1281
|
const nearbyNetworkFailures = db
|
|
1164
1282
|
.prepare(`
|
|
1165
|
-
SELECT request_id, session_id, ts_start, duration_ms, method, url, status, initiator, error_class
|
|
1283
|
+
SELECT request_id, session_id, ts_start, duration_ms, method, url, origin, status, initiator, error_class
|
|
1166
1284
|
FROM network
|
|
1167
1285
|
WHERE session_id = ?
|
|
1168
1286
|
AND ts_start BETWEEN ? AND ?
|
|
@@ -1551,6 +1669,38 @@ export function createV2ToolHandlers(captureClient) {
|
|
|
1551
1669
|
...ensureCaptureSuccess(capture, sessionId),
|
|
1552
1670
|
};
|
|
1553
1671
|
},
|
|
1672
|
+
get_live_console_logs: async (input) => {
|
|
1673
|
+
const sessionId = getSessionId(input);
|
|
1674
|
+
if (!sessionId) {
|
|
1675
|
+
throw new Error('sessionId is required');
|
|
1676
|
+
}
|
|
1677
|
+
const origin = normalizeRequestedOrigin(input.url);
|
|
1678
|
+
const tabId = resolveOptionalTabId(input.tabId);
|
|
1679
|
+
const levels = resolveLiveConsoleLevels(input.levels);
|
|
1680
|
+
const contains = typeof input.contains === 'string' && input.contains.trim().length > 0
|
|
1681
|
+
? input.contains.trim()
|
|
1682
|
+
: undefined;
|
|
1683
|
+
const sinceTs = resolveOptionalTimestamp(input.sinceTs);
|
|
1684
|
+
const includeRuntimeErrors = input.includeRuntimeErrors !== false;
|
|
1685
|
+
const limit = resolveLimit(input.limit, DEFAULT_EVENT_LIMIT);
|
|
1686
|
+
const capture = await executeLiveCapture(captureClient, sessionId, 'CAPTURE_GET_LIVE_CONSOLE_LOGS', {
|
|
1687
|
+
origin,
|
|
1688
|
+
tabId,
|
|
1689
|
+
levels,
|
|
1690
|
+
contains,
|
|
1691
|
+
sinceTs,
|
|
1692
|
+
includeRuntimeErrors,
|
|
1693
|
+
limit,
|
|
1694
|
+
}, 3_000);
|
|
1695
|
+
return {
|
|
1696
|
+
...createBaseResponse(sessionId),
|
|
1697
|
+
limitsApplied: {
|
|
1698
|
+
maxResults: limit,
|
|
1699
|
+
truncated: capture.truncated ?? false,
|
|
1700
|
+
},
|
|
1701
|
+
...ensureCaptureSuccess(capture, sessionId),
|
|
1702
|
+
};
|
|
1703
|
+
},
|
|
1554
1704
|
};
|
|
1555
1705
|
}
|
|
1556
1706
|
function isRecord(value) {
|