@bitfab/sdk 0.18.2 → 0.19.1

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
@@ -45,6 +45,120 @@ var init_errors = __esm({
45
45
  }
46
46
  });
47
47
 
48
+ // src/serialize.ts
49
+ function describeValue(value) {
50
+ try {
51
+ const ctorName = value?.constructor?.name;
52
+ if (ctorName && ctorName !== "Object") {
53
+ return ctorName;
54
+ }
55
+ } catch {
56
+ }
57
+ return typeof value;
58
+ }
59
+ function unserializableStub(value, reason) {
60
+ let summary;
61
+ try {
62
+ summary = `<unserializable: ${describeValue(value)} (${reason})>`;
63
+ } catch {
64
+ summary = `<unserializable (${reason})>`;
65
+ }
66
+ return { json: summary };
67
+ }
68
+ function serializeValue(value) {
69
+ try {
70
+ const { json, meta } = import_superjson.default.serialize(value);
71
+ let size;
72
+ try {
73
+ size = JSON.stringify(json).length;
74
+ } catch {
75
+ return unserializableStub(value, "stringify_failed_after_superjson");
76
+ }
77
+ if (size > MAX_SERIALIZED_BYTES) {
78
+ return unserializableStub(value, `too_large_${size}_bytes`);
79
+ }
80
+ return meta ? { json, meta } : { json };
81
+ } catch {
82
+ try {
83
+ return { json: JSON.parse(JSON.stringify(value)) };
84
+ } catch {
85
+ return unserializableStub(value, "json_stringify_failed");
86
+ }
87
+ }
88
+ }
89
+ function deserializeValue(serialized) {
90
+ if (serialized.meta === void 0) {
91
+ return serialized.json;
92
+ }
93
+ return import_superjson.default.deserialize({
94
+ json: serialized.json,
95
+ meta: serialized.meta
96
+ });
97
+ }
98
+ function toJsonSafe(value) {
99
+ return toJsonSafeInner(value, 0, /* @__PURE__ */ new WeakSet());
100
+ }
101
+ function toJsonSafeInner(value, depth, seen) {
102
+ if (value === null || value === void 0) {
103
+ return value;
104
+ }
105
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
106
+ return value;
107
+ }
108
+ const className = value?.constructor?.name ?? typeof value;
109
+ if (depth > MAX_SAFE_DEPTH) {
110
+ return `<${className}>`;
111
+ }
112
+ if (typeof value !== "object") {
113
+ try {
114
+ return String(value);
115
+ } catch {
116
+ return `<${className}>`;
117
+ }
118
+ }
119
+ if (seen.has(value)) {
120
+ return `<cycle ${className}>`;
121
+ }
122
+ seen.add(value);
123
+ let result;
124
+ if (Array.isArray(value)) {
125
+ result = value.map((item) => toJsonSafeInner(item, depth + 1, seen));
126
+ } else if (typeof value.toJSON === "function") {
127
+ try {
128
+ result = toJsonSafeInner(
129
+ value.toJSON(),
130
+ depth + 1,
131
+ seen
132
+ );
133
+ } catch {
134
+ result = `<${className}>`;
135
+ }
136
+ } else {
137
+ try {
138
+ const obj = {};
139
+ for (const [k, v] of Object.entries(value)) {
140
+ if (!k.startsWith("_")) {
141
+ obj[k] = toJsonSafeInner(v, depth + 1, seen);
142
+ }
143
+ }
144
+ result = obj;
145
+ } catch {
146
+ result = `<${className}>`;
147
+ }
148
+ }
149
+ seen.delete(value);
150
+ return result;
151
+ }
152
+ var import_superjson, MAX_SERIALIZED_BYTES, MAX_SAFE_DEPTH;
153
+ var init_serialize = __esm({
154
+ "src/serialize.ts"() {
155
+ "use strict";
156
+ import_superjson = __toESM(require("superjson"), 1);
157
+ MAX_SERIALIZED_BYTES = 512e3;
158
+ MAX_SAFE_DEPTH = 6;
159
+ }
160
+ });
161
+
48
162
  // src/asyncStorage.ts
