@saptools/cf-inspector 0.4.12 → 0.5.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/dist/index.js CHANGED
@@ -474,37 +474,65 @@ async function removeBreakpoint(session, breakpointId) {
474
474
  // src/inspector/discovery.ts
475
475
  init_types();
476
476
  import { request } from "http";
477
+ import { performance } from "perf_hooks";
478
+ var InvalidDiscoveryPayloadError = class extends CfInspectorError {
479
+ };
477
480
  async function fetchJson(url, timeoutMs) {
478
- return await new Promise((resolve, reject) => {
479
- const req = request(url, { method: "GET" }, (res) => {
480
- const chunks = [];
481
- res.on("data", (chunk) => {
482
- chunks.push(chunk);
483
- });
484
- res.on("end", () => {
485
- try {
486
- resolve(parseJsonResponse(chunks));
487
- } catch (err) {
488
- reject(parseDiscoveryError(url, err));
489
- }
490
- });
491
- res.on("error", (err) => {
492
- reject(newDiscoveryError(`Inspector discovery response error: ${err.message}`));
481
+ const deadline = performance.now() + timeoutMs;
482
+ let lastError;
483
+ while (performance.now() < deadline) {
484
+ try {
485
+ const remainingMs = deadline - performance.now();
486
+ if (remainingMs <= 0) {
487
+ break;
488
+ }
489
+ return await new Promise((resolve, reject) => {
490
+ const req = request(url, { method: "GET" }, (res) => {
491
+ const chunks = [];
492
+ res.on("data", (chunk) => {
493
+ chunks.push(chunk);
494
+ });
495
+ res.on("end", () => {
496
+ try {
497
+ resolve(parseJsonResponse(chunks));
498
+ } catch (err) {
499
+ reject(parseDiscoveryError(url, err));
500
+ }
501
+ });
502
+ res.on("error", (err) => {
503
+ reject(newDiscoveryError(`Inspector discovery response error: ${err.message}`));
504
+ });
505
+ });
506
+ const attemptTimeoutMs = Math.min(2e3, remainingMs);
507
+ req.setTimeout(attemptTimeoutMs, () => {
508
+ req.destroy(
509
+ new CfInspectorError(
510
+ "INSPECTOR_DISCOVERY_FAILED",
511
+ `Inspector discovery at ${url} timed out after ${timeoutMs.toString()}ms`
512
+ )
513
+ );
514
+ });
515
+ req.on("error", (err) => {
516
+ reject(err instanceof CfInspectorError ? err : formatDiscoveryRequestError(url, err));
517
+ });
518
+ req.end();
493
519
  });
494
- });
495
- req.setTimeout(timeoutMs, () => {
496
- req.destroy(
497
- new CfInspectorError(
498
- "INSPECTOR_DISCOVERY_FAILED",
499
- `Inspector discovery at ${url} timed out after ${timeoutMs.toString()}ms`
500
- )
501
- );
502
- });
503
- req.on("error", (err) => {
504
- reject(err instanceof CfInspectorError ? err : formatDiscoveryRequestError(url, err));
505
- });
506
- req.end();
507
- });
520
+ } catch (err) {
521
+ if (err instanceof InvalidDiscoveryPayloadError) {
522
+ throw err;
523
+ }
524
+ lastError = err;
525
+ const now = performance.now();
526
+ if (now < deadline) {
527
+ const sleepMs = Math.min(1e3, deadline - now);
528
+ await new Promise((r) => setTimeout(r, sleepMs));
529
+ }
530
+ }
531
+ }
532
+ if (lastError instanceof Error) {
533
+ throw lastError;
534
+ }
535
+ throw new CfInspectorError("INSPECTOR_DISCOVERY_FAILED", `Inspector discovery at ${url} timed out after ${timeoutMs.toString()}ms`);
508
536
  }
509
537
  function isNodeSystemError(err) {
510
538
  return err instanceof Error;
@@ -540,7 +568,10 @@ function parseJsonResponse(chunks) {
540
568
  }
541
569
  function parseDiscoveryError(url, err) {
542
570
  const message = err instanceof Error ? err.message : String(err);
543
- return newDiscoveryError(`Failed to parse inspector discovery response from ${url}: ${message}`);
571
+ return new InvalidDiscoveryPayloadError(
572
+ "INSPECTOR_DISCOVERY_FAILED",
573
+ `Failed to parse inspector discovery response from ${url}: ${message}`
574
+ );
544
575
  }
545
576
  function newDiscoveryError(message) {
546
577
  return new CfInspectorError("INSPECTOR_DISCOVERY_FAILED", message);
@@ -614,7 +645,7 @@ async function fetchInspectorVersion(host, port, timeoutMs) {
614
645
 
615
646
  // src/inspector/pause.ts
616
647
  init_types();
617
- import { performance } from "perf_hooks";
648
+ import { performance as performance2 } from "perf_hooks";
618
649
  function pauseMatches(pause, breakpointIds, pauseReasons) {
619
650
  if (pauseReasons !== void 0 && pauseReasons.length > 0) {
620
651
  return pauseReasons.includes(pause.reason);
@@ -625,7 +656,7 @@ function pauseMatches(pause, breakpointIds, pauseReasons) {
625
656
  return pause.hitBreakpoints.some((id) => breakpointIds.includes(id));
626
657
  }
627
658
  function remainingUntil(deadlineMs) {
628
- return Math.max(0, deadlineMs - performance.now());
659
+ return Math.max(0, deadlineMs - performance2.now());
629
660
  }
630
661
  function hasResumedSincePause(session, pause) {
631
662
  const pauseAt = pause.receivedAtMs;
@@ -655,7 +686,7 @@ async function waitForUnmatchedPauseToResume(session, pause, deadlineMs, timeout
655
686
  }
656
687
  try {
657
688
  await session.client.waitFor("Debugger.resumed", { timeoutMs: remainingMs });
658
- session.debuggerState.lastResumedAtMs = performance.now();
689
+ session.debuggerState.lastResumedAtMs = performance2.now();
659
690
  } catch (err) {
660
691
  if (err instanceof CfInspectorError && err.code === "BREAKPOINT_NOT_HIT") {
661
692
  throwUnrelatedPauseTimeout(pause, timeoutMs);
@@ -678,7 +709,7 @@ async function handleUnmatchedPause(session, pause, options, deadlineMs) {
678
709
  await waitForUnmatchedPauseToResume(session, pause, deadlineMs, options.timeoutMs);
679
710
  }
680
711
  async function waitForPause(session, options) {
681
- const deadlineMs = performance.now() + options.timeoutMs;
712
+ const deadlineMs = performance2.now() + options.timeoutMs;
682
713
  const buffer = session.pauseBuffer;
683
714
  while (buffer.length > 0 || remainingUntil(deadlineMs) > 0) {
684
715
  while (buffer.length > 0) {
@@ -711,14 +742,14 @@ async function waitForLivePause(session, options, deadlineMs) {
711
742
  params = await session.client.waitFor("Debugger.paused", {
712
743
  timeoutMs: remainingMs,
713
744
  predicate: () => {
714
- receivedAtMs = performance.now();
745
+ receivedAtMs = performance2.now();
715
746
  return true;
716
747
  }
717
748
  });
718
749
  } finally {
719
750
  session.pauseWaitGate.active = false;
720
751
  }
721
- return toPauseEvent(params, receivedAtMs ?? performance.now(), session.scripts);
752
+ return toPauseEvent(params, receivedAtMs ?? performance2.now(), session.scripts);
722
753
  }
723
754
 
724
755
  // src/inspector/runtime.ts
@@ -729,15 +760,30 @@ async function resume(session) {
729
760
  async function setPauseOnExceptions(session, state) {
730
761
  await session.client.send("Debugger.setPauseOnExceptions", { state });
731
762
  }
732
- async function evaluateOnFrame(session, callFrameId, expression) {
763
+ async function evaluateOnFrame(session, callFrameId, expression, options = {}) {
733
764
  return await session.client.send("Debugger.evaluateOnCallFrame", {
734
765
  callFrameId,
735
766
  expression,
736
767
  returnByValue: false,
737
768
  generatePreview: true,
738
- silent: true
769
+ silent: true,
770
+ ...options.throwOnSideEffect === void 0 ? {} : { throwOnSideEffect: options.throwOnSideEffect }
739
771
  });
740
772
  }
773
+ function isSideEffectRefusal(result) {
774
+ const classNames = [
775
+ result.result?.className,
776
+ result.exceptionDetails?.exception?.className
777
+ ];
778
+ const descriptions = [
779
+ result.result?.description,
780
+ result.exceptionDetails?.exception?.description
781
+ ];
782
+ const isEvalError = classNames.includes("EvalError");
783
+ return isEvalError && descriptions.some(
784
+ (description) => typeof description === "string" && description.toLowerCase().includes("possible side-effect in debug-evaluate")
785
+ );
786
+ }
741
787
  async function evaluateGlobal(session, expression) {
742
788
  return await session.client.send("Runtime.evaluate", {
743
789
  expression,
@@ -789,7 +835,7 @@ async function getProperties(session, objectId) {
789
835
  }
790
836
 
791
837
  // src/inspector/session.ts
792
- import { performance as performance2 } from "perf_hooks";
838
+ import { performance as performance3 } from "perf_hooks";
793
839
 
794
840
  // src/cdp/client.ts
795
841
  init_types();
@@ -1031,12 +1077,203 @@ var CdpClient = class _CdpClient {
1031
1077
  this.emitter.removeAllListeners();
1032
1078
  }
1033
1079
  };
1080
+ var NodeWorkerTransport = class {
1081
+ constructor(parent, sessionId) {
1082
+ this.parent = parent;
1083
+ this.sessionId = sessionId;
1084
+ this.detachParentListeners = [
1085
+ parent.on("NodeWorker.receivedMessageFromWorker", (raw) => {
1086
+ this.forwardWorkerMessage(raw);
1087
+ }),
1088
+ parent.on("NodeWorker.detachedFromWorker", (raw) => {
1089
+ this.handleWorkerDetach(raw);
1090
+ }),
1091
+ parent.onClose((error) => {
1092
+ this.closeWithError(error);
1093
+ })
1094
+ ];
1095
+ }
1096
+ parent;
1097
+ sessionId;
1098
+ emitter = new EventEmitter();
1099
+ detachParentListeners;
1100
+ readyState = 1;
1101
+ send(payload) {
1102
+ if (this.readyState !== 1) {
1103
+ throw new CfInspectorError("INSPECTOR_CONNECTION_FAILED", "Worker inspector session is closed");
1104
+ }
1105
+ void this.parent.send("NodeWorker.sendMessageToWorker", {
1106
+ sessionId: this.sessionId,
1107
+ message: payload
1108
+ }).catch((error) => {
1109
+ const normalized = error instanceof Error ? error : new Error(String(error));
1110
+ this.closeWithError(normalized);
1111
+ });
1112
+ }
1113
+ close() {
1114
+ this.finishClose();
1115
+ }
1116
+ on(event, listener) {
1117
+ this.emitter.on(event, listener);
1118
+ }
1119
+ off(event, listener) {
1120
+ this.emitter.off(event, listener);
1121
+ }
1122
+ forwardWorkerMessage(raw) {
1123
+ const params = asNodeWorkerEventParams(raw);
1124
+ if (params.sessionId !== this.sessionId || typeof params.message !== "string") {
1125
+ return;
1126
+ }
1127
+ this.emitter.emit("message", params.message);
1128
+ }
1129
+ handleWorkerDetach(raw) {
1130
+ const params = asNodeWorkerEventParams(raw);
1131
+ if (params.sessionId === this.sessionId) {
1132
+ this.finishClose();
1133
+ }
1134
+ }
1135
+ closeWithError(error) {
1136
+ if (this.readyState !== 1) {
1137
+ return;
1138
+ }
1139
+ this.emitter.emit("error", error);
1140
+ this.finishClose();
1141
+ }
1142
+ finishClose() {
1143
+ if (this.readyState !== 1) {
1144
+ return;
1145
+ }
1146
+ this.readyState = 3;
1147
+ for (const detach of this.detachParentListeners) {
1148
+ detach();
1149
+ }
1150
+ this.emitter.emit("close");
1151
+ this.emitter.removeAllListeners();
1152
+ }
1153
+ };
1154
+ function asNodeWorkerEventParams(raw) {
1155
+ if (!isUnknownRecord(raw)) {
1156
+ return {};
1157
+ }
1158
+ const sessionId = raw["sessionId"];
1159
+ const message = raw["message"];
1160
+ return {
1161
+ ...typeof sessionId === "string" ? { sessionId } : {},
1162
+ ...typeof message === "string" ? { message } : {}
1163
+ };
1164
+ }
1165
+ function isUnknownRecord(value) {
1166
+ return typeof value === "object" && value !== null;
1167
+ }
1168
+ async function createNodeWorkerClient(parent, sessionId, requestTimeoutMs = DEFAULT_REQUEST_TIMEOUT_MS) {
1169
+ const transport = new NodeWorkerTransport(parent, sessionId);
1170
+ return await CdpClient.connect({
1171
+ url: `node-worker://${sessionId}`,
1172
+ transportFactory: () => Promise.resolve(transport),
1173
+ requestTimeoutMs
1174
+ });
1175
+ }
1034
1176
 
1035
1177
  // src/inspector/session.ts
1036
1178
  init_types();
1037
1179
  var DEFAULT_CONNECT_TIMEOUT_MS = 5e3;
1038
1180
  var DEFAULT_HOST = "127.0.0.1";
1039
1181
  var PAUSE_BUFFER_LIMIT = 32;
1182
+ var NodeWorkerDiscovery = class {
1183
+ constructor(client) {
1184
+ this.client = client;
1185
+ this.detachListeners = [
1186
+ client.on("NodeWorker.attachedToWorker", (raw) => {
1187
+ const worker = toInspectorWorkerTarget(raw);
1188
+ if (worker !== void 0) {
1189
+ this.workers.set(worker.sessionId, worker);
1190
+ }
1191
+ }),
1192
+ client.on("NodeWorker.detachedFromWorker", (raw) => {
1193
+ const sessionId = readField(raw, "sessionId");
1194
+ if (typeof sessionId === "string") {
1195
+ this.workers.delete(sessionId);
1196
+ }
1197
+ })
1198
+ ];
1199
+ }
1200
+ client;
1201
+ workers = /* @__PURE__ */ new Map();
1202
+ detachListeners;
1203
+ supported = false;
1204
+ disposed = false;
1205
+ async enable() {
1206
+ try {
1207
+ await this.client.send("NodeWorker.enable", { waitForDebuggerOnStart: false });
1208
+ this.supported = true;
1209
+ } catch (error) {
1210
+ if (!isUnsupportedNodeWorkerDomain(error)) {
1211
+ throw error;
1212
+ }
1213
+ }
1214
+ }
1215
+ list() {
1216
+ return [...this.workers.values()].sort(compareWorkers);
1217
+ }
1218
+ async dispose() {
1219
+ if (this.disposed) {
1220
+ return;
1221
+ }
1222
+ this.disposed = true;
1223
+ if (this.supported && !this.client.isClosed) {
1224
+ try {
1225
+ await this.client.send("NodeWorker.disable");
1226
+ } catch {
1227
+ }
1228
+ }
1229
+ for (const detach of this.detachListeners) {
1230
+ detach();
1231
+ }
1232
+ }
1233
+ };
1234
+ function isUnsupportedNodeWorkerDomain(error) {
1235
+ if (!(error instanceof CfInspectorError) || error.code !== "CDP_REQUEST_FAILED") {
1236
+ return false;
1237
+ }
1238
+ return error.detail?.includes('"code":-32601') === true;
1239
+ }
1240
+ function compareWorkers(left, right) {
1241
+ const leftId = Number.parseInt(left.workerId, 10);
1242
+ const rightId = Number.parseInt(right.workerId, 10);
1243
+ if (!Number.isNaN(leftId) && !Number.isNaN(rightId) && leftId !== rightId) {
1244
+ return leftId - rightId;
1245
+ }
1246
+ return left.workerId.localeCompare(right.workerId);
1247
+ }
1248
+ function toInspectorWorkerTarget(raw) {
1249
+ const sessionId = readField(raw, "sessionId");
1250
+ const info = readField(raw, "workerInfo");
1251
+ if (typeof sessionId !== "string" || !isUnknownRecord2(info)) {
1252
+ return void 0;
1253
+ }
1254
+ const workerId = asString(info["workerId"]);
1255
+ if (workerId.length === 0) {
1256
+ return void 0;
1257
+ }
1258
+ return {
1259
+ sessionId,
1260
+ workerId,
1261
+ type: asString(info["type"]),
1262
+ title: asString(info["title"]),
1263
+ url: asString(info["url"])
1264
+ };
1265
+ }
1266
+ function readField(value, name) {
1267
+ return isUnknownRecord2(value) ? value[name] : void 0;
1268
+ }
1269
+ function isUnknownRecord2(value) {
1270
+ return typeof value === "object" && value !== null;
1271
+ }
1272
+ async function startNodeWorkerDiscovery(client) {
1273
+ const discovery = new NodeWorkerDiscovery(client);
1274
+ await discovery.enable();
1275
+ return discovery;
1276
+ }
1040
1277
  async function connectInspector(options) {
1041
1278
  const host = options.host ?? DEFAULT_HOST;
1042
1279
  const connectTimeoutMs = options.connectTimeoutMs ?? DEFAULT_CONNECT_TIMEOUT_MS;
@@ -1053,13 +1290,70 @@ async function connectInspector(options) {
1053
1290
  url: target.webSocketDebuggerUrl,
1054
1291
  connectTimeoutMs
1055
1292
  });
1293
+ let workerDiscovery;
1056
1294
  try {
1057
- return await initSession(client, target);
1295
+ workerDiscovery = await startNodeWorkerDiscovery(client);
1296
+ if (options.workerIndex === void 0) {
1297
+ const session = await initSession(client, target);
1298
+ return withWorkerMetadata(session, workerDiscovery, targetIndex, targets.length);
1299
+ }
1300
+ return await initWorkerSession(
1301
+ client,
1302
+ workerDiscovery,
1303
+ options.workerIndex,
1304
+ targetIndex,
1305
+ targets.length
1306
+ );
1058
1307
  } catch (err) {
1308
+ await workerDiscovery?.dispose();
1059
1309
  client.dispose();
1060
1310
  throw err;
1061
1311
  }
1062
1312
  }
1313
+ async function initWorkerSession(parent, discovery, workerIndex, targetIndex, targetCount) {
1314
+ const workers = discovery.list();
1315
+ if (!discovery.supported) {
1316
+ throw new CfInspectorError(
1317
+ "INSPECTOR_DISCOVERY_FAILED",
1318
+ "This runtime does not expose the NodeWorker CDP domain; --worker cannot be used. Run list-targets for available raw targets."
1319
+ );
1320
+ }
1321
+ const worker = workers[workerIndex];
1322
+ if (worker === void 0) {
1323
+ throw new CfInspectorError(
1324
+ "INSPECTOR_DISCOVERY_FAILED",
1325
+ `No NodeWorker sub-session at index ${workerIndex.toString()} (available: ${workers.length.toString()}). Ensure the worker is alive, then rerun list-targets.`
1326
+ );
1327
+ }
1328
+ const client = await createNodeWorkerClient(parent, worker.sessionId);
1329
+ const session = await initSession(client, workerToInspectorTarget(worker));
1330
+ return withWorkerMetadata(session, discovery, targetIndex, targetCount, workerIndex, parent);
1331
+ }
1332
+ function withWorkerMetadata(session, discovery, targetIndex, targetCount, workerIndex, parent) {
1333
+ return {
1334
+ ...session,
1335
+ targetIndex,
1336
+ targetCount,
1337
+ ...workerIndex === void 0 ? {} : { workerIndex },
1338
+ workerTargets: discovery.list(),
1339
+ workerDiscoverySupported: discovery.supported,
1340
+ dispose: async () => {
1341
+ await session.dispose();
1342
+ await discovery.dispose();
1343
+ parent?.dispose();
1344
+ }
1345
+ };
1346
+ }
1347
+ function workerToInspectorTarget(worker) {
1348
+ return {
1349
+ description: "Node worker sub-session",
1350
+ id: worker.workerId,
1351
+ title: worker.title,
1352
+ type: worker.type,
1353
+ url: worker.url,
1354
+ webSocketDebuggerUrl: `node-worker://${worker.sessionId}`
1355
+ };
1356
+ }
1063
1357
  async function initSession(client, target) {
1064
1358
  const scripts = /* @__PURE__ */ new Map();
1065
1359
  client.on("Debugger.scriptParsed", (raw) => {
@@ -1079,14 +1373,14 @@ async function initSession(client, target) {
1079
1373
  return;
1080
1374
  }
1081
1375
  const params = raw;
1082
- const event = toPauseEvent(params, performance2.now(), scripts);
1376
+ const event = toPauseEvent(params, performance3.now(), scripts);
1083
1377
  if (pauseBuffer.length >= PAUSE_BUFFER_LIMIT) {
1084
1378
  pauseBuffer.shift();
1085
1379
  }
1086
1380
  pauseBuffer.push(event);
1087
1381
  });
1088
1382
  client.on("Debugger.resumed", () => {
1089
- debuggerState.lastResumedAtMs = performance2.now();
1383
+ debuggerState.lastResumedAtMs = performance3.now();
1090
1384
  });
1091
1385
  await client.send("Runtime.enable");
1092
1386
  await client.send("Debugger.enable");
@@ -1107,9 +1401,61 @@ async function initSession(client, target) {
1107
1401
  };
1108
1402
  }
1109
1403
 
1404
+ // src/cli/captureParser.ts
1405
+ function isQuoteChar(value) {
1406
+ return value === "'" || value === '"' || value === "`";
1407
+ }
1408
+ function consumeQuotedChar(state, char) {
1409
+ if (state.quote === void 0) {
1410
+ return false;
1411
+ }
1412
+ if (state.escaped) {
1413
+ state.escaped = false;
1414
+ return true;
1415
+ }
1416
+ if (char === "\\") {
1417
+ state.escaped = true;
1418
+ return true;
1419
+ }
1420
+ if (char === state.quote) {
1421
+ state.quote = void 0;
1422
+ }
1423
+ return true;
1424
+ }
1425
+ function stripQuotedText(expression) {
1426
+ const state = { quote: void 0, escaped: false };
1427
+ let stripped = "";
1428
+ for (const char of expression) {
1429
+ if (consumeQuotedChar(state, char)) {
1430
+ stripped += " ";
1431
+ continue;
1432
+ }
1433
+ if (isQuoteChar(char)) {
1434
+ state.quote = char;
1435
+ stripped += " ";
1436
+ continue;
1437
+ }
1438
+ stripped += char;
1439
+ }
1440
+ return stripped;
1441
+ }
1442
+ function looksLikeMutation(expression) {
1443
+ const stripped = stripQuotedText(expression);
1444
+ const hasUpdate = /(?:\+\+|--)/u.test(stripped);
1445
+ const hasAssignment = /(?:\*\*=|&&=|\|\|=|\?\?=|[+\-*/%&|^]=|(?:^|[^=!<>])=(?!=|>))/u.test(stripped);
1446
+ const hasDelete = /\bdelete\b/u.test(stripped);
1447
+ const hasMutatingMethod = /\.\s*(?:push|pop|shift|unshift|splice|sort|reverse|fill|copyWithin|set|add|delete|clear)\s*\(/u.test(stripped);
1448
+ const hasObjectMutation = /\bObject\s*\.\s*(?:assign|defineProperty|defineProperties)\s*\(/u.test(stripped);
1449
+ return hasUpdate || hasAssignment || hasDelete || hasMutatingMethod || hasObjectMutation;
1450
+ }
1451
+
1452
+ // src/snapshot/evaluation.ts
1453
+ init_types();
1454
+
1110
1455
  // src/snapshot/values.ts
1111
1456
  init_types();
1112
- var DEFAULT_MAX_VALUE_LENGTH = 4096;
1457
+ var DEFAULT_MAX_VALUE_LENGTH = 131072;
1458
+ var DEFAULT_STREAM_MAX_VALUE_LENGTH = 4096;
1113
1459
  function isPrimitive(value) {
1114
1460
  const t = typeof value;
1115
1461
  return t === "string" || t === "number" || t === "boolean" || t === "bigint" || t === "symbol";
@@ -1137,9 +1483,16 @@ function resolveMaxValueLength(value) {
1137
1483
  }
1138
1484
  function limitValueLength(raw, maxValueLength = DEFAULT_MAX_VALUE_LENGTH) {
1139
1485
  if (raw.length <= maxValueLength) {
1140
- return raw;
1486
+ return { text: raw, truncated: false };
1141
1487
  }
1142
- return `${raw.slice(0, maxValueLength)}...`;
1488
+ return {
1489
+ text: raw.slice(0, maxValueLength),
1490
+ truncated: true,
1491
+ originalLength: raw.length
1492
+ };
1493
+ }
1494
+ function textTruncationFields(limited) {
1495
+ return limited.truncated ? { truncated: true, originalLength: limited.originalLength } : {};
1143
1496
  }
1144
1497
  function parseQuotedString(value) {
1145
1498
  try {
@@ -1224,7 +1577,12 @@ function toStructuredValue(variable) {
1224
1577
  // src/snapshot/evaluation.ts
1225
1578
  function evalResultToCaptured(expression, result, maxValueLength = DEFAULT_MAX_VALUE_LENGTH) {
1226
1579
  if (result.exceptionDetails !== void 0) {
1227
- return { expression, error: readEvalError(result, maxValueLength) };
1580
+ const limited = readEvalError(result, maxValueLength);
1581
+ return {
1582
+ expression,
1583
+ error: limited.text,
1584
+ ...textTruncationFields(limited)
1585
+ };
1228
1586
  }
1229
1587
  const inner = result.result;
1230
1588
  if (!inner) {
@@ -1232,8 +1590,12 @@ function evalResultToCaptured(expression, result, maxValueLength = DEFAULT_MAX_V
1232
1590
  }
1233
1591
  const type = typeof inner.type === "string" ? inner.type : void 0;
1234
1592
  const buildCaptured = (rendered) => {
1235
- const sanitized = limitValueLength(rendered, maxValueLength);
1236
- const base = { expression, value: sanitized };
1593
+ const limited = limitValueLength(rendered, maxValueLength);
1594
+ const base = {
1595
+ expression,
1596
+ value: limited.text,
1597
+ ...textTruncationFields(limited)
1598
+ };
1237
1599
  return type === void 0 ? base : { ...base, type };
1238
1600
  };
1239
1601
  if (type === "string" && typeof inner.value === "string") {
@@ -1250,6 +1612,18 @@ function evalResultToCaptured(expression, result, maxValueLength = DEFAULT_MAX_V
1250
1612
  }
1251
1613
  return buildCaptured("undefined");
1252
1614
  }
1615
+ function sideEffectRefusalToCaptured(expression) {
1616
+ const error = new CfInspectorError(
1617
+ "MUTATION_NOT_ALLOWED",
1618
+ `V8 blocked the capture expression "${expression}" because it may have side effects. Pass --allow-mutation to run it explicitly.`
1619
+ );
1620
+ return {
1621
+ expression,
1622
+ error: `${error.code}: ${error.message}`,
1623
+ mutationRisk: true,
1624
+ blocked: true
1625
+ };
1626
+ }
1253
1627
  function readEvalError(result, maxValueLength) {
1254
1628
  const text = typeof result.exceptionDetails?.exception?.description === "string" ? result.exceptionDetails.exception.description : typeof result.exceptionDetails?.text === "string" ? result.exceptionDetails.text : "evaluation failed";
1255
1629
  return limitValueLength(text, maxValueLength);
@@ -1307,56 +1681,88 @@ async function captureProperties(session, objectId, limit, depth, maxValueLength
1307
1681
  return await captureProperty(session, prop, depth, maxValueLength);
1308
1682
  })
1309
1683
  );
1310
- return variables;
1684
+ const omittedCount = Math.max(properties.length - limited.length, 0);
1685
+ return omittedCount === 0 ? { variables } : { variables, omittedCount };
1311
1686
  }
1312
1687
  async function captureProperty(session, prop, depth, maxValueLength) {
1313
1688
  const name = typeof prop.name === "string" ? prop.name : "?";
1314
1689
  const described = describeProperty(prop);
1315
- const children = await capturePropertyChildren(session, described, depth, maxValueLength);
1316
- const sanitizedValue = limitValueLength(described.value, maxValueLength);
1317
- const base = { name, value: sanitizedValue };
1690
+ const capturedChildren = await capturePropertyChildren(
1691
+ session,
1692
+ described,
1693
+ depth,
1694
+ maxValueLength
1695
+ );
1696
+ const limited = limitValueLength(described.value, maxValueLength);
1697
+ const base = {
1698
+ name,
1699
+ value: limited.text,
1700
+ ...textTruncationFields(limited)
1701
+ };
1318
1702
  const withType = described.type === void 0 ? base : { ...base, type: described.type };
1319
- return children === void 0 ? withType : { ...withType, children };
1703
+ const children = capturedChildren?.variables;
1704
+ const withChildren = children === void 0 || children.length === 0 ? withType : { ...withType, children };
1705
+ const omittedCount = capturedChildren?.omittedCount ?? 0;
1706
+ return omittedCount === 0 ? withChildren : { ...withChildren, truncated: true, omittedCount };
1320
1707
  }
1321
1708
  async function capturePropertyChildren(session, described, depth, maxValueLength) {
1322
- if (depth <= 0 || described.objectId === void 0 || !isExpandable(described.type)) {
1709
+ if (described.objectId === void 0 || !isExpandable(described.type)) {
1323
1710
  return void 0;
1324
1711
  }
1712
+ if (depth <= 0) {
1713
+ return await countDepthOmissions(session, described.objectId);
1714
+ }
1325
1715
  try {
1326
- const nested = await captureProperties(
1716
+ return await captureProperties(
1327
1717
  session,
1328
1718
  described.objectId,
1329
1719
  MAX_CHILD_VARIABLES,
1330
1720
  depth - 1,
1331
1721
  maxValueLength
1332
1722
  );
1333
- return nested.length > 0 ? nested : void 0;
1334
1723
  } catch {
1335
1724
  return void 0;
1336
1725
  }
1337
1726
  }
1727
+ async function countDepthOmissions(session, objectId) {
1728
+ try {
1729
+ const properties = await getProperties(session, objectId);
1730
+ return properties.length === 0 ? void 0 : { variables: [], omittedCount: properties.length };
1731
+ } catch {
1732
+ return void 0;
1733
+ }
1734
+ }
1735
+ function countPropertyOmissions(captured) {
1736
+ return (captured.omittedCount ?? 0) + captured.variables.reduce((total, variable) => {
1737
+ const childOmissions = variable.children === void 0 ? 0 : countPropertyOmissions({ variables: variable.children });
1738
+ return total + (variable.omittedCount ?? 0) + childOmissions;
1739
+ }, 0);
1740
+ }
1338
1741
 
1339
1742
  // src/snapshot/exception.ts
1340
1743
  function asString2(value) {
1341
1744
  return typeof value === "string" && value.length > 0 ? value : void 0;
1342
1745
  }
1343
- async function materializeObject(session, objectId, maxValueLength) {
1746
+ async function materializeObject(session, objectId) {
1344
1747
  try {
1345
- const properties = await captureProperties(
1748
+ const captured = await captureProperties(
1346
1749
  session,
1347
1750
  objectId,
1348
1751
  MAX_SCOPE_VARIABLES,
1349
1752
  MAX_VARIABLE_DEPTH,
1350
- maxValueLength
1753
+ Number.MAX_SAFE_INTEGER
1351
1754
  );
1352
- if (properties.length === 0) {
1755
+ if (captured.variables.length === 0) {
1353
1756
  return void 0;
1354
1757
  }
1355
1758
  const structured = {};
1356
- for (const variable of properties) {
1759
+ for (const variable of captured.variables) {
1357
1760
  structured[variable.name] = toStructuredValue(variable);
1358
1761
  }
1359
- return JSON.stringify(structured);
1762
+ return {
1763
+ value: JSON.stringify(structured),
1764
+ omittedCount: countPropertyOmissions(captured)
1765
+ };
1360
1766
  } catch {
1361
1767
  return void 0;
1362
1768
  }
@@ -1409,18 +1815,44 @@ async function captureException(session, pause, maxValueLength) {
1409
1815
  return { error: "exception data has no objectId or value" };
1410
1816
  }
1411
1817
  const message = await readPropertyDescription(session, objectId, "message");
1412
- const rendered = await materializeObject(session, objectId, maxValueLength);
1818
+ const rendered = await materializeObject(session, objectId);
1413
1819
  if (rendered !== void 0) {
1414
- const result = buildResult(type, description, rendered, maxValueLength);
1415
- return message === void 0 ? result : { ...result, description: limitValueLength(message, maxValueLength) };
1820
+ return buildResult(
1821
+ type,
1822
+ message ?? description,
1823
+ rendered.value,
1824
+ maxValueLength,
1825
+ rendered.omittedCount
1826
+ );
1416
1827
  }
1417
1828
  return buildResult(type, description, description ?? "[exception]", maxValueLength);
1418
1829
  }
1419
- function buildResult(type, description, value, maxValueLength) {
1420
- const safeValue = limitValueLength(value, maxValueLength);
1421
- const base = { value: safeValue };
1830
+ function buildResult(type, description, value, maxValueLength, omittedCount = 0) {
1831
+ const limitedValue = limitValueLength(value, maxValueLength);
1832
+ const limitedDescription = description === void 0 ? void 0 : limitValueLength(description, maxValueLength);
1833
+ const base = {
1834
+ value: limitedValue.text,
1835
+ ...exceptionTruncationFields(limitedValue, limitedDescription)
1836
+ };
1422
1837
  const withType = type === void 0 ? base : { ...base, type };
1423
- return description === void 0 ? withType : { ...withType, description: limitValueLength(description, maxValueLength) };
1838
+ const withDescription = limitedDescription === void 0 ? withType : { ...withType, description: limitedDescription.text };
1839
+ return omittedCount === 0 ? withDescription : { ...withDescription, truncated: true, omittedCount };
1840
+ }
1841
+ function exceptionTruncationFields(value, description) {
1842
+ const valueLength = value.truncated ? value.originalLength : void 0;
1843
+ const descriptionLength = description?.truncated === true ? description.originalLength : void 0;
1844
+ const lengths = [valueLength, descriptionLength].filter(
1845
+ (length) => length !== void 0
1846
+ );
1847
+ if (lengths.length === 0) {
1848
+ return {};
1849
+ }
1850
+ return {
1851
+ truncated: true,
1852
+ originalLength: Math.max(...lengths),
1853
+ ...valueLength === void 0 ? {} : { valueOriginalLength: valueLength },
1854
+ ...descriptionLength === void 0 ? {} : { descriptionOriginalLength: descriptionLength }
1855
+ };
1424
1856
  }
1425
1857
 
1426
1858
  // src/snapshot/objects.ts
@@ -1435,20 +1867,23 @@ function objectIdFromEvalResult(result) {
1435
1867
  }
1436
1868
  return objectId;
1437
1869
  }
1438
- async function renderObjectCapture(session, objectId, maxValueLength) {
1870
+ async function renderObjectCapture(session, objectId) {
1439
1871
  try {
1440
- const properties = await captureProperties(
1872
+ const captured = await captureProperties(
1441
1873
  session,
1442
1874
  objectId,
1443
1875
  MAX_SCOPE_VARIABLES,
1444
1876
  MAX_VARIABLE_DEPTH,
1445
- maxValueLength
1877
+ Number.MAX_SAFE_INTEGER
1446
1878
  );
1447
1879
  const structured = {};
1448
- for (const variable of properties) {
1880
+ for (const variable of captured.variables) {
1449
1881
  structured[variable.name] = toStructuredValue(variable);
1450
1882
  }
1451
- return JSON.stringify(structured);
1883
+ return {
1884
+ value: JSON.stringify(structured),
1885
+ omittedCount: countPropertyOmissions(captured)
1886
+ };
1452
1887
  } catch {
1453
1888
  return void 0;
1454
1889
  }
@@ -1470,16 +1905,22 @@ async function withSerializedObjectCapture(session, expression, evalResult, capt
1470
1905
  if (objectId === void 0) {
1471
1906
  return captured;
1472
1907
  }
1473
- const rendered = await renderObjectCapture(session, objectId, maxValueLength);
1908
+ const rendered = await renderObjectCapture(session, objectId);
1474
1909
  if (rendered === void 0) {
1475
1910
  return captured;
1476
1911
  }
1477
- const normalized = normalizeRenderedObjectCapture(rendered, captured.value);
1912
+ const normalized = normalizeRenderedObjectCapture(rendered.value, captured.value);
1478
1913
  if (normalized === void 0) {
1479
1914
  return captured;
1480
1915
  }
1481
- const value = limitValueLength(normalized, maxValueLength);
1482
- return captured.type === void 0 ? { expression, value } : { expression, value, type: captured.type };
1916
+ const limited = limitValueLength(normalized, maxValueLength);
1917
+ const base = {
1918
+ expression,
1919
+ value: limited.text,
1920
+ ...textTruncationFields(limited),
1921
+ ...captured.type === void 0 ? {} : { type: captured.type }
1922
+ };
1923
+ return rendered.omittedCount === 0 ? base : { ...base, truncated: true, omittedCount: rendered.omittedCount };
1483
1924
  }
1484
1925
 
1485
1926
  // src/snapshot/scopes.ts
@@ -1494,35 +1935,39 @@ var PRIORITY_BY_TYPE = {
1494
1935
  module: 6,
1495
1936
  script: 7
1496
1937
  };
1497
- function selectScopes(scopeChain) {
1938
+ function rankedScopes(scopeChain) {
1498
1939
  const eligible = scopeChain.filter((scope) => scope.objectId !== void 0 && scope.type !== "global");
1499
- return [...eligible].sort((a, b) => priorityOf(a.type) - priorityOf(b.type)).slice(0, MAX_SCOPES);
1940
+ return [...eligible].sort((a, b) => priorityOf(a.type) - priorityOf(b.type));
1500
1941
  }
1501
1942
  function priorityOf(type) {
1502
1943
  return PRIORITY_BY_TYPE[type] ?? Number.MAX_SAFE_INTEGER;
1503
1944
  }
1504
1945
  async function captureScopes(session, frame, maxValueLength) {
1505
- const scopes = selectScopes(frame.scopeChain);
1506
- return await Promise.all(
1946
+ const ranked = rankedScopes(frame.scopeChain);
1947
+ const scopes = ranked.slice(0, MAX_SCOPES);
1948
+ const capturedScopes = await Promise.all(
1507
1949
  scopes.map(async (scope) => {
1508
1950
  const objectId = scope.objectId;
1509
1951
  if (objectId === void 0) {
1510
1952
  return { type: scope.type, variables: [] };
1511
1953
  }
1512
1954
  try {
1513
- const variables = await captureProperties(
1955
+ const captured = await captureProperties(
1514
1956
  session,
1515
1957
  objectId,
1516
1958
  MAX_SCOPE_VARIABLES,
1517
1959
  MAX_VARIABLE_DEPTH,
1518
1960
  maxValueLength
1519
1961
  );
1520
- return { type: scope.type, variables };
1962
+ const base = { type: scope.type, variables: captured.variables };
1963
+ return captured.omittedCount === void 0 ? base : { ...base, truncated: true, omittedCount: captured.omittedCount };
1521
1964
  } catch {
1522
1965
  return { type: scope.type, variables: [] };
1523
1966
  }
1524
1967
  })
1525
1968
  );
1969
+ const omittedCount = Math.max(ranked.length - capturedScopes.length, 0);
1970
+ return omittedCount === 0 ? { scopes: capturedScopes } : { scopes: capturedScopes, omittedCount };
1526
1971
  }
1527
1972
 
1528
1973
  // src/snapshot/stack.ts
@@ -1542,23 +1987,48 @@ function buildBaseFrame(frame) {
1542
1987
  };
1543
1988
  return frame.url === void 0 ? base : { ...base, url: frame.url };
1544
1989
  }
1545
- async function captureFrameExpression(session, callFrameId, expression, maxValueLength) {
1990
+ async function captureFrameExpression(session, callFrameId, expression, maxValueLength, throwOnSideEffect) {
1991
+ const mutationRisk = throwOnSideEffect === false && looksLikeMutation(expression);
1546
1992
  try {
1547
- const result = await evaluateOnFrame(session, callFrameId, expression);
1993
+ const result = await evaluateOnFrame(session, callFrameId, expression, {
1994
+ ...throwOnSideEffect === void 0 ? {} : { throwOnSideEffect }
1995
+ });
1996
+ if (isSideEffectRefusal(result)) {
1997
+ return sideEffectRefusalToCaptured(expression);
1998
+ }
1548
1999
  const captured = evalResultToCaptured(expression, result, maxValueLength);
1549
- return await withSerializedObjectCapture(session, expression, result, captured, maxValueLength);
2000
+ const serialized = await withSerializedObjectCapture(
2001
+ session,
2002
+ expression,
2003
+ result,
2004
+ captured,
2005
+ maxValueLength
2006
+ );
2007
+ return mutationRisk ? { ...serialized, mutationRisk: true } : serialized;
1550
2008
  } catch (err) {
1551
2009
  const message = err instanceof Error ? err.message : String(err);
1552
- return { expression, error: limitValueLength(message, maxValueLength) };
2010
+ const limited = limitValueLength(message, maxValueLength);
2011
+ const captured = {
2012
+ expression,
2013
+ error: limited.text,
2014
+ ...textTruncationFields(limited)
2015
+ };
2016
+ return mutationRisk ? { ...captured, mutationRisk: true } : captured;
1553
2017
  }
1554
2018
  }
1555
- async function captureFrameExpressions(session, frame, expressions, maxValueLength) {
2019
+ async function captureFrameExpressions(session, frame, expressions, maxValueLength, throwOnSideEffect) {
1556
2020
  if (expressions.length === 0) {
1557
2021
  return [];
1558
2022
  }
1559
2023
  return await Promise.all(
1560
2024
  expressions.map(
1561
- (expression) => captureFrameExpression(session, frame.callFrameId, expression, maxValueLength)
2025
+ (expression) => captureFrameExpression(
2026
+ session,
2027
+ frame.callFrameId,
2028
+ expression,
2029
+ maxValueLength,
2030
+ throwOnSideEffect
2031
+ )
1562
2032
  )
1563
2033
  );
1564
2034
  }
@@ -1578,7 +2048,8 @@ async function walkStack(session, callFrames, options) {
1578
2048
  session,
1579
2049
  frame,
1580
2050
  options.stackCaptures,
1581
- options.maxValueLength
2051
+ options.maxValueLength,
2052
+ options.throwOnSideEffect
1582
2053
  );
1583
2054
  return { ...base, captures };
1584
2055
  })
@@ -1600,14 +2071,25 @@ async function captureSnapshot(session, pause, options = {}) {
1600
2071
  column: top.columnNumber + 1
1601
2072
  };
1602
2073
  if (options.includeScopes === true) {
1603
- const scopes = await captureScopes(session, top, maxValueLength);
1604
- topFrame = { ...topFrame, scopes };
2074
+ const capturedScopes = await captureScopes(session, top, maxValueLength);
2075
+ topFrame = {
2076
+ ...topFrame,
2077
+ scopes: capturedScopes.scopes,
2078
+ ...capturedScopes.omittedCount === void 0 ? {} : { truncated: true, omittedCount: capturedScopes.omittedCount }
2079
+ };
1605
2080
  }
1606
- captures = await captureExpressions(session, top.callFrameId, options.captures, maxValueLength);
2081
+ captures = await captureExpressions(
2082
+ session,
2083
+ top.callFrameId,
2084
+ options.captures,
2085
+ maxValueLength,
2086
+ options.throwOnSideEffect
2087
+ );
1607
2088
  stack = await walkStack(session, pause.callFrames, {
1608
2089
  stackDepth: options.stackDepth ?? DEFAULT_STACK_DEPTH,
1609
2090
  stackCaptures: options.stackCaptures ?? [],
1610
- maxValueLength
2091
+ maxValueLength,
2092
+ ...options.throwOnSideEffect === void 0 ? {} : { throwOnSideEffect: options.throwOnSideEffect }
1611
2093
  });
1612
2094
  }
1613
2095
  const exception = await captureException(session, pause, maxValueLength);
@@ -1630,24 +2112,49 @@ function buildResult2(input) {
1630
2112
  const withStack = input.stack.length > 0 ? { ...withFrame, stack: input.stack } : withFrame;
1631
2113
  return input.exception === void 0 ? withStack : { ...withStack, exception: input.exception };
1632
2114
  }
1633
- async function captureExpressions(session, callFrameId, captures, maxValueLength) {
2115
+ async function captureExpressions(session, callFrameId, captures, maxValueLength, throwOnSideEffect) {
1634
2116
  if (captures === void 0 || captures.length === 0) {
1635
2117
  return [];
1636
2118
  }
1637
2119
  return await Promise.all(
1638
2120
  captures.map(async (expression) => {
1639
- return await captureExpression(session, callFrameId, expression, maxValueLength);
2121
+ return await captureExpression(
2122
+ session,
2123
+ callFrameId,
2124
+ expression,
2125
+ maxValueLength,
2126
+ throwOnSideEffect
2127
+ );
1640
2128
  })
1641
2129
  );
1642
2130
  }
1643
- async function captureExpression(session, callFrameId, expression, maxValueLength) {
2131
+ async function captureExpression(session, callFrameId, expression, maxValueLength, throwOnSideEffect) {
2132
+ const mutationRisk = throwOnSideEffect === false && looksLikeMutation(expression);
1644
2133
  try {
1645
- const result = await evaluateOnFrame(session, callFrameId, expression);
2134
+ const result = await evaluateOnFrame(session, callFrameId, expression, {
2135
+ ...throwOnSideEffect === void 0 ? {} : { throwOnSideEffect }
2136
+ });
2137
+ if (isSideEffectRefusal(result)) {
2138
+ return sideEffectRefusalToCaptured(expression);
2139
+ }
1646
2140
  const captured = evalResultToCaptured(expression, result, maxValueLength);
1647
- return await withSerializedObjectCapture(session, expression, result, captured, maxValueLength);
2141
+ const serialized = await withSerializedObjectCapture(
2142
+ session,
2143
+ expression,
2144
+ result,
2145
+ captured,
2146
+ maxValueLength
2147
+ );
2148
+ return mutationRisk ? { ...serialized, mutationRisk: true } : serialized;
1648
2149
  } catch (err) {
1649
2150
  const message = err instanceof Error ? err.message : String(err);
1650
- return { expression, error: limitValueLength(message, maxValueLength) };
2151
+ const limited = limitValueLength(message, maxValueLength);
2152
+ const captured = {
2153
+ expression,
2154
+ error: limited.text,
2155
+ ...textTruncationFields(limited)
2156
+ };
2157
+ return mutationRisk ? { ...captured, mutationRisk: true } : captured;
1651
2158
  }
1652
2159
  }
1653
2160
 
@@ -1735,7 +2242,7 @@ function readArg(arg, index) {
1735
2242
  }
1736
2243
  return index === 0 ? void 0 : "";
1737
2244
  }
1738
- function parseLogEvent(rawArgs, sentinel, location, timestamp) {
2245
+ function parseLogEvent(rawArgs, sentinel, location, timestamp, maxValueLength = DEFAULT_STREAM_MAX_VALUE_LENGTH) {
1739
2246
  if (!Array.isArray(rawArgs) || rawArgs.length < 2) {
1740
2247
  return void 0;
1741
2248
  }
@@ -1747,21 +2254,37 @@ function parseLogEvent(rawArgs, sentinel, location, timestamp) {
1747
2254
  const ts = new Date(typeof timestamp === "number" ? timestamp : Date.now()).toISOString();
1748
2255
  const at = `${location.file}:${location.line.toString()}`;
1749
2256
  if (payload.startsWith("!err:")) {
1750
- return { ts, at, error: payload.slice("!err:".length) };
2257
+ const limited = limitValueLength(payload.slice("!err:".length), maxValueLength);
2258
+ return {
2259
+ ts,
2260
+ at,
2261
+ error: limited.text,
2262
+ ...textTruncationFields(limited)
2263
+ };
1751
2264
  }
1752
- return parsePayload(ts, at, payload);
2265
+ return parsePayload(ts, at, payload, maxValueLength);
1753
2266
  }
1754
- function parsePayload(ts, at, payload) {
2267
+ function parsePayload(ts, at, payload, maxValueLength) {
1755
2268
  try {
1756
2269
  const parsed = JSON.parse(payload);
1757
2270
  if (typeof parsed === "string") {
1758
- return { ts, at, value: parsed };
2271
+ return buildValueEvent(ts, at, parsed, maxValueLength);
1759
2272
  }
1760
- return { ts, at, value: JSON.stringify(parsed) };
2273
+ return buildValueEvent(ts, at, JSON.stringify(parsed), maxValueLength);
1761
2274
  } catch {
1762
- return { ts, at, value: payload, raw: payload };
2275
+ return buildValueEvent(ts, at, payload, maxValueLength, true);
1763
2276
  }
1764
2277
  }
2278
+ function buildValueEvent(ts, at, value, maxValueLength, includeRaw = false) {
2279
+ const limited = limitValueLength(value, maxValueLength);
2280
+ return {
2281
+ ts,
2282
+ at,
2283
+ value: limited.text,
2284
+ ...includeRaw ? { raw: limited.text } : {},
2285
+ ...textTruncationFields(limited)
2286
+ };
2287
+ }
1765
2288
 
1766
2289
  // src/logpoint/stream.ts
1767
2290
  function validateMaxEvents(maxEvents) {
@@ -1791,6 +2314,9 @@ function validateHitCount2(hitCount) {
1791
2314
  async function streamLogpoint(session, options) {
1792
2315
  const maxEvents = validateMaxEvents(options.maxEvents);
1793
2316
  const hitCount = validateHitCount2(options.hitCount);
2317
+ const maxValueLength = resolveMaxValueLength(
2318
+ options.maxValueLength ?? DEFAULT_STREAM_MAX_VALUE_LENGTH
2319
+ );
1794
2320
  const sentinel = generateSentinel();
1795
2321
  const condition = buildLogpointCondition(sentinel, options.expression, {
1796
2322
  ...options.condition === void 0 ? {} : { predicate: options.condition },
@@ -1803,7 +2329,7 @@ async function streamLogpoint(session, options) {
1803
2329
  if (maxEventsReached) {
1804
2330
  return;
1805
2331
  }
1806
- const event = toLogpointEvent(raw, sentinel, options.location);
2332
+ const event = toLogpointEvent(raw, sentinel, options.location, maxValueLength);
1807
2333
  if (event === void 0) {
1808
2334
  return;
1809
2335
  }
@@ -1843,13 +2369,13 @@ async function streamLogpoint(session, options) {
1843
2369
  await removeBreakpointBestEffort(session, handle.breakpointId);
1844
2370
  }
1845
2371
  }
1846
- function toLogpointEvent(raw, sentinel, location) {
2372
+ function toLogpointEvent(raw, sentinel, location, maxValueLength) {
1847
2373
  const params = raw;
1848
2374
  if (asString3(params.type) !== "log") {
1849
2375
  return void 0;
1850
2376
  }
1851
2377
  const ts = typeof params.timestamp === "number" ? params.timestamp : void 0;
1852
- return parseLogEvent(params.args, sentinel, location, ts);
2378
+ return parseLogEvent(params.args, sentinel, location, ts, maxValueLength);
1853
2379
  }
1854
2380
  async function removeBreakpointBestEffort(session, breakpointId) {
1855
2381
  try {