@bitfab/sdk 0.54.3 → 0.54.5

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.
Files changed (32) hide show
  1. package/dist/{chunk-GNHJKB5U.js → chunk-3STIE5QL.js} +113 -6
  2. package/dist/chunk-3STIE5QL.js.map +1 -0
  3. package/dist/{chunk-NONYCJ2E.js → chunk-4G3ZJBXQ.js} +3 -3
  4. package/dist/{chunk-GTDGXH7C.js → chunk-7DSNNK5I.js} +124 -54
  5. package/dist/chunk-7DSNNK5I.js.map +1 -0
  6. package/dist/{chunk-GRMGUSH4.js → chunk-PIF5HH3Z.js} +113 -6
  7. package/dist/chunk-PIF5HH3Z.js.map +1 -0
  8. package/dist/{chunk-QKZYQWUR.js → chunk-YH6YO2WS.js} +2 -2
  9. package/dist/{http-N4UKTUO7.js → http-36EP65LE.js} +2 -2
  10. package/dist/{http-LIAIPCJB.js → http-JQ4RXRWH.js} +2 -2
  11. package/dist/index.cjs +236 -52
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.d.cts +114 -73
  14. package/dist/index.d.ts +114 -73
  15. package/dist/index.js +3 -3
  16. package/dist/node.cjs +236 -52
  17. package/dist/node.cjs.map +1 -1
  18. package/dist/node.d.cts +1 -1
  19. package/dist/node.d.ts +1 -1
  20. package/dist/node.js +3 -3
  21. package/dist/{replay-OFNZHVQZ.js → replay-HNSQHX52.js} +3 -3
  22. package/dist/replayCli.js +2 -2
  23. package/dist/seedCli.js +2 -2
  24. package/package.json +1 -1
  25. package/dist/chunk-GNHJKB5U.js.map +0 -1
  26. package/dist/chunk-GRMGUSH4.js.map +0 -1
  27. package/dist/chunk-GTDGXH7C.js.map +0 -1
  28. /package/dist/{chunk-NONYCJ2E.js.map → chunk-4G3ZJBXQ.js.map} +0 -0
  29. /package/dist/{chunk-QKZYQWUR.js.map → chunk-YH6YO2WS.js.map} +0 -0
  30. /package/dist/{http-LIAIPCJB.js.map → http-36EP65LE.js.map} +0 -0
  31. /package/dist/{http-N4UKTUO7.js.map → http-JQ4RXRWH.js.map} +0 -0
  32. /package/dist/{replay-OFNZHVQZ.js.map → replay-HNSQHX52.js.map} +0 -0
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.3";
91
+ __version__ = "0.54.5";
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
  }
@@ -4242,45 +4356,6 @@ var AssertionCategoriesClient = class {
4242
4356
  }
4243
4357
  };
4244
4358
 
4245
- // src/assertions.ts
4246
- var ASSERTIONS_PATH = "/api/sdk/traces/assertions";
4247
- function traceAssertionsPath(traceId, suffix = "") {
4248
- return `/api/sdk/traces/${encodeURIComponent(traceId)}/assertions${suffix}`;
4249
- }
4250
- var TracesClient = class {
4251
- constructor(httpClient) {
4252
- this.httpClient = httpClient;
4253
- }
4254
- async getAssertions(traceId) {
4255
- return this.httpClient.get(
4256
- traceAssertionsPath(traceId)
4257
- );
4258
- }
4259
- async saveAssertions(params) {
4260
- return this.saveAssertionsAll({
4261
- updates: [{ traceId: params.traceId, assertions: params.assertions }],
4262
- source: params.source
4263
- });
4264
- }
4265
- async saveAssertionsAll(params) {
4266
- if (params.updates.length === 0) {
4267
- return [];
4268
- }
4269
- const response = await this.httpClient.request(ASSERTIONS_PATH, {
4270
- updates: params.updates,
4271
- source: params.source ?? "agent"
4272
- });
4273
- return response.assertions;
4274
- }
4275
- async archiveAssertions(params) {
4276
- const response = await this.httpClient.request(
4277
- traceAssertionsPath(params.traceId, "/archive"),
4278
- { assertionIds: params.assertionIds }
4279
- );
4280
- return response.archived;
4281
- }
4282
- };
4283
-
4284
4359
  // src/claudeAgentSdk.ts
