@bitfab/sdk 0.38.1 → 0.38.3

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.cjs CHANGED
@@ -42,7 +42,7 @@ var __version__, __packageName__;
42
42
  var init_version_generated = __esm({
43
43
  "src/version.generated.ts"() {
44
44
  "use strict";
45
- __version__ = "0.38.1";
45
+ __version__ = "0.38.3";
46
46
  __packageName__ = "@bitfab/sdk";
47
47
  }
48
48
  });
@@ -812,7 +812,7 @@ var init_otel = __esm({
812
812
  EXPORT_CONCURRENCY_ENV = "BITFAB_OTEL_EXPORT_CONCURRENCY";
813
813
  MAX_QUEUE_SIZE = 8192;
814
814
  DIRECT_MAX_EXPORT_BATCH_SIZE = 512;
815
- DIRECT_MAX_REQUEST_BATCH_SIZE = 8;
815
+ DIRECT_MAX_REQUEST_BATCH_SIZE = 128;
816
816
  DEFAULT_EXPORT_CONCURRENCY = 32;
817
817
  MAX_EXPORT_CONCURRENCY = 64;
818
818
  SCHEDULE_DELAY_MILLIS = 5e3;
@@ -1704,6 +1704,12 @@ var init_http = __esm({
1704
1704
  async lookupFunction(name) {
1705
1705
  return this.request("/api/sdk/functions/lookup", { name });
1706
1706
  }
1707
+ async getAutoTracePolicy(traceFunctionKey, protocol) {
1708
+ return this.request("/api/sdk/auto-trace/policy", {
1709
+ traceFunctionKey,
1710
+ protocol
1711
+ });
1712
+ }
1707
1713
  async getTraceSpan(traceId, lookup) {
1708
1714
  const searchParams = new URLSearchParams();
1709
1715
  if (lookup.id !== void 0) {
@@ -2798,6 +2804,11 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options, reg
2798
2804
  );
2799
2805
  }
2800
2806
  }
2807
+ if (options?.traceIds !== void 0 && options?.datasetId !== void 0) {
2808
+ throw new BitfabError(
2809
+ "traceIds and datasetId select different replay sources and cannot be used together."
2810
+ );
2811
+ }
2801
2812
  if (options?.limit !== void 0 && options?.traceIds !== void 0) {
2802
2813
  try {
2803
2814
  console.warn(
@@ -3125,6 +3136,7 @@ __export(index_exports, {
3125
3136
  ReplayError: () => ReplayError,
3126
3137
  SUPPORTED_PROVIDERS: () => SUPPORTED_PROVIDERS,
3127
3138
  __version__: () => __version__,
3139
+ defineReplayRegistry: () => defineReplayRegistry,
3128
3140
  finalizers: () => finalizers,
3129
3141
  flushTraces: () => flushTraces,
3130
3142
  getCurrentReplayBranch: () => getCurrentReplayBranch,
@@ -3749,6 +3761,80 @@ var BitfabClaudeAgentHandler = class {
3749
3761
  // src/client.ts
3750
3762
  init_asyncStorage();
3751
3763
 
3764
+ // src/autoTrace.ts
3765
+ init_asyncStorage();
3766
+ var autoTraceGlobal = globalThis;
3767
+ var autoTraceState = autoTraceGlobal.__bitfabAutoTraceStateV3 ?? {
3768
+ storage: null,
3769
+ browserScope: void 0,
3770
+ capturePolicies: /* @__PURE__ */ new WeakMap(),
3771
+ activeRoots: 0
3772
+ };
3773
+ autoTraceGlobal.__bitfabAutoTraceStateV3 = autoTraceState;
3774
+ function initializeAutoTraceStorage() {
3775
+ autoTraceState.storage ?? (autoTraceState.storage = createAsyncLocalStorage());
3776
+ }
3777
+ function runWithAutoTraceContext(context, fn, depth = 0) {
3778
+ initializeAutoTraceStorage();
3779
+ const scope = { context, depth };
3780
+ if (autoTraceState.storage) {
3781
+ return autoTraceState.storage.run(scope, fn);
3782
+ }
3783
+ const previous = autoTraceState.browserScope;
3784
+ autoTraceState.browserScope = scope;
3785
+ try {
3786
+ return fn();
3787
+ } finally {
3788
+ autoTraceState.browserScope = previous;
3789
+ }
3790
+ }
3791
+ function runWithAutoTraceRootContext(context, fn) {
3792
+ autoTraceState.activeRoots += 1;
3793
+ let result;
3794
+ try {
3795
+ result = runWithAutoTraceContext(context, fn);
3796
+ } catch (error) {
3797
+ autoTraceState.activeRoots -= 1;
3798
+ throw error;
3799
+ }
3800
+ if (isAutoTraceAsyncGenerator(result)) {
3801
+ autoTraceState.activeRoots -= 1;
3802
+ return wrapAutoTraceAsyncGenerator(context, result);
3803
+ }
3804
+ if (result instanceof Promise) {
3805
+ return result.finally(() => {
3806
+ autoTraceState.activeRoots -= 1;
3807
+ });
3808
+ }
3809
+ autoTraceState.activeRoots -= 1;
3810
+ return result;
3811
+ }
3812
+ function isAutoTraceAsyncGenerator(value) {
3813
+ if (value === null || typeof value !== "object") {
3814
+ return false;
3815
+ }
3816
+ const candidate = value;
3817
+ return typeof candidate.next === "function" && typeof candidate.return === "function" && typeof candidate.throw === "function" && typeof candidate[Symbol.asyncIterator] === "function";
3818
+ }
3819
+ function wrapAutoTraceAsyncGenerator(context, source) {
3820
+ const step = (method, value) => runWithAutoTraceRootContext(context, () => source[method](value));
3821
+ const wrapped = {
3822
+ next: (value) => step("next", value),
3823
+ return: (value) => step("return", value),
3824
+ throw: (error) => step("throw", error),
3825
+ [Symbol.asyncIterator]: () => wrapped
3826
+ };
3827
+ return wrapped;
3828
+ }
3829
+ function __setBitfabAutoTraceCapturePolicy(client, traceFunctionKey, functionIds) {
3830
+ const policies = autoTraceState.capturePolicies.get(client) ?? /* @__PURE__ */ new Map();
3831
+ policies.set(traceFunctionKey, new Set(functionIds));
3832
+ autoTraceState.capturePolicies.set(client, policies);
3833
+ }
3834
+ function getAutoTraceCapturePolicy(client, traceFunctionKey) {
3835
+ return autoTraceState.capturePolicies.get(client)?.get(traceFunctionKey) ?? /* @__PURE__ */ new Set();
3836
+ }
3837
+
3752
3838
  // src/optionalPeer.ts
3753
3839
  function importOptionalPeer(specifierParts) {
3754
3840
  const specifier = specifierParts.join("/");
@@ -5490,6 +5576,14 @@ function readEnv2(name) {
5490
5576
  }
5491
5577
  return void 0;
5492
5578
  }
5579
+ var DEFAULT_AUTO_TRACE_MAX_DEPTH = 30;
5580
+ var DEFAULT_AUTO_TRACE_MAX_SPANS = 500;
5581
+ var AUTO_TRACE_PROTOCOL = "ts-auto-v1";
5582
+ var AUTO_TRACE_POLICY_REFRESH_MS = 6e4;
5583
+ var AUTO_TRACE_POLICY_RETRY_MS = 1e4;
5584
+ function autoTraceLimit(value, fallback) {
5585
+ return value !== void 0 && Number.isFinite(value) && value >= 0 ? Math.floor(value) : fallback;
5586
+ }
5493
5587
  var Bitfab = class {
5494
5588
  /**
5495
5589
  * Initialize the Bitfab client.
@@ -5499,6 +5593,7 @@ var Bitfab = class {
5499
5593
  constructor(config) {
5500
5594
  /** Gate the empty-key warning to fire at most once. */
5501
5595
  this.apiKeyWarned = false;
5596
+ this.autoTracePolicyRefreshes = /* @__PURE__ */ new Map();
5502
5597
  /**
5503
5598
  * Mock overrides registered via {@link Bitfab.registerMockOverride}, applied
5504
5599
  * to every `replay` on this client (after any per-call `mockOverride`). In
@@ -5522,6 +5617,178 @@ var Bitfab = class {
5522
5617
  timeout: this.timeout
5523
5618
  });
5524
5619
  }
5620
+ /**
5621
+ * Decorate a class method as an automatically expanded trace root.
5622
+ *
5623
+ * Build instrumentation turns repository functions called beneath this
5624
+ * method into nested spans. Every generated span preserves structure; only
5625
+ * function IDs selected by the capture policy include inputs and output.
5626
+ * Without a compatible build transform, this still records the decorated
5627
+ * method as a normal rich root span but cannot discover child calls.
5628
+ *
5629
+ * @param traceFunctionKey - Groups traces and their capture policy.
5630
+ * @param options - Root presentation, subtree bounds, and exclusions.
5631
+ * @experimental Automatic child-call instrumentation is experimental.
5632
+ */
5633
+ trace(traceFunctionKey, options = {}) {
5634
+ const decorator = (...args) => {
5635
+ if (args.length === 3) {
5636
+ const propertyKey = args[1];
5637
+ const descriptor = args[2];
5638
+ if (!descriptor || typeof descriptor.value !== "function") {
5639
+ throw new BitfabError("@bitfab.trace can only decorate methods");
5640
+ }
5641
+ if (!this.explicitlyEnabled) {
5642
+ return;
5643
+ }
5644
+ descriptor.value = this.createAutoTraceRoot(
5645
+ traceFunctionKey,
5646
+ String(propertyKey),
5647
+ options,
5648
+ descriptor.value
5649
+ );
5650
+ return;
5651
+ }
5652
+ const method = args[0];
5653
+ const context = args[1];
5654
+ if (typeof method !== "function" || context?.kind !== "method" || context.name === void 0) {
5655
+ throw new BitfabError("@bitfab.trace can only decorate methods");
5656
+ }
5657
+ if (!this.explicitlyEnabled) {
5658
+ return method;
5659
+ }
5660
+ return this.createAutoTraceRoot(
5661
+ traceFunctionKey,
5662
+ String(context.name),
5663
+ options,
5664
+ method
5665
+ );
5666
+ };
5667
+ return decorator;
5668
+ }
5669
+ withTrace(traceFunctionKey, optionsOrFn, maybeFn) {
5670
+ const options = typeof optionsOrFn === "function" ? {} : optionsOrFn;
5671
+ const fn = typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
5672
+ if (!fn) {
5673
+ throw new BitfabError("bitfab.withTrace requires a function");
5674
+ }
5675
+ if (!this.explicitlyEnabled) {
5676
+ return fn;
5677
+ }
5678
+ const name = fn.name !== "" ? fn.name : traceFunctionKey;
5679
+ return this.createAutoTraceRoot(traceFunctionKey, name, options, fn);
5680
+ }
5681
+ createAutoTraceRoot(traceFunctionKey, name, options, fn) {
5682
+ const self = this;
5683
+ const maxDepth = autoTraceLimit(
5684
+ options.maxDepth,
5685
+ DEFAULT_AUTO_TRACE_MAX_DEPTH
5686
+ );
5687
+ const maxSpans = autoTraceLimit(
5688
+ options.maxSpans,
5689
+ DEFAULT_AUTO_TRACE_MAX_SPANS
5690
+ );
5691
+ const excluded = new Set(options.exclude ?? []);
5692
+ const includeWrappers = options.includeWrappers ?? false;
5693
+ const tracedRoot = this.withSpan(
5694
+ traceFunctionKey,
5695
+ { name: options.name ?? name, type: options.type ?? "custom" },
5696
+ function(...args) {
5697
+ const capturePolicy = getAutoTraceCapturePolicy(self, traceFunctionKey);
5698
+ self.refreshAutoTraceCapturePolicy(traceFunctionKey);
5699
+ let spansUsed = 0;
5700
+ let truncated = false;
5701
+ const warnTruncated = () => {
5702
+ if (!truncated) {
5703
+ truncated = true;
5704
+ getCurrentTrace().setMetadata({
5705
+ bitfabAutoTrace: {
5706
+ protocol: AUTO_TRACE_PROTOCOL,
5707
+ truncated: true,
5708
+ maxDepth,
5709
+ maxSpans
5710
+ }
5711
+ });
5712
+ }
5713
+ warnOnce(
5714
+ `auto-trace-truncated:${traceFunctionKey}`,
5715
+ `"${traceFunctionKey}" hit an automatic subtree capture limit (maxDepth=${maxDepth}, maxSpans=${maxSpans}); its trace is incomplete. Raise the limits or narrow the subtree with exclude.`
5716
+ );
5717
+ };
5718
+ const autoTraceContext = {
5719
+ invoke(definition, inputs, invokeFn, depth) {
5720
+ const nameParts = definition.name.split(".");
5721
+ const simpleName = nameParts[nameParts.length - 1];
5722
+ if (excluded.has(definition.name) || simpleName !== void 0 && excluded.has(simpleName) || definition.wrapper === true && !includeWrappers) {
5723
+ return invokeFn();
5724
+ }
5725
+ if (depth >= maxDepth || spansUsed >= maxSpans) {
5726
+ warnTruncated();
5727
+ return invokeFn();
5728
+ }
5729
+ spansUsed += 1;
5730
+ const childOptions = {
5731
+ name: definition.name,
5732
+ type: "function",
5733
+ captureWhen: "nested",
5734
+ functionId: definition.id,
5735
+ captureContent: capturePolicy.has(definition.id),
5736
+ autoTraceDefinition: definition
5737
+ };
5738
+ const tracedChild = self.withSpan(
5739
+ traceFunctionKey,
5740
+ childOptions,
5741
+ (..._inputs) => runWithAutoTraceContext(autoTraceContext, invokeFn, depth + 1)
5742
+ );
5743
+ return tracedChild(...inputs);
5744
+ }
5745
+ };
5746
+ return runWithAutoTraceRootContext(
5747
+ autoTraceContext,
5748
+ () => fn.apply(this, args)
5749
+ );
5750
+ }
5751
+ );
5752
+ const autoTraceRoot = function(...args) {
5753
+ if (!self.isTracingEnabled()) {
5754
+ return fn.apply(this, args);
5755
+ }
5756
+ return tracedRoot.apply(this, args);
5757
+ };
5758
+ Object.defineProperty(autoTraceRoot, "_bitfabTraceFunctionKey", {
5759
+ value: traceFunctionKey
5760
+ });
5761
+ return autoTraceRoot;
5762
+ }
5763
+ refreshAutoTraceCapturePolicy(traceFunctionKey) {
5764
+ const now = Date.now();
5765
+ const state = this.autoTracePolicyRefreshes.get(traceFunctionKey) ?? {
5766
+ refreshAfter: 0
5767
+ };
5768
+ if (state.inFlight || now < state.refreshAfter) {
5769
+ return;
5770
+ }
5771
+ const request = this.httpClient.getAutoTracePolicy(
5772
+ traceFunctionKey,
5773
+ AUTO_TRACE_PROTOCOL
5774
+ ).then((policy) => {
5775
+ if (policy.protocol !== AUTO_TRACE_PROTOCOL) {
5776
+ state.refreshAfter = Date.now() + AUTO_TRACE_POLICY_RETRY_MS;
5777
+ return;
5778
+ }
5779
+ const functionIds = Array.isArray(policy.functionIds) ? policy.functionIds.filter(
5780
+ (id) => typeof id === "string" && id.startsWith(`${AUTO_TRACE_PROTOCOL}:`)
5781
+ ).slice(0, DEFAULT_AUTO_TRACE_MAX_SPANS) : [];
5782
+ __setBitfabAutoTraceCapturePolicy(this, traceFunctionKey, functionIds);
5783
+ state.refreshAfter = Date.now() + AUTO_TRACE_POLICY_REFRESH_MS;
5784
+ }).catch(() => {
5785
+ state.refreshAfter = Date.now() + AUTO_TRACE_POLICY_RETRY_MS;
5786
+ }).finally(() => {
5787
+ state.inFlight = void 0;
5788
+ });
5789
+ state.inFlight = request;
5790
+ this.autoTracePolicyRefreshes.set(traceFunctionKey, state);
5791
+ }
5525
5792
  /**
5526
5793
  * Flush and permanently close this client's tracing resources: its pending
5527
5794
  * requests and the single span-transport worker shared by its decorators and
@@ -6068,7 +6335,10 @@ var Bitfab = class {
6068
6335
  parentSpanId,
6069
6336
  inputs,
6070
6337
  startedAt,
6071
- spanType: options.type ?? "custom"
6338
+ spanType: options.type ?? "custom",
6339
+ functionId: options.functionId,
6340
+ captureContent: options.captureContent ?? true,
6341
+ autoTraceDefinition: options.autoTraceDefinition
6072
6342
  };
6073
6343
  const sendSpan = async (params) => {
6074
6344
  const replayCtx = getReplayContext();
@@ -6233,7 +6503,16 @@ var Bitfab = class {
6233
6503
  }
6234
6504
  };
6235
6505
  executeWithContext = () => {
6236
- const result = fn.apply(this, args);
6506
+ let result;
6507
+ try {
6508
+ result = fn.apply(this, args);
6509
+ } catch (error) {
6510
+ void sendSpan({
6511
+ result: void 0,
6512
+ error: error instanceof Error ? error.message : String(error)
6513
+ });
6514
+ throw error;
6515
+ }
6237
6516
  if (result instanceof Promise) {
6238
6517
  return result.then((resolvedResult) => {
6239
6518
  recordSpan(resolvedResult);
@@ -6474,8 +6753,8 @@ var Bitfab = class {
6474
6753
  * Queued on the client's span transport; delivery is the transport's job.
6475
6754
  */
6476
6755
  sendWrapperSpan(params) {
6477
- const serializedInputs = serializeValue(params.inputs);
6478
- const serializedResult = serializeValue(params.result);
6756
+ const serializedInputs = params.captureContent ? serializeValue(params.inputs) : void 0;
6757
+ const serializedResult = params.captureContent ? serializeValue(params.result) : void 0;
6479
6758
  const externalSpan = {
6480
6759
  id: params.spanId,
6481
6760
  trace_id: params.traceId,
@@ -6484,26 +6763,38 @@ var Bitfab = class {
6484
6763
  span_data: {
6485
6764
  name: params.spanName,
6486
6765
  type: params.spanType,
6487
- input: serializedInputs.json,
6488
- output: serializedResult.json,
6489
- // Include superjson meta for type preservation
6490
- ...serializedInputs.meta !== void 0 && {
6491
- input_meta: serializedInputs.meta
6766
+ ...params.functionId !== void 0 && {
6767
+ function_id: params.functionId,
6768
+ content_captured: params.captureContent
6769
+ },
6770
+ ...params.autoTraceDefinition !== void 0 && {
6771
+ function_file: params.autoTraceDefinition.file,
6772
+ function_line: params.autoTraceDefinition.line,
6773
+ function_column: params.autoTraceDefinition.column
6492
6774
  },
6493
- ...serializedResult.meta !== void 0 && {
6494
- output_meta: serializedResult.meta
6775
+ ...serializedInputs !== void 0 && {
6776
+ input: serializedInputs.json,
6777
+ ...serializedInputs.meta !== void 0 && {
6778
+ input_meta: serializedInputs.meta
6779
+ }
6780
+ },
6781
+ ...serializedResult !== void 0 && {
6782
+ output: serializedResult.json,
6783
+ ...serializedResult.meta !== void 0 && {
6784
+ output_meta: serializedResult.meta
6785
+ }
6495
6786
  },
6496
6787
  ...params.functionName !== void 0 && {
6497
6788
  function_name: params.functionName
6498
6789
  },
6499
- ...params.error !== void 0 && {
6790
+ ...params.captureContent && params.error !== void 0 && {
6500
6791
  error: params.error,
6501
6792
  error_source: "code"
6502
6793
  },
6503
- ...params.contexts && params.contexts.length > 0 && {
6794
+ ...params.captureContent && params.contexts && params.contexts.length > 0 && {
6504
6795
  contexts: params.contexts
6505
6796
  },
6506
- ...params.prompt !== void 0 && { prompt: params.prompt }
6797
+ ...params.captureContent && params.prompt !== void 0 && { prompt: params.prompt }
6507
6798
  }
6508
6799
  };
6509
6800
  if (params.parentSpanId) {
@@ -6778,6 +7069,13 @@ var finalizers = {
6778
7069
  // src/index.ts
6779
7070
  init_http();
6780
7071
  init_replay();
7072
+
7073
+ // src/replayRegistry.ts
7074
+ init_errors();
7075
+ init_replay();
7076
+ function defineReplayRegistry(registry) {
7077
+ return registry;
7078
+ }
6781
7079
  // Annotate the CommonJS export names for ESM import in node:
6782
7080
  0 && (module.exports = {
6783
7081
  BITFAB_PROGRESS_PREFIX,
@@ -6796,6 +7094,7 @@ init_replay();
6796
7094
  ReplayError,
6797
7095
  SUPPORTED_PROVIDERS,
6798
7096
  __version__,
7097
+ defineReplayRegistry,
6799
7098
  finalizers,
6800
7099
  flushTraces,
6801
7100
  getCurrentReplayBranch,