bitfab 0.52.0 → 0.52.2

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.d.cts CHANGED
@@ -536,7 +536,7 @@ declare class HttpClient {
536
536
  * {@link HttpClient.sendExternalSpan}; replay confirms persistence with the
537
537
  * server-authoritative barrier in `replay.ts`, not by awaiting this call.
538
538
  */
539
- sendExternalTrace(payload: Record<string, unknown>): void;
539
+ sendExternalTrace(rawPayload: Record<string, unknown>): void;
540
540
  /**
541
541
  * Partial update of an existing trace identified by its Bitfab trace ID.
542
542
  * Used by the detached `client.getTrace(id)` handle.
@@ -1656,12 +1656,16 @@ interface ReplayOptions {
1656
1656
  * Maximum number of traces to replay (1-5,000, default 5). Ignored when
1657
1657
  * `traceIds` is passed (with a warning), or when `datasetId` / `datasetIds`
1658
1658
  * is passed, because either source already determines how many traces replay.
1659
+ * To replay part of a dataset selection, name the members to run in
1660
+ * `traceIds` rather than bounding it here.
1659
1661
  */
1660
1662
  limit?: number;
1661
1663
  attempts?: number;
1662
1664
  /**
1663
- * Optional list of specific trace IDs to replay (max 100). Mutually exclusive
1664
- * with `datasetId` and `datasetIds`.
1665
+ * Optional list of specific trace IDs to replay (max 100). Passed alongside
1666
+ * `datasetId` or `datasetIds` it pins which members of that selection replay,
1667
+ * and the server rejects any ID none of those datasets contains. On its own
1668
+ * it selects by ID with no dataset attribution.
1665
1669
  */
1666
1670
  traceIds?: string[];
1667
1671
  /** Optional display name for the resulting experiment/test run. */
@@ -1719,8 +1723,9 @@ interface ReplayOptions {
1719
1723
  /** Group ID to associate this replay with an experiment group for live streaming in Studio. */
1720
1724
  experimentGroupId?: string;
1721
1725
  /**
1722
- * Dataset this replay runs against. Mutually exclusive with `traceIds` and
1723
- * with `datasetIds`. When set, the resulting experiment is
1726
+ * Dataset this replay runs against. Mutually exclusive with `datasetIds`.
1727
+ * Alone it replays the dataset's full membership, and with `traceIds` it
1728
+ * replays only those members. When set, the resulting experiment is
1724
1729
  * durably attributed to the dataset (stored on the test run), so it appears
1725
1730
  * under the dataset's experiments even if the trace lineage can't be
1726
1731
  * reconstructed. Validated server-side against the org.
@@ -3288,7 +3293,7 @@ declare class BitfabFunction {
3288
3293
  /**
3289
3294
  * SDK version from package.json (injected at build time)
3290
3295
  */
3291
- declare const __version__ = "0.52.0";
3296
+ declare const __version__ = "0.52.2";
3292
3297
 
3293
3298
  /**
3294
3299
  * Constants for the Bitfab SDK.
package/dist/index.d.ts CHANGED
@@ -536,7 +536,7 @@ declare class HttpClient {
536
536
  * {@link HttpClient.sendExternalSpan}; replay confirms persistence with the
537
537
  * server-authoritative barrier in `replay.ts`, not by awaiting this call.
538
538
  */
539
- sendExternalTrace(payload: Record<string, unknown>): void;
539
+ sendExternalTrace(rawPayload: Record<string, unknown>): void;
540
540
  /**
541
541
  * Partial update of an existing trace identified by its Bitfab trace ID.
542
542
  * Used by the detached `client.getTrace(id)` handle.
@@ -1656,12 +1656,16 @@ interface ReplayOptions {
1656
1656
  * Maximum number of traces to replay (1-5,000, default 5). Ignored when
1657
1657
  * `traceIds` is passed (with a warning), or when `datasetId` / `datasetIds`
1658
1658
  * is passed, because either source already determines how many traces replay.
1659
+ * To replay part of a dataset selection, name the members to run in
1660
+ * `traceIds` rather than bounding it here.
1659
1661
  */
1660
1662
  limit?: number;
1661
1663
  attempts?: number;
1662
1664
  /**
1663
- * Optional list of specific trace IDs to replay (max 100). Mutually exclusive
1664
- * with `datasetId` and `datasetIds`.
1665
+ * Optional list of specific trace IDs to replay (max 100). Passed alongside
1666
+ * `datasetId` or `datasetIds` it pins which members of that selection replay,
1667
+ * and the server rejects any ID none of those datasets contains. On its own
1668
+ * it selects by ID with no dataset attribution.
1665
1669
  */
1666
1670
  traceIds?: string[];
1667
1671
  /** Optional display name for the resulting experiment/test run. */
@@ -1719,8 +1723,9 @@ interface ReplayOptions {
1719
1723
  /** Group ID to associate this replay with an experiment group for live streaming in Studio. */
1720
1724
  experimentGroupId?: string;
1721
1725
  /**
1722
- * Dataset this replay runs against. Mutually exclusive with `traceIds` and
1723
- * with `datasetIds`. When set, the resulting experiment is
1726
+ * Dataset this replay runs against. Mutually exclusive with `datasetIds`.
1727
+ * Alone it replays the dataset's full membership, and with `traceIds` it
1728
+ * replays only those members. When set, the resulting experiment is
1724
1729
  * durably attributed to the dataset (stored on the test run), so it appears
1725
1730
  * under the dataset's experiments even if the trace lineage can't be
1726
1731
  * reconstructed. Validated server-side against the org.
@@ -3288,7 +3293,7 @@ declare class BitfabFunction {
3288
3293
  /**
3289
3294
  * SDK version from package.json (injected at build time)
3290
3295
  */
3291
- declare const __version__ = "0.52.0";
3296
+ declare const __version__ = "0.52.2";
3292
3297
 
3293
3298
  /**
3294
3299
  * Constants for the Bitfab SDK.
package/dist/index.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  getCurrentSpan,
28
28
  getCurrentTrace,
29
29
  seedFromRegistry
30
- } from "./chunk-KZKVSOBL.js";
30
+ } from "./chunk-RU7KJE2D.js";
31
31
  import "./chunk-ZUD7OFYB.js";
32
32
  import {
33
33
  BITFAB_PROGRESS_PREFIX,
@@ -36,7 +36,7 @@ import {
36
36
  ReplayError,
37
37
  reportReplayProgress,
38
38
  serializeReplayResult
39
- } from "./chunk-LLS4QMFH.js";
39
+ } from "./chunk-SIMPLMRG.js";
40
40
  import {
41
41
  BitfabError,
42
42
  DEFAULT_SERVICE_URL,
@@ -44,7 +44,7 @@ import {
44
44
  MixedTracingError,
45
45
  __version__,
46
46
  flushTraces
47
- } from "./chunk-6M3EOIRH.js";
47
+ } from "./chunk-XL5M3ETX.js";
48
48
  import "./chunk-H6LZRFMN.js";
49
49
  export {
50
50
  BITFAB_PROGRESS_PREFIX,
package/dist/node.cjs CHANGED
@@ -97,7 +97,7 @@ var __version__, __packageName__;
97
97
  var init_version_generated = __esm({
98
98
  "src/version.generated.ts"() {
99
99
  "use strict";
100
- __version__ = "0.52.0";
100
+ __version__ = "0.52.2";
101
101
  __packageName__ = "bitfab";
102
102
  }
103
103
  });
@@ -550,6 +550,69 @@ var init_serializePayload = __esm({
550
550
  }
551
551
  });
552
552
 
553
+ // src/traceMetadata.ts
554
+ function recordCallerTraceMetadata(traceId, metadata) {
555
+ if (typeof traceId !== "string" || traceId === "") {
556
+ return;
557
+ }
558
+ if (typeof metadata !== "object" || metadata === null) {
559
+ return;
560
+ }
561
+ if (Object.keys(metadata).length === 0) {
562
+ return;
563
+ }
564
+ callerMetadata.set(traceId, { ...callerMetadata.get(traceId), ...metadata });
565
+ }
566
+ function callerTraceMetadata(traceId) {
567
+ const recorded = callerMetadata.get(traceId);
568
+ return recorded ? { ...recorded } : void 0;
569
+ }
570
+ function forgetTraceMetadata(traceId) {
571
+ callerMetadata.delete(traceId);
572
+ derivedMetadata.delete(traceId);
573
+ }
574
+ function mergeCallerMetadataIntoTracePayload(payload) {
575
+ const externalTrace = payload.externalTrace;
576
+ if (typeof externalTrace !== "object" || externalTrace === null) {
577
+ return payload;
578
+ }
579
+ const external = externalTrace;
580
+ const traceId = typeof payload.id === "string" && payload.id !== "" ? payload.id : external.id;
581
+ if (typeof traceId !== "string" || traceId === "") {
582
+ return payload;
583
+ }
584
+ const caller = callerMetadata.get(traceId);
585
+ if (!caller) {
586
+ return payload;
587
+ }
588
+ const derived = derivedMetadata.get(traceId) ?? {};
589
+ const exported = external.metadata;
590
+ if (typeof exported === "object" && exported !== null) {
591
+ Object.assign(derived, exported);
592
+ }
593
+ derivedMetadata.set(traceId, derived);
594
+ const shadowed = Object.keys(derived).filter((key) => key in caller && caller[key] !== derived[key]).sort();
595
+ if (shadowed.length > 0) {
596
+ warnOnce(
597
+ `trace-metadata-shadowed:${shadowed.join(",")}`,
598
+ `trace metadata key(s) ${shadowed.join(", ")} were set both by the caller and by an integration's own trace export; the caller's value is the one kept on the trace.`
599
+ );
600
+ }
601
+ return {
602
+ ...payload,
603
+ externalTrace: { ...external, metadata: { ...derived, ...caller } }
604
+ };
605
+ }
606
+ var callerMetadata, derivedMetadata;
607
+ var init_traceMetadata = __esm({
608
+ "src/traceMetadata.ts"() {
609
+ "use strict";
610
+ init_warnOnce();
611
+ callerMetadata = /* @__PURE__ */ new Map();
612
+ derivedMetadata = /* @__PURE__ */ new Map();
613
+ }
614
+ });
615
+
553
616
  // src/transportTypes.ts