4285
4360
  init_constants();
4286
4361
  init_http();
@@ -4508,6 +4583,7 @@ var BitfabClaudeAgentHandler = class {
4508
4583
  spanInfo.dropped = [...inputDropped];
4509
4584
  }
4510
4585
  this.runToSpan.set(spanId, spanInfo);
4586
+ this.httpClient.traceCompletion.start(spanInfo.traceId, spanInfo.spanId);
4511
4587
  return spanInfo;
4512
4588
  }
4513
4589
  completeSpan(spanId, output, error, extraContexts) {
@@ -4529,6 +4605,7 @@ var BitfabClaudeAgentHandler = class {
4529
4605
  spanInfo.contexts.push(extraContexts);
4530
4606
  }
4531
4607
  this.sendSpan(spanInfo);
4608
+ this.httpClient.traceCompletion.end(spanInfo.traceId, spanInfo.spanId);
4532
4609
  }
4533
4610
  sendSpan(spanInfo) {
4534
4611
  const spanData = {
@@ -6186,6 +6263,9 @@ var BitfabLangGraphCallbackHandler = class {
6186
6263
  spanInfo.hidden = true;
6187
6264
  }
6188
6265
  this.runToSpan.set(runId, spanInfo);
6266
+ if (spanInfo.hidden !== true) {
6267
+ this.httpClient.traceCompletion.start(spanInfo.traceId, spanInfo.spanId);
6268
+ }
6189
6269
  if (isRootInvocation) {
6190
6270
  this.sendTraceStart(spanInfo);
6191
6271
  }
@@ -6217,6 +6297,7 @@ var BitfabLangGraphCallbackHandler = class {
6217
6297
  this.sendTraceCompletion(spanInfo, invocation?.activeContext ?? null);
6218
6298
  this.invocations.delete(runId);
6219
6299
  }
6300
+ this.httpClient.traceCompletion.end(spanInfo.traceId, spanInfo.spanId);
6220
6301
  }
6221
6302
  sendSpan(spanInfo) {
6222
6303
  const spanData = {
@@ -6923,6 +7004,55 @@ var StreamFinalizationError = class extends Error {
6923
7004
  // src/client.ts
6924
7005
  init_traceMetadata();
6925
7006
 
7007
+ // src/traces.ts
7008
+ var ASSERTIONS_PATH = "/api/sdk/traces/assertions";
7009
+ var SEARCH_PATH = "/api/sdk/traces/search";
7010
+ function traceAssertionsPath(traceId, suffix = "") {
7011
+ return `/api/sdk/traces/${encodeURIComponent(traceId)}/assertions${suffix}`;
7012
+ }
7013
+ var TracesClient = class {
7014
+ constructor(httpClient) {
7015
+ this.httpClient = httpClient;
7016
+ }
7017
+ /**
7018
+ * Search traces by exact caller metadata.
7019
+ *
7020
+ * Keys and values are matched case-insensitively. Up to 10 supplied pairs
7021
+ * must match. Use `nextCursor` from the result to fetch another page.
7022
+ */
7023
+ async search(params) {
7024
+ return this.httpClient.request(SEARCH_PATH, params);
7025
+ }
7026
+ async getAssertions(traceId) {
7027
+ return this.httpClient.get(
7028
+ traceAssertionsPath(traceId)
7029
+ );
7030
+ }
7031
+ async saveAssertions(params) {
7032
+ return this.saveAssertionsAll({
7033
+ updates: [{ traceId: params.traceId, assertions: params.assertions }],
7034
+ source: params.source
7035
+ });
7036
+ }
7037
+ async saveAssertionsAll(params) {
7038
+ if (params.updates.length === 0) {
7039
+ return [];
7040
+ }
7041
+ const response = await this.httpClient.request(ASSERTIONS_PATH, {
7042
+ updates: params.updates,
7043
+ source: params.source ?? "agent"
7044
+ });
7045
+ return response.assertions;
7046
+ }
7047
+ async archiveAssertions(params) {
7048
+ const response = await this.httpClient.request(
7049
+ traceAssertionsPath(params.traceId, "/archive"),
7050
+ { assertionIds: params.assertionIds }
7051
+ );
7052
+ return response.archived;
7053
+ }
7054
+ };
7055
+
6926
7056
  // src/tracing.ts
6927
7057
  init_constants();
6928
7058
  init_http();
@@ -6938,6 +7068,8 @@ var BitfabOpenAITracingProcessor = class {
6938
7068
  this.activeTraces = {};
6939
7069
  this.activeSpanMappings = {};
6940
7070
  this.canonicalTraceIds = {};
7071
+ this.startedSpans = /* @__PURE__ */ new Map();
7072
+ this.endedTraces = /* @__PURE__ */ new Set();
6941
7073
  this.ownsHttpClient = config._httpClient === void 0;
6942
7074
  this.httpClient = config._httpClient ?? new HttpClient({
6943
7075
  apiKey: config.apiKey,
@@ -6976,6 +7108,10 @@ var BitfabOpenAITracingProcessor = class {
6976
7108
  }
6977
7109
  const canonicalTraceId = activeContext?.traceId ?? this.getCanonicalTraceId(trace.traceId);
6978
7110
  this.canonicalTraceIds[trace.traceId] = canonicalTraceId;
7111
+ this.httpClient.traceCompletion.hold(
7112
+ activeContext?.traceId ?? trace.traceId,
7113
+ `openai:${trace.traceId}`
7114
+ );
6979
7115
  this.sendTrace(trace, {
6980
7116
  id: canonicalTraceId,
6981
7117
  sourceTraceId: activeContext?.traceId
@@ -6993,16 +7129,33 @@ var BitfabOpenAITracingProcessor = class {
6993
7129
  id: mapping?.traceId ?? this.getCanonicalTraceId(trace.traceId),
6994
7130
  sourceTraceId: mapping?.traceId
6995
7131
  });
6996
- delete this.activeSpanMappings[trace.traceId];
6997
- delete this.canonicalTraceIds[trace.traceId];
6998
- delete this.activeTraces[trace.traceId];
7132
+ this.endedTraces.add(trace.traceId);
7133
+ this.httpClient.traceCompletion.end(
7134
+ mapping?.traceId ?? trace.traceId,
7135
+ `openai:${trace.traceId}`
7136
+ );
7137
+ this.cleanupTrace(trace.traceId);
7138
+ }
7139
+ cleanupTrace(traceId) {
7140
+ if (!this.endedTraces.has(traceId) || [...this.startedSpans.values()].includes(traceId)) {
7141
+ return;
7142
+ }
7143
+ this.endedTraces.delete(traceId);
7144
+ delete this.activeSpanMappings[traceId];
7145
+ delete this.canonicalTraceIds[traceId];
7146
+ delete this.activeTraces[traceId];
6999
7147
  }
7000
7148
  /**
7001
7149
  * Called when a span is started. Span payloads are authoritative completed
7002
7150
  * snapshots, so start notifications do not cross the transport boundary.
7003
7151
  */
7004
7152
  // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data
7005
- async onSpanStart(_span) {
7153
+ async onSpanStart(span) {
7154
+ if (span.spanId !== void 0 && span.traceId !== null && span.traceId !== void 0) {
7155
+ this.startedSpans.set(span.spanId, span.traceId);
7156
+ const traceId = this.activeSpanMappings[span.traceId]?.traceId ?? span.traceId;
7157
+ this.httpClient.traceCompletion.start(traceId, span.spanId);
7158
+ }
7006
7159
  }
7007
7160
  /**
7008
7161
  * Called when a span is ended.
@@ -7011,7 +7164,17 @@ var BitfabOpenAITracingProcessor = class {
7011
7164
  */
7012
7165
  // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data
7013
7166
  async onSpanEnd(span) {
7014
- this.sendSpan(span);
7167
+ const originalTraceId = span.traceId ?? "";
7168
+ const traceId = this.activeSpanMappings[originalTraceId]?.traceId ?? originalTraceId;
7169
+ try {
7170
+ this.sendSpan(span);
7171
+ } finally {
7172
+ if (span.spanId !== void 0) {
7173
+ this.httpClient.traceCompletion.end(traceId, span.spanId);
7174
+ this.startedSpans.delete(span.spanId);
7175
+ }
7176
+ this.cleanupTrace(originalTraceId);
7177
+ }
7015
7178
  }
7016
7179
  /**
7017
7180
  * Called when a trace is being flushed.
@@ -8717,6 +8880,7 @@ var Bitfab = class {
8717
8880
  let newStack;
8718
8881
  let executeWithContext;
8719
8882
  let registeredTraceId;
8883
+ let startedSpan;
8720
8884
  try {
8721
8885
  const currentStack = getSpanStack();
8722
8886
  const parentContext = currentStack[currentStack.length - 1];
@@ -8768,6 +8932,8 @@ var Bitfab = class {
8768
8932
  });
8769
8933
  registeredTraceId = traceId;
8770
8934
  }
8935
+ self.httpClient.traceCompletion.start(traceId, spanId);
8936
+ startedSpan = { traceId, spanId };
8771
8937
  const functionName = fn.name !== "" ? fn.name : void 0;
8772
8938
  const rootTraceFunctionKey = activeTraceStates.get(traceId)?.traceFunctionKey ?? traceFunctionKey;
8773
8939
  const baseSpanParams = {
@@ -8842,6 +9008,8 @@ var Bitfab = class {
8842
9008
  retireTraceMetadata(traceId);
8843
9009
  }
8844
9010
  } catch {
9011
+ } finally {
9012
+ self.httpClient.traceCompletion.end(traceId, spanId);
8845
9013
  }
8846
9014
  };
8847
9015
  const recordSpan = (result) => {
@@ -8858,6 +9026,14 @@ var Bitfab = class {
8858
9026
  void sendSpan({ result });
8859
9027
  }
8860
9028
  };
9029
+ const resolveMockOrAbort = async (resolve) => {
9030
+ try {
9031
+ return await resolve();
9032
+ } catch (error) {
9033
+ self.httpClient.traceCompletion.abort(traceId, spanId);
9034
+ throw error;
9035
+ }
9036
+ };
8861
9037
  executeWithContext = () => {
8862
9038
  let result;
8863
9039
  try {
@@ -8914,7 +9090,7 @@ var Bitfab = class {
8914
9090
  );
8915
9091
  }
8916
9092
  return (async () => {
8917
- const output = await pending;
9093
+ const output = await resolveMockOrAbort(() => pending);
8918
9094
  void sendSpan({
8919
9095
  result: output,
8920
9096
  mocked: true,
@@ -8984,7 +9160,7 @@ var Bitfab = class {
8984
9160
  );
8985
9161
  }
8986
9162
  return runWithSpanStack(newStack, async () => {
8987
- const resolved2 = await resolution;
9163
+ const resolved2 = await resolveMockOrAbort(() => resolution);
8988
9164
  if (resolved2.matched) {
8989
9165
  void sendSpan({
8990
9166
  result: resolved2.output,
@@ -9000,7 +9176,9 @@ var Bitfab = class {
9000
9176
  );
9001
9177
  }
9002
9178
  if (shouldMockWithBaseStrategy) {
9003
- const output = await resolveRecordedOutput();
9179
+ const output = await resolveMockOrAbort(
9180
+ () => resolveRecordedOutput()
9181
+ );
9004
9182
  void sendSpan({
9005
9183
  result: output,
9006
9184
  mocked: true,
@@ -9030,6 +9208,12 @@ var Bitfab = class {
9030
9208
  }
9031
9209
  }
9032
9210
  } catch (setupError) {
9211
+ if (startedSpan) {
9212
+ self.httpClient.traceCompletion.abort(
9213
+ startedSpan.traceId,
9214
+ startedSpan.spanId
9215
+ );
9216
+ }
9033
9217
  if (registeredTraceId) {
9034
9218
  activeTraceStates.delete(registeredTraceId);
9035
9219
  retireTraceMetadata(registeredTraceId);