@bitfab/sdk 0.54.2 → 0.54.4

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
@@ -1,3 +1,17 @@
1
+ declare class TraceCompletion {
2
+ private readonly traces;
3
+ private readonly closed;
4
+ private state;
5
+ start(traceId: string, spanId: string): void;
6
+ open(traceId: string): void;
7
+ hold(traceId: string, key: string): void;
8
+ record(traceId: string, spanId: string): void;
9
+ end(traceId: string, spanId: string): void;
10
+ abort(traceId: string, spanId: string): void;
11
+ close(traceId: string, complete: (count: number) => void, dropped?: boolean): void;
12
+ private drain;
13
+ }
14
+
1
15
  /**
2
16
  * Per-trace database snapshot ref capture.
3
17
  *
@@ -327,14 +341,6 @@ interface SimulationPlanResponse {
327
341
  }
328
342
  type SimulationPlanSubmit = (payload: Record<string, unknown>) => void;
329
343
 
330
- /**
331
- * HTTP client utilities for Bitfab API requests.
332
- *
333
- * This module provides:
334
- * - HttpClient class for making API requests
335
- * - awaitOnExit helper so deferred span work still gates process exit
336
- */
337
-
338
344
  /**
339
345
  * Wait for pending fire-and-forget requests AND every live span transport to
340
346
  * deliver, within one total deadline. Useful in tests and scripts to ensure all
@@ -407,6 +413,7 @@ declare class HttpClient {
407
413
  private traceTransport;
408
414
  private readonly traceDeliveries;
409
415
  private readonly deferredWork;
416
+ readonly traceCompletion: TraceCompletion;
410
417
  private closed;
411
418
  private closing;
412
419
  externalSpanTransform: ((payload: Record<string, unknown>, submit: SimulationPlanSubmit) => void) | undefined;
@@ -547,6 +554,7 @@ declare class HttpClient {
547
554
  * server-authoritative barrier in `replay.ts`, not by awaiting this call.
548
555
  */
549
556
  sendExternalTrace(rawPayload: Record<string, unknown>): void;
557
+ private sendCountedExternalTrace;
550
558
  submitExternalTrace(payload: Record<string, unknown>): void;
551
559
  /**
552
560
  * Partial update of an existing trace identified by its Bitfab trace ID.
@@ -748,7 +756,7 @@ interface CompleteReplayResponse {
748
756
  /**
749
757
  * Per-replay-trace token usage, keyed by the server trace id (the values of
750
758
  * `traceIds`). Aggregated server-side from the freshly-uploaded replay spans,
751
- * so it's the REPLAYED run's tokens (the same source Studio reads), not the
759
+ * so it's the REPLAYED run's tokens (the same source the dashboard reads), not the
752
760
  * original trace's. The SDK maps each item onto this to set
753
761
  * `ReplayItem.tokens`. Absent on servers that predate this field.
754
762
  */
