@bitfab/sdk 0.27.1 → 0.28.0
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/{chunk-H5QQ54UI.js → chunk-RS5Z6YXY.js} +148 -40
- package/dist/chunk-RS5Z6YXY.js.map +1 -0
- package/dist/index.cjs +147 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +149 -90
- package/dist/index.d.ts +149 -90
- package/dist/index.js +1 -1
- package/dist/node.cjs +147 -39
- package/dist/node.cjs.map +1 -1
- package/dist/node.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-H5QQ54UI.js.map +0 -1
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
} from "./chunk-MD4XQGAF.js";
|
|
14
14
|
|
|
15
15
|
// src/version.generated.ts
|
|
16
|
-
var __version__ = "0.
|
|
16
|
+
var __version__ = "0.28.0";
|
|
17
17
|
|
|
18
18
|
// src/constants.ts
|
|
19
19
|
var DEFAULT_SERVICE_URL = "https://bitfab.ai";
|
|
@@ -168,6 +168,13 @@ var HttpClient = class {
|
|
|
168
168
|
this.serviceUrl = config.serviceUrl;
|
|
169
169
|
this.timeout = config.timeout ?? 12e4;
|
|
170
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Resolve the API key at the moment it is needed (request time), invoking
|
|
173
|
+
* the function form if one was supplied. Never read at construction.
|
|
174
|
+
*/
|
|
175
|
+
resolveApiKey() {
|
|
176
|
+
return typeof this.apiKey === "function" ? this.apiKey() : this.apiKey;
|
|
177
|
+
}
|
|
171
178
|
/**
|
|
172
179
|
* Make an HTTP request to the Bitfab API. Defaults to POST; pass
|
|
173
180
|
* `options.method` to use a different verb (e.g. "PATCH").
|
|
@@ -198,7 +205,7 @@ var HttpClient = class {
|
|
|
198
205
|
method,
|
|
199
206
|
headers: {
|
|
200
207
|
"Content-Type": "application/json",
|
|
201
|
-
Authorization: `Bearer ${this.
|
|
208
|
+
Authorization: `Bearer ${this.resolveApiKey() ?? ""}`
|
|
202
209
|
},
|
|
203
210
|
body,
|
|
204
211
|
signal: controller.signal
|
|
@@ -359,7 +366,7 @@ var HttpClient = class {
|
|
|
359
366
|
try {
|
|
360
367
|
const response = await fetch(url, {
|
|
361
368
|
method: "GET",
|
|
362
|
-
headers: { Authorization: `Bearer ${this.
|
|
369
|
+
headers: { Authorization: `Bearer ${this.resolveApiKey() ?? ""}` },
|
|
363
370
|
signal: controller.signal
|
|
364
371
|
});
|
|
365
372
|
if (!response.ok) {
|
|
@@ -395,7 +402,7 @@ var HttpClient = class {
|
|
|
395
402
|
try {
|
|
396
403
|
const response = await fetch(url, {
|
|
397
404
|
method: "GET",
|
|
398
|
-
headers: { Authorization: `Bearer ${this.
|
|
405
|
+
headers: { Authorization: `Bearer ${this.resolveApiKey() ?? ""}` },
|
|
399
406
|
signal: controller.signal
|
|
400
407
|
});
|
|
401
408
|
if (!response.ok) {
|
|
@@ -1359,6 +1366,7 @@ function buildSnapshotRef(config, sdkWallClockBeforeFn) {
|
|
|
1359
1366
|
|
|
1360
1367
|
// src/langgraph.ts
|
|
1361
1368
|
var LANGSMITH_HIDDEN_TAG = "langsmith:hidden";
|
|
1369
|
+
var CHAIN_RUN_TYPES = /* @__PURE__ */ new Set(["chain", "parser", "prompt"]);
|
|
1362
1370
|
var LANGGRAPH_METADATA_KEYS = [
|
|
1363
1371
|
"langgraph_step",
|
|
1364
1372
|
"langgraph_node",
|
|
@@ -1369,6 +1377,18 @@ var LANGGRAPH_METADATA_KEYS = [
|
|
|
1369
1377
|
function nowIso2() {
|
|
1370
1378
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
1371
1379
|
}
|
|
1380
|
+
function normalizeChainStartArgs(parentRunIdOrRunType, runTypeOrRunName, runNameOrParentRunId) {
|
|
1381
|
+
if (parentRunIdOrRunType && CHAIN_RUN_TYPES.has(parentRunIdOrRunType)) {
|
|
1382
|
+
return {
|
|
1383
|
+
parentRunId: runNameOrParentRunId,
|
|
1384
|
+
runName: runTypeOrRunName
|
|
1385
|
+
};
|
|
1386
|
+
}
|
|
1387
|
+
return {
|
|
1388
|
+
parentRunId: parentRunIdOrRunType,
|
|
1389
|
+
runName: runNameOrParentRunId
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1372
1392
|
function convertMessage(message) {
|
|
1373
1393
|
if (typeof message !== "object" || message === null) {
|
|
1374
1394
|
return { role: "unknown", content: String(message) };
|
|
@@ -1580,6 +1600,7 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
1580
1600
|
const willHide = tags?.includes(LANGSMITH_HIDDEN_TAG) === true;
|
|
1581
1601
|
let invocation;
|
|
1582
1602
|
let effectiveParentId;
|
|
1603
|
+
let isRootInvocation = false;
|
|
1583
1604
|
if (parentSpan) {
|
|
1584
1605
|
const existing = this.invocations.get(parentSpan.rootRunId);
|
|
1585
1606
|
if (existing) {
|
|
@@ -1610,6 +1631,7 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
1610
1631
|
};
|
|
1611
1632
|
this.invocations.set(runId, invocation);
|
|
1612
1633
|
effectiveParentId = activeContext?.spanId ?? null;
|
|
1634
|
+
isRootInvocation = true;
|
|
1613
1635
|
}
|
|
1614
1636
|
const lgMetadata = extractLangGraphMetadata(metadata);
|
|
1615
1637
|
const contexts = Object.keys(lgMetadata).length > 0 ? [lgMetadata] : [];
|
|
@@ -1632,6 +1654,9 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
1632
1654
|
spanInfo.hidden = true;
|
|
1633
1655
|
}
|
|
1634
1656
|
this.runToSpan.set(runId, spanInfo);
|
|
1657
|
+
if (isRootInvocation) {
|
|
1658
|
+
this.sendTraceStart(spanInfo);
|
|
1659
|
+
}
|
|
1635
1660
|
return spanInfo;
|
|
1636
1661
|
}
|
|
1637
1662
|
completeSpan(runId, output, error, extraContexts) {
|
|
@@ -1722,11 +1747,35 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
1722
1747
|
} catch {
|
|
1723
1748
|
}
|
|
1724
1749
|
}
|
|
1750
|
+
sendTraceStart(rootSpan) {
|
|
1751
|
+
const traceData = {
|
|
1752
|
+
type: "sdk-function",
|
|
1753
|
+
source: "typescript-sdk-langgraph",
|
|
1754
|
+
traceFunctionKey: this.traceFunctionKey,
|
|
1755
|
+
externalTrace: {
|
|
1756
|
+
id: rootSpan.traceId,
|
|
1757
|
+
started_at: rootSpan.startedAt,
|
|
1758
|
+
workflow_name: this.traceFunctionKey
|
|
1759
|
+
},
|
|
1760
|
+
completed: false
|
|
1761
|
+
};
|
|
1762
|
+
const finalized = finalizeTracePayload(traceData);
|
|
1763
|
+
try {
|
|
1764
|
+
this.httpClient.sendExternalTrace(finalized);
|
|
1765
|
+
} catch {
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1725
1768
|
// ── chain callbacks (graph nodes) ─────────────────────────────
|
|
1726
|
-
async handleChainStart(chain, inputs, runId,
|
|
1769
|
+
async handleChainStart(chain, inputs, runId, parentRunIdOrRunType, tags, metadata, runTypeOrRunName, runNameOrParentRunId) {
|
|
1727
1770
|
try {
|
|
1728
|
-
const
|
|
1729
|
-
|
|
1771
|
+
const { parentRunId, runName } = normalizeChainStartArgs(
|
|
1772
|
+
parentRunIdOrRunType,
|
|
1773
|
+
runTypeOrRunName,
|
|
1774
|
+
runNameOrParentRunId
|
|
1775
|
+
);
|
|
1776
|
+
const serialized = chain ?? {};
|
|
1777
|
+
const idArr = serialized.id;
|
|
1778
|
+
const name = runName ?? serialized.name ?? idArr?.[idArr.length - 1] ?? "chain";
|
|
1730
1779
|
this.startSpan(
|
|
1731
1780
|
runId,
|
|
1732
1781
|
parentRunId,
|
|
@@ -1761,11 +1810,12 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
1761
1810
|
}
|
|
1762
1811
|
}
|
|
1763
1812
|
// ── LLM callbacks ─────────────────────────────────────────────
|
|
1764
|
-
async handleChatModelStart(llm, messages, runId, parentRunId, _extraParams, tags, metadata) {
|
|
1813
|
+
async handleChatModelStart(llm, messages, runId, parentRunId, _extraParams, tags, metadata, runName) {
|
|
1765
1814
|
try {
|
|
1766
|
-
const
|
|
1767
|
-
const
|
|
1768
|
-
const
|
|
1815
|
+
const serialized = llm ?? {};
|
|
1816
|
+
const model = extractModelName(serialized, metadata);
|
|
1817
|
+
const idArr = serialized.id;
|
|
1818
|
+
const name = runName ?? model ?? idArr?.[idArr.length - 1] ?? "llm";
|
|
1769
1819
|
const converted = messages.map((batch) => batch.map(convertMessage));
|
|
1770
1820
|
const spanInfo = this.startSpan(
|
|
1771
1821
|
runId,
|
|
@@ -1780,11 +1830,12 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
1780
1830
|
} catch {
|
|
1781
1831
|
}
|
|
1782
1832
|
}
|
|
1783
|
-
async handleLLMStart(llm, prompts, runId, parentRunId, _extraParams, tags, metadata) {
|
|
1833
|
+
async handleLLMStart(llm, prompts, runId, parentRunId, _extraParams, tags, metadata, runName) {
|
|
1784
1834
|
try {
|
|
1785
|
-
const
|
|
1786
|
-
const
|
|
1787
|
-
const
|
|
1835
|
+
const serialized = llm ?? {};
|
|
1836
|
+
const model = extractModelName(serialized, metadata);
|
|
1837
|
+
const idArr = serialized.id;
|
|
1838
|
+
const name = runName ?? model ?? idArr?.[idArr.length - 1] ?? "llm";
|
|
1788
1839
|
const spanInfo = this.startSpan(
|
|
1789
1840
|
runId,
|
|
1790
1841
|
parentRunId,
|
|
@@ -1837,9 +1888,10 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
1837
1888
|
async handleLLMNewToken() {
|
|
1838
1889
|
}
|
|
1839
1890
|
// ── tool callbacks ────────────────────────────────────────────
|
|
1840
|
-
async handleToolStart(tool, input, runId, parentRunId, tags, metadata) {
|
|
1891
|
+
async handleToolStart(tool, input, runId, parentRunId, tags, metadata, runName) {
|
|
1841
1892
|
try {
|
|
1842
|
-
const
|
|
1893
|
+
const serialized = tool ?? {};
|
|
1894
|
+
const name = runName ?? serialized.name ?? "tool";
|
|
1843
1895
|
this.startSpan(
|
|
1844
1896
|
runId,
|
|
1845
1897
|
parentRunId,
|
|
@@ -1869,9 +1921,10 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
1869
1921
|
}
|
|
1870
1922
|
}
|
|
1871
1923
|
// ── retriever callbacks ───────────────────────────────────────
|
|
1872
|
-
async handleRetrieverStart(retriever, query, runId, parentRunId, tags, metadata) {
|
|
1924
|
+
async handleRetrieverStart(retriever, query, runId, parentRunId, tags, metadata, runName) {
|
|
1873
1925
|
try {
|
|
1874
|
-
const
|
|
1926
|
+
const serialized = retriever ?? {};
|
|
1927
|
+
const name = runName ?? serialized.name ?? "retriever";
|
|
1875
1928
|
this.startSpan(
|
|
1876
1929
|
runId,
|
|
1877
1930
|
parentRunId,
|
|
@@ -2660,6 +2713,12 @@ function getCurrentTrace() {
|
|
|
2660
2713
|
}
|
|
2661
2714
|
};
|
|
2662
2715
|
}
|
|
2716
|
+
function readEnv(name) {
|
|
2717
|
+
if (typeof process !== "undefined" && process.env) {
|
|
2718
|
+
return process.env[name];
|
|
2719
|
+
}
|
|
2720
|
+
return void 0;
|
|
2721
|
+
}
|
|
2663
2722
|
var Bitfab = class {
|
|
2664
2723
|
/**
|
|
2665
2724
|
* Initialize the Bitfab client.
|
|
@@ -2667,30 +2726,75 @@ var Bitfab = class {
|
|
|
2667
2726
|
* @param config - Configuration options for the client
|
|
2668
2727
|
*/
|
|
2669
2728
|
constructor(config) {
|
|
2670
|
-
|
|
2729
|
+
/** Gate the empty-key warning to fire at most once. */
|
|
2730
|
+
this.apiKeyWarned = false;
|
|
2731
|
+
this.apiKeyConfig = config.apiKey;
|
|
2671
2732
|
this.serviceUrl = config.serviceUrl ?? DEFAULT_SERVICE_URL;
|
|
2672
2733
|
this.timeout = config.timeout ?? 12e4;
|
|
2673
2734
|
this.envVars = config.envVars ?? {};
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
console.warn(
|
|
2677
|
-
"Bitfab: apiKey is empty \u2014 tracing is disabled. Provide a valid API key to enable tracing."
|
|
2678
|
-
);
|
|
2679
|
-
this.enabled = false;
|
|
2680
|
-
} else {
|
|
2681
|
-
this.enabled = enabled;
|
|
2682
|
-
}
|
|
2735
|
+
this.explicitlyEnabled = config.enabled ?? true;
|
|
2736
|
+
this.strict = config.strict ?? false;
|
|
2683
2737
|
this.bamlClient = config.bamlClient ?? null;
|
|
2684
2738
|
if (config.dbSnapshot) {
|
|
2685
2739
|
validateDbSnapshotConfig(config.dbSnapshot);
|
|
2686
2740
|
}
|
|
2687
2741
|
this.dbSnapshot = config.dbSnapshot;
|
|
2688
2742
|
this.httpClient = new HttpClient({
|
|
2689
|
-
apiKey: this.
|
|
2743
|
+
apiKey: () => this.resolveApiKey(),
|
|
2690
2744
|
serviceUrl: this.serviceUrl,
|
|
2691
2745
|
timeout: this.timeout
|
|
2692
2746
|
});
|
|
2693
2747
|
}
|
|
2748
|
+
/**
|
|
2749
|
+
* Resolve the API key lazily, the first time a span actually needs it.
|
|
2750
|
+
*
|
|
2751
|
+
* The key is intentionally NOT read at construction. In ESM, a shim that
|
|
2752
|
+
* does `new Bitfab({ apiKey: process.env.BITFAB_API_KEY })` is hoisted and
|
|
2753
|
+
* evaluated before the importing script's body runs `dotenv.config()`, so
|
|
2754
|
+
* the key would be empty at construction even though it is set moments
|
|
2755
|
+
* later. Resolving here (at first `withSpan` call / first request) reads
|
|
2756
|
+
* the key after env loading has run.
|
|
2757
|
+
*
|
|
2758
|
+
* Resolution order: the configured value (string, or function called each
|
|
2759
|
+
* time it is still unresolved), then a fallback read of `BITFAB_API_KEY`
|
|
2760
|
+
* from the environment. Once a non-empty key is found it is cached, so an
|
|
2761
|
+
* early resolve that found nothing never poisons a later one.
|
|
2762
|
+
*/
|
|
2763
|
+
resolveApiKey() {
|
|
2764
|
+
if (this.resolvedApiKey !== void 0) {
|
|
2765
|
+
return this.resolvedApiKey;
|
|
2766
|
+
}
|
|
2767
|
+
const fromConfig = typeof this.apiKeyConfig === "function" ? this.apiKeyConfig() : this.apiKeyConfig;
|
|
2768
|
+
const candidate = fromConfig && fromConfig.trim() !== "" ? fromConfig : readEnv("BITFAB_API_KEY");
|
|
2769
|
+
const key = candidate && candidate.trim() !== "" ? candidate : void 0;
|
|
2770
|
+
if (key) {
|
|
2771
|
+
this.resolvedApiKey = key;
|
|
2772
|
+
return key;
|
|
2773
|
+
}
|
|
2774
|
+
if (this.strict) {
|
|
2775
|
+
throw new BitfabError(
|
|
2776
|
+
"Bitfab: no API key resolved. Set BITFAB_API_KEY or pass apiKey to new Bitfab(). If a script loads env with dotenv, load it before the module that constructs the client is imported (e.g. `node --env-file=.env script.ts`), or pass `apiKey: () => process.env.BITFAB_API_KEY`."
|
|
2777
|
+
);
|
|
2778
|
+
}
|
|
2779
|
+
if (this.explicitlyEnabled && !this.apiKeyWarned) {
|
|
2780
|
+
this.apiKeyWarned = true;
|
|
2781
|
+
console.warn(
|
|
2782
|
+
"Bitfab: apiKey is empty \u2014 tracing is disabled. Provide a valid API key to enable tracing."
|
|
2783
|
+
);
|
|
2784
|
+
}
|
|
2785
|
+
return void 0;
|
|
2786
|
+
}
|
|
2787
|
+
/**
|
|
2788
|
+
* Whether tracing should run, decided lazily at call time (not frozen at
|
|
2789
|
+
* construction). An explicit `enabled: false` short-circuits without ever
|
|
2790
|
+
* touching the key.
|
|
2791
|
+
*/
|
|
2792
|
+
isTracingEnabled() {
|
|
2793
|
+
if (!this.explicitlyEnabled) {
|
|
2794
|
+
return false;
|
|
2795
|
+
}
|
|
2796
|
+
return this.resolveApiKey() !== void 0;
|
|
2797
|
+
}
|
|
2694
2798
|
/**
|
|
2695
2799
|
* Fetch the function with its current version and BAML prompt from the server.
|
|
2696
2800
|
*
|
|
@@ -2783,7 +2887,9 @@ var Bitfab = class {
|
|
|
2783
2887
|
*/
|
|
2784
2888
|
getOpenAiTracingProcessor() {
|
|
2785
2889
|
return new BitfabOpenAITracingProcessor({
|
|
2786
|
-
|
|
2890
|
+
// Resolved at getter-call time (framework handlers are set up after env
|
|
2891
|
+
// loads); the withSpan path stays lazy via the constructor HttpClient thunk.
|
|
2892
|
+
apiKey: this.resolveApiKey(),
|
|
2787
2893
|
serviceUrl: this.serviceUrl,
|
|
2788
2894
|
getActiveSpanContext: () => {
|
|
2789
2895
|
const stack = getSpanStack();
|
|
@@ -2842,7 +2948,7 @@ var Bitfab = class {
|
|
|
2842
2948
|
*/
|
|
2843
2949
|
getLangGraphCallbackHandler(traceFunctionKey) {
|
|
2844
2950
|
return new BitfabLangGraphCallbackHandler({
|
|
2845
|
-
apiKey: this.
|
|
2951
|
+
apiKey: this.resolveApiKey(),
|
|
2846
2952
|
traceFunctionKey,
|
|
2847
2953
|
serviceUrl: this.serviceUrl,
|
|
2848
2954
|
getActiveSpanContext: () => {
|
|
@@ -2894,7 +3000,7 @@ var Bitfab = class {
|
|
|
2894
3000
|
*/
|
|
2895
3001
|
getClaudeAgentHandler(traceFunctionKey) {
|
|
2896
3002
|
return new BitfabClaudeAgentHandler({
|
|
2897
|
-
apiKey: this.
|
|
3003
|
+
apiKey: this.resolveApiKey(),
|
|
2898
3004
|
traceFunctionKey,
|
|
2899
3005
|
serviceUrl: this.serviceUrl,
|
|
2900
3006
|
getActiveSpanContext: () => {
|
|
@@ -3066,9 +3172,8 @@ var Bitfab = class {
|
|
|
3066
3172
|
* @returns A wrapped function with the same signature that creates spans for inputs and outputs
|
|
3067
3173
|
*/
|
|
3068
3174
|
withSpan(traceFunctionKey, optionsOrFn, maybeFn) {
|
|
3069
|
-
if (!this.
|
|
3070
|
-
|
|
3071
|
-
return fn2;
|
|
3175
|
+
if (!this.explicitlyEnabled) {
|
|
3176
|
+
return typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
|
|
3072
3177
|
}
|
|
3073
3178
|
const options = typeof optionsOrFn === "function" ? {} : optionsOrFn;
|
|
3074
3179
|
const fn = typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
|
|
@@ -3083,6 +3188,9 @@ var Bitfab = class {
|
|
|
3083
3188
|
}
|
|
3084
3189
|
})();
|
|
3085
3190
|
const wrappedFn = function(...args) {
|
|
3191
|
+
if (!self.isTracingEnabled()) {
|
|
3192
|
+
return fn.apply(this, args);
|
|
3193
|
+
}
|
|
3086
3194
|
if (!asyncLocalStorage && !isAsyncStorageInitDone()) {
|
|
3087
3195
|
return asyncLocalStorageReady.then(
|
|
3088
3196
|
() => wrappedFn.apply(this, args)
|
|
@@ -3343,7 +3451,7 @@ var Bitfab = class {
|
|
|
3343
3451
|
return {
|
|
3344
3452
|
traceId,
|
|
3345
3453
|
addContext: (context) => {
|
|
3346
|
-
if (!this.
|
|
3454
|
+
if (!this.isTracingEnabled()) {
|
|
3347
3455
|
return Promise.resolve();
|
|
3348
3456
|
}
|
|
3349
3457
|
if (typeof context !== "object" || context === null) {
|
|
@@ -3354,7 +3462,7 @@ var Bitfab = class {
|
|
|
3354
3462
|
});
|
|
3355
3463
|
},
|
|
3356
3464
|
setMetadata: (metadata) => {
|
|
3357
|
-
if (!this.
|
|
3465
|
+
if (!this.isTracingEnabled()) {
|
|
3358
3466
|
return Promise.resolve();
|
|
3359
3467
|
}
|
|
3360
3468
|
if (typeof metadata !== "object" || metadata === null) {
|
|
@@ -3363,7 +3471,7 @@ var Bitfab = class {
|
|
|
3363
3471
|
return this.httpClient.patchTrace(traceId, { mergeMetadata: metadata });
|
|
3364
3472
|
},
|
|
3365
3473
|
setSessionId: (sessionId) => {
|
|
3366
|
-
if (!this.
|
|
3474
|
+
if (!this.isTracingEnabled()) {
|
|
3367
3475
|
return Promise.resolve();
|
|
3368
3476
|
}
|
|
3369
3477
|
if (typeof sessionId !== "string" || sessionId.length === 0) {
|
|
@@ -3752,4 +3860,4 @@ export {
|
|
|
3752
3860
|
BitfabFunction,
|
|
3753
3861
|
finalizers
|
|
3754
3862
|
};
|
|
3755
|
-
//# sourceMappingURL=chunk-
|
|
3863
|
+
//# sourceMappingURL=chunk-RS5Z6YXY.js.map
|