@xbbg/langgraph 1.4.11 → 1.4.12

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
@@ -63,6 +63,12 @@ var DEFAULT_MAX_SECURITIES = 25;
63
63
  var DEFAULT_MAX_FIELDS = 25;
64
64
  var DEFAULT_MAX_ROWS = 500;
65
65
  var DEFAULT_MAX_STRING_CHARS = 2e3;
66
+ var DEFAULT_MAX_RESULT_BYTES = 1048576;
67
+ var DEFAULT_MAX_RESULT_NODES = 5e4;
68
+ var DEFAULT_MAX_CONTENT_BYTES = 65536;
69
+ var DEFAULT_MAX_CONTENT_ROWS = 50;
70
+ var MIN_RESULT_BYTE_BUDGET = 256;
71
+ var MIN_RESULT_NODE_BUDGET = 10;
66
72
  var DEFAULT_MAX_BQL_QUERY_CHARS = 4e3;
67
73
  var DEFAULT_MAX_SEARCH_SPEC_CHARS = 1e3;
68
74
  var DEFAULT_MAX_STREAM_UPDATES = 10;
@@ -78,11 +84,20 @@ function positiveInteger(value, fallback, name) {
78
84
  if (value === void 0) {
79
85
  return fallback;
80
86
  }
81
- if (!Number.isInteger(value) || value <= 0) {
82
- throw new RangeError(`${name} must be a positive integer; got ${String(value)}`);
87
+ if (!Number.isSafeInteger(value) || value <= 0) {
88
+ throw new RangeError(
89
+ `${name} must be a positive integer no greater than Number.MAX_SAFE_INTEGER; got ${String(value)}`
90
+ );
83
91
  }
84
92
  return value;
85
93
  }
94
+ function integerAtLeast(value, fallback, minimum, name) {
95
+ const normalized = positiveInteger(value, fallback, name);
96
+ if (normalized < minimum) {
97
+ throw new RangeError(`${name} must be at least ${String(minimum)}; got ${String(normalized)}`);
98
+ }
99
+ return normalized;
100
+ }
86
101
  function disabledToolSet(tools) {
87
102
  return new Set(tools ?? []);
88
103
  }
@@ -98,7 +113,30 @@ function normalizeBloombergToolsOptions(options = {}) {
98
113
  "maxBqlQueryChars"
99
114
  ),
100
115
  maxFields: positiveInteger(options.maxFields, DEFAULT_MAX_FIELDS, "maxFields"),
116
+ maxContentBytes: integerAtLeast(
117
+ options.maxContentBytes,
118
+ DEFAULT_MAX_CONTENT_BYTES,
119
+ MIN_RESULT_BYTE_BUDGET,
120
+ "maxContentBytes"
121
+ ),
122
+ maxContentRows: positiveInteger(
123
+ options.maxContentRows,
124
+ DEFAULT_MAX_CONTENT_ROWS,
125
+ "maxContentRows"
126
+ ),
101
127
  maxRows: positiveInteger(options.maxRows, DEFAULT_MAX_ROWS, "maxRows"),
128
+ maxResultBytes: integerAtLeast(
129
+ options.maxResultBytes,
130
+ DEFAULT_MAX_RESULT_BYTES,
131
+ MIN_RESULT_BYTE_BUDGET,
132
+ "maxResultBytes"
133
+ ),
134
+ maxResultNodes: integerAtLeast(
135
+ options.maxResultNodes,
136
+ DEFAULT_MAX_RESULT_NODES,
137
+ MIN_RESULT_NODE_BUDGET,
138
+ "maxResultNodes"
139
+ ),
102
140
  maxSearchSpecChars: positiveInteger(
103
141
  options.maxSearchSpecChars,
104
142
  DEFAULT_MAX_SEARCH_SPEC_CHARS,
@@ -178,181 +216,863 @@ function createCoreResolver(options = {}) {
178
216
  }
179
217
 
180
218
  // src/result-limits.ts
219
+ var OMIT = /* @__PURE__ */ Symbol("omit_result_value");
181
220
  var MAX_RESULT_DEPTH = 32;
221
+ var MIN_TOOL_RESULT_NODES = 10;
222
+ var MAX_ERROR_DIAGNOSTICS = 8;
223
+ var RESULT_ENVELOPE_RESERVE_BYTES = 768;
224
+ var CONTENT_ENVELOPE_RESERVE_BYTES = 768;
225
+ var MIN_TOOL_RESULT_BYTES = 256;
182
226
  var MAX_ENTITLEMENT_EIDS = 1e4;
183
227
  var MAX_BLOOMBERG_EID = 2147483647;
184
228
  var MAX_EID_SECURITIES = 1e3;
185
229
  var MAX_EID_SECURITY_NAME_BYTES = 65536;
186
230
  var UTF8_ENCODER = new TextEncoder();
231
+ var TRUNCATION_REASON_ORDER = [
232
+ "max_rows",
233
+ "max_string_chars",
234
+ "max_result_bytes",
235
+ "max_result_nodes",
236
+ "max_result_depth",
237
+ "circular_reference",
238
+ "binary_data",
239
+ "accessor_omitted",
240
+ "unsupported_value",
241
+ "invalid_entitlement_data",
242
+ "entitlement_limit",
243
+ "upstream_truncation"
244
+ ];
245
+ var ERROR_SHAPE_KEYS = {
246
+ error: true,
247
+ errors: true,
248
+ fielderrors: true,
249
+ fieldexception: true,
250
+ fieldexceptions: true,
251
+ responseerror: true,
252
+ responseerrors: true,
253
+ securityerror: true,
254
+ securityerrors: true,
255
+ unsubscribeerror: true
256
+ };
257
+ var PRIORITY_KEYS = [
258
+ "error",
259
+ "errors",
260
+ "responseError",
261
+ "responseErrors",
262
+ "securityError",
263
+ "securityErrors",
264
+ "fieldException",
265
+ "fieldExceptions",
266
+ "fieldErrors",
267
+ "unsubscribeError",
268
+ "truncated",
269
+ "truncatedInput",
270
+ "eidData",
271
+ "eidDataTruncation",
272
+ "diagnostics",
273
+ "metadata"
274
+ ];
187
275
  function isPlainObject(value) {
188
276
  const prototype = Object.getPrototypeOf(value);
189
277
  return prototype === Object.prototype || prototype === null;
190
278
  }
191
- function truncateString(value, maxStringChars, state) {
192
- if (value.length <= maxStringChars) {
193
- return value;
279
+ function addReason(state, reason) {
280
+ state.reasons.add(reason);
281
+ }
282
+ function consumeVisit(state) {
283
+ if (state.visitedNodes >= state.limits.maxResultNodes) {
284
+ addReason(state, "max_result_nodes");
285
+ return false;
286
+ }
287
+ state.visitedNodes += 1;
288
+ return true;
289
+ }
290
+ function consumeVisitBefore(state, limit) {
291
+ if (state.visitedNodes >= limit) {
292
+ addReason(state, "max_result_nodes");
293
+ return false;
194
294
  }
195
- state.truncated = true;
196
- return `${value.slice(0, maxStringChars)}\u2026[truncated ${value.length - maxStringChars} chars]`;
295
+ return consumeVisit(state);
197
296
  }
198
- function arrayMetadata(value) {
199
- const metadata = {};
200
- for (const [key, entry] of Object.entries(value)) {
201
- if (!/^(?:0|[1-9]\d*)$/u.test(key)) {
202
- metadata[key] = entry;
297
+ function projectionBudget(totalBytes, preferredReserveBytes) {
298
+ const reserve = Math.min(preferredReserveBytes, Math.floor(totalBytes / 2));
299
+ return Math.max(4, totalBytes - reserve);
300
+ }
301
+ function jsonStringUnit(value, index) {
302
+ const code = value.charCodeAt(index);
303
+ if (code === 34 || code === 92 || code === 8 || code === 12 || code === 10 || code === 13 || code === 9) {
304
+ return { bytes: 2, width: 1 };
305
+ }
306
+ if (code <= 31) {
307
+ return { bytes: 6, width: 1 };
308
+ }
309
+ if (code <= 127) {
310
+ return { bytes: 1, width: 1 };
311
+ }
312
+ if (code <= 2047) {
313
+ return { bytes: 2, width: 1 };
314
+ }
315
+ if (code >= 55296 && code <= 56319) {
316
+ const next = value.charCodeAt(index + 1);
317
+ if (next >= 56320 && next <= 57343) {
318
+ return { bytes: 4, width: 2 };
319
+ }
320
+ return { bytes: 6, width: 1 };
321
+ }
322
+ if (code >= 56320 && code <= 57343) {
323
+ return { bytes: 6, width: 1 };
324
+ }
325
+ return { bytes: 3, width: 1 };
326
+ }
327
+ function jsonStringByteLength(value, stopAfter = Number.MAX_SAFE_INTEGER) {
328
+ let byteLength = 2;
329
+ for (let index = 0; index < value.length; ) {
330
+ const unit = jsonStringUnit(value, index);
331
+ byteLength += unit.bytes;
332
+ if (byteLength > stopAfter) {
333
+ return stopAfter + 1;
203
334
  }
335
+ index += unit.width;
204
336
  }
205
- return metadata;
337
+ return byteLength;
338
+ }
339
+ function utf8ByteLengthAtMost(value, maximum) {
340
+ let byteLength = 0;
341
+ for (let index = 0; index < value.length; ) {
342
+ const code = value.charCodeAt(index);
343
+ let width = 1;
344
+ let bytes;
345
+ if (code <= 127) {
346
+ bytes = 1;
347
+ } else if (code <= 2047) {
348
+ bytes = 2;
349
+ } else if (code >= 55296 && code <= 56319) {
350
+ const next = value.charCodeAt(index + 1);
351
+ if (next >= 56320 && next <= 57343) {
352
+ bytes = 4;
353
+ width = 2;
354
+ } else {
355
+ bytes = 3;
356
+ }
357
+ } else {
358
+ bytes = 3;
359
+ }
360
+ byteLength += bytes;
361
+ if (byteLength > maximum) {
362
+ return null;
363
+ }
364
+ index += width;
365
+ }
366
+ return byteLength;
367
+ }
368
+ function safePrefixEnd(value, requestedEnd) {
369
+ if (requestedEnd > 0 && requestedEnd < value.length && value.charCodeAt(requestedEnd - 1) >= 55296 && value.charCodeAt(requestedEnd - 1) <= 56319 && value.charCodeAt(requestedEnd) >= 56320 && value.charCodeAt(requestedEnd) <= 57343) {
370
+ return requestedEnd - 1;
371
+ }
372
+ return requestedEnd;
373
+ }
374
+ function fitString(value, maximumJsonBytes, state) {
375
+ const charLimit = safePrefixEnd(value, Math.min(value.length, state.limits.maxStringChars));
376
+ if (charLimit < value.length) {
377
+ addReason(state, "max_string_chars");
378
+ }
379
+ const suffix = `\u2026[truncated ${value.length - charLimit} chars]`;
380
+ const characterLimited = charLimit === value.length ? value : `${value.slice(0, charLimit)}${suffix}`;
381
+ const characterLimitedBytes = jsonStringByteLength(characterLimited, maximumJsonBytes);
382
+ if (characterLimitedBytes <= maximumJsonBytes) {
383
+ state.retainedNodes += 1;
384
+ return { byteLength: characterLimitedBytes, value: characterLimited };
385
+ }
386
+ addReason(state, "max_result_bytes");
387
+ const markerOnly = `\u2026[truncated ${value.length} chars]`;
388
+ const markerOnlyBytes = jsonStringByteLength(markerOnly, maximumJsonBytes);
389
+ if (markerOnlyBytes > maximumJsonBytes) {
390
+ if (maximumJsonBytes < 2) {
391
+ return OMIT;
392
+ }
393
+ state.retainedNodes += 1;
394
+ return { byteLength: 2, value: "" };
395
+ }
396
+ const prefixBudget = Math.max(0, maximumJsonBytes - 2 - 64);
397
+ let prefixBytes = 0;
398
+ let prefixEnd = 0;
399
+ while (prefixEnd < charLimit) {
400
+ const unit = jsonStringUnit(value, prefixEnd);
401
+ if (prefixBytes + unit.bytes > prefixBudget) {
402
+ break;
403
+ }
404
+ prefixBytes += unit.bytes;
405
+ prefixEnd += unit.width;
406
+ }
407
+ const fittedSuffix = `\u2026[truncated ${value.length - prefixEnd} chars]`;
408
+ const fitted = `${value.slice(0, prefixEnd)}${fittedSuffix}`;
409
+ const fittedBytes = jsonStringByteLength(fitted, maximumJsonBytes);
410
+ if (fittedBytes > maximumJsonBytes) {
411
+ state.retainedNodes += 1;
412
+ return { byteLength: markerOnlyBytes, value: markerOnly };
413
+ }
414
+ state.retainedNodes += 1;
415
+ return { byteLength: fittedBytes, value: fitted };
416
+ }
417
+ function defineJsonProperty(target, key, value) {
418
+ Object.defineProperty(target, key, {
419
+ configurable: true,
420
+ enumerable: true,
421
+ value,
422
+ writable: true
423
+ });
424
+ }
425
+ function ownEnumerableDescriptor(value, key) {
426
+ try {
427
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
428
+ return descriptor?.enumerable === true ? descriptor : void 0;
429
+ } catch {
430
+ return void 0;
431
+ }
432
+ }
433
+ function rememberErrorDiagnostic(state, key, value) {
434
+ state.hasErrors = true;
435
+ if (state.diagnostics.length >= MAX_ERROR_DIAGNOSTICS) {
436
+ return;
437
+ }
438
+ const diagnostic = /* @__PURE__ */ Object.create(null);
439
+ defineJsonProperty(diagnostic, key, value);
440
+ state.diagnostics.push(Object.freeze(diagnostic));
441
+ }
442
+ function hasReportedError(value) {
443
+ if (value === void 0 || value === null || value === false || value === "") {
444
+ return false;
445
+ }
446
+ return !Array.isArray(value) || value.length > 0;
447
+ }
448
+ function primitiveBuilt(value, maximumJsonBytes, state) {
449
+ const json = value === null ? "null" : String(value);
450
+ const byteLength = json.length;
451
+ if (byteLength > maximumJsonBytes) {
452
+ addReason(state, "max_result_bytes");
453
+ return OMIT;
454
+ }
455
+ state.retainedNodes += 1;
456
+ return { byteLength, value };
457
+ }
458
+ function buildUnsupported(label, maximumJsonBytes, state, reason = "unsupported_value") {
459
+ addReason(state, reason);
460
+ return fitString(label, maximumJsonBytes, state);
206
461
  }
207
- function limitEidData(value, maxStringChars, state, depth, seen) {
208
- if (typeof value !== "object" || value === null || !isPlainObject(value)) {
209
- state.truncated = true;
462
+ function prepareEidData(value, state) {
463
+ const data = /* @__PURE__ */ Object.create(null);
464
+ const securityCounts = [];
465
+ let validContainer = false;
466
+ if (typeof value === "object" && value !== null) {
467
+ try {
468
+ validContainer = isPlainObject(value);
469
+ } catch {
470
+ validContainer = false;
471
+ }
472
+ }
473
+ if (!validContainer) {
474
+ addReason(state, "invalid_entitlement_data");
210
475
  return {
211
- data: {},
476
+ data,
477
+ invalidSecurityCount: 1,
478
+ scannedSecurityCount: 1,
479
+ securityCounts,
480
+ totalEidCount: 0,
481
+ totalSecurityCount: 1,
212
482
  truncation: {
213
483
  invalidSecurityCount: 1,
214
484
  omittedSecurityCount: 0,
215
485
  retainedEidCount: 0,
216
486
  retainedSecurityCount: 0,
217
- securityCounts: [],
487
+ scannedSecurityCount: 1,
488
+ securityCounts,
218
489
  totalEidCount: 0,
219
490
  totalSecurityCount: 1
220
491
  }
221
492
  };
222
493
  }
223
- const data = /* @__PURE__ */ Object.create(null);
224
- const securityCounts = [];
225
- const entries = Object.entries(value);
494
+ const eidRecord = value;
495
+ let complete = true;
496
+ let invalidSecurityCount = 0;
226
497
  let retainedEidCount = 0;
227
498
  let retainedSecurityCount = 0;
228
499
  let retainedSecurityNameBytes = 0;
500
+ let scannedSecurityCount = 0;
229
501
  let totalEidCount = 0;
230
- let invalidSecurityCount = 0;
231
- for (const [security, eids] of entries) {
232
- if (!Array.isArray(eids)) {
233
- state.truncated = true;
502
+ const remainingNodeBudget = state.limits.maxResultNodes - state.visitedNodes;
503
+ const reservedSummaryNodes = Math.min(16, Math.max(0, remainingNodeBudget - 1));
504
+ const eidVisitLimit = state.visitedNodes + Math.max(1, Math.floor((remainingNodeBudget - reservedSummaryNodes) / 2));
505
+ securityLoop: for (const security in eidRecord) {
506
+ if (!Object.hasOwn(eidRecord, security)) {
507
+ continue;
508
+ }
509
+ if (!consumeVisitBefore(state, eidVisitLimit)) {
510
+ complete = false;
511
+ break;
512
+ }
513
+ scannedSecurityCount += 1;
514
+ const descriptor = ownEnumerableDescriptor(eidRecord, security);
515
+ if (descriptor === void 0) {
516
+ continue;
517
+ }
518
+ if (!("value" in descriptor) || !Array.isArray(descriptor.value)) {
234
519
  invalidSecurityCount += 1;
520
+ addReason(state, "invalid_entitlement_data");
235
521
  continue;
236
522
  }
237
- let validEids = true;
523
+ const eids = descriptor.value;
524
+ const remainingNameBytes = MAX_EID_SECURITY_NAME_BYTES - retainedSecurityNameBytes;
525
+ const securityNameBytes = utf8ByteLengthAtMost(security, remainingNameBytes);
526
+ const canRetainSecurity = retainedSecurityCount < MAX_EID_SECURITIES && securityNameBytes !== null;
527
+ const remainingEidCapacity = Math.max(0, MAX_ENTITLEMENT_EIDS - retainedEidCount);
528
+ const retained = [];
529
+ let incomplete = false;
238
530
  for (let index = 0; index < eids.length; index += 1) {
239
- const eid = eids[index];
240
- if (!Object.hasOwn(eids, index) || typeof eid !== "number" || !Number.isInteger(eid) || eid <= 0 || eid > MAX_BLOOMBERG_EID) {
241
- validEids = false;
531
+ if (!consumeVisitBefore(state, eidVisitLimit)) {
532
+ complete = false;
533
+ incomplete = true;
242
534
  break;
243
535
  }
536
+ const eidDescriptor = Object.getOwnPropertyDescriptor(eids, String(index));
537
+ const eid = eidDescriptor !== void 0 && "value" in eidDescriptor ? eidDescriptor.value : void 0;
538
+ if (eidDescriptor === void 0 || !("value" in eidDescriptor) || typeof eid !== "number" || !Number.isInteger(eid) || eid <= 0 || eid > MAX_BLOOMBERG_EID) {
539
+ invalidSecurityCount += 1;
540
+ addReason(state, "invalid_entitlement_data");
541
+ continue securityLoop;
542
+ }
543
+ if (canRetainSecurity && retained.length < remainingEidCapacity) {
544
+ retained.push(eid);
545
+ }
244
546
  }
245
- if (!validEids) {
246
- state.truncated = true;
247
- invalidSecurityCount += 1;
248
- continue;
249
- }
250
- const originalCount = eids.length;
251
- totalEidCount += originalCount;
252
- const securityNameBytes = UTF8_ENCODER.encode(security).byteLength;
253
- const canRetainSecurity = retainedSecurityCount < MAX_EID_SECURITIES && retainedSecurityNameBytes + securityNameBytes <= MAX_EID_SECURITY_NAME_BYTES;
547
+ totalEidCount = Math.min(Number.MAX_SAFE_INTEGER, totalEidCount + eids.length);
254
548
  if (!canRetainSecurity) {
255
- state.truncated = true;
549
+ addReason(state, "entitlement_limit");
550
+ if (incomplete) {
551
+ break;
552
+ }
256
553
  continue;
257
554
  }
555
+ retainedEidCount += retained.length;
258
556
  retainedSecurityCount += 1;
259
557
  retainedSecurityNameBytes += securityNameBytes;
260
- const remainingEidCapacity = Math.max(0, MAX_ENTITLEMENT_EIDS - retainedEidCount);
261
- const retained = eids.slice(0, remainingEidCapacity);
262
- retainedEidCount += retained.length;
263
- data[security] = limitValue(retained, MAX_ENTITLEMENT_EIDS, maxStringChars, state, depth, seen);
264
- securityCounts.push({
265
- originalCount,
266
- retainedCount: retained.length
267
- });
268
- if (retained.length !== originalCount) {
269
- state.truncated = true;
558
+ defineJsonProperty(data, security, retained);
559
+ securityCounts.push({ originalCount: eids.length, retainedCount: retained.length });
560
+ if (!incomplete && retained.length !== eids.length) {
561
+ addReason(state, "entitlement_limit");
562
+ }
563
+ if (incomplete) {
564
+ break;
270
565
  }
271
566
  }
272
- const omittedSecurityCount = entries.length - retainedSecurityCount - invalidSecurityCount;
273
- const wasTruncated = retainedSecurityCount !== entries.length || retainedEidCount !== totalEidCount || invalidSecurityCount > 0;
567
+ const omittedSecurityCount = complete ? scannedSecurityCount - retainedSecurityCount - invalidSecurityCount : null;
568
+ const wasTruncated = !complete || invalidSecurityCount > 0 || omittedSecurityCount !== 0 || retainedEidCount !== totalEidCount;
569
+ if (!wasTruncated) {
570
+ return {
571
+ data,
572
+ invalidSecurityCount,
573
+ scannedSecurityCount,
574
+ securityCounts,
575
+ totalEidCount,
576
+ totalSecurityCount: scannedSecurityCount
577
+ };
578
+ }
274
579
  return {
275
580
  data,
276
- ...wasTruncated ? {
277
- truncation: {
278
- invalidSecurityCount,
279
- omittedSecurityCount,
280
- retainedEidCount,
281
- retainedSecurityCount,
282
- securityCounts,
283
- totalEidCount,
284
- totalSecurityCount: entries.length
285
- }
286
- } : {}
581
+ invalidSecurityCount,
582
+ scannedSecurityCount,
583
+ securityCounts,
584
+ totalEidCount: complete ? totalEidCount : null,
585
+ totalSecurityCount: complete ? scannedSecurityCount : null,
586
+ truncation: {
587
+ invalidSecurityCount,
588
+ omittedSecurityCount,
589
+ retainedEidCount,
590
+ retainedSecurityCount,
591
+ scannedSecurityCount,
592
+ securityCounts,
593
+ totalEidCount: complete ? totalEidCount : null,
594
+ totalSecurityCount: complete ? scannedSecurityCount : null
595
+ }
287
596
  };
288
597
  }
289
- function limitValue(value, maxRows, maxStringChars, state, depth = 0, seen = /* @__PURE__ */ new WeakSet()) {
290
- if (typeof value === "string") {
291
- return truncateString(value, maxStringChars, state);
598
+ function eidSummaryRecord(source) {
599
+ const descriptor = ownEnumerableDescriptor(source, "eidDataTruncation");
600
+ if (descriptor === void 0 || !("value" in descriptor) || typeof descriptor.value !== "object" || descriptor.value === null) {
601
+ return void 0;
292
602
  }
293
- if (value instanceof Date) {
294
- return value.toISOString();
603
+ return descriptor.value;
604
+ }
605
+ function eidSummaryCount(summary, key) {
606
+ if (summary === void 0) {
607
+ return void 0;
295
608
  }
296
- if (depth > MAX_RESULT_DEPTH) {
297
- state.truncated = true;
298
- return "[Max result depth exceeded]";
609
+ const descriptor = ownEnumerableDescriptor(summary, key);
610
+ if (descriptor === void 0 || !("value" in descriptor)) {
611
+ return void 0;
299
612
  }
300
- if (Array.isArray(value)) {
301
- if (seen.has(value)) {
302
- state.truncated = true;
303
- return "[Circular]";
613
+ const value = descriptor.value;
614
+ return value === null || typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
615
+ }
616
+ function eidSummarySecurityCounts(summary) {
617
+ if (summary === void 0) {
618
+ return [];
619
+ }
620
+ const descriptor = ownEnumerableDescriptor(summary, "securityCounts");
621
+ if (descriptor === void 0 || !("value" in descriptor) || !Array.isArray(descriptor.value)) {
622
+ return [];
623
+ }
624
+ const counts = [];
625
+ for (let index = 0; index < descriptor.value.length; index += 1) {
626
+ const entryDescriptor = Object.getOwnPropertyDescriptor(descriptor.value, String(index));
627
+ if (entryDescriptor === void 0 || !("value" in entryDescriptor) || typeof entryDescriptor.value !== "object" || entryDescriptor.value === null) {
628
+ break;
304
629
  }
305
- seen.add(value);
306
- const capped = value.length > maxRows ? value.slice(0, maxRows) : value;
307
- if (capped.length !== value.length) {
308
- state.truncated = true;
630
+ const originalCount = eidSummaryCount(
631
+ entryDescriptor.value,
632
+ "originalCount"
633
+ );
634
+ const retainedCount = eidSummaryCount(
635
+ entryDescriptor.value,
636
+ "retainedCount"
637
+ );
638
+ if (originalCount === void 0 || originalCount !== null && typeof originalCount !== "number" || typeof retainedCount !== "number") {
639
+ break;
309
640
  }
310
- const rows = capped.map(
311
- (item) => limitValue(item, maxRows, maxStringChars, state, depth + 1, seen)
641
+ counts.push({ originalCount, retainedCount });
642
+ }
643
+ return counts;
644
+ }
645
+ function emittedEidTruncation(source, emittedValue, prepared) {
646
+ const emitted = typeof emittedValue === "object" && emittedValue !== null ? emittedValue : /* @__PURE__ */ Object.create(null);
647
+ const prior = eidSummaryRecord(source);
648
+ const priorSecurityCounts = eidSummarySecurityCounts(prior);
649
+ const securityCounts = [];
650
+ let retainedEidCount = 0;
651
+ let retainedSecurityCount = 0;
652
+ for (const security in emitted) {
653
+ if (!Object.hasOwn(emitted, security)) {
654
+ continue;
655
+ }
656
+ const descriptor = ownEnumerableDescriptor(emitted, security);
657
+ if (descriptor === void 0 || !("value" in descriptor) || !Array.isArray(descriptor.value)) {
658
+ continue;
659
+ }
660
+ const retainedCount = descriptor.value.length;
661
+ const preparedCount = prepared.securityCounts[retainedSecurityCount];
662
+ const priorCount = priorSecurityCounts[retainedSecurityCount];
663
+ securityCounts.push({
664
+ originalCount: prior === void 0 ? preparedCount?.originalCount ?? retainedCount : priorCount?.originalCount ?? null,
665
+ retainedCount
666
+ });
667
+ retainedEidCount = Math.min(Number.MAX_SAFE_INTEGER, retainedEidCount + retainedCount);
668
+ retainedSecurityCount += 1;
669
+ }
670
+ const priorTotalEidCount = eidSummaryCount(prior, "totalEidCount");
671
+ const priorTotalSecurityCount = eidSummaryCount(prior, "totalSecurityCount");
672
+ const totalEidCount = prior === void 0 ? prepared.totalEidCount : priorTotalEidCount === void 0 ? null : priorTotalEidCount;
673
+ const totalSecurityCount = prior === void 0 ? prepared.totalSecurityCount : priorTotalSecurityCount === void 0 ? null : priorTotalSecurityCount;
674
+ const priorInvalidSecurityCount = eidSummaryCount(prior, "invalidSecurityCount");
675
+ const invalidSecurityCount = typeof priorInvalidSecurityCount === "number" ? priorInvalidSecurityCount : prepared.invalidSecurityCount;
676
+ const priorScannedSecurityCount = eidSummaryCount(prior, "scannedSecurityCount");
677
+ const scannedSecurityCount = typeof priorScannedSecurityCount === "number" ? priorScannedSecurityCount : prepared.scannedSecurityCount;
678
+ const omittedSecurityCount = totalSecurityCount === null ? null : Math.max(0, totalSecurityCount - retainedSecurityCount - invalidSecurityCount);
679
+ const truncated = prior !== void 0 || prepared.truncation !== void 0 || totalEidCount === null || totalSecurityCount === null || retainedEidCount !== totalEidCount || retainedSecurityCount + invalidSecurityCount !== totalSecurityCount;
680
+ if (!truncated) {
681
+ return void 0;
682
+ }
683
+ return {
684
+ retainedEidCount,
685
+ totalEidCount,
686
+ retainedSecurityCount,
687
+ totalSecurityCount,
688
+ securityCounts,
689
+ invalidSecurityCount,
690
+ omittedSecurityCount,
691
+ scannedSecurityCount
692
+ };
693
+ }
694
+ function appendBuiltProperty(accumulator, key, built, maximumJsonBytes, state) {
695
+ if (Object.hasOwn(accumulator.value, key)) {
696
+ return true;
697
+ }
698
+ const commaBytes = accumulator.propertyCount === 0 ? 0 : 1;
699
+ const availableForKey = maximumJsonBytes - accumulator.byteLength - commaBytes - 1 - built.byteLength;
700
+ if (availableForKey < 2) {
701
+ addReason(state, "max_result_bytes");
702
+ return false;
703
+ }
704
+ const keyBytes = jsonStringByteLength(key, availableForKey);
705
+ if (keyBytes > availableForKey) {
706
+ addReason(state, "max_result_bytes");
707
+ return false;
708
+ }
709
+ defineJsonProperty(accumulator.value, key, built.value);
710
+ accumulator.byteLength += commaBytes + keyBytes + 1 + built.byteLength;
711
+ accumulator.propertyCount += 1;
712
+ return true;
713
+ }
714
+ function buildProperty(source, key, accumulator, maximumJsonBytes, state, depth, rowLimit) {
715
+ const descriptor = ownEnumerableDescriptor(source, key);
716
+ if (descriptor === void 0) {
717
+ return true;
718
+ }
719
+ if (key === "eidDataTruncation" && ownEnumerableDescriptor(source, "eidData") !== void 0) {
720
+ return true;
721
+ }
722
+ const commaBytes = accumulator.propertyCount === 0 ? 0 : 1;
723
+ const availableForKeyAndChild = maximumJsonBytes - accumulator.byteLength - commaBytes - 1;
724
+ if (availableForKeyAndChild < 4) {
725
+ addReason(state, "max_result_bytes");
726
+ return false;
727
+ }
728
+ const maximumKeyBytes = availableForKeyAndChild - 2;
729
+ const keyBytes = jsonStringByteLength(key, maximumKeyBytes);
730
+ if (keyBytes > maximumKeyBytes) {
731
+ addReason(state, "max_result_bytes");
732
+ return false;
733
+ }
734
+ const childBudget = availableForKeyAndChild - keyBytes;
735
+ let rawValue;
736
+ if ("value" in descriptor) {
737
+ rawValue = descriptor.value;
738
+ } else {
739
+ addReason(state, "accessor_omitted");
740
+ rawValue = "[Accessor omitted]";
741
+ }
742
+ const errorKey = ERROR_SHAPE_KEYS[key.toLowerCase()] === true && hasReportedError(rawValue);
743
+ if (errorKey) {
744
+ state.hasErrors = true;
745
+ }
746
+ const useSharedRows = key === "rows" || key === "data" && Array.isArray(rawValue);
747
+ if (key === "eidData") {
748
+ const prepared = prepareEidData(rawValue, state);
749
+ const built2 = buildValue(
750
+ prepared.data,
751
+ Math.max(2, Math.floor(childBudget / 3)),
752
+ state,
753
+ depth + 1,
754
+ MAX_ENTITLEMENT_EIDS,
755
+ false
312
756
  );
313
- const metadata = arrayMetadata(value);
314
- if (Object.keys(metadata).length === 0) {
315
- return rows;
316
- }
317
- const output = { rows };
318
- for (const [key, entry] of Object.entries(metadata)) {
319
- if (key === "eidData") {
320
- const limited = limitEidData(entry, maxStringChars, state, depth + 1, seen);
321
- output.eidData = limited.data;
322
- if (limited.truncation !== void 0) {
323
- output.eidDataTruncation = limited.truncation;
757
+ if (built2 === OMIT || !appendBuiltProperty(accumulator, key, built2, maximumJsonBytes, state)) {
758
+ return false;
759
+ }
760
+ const emittedTruncation = emittedEidTruncation(source, built2.value, prepared);
761
+ if (emittedTruncation !== void 0) {
762
+ const summaryCommaBytes = accumulator.propertyCount === 0 ? 0 : 1;
763
+ const summaryKeyBytes = jsonStringByteLength("eidDataTruncation");
764
+ const summaryBudget = maximumJsonBytes - accumulator.byteLength - summaryCommaBytes - summaryKeyBytes - 1;
765
+ const summary = buildValue(
766
+ emittedTruncation,
767
+ summaryBudget,
768
+ state,
769
+ depth + 1,
770
+ MAX_EID_SECURITIES,
771
+ false
772
+ );
773
+ if (summary === OMIT || !appendBuiltProperty(accumulator, "eidDataTruncation", summary, maximumJsonBytes, state)) {
774
+ state.omittedPropertiesAtLeast += 1;
775
+ }
776
+ }
777
+ return true;
778
+ }
779
+ const built = buildValue(rawValue, childBudget, state, depth + 1, rowLimit, useSharedRows);
780
+ if (built === OMIT || !appendBuiltProperty(accumulator, key, built, maximumJsonBytes, state)) {
781
+ return false;
782
+ }
783
+ if (errorKey) {
784
+ rememberErrorDiagnostic(state, key, built.value);
785
+ }
786
+ if ((key === "truncated" || key === "truncatedInput") && rawValue === true) {
787
+ addReason(state, "upstream_truncation");
788
+ }
789
+ return true;
790
+ }
791
+ function hasArrayMetadata(value) {
792
+ for (const key of PRIORITY_KEYS) {
793
+ if (ownEnumerableDescriptor(value, key) !== void 0) {
794
+ return true;
795
+ }
796
+ }
797
+ return false;
798
+ }
799
+ function buildArrayRows(value, maximumJsonBytes, state, depth, rowLimit, useSharedRows) {
800
+ if (maximumJsonBytes < 2) {
801
+ addReason(state, "max_result_bytes");
802
+ return OMIT;
803
+ }
804
+ state.retainedNodes += 1;
805
+ const output = [];
806
+ let byteLength = 2;
807
+ let processedRows = 0;
808
+ const retainedLength = Math.min(
809
+ value.length,
810
+ rowLimit,
811
+ useSharedRows ? state.remainingRows : Number.MAX_SAFE_INTEGER
812
+ );
813
+ for (let index = 0; index < retainedLength; index += 1) {
814
+ const commaBytes = index === 0 ? 0 : 1;
815
+ const childBudget = maximumJsonBytes - byteLength - commaBytes;
816
+ const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
817
+ let entry = null;
818
+ if (descriptor !== void 0 && "value" in descriptor) {
819
+ entry = descriptor.value;
820
+ } else if (descriptor !== void 0) {
821
+ addReason(state, "accessor_omitted");
822
+ entry = "[Accessor omitted]";
823
+ }
824
+ const built = buildValue(entry, childBudget, state, depth + 1, rowLimit, false);
825
+ if (built === OMIT) {
826
+ break;
827
+ }
828
+ output.push(built.value);
829
+ byteLength += commaBytes + built.byteLength;
830
+ processedRows = index + 1;
831
+ }
832
+ if (useSharedRows) {
833
+ state.maximumArrayRows = Math.max(state.maximumArrayRows, processedRows);
834
+ }
835
+ if (useSharedRows) {
836
+ state.remainingRows -= processedRows;
837
+ state.retainedRows += processedRows;
838
+ }
839
+ if (retainedLength < value.length) {
840
+ addReason(state, "max_rows");
841
+ }
842
+ if (processedRows < value.length) {
843
+ state.omittedRows += value.length - processedRows;
844
+ }
845
+ return { byteLength, value: output };
846
+ }
847
+ function buildArray(value, maximumJsonBytes, state, depth, rowLimit, useSharedRows) {
848
+ if (state.ancestors.has(value)) {
849
+ return buildUnsupported("[Circular]", maximumJsonBytes, state, "circular_reference");
850
+ }
851
+ state.ancestors.add(value);
852
+ try {
853
+ if (!hasArrayMetadata(value)) {
854
+ return buildArrayRows(value, maximumJsonBytes, state, depth, rowLimit, useSharedRows);
855
+ }
856
+ if (maximumJsonBytes < 2) {
857
+ addReason(state, "max_result_bytes");
858
+ return OMIT;
859
+ }
860
+ state.retainedNodes += 1;
861
+ const accumulator = {
862
+ byteLength: 2,
863
+ propertyCount: 0,
864
+ value: /* @__PURE__ */ Object.create(null)
865
+ };
866
+ for (const key of PRIORITY_KEYS) {
867
+ const isErrorMetadata = key === "diagnostics" || ERROR_SHAPE_KEYS[key.toLowerCase()] === true;
868
+ if (state.rowsBeforeMetadata && !isErrorMetadata) {
869
+ continue;
870
+ }
871
+ if (!buildProperty(value, key, accumulator, maximumJsonBytes, state, depth, rowLimit)) {
872
+ state.omittedPropertiesAtLeast += 1;
873
+ }
874
+ }
875
+ const commaBytes = accumulator.propertyCount === 0 ? 0 : 1;
876
+ const rowsKeyBytes = jsonStringByteLength("rows");
877
+ const rowsBudget = maximumJsonBytes - accumulator.byteLength - commaBytes - rowsKeyBytes - 1;
878
+ const rows = consumeVisit(state) ? buildArrayRows(value, rowsBudget, state, depth + 1, rowLimit, useSharedRows) : OMIT;
879
+ if (rows === OMIT) {
880
+ state.omittedRows += value.length;
881
+ state.omittedPropertiesAtLeast += 1;
882
+ } else if (!appendBuiltProperty(accumulator, "rows", rows, maximumJsonBytes, state)) {
883
+ state.omittedRows += Math.min(value.length, rowLimit);
884
+ state.omittedPropertiesAtLeast += 1;
885
+ }
886
+ if (state.rowsBeforeMetadata) {
887
+ for (const key of PRIORITY_KEYS) {
888
+ if (key === "diagnostics" || ERROR_SHAPE_KEYS[key.toLowerCase()] === true) {
889
+ continue;
890
+ }
891
+ if (!buildProperty(value, key, accumulator, maximumJsonBytes, state, depth, rowLimit)) {
892
+ state.omittedPropertiesAtLeast += 1;
324
893
  }
894
+ }
895
+ }
896
+ return { byteLength: accumulator.byteLength, value: accumulator.value };
897
+ } finally {
898
+ state.ancestors.delete(value);
899
+ }
900
+ }
901
+ function buildObject(value, maximumJsonBytes, state, depth, rowLimit) {
902
+ if (state.ancestors.has(value)) {
903
+ return buildUnsupported("[Circular]", maximumJsonBytes, state, "circular_reference");
904
+ }
905
+ if (maximumJsonBytes < 2) {
906
+ addReason(state, "max_result_bytes");
907
+ return OMIT;
908
+ }
909
+ state.ancestors.add(value);
910
+ state.retainedNodes += 1;
911
+ try {
912
+ const accumulator = {
913
+ byteLength: 2,
914
+ propertyCount: 0,
915
+ value: /* @__PURE__ */ Object.create(null)
916
+ };
917
+ const processed = /* @__PURE__ */ new Set();
918
+ for (const key of PRIORITY_KEYS) {
919
+ processed.add(key);
920
+ if (!buildProperty(value, key, accumulator, maximumJsonBytes, state, depth, rowLimit)) {
921
+ state.omittedPropertiesAtLeast += 1;
922
+ }
923
+ }
924
+ for (const key in value) {
925
+ if (!Object.hasOwn(value, key) || processed.has(key)) {
325
926
  continue;
326
927
  }
327
- output[key] = limitValue(entry, maxRows, maxStringChars, state, depth + 1, seen);
928
+ if (!buildProperty(value, key, accumulator, maximumJsonBytes, state, depth, rowLimit)) {
929
+ state.omittedPropertiesAtLeast += 1;
930
+ break;
931
+ }
328
932
  }
329
- return output;
933
+ return { byteLength: accumulator.byteLength, value: accumulator.value };
934
+ } finally {
935
+ state.ancestors.delete(value);
330
936
  }
331
- if (typeof value === "object" && value !== null) {
332
- if (seen.has(value)) {
333
- state.truncated = true;
334
- return "[Circular]";
335
- }
336
- if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer) {
337
- state.truncated = true;
338
- return `[binary data: ${value.byteLength} bytes]`;
339
- }
340
- if (!isPlainObject(value)) {
341
- const toJSON = value.toJSON;
342
- if (typeof toJSON === "function") {
343
- seen.add(value);
344
- return limitValue(toJSON.call(value), maxRows, maxStringChars, state, depth + 1, seen);
937
+ }
938
+ function errorRecord(error) {
939
+ const record3 = {
940
+ message: error.message,
941
+ name: error.name
942
+ };
943
+ if (error.cause !== void 0) {
944
+ record3.cause = error.cause;
945
+ }
946
+ return record3;
947
+ }
948
+ var ACCESSOR_METHOD = /* @__PURE__ */ Symbol("accessor_method");
949
+ function isCallable(value) {
950
+ return typeof value === "function";
951
+ }
952
+ function dataMethod(value, name) {
953
+ let current = value;
954
+ try {
955
+ for (let depth = 0; current !== null && depth <= MAX_RESULT_DEPTH; depth += 1) {
956
+ const descriptor = Object.getOwnPropertyDescriptor(current, name);
957
+ if (descriptor !== void 0) {
958
+ if (!("value" in descriptor)) {
959
+ return ACCESSOR_METHOD;
960
+ }
961
+ const method = descriptor.value;
962
+ return isCallable(method) ? method : void 0;
345
963
  }
346
- return value;
964
+ current = Object.getPrototypeOf(current);
347
965
  }
348
- seen.add(value);
349
- const output = {};
350
- for (const [key, entry] of Object.entries(value)) {
351
- output[key] = limitValue(entry, maxRows, maxStringChars, state, depth + 1, seen);
966
+ } catch {
967
+ return ACCESSOR_METHOD;
968
+ }
969
+ return void 0;
970
+ }
971
+ function buildValue(value, maximumJsonBytes, state, depth, rowLimit, useSharedRows) {
972
+ if (!consumeVisit(state)) {
973
+ return OMIT;
974
+ }
975
+ if (depth > MAX_RESULT_DEPTH) {
976
+ return buildUnsupported(
977
+ "[Max result depth exceeded]",
978
+ maximumJsonBytes,
979
+ state,
980
+ "max_result_depth"
981
+ );
982
+ }
983
+ if (typeof value === "string") {
984
+ return fitString(value, maximumJsonBytes, state);
985
+ }
986
+ if (typeof value === "bigint") {
987
+ return fitString(value.toString(), maximumJsonBytes, state);
988
+ }
989
+ if (value === null || typeof value === "boolean") {
990
+ return primitiveBuilt(value, maximumJsonBytes, state);
991
+ }
992
+ if (typeof value === "number") {
993
+ const jsonValue = Number.isFinite(value) ? value : null;
994
+ if (jsonValue === null) {
995
+ addReason(state, "unsupported_value");
352
996
  }
353
- return output;
997
+ return primitiveBuilt(jsonValue, maximumJsonBytes, state);
998
+ }
999
+ if (typeof value === "undefined" || typeof value === "function" || typeof value === "symbol") {
1000
+ addReason(state, "unsupported_value");
1001
+ return primitiveBuilt(null, maximumJsonBytes, state);
1002
+ }
1003
+ if (value instanceof Date) {
1004
+ const milliseconds = value.getTime();
1005
+ if (!Number.isFinite(milliseconds)) {
1006
+ addReason(state, "unsupported_value");
1007
+ return fitString("[Invalid Date]", maximumJsonBytes, state);
1008
+ }
1009
+ return fitString(value.toISOString(), maximumJsonBytes, state);
1010
+ }
1011
+ if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer) {
1012
+ return buildUnsupported(
1013
+ `[binary data: ${String(value.byteLength)} bytes]`,
1014
+ maximumJsonBytes,
1015
+ state,
1016
+ "binary_data"
1017
+ );
1018
+ }
1019
+ if (Array.isArray(value)) {
1020
+ return buildArray(value, maximumJsonBytes, state, depth, rowLimit, useSharedRows);
1021
+ }
1022
+ if (value instanceof Error) {
1023
+ state.hasErrors = true;
1024
+ if (state.ancestors.has(value)) {
1025
+ return buildUnsupported("[Circular]", maximumJsonBytes, state, "circular_reference");
1026
+ }
1027
+ state.ancestors.add(value);
1028
+ try {
1029
+ const built = buildObject(errorRecord(value), maximumJsonBytes, state, depth, rowLimit);
1030
+ if (built !== OMIT) {
1031
+ rememberErrorDiagnostic(state, "error", built.value);
1032
+ }
1033
+ return built;
1034
+ } finally {
1035
+ state.ancestors.delete(value);
1036
+ }
1037
+ }
1038
+ let plainObject;
1039
+ try {
1040
+ plainObject = isPlainObject(value) ? value : void 0;
1041
+ } catch {
1042
+ return buildUnsupported("[Uninspectable object]", maximumJsonBytes, state);
1043
+ }
1044
+ if (plainObject !== void 0) {
1045
+ return buildObject(plainObject, maximumJsonBytes, state, depth, rowLimit);
1046
+ }
1047
+ const toJSON = dataMethod(value, "toJSON");
1048
+ if (toJSON === ACCESSOR_METHOD) {
1049
+ return buildUnsupported("[Accessor omitted]", maximumJsonBytes, state, "accessor_omitted");
1050
+ }
1051
+ if (toJSON === void 0) {
1052
+ return buildUnsupported("[Unsupported object]", maximumJsonBytes, state);
1053
+ }
1054
+ if (state.ancestors.has(value)) {
1055
+ return buildUnsupported("[Circular]", maximumJsonBytes, state, "circular_reference");
1056
+ }
1057
+ state.ancestors.add(value);
1058
+ try {
1059
+ let converted;
1060
+ try {
1061
+ converted = toJSON.call(value);
1062
+ } catch (error) {
1063
+ state.hasErrors = true;
1064
+ addReason(state, "unsupported_value");
1065
+ converted = {
1066
+ error: {
1067
+ message: error instanceof Error ? error.message : String(error),
1068
+ name: "toJSON"
1069
+ }
1070
+ };
1071
+ }
1072
+ return buildValue(converted, maximumJsonBytes, state, depth + 1, rowLimit, useSharedRows);
1073
+ } finally {
1074
+ state.ancestors.delete(value);
354
1075
  }
355
- return value;
356
1076
  }
357
1077
  function rowCountOf(value) {
358
1078
  if (Array.isArray(value)) {
@@ -362,104 +1082,339 @@ function rowCountOf(value) {
362
1082
  return null;
363
1083
  }
364
1084
  const record3 = value;
365
- const rowCount = record3.rowCount;
366
- if (typeof rowCount === "number" && Number.isInteger(rowCount) && rowCount >= 0) {
367
- return rowCount;
368
- }
369
- const updateCount = record3.updateCount;
370
- if (typeof updateCount === "number" && Number.isInteger(updateCount) && updateCount >= 0) {
371
- return updateCount;
1085
+ for (const key of ["rowCount", "updateCount"]) {
1086
+ const descriptor = ownEnumerableDescriptor(record3, key);
1087
+ if (descriptor !== void 0 && "value" in descriptor && typeof descriptor.value === "number" && Number.isSafeInteger(descriptor.value) && descriptor.value >= 0) {
1088
+ return descriptor.value;
1089
+ }
372
1090
  }
373
1091
  return null;
374
1092
  }
375
- var ERROR_SHAPE_KEYS = /* @__PURE__ */ new Set([
376
- "error",
377
- "errors",
378
- "fielderrors",
379
- "fieldexception",
380
- "fieldexceptions",
381
- "responseerror",
382
- "securityerror"
383
- ]);
384
- function hasErrorShape(value) {
385
- const pending = [value];
386
- const seen = /* @__PURE__ */ new WeakSet();
387
- while (pending.length > 0) {
388
- const entry = pending.pop();
389
- if (typeof entry !== "object" || entry === null) {
390
- continue;
391
- }
392
- if (seen.has(entry)) {
393
- continue;
394
- }
395
- seen.add(entry);
396
- if (Array.isArray(entry)) {
397
- for (const child of entry) {
398
- pending.push(child);
399
- }
400
- continue;
401
- }
402
- for (const [key, child] of Object.entries(entry)) {
403
- if (ERROR_SHAPE_KEYS.has(key.toLowerCase()) && child !== void 0) {
404
- return true;
405
- }
406
- pending.push(child);
1093
+ function truncationSummary(state) {
1094
+ if (state.reasons.size === 0) {
1095
+ return void 0;
1096
+ }
1097
+ return {
1098
+ reasons: TRUNCATION_REASON_ORDER.filter((reason) => state.reasons.has(reason)),
1099
+ inspectedNodes: state.visitedNodes,
1100
+ retainedNodes: state.retainedNodes,
1101
+ ...state.omittedPropertiesAtLeast === 0 ? {} : { omittedPropertiesAtLeast: state.omittedPropertiesAtLeast },
1102
+ ...state.omittedRows === 0 ? {} : { omittedRows: state.omittedRows }
1103
+ };
1104
+ }
1105
+ function validateResultLimits(limits) {
1106
+ for (const name of ["maxResultBytes", "maxResultNodes", "maxRows", "maxStringChars"]) {
1107
+ const value = limits[name];
1108
+ if (!Number.isSafeInteger(value) || value <= 0) {
1109
+ throw new RangeError(`${name} must be a positive safe integer; got ${String(value)}`);
407
1110
  }
408
1111
  }
409
- return false;
1112
+ if (limits.maxResultBytes < 4) {
1113
+ throw new RangeError(`maxResultBytes must be at least 4; got ${String(limits.maxResultBytes)}`);
1114
+ }
410
1115
  }
411
- function limitResult(value, maxRows, maxStringChars) {
412
- const state = { truncated: false };
1116
+ function limitResultWithRowPriority(value, limits, rowsBeforeMetadata) {
1117
+ validateResultLimits(limits);
1118
+ const state = {
1119
+ ancestors: /* @__PURE__ */ new WeakSet(),
1120
+ diagnostics: [],
1121
+ hasErrors: false,
1122
+ maximumArrayRows: 0,
1123
+ limits,
1124
+ omittedPropertiesAtLeast: 0,
1125
+ omittedRows: 0,
1126
+ remainingRows: limits.maxRows,
1127
+ reasons: /* @__PURE__ */ new Set(),
1128
+ retainedNodes: 0,
1129
+ retainedRows: 0,
1130
+ rowsBeforeMetadata,
1131
+ visitedNodes: 0
1132
+ };
413
1133
  const rowCount = rowCountOf(value);
414
- const limitedValue = limitValue(value, maxRows, maxStringChars, state);
1134
+ const built = buildValue(value, limits.maxResultBytes, state, 0, limits.maxRows, true);
1135
+ const result = built === OMIT ? { byteLength: 4, value: null } : built;
1136
+ if (built === OMIT) {
1137
+ addReason(state, "max_result_bytes");
1138
+ }
1139
+ const truncation = truncationSummary(state);
415
1140
  return {
1141
+ byteLength: result.byteLength,
1142
+ errorDiagnostics: state.diagnostics,
1143
+ inspectedNodes: state.visitedNodes,
1144
+ maximumArrayRows: state.maximumArrayRows,
1145
+ retainedRows: state.retainedRows,
1146
+ hasErrors: state.hasErrors,
416
1147
  rowCount,
417
- truncated: state.truncated,
418
- value: limitedValue
1148
+ truncated: truncation !== void 0,
1149
+ ...truncation === void 0 ? {} : { truncation },
1150
+ value: result.value
1151
+ };
1152
+ }
1153
+ function artifactEnvelope(tool2, limited, truncation) {
1154
+ return {
1155
+ tool: tool2,
1156
+ rowCount: limited.rowCount,
1157
+ truncated: limited.truncated,
1158
+ ...truncation === void 0 ? {} : { truncation },
1159
+ ...limited.hasErrors ? { hasErrors: true } : {},
1160
+ data: limited.value
1161
+ };
1162
+ }
1163
+ function boundedJsonByteLength(value) {
1164
+ return UTF8_ENCODER.encode(JSON.stringify(value)).byteLength;
1165
+ }
1166
+ function mergeLimited(first, second) {
1167
+ const reasons = new Set(first.truncation?.reasons ?? []);
1168
+ for (const reason of second.truncation?.reasons ?? []) {
1169
+ reasons.add(reason);
1170
+ }
1171
+ const retainedNodes = second.truncation?.retainedNodes ?? first.truncation?.retainedNodes;
1172
+ const omittedPropertiesAtLeast = (first.truncation?.omittedPropertiesAtLeast ?? 0) + (second.truncation?.omittedPropertiesAtLeast ?? 0);
1173
+ const omittedRows = (first.truncation?.omittedRows ?? 0) + (second.truncation?.omittedRows ?? 0);
1174
+ const truncation = reasons.size === 0 ? void 0 : {
1175
+ reasons: TRUNCATION_REASON_ORDER.filter((reason) => reasons.has(reason)),
1176
+ inspectedNodes: first.inspectedNodes + second.inspectedNodes,
1177
+ ...retainedNodes === void 0 ? {} : { retainedNodes },
1178
+ ...omittedPropertiesAtLeast === 0 ? {} : { omittedPropertiesAtLeast },
1179
+ ...omittedRows === 0 ? {} : { omittedRows }
1180
+ };
1181
+ return {
1182
+ byteLength: second.byteLength,
1183
+ maximumArrayRows: second.maximumArrayRows,
1184
+ retainedRows: second.retainedRows,
1185
+ errorDiagnostics: second.errorDiagnostics.length === 0 ? first.errorDiagnostics : second.errorDiagnostics,
1186
+ hasErrors: first.hasErrors || second.hasErrors,
1187
+ inspectedNodes: first.inspectedNodes + second.inspectedNodes,
1188
+ rowCount: first.rowCount,
1189
+ truncated: truncation !== void 0,
1190
+ ...truncation === void 0 ? {} : { truncation },
1191
+ value: second.value
1192
+ };
1193
+ }
1194
+ function fitArtifact(tool2, limited, maxResultBytes) {
1195
+ let envelope = artifactEnvelope(tool2, limited, limited.truncation);
1196
+ if (boundedJsonByteLength(envelope) <= maxResultBytes) {
1197
+ return envelope;
1198
+ }
1199
+ const fitLimited = limited.truncated ? limited : { ...limited, truncated: true };
1200
+ const reasons = limited.truncation?.reasons ?? ["max_result_bytes"];
1201
+ envelope = artifactEnvelope(tool2, fitLimited, { reasons });
1202
+ if (boundedJsonByteLength(envelope) <= maxResultBytes) {
1203
+ return envelope;
1204
+ }
1205
+ const primaryReason = reasons.find((reason) => reason !== "max_result_bytes") ?? "max_result_bytes";
1206
+ const compactReasons = primaryReason === "max_result_bytes" ? [primaryReason] : [primaryReason, "max_result_bytes"];
1207
+ envelope = artifactEnvelope(tool2, fitLimited, { reasons: compactReasons });
1208
+ if (boundedJsonByteLength(envelope) <= maxResultBytes) {
1209
+ return envelope;
1210
+ }
1211
+ envelope = artifactEnvelope(tool2, fitLimited, {
1212
+ reasons: ["max_result_bytes"]
1213
+ });
1214
+ if (boundedJsonByteLength(envelope) <= maxResultBytes) {
1215
+ return envelope;
1216
+ }
1217
+ return {
1218
+ tool: tool2,
1219
+ rowCount: limited.rowCount,
1220
+ truncated: true,
1221
+ truncation: { reasons: ["max_result_bytes"] },
1222
+ ...limited.hasErrors ? { hasErrors: true } : {},
1223
+ data: null
419
1224
  };
420
1225
  }
421
- function summarizeEnvelope(envelope) {
422
- const rowText = envelope.rowCount === null ? "row count unknown" : `${envelope.rowCount} row${envelope.rowCount === 1 ? "" : "s"}`;
1226
+ function rowText(rowCount) {
1227
+ return rowCount === null ? "row count unknown" : `${String(rowCount)} row${rowCount === 1 ? "" : "s"}`;
1228
+ }
1229
+ function summarizeEnvelope(envelope, contentTruncation) {
423
1230
  const notes = [];
424
- if (envelope.rowCount === 0 || envelope.data === null || envelope.data === void 0) {
1231
+ if (envelope.rowCount === 0 || !envelope.truncated && (envelope.data === null || envelope.data === void 0)) {
425
1232
  notes.push(
426
1233
  "empty result; verify identifiers, fields, and date range before concluding no data exists"
427
1234
  );
428
1235
  }
429
- if (envelope.truncated) {
430
- notes.push("artifact truncated to configured limits");
431
- }
432
- if (hasErrorShape(envelope.data)) {
433
- notes.push("inspect result payload for Bloomberg error details");
1236
+ if (envelope.hasErrors === true) {
1237
+ notes.push("Bloomberg error diagnostics included in preview");
434
1238
  }
1239
+ const artifactReasons = envelope.truncation?.reasons.join(",") ?? "none";
1240
+ const contentReasons = contentTruncation?.reasons.join(",") ?? "none";
435
1241
  const noteText = notes.length === 0 ? "" : `; ${notes.join("; ")}`;
436
- return `${envelope.tool}: ${rowText}; truncated=${String(envelope.truncated)}${noteText}`;
437
- }
438
- function resultJsonReplacer(_key, value) {
439
- if (typeof value === "bigint") {
440
- return value.toString();
441
- }
442
- return value;
1242
+ return `${envelope.tool}: ${rowText(envelope.rowCount)}; artifactTruncated=${String(envelope.truncated)}; contentTruncated=${String(contentTruncation !== void 0)}; artifactReasons=${artifactReasons}; contentReasons=${contentReasons}${noteText}`;
443
1243
  }
444
- function formatToolContent(envelope) {
445
- const payload = {
1244
+ function contentPayload(envelope, limited) {
1245
+ const projected = limited.value;
1246
+ return {
446
1247
  tool: envelope.tool,
447
1248
  rowCount: envelope.rowCount,
448
1249
  truncated: envelope.truncated,
449
- data: envelope.data
1250
+ contentTruncated: limited.truncated,
1251
+ ...projected ?? { data: null }
450
1252
  };
451
- return `${summarizeEnvelope(envelope)}
452
- ${JSON.stringify(payload, resultJsonReplacer)}`;
453
1253
  }
454
- function createToolResult(tool2, value, maxRows, maxStringChars) {
455
- const limited = limitResult(value, maxRows, maxStringChars);
456
- const envelope = {
457
- tool: tool2,
458
- rowCount: limited.rowCount,
459
- truncated: limited.truncated,
460
- data: limited.value
1254
+ function formatToolContent(envelope, preview, maxContentBytes) {
1255
+ const firstPreviewValue = preview.value;
1256
+ const summary = summarizeEnvelope(envelope, preview.truncation);
1257
+ const payload = contentPayload(envelope, preview);
1258
+ const content = `${summary}
1259
+ ${JSON.stringify(payload)}`;
1260
+ if (UTF8_ENCODER.encode(content).byteLength <= maxContentBytes) {
1261
+ return content;
1262
+ }
1263
+ const compactSummary = `${envelope.tool}: ${rowText(envelope.rowCount)}; artifactTruncated=${String(envelope.truncated)}; contentTruncated=${String(preview.truncated)}; hasErrors=${String(envelope.hasErrors === true)}`;
1264
+ const compactContent = `${compactSummary}
1265
+ ${JSON.stringify(firstPreviewValue)}`;
1266
+ if (UTF8_ENCODER.encode(compactContent).byteLength <= maxContentBytes) {
1267
+ return compactContent;
1268
+ }
1269
+ return compactSummary;
1270
+ }
1271
+ function exhaustedProjection(rowCount) {
1272
+ return {
1273
+ byteLength: 4,
1274
+ maximumArrayRows: 0,
1275
+ retainedRows: 0,
1276
+ errorDiagnostics: [],
1277
+ hasErrors: false,
1278
+ inspectedNodes: 0,
1279
+ rowCount,
1280
+ truncated: true,
1281
+ truncation: {
1282
+ inspectedNodes: 0,
1283
+ reasons: ["max_result_nodes"],
1284
+ retainedNodes: 0
1285
+ },
1286
+ value: null
1287
+ };
1288
+ }
1289
+ function projectResult(value, limits, rowsBeforeMetadata) {
1290
+ return limits.maxResultNodes === 0 ? exhaustedProjection(rowCountOf(value)) : limitResultWithRowPriority(value, limits, rowsBeforeMetadata);
1291
+ }
1292
+ function withAggregateInspection(limited, inspectedNodes) {
1293
+ return {
1294
+ ...limited,
1295
+ inspectedNodes,
1296
+ ...limited.truncation === void 0 ? {} : {
1297
+ truncation: {
1298
+ ...limited.truncation,
1299
+ inspectedNodes
1300
+ }
1301
+ }
461
1302
  };
462
- return [formatToolContent(envelope), envelope];
1303
+ }
1304
+ function reusedProjection(value, canonical) {
1305
+ return {
1306
+ byteLength: boundedJsonByteLength(value),
1307
+ errorDiagnostics: [],
1308
+ hasErrors: false,
1309
+ inspectedNodes: 0,
1310
+ maximumArrayRows: canonical.maximumArrayRows,
1311
+ retainedRows: canonical.retainedRows,
1312
+ rowCount: rowCountOf(value),
1313
+ truncated: false,
1314
+ value
1315
+ };
1316
+ }
1317
+ function canReuseProjection(canonical, byteLength, maxBytes, maxRows) {
1318
+ return byteLength <= maxBytes && canonical.maximumArrayRows <= maxRows;
1319
+ }
1320
+ function createToolResult(tool2, value, limits) {
1321
+ const initialInspectedNodes = limits.materializedNodes ?? 0;
1322
+ if (limits.maxResultBytes < MIN_TOOL_RESULT_BYTES) {
1323
+ throw new RangeError(
1324
+ `maxResultBytes must be at least ${String(MIN_TOOL_RESULT_BYTES)}; got ${String(limits.maxResultBytes)}`
1325
+ );
1326
+ }
1327
+ if (limits.maxContentBytes < MIN_TOOL_RESULT_BYTES) {
1328
+ throw new RangeError(
1329
+ `maxContentBytes must be at least ${String(MIN_TOOL_RESULT_BYTES)}; got ${String(limits.maxContentBytes)}`
1330
+ );
1331
+ }
1332
+ if (limits.maxResultNodes < MIN_TOOL_RESULT_NODES) {
1333
+ throw new RangeError(
1334
+ `maxResultNodes must be at least ${String(MIN_TOOL_RESULT_NODES)}; got ${String(limits.maxResultNodes)}`
1335
+ );
1336
+ }
1337
+ validateResultLimits(limits);
1338
+ if (!Number.isSafeInteger(initialInspectedNodes) || initialInspectedNodes < 0 || initialInspectedNodes > limits.maxResultNodes) {
1339
+ throw new RangeError(
1340
+ `materializedNodes must be between 0 and maxResultNodes; got ${String(initialInspectedNodes)}`
1341
+ );
1342
+ }
1343
+ const availableNodeBudget = limits.maxResultNodes - initialInspectedNodes;
1344
+ const hasEidMetadata = typeof value === "object" && value !== null && ownEnumerableDescriptor(value, "eidData") !== void 0;
1345
+ const canonicalNodeBudget = availableNodeBudget === 0 ? 0 : Math.max(
1346
+ 1,
1347
+ hasEidMetadata ? availableNodeBudget - Math.ceil(availableNodeBudget / 5) : Math.floor(availableNodeBudget / 3)
1348
+ );
1349
+ const canonical = projectResult(
1350
+ value,
1351
+ {
1352
+ maxResultBytes: Math.max(limits.maxResultBytes, limits.maxContentBytes),
1353
+ maxResultNodes: canonicalNodeBudget,
1354
+ maxRows: Math.max(limits.maxRows, limits.maxContentRows),
1355
+ maxStringChars: limits.maxStringChars
1356
+ },
1357
+ false
1358
+ );
1359
+ const artifactDataBudget = projectionBudget(limits.maxResultBytes, RESULT_ENVELOPE_RESERVE_BYTES);
1360
+ const contentDataBudget = projectionBudget(
1361
+ limits.maxContentBytes,
1362
+ CONTENT_ENVELOPE_RESERVE_BYTES
1363
+ );
1364
+ const contentSource = /* @__PURE__ */ Object.create(null);
1365
+ if (canonical.errorDiagnostics.length > 0) {
1366
+ contentSource.diagnostics = canonical.errorDiagnostics;
1367
+ }
1368
+ contentSource.data = canonical.value;
1369
+ const contentSourceBytes = boundedJsonByteLength(contentSource);
1370
+ const reuseArtifact = canReuseProjection(
1371
+ canonical,
1372
+ canonical.byteLength,
1373
+ artifactDataBudget,
1374
+ limits.maxRows
1375
+ );
1376
+ const reuseContent = canReuseProjection(
1377
+ canonical,
1378
+ contentSourceBytes,
1379
+ contentDataBudget,
1380
+ limits.maxContentRows
1381
+ );
1382
+ const remainingNodeBudget = Math.max(0, availableNodeBudget - canonical.inspectedNodes);
1383
+ const artifactNeedsNodes = !reuseArtifact;
1384
+ const contentNeedsNodes = !reuseContent;
1385
+ const artifactNodeBudget = artifactNeedsNodes ? contentNeedsNodes ? Math.floor(remainingNodeBudget / 2) : remainingNodeBudget : 0;
1386
+ const contentNodeBudget = contentNeedsNodes ? remainingNodeBudget - artifactNodeBudget : 0;
1387
+ const artifactProjection = reuseArtifact ? reusedProjection(canonical.value, canonical) : projectResult(
1388
+ canonical.value,
1389
+ {
1390
+ maxResultBytes: artifactDataBudget,
1391
+ maxResultNodes: artifactNodeBudget,
1392
+ maxRows: limits.maxRows,
1393
+ maxStringChars: Number.MAX_SAFE_INTEGER
1394
+ },
1395
+ false
1396
+ );
1397
+ const contentProjection = reuseContent ? reusedProjection(contentSource, canonical) : projectResult(
1398
+ contentSource,
1399
+ {
1400
+ maxResultBytes: contentDataBudget,
1401
+ maxResultNodes: contentNodeBudget,
1402
+ maxRows: limits.maxContentRows,
1403
+ maxStringChars: Number.MAX_SAFE_INTEGER
1404
+ },
1405
+ true
1406
+ );
1407
+ const inspectedNodes = initialInspectedNodes + canonical.inspectedNodes + artifactProjection.inspectedNodes + contentProjection.inspectedNodes;
1408
+ const artifactResult = withAggregateInspection(
1409
+ mergeLimited(canonical, artifactProjection),
1410
+ inspectedNodes
1411
+ );
1412
+ const contentResult = withAggregateInspection(
1413
+ mergeLimited(canonical, contentProjection),
1414
+ inspectedNodes
1415
+ );
1416
+ const envelope = fitArtifact(tool2, artifactResult, limits.maxResultBytes);
1417
+ return [formatToolContent(envelope, contentResult, limits.maxContentBytes), envelope];
463
1418
  }
464
1419
  function throwWithToolContext(tool2, error) {
465
1420
  const prefix = `${tool2} failed`;
@@ -475,7 +1430,82 @@ function throwWithToolContext(tool2, error) {
475
1430
  }
476
1431
 
477
1432
  // src/langchain-tool.ts
1433
+ var INPUT_JSON_SCHEMA_CACHE = /* @__PURE__ */ new WeakMap();
1434
+ function freezeJsonSchema(root) {
1435
+ const pending = [root];
1436
+ const seen = /* @__PURE__ */ new WeakSet();
1437
+ while (pending.length > 0) {
1438
+ const value = pending.pop();
1439
+ if (value === void 0 || seen.has(value)) {
1440
+ continue;
1441
+ }
1442
+ seen.add(value);
1443
+ for (const rawChild of Object.values(value)) {
1444
+ const child = rawChild;
1445
+ if (typeof child === "object" && child !== null) {
1446
+ pending.push(child);
1447
+ }
1448
+ }
1449
+ Object.freeze(value);
1450
+ }
1451
+ return root;
1452
+ }
1453
+ function cloneJsonSchemaValue(value, seen, active) {
1454
+ if (value === null || typeof value === "string" || typeof value === "boolean") {
1455
+ return value;
1456
+ }
1457
+ if (typeof value === "number") {
1458
+ if (!Number.isFinite(value)) {
1459
+ throw new TypeError("JSON Schema numbers must be finite");
1460
+ }
1461
+ return value;
1462
+ }
1463
+ if (typeof value !== "object") {
1464
+ throw new TypeError(`JSON Schema contains unsupported ${typeof value} value`);
1465
+ }
1466
+ const cached = seen.get(value);
1467
+ if (cached !== void 0) {
1468
+ if (active.has(value)) {
1469
+ throw new TypeError("JSON Schema must not contain object cycles");
1470
+ }
1471
+ return cached;
1472
+ }
1473
+ const output = Array.isArray(value) ? [] : {};
1474
+ seen.set(value, output);
1475
+ active.add(value);
1476
+ try {
1477
+ for (const key of Object.keys(value)) {
1478
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
1479
+ if (descriptor === void 0 || !("value" in descriptor)) {
1480
+ throw new TypeError(`JSON Schema property ${key} must not be an accessor`);
1481
+ }
1482
+ Object.defineProperty(output, key, {
1483
+ configurable: true,
1484
+ enumerable: true,
1485
+ value: cloneJsonSchemaValue(descriptor.value, seen, active),
1486
+ writable: true
1487
+ });
1488
+ }
1489
+ } finally {
1490
+ active.delete(value);
1491
+ }
1492
+ return output;
1493
+ }
1494
+ function cachedRawJsonSchema(schema) {
1495
+ const cached = INPUT_JSON_SCHEMA_CACHE.get(schema);
1496
+ if (cached !== void 0) {
1497
+ return cached;
1498
+ }
1499
+ const clone = cloneJsonSchemaValue(schema, /* @__PURE__ */ new WeakMap(), /* @__PURE__ */ new WeakSet());
1500
+ const immutable = freezeJsonSchema(clone);
1501
+ INPUT_JSON_SCHEMA_CACHE.set(schema, immutable);
1502
+ return immutable;
1503
+ }
478
1504
  function inputJsonSchema(schema) {
1505
+ const cached = INPUT_JSON_SCHEMA_CACHE.get(schema);
1506
+ if (cached !== void 0) {
1507
+ return cached;
1508
+ }
479
1509
  const jsonSchema = zodToJsonSchema.zodToJsonSchema(schema, {
480
1510
  $refStrategy: "none",
481
1511
  effectStrategy: "input",
@@ -483,12 +1513,14 @@ function inputJsonSchema(schema) {
483
1513
  });
484
1514
  delete jsonSchema.$schema;
485
1515
  delete jsonSchema.definitions;
486
- return jsonSchema;
1516
+ const immutable = freezeJsonSchema(jsonSchema);
1517
+ INPUT_JSON_SCHEMA_CACHE.set(schema, immutable);
1518
+ return immutable;
487
1519
  }
488
1520
  function toolParameterJsonSchema(toolInstance) {
489
1521
  const schema = toolInstance.schema;
490
1522
  if (schema !== null && typeof schema === "object" && !("safeParse" in schema)) {
491
- return schema;
1523
+ return cachedRawJsonSchema(schema);
492
1524
  }
493
1525
  return inputJsonSchema(schema);
494
1526
  }
@@ -1347,7 +2379,7 @@ function chartSpecSchema(options) {
1347
2379
 
1348
2380
  // src/ext-tools.ts
1349
2381
  function resultString(resolver, name, value) {
1350
- return createToolResult(name, value, resolver.options.maxRows, resolver.options.maxStringChars);
2382
+ return createToolResult(name, value, resolver.options);
1351
2383
  }
1352
2384
  function recoveryOverrides(recoveryRate) {
1353
2385
  return recoveryRate === void 0 ? void 0 : { CDS_RR: recoveryRate };
@@ -1821,8 +2853,8 @@ var OVERFLOW_POLICIES = ["block", "drop_newest"];
1821
2853
  var OVERFLOW_POLICY_DEFAULT = "drop_newest";
1822
2854
  var OVERFLOW_POLICY_VALUES = "block, drop_newest";
1823
2855
  var OVERFLOW_POLICY_DOCS = {
1824
- block: "Retry within a short bounded window on Bloomberg's callback thread, then flag a slow consumer and drop the update.",
1825
- drop_newest: "Drop the newest update as soon as the buffer is full; never stalls Bloomberg's callback thread."
2856
+ block: "Wait briefly on a bounded forwarding task, never on Bloomberg's callback thread; queue overflow or timeout closes with a data-loss error. Resubscribe for a fresh image.",
2857
+ drop_newest: "Close with a data-loss error when the consumer buffer is full; never waits on Bloomberg's callback thread. Resubscribe for a fresh image."
1826
2858
  };
1827
2859
 
1828
2860
  // src/schemas.ts
@@ -2543,7 +3575,7 @@ function createDepthSnapshotSchema(options) {
2543
3575
 
2544
3576
  // src/tools.ts
2545
3577
  function resultString2(resolver, name, value) {
2546
- return createToolResult(name, value, resolver.options.maxRows, resolver.options.maxStringChars);
3578
+ return createToolResult(name, value, resolver.options);
2547
3579
  }
2548
3580
  var STREAM_TIMEOUT = /* @__PURE__ */ Symbol("stream_timeout");
2549
3581
  var STREAM_ABORTED = /* @__PURE__ */ Symbol("stream_aborted");
@@ -2567,57 +3599,48 @@ function singleTickerStreamOptions(input) {
2567
3599
  function isRecord(value) {
2568
3600
  return typeof value === "object" && value !== null;
2569
3601
  }
2570
- function rowsFromArrowTable(value) {
3602
+ function truncatedArrowRows(rows, rowCount) {
3603
+ return {
3604
+ rows,
3605
+ rowCount,
3606
+ truncated: true,
3607
+ truncation: {
3608
+ omittedRowsAtLeast: rowCount - rows.length,
3609
+ reason: "max_rows"
3610
+ }
3611
+ };
3612
+ }
3613
+ function rowsFromArrowTable(value, maxRows) {
2571
3614
  if (!isRecord(value)) {
2572
3615
  return void 0;
2573
3616
  }
2574
- const toArray = value.toArray;
2575
- if (typeof toArray === "function") {
2576
- return Array.from(toArray.call(value));
2577
- }
2578
3617
  const numRows = value.numRows;
2579
3618
  const get = value.get;
2580
- if (typeof numRows === "number" && Number.isInteger(numRows) && typeof get === "function") {
3619
+ if (typeof numRows === "number" && Number.isSafeInteger(numRows) && numRows >= 0 && typeof get === "function") {
3620
+ const retainedRows = Math.min(numRows, maxRows);
2581
3621
  const rows = [];
2582
- for (let index = 0; index < numRows; index += 1) {
3622
+ for (let index = 0; index < retainedRows; index += 1) {
2583
3623
  rows.push(get.call(value, index));
2584
3624
  }
2585
- return rows;
3625
+ return {
3626
+ materializedRows: retainedRows,
3627
+ value: retainedRows === numRows ? rows : truncatedArrowRows(rows, numRows)
3628
+ };
2586
3629
  }
2587
3630
  return void 0;
2588
3631
  }
2589
- function jsonCompatible(value) {
2590
- if (typeof value === "bigint") {
2591
- return value.toString();
3632
+ function normalizeStreamUpdate(value, maxRows) {
3633
+ const arrowRows = rowsFromArrowTable(value, maxRows);
3634
+ if (arrowRows !== void 0) {
3635
+ return arrowRows;
2592
3636
  }
2593
- if (value instanceof Date) {
2594
- return value.toISOString();
2595
- }
2596
- if (Array.isArray(value)) {
2597
- return value.map(jsonCompatible);
2598
- }
2599
- if (!isRecord(value)) {
2600
- return value;
2601
- }
2602
- const toJSON = value.toJSON;
2603
- if (typeof toJSON === "function") {
2604
- return jsonCompatible(toJSON.call(value));
2605
- }
2606
- const output = {};
2607
- for (const [key, entry] of Object.entries(value)) {
2608
- output[key] = jsonCompatible(entry);
2609
- }
2610
- return output;
2611
- }
2612
- function normalizeStreamUpdate(value) {
2613
3637
  if (isRecord(value)) {
2614
3638
  const toObject = value.toObject;
2615
3639
  if (typeof toObject === "function") {
2616
- return jsonCompatible(toObject.call(value));
3640
+ return { materializedRows: 0, value: toObject.call(value) };
2617
3641
  }
2618
3642
  }
2619
- const rows = rowsFromArrowTable(value);
2620
- return rows === void 0 ? jsonCompatible(value) : rows.map(jsonCompatible);
3643
+ return { materializedRows: 0, value };
2621
3644
  }
2622
3645
  async function nextWithinTimeout(iterator, deadlineMs, signal) {
2623
3646
  if (signal?.aborted === true) {
@@ -2656,9 +3679,11 @@ async function nextWithinTimeout(iterator, deadlineMs, signal) {
2656
3679
  }
2657
3680
  return result;
2658
3681
  }
2659
- async function collectSnapshot(subscription, input, signal) {
3682
+ async function collectSnapshot(subscription, input, signal, maxRows, maxResultNodes) {
2660
3683
  const updates = [];
2661
3684
  const deadlineMs = Date.now() + input.timeoutMs;
3685
+ const arrowRowAllowance = Math.min(maxRows, Math.floor(maxResultNodes / 3));
3686
+ let remainingArrowRows = arrowRowAllowance;
2662
3687
  let reason = "max_updates";
2663
3688
  let failed = false;
2664
3689
  let caught;
@@ -2676,7 +3701,9 @@ async function collectSnapshot(subscription, input, signal) {
2676
3701
  reason = "done";
2677
3702
  break;
2678
3703
  }
2679
- updates.push(normalizeStreamUpdate(next.value));
3704
+ const normalized = normalizeStreamUpdate(next.value, remainingArrowRows);
3705
+ updates.push(normalized.value);
3706
+ remainingArrowRows -= normalized.materializedRows;
2680
3707
  }
2681
3708
  } catch (error) {
2682
3709
  failed = true;
@@ -2695,12 +3722,15 @@ async function collectSnapshot(subscription, input, signal) {
2695
3722
  throw caught;
2696
3723
  }
2697
3724
  return {
2698
- maxUpdates: input.maxUpdates,
2699
- reason,
2700
- timeoutMs: input.timeoutMs,
2701
- updateCount: updates.length,
2702
- updates,
2703
- ...unsubscribeError === void 0 ? {} : { unsubscribeError }
3725
+ materializedRows: arrowRowAllowance - remainingArrowRows,
3726
+ result: {
3727
+ maxUpdates: input.maxUpdates,
3728
+ reason,
3729
+ timeoutMs: input.timeoutMs,
3730
+ updateCount: updates.length,
3731
+ updates,
3732
+ ...unsubscribeError === void 0 ? {} : { unsubscribeError }
3733
+ }
2704
3734
  };
2705
3735
  }
2706
3736
  function validationSetting(resolver, value) {
@@ -2865,12 +3895,10 @@ function checkEntitlementsWithResolver(resolver) {
2865
3895
  try {
2866
3896
  const engine = await resolver.getEngine();
2867
3897
  const result = await engine.checkEntitlements(input.service ?? "//blp/refdata", input.eids);
2868
- return createToolResult(
2869
- name,
2870
- result,
2871
- MAX_ENTITLEMENT_EIDS,
2872
- resolver.options.maxStringChars
2873
- );
3898
+ return createToolResult(name, result, {
3899
+ ...resolver.options,
3900
+ maxRows: MAX_ENTITLEMENT_EIDS
3901
+ });
2874
3902
  } catch (error) {
2875
3903
  throwWithToolContext(name, error);
2876
3904
  }
@@ -3180,8 +4208,17 @@ function streamSnapshotWithResolver(resolver) {
3180
4208
  const engine = await resolver.getEngine();
3181
4209
  signal?.throwIfAborted();
3182
4210
  const subscription = await engine.stream(input.tickers, input.fields, streamOptions(input));
3183
- const result = await collectSnapshot(subscription, input, signal);
3184
- return resultString2(resolver, name, result);
4211
+ const snapshot = await collectSnapshot(
4212
+ subscription,
4213
+ input,
4214
+ signal,
4215
+ Math.max(resolver.options.maxRows, resolver.options.maxContentRows),
4216
+ resolver.options.maxResultNodes
4217
+ );
4218
+ return createToolResult(name, snapshot.result, {
4219
+ ...resolver.options,
4220
+ materializedNodes: snapshot.materializedRows
4221
+ });
3185
4222
  } catch (error) {
3186
4223
  throwWithToolContext(name, error);
3187
4224
  }
@@ -3203,8 +4240,17 @@ function mktbarSnapshotWithResolver(resolver) {
3203
4240
  const engine = await resolver.getEngine();
3204
4241
  signal?.throwIfAborted();
3205
4242
  const subscription = await engine.mktbar(input.ticker, singleTickerStreamOptions(input));
3206
- const result = await collectSnapshot(subscription, input, signal);
3207
- return resultString2(resolver, name, result);
4243
+ const snapshot = await collectSnapshot(
4244
+ subscription,
4245
+ input,
4246
+ signal,
4247
+ Math.max(resolver.options.maxRows, resolver.options.maxContentRows),
4248
+ resolver.options.maxResultNodes
4249
+ );
4250
+ return createToolResult(name, snapshot.result, {
4251
+ ...resolver.options,
4252
+ materializedNodes: snapshot.materializedRows
4253
+ });
3208
4254
  } catch (error) {
3209
4255
  throwWithToolContext(name, error);
3210
4256
  }
@@ -3226,8 +4272,17 @@ function depthSnapshotWithResolver(resolver) {
3226
4272
  const engine = await resolver.getEngine();
3227
4273
  signal?.throwIfAborted();
3228
4274
  const subscription = await engine.depth(input.ticker, singleTickerStreamOptions(input));
3229
- const result = await collectSnapshot(subscription, input, signal);
3230
- return resultString2(resolver, name, result);
4275
+ const snapshot = await collectSnapshot(
4276
+ subscription,
4277
+ input,
4278
+ signal,
4279
+ Math.max(resolver.options.maxRows, resolver.options.maxContentRows),
4280
+ resolver.options.maxResultNodes
4281
+ );
4282
+ return createToolResult(name, snapshot.result, {
4283
+ ...resolver.options,
4284
+ materializedNodes: snapshot.materializedRows
4285
+ });
3231
4286
  } catch (error) {
3232
4287
  throwWithToolContext(name, error);
3233
4288
  }