@@ -1786,7 +1794,7 @@ interface ReplayOptions {
1786
1794
  * not use the historical data you asked for.
1787
1795
  */
1788
1796
  dbBranch?: DbBranchOptions | boolean;
1789
- /** Group ID to associate this replay with an experiment group for live streaming in Studio. */
1797
+ /** Group ID to associate this replay with an experiment group for live streaming on the experiments page. */
1790
1798
  experimentGroupId?: string;
1791
1799
  /**
1792
1800
  * Dataset this replay runs against. Mutually exclusive with `datasetIds`.
@@ -2093,7 +2101,7 @@ interface ReplayItem<T> {
2093
2101
  * Token usage from the REPLAYED run (this item's new execution), aggregated
2094
2102
  * server-side from the spans it produced, or null if the run captured no
2095
2103
  * token data. Compare against {@link ReplayItem.originalTokens} to see how
2096
- * the code change moved cost. Matches what Studio's experiments view shows.
2104
+ * the code change moved cost. Matches what the experiments page shows.
2097
2105
  *
2098
2106
  * Unprefixed because the replay is this item's subject: anything describing
2099
2107
  * the trace being replayed carries `original`.
@@ -2235,6 +2243,7 @@ interface Trace {
2235
2243
  toJSON(): unknown;
2236
2244
  }
2237
2245
  interface Span<_T = any> {
2246
+ spanId?: string;
2238
2247
  traceId?: string;
2239
2248
  toJSON(): unknown;
2240
2249
  spanData?: {
@@ -2323,11 +2332,14 @@ declare class BitfabOpenAITracingProcessor implements TracingProcessor {
2323
2332
  * since the parent withSpan handles completion.
2324
2333
  */
2325
2334
  onTraceEnd(trace: Trace): Promise<void>;
2335
+ private readonly startedSpans;
2336
+ private readonly endedTraces;
2337
+ private cleanupTrace;
2326
2338
  /**
2327
2339
  * Called when a span is started. Span payloads are authoritative completed
2328
2340
  * snapshots, so start notifications do not cross the transport boundary.
2329
2341
  */
2330
- onSpanStart(_span: Span<any>): Promise<void>;
2342
+ onSpanStart(span: Span<any>): Promise<void>;
2331
2343
  /**
2332
2344
  * Called when a span is ended.
2333
2345
  *
@@ -3379,7 +3391,7 @@ interface CommitRef {
3379
3391
  /**
3380
3392
  * SDK version from package.json (injected at build time)
3381
3393
  */
3382
- declare const __version__ = "0.54.2";
3394
+ declare const __version__ = "0.54.4";
3383
3395
 
3384
3396
  /**
3385
3397
  * Constants for the Bitfab SDK.
package/dist/index.d.ts CHANGED
@@ -1,3 +1,17 @@
1
+ declare class TraceCompletion {
2
+ private readonly traces;
3
+ private readonly closed;
4
+ private state;
5
+ start(traceId: string, spanId: string): void;
6
+ open(traceId: string): void;
7
+ hold(traceId: string, key: string): void;
8
+ record(traceId: string, spanId: string): void;
9
+ end(traceId: string, spanId: string): void;
10
+ abort(traceId: string, spanId: string): void;
11
+ close(traceId: string, complete: (count: number) => void, dropped?: boolean): void;
12
+ private drain;
13
+ }
14
+
1
15
  /**
2
16
  * Per-trace database snapshot ref capture.
3
17
  *
@@ -327,14 +341,6 @@ interface SimulationPlanResponse {
327
341
  }
328
342
  type SimulationPlanSubmit = (payload: Record<string, unknown>) => void;
329
343
 
330
- /**
331
- * HTTP client utilities for Bitfab API requests.
332
- *
333
- * This module provides:
334
- * - HttpClient class for making API requests
335
- * - awaitOnExit helper so deferred span work still gates process exit
336
- */
337
-
338
344
  /**
339
345
  * Wait for pending fire-and-forget requests AND every live span transport to
340
346
  * deliver, within one total deadline. Useful in tests and scripts to ensure all
@@ -407,6 +413,7 @@ declare class HttpClient {
407
413
  private traceTransport;
408
414
  private readonly traceDeliveries;
409
415
  private readonly deferredWork;
416
+ readonly traceCompletion: TraceCompletion;
410
417
  private closed;
411
418
  private closing;
412
419
  externalSpanTransform: ((payload: Record<string, unknown>, submit: SimulationPlanSubmit) => void) | undefined;
@@ -547,6 +554,7 @@ declare class HttpClient {
547
554
  * server-authoritative barrier in `replay.ts`, not by awaiting this call.
548
555
  */
549
556
  sendExternalTrace(rawPayload: Record<string, unknown>): void;
557
+ private sendCountedExternalTrace;
550
558
  submitExternalTrace(payload: Record<string, unknown>): void;
551
559
  /**
552
560
  * Partial update of an existing trace identified by its Bitfab trace ID.
@@ -748,7 +756,7 @@ interface CompleteReplayResponse {
748
756
  /**
749
757
  * Per-replay-trace token usage, keyed by the server trace id (the values of
750
758
  * `traceIds`). Aggregated server-side from the freshly-uploaded replay spans,
751
- * so it's the REPLAYED run's tokens (the same source Studio reads), not the
759
+ * so it's the REPLAYED run's tokens (the same source the dashboard reads), not the
752
760
  * original trace's. The SDK maps each item onto this to set
753
761
  * `ReplayItem.tokens`. Absent on servers that predate this field.
754
762
  */
@@ -1786,7 +1794,7 @@ interface ReplayOptions {
1786
1794
  * not use the historical data you asked for.
1787
1795
  */
1788
1796
  dbBranch?: DbBranchOptions | boolean;
1789
- /** Group ID to associate this replay with an experiment group for live streaming in Studio. */
1797
+ /** Group ID to associate this replay with an experiment group for live streaming on the experiments page. */
1790
1798
  experimentGroupId?: string;
1791
1799
  /**
1792
1800
  * Dataset this replay runs against. Mutually exclusive with `datasetIds`.
@@ -2093,7 +2101,7 @@ interface ReplayItem<T> {
2093
2101
  * Token usage from the REPLAYED run (this item's new execution), aggregated
2094
2102
  * server-side from the spans it produced, or null if the run captured no
2095
2103
  * token data. Compare against {@link ReplayItem.originalTokens} to see how
2096
- * the code change moved cost. Matches what Studio's experiments view shows.
2104
+ * the code change moved cost. Matches what the experiments page shows.
2097
2105
  *
2098
2106
  * Unprefixed because the replay is this item's subject: anything describing
2099
2107
  * the trace being replayed carries `original`.
@@ -2235,6 +2243,7 @@ interface Trace {
2235
2243
  toJSON(): unknown;
2236
2244
  }
2237
2245
  interface Span<_T = any> {
2246
+ spanId?: string;
2238
2247
  traceId?: string;
2239
2248
  toJSON(): unknown;
2240
2249
  spanData?: {
@@ -2323,11 +2332,14 @@ declare class BitfabOpenAITracingProcessor implements TracingProcessor {
2323
2332
  * since the parent withSpan handles completion.
2324
2333
  */
2325
2334
  onTraceEnd(trace: Trace): Promise<void>;
2335
+ private readonly startedSpans;
2336
+ private readonly endedTraces;
2337
+ private cleanupTrace;
2326
2338
  /**
2327
2339
  * Called when a span is started. Span payloads are authoritative completed
2328
2340
  * snapshots, so start notifications do not cross the transport boundary.
2329
2341
  */
2330
- onSpanStart(_span: Span<any>): Promise<void>;
2342
+ onSpanStart(span: Span<any>): Promise<void>;
2331
2343
  /**
2332
2344
  * Called when a span is ended.
2333
2345
  *
@@ -3379,7 +3391,7 @@ interface CommitRef {
3379
3391
  /**
3380
3392
  * SDK version from package.json (injected at build time)
3381
3393
  */
3382
- declare const __version__ = "0.54.2";
3394
+ declare const __version__ = "0.54.4";
3383
3395
 
3384
3396
  /**
3385
3397
  * Constants for the Bitfab SDK.
package/dist/index.js CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  getCurrentTrace,
21
21
  reseedFromRegistry,
22
22
  seedFromRegistry
23
- } from "./chunk-4ZACHEMR.js";
23
+ } from "./chunk-A4NRNU72.js";
24
24
  import "./chunk-EGWJYCNT.js";
25
25
  import {
26
26
  BITFAB_PROGRESS_PREFIX,
@@ -29,7 +29,7 @@ import {
29
29
  ReplayError,
30
30
  reportReplayProgress,
31
31
  serializeReplayResult
32
- } from "./chunk-SPZEKXAE.js";
32
+ } from "./chunk-NFJ6ZZWY.js";
33
33
  import {
34
34
  BitfabError,
35
35
  DEFAULT_SERVICE_URL,
@@ -37,7 +37,7 @@ import {
37
37
  MixedTracingError,
38
38
  __version__,
39
39
  flushTraces
40
- } from "./chunk-BIEDMC5U.js";
40
+ } from "./chunk-GMUC6A7M.js";
41
41
  import "./chunk-VCRFFCLY.js";
42
42
  export {
43
43
  AssertionCategoriesClient,
package/dist/node.cjs CHANGED
@@ -88,7 +88,7 @@ var __version__, __packageName__;
88
88
  var init_version_generated = __esm({
89
89
  "src/version.generated.ts"() {
90
90
  "use strict";
91
- __version__ = "0.54.2";
91
+ __version__ = "0.54.4";
92
92
  __packageName__ = "@bitfab/sdk";
93
93
  }
94
94
  });
@@ -103,6 +103,99 @@ var init_constants = __esm({
103
103
  }
104
104
  });
105
105
 
106
+ // src/traceCompletion.ts
107
+ var TraceCompletion;
108
+ var init_traceCompletion = __esm({
109
+ "src/traceCompletion.ts"() {
110
+ "use strict";
111
+ TraceCompletion = class {
112
+ constructor() {
113
+ this.traces = /* @__PURE__ */ new Map();
114
+ this.closed = /* @__PURE__ */ new Map();
115
+ }
116
+ state(traceId) {
117
+ let state = this.traces.get(traceId);
118
+ if (state === void 0) {
119
+ state = { spanIds: /* @__PURE__ */ new Set(), active: /* @__PURE__ */ new Set() };
120
+ this.traces.set(traceId, state);
121
+ }
122
+ return state;
123
+ }
124
+ start(traceId, spanId) {
125
+ if (this.closed.has(traceId)) {
126
+ return;
127
+ }
128
+ const state = this.state(traceId);
129
+ state.spanIds.add(spanId);
130
+ state.active.add(spanId);
131
+ }
132
+ open(traceId) {
133
+ if (!this.closed.has(traceId)) {
134
+ this.state(traceId);
135
+ }
136
+ }
137
+ hold(traceId, key) {
138
+ this.state(traceId).active.add(key);
139
+ }
140
+ record(traceId, spanId) {
141
+ if (!this.closed.has(traceId)) {
142
+ this.state(traceId).spanIds.add(spanId);
143
+ }
144
+ }
145
+ end(traceId, spanId) {
146
+ const state = this.traces.get(traceId);
147
+ if (state !== void 0) {
148
+ state.active.delete(spanId);
149
+ this.drain(traceId, state);
150
+ }
151
+ }
152
+ abort(traceId, spanId) {
153
+ const state = this.traces.get(traceId);
154
+ if (state === void 0) {
155
+ return;
156
+ }
157
+ state.active.delete(spanId);
158
+ state.spanIds.delete(spanId);
159
+ if (state.active.size === 0 && state.spanIds.size === 0 && state.complete === void 0) {
160
+ this.traces.delete(traceId);
161
+ return;
162
+ }
163
+ this.drain(traceId, state);
164
+ }
165
+ close(traceId, complete, dropped = false) {
166
+ const count = this.closed.get(traceId);
167
+ if (count !== void 0) {
168
+ complete(count);
169
+ return;
170
+ }
171
+ const state = this.traces.get(traceId);
172
+ if (state === void 0) {
173
+ return;
174
+ }
175
+ state.complete = complete;
176
+ if (dropped) {
177
+ state.active.clear();
178
+ }
179
+ this.drain(traceId, state);
180
+ }
181
+ drain(traceId, state) {
182
+ if (state.active.size !== 0 || state.complete === void 0) {
183
+ return;
184
+ }
185
+ this.traces.delete(traceId);
186
+ this.closed.set(traceId, state.spanIds.size);
187
+ if (this.closed.size > 1024) {
188
+ const oldest = this.closed.keys().next().value;
189
+ if (oldest !== void 0) {
190
+ this.closed.delete(oldest);
191
+ }
192
+ }
193
+ state.complete(state.spanIds.size);
194
+ }
195
+ };
196
+ }
197
+ });
198
+
106
199
  // src/readEnv.ts