554
617
  var DeliveryError;
555
618
  var init_transportTypes = __esm({
@@ -1368,6 +1431,7 @@ var init_http = __esm({
1368
1431
  init_errors();
1369
1432
  init_replayContext();
1370
1433
  init_serializePayload();
1434
+ init_traceMetadata();
1371
1435
  init_transport();
1372
1436
  init_transportTypes();
1373
1437
  init_unrefTimer();
@@ -1831,7 +1895,8 @@ var init_http = __esm({
1831
1895
  * {@link HttpClient.sendExternalSpan}; replay confirms persistence with the
1832
1896
  * server-authoritative barrier in `replay.ts`, not by awaiting this call.
1833
1897
  */
1834
- sendExternalTrace(payload) {
1898
+ sendExternalTrace(rawPayload) {
1899
+ const payload = mergeCallerMetadataIntoTracePayload(rawPayload);
1835
1900
  this.getTraceTransport()?.submit(
1836
1901
  "external_trace",
1837
1902
  {
@@ -2944,11 +3009,6 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2944
3009
  }
2945
3010
  }
2946
3011
  const datasetIds = resolveDatasetIds(options);
2947
- if (options?.traceIds !== void 0 && datasetIds !== void 0) {
2948
- throw new BitfabError(
2949
- "traceIds and datasetIds select different replay sources and cannot be used together."
2950
- );
2951
- }
2952
3012
  if (options?.limit !== void 0 && options?.traceIds !== void 0) {
2953
3013
  try {
2954
3014
  console.warn(
@@ -5723,6 +5783,7 @@ function runWithSeedContext(ctx, fn) {
5723
5783
 
5724
5784
  // src/client.ts
5725
5785
  init_serialize();
5786
+ init_traceMetadata();
5726
5787
 
5727
5788
  // src/tracing.ts
5728
5789
  init_constants();
@@ -6403,8 +6464,7 @@ function getCurrentTrace() {
6403
6464
  if (typeof metadata !== "object" || metadata === null) {
6404
6465
  return;
6405
6466
  }
6406
- const traceState = getOrCreateTraceState();
6407
- traceState.metadata = { ...traceState.metadata, ...metadata };
6467
+ recordCallerTraceMetadata(traceId, metadata);
6408
6468
  } catch {
6409
6469
  }
6410
6470
  },
@@ -7397,7 +7457,7 @@ var Bitfab = class {
7397
7457
  endedAt,
7398
7458
  sessionId: traceState?.sessionId,
7399
7459
  name: traceState?.name,
7400
- metadata: traceState?.metadata,
7460
+ metadata: callerTraceMetadata(traceId),
7401
7461
  contexts: traceState?.contexts ?? [],
7402
7462
  testRunId: traceState?.testRunId,
7403
7463
  inputSourceTraceId: traceState?.inputSourceTraceId,
@@ -7421,6 +7481,7 @@ var Bitfab = class {
7421
7481
  }
7422
7482
  });
7423
7483
  activeTraceStates.delete(traceId);
7484
+ forgetTraceMetadata(traceId);
7424
7485
  }
7425
7486
  } catch {
7426
7487
  }
@@ -7613,6 +7674,7 @@ var Bitfab = class {
7613
7674
  } catch (setupError) {
7614
7675
  if (registeredTraceId) {
7615
7676
  activeTraceStates.delete(registeredTraceId);
7677
+ forgetTraceMetadata(registeredTraceId);
7616
7678
  }
7617
7679
  if (setupError instanceof MixedTracingError) {
7618
7680
  throw setupError;
@@ -7973,14 +8035,16 @@ var Bitfab = class {
7973
8035
  }
7974
8036
  const traceId = randomUuid();
7975
8037
  const startedAt = nowIsoTimestamp();
8038
+ if (options.metadata !== void 0) {
8039
+ recordCallerTraceMetadata(traceId, options.metadata);
8040
+ }
7976
8041
  activeTraceStates.set(traceId, {
7977
8042
  traceId,
7978
8043
  startedAt,
7979
8044
  contexts: [],
7980
8045
  ingestionType: "seeded",
7981
8046
  ...options.sessionId !== void 0 && { sessionId: options.sessionId },
7982
- ...options.name !== void 0 && { name: options.name },
7983
- ...options.metadata !== void 0 && { metadata: options.metadata }
8047
+ ...options.name !== void 0 && { name: options.name }
7984
8048
  });
7985
8049
  try {
7986
8050
  this.sendWrapperSpan({
@@ -8003,12 +8067,13 @@ var Bitfab = class {
8003
8067
  endedAt: startedAt,
8004
8068
  sessionId: options.sessionId,
8005
8069
  name: options.name,
8006
- metadata: options.metadata,
8070
+ metadata: callerTraceMetadata(traceId),
8007
8071
  contexts: [],
8008
8072
  ingestionType: "seeded"
8009
8073
  });
8010
8074
  } finally {
8011
8075
  activeTraceStates.delete(traceId);
8076
+ forgetTraceMetadata(traceId);
8012
8077
  }
8013
8078
  return traceId;
8014
8079
  }
@@ -8033,14 +8098,16 @@ var Bitfab = class {
8033
8098
  }
8034
8099
  await seedContextReady;
8035
8100
  const traceId = randomUuid();
8101
+ if (options?.metadata !== void 0) {
8102
+ recordCallerTraceMetadata(traceId, options.metadata);
8103
+ }
8036
8104
  activeTraceStates.set(traceId, {
8037
8105
  traceId,
8038
8106
  startedAt: nowIsoTimestamp(),
8039
8107
  contexts: [],
8040
8108
  ingestionType: "seeded",
8041
8109
  ...options?.sessionId !== void 0 && { sessionId: options.sessionId },
8042
- ...options?.name !== void 0 && { name: options.name },
8043
- ...options?.metadata !== void 0 && { metadata: options.metadata }
8110
+ ...options?.name !== void 0 && { name: options.name }
8044
8111
  });
8045
8112
  const args = options?.args ?? [];
8046
8113
  let unrecorded = true;
@@ -8052,6 +8119,7 @@ var Bitfab = class {
8052
8119
  await flushTraces2(3e4);
8053
8120
  } finally {
8054
8121
  unrecorded = activeTraceStates.delete(traceId);
8122
+ forgetTraceMetadata(traceId);
8055
8123
  }
8056
8124
  }
8057
8125
  if (unrecorded) {