@bitfab/sdk 0.38.0 → 0.38.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.cjs CHANGED
@@ -38,11 +38,12 @@ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot
38
38
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
39
39
 
40
40
  // src/version.generated.ts
41
- var __version__;
41
+ var __version__, __packageName__;
42
42
  var init_version_generated = __esm({
43
43
  "src/version.generated.ts"() {
44
44
  "use strict";
45
- __version__ = "0.38.0";
45
+ __version__ = "0.38.2";
46
+ __packageName__ = "@bitfab/sdk";
46
47
  }
47
48
  });
48
49
 
@@ -811,7 +812,7 @@ var init_otel = __esm({
811
812
  EXPORT_CONCURRENCY_ENV = "BITFAB_OTEL_EXPORT_CONCURRENCY";
812
813
  MAX_QUEUE_SIZE = 8192;
813
814
  DIRECT_MAX_EXPORT_BATCH_SIZE = 512;
814
- DIRECT_MAX_REQUEST_BATCH_SIZE = 8;
815
+ DIRECT_MAX_REQUEST_BATCH_SIZE = 128;
815
816
  DEFAULT_EXPORT_CONCURRENCY = 32;
816
817
  MAX_EXPORT_CONCURRENCY = 64;
817
818
  SCHEDULE_DELAY_MILLIS = 5e3;
@@ -1703,6 +1704,12 @@ var init_http = __esm({
1703
1704
  async lookupFunction(name) {
1704
1705
  return this.request("/api/sdk/functions/lookup", { name });
1705
1706
  }
1707
+ async getAutoTracePolicy(traceFunctionKey, protocol) {
1708
+ return this.request("/api/sdk/auto-trace/policy", {
1709
+ traceFunctionKey,
1710
+ protocol
1711
+ });
1712
+ }
1706
1713
  async getTraceSpan(traceId, lookup) {
1707
1714
  const searchParams = new URLSearchParams();
1708
1715
  if (lookup.id !== void 0) {
@@ -1753,7 +1760,12 @@ var init_http = __esm({
1753
1760
  * the OTLP carrier has no path to carry it.
1754
1761
  */
1755
1762
  sendInternalTrace(functionId, payload) {
1756
- const body = { ...payload, functionId, sdkVersion: __version__ };
1763
+ const body = {
1764
+ ...payload,
1765
+ functionId,
1766
+ sdkPackage: __packageName__,
1767
+ sdkVersion: __version__
1768
+ };
1757
1769
  this.getTraceTransport()?.submit(
1758
1770
  "internal_trace",
1759
1771
  body,
@@ -1782,7 +1794,11 @@ var init_http = __esm({
1782
1794
  sendExternalTrace(payload) {
1783
1795
  this.getTraceTransport()?.submit(
1784
1796
  "external_trace",
1785
- { ...payload, sdkVersion: __version__ },
1797
+ {
1798
+ ...payload,
1799
+ sdkPackage: __packageName__,
1800
+ sdkVersion: __version__
1801
+ },
1786
1802
  this.recordedMeta(
1787
1803
  "external_trace",
1788
1804
  payload,
@@ -3739,6 +3755,80 @@ var BitfabClaudeAgentHandler = class {
3739
3755
  // src/client.ts
3740
3756
  init_asyncStorage();
3741
3757
 
3758
+ // src/autoTrace.ts
3759
+ init_asyncStorage();
3760
+ var autoTraceGlobal = globalThis;
3761
+ var autoTraceState = autoTraceGlobal.__bitfabAutoTraceStateV3 ?? {
3762
+ storage: null,
3763
+ browserScope: void 0,
3764
+ capturePolicies: /* @__PURE__ */ new WeakMap(),
3765
+ activeRoots: 0
3766
+ };
3767
+ autoTraceGlobal.__bitfabAutoTraceStateV3 = autoTraceState;
3768
+ function initializeAutoTraceStorage() {
3769
+ autoTraceState.storage ?? (autoTraceState.storage = createAsyncLocalStorage());
3770
+ }
3771
+ function runWithAutoTraceContext(context, fn, depth = 0) {
3772
+ initializeAutoTraceStorage();
3773
+ const scope = { context, depth };
3774
+ if (autoTraceState.storage) {
3775
+ return autoTraceState.storage.run(scope, fn);
3776
+ }
3777
+ const previous = autoTraceState.browserScope;
3778
+ autoTraceState.browserScope = scope;
3779
+ try {
3780
+ return fn();
3781
+ } finally {
3782
+ autoTraceState.browserScope = previous;
3783
+ }
3784
+ }
3785
+ function runWithAutoTraceRootContext(context, fn) {
3786
+ autoTraceState.activeRoots += 1;
3787
+ let result;
3788
+ try {
3789
+ result = runWithAutoTraceContext(context, fn);
3790
+ } catch (error) {
3791
+ autoTraceState.activeRoots -= 1;
3792
+ throw error;
3793
+ }
3794
+ if (isAutoTraceAsyncGenerator(result)) {
3795
+ autoTraceState.activeRoots -= 1;
3796
+ return wrapAutoTraceAsyncGenerator(context, result);
3797
+ }
3798
+ if (result instanceof Promise) {
3799
+ return result.finally(() => {
3800
+ autoTraceState.activeRoots -= 1;
3801
+ });
3802
+ }
3803
+ autoTraceState.activeRoots -= 1;
3804
+ return result;
3805
+ }
3806
+ function isAutoTraceAsyncGenerator(value) {
3807
+ if (value === null || typeof value !== "object") {
3808
+ return false;
3809
+ }
3810
+ const candidate = value;
3811
+ return typeof candidate.next === "function" && typeof candidate.return === "function" && typeof candidate.throw === "function" && typeof candidate[Symbol.asyncIterator] === "function";
3812
+ }
3813
+ function wrapAutoTraceAsyncGenerator(context, source) {
3814
+ const step = (method, value) => runWithAutoTraceRootContext(context, () => source[method](value));
3815
+ const wrapped = {
3816
+ next: (value) => step("next", value),
3817
+ return: (value) => step("return", value),
3818
+ throw: (error) => step("throw", error),
3819
+ [Symbol.asyncIterator]: () => wrapped
3820
+ };
3821
+ return wrapped;
3822
+ }
3823
+ function __setBitfabAutoTraceCapturePolicy(client, traceFunctionKey, functionIds) {
3824
+ const policies = autoTraceState.capturePolicies.get(client) ?? /* @__PURE__ */ new Map();
3825
+ policies.set(traceFunctionKey, new Set(functionIds));
3826
+ autoTraceState.capturePolicies.set(client, policies);
3827
+ }
3828
+ function getAutoTraceCapturePolicy(client, traceFunctionKey) {
3829
+ return autoTraceState.capturePolicies.get(client)?.get(traceFunctionKey) ?? /* @__PURE__ */ new Set();
3830
+ }
3831
+
3742
3832
  // src/optionalPeer.ts
3743
3833
  function importOptionalPeer(specifierParts) {
3744
3834
  const specifier = specifierParts.join("/");
@@ -5480,6 +5570,14 @@ function readEnv2(name) {
5480
5570
  }
5481
5571
  return void 0;
5482
5572
  }
5573
+ var DEFAULT_AUTO_TRACE_MAX_DEPTH = 30;
5574
+ var DEFAULT_AUTO_TRACE_MAX_SPANS = 500;
5575
+ var AUTO_TRACE_PROTOCOL = "ts-auto-v1";
5576
+ var AUTO_TRACE_POLICY_REFRESH_MS = 6e4;
5577
+ var AUTO_TRACE_POLICY_RETRY_MS = 1e4;
5578
+ function autoTraceLimit(value, fallback) {
5579
+ return value !== void 0 && Number.isFinite(value) && value >= 0 ? Math.floor(value) : fallback;
5580
+ }
5483
5581
  var Bitfab = class {
5484
5582
  /**
5485
5583
  * Initialize the Bitfab client.
@@ -5489,6 +5587,7 @@ var Bitfab = class {
5489
5587
  constructor(config) {
5490
5588
  /** Gate the empty-key warning to fire at most once. */
5491
5589
  this.apiKeyWarned = false;
5590
+ this.autoTracePolicyRefreshes = /* @__PURE__ */ new Map();
5492
5591
  /**
5493
5592
  * Mock overrides registered via {@link Bitfab.registerMockOverride}, applied
5494
5593
  * to every `replay` on this client (after any per-call `mockOverride`). In
@@ -5512,6 +5611,178 @@ var Bitfab = class {
5512
5611
  timeout: this.timeout
5513
5612
  });
5514
5613
  }
5614
+ /**
5615
+ * Decorate a class method as an automatically expanded trace root.
5616
+ *
5617
+ * Build instrumentation turns repository functions called beneath this
5618
+ * method into nested spans. Every generated span preserves structure; only
5619
+ * function IDs selected by the capture policy include inputs and output.
5620
+ * Without a compatible build transform, this still records the decorated
5621
+ * method as a normal rich root span but cannot discover child calls.
5622
+ *
5623
+ * @param traceFunctionKey - Groups traces and their capture policy.
5624
+ * @param options - Root presentation, subtree bounds, and exclusions.
5625
+ * @experimental Automatic child-call instrumentation is experimental.
5626
+ */
5627
+ trace(traceFunctionKey, options = {}) {
5628
+ const decorator = (...args) => {
5629
+ if (args.length === 3) {
5630
+ const propertyKey = args[1];
5631
+ const descriptor = args[2];
5632
+ if (!descriptor || typeof descriptor.value !== "function") {
5633
+ throw new BitfabError("@bitfab.trace can only decorate methods");
5634
+ }
5635
+ if (!this.explicitlyEnabled) {
5636
+ return;
5637
+ }
5638
+ descriptor.value = this.createAutoTraceRoot(
5639
+ traceFunctionKey,
5640
+ String(propertyKey),
5641
+ options,
5642
+ descriptor.value
5643
+ );
5644
+ return;
5645
+ }
5646
+ const method = args[0];
5647
+ const context = args[1];
5648
+ if (typeof method !== "function" || context?.kind !== "method" || context.name === void 0) {
5649
+ throw new BitfabError("@bitfab.trace can only decorate methods");
5650
+ }
5651
+ if (!this.explicitlyEnabled) {
5652
+ return method;
5653
+ }
5654
+ return this.createAutoTraceRoot(
5655
+ traceFunctionKey,
5656
+ String(context.name),
5657
+ options,
5658
+ method
5659
+ );
5660
+ };
5661
+ return decorator;
5662
+ }
5663
+ withTrace(traceFunctionKey, optionsOrFn, maybeFn) {
5664
+ const options = typeof optionsOrFn === "function" ? {} : optionsOrFn;
5665
+ const fn = typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
5666
+ if (!fn) {
5667
+ throw new BitfabError("bitfab.withTrace requires a function");
5668
+ }
5669
+ if (!this.explicitlyEnabled) {
5670
+ return fn;
5671
+ }
5672
+ const name = fn.name !== "" ? fn.name : traceFunctionKey;
5673
+ return this.createAutoTraceRoot(traceFunctionKey, name, options, fn);
5674
+ }
5675
+ createAutoTraceRoot(traceFunctionKey, name, options, fn) {
5676
+ const self = this;
5677
+ const maxDepth = autoTraceLimit(
5678
+ options.maxDepth,
5679
+ DEFAULT_AUTO_TRACE_MAX_DEPTH
5680
+ );
5681
+ const maxSpans = autoTraceLimit(
5682
+ options.maxSpans,
5683
+ DEFAULT_AUTO_TRACE_MAX_SPANS
5684
+ );
5685
+ const excluded = new Set(options.exclude ?? []);
5686
+ const includeWrappers = options.includeWrappers ?? false;
5687
+ const tracedRoot = this.withSpan(
5688
+ traceFunctionKey,
5689
+ { name: options.name ?? name, type: options.type ?? "custom" },
5690
+ function(...args) {
5691
+ const capturePolicy = getAutoTraceCapturePolicy(self, traceFunctionKey);
5692
+ self.refreshAutoTraceCapturePolicy(traceFunctionKey);
5693
+ let spansUsed = 0;
5694
+ let truncated = false;
5695
+ const warnTruncated = () => {
5696
+ if (!truncated) {
5697
+ truncated = true;
5698
+ getCurrentTrace().setMetadata({
5699
+ bitfabAutoTrace: {
5700
+ protocol: AUTO_TRACE_PROTOCOL,
5701
+ truncated: true,
5702
+ maxDepth,
5703
+ maxSpans
5704
+ }
5705
+ });
5706
+ }
5707
+ warnOnce(
5708
+ `auto-trace-truncated:${traceFunctionKey}`,
5709
+ `"${traceFunctionKey}" hit an automatic subtree capture limit (maxDepth=${maxDepth}, maxSpans=${maxSpans}); its trace is incomplete. Raise the limits or narrow the subtree with exclude.`
5710
+ );
5711
+ };
5712
+ const autoTraceContext = {
5713
+ invoke(definition, inputs, invokeFn, depth) {
5714
+ const nameParts = definition.name.split(".");
5715
+ const simpleName = nameParts[nameParts.length - 1];
5716
+ if (excluded.has(definition.name) || simpleName !== void 0 && excluded.has(simpleName) || definition.wrapper === true && !includeWrappers) {
5717
+ return invokeFn();
5718
+ }
5719
+ if (depth >= maxDepth || spansUsed >= maxSpans) {
5720
+ warnTruncated();
5721
+ return invokeFn();
5722
+ }
5723
+ spansUsed += 1;
5724
+ const childOptions = {
5725
+ name: definition.name,
5726
+ type: "function",
5727
+ captureWhen: "nested",
5728
+ functionId: definition.id,
5729
+ captureContent: capturePolicy.has(definition.id),
5730
+ autoTraceDefinition: definition
5731
+ };
5732
+ const tracedChild = self.withSpan(
5733
+ traceFunctionKey,
5734
+ childOptions,
5735
+ (..._inputs) => runWithAutoTraceContext(autoTraceContext, invokeFn, depth + 1)
5736
+ );
5737
+ return tracedChild(...inputs);
5738
+ }
5739
+ };
5740
+ return runWithAutoTraceRootContext(
5741
+ autoTraceContext,
5742
+ () => fn.apply(this, args)
5743
+ );
5744
+ }
5745
+ );
5746
+ const autoTraceRoot = function(...args) {
5747
+ if (!self.isTracingEnabled()) {
5748
+ return fn.apply(this, args);
5749
+ }
5750
+ return tracedRoot.apply(this, args);
5751
+ };
5752
+ Object.defineProperty(autoTraceRoot, "_bitfabTraceFunctionKey", {
5753
+ value: traceFunctionKey
5754
+ });
5755
+ return autoTraceRoot;
5756
+ }
5757
+ refreshAutoTraceCapturePolicy(traceFunctionKey) {
5758
+ const now = Date.now();
5759
+ const state = this.autoTracePolicyRefreshes.get(traceFunctionKey) ?? {
5760
+ refreshAfter: 0
5761
+ };
5762
+ if (state.inFlight || now < state.refreshAfter) {
5763
+ return;
5764
+ }
5765
+ const request = this.httpClient.getAutoTracePolicy(
5766
+ traceFunctionKey,
5767
+ AUTO_TRACE_PROTOCOL
5768
+ ).then((policy) => {
5769
+ if (policy.protocol !== AUTO_TRACE_PROTOCOL) {
5770
+ state.refreshAfter = Date.now() + AUTO_TRACE_POLICY_RETRY_MS;
5771
+ return;
5772
+ }
5773
+ const functionIds = Array.isArray(policy.functionIds) ? policy.functionIds.filter(
5774
+ (id) => typeof id === "string" && id.startsWith(`${AUTO_TRACE_PROTOCOL}:`)
5775
+ ).slice(0, DEFAULT_AUTO_TRACE_MAX_SPANS) : [];
5776
+ __setBitfabAutoTraceCapturePolicy(this, traceFunctionKey, functionIds);
5777
+ state.refreshAfter = Date.now() + AUTO_TRACE_POLICY_REFRESH_MS;
5778
+ }).catch(() => {
5779
+ state.refreshAfter = Date.now() + AUTO_TRACE_POLICY_RETRY_MS;
5780
+ }).finally(() => {
5781
+ state.inFlight = void 0;
5782
+ });
5783
+ state.inFlight = request;
5784
+ this.autoTracePolicyRefreshes.set(traceFunctionKey, state);
5785
+ }
5515
5786
  /**
5516
5787
  * Flush and permanently close this client's tracing resources: its pending
5517
5788
  * requests and the single span-transport worker shared by its decorators and
@@ -6058,7 +6329,10 @@ var Bitfab = class {
6058
6329
  parentSpanId,
6059
6330
  inputs,
6060
6331
  startedAt,
6061
- spanType: options.type ?? "custom"
6332
+ spanType: options.type ?? "custom",
6333
+ functionId: options.functionId,
6334
+ captureContent: options.captureContent ?? true,
6335
+ autoTraceDefinition: options.autoTraceDefinition
6062
6336
  };
6063
6337
  const sendSpan = async (params) => {
6064
6338
  const replayCtx = getReplayContext();
@@ -6223,7 +6497,16 @@ var Bitfab = class {
6223
6497
  }
6224
6498
  };
6225
6499
  executeWithContext = () => {
6226
- const result = fn.apply(this, args);
6500
+ let result;
6501
+ try {
6502
+ result = fn.apply(this, args);
6503
+ } catch (error) {
6504
+ void sendSpan({
6505
+ result: void 0,
6506
+ error: error instanceof Error ? error.message : String(error)
6507
+ });
6508
+ throw error;
6509
+ }
6227
6510
  if (result instanceof Promise) {
6228
6511
  return result.then((resolvedResult) => {
6229
6512
  recordSpan(resolvedResult);
@@ -6464,8 +6747,8 @@ var Bitfab = class {
6464
6747
  * Queued on the client's span transport; delivery is the transport's job.
6465
6748
  */
6466
6749
  sendWrapperSpan(params) {
6467
- const serializedInputs = serializeValue(params.inputs);
6468
- const serializedResult = serializeValue(params.result);
6750
+ const serializedInputs = params.captureContent ? serializeValue(params.inputs) : void 0;
6751
+ const serializedResult = params.captureContent ? serializeValue(params.result) : void 0;
6469
6752
  const externalSpan = {
6470
6753
  id: params.spanId,
6471
6754
  trace_id: params.traceId,
@@ -6474,26 +6757,38 @@ var Bitfab = class {
6474
6757
  span_data: {
6475
6758
  name: params.spanName,
6476
6759
  type: params.spanType,
6477
- input: serializedInputs.json,
6478
- output: serializedResult.json,
6479
- // Include superjson meta for type preservation
6480
- ...serializedInputs.meta !== void 0 && {
6481
- input_meta: serializedInputs.meta
6760
+ ...params.functionId !== void 0 && {
6761
+ function_id: params.functionId,
6762
+ content_captured: params.captureContent
6763
+ },
6764
+ ...params.autoTraceDefinition !== void 0 && {
6765
+ function_file: params.autoTraceDefinition.file,
6766
+ function_line: params.autoTraceDefinition.line,
6767
+ function_column: params.autoTraceDefinition.column
6482
6768
  },
6483
- ...serializedResult.meta !== void 0 && {
6484
- output_meta: serializedResult.meta
6769
+ ...serializedInputs !== void 0 && {
6770
+ input: serializedInputs.json,
6771
+ ...serializedInputs.meta !== void 0 && {
6772
+ input_meta: serializedInputs.meta
6773
+ }
6774
+ },
6775
+ ...serializedResult !== void 0 && {
6776
+ output: serializedResult.json,
6777
+ ...serializedResult.meta !== void 0 && {
6778
+ output_meta: serializedResult.meta
6779
+ }
6485
6780
  },
6486
6781
  ...params.functionName !== void 0 && {
6487
6782
  function_name: params.functionName
6488
6783
  },
6489
- ...params.error !== void 0 && {
6784
+ ...params.captureContent && params.error !== void 0 && {
6490
6785
  error: params.error,
6491
6786
  error_source: "code"
6492
6787
  },
6493
- ...params.contexts && params.contexts.length > 0 && {
6788
+ ...params.captureContent && params.contexts && params.contexts.length > 0 && {
6494
6789
  contexts: params.contexts
6495
6790
  },
6496
- ...params.prompt !== void 0 && { prompt: params.prompt }
6791
+ ...params.captureContent && params.prompt !== void 0 && { prompt: params.prompt }
6497
6792
  }
6498
6793
  };
6499
6794
  if (params.parentSpanId) {