107
200
  function readEnv(name) {
108
201
  if (typeof process !== "undefined" && process.env) {
@@ -2150,6 +2243,7 @@ var REPLAY_DB_BRANCH_REQUEST_TIMEOUT_MS, REPLAY_COMPLETE_REQUEST_TIMEOUT_MS, OTL
2150
2243
  var init_http = __esm({
2151
2244
  "src/http.ts"() {
2152
2245
  "use strict";
2246
+ init_traceCompletion();
2153
2247
  init_compress();
2154
2248
  init_constants();
2155
2249
  init_errors();
@@ -2212,6 +2306,7 @@ var init_http = __esm({
2212
2306
  // must not wait on another client's slow finalize: a false `close()` failure
2213
2307
  // caused by unrelated work is worse than no signal at all.
2214
2308
  this.deferredWork = /* @__PURE__ */ new Set();
2309
+ this.traceCompletion = new TraceCompletion();
2215
2310
  this.closed = false;
2216
2311
  this.apiKey = config.apiKey;
2217
2312
  this.serviceUrl = config.serviceUrl;
@@ -2645,6 +2740,10 @@ var init_http = __esm({
2645
2740
  );
2646
2741
  }
2647
2742
  sendExternalSpan(payload) {
2743
+ const ref2 = carrierRef(payload);
2744
+ if (ref2?.spanId !== void 0) {
2745
+ this.traceCompletion.record(ref2.traceId, ref2.spanId);
2746
+ }
2648
2747
  const gate = this.externalSpanTransform;
2649
2748
  if (gate === void 0) {
2650
2749
  this.submitExternalSpan(payload);
@@ -2676,13 +2775,28 @@ var init_http = __esm({
2676
2775
  */
2677
2776
  sendExternalTrace(rawPayload) {
2678
2777
  const payload = mergeCallerMetadataIntoTracePayload(rawPayload);
2679
- const gate = this.externalTraceTransform;
2680
- if (gate === void 0) {
2681
- this.submitExternalTrace(payload);
2778
+ const traceId = sourceTraceIdOf(payload);
2779
+ if (payload.completed === true && traceId !== void 0) {
2780
+ this.traceCompletion.close(
2781
+ traceId,
2782
+ (expectedSpanCount) => this.sendCountedExternalTrace({ ...payload, expectedSpanCount }),
2783
+ payload.dropped === true
2784
+ );
2682
2785
  return;
2683
2786
  }
2787
+ if (traceId !== void 0) {
2788
+ this.traceCompletion.open(traceId);
2789
+ }
2790
+ this.sendCountedExternalTrace(payload);
2791
+ }
2792
+ sendCountedExternalTrace(payload) {
2684
2793
  try {
2685
- gate(payload, (ready) => this.submitExternalTrace(ready));
2794
+ const gate = this.externalTraceTransform;
2795
+ if (gate === void 0) {
2796
+ this.submitExternalTrace(payload);
2797
+ } else {
2798
+ gate(payload, (ready) => this.submitExternalTrace(ready));
2799
+ }
2686
2800
  } catch (error) {
2687
2801
  warnDroppedExternalTrace(error);
2688
2802
  }
@@ -4508,6 +4622,7 @@ var BitfabClaudeAgentHandler = class {
4508
4622
  spanInfo.dropped = [...inputDropped];
4509
4623
  }
4510
4624
  this.runToSpan.set(spanId, spanInfo);
4625
+ this.httpClient.traceCompletion.start(spanInfo.traceId, spanInfo.spanId);
4511
4626
  return spanInfo;
4512
4627
  }
4513
4628
  completeSpan(spanId, output, error, extraContexts) {
@@ -4529,6 +4644,7 @@ var BitfabClaudeAgentHandler = class {
4529
4644
  spanInfo.contexts.push(extraContexts);
4530
4645
  }
4531
4646
  this.sendSpan(spanInfo);
4647
+ this.httpClient.traceCompletion.end(spanInfo.traceId, spanInfo.spanId);
4532
4648
  }
4533
4649
  sendSpan(spanInfo) {
4534
4650
  const spanData = {
@@ -6186,6 +6302,9 @@ var BitfabLangGraphCallbackHandler = class {
6186
6302
  spanInfo.hidden = true;
6187
6303
  }
6188
6304
  this.runToSpan.set(runId, spanInfo);
6305
+ if (spanInfo.hidden !== true) {
6306
+ this.httpClient.traceCompletion.start(spanInfo.traceId, spanInfo.spanId);
6307
+ }
6189
6308
  if (isRootInvocation) {
6190
6309
  this.sendTraceStart(spanInfo);
6191
6310
  }
@@ -6217,6 +6336,7 @@ var BitfabLangGraphCallbackHandler = class {
6217
6336
  this.sendTraceCompletion(spanInfo, invocation?.activeContext ?? null);
6218
6337
  this.invocations.delete(runId);
6219
6338
  }
6339
+ this.httpClient.traceCompletion.end(spanInfo.traceId, spanInfo.spanId);
6220
6340
  }
6221
6341
  sendSpan(spanInfo) {
6222
6342
  const spanData = {
@@ -6938,6 +7058,8 @@ var BitfabOpenAITracingProcessor = class {
6938
7058
  this.activeTraces = {};
6939
7059
  this.activeSpanMappings = {};
6940
7060
  this.canonicalTraceIds = {};
7061
+ this.startedSpans = /* @__PURE__ */ new Map();
7062
+ this.endedTraces = /* @__PURE__ */ new Set();
6941
7063
  this.ownsHttpClient = config._httpClient === void 0;
6942
7064
  this.httpClient = config._httpClient ?? new HttpClient({
6943
7065
  apiKey: config.apiKey,
@@ -6976,6 +7098,10 @@ var BitfabOpenAITracingProcessor = class {
6976
7098
  }
6977
7099
  const canonicalTraceId = activeContext?.traceId ?? this.getCanonicalTraceId(trace.traceId);
6978
7100
  this.canonicalTraceIds[trace.traceId] = canonicalTraceId;
7101
+ this.httpClient.traceCompletion.hold(
7102
+ activeContext?.traceId ?? trace.traceId,
7103
+ `openai:${trace.traceId}`
7104
+ );
6979
7105
  this.sendTrace(trace, {
6980
7106
  id: canonicalTraceId,
6981
7107
  sourceTraceId: activeContext?.traceId
@@ -6993,16 +7119,33 @@ var BitfabOpenAITracingProcessor = class {
6993
7119
  id: mapping?.traceId ?? this.getCanonicalTraceId(trace.traceId),
6994
7120
  sourceTraceId: mapping?.traceId
6995
7121
  });
6996
- delete this.activeSpanMappings[trace.traceId];
6997
- delete this.canonicalTraceIds[trace.traceId];
6998
- delete this.activeTraces[trace.traceId];
7122
+ this.endedTraces.add(trace.traceId);
7123
+ this.httpClient.traceCompletion.end(
7124
+ mapping?.traceId ?? trace.traceId,
7125
+ `openai:${trace.traceId}`
7126
+ );
7127
+ this.cleanupTrace(trace.traceId);
7128
+ }
7129
+ cleanupTrace(traceId) {
7130
+ if (!this.endedTraces.has(traceId) || [...this.startedSpans.values()].includes(traceId)) {
7131
+ return;
7132
+ }
7133
+ this.endedTraces.delete(traceId);
7134
+ delete this.activeSpanMappings[traceId];
7135
+ delete this.canonicalTraceIds[traceId];
7136
+ delete this.activeTraces[traceId];
6999
7137
  }
7000
7138
  /**
7001
7139
  * Called when a span is started. Span payloads are authoritative completed
7002
7140
  * snapshots, so start notifications do not cross the transport boundary.
7003
7141
  */
7004
7142
  // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data
7005
- async onSpanStart(_span) {
7143
+ async onSpanStart(span) {
7144
+ if (span.spanId !== void 0 && span.traceId !== null && span.traceId !== void 0) {
7145
+ this.startedSpans.set(span.spanId, span.traceId);
7146
+ const traceId = this.activeSpanMappings[span.traceId]?.traceId ?? span.traceId;
7147
+ this.httpClient.traceCompletion.start(traceId, span.spanId);
7148
+ }
7006
7149
  }
7007
7150
  /**
7008
7151
  * Called when a span is ended.
@@ -7011,7 +7154,17 @@ var BitfabOpenAITracingProcessor = class {
7011
7154
  */
7012
7155
  // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data
7013
7156
  async onSpanEnd(span) {
7014
- this.sendSpan(span);
7157
+ const originalTraceId = span.traceId ?? "";
7158
+ const traceId = this.activeSpanMappings[originalTraceId]?.traceId ?? originalTraceId;
7159
+ try {
7160
+ this.sendSpan(span);
7161
+ } finally {
7162
+ if (span.spanId !== void 0) {
7163
+ this.httpClient.traceCompletion.end(traceId, span.spanId);
7164
+ this.startedSpans.delete(span.spanId);
7165
+ }
7166
+ this.cleanupTrace(originalTraceId);
7167
+ }
7015
7168
  }
7016
7169
  /**
7017
7170
  * Called when a trace is being flushed.
@@ -8717,6 +8870,7 @@ var Bitfab = class {
8717
8870
  let newStack;
8718
8871
  let executeWithContext;
8719
8872
  let registeredTraceId;
8873
+ let startedSpan;
8720
8874
  try {
8721
8875
  const currentStack = getSpanStack();
8722
8876
  const parentContext = currentStack[currentStack.length - 1];
@@ -8768,6 +8922,8 @@ var Bitfab = class {
8768
8922
  });
8769
8923
  registeredTraceId = traceId;
8770
8924
  }
8925
+ self.httpClient.traceCompletion.start(traceId, spanId);
8926
+ startedSpan = { traceId, spanId };
8771
8927
  const functionName = fn.name !== "" ? fn.name : void 0;
8772
8928
  const rootTraceFunctionKey = activeTraceStates.get(traceId)?.traceFunctionKey ?? traceFunctionKey;
8773
8929
  const baseSpanParams = {
@@ -8842,6 +8998,8 @@ var Bitfab = class {
8842
8998
  retireTraceMetadata(traceId);
8843
8999
  }
8844
9000
  } catch {
9001
+ } finally {
9002
+ self.httpClient.traceCompletion.end(traceId, spanId);
8845
9003
  }
8846
9004
  };
8847
9005
  const recordSpan = (result) => {
@@ -8858,6 +9016,14 @@ var Bitfab = class {
8858
9016
  void sendSpan({ result });
8859
9017
  }
8860
9018
  };
9019
+ const resolveMockOrAbort = async (resolve) => {
9020
+ try {
9021
+ return await resolve();
9022
+ } catch (error) {
9023
+ self.httpClient.traceCompletion.abort(traceId, spanId);
9024
+ throw error;
9025
+ }
9026
+ };
8861
9027
  executeWithContext = () => {
8862
9028
  let result;
8863
9029
  try {
@@ -8914,7 +9080,7 @@ var Bitfab = class {
8914
9080
  );
8915
9081
  }
8916
9082
  return (async () => {
8917
- const output = await pending;
9083
+ const output = await resolveMockOrAbort(() => pending);
8918
9084
  void sendSpan({
8919
9085
  result: output,
8920
9086
  mocked: true,
@@ -8984,7 +9150,7 @@ var Bitfab = class {
8984
9150
  );
8985
9151
  }
8986
9152
  return runWithSpanStack(newStack, async () => {
8987
- const resolved2 = await resolution;
9153
+ const resolved2 = await resolveMockOrAbort(() => resolution);
8988
9154
  if (resolved2.matched) {
8989
9155
  void sendSpan({
8990
9156
  result: resolved2.output,
@@ -9000,7 +9166,9 @@ var Bitfab = class {
9000
9166
  );
9001
9167
  }
9002
9168
  if (shouldMockWithBaseStrategy) {
9003
- const output = await resolveRecordedOutput();
9169
+ const output = await resolveMockOrAbort(
9170
+ () => resolveRecordedOutput()
9171
+ );
9004
9172
  void sendSpan({
9005
9173
  result: output,
9006
9174
  mocked: true,
@@ -9030,6 +9198,12 @@ var Bitfab = class {
9030
9198
  }
9031
9199
  }
9032
9200
  } catch (setupError) {
9201
+ if (startedSpan) {
9202
+ self.httpClient.traceCompletion.abort(
9203
+ startedSpan.traceId,
9204
+ startedSpan.spanId
9205
+ );
9206
+ }
9033
9207
  if (registeredTraceId) {
9034
9208
  activeTraceStates.delete(registeredTraceId);
9035
9209
  retireTraceMetadata(registeredTraceId);