49
163
  function registerAsyncLocalStorageClass(cls) {
50
164
  if (!AsyncLocalStorageClass) {
@@ -106,65 +220,6 @@ var init_replayContext = __esm({
106
220
  }
107
221
  });
108
222
 
109
- // src/serialize.ts
110
- function describeValue(value) {
111
- try {
112
- const ctorName = value?.constructor?.name;
113
- if (ctorName && ctorName !== "Object") {
114
- return ctorName;
115
- }
116
- } catch {
117
- }
118
- return typeof value;
119
- }
120
- function unserializableStub(value, reason) {
121
- let summary;
122
- try {
123
- summary = `<unserializable: ${describeValue(value)} (${reason})>`;
124
- } catch {
125
- summary = `<unserializable (${reason})>`;
126
- }
127
- return { json: summary };
128
- }
129
- function serializeValue(value) {
130
- try {
131
- const { json, meta } = import_superjson.default.serialize(value);
132
- let size;
133
- try {
134
- size = JSON.stringify(json).length;
135
- } catch {
136
- return unserializableStub(value, "stringify_failed_after_superjson");
137
- }
138
- if (size > MAX_SERIALIZED_BYTES) {
139
- return unserializableStub(value, `too_large_${size}_bytes`);
140
- }
141
- return meta ? { json, meta } : { json };
142
- } catch {
143
- try {
144
- return { json: JSON.parse(JSON.stringify(value)) };
145
- } catch {
146
- return unserializableStub(value, "json_stringify_failed");
147
- }
148
- }
149
- }
150
- function deserializeValue(serialized) {
151
- if (serialized.meta === void 0) {
152
- return serialized.json;
153
- }
154
- return import_superjson.default.deserialize({
155
- json: serialized.json,
156
- meta: serialized.meta
157
- });
158
- }
159
- var import_superjson, MAX_SERIALIZED_BYTES;
160
- var init_serialize = __esm({
161
- "src/serialize.ts"() {
162
- "use strict";
163
- import_superjson = __toESM(require("superjson"), 1);
164
- MAX_SERIALIZED_BYTES = 512e3;
165
- }
166
- });
167
-
168
223
  // src/replay.ts
169
224
  var replay_exports = {};
170
225
  __export(replay_exports, {
@@ -433,13 +488,93 @@ __export(index_exports, {
433
488
  module.exports = __toCommonJS(index_exports);
434
489
 
435
490
  // src/version.generated.ts
436
- var __version__ = "0.18.2";
491
+ var __version__ = "0.19.1";
437
492
 
438
493
  // src/constants.ts
439
494
  var DEFAULT_SERVICE_URL = "https://bitfab.ai";
440
495
 
441
496
  // src/http.ts
442
497
  init_errors();
498
+ function serializePayloadBody(payload) {
499
+ try {
500
+ return { body: JSON.stringify(payload), dropped: [] };
501
+ } catch {
502
+ const dropped = [];
503
+ const sanitize = (value, seen) => {
504
+ const t = typeof value;
505
+ if (value === null || t === "string" || t === "number" || t === "boolean") {
506
+ return value;
507
+ }
508
+ if (t === "bigint") {
509
+ dropped.push("BigInt");
510
+ return "<unserializable: BigInt>";
511
+ }
512
+ if (t === "function") {
513
+ const name = value.name || "Function";
514
+ dropped.push(name);
515
+ return `<unserializable: ${name}>`;
516
+ }
517
+ if (t === "symbol") {
518
+ dropped.push("Symbol");
519
+ return "<unserializable: Symbol>";
520
+ }
521
+ if (t !== "object") {
522
+ return void 0;
523
+ }
524
+ const obj = value;
525
+ const className = obj.constructor?.name || "object";
526
+ if (seen.has(obj)) {
527
+ dropped.push(className);
528
+ return `<cycle: ${className}>`;
529
+ }
530
+ seen.add(obj);
531
+ let result;
532
+ if (Array.isArray(obj)) {
533
+ result = obj.map((item) => sanitize(item, seen));
534
+ } else if (typeof obj.toJSON === "function") {
535
+ try {
536
+ result = sanitize(obj.toJSON(), seen);
537
+ } catch {
538
+ dropped.push(className);
539
+ result = `<unserializable: ${className}>`;
540
+ }
541
+ } else {
542
+ const out = {};
543
+ for (const [k, v] of Object.entries(obj)) {
544
+ out[k] = sanitize(v, seen);
545
+ }
546
+ result = out;
547
+ }
548
+ seen.delete(obj);
549
+ return result;
550
+ };
551
+ let sanitized;
552
+ try {
553
+ sanitized = sanitize(payload, /* @__PURE__ */ new WeakSet());
554
+ } catch (error) {
555
+ const message = error instanceof Error ? error.message : String(error);
556
+ return {
557
+ body: JSON.stringify({ error: `payload_serialize_failed: ${message}` }),
558
+ dropped
559
+ };
560
+ }
561
+ if (dropped.length > 0 && typeof sanitized === "object" && sanitized !== null && !Array.isArray(sanitized)) {
562
+ const obj = sanitized;
563
+ const existing = Array.isArray(obj.errors) ? obj.errors : [];
564
+ obj.errors = [
565
+ ...existing,
566
+ {
567
+ source: "sdk",
568
+ step: "json_serialize",
569
+ error: `stubbed non-serializable value(s): ${[
570
+ ...new Set(dropped)
571
+ ].join(", ")}`
572
+ }
573
+ ];
574
+ }
575
+ return { body: JSON.stringify(sanitized), dropped };
576
+ }
577
+ }
443
578
  var pendingTracePromises = /* @__PURE__ */ new Set();
444
579
  function awaitOnExit(promise) {
445
580
  pendingTracePromises.add(promise);
@@ -498,23 +633,14 @@ var HttpClient = class {
498
633
  const method = options?.method ?? "POST";
499
634
  const controller = new AbortController();
500
635
  const timeoutId = setTimeout(() => controller.abort(), timeout);
501
- let body;
502
- let serializationError;
503
- try {
504
- body = JSON.stringify(payload);
505
- } catch (error) {
506
- serializationError = error instanceof Error ? error.message : String(error);
507
- body = JSON.stringify({
508
- ...Object.fromEntries(
509
- Object.entries(payload).filter(
510
- ([, v]) => typeof v === "string" || typeof v === "number"
511
- )
512
- ),
513
- rawSpan: {},
514
- errors: [
515
- { source: "sdk", step: "json_serialize", error: serializationError }
516
- ]
517
- });
636
+ const { body, dropped } = serializePayloadBody(payload);
637
+ if (dropped.length > 0) {
638
+ try {
639
+ console.warn(
640
+ `Bitfab: request body to ${endpoint} held ${dropped.length} non-serializable value(s) (${[...new Set(dropped)].join(", ")}); they were stubbed so the span still sends, but the trace may be incomplete or not replayable. Capture a JSON-safe projection of this input to make it replayable.`
641
+ );
642
+ } catch {
643
+ }
518
644
  }
519
645
  try {
520
646
  const response = await fetch(url, {
@@ -772,56 +898,41 @@ var HttpClient = class {
772
898
  };
773
899
 
774
900
  // src/claudeAgentSdk.ts
901
+ init_serialize();
775
902
  function nowIso() {
776
903
  return (/* @__PURE__ */ new Date()).toISOString();
777
904
  }
778
- function safeSerialize(value) {
779
- if (value === null || value === void 0) {
780
- return value;
781
- }
782
- if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
783
- return value;
784
- }
785
- if (Array.isArray(value)) {
786
- return value.map(safeSerialize);
787
- }
788
- if (typeof value === "object") {
789
- if (typeof value.toJSON === "function") {
790
- return value.toJSON();
791
- }
792
- const result = {};
793
- for (const [k, v] of Object.entries(value)) {
794
- if (!k.startsWith("_")) {
795
- result[k] = safeSerialize(v);
796
- }
797
- }
798
- return result;
799
- }
800
- return String(value);
801
- }
905
+ var safeSerialize = toJsonSafe;
802
906
  function extractContentBlocks(content) {
803
907
  if (!Array.isArray(content)) {
804
908
  return [];
805
909
  }
806
910
  return content.map((block) => safeSerialize(block));
807
911
  }
912
+ function asTokenCount(val) {
913
+ return typeof val === "number" && Number.isFinite(val) ? val : null;
914
+ }
808
915
  function extractUsage(message) {
809
916
  const usageInfo = {};
810
917
  const usage = message.usage;
811
918
  if (!usage) {
812
919
  return usageInfo;
813
920
  }
814
- const mapping = {
815
- input_tokens: "inputTokens",
816
- output_tokens: "outputTokens",
817
- cache_read_input_tokens: "cacheReadTokens",
818
- cache_creation_input_tokens: "cacheCreationTokens"
819
- };
820
- for (const [srcKey, dstKey] of Object.entries(mapping)) {
821
- const val = usage[srcKey];
822
- if (val !== void 0 && val !== null) {
823
- usageInfo[dstKey] = val;
824
- }
921
+ const baseInput = asTokenCount(usage.input_tokens);
922
+ const cacheRead = asTokenCount(usage.cache_read_input_tokens);
923
+ const cacheCreation = asTokenCount(usage.cache_creation_input_tokens);
924
+ if (baseInput !== null || cacheRead !== null || cacheCreation !== null) {
925
+ usageInfo.inputTokens = (baseInput ?? 0) + (cacheRead ?? 0) + (cacheCreation ?? 0);
926
+ }
927
+ const output = asTokenCount(usage.output_tokens);
928
+ if (output !== null) {
929
+ usageInfo.outputTokens = output;
930
+ }
931
+ if (cacheRead !== null) {
932
+ usageInfo.cacheReadTokens = cacheRead;
933
+ }
934
+ if (cacheCreation !== null) {
935
+ usageInfo.cacheCreationTokens = cacheCreation;
825
936
  }
826
937
  return usageInfo;
827
938
  }
@@ -1554,6 +1665,7 @@ function buildSnapshotRef(config, sdkWallClockBeforeFn) {
1554
1665
  }
1555
1666
 
1556
1667
  // src/langgraph.ts
1668
+ init_serialize();
1557
1669
  var LANGSMITH_HIDDEN_TAG = "langsmith:hidden";
1558
1670
  var LANGGRAPH_METADATA_KEYS = [
1559
1671
  "langgraph_step",
@@ -1565,56 +1677,7 @@ var LANGGRAPH_METADATA_KEYS = [
1565
1677
  function nowIso2() {
1566
1678
  return (/* @__PURE__ */ new Date()).toISOString();
1567
1679
  }
1568
- var MAX_SERIALIZE_DEPTH = 6;
1569
- function safeSerialize2(value) {
1570
- return safeSerializeInner(value, 0, /* @__PURE__ */ new WeakSet());
1571
- }
1572
- function safeSerializeInner(value, depth, seen) {
1573
- if (value === null || value === void 0) {
1574
- return value;
1575
- }
1576
- if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
1577
- return value;
1578
- }
1579
- const className = value?.constructor?.name ?? typeof value;
1580
- if (depth > MAX_SERIALIZE_DEPTH) {
1581
- return `<${className}>`;
1582
- }
1583
- if (typeof value === "object") {
1584
- if (seen.has(value)) {
1585
- return `<cycle ${className}>`;
1586
- }
1587
- seen.add(value);
1588
- }
1589
- if (Array.isArray(value)) {
1590
- return value.map((item) => safeSerializeInner(item, depth + 1, seen));
1591
- }
1592
- if (typeof value === "object") {
1593
- if (typeof value.toJSON === "function") {
1594
- try {
1595
- return value.toJSON();
1596
- } catch {
1597
- return `<${className}>`;
1598
- }
1599
- }
1600
- try {
1601
- const result = {};
1602
- for (const [k, v] of Object.entries(value)) {
1603
- if (!k.startsWith("_")) {
1604
- result[k] = safeSerializeInner(v, depth + 1, seen);
1605
- }
1606
- }
1607
- return result;
1608
- } catch {
1609
- return `<${className}>`;
1610
- }
1611
- }
1612
- try {
1613
- return String(value);
1614
- } catch {
1615
- return `<${className}>`;
1616
- }
1617
- }
1680
+ var safeSerialize2 = toJsonSafe;
1618
1681
  function convertMessage(message) {
1619
1682
  if (typeof message !== "object" || message === null) {
1620
1683
  return { role: "unknown", content: String(message) };
@@ -1663,7 +1726,7 @@ function extractModelName(serialized, metadata) {
1663
1726
  }
1664
1727
  return void 0;
1665
1728
  }
1666
- function asTokenCount(value) {
1729
+ function asTokenCount2(value) {
1667
1730
  return typeof value === "number" && Number.isFinite(value) ? value : null;
1668
1731
  }
1669
1732
  function normalizeTokenUsage(raw) {
@@ -1672,10 +1735,10 @@ function normalizeTokenUsage(raw) {
1672
1735
  }
1673
1736
  const u = raw;
1674
1737
  if ("cache_read_input_tokens" in u || "cache_creation_input_tokens" in u) {
1675
- const cacheRead = asTokenCount(u.cache_read_input_tokens);
1676
- const cacheCreation = asTokenCount(u.cache_creation_input_tokens);
1677
- const baseInput = asTokenCount(u.input_tokens);
1678
- const outputTokens = asTokenCount(u.output_tokens);
1738
+ const cacheRead = asTokenCount2(u.cache_read_input_tokens);
1739
+ const cacheCreation = asTokenCount2(u.cache_creation_input_tokens);
1740
+ const baseInput = asTokenCount2(u.input_tokens);
1741
+ const outputTokens = asTokenCount2(u.output_tokens);
1679
1742
  if (cacheRead === null && cacheCreation === null && baseInput === null && outputTokens === null) {
1680
1743
  return null;
1681
1744
  }
@@ -1690,25 +1753,25 @@ function normalizeTokenUsage(raw) {
1690
1753
  if ("prompt_tokens" in u || "completion_tokens" in u || "promptTokens" in u || "completionTokens" in u) {
1691
1754
  const promptDetails = u.prompt_tokens_details ?? {};
1692
1755
  return withAnyTokenCount({
1693
- inputTokens: asTokenCount(u.prompt_tokens) ?? asTokenCount(u.promptTokens),
1694
- outputTokens: asTokenCount(u.completion_tokens) ?? asTokenCount(u.completionTokens),
1695
- totalTokens: asTokenCount(u.total_tokens) ?? asTokenCount(u.totalTokens),
1696
- cachedInputTokens: asTokenCount(promptDetails.cached_tokens)
1756
+ inputTokens: asTokenCount2(u.prompt_tokens) ?? asTokenCount2(u.promptTokens),
1757
+ outputTokens: asTokenCount2(u.completion_tokens) ?? asTokenCount2(u.completionTokens),
1758
+ totalTokens: asTokenCount2(u.total_tokens) ?? asTokenCount2(u.totalTokens),
1759
+ cachedInputTokens: asTokenCount2(promptDetails.cached_tokens)
1697
1760
  });
1698
1761
  }
1699
1762
  if ("prompt_token_count" in u || "candidates_token_count" in u) {
1700
1763
  return withAnyTokenCount({
1701
- inputTokens: asTokenCount(u.prompt_token_count),
1702
- outputTokens: asTokenCount(u.candidates_token_count),
1703
- totalTokens: asTokenCount(u.total_token_count),
1704
- cachedInputTokens: asTokenCount(u.cached_content_token_count)
1764
+ inputTokens: asTokenCount2(u.prompt_token_count),
1765
+ outputTokens: asTokenCount2(u.candidates_token_count),
1766
+ totalTokens: asTokenCount2(u.total_token_count),
1767
+ cachedInputTokens: asTokenCount2(u.cached_content_token_count)
1705
1768
  });
1706
1769
  }
1707
1770
  if ("input_tokens" in u || "output_tokens" in u) {
1708
1771
  const inputDetails = u.input_token_details ?? {};
1709
- const inputTokens = asTokenCount(u.input_tokens);
1710
- const outputTokens = asTokenCount(u.output_tokens);
1711
- let totalTokens = asTokenCount(u.total_tokens);
1772
+ const inputTokens = asTokenCount2(u.input_tokens);
1773
+ const outputTokens = asTokenCount2(u.output_tokens);
1774
+ let totalTokens = asTokenCount2(u.total_tokens);
1712
1775
  if (totalTokens === null && inputTokens !== null && outputTokens !== null) {
1713
1776
  totalTokens = inputTokens + outputTokens;
1714
1777
  }
@@ -1716,7 +1779,7 @@ function normalizeTokenUsage(raw) {
1716
1779
  inputTokens,
1717
1780
  outputTokens,
1718
1781
  totalTokens,
1719
- cachedInputTokens: asTokenCount(inputDetails.cache_read)
1782
+ cachedInputTokens: asTokenCount2(inputDetails.cache_read)
1720
1783
  });
1721
1784
  }
1722
1785
  return null;