bitfab 0.53.0 → 0.53.1

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.
@@ -99,7 +99,7 @@ function encodeRequestBody(body) {
99
99
  }
100
100
 
101
101
  // src/version.generated.ts
102
- var __version__ = "0.53.0";
102
+ var __version__ = "0.53.1";
103
103
  var __packageName__ = "bitfab";
104
104
 
105
105
  // src/constants.ts
@@ -385,8 +385,8 @@ function encodePayloadBody(payload) {
385
385
  const marker = { error: `payload_serialize_failed: ${message}` };
386
386
  return { body: JSON.stringify(marker), dropped, value: marker };
387
387
  }
388
- const isRecord = typeof sanitized === "object" && sanitized !== null && !Array.isArray(sanitized);
389
- if (dropped.length > 0 && isRecord) {
388
+ const isRecord3 = typeof sanitized === "object" && sanitized !== null && !Array.isArray(sanitized);
389
+ if (dropped.length > 0 && isRecord3) {
390
390
  const obj = sanitized;
391
391
  const existing = Array.isArray(obj.errors) ? obj.errors : [];
392
392
  obj.errors = [
@@ -403,11 +403,431 @@ function encodePayloadBody(payload) {
403
403
  return {
404
404
  body: JSON.stringify(sanitized),
405
405
  dropped,
406
- value: isRecord ? sanitized : void 0
406
+ value: isRecord3 ? sanitized : void 0
407
407
  };
408
408
  }
409
409
  }
410
410
 
411
+ // src/policyRefresh.ts
412
+ var PolicyRefresh = class {
413
+ constructor() {
414
+ this.refreshAfter = 0;
415
+ }
416
+ due() {
417
+ return this.inFlight === void 0 && Date.now() >= this.refreshAfter;
418
+ }
419
+ hold(durationMs) {
420
+ this.refreshAfter = Date.now() + durationMs;
421
+ }
422
+ releaseHold() {
423
+ this.refreshAfter = 0;
424
+ }
425
+ run(read, onLoaded, onFailed) {
426
+ if (!this.due()) {
427
+ return;
428
+ }
429
+ let request;
430
+ try {
431
+ request = read().then(onLoaded).catch(onFailed).finally(() => {
432
+ this.inFlight = void 0;
433
+ });
434
+ } catch (error) {
435
+ onFailed(error);
436
+ return;
437
+ }
438
+ this.inFlight = request;
439
+ }
440
+ };
441
+
442
+ // src/spanOrigin.ts
443
+ var SPAN_ORIGIN_NAME = "bitfab.sdk.typescript";
444
+ var SPAN_INSTRUMENTATIONS = [
445
+ "span",
446
+ "trace",
447
+ "openai-agents",
448
+ "langgraph",
449
+ "claude-agent-sdk",
450
+ "vercel-ai"
451
+ ];
452
+ var FRAMEWORK_INSTRUMENTATIONS = [
453
+ "openai-agents",
454
+ "langgraph",
455
+ "claude-agent-sdk",
456
+ "vercel-ai"
457
+ ];
458
+ var FRAMEWORK_INSTRUMENTATION_SET = new Set(
459
+ FRAMEWORK_INSTRUMENTATIONS
460
+ );
461
+ function isFrameworkInstrumentation(value) {
462
+ return typeof value === "string" && FRAMEWORK_INSTRUMENTATION_SET.has(value);
463
+ }
464
+ function makeSpanOrigin(instrumentation) {
465
+ return {
466
+ name: SPAN_ORIGIN_NAME,
467
+ version: __version__,
468
+ instrumentation: { name: instrumentation }
469
+ };
470
+ }
471
+ function isRecord(value) {
472
+ return typeof value === "object" && value !== null && !Array.isArray(value);
473
+ }
474
+ function spanOriginOf(payload) {
475
+ const rawSpan = payload.rawSpan;
476
+ if (!isRecord(rawSpan)) {
477
+ return void 0;
478
+ }
479
+ const origin = rawSpan.span_origin;
480
+ if (!isRecord(origin) || !isRecord(origin.instrumentation)) {
481
+ return void 0;
482
+ }
483
+ const { name, version } = origin;
484
+ const instrumentation = origin.instrumentation.name;
485
+ if (typeof name !== "string" || typeof version !== "string" || typeof instrumentation !== "string" || !SPAN_INSTRUMENTATIONS.includes(instrumentation)) {
486
+ return void 0;
487
+ }
488
+ return {
489
+ name,
490
+ version,
491
+ instrumentation: { name: instrumentation }
492
+ };
493
+ }
494
+ function spanInstrumentationOf(payload) {
495
+ return spanOriginOf(payload)?.instrumentation.name;
496
+ }
497
+ function recordedByFramework(payload) {
498
+ return isFrameworkInstrumentation(spanInstrumentationOf(payload));
499
+ }
500
+
501
+ // src/unrefTimer.ts
502
+ function unrefTimer(timer) {
503
+ const handle = timer;
504
+ if (typeof handle.unref === "function") {
505
+ handle.unref();
506
+ }
507
+ }
508
+
509
+ // src/simulationPlan.ts
510
+ var SIMULATION_PLAN_REFRESH_MS = 6e4;
511
+ var SIMULATION_PLAN_RETRY_MS = 1e4;
512
+ var SIMULATION_PLAN_READ_TIMEOUT_MS = 5e3;
513
+ var SIMULATION_PLAN_MAX_HELD = 1e3;
514
+ var DISABLE_SIMULATION_PLAN_ENV = "BITFAB_DISABLE_SIM_PLAN";
515
+ var ROOT_TRACE_FUNCTION_KEY_FIELD = "rootTraceFunctionKey";
516
+ var CONTENT_OFF_KEY = "content_off_by_simulation_plan";
517
+ var CONTENT_KEYS = ["input", "input_meta", "output", "output_meta"];
518
+ function planWaitSliceMs(timeoutMs) {
519
+ return Math.min(SIMULATION_PLAN_READ_TIMEOUT_MS, Math.max(timeoutMs, 0) / 2);
520
+ }
521
+ function parseSimulationPlan(body) {
522
+ if (typeof body !== "object" || body === null) {
523
+ return null;
524
+ }
525
+ const nodes = body.nodes;
526
+ if (!Array.isArray(nodes)) {
527
+ return null;
528
+ }
529
+ const contentOff = /* @__PURE__ */ new Map();
530
+ for (const node of nodes) {
531
+ if (typeof node !== "object" || node === null) {
532
+ continue;
533
+ }
534
+ const { traceFunctionKey, name, captureContent } = node;
535
+ if (typeof traceFunctionKey !== "string" || typeof name !== "string" || typeof captureContent !== "boolean") {
536
+ continue;
537
+ }
538
+ if (captureContent) {
539
+ continue;
540
+ }
541
+ const names = contentOff.get(traceFunctionKey) ?? /* @__PURE__ */ new Set();
542
+ names.add(name);
543
+ contentOff.set(traceFunctionKey, names);
544
+ }
545
+ return contentOff;
546
+ }
547
+ function traceIdOf(payload) {
548
+ const traceId = payload.traceId;
549
+ if (typeof traceId === "string") {
550
+ return traceId;
551
+ }
552
+ const id = payload.id;
553
+ return typeof id === "string" ? id : void 0;
554
+ }
555
+ function isRecord2(value) {
556
+ return typeof value === "object" && value !== null;
557
+ }
558
+ function rawSpanOf(payload) {
559
+ return isRecord2(payload.rawSpan) ? payload.rawSpan : void 0;
560
+ }
561
+ function spanDataOf(payload) {
562
+ const spanData = rawSpanOf(payload)?.span_data;
563
+ return isRecord2(spanData) ? spanData : void 0;
564
+ }
565
+ function spanNameOf(payload) {
566
+ const name = spanDataOf(payload)?.name;
567
+ return typeof name === "string" ? name : void 0;
568
+ }
569
+ function stripContent(payload) {
570
+ const rawSpan = rawSpanOf(payload);
571
+ const spanData = spanDataOf(payload);
572
+ if (rawSpan === void 0 || spanData === void 0) {
573
+ return payload;
574
+ }
575
+ const kept = { ...spanData };
576
+ for (const key of CONTENT_KEYS) {
577
+ delete kept[key];
578
+ }
579
+ kept[CONTENT_OFF_KEY] = true;
580
+ return { ...payload, rawSpan: { ...rawSpan, span_data: kept } };
581
+ }
582
+ function simulationPlanEnvDisabled() {
583
+ const value = readEnv(DISABLE_SIMULATION_PLAN_ENV);
584
+ return typeof value === "string" && value.trim() !== "";
585
+ }
586
+ function missingSimulationPlanEndpoint(error) {
587
+ return error instanceof BitfabError && error.status === 404;
588
+ }
589
+ var SimulationPlan = class {
590
+ constructor(source, enabled = true) {
591
+ this.source = source;
592
+ this.enabled = enabled;
593
+ this.policyRefresh = new PolicyRefresh();
594
+ this.retryPending = false;
595
+ this.waitingForFirstLoad = 0;
596
+ this.held = [];
597
+ this.droppedWhileHolding = 0;
598
+ this.stopped = false;
599
+ this.loaded = new Promise((resolve) => {
600
+ this.resolveLoaded = resolve;
601
+ });
602
+ }
603
+ disabled() {
604
+ return !this.enabled || simulationPlanEnvDisabled();
605
+ }
606
+ refresh() {
607
+ if (this.stopped || this.disabled()) {
608
+ return;
609
+ }
610
+ this.policyRefresh.run(
611
+ () => this.source.getSimulationPlan(),
612
+ (body) => {
613
+ const parsed = parseSimulationPlan(body);
614
+ if (parsed === null) {
615
+ this.scheduleRetry(
616
+ "sim-plan-unreadable",
617
+ "the sim plan response was not understood"
618
+ );
619
+ return;
620
+ }
621
+ this.markLoaded(parsed);
622
+ },
623
+ (error) => {
624
+ if (missingSimulationPlanEndpoint(error)) {
625
+ this.markLoaded(/* @__PURE__ */ new Map());
626
+ return;
627
+ }
628
+ this.scheduleRetry(
629
+ "sim-plan-unavailable",
630
+ `could not read the sim plan: ${error instanceof Error ? error.message : String(error)}`
631
+ );
632
+ }
633
+ );
634
+ }
635
+ markLoaded(parsed) {
636
+ if (this.stopped) {
637
+ return;
638
+ }
639
+ this.contentOffByKey = parsed;
640
+ this.policyRefresh.hold(SIMULATION_PLAN_REFRESH_MS);
641
+ this.retryPending = false;
642
+ this.clearRetryTimer();
643
+ this.resolveLoaded?.();
644
+ this.resolveLoaded = void 0;
645
+ this.releaseHeld();
646
+ }
647
+ scheduleRetry(warnKey, reason) {
648
+ if (this.stopped) {
649
+ return;
650
+ }
651
+ this.policyRefresh.hold(SIMULATION_PLAN_RETRY_MS);
652
+ if (this.contentOffByKey !== void 0) {
653
+ return;
654
+ }
655
+ this.retryPending = true;
656
+ warnOnce(
657
+ warnKey,
658
+ `${reason}. Spans are held until the first read succeeds; while a record is held it is retried every ${SIMULATION_PLAN_RETRY_MS / 1e3}s, otherwise on the next span.`
659
+ );
660
+ this.armRetry();
661
+ }
662
+ holdsWork() {
663
+ return this.held.length > 0 || this.waitingForFirstLoad > 0;
664
+ }
665
+ armRetry() {
666
+ if (this.stopped || !this.retryPending || this.retryTimer !== void 0 || !this.holdsWork()) {
667
+ return;
668
+ }
669
+ const timer = setTimeout(() => {
670
+ this.retryTimer = void 0;
671
+ this.policyRefresh.releaseHold();
672
+ this.refresh();
673
+ }, SIMULATION_PLAN_RETRY_MS);
674
+ unrefTimer(timer);
675
+ this.retryTimer = timer;
676
+ }
677
+ clearRetryTimer() {
678
+ if (this.retryTimer !== void 0) {
679
+ clearTimeout(this.retryTimer);
680
+ this.retryTimer = void 0;
681
+ }
682
+ }
683
+ syncRetryTimer() {
684
+ if (this.holdsWork()) {
685
+ return;
686
+ }
687
+ this.clearRetryTimer();
688
+ }
689
+ firstLoad() {
690
+ if (this.contentOffByKey !== void 0 || this.stopped || this.disabled()) {
691
+ return void 0;
692
+ }
693
+ return this.loaded;
694
+ }
695
+ send(payload, traceFunctionKey, submit) {
696
+ this.refresh();
697
+ if (this.stopped || this.disabled() || traceFunctionKey === void 0 || spanNameOf(payload) === void 0 || recordedByFramework(payload)) {
698
+ submit(payload);
699
+ return;
700
+ }
701
+ if (this.contentOffByKey === void 0) {
702
+ this.hold({ payload, traceFunctionKey, submit });
703
+ return;
704
+ }
705
+ this.submitEntry({ payload, traceFunctionKey, submit });
706
+ }
707
+ sendTrace(payload, submit) {
708
+ this.refresh();
709
+ if (this.stopped || this.disabled() || this.contentOffByKey !== void 0 || !this.holdsSpanOfTrace(traceIdOf(payload))) {
710
+ submit(payload);
711
+ return;
712
+ }
713
+ this.hold({ payload, traceFunctionKey: void 0, submit });
714
+ }
715
+ holdsSpanOfTrace(traceId) {
716
+ if (traceId === void 0) {
717
+ return false;
718
+ }
719
+ return this.held.some(
720
+ (entry) => entry.traceFunctionKey !== void 0 && traceIdOf(entry.payload) === traceId
721
+ );
722
+ }
723
+ hold(entry) {
724
+ this.held.push(entry);
725
+ while (this.held.length > SIMULATION_PLAN_MAX_HELD) {
726
+ this.held.shift();
727
+ this.droppedWhileHolding += 1;
728
+ }
729
+ this.armRetry();
730
+ }
731
+ submitEntry(entry) {
732
+ try {
733
+ entry.submit(
734
+ entry.traceFunctionKey === void 0 ? entry.payload : this.apply(entry.payload, entry.traceFunctionKey)
735
+ );
736
+ } catch (error) {
737
+ warnOnce(
738
+ "sim-plan-held-span-dropped",
739
+ `a span held for the sim plan was dropped when released: ${error instanceof Error ? error.message : String(error)}`
740
+ );
741
+ }
742
+ }
743
+ releaseHeld() {
744
+ const held = this.held;
745
+ this.held = [];
746
+ this.syncRetryTimer();
747
+ this.warnDropped();
748
+ for (const entry of held) {
749
+ this.submitEntry(entry);
750
+ }
751
+ }
752
+ warnDropped() {
753
+ if (this.droppedWhileHolding === 0) {
754
+ return;
755
+ }
756
+ const dropped = this.droppedWhileHolding;
757
+ this.droppedWhileHolding = 0;
758
+ warnOnce(
759
+ "sim-plan-held-overflow",
760
+ `${dropped} record(s) were dropped while the sim plan was still loading; at most ${SIMULATION_PLAN_MAX_HELD} are held per client.`
761
+ );
762
+ }
763
+ warnNeverLoaded() {
764
+ if (this.held.length === 0) {
765
+ return;
766
+ }
767
+ warnOnce(
768
+ "sim-plan-never-loaded",
769
+ `${this.held.length} record(s) were not sent because the sim plan never loaded`
770
+ );
771
+ }
772
+ async release(timeoutMs) {
773
+ this.refresh();
774
+ if (this.holdsWork()) {
775
+ await this.waitForFirstLoad(timeoutMs);
776
+ }
777
+ this.warnNeverLoaded();
778
+ this.warnDropped();
779
+ }
780
+ waitForFirstLoad(timeoutMs) {
781
+ const firstLoad = this.firstLoad();
782
+ if (firstLoad === void 0) {
783
+ return Promise.resolve();
784
+ }
785
+ this.waitingForFirstLoad += 1;
786
+ this.armRetry();
787
+ return new Promise((resolve) => {
788
+ let settled = false;
789
+ const finish = () => {
790
+ if (settled) {
791
+ return;
792
+ }
793
+ settled = true;
794
+ this.waitingForFirstLoad -= 1;
795
+ this.syncRetryTimer();
796
+ resolve();
797
+ };
798
+ const timer = setTimeout(finish, Math.max(timeoutMs, 0));
799
+ void firstLoad.then(() => {
800
+ clearTimeout(timer);
801
+ finish();
802
+ });
803
+ });
804
+ }
805
+ stop() {
806
+ if (this.stopped) {
807
+ return;
808
+ }
809
+ this.stopped = true;
810
+ this.retryPending = false;
811
+ this.clearRetryTimer();
812
+ this.warnNeverLoaded();
813
+ this.held = [];
814
+ this.warnDropped();
815
+ }
816
+ contentOff(traceFunctionKey, spanName) {
817
+ return this.contentOffByKey?.get(traceFunctionKey)?.has(spanName) === true;
818
+ }
819
+ apply(payload, traceFunctionKey) {
820
+ if (recordedByFramework(payload)) {
821
+ return payload;
822
+ }
823
+ const name = spanNameOf(payload);
824
+ if (name === void 0 || !this.contentOff(traceFunctionKey, name)) {
825
+ return payload;
826
+ }
827
+ return stripContent(payload);
828
+ }
829
+ };
830
+
411
831
  // src/traceMetadata.ts
412
832
  var RETAINED_COMPLETED_TRACES = 128;
413
833
  var activeRecords = /* @__PURE__ */ new Map();
@@ -523,14 +943,6 @@ var DeliveryError = class extends Error {
523
943
  }
524
944
  };
525
945
 
526
- // src/unrefTimer.ts
527
- function unrefTimer(timer) {
528
- const handle = timer;
529
- if (typeof handle.unref === "function") {
530
- handle.unref();
531
- }
532
- }
533
-
534
946
  // src/otel.ts
535
947
  var OPERATION_ATTRIBUTE = "bitfab.operation";
536
948
  var PAYLOAD_ATTRIBUTE = "bitfab.payload";
@@ -1153,6 +1565,18 @@ var RETRYABLE_STATUSES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
1153
1565
  var EXIT_FLUSH_TIMEOUT_MS = 5e3;
1154
1566
  var DEFAULT_LIFECYCLE_TIMEOUT_MS2 = 3e4;
1155
1567
  var pendingTracePromises = /* @__PURE__ */ new Set();
1568
+ var liveHttpClients = /* @__PURE__ */ new Set();
1569
+ async function releaseHeldExternalSpans(timeoutMs) {
1570
+ const deadline = Date.now() + Math.max(timeoutMs, 0);
1571
+ for (const client of [...liveHttpClients]) {
1572
+ await client.releaseHeldExternalSpans?.(Math.max(0, deadline - Date.now()));
1573
+ }
1574
+ }
1575
+ function stopSimulationPlans() {
1576
+ for (const client of [...liveHttpClients]) {
1577
+ client.stopSimulationPlan?.();
1578
+ }
1579
+ }
1156
1580
  function awaitOnExit(promise) {
1157
1581
  pendingTracePromises.add(promise);
1158
1582
  void promise.finally(() => {
@@ -1163,7 +1587,10 @@ function awaitOnExit(promise) {
1163
1587
  }
1164
1588
  async function flushTraces(timeoutMs = 5e3) {
1165
1589
  const deadline = Date.now() + Math.max(timeoutMs, 0);
1166
- const requestsFlushed = await awaitPendingRequests(timeoutMs);
1590
+ await releaseHeldExternalSpans(planWaitSliceMs(timeoutMs));
1591
+ const requestsFlushed = await awaitPendingRequests(
1592
+ Math.max(0, deadline - Date.now())
1593
+ );
1167
1594
  const transportsFlushed = await flushTraceTransports(
1168
1595
  Math.max(0, deadline - Date.now())
1169
1596
  );
@@ -1200,12 +1627,27 @@ if (typeof process !== "undefined" && process.versions != null && process.versio
1200
1627
  return;
1201
1628
  }
1202
1629
  isFlushing = true;
1203
- void Promise.allSettled([
1204
- ...Array.from(pendingTracePromises).map((p) => p.catch(() => {
1205
- })),
1206
- shutdownTraceTransports(EXIT_FLUSH_TIMEOUT_MS).catch(() => false)
1207
- ]).then(() => {
1630
+ const planWaitMs = SIMULATION_PLAN_READ_TIMEOUT_MS;
1631
+ const stopFlushing = () => {
1208
1632
  isFlushing = false;
1633
+ };
1634
+ const deadline = setTimeout(
1635
+ stopFlushing,
1636
+ EXIT_FLUSH_TIMEOUT_MS + planWaitMs
1637
+ );
1638
+ unrefTimer(deadline);
1639
+ void releaseHeldExternalSpans(planWaitMs).catch(() => {
1640
+ }).then(() => {
1641
+ stopSimulationPlans();
1642
+ }).then(
1643
+ () => Promise.allSettled([
1644
+ ...Array.from(pendingTracePromises).map((p) => p.catch(() => {
1645
+ })),
1646
+ shutdownTraceTransports(EXIT_FLUSH_TIMEOUT_MS).catch(() => false)
1647
+ ])
1648
+ ).then(() => {
1649
+ clearTimeout(deadline);
1650
+ stopFlushing();
1209
1651
  });
1210
1652
  });
1211
1653
  }
@@ -1299,6 +1741,21 @@ function sourceTraceIdOf(payload) {
1299
1741
  return typeof id === "string" ? id : void 0;
1300
1742
  }
1301
1743
  var carrierSeq = 0;
1744
+ function describeError(error) {
1745
+ return error instanceof Error ? error.message : String(error);
1746
+ }
1747
+ function warnDroppedExternalSpan(error) {
1748
+ warnOnce(
1749
+ "external-span-dropped",
1750
+ `a span was dropped because the send step failed: ${describeError(error)}`
1751
+ );
1752
+ }
1753
+ function warnDroppedExternalTrace(error) {
1754
+ warnOnce(
1755
+ "external-trace-dropped",
1756
+ `a trace was dropped because the send step failed: ${describeError(error)}`
1757
+ );
1758
+ }
1302
1759
  var HttpClient = class {
1303
1760
  constructor(config) {
1304
1761
  // Only traces a caller asked about are tracked, so ordinary tracing stores
@@ -1313,6 +1770,7 @@ var HttpClient = class {
1313
1770
  this.apiKey = config.apiKey;
1314
1771
  this.serviceUrl = config.serviceUrl;
1315
1772
  this.timeout = config.timeout ?? 12e4;
1773
+ liveHttpClients.add(this);
1316
1774
  }
1317
1775
  /**
1318
1776
  * Resolve the API key at the moment it is needed (request time), invoking
@@ -1510,9 +1968,14 @@ var HttpClient = class {
1510
1968
  * attributing its timeout here would fail a client whose own work succeeded.
1511
1969
  */
1512
1970
  async settleDeferredWork(timeoutMs = DEFAULT_LIFECYCLE_TIMEOUT_MS2) {
1971
+ const deadline = Date.now() + Math.max(timeoutMs, 0);
1972
+ await this.releaseHeldExternalSpans?.(planWaitSliceMs(timeoutMs));
1513
1973
  await replayContextReady.catch(() => {
1514
1974
  });
1515
- return waitForPromises(Array.from(this.deferredWork), timeoutMs);
1975
+ return waitForPromises(
1976
+ Array.from(this.deferredWork),
1977
+ Math.max(0, deadline - Date.now())
1978
+ );
1516
1979
  }
1517
1980
  /**
1518
1981
  * Wait for spans queued by this client to be delivered, within one deadline.
@@ -1520,7 +1983,9 @@ var HttpClient = class {
1520
1983
  */
1521
1984
  async waitForPendingRequests(timeoutMs = DEFAULT_LIFECYCLE_TIMEOUT_MS2) {
1522
1985
  const deadline = Date.now() + Math.max(timeoutMs, 0);
1523
- const settled = await this.settleDeferredWork(timeoutMs);
1986
+ const settled = await this.settleDeferredWork(
1987
+ Math.max(0, deadline - Date.now())
1988
+ );
1524
1989
  const flushed = await this.traceTransport?.flush(Math.max(0, deadline - Date.now())) ?? true;
1525
1990
  return settled && flushed;
1526
1991
  }
@@ -1535,6 +2000,13 @@ var HttpClient = class {
1535
2000
  }
1536
2001
  const deadline = Date.now() + Math.max(timeoutMs, 0);
1537
2002
  this.closing = (async () => {
2003
+ await this.releaseHeldExternalSpans?.(planWaitSliceMs(timeoutMs));
2004
+ this.stopSimulationPlan?.();
2005
+ this.externalSpanTransform = void 0;
2006
+ this.externalTraceTransform = void 0;
2007
+ this.releaseHeldExternalSpans = void 0;
2008
+ this.stopSimulationPlan = void 0;
2009
+ liveHttpClients.delete(this);
1538
2010
  const settled = await this.settleDeferredWork(
1539
2011
  Math.max(0, deadline - Date.now())
1540
2012
  );
@@ -1646,6 +2118,13 @@ var HttpClient = class {
1646
2118
  protocol
1647
2119
  });
1648
2120
  }
2121
+ async getSimulationPlan() {
2122
+ return this.get(
2123
+ "/api/sdk/sim-plan",
2124
+ SIMULATION_PLAN_READ_TIMEOUT_MS,
2125
+ { Connection: "close" }
2126
+ );
2127
+ }
1649
2128
  async getTraceSpan(traceId, lookup) {
1650
2129
  const searchParams = new URLSearchParams();
1651
2130
  if (lookup.id !== void 0) {
@@ -1662,14 +2141,18 @@ var HttpClient = class {
1662
2141
  * GET a JSON endpoint on the service with the client's API key. Throws a
1663
2142
  * `BitfabError` carrying the status text for any non-2xx response.
1664
2143
  */
1665
- async get(endpoint) {
2144
+ async get(endpoint, timeoutMs, extraHeaders) {
1666
2145
  const url = `${this.serviceUrl}${endpoint}`;
2146
+ const timeout = timeoutMs ?? this.timeout;
1667
2147
  const controller = new AbortController();
1668
- const timeoutId = setTimeout(() => controller.abort(), this.timeout);
2148
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
1669
2149
  try {
1670
2150
  const response = await fetch(url, {
1671
2151
  method: "GET",
1672
- headers: { Authorization: `Bearer ${this.resolveApiKey() ?? ""}` },
2152
+ headers: {
2153
+ Authorization: `Bearer ${this.resolveApiKey() ?? ""}`,
2154
+ ...extraHeaders
2155
+ },
1673
2156
  signal: controller.signal
1674
2157
  });
1675
2158
  if (!response.ok) {
@@ -1688,7 +2171,7 @@ var HttpClient = class {
1688
2171
  }
1689
2172
  if (error instanceof Error) {
1690
2173
  if (error.name === "AbortError") {
1691
- throw new BitfabError(`Request timed out after ${this.timeout}ms`);
2174
+ throw new BitfabError(`Request timed out after ${timeout}ms`);
1692
2175
  }
1693
2176
  throw new BitfabError(error.message);
1694
2177
  }
@@ -1715,16 +2198,27 @@ var HttpClient = class {
1715
2198
  carrierMeta("internal_trace", body, void 0)
1716
2199
  );
1717
2200
  }
1718
- /**
1719
- * Queue an external span (from withSpan wrapper or OpenAI tracing) onto this
1720
- * client's batching transport. Fire-and-forget: the transport owns delivery,
1721
- * so callers await `flushTraces()` or `close()` rather than a per-span
1722
- * promise.
1723
- */
1724
2201
  sendExternalSpan(payload) {
2202
+ const gate = this.externalSpanTransform;
2203
+ if (gate === void 0) {
2204
+ this.submitExternalSpan(payload);
2205
+ return;
2206
+ }
2207
+ try {
2208
+ gate(payload, (ready) => this.submitExternalSpan(ready));
2209
+ } catch (error) {
2210
+ warnDroppedExternalSpan(error);
2211
+ }
2212
+ }
2213
+ submitExternalSpan(payload) {
2214
+ const body = {
2215
+ ...payload,
2216
+ sdkVersion: __version__
2217
+ };
2218
+ delete body[ROOT_TRACE_FUNCTION_KEY_FIELD];
1725
2219
  this.getTraceTransport()?.submit(
1726
2220
  "external_span",
1727
- { ...payload, sdkVersion: __version__ },
2221
+ body,
1728
2222
  this.recordedMeta("external_span", payload, carrierRef(payload))
1729
2223
  );
1730
2224
  }
@@ -1736,6 +2230,18 @@ var HttpClient = class {
1736
2230
  */
1737
2231
  sendExternalTrace(rawPayload) {
1738
2232
  const payload = mergeCallerMetadataIntoTracePayload(rawPayload);
2233
+ const gate = this.externalTraceTransform;
2234
+ if (gate === void 0) {
2235
+ this.submitExternalTrace(payload);
2236
+ return;
2237
+ }
2238
+ try {
2239
+ gate(payload, (ready) => this.submitExternalTrace(ready));
2240
+ } catch (error) {
2241
+ warnDroppedExternalTrace(error);
2242
+ }
2243
+ }
2244
+ submitExternalTrace(payload) {
1739
2245
  this.getTraceTransport()?.submit(
1740
2246
  "external_trace",
1741
2247
  {
@@ -1983,6 +2489,10 @@ export {
1983
2489
  MAX_COMPRESSIBLE_SPAN_CARRIER_BYTES,
1984
2490
  warnOnce,
1985
2491
  serializePayloadBody,
2492
+ PolicyRefresh,
2493
+ makeSpanOrigin,
2494
+ ROOT_TRACE_FUNCTION_KEY_FIELD,
2495
+ SimulationPlan,
1986
2496
  recordCallerTraceMetadata,
1987
2497
  callerTraceMetadata,
1988
2498
  retireTraceMetadata,
@@ -1992,4 +2502,4 @@ export {
1992
2502
  parseRetryAfterMs,
1993
2503
  HttpClient
1994
2504
  };
1995
- //# sourceMappingURL=chunk-6IMGAODW.js.map
2505
+ //# sourceMappingURL=chunk-ASMHSKFS.js.map