@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
package/dist/index.js
CHANGED
package/dist/node.cjs
CHANGED
|
@@ -650,7 +650,7 @@ registerAsyncLocalStorageClass(
|
|
|
650
650
|
);
|
|
651
651
|
|
|
652
652
|
// src/version.generated.ts
|
|
653
|
-
var __version__ = "0.
|
|
653
|
+
var __version__ = "0.28.0";
|
|
654
654
|
|
|
655
655
|
// src/constants.ts
|
|
656
656
|
var DEFAULT_SERVICE_URL = "https://bitfab.ai";
|
|
@@ -809,6 +809,13 @@ var HttpClient = class {
|
|
|
809
809
|
this.serviceUrl = config.serviceUrl;
|
|
810
810
|
this.timeout = config.timeout ?? 12e4;
|
|
811
811
|
}
|
|
812
|
+
/**
|
|
813
|
+
* Resolve the API key at the moment it is needed (request time), invoking
|
|
814
|
+
* the function form if one was supplied. Never read at construction.
|
|
815
|
+
*/
|
|
816
|
+
resolveApiKey() {
|
|
817
|
+
return typeof this.apiKey === "function" ? this.apiKey() : this.apiKey;
|
|
818
|
+
}
|
|
812
819
|
/**
|
|
813
820
|
* Make an HTTP request to the Bitfab API. Defaults to POST; pass
|
|
814
821
|
* `options.method` to use a different verb (e.g. "PATCH").
|
|
@@ -839,7 +846,7 @@ var HttpClient = class {
|
|
|
839
846
|
method,
|
|
840
847
|
headers: {
|
|
841
848
|
"Content-Type": "application/json",
|
|
842
|
-
Authorization: `Bearer ${this.
|
|
849
|
+
Authorization: `Bearer ${this.resolveApiKey() ?? ""}`
|
|
843
850
|
},
|
|
844
851
|
body,
|
|
845
852
|
signal: controller.signal
|
|
@@ -1000,7 +1007,7 @@ var HttpClient = class {
|
|
|
1000
1007
|
try {
|
|
1001
1008
|
const response = await fetch(url, {
|
|
1002
1009
|
method: "GET",
|
|
1003
|
-
headers: { Authorization: `Bearer ${this.
|
|
1010
|
+
headers: { Authorization: `Bearer ${this.resolveApiKey() ?? ""}` },
|
|
1004
1011
|
signal: controller.signal
|
|
1005
1012
|
});
|
|
1006
1013
|
if (!response.ok) {
|
|
@@ -1036,7 +1043,7 @@ var HttpClient = class {
|
|
|
1036
1043
|
try {
|
|
1037
1044
|
const response = await fetch(url, {
|
|
1038
1045
|
method: "GET",
|
|
1039
|
-
headers: { Authorization: `Bearer ${this.
|
|
1046
|
+
headers: { Authorization: `Bearer ${this.resolveApiKey() ?? ""}` },
|
|
1040
1047
|
signal: controller.signal
|
|
1041
1048
|
});
|
|
1042
1049
|
if (!response.ok) {
|
|
@@ -2010,6 +2017,7 @@ function buildSnapshotRef(config, sdkWallClockBeforeFn) {
|
|
|
2010
2017
|
init_randomUuid();
|
|
2011
2018
|
init_serialize();
|
|
2012
2019
|
var LANGSMITH_HIDDEN_TAG = "langsmith:hidden";
|
|
2020
|
+
var CHAIN_RUN_TYPES = /* @__PURE__ */ new Set(["chain", "parser", "prompt"]);
|
|
2013
2021
|
var LANGGRAPH_METADATA_KEYS = [
|
|
2014
2022
|
"langgraph_step",
|
|
2015
2023
|
"langgraph_node",
|
|
@@ -2020,6 +2028,18 @@ var LANGGRAPH_METADATA_KEYS = [
|
|
|
2020
2028
|
function nowIso2() {
|
|
2021
2029
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
2022
2030
|
}
|
|
2031
|
+
function normalizeChainStartArgs(parentRunIdOrRunType, runTypeOrRunName, runNameOrParentRunId) {
|
|
2032
|
+
if (parentRunIdOrRunType && CHAIN_RUN_TYPES.has(parentRunIdOrRunType)) {
|
|
2033
|
+
return {
|
|
2034
|
+
parentRunId: runNameOrParentRunId,
|
|
2035
|
+
runName: runTypeOrRunName
|
|
2036
|
+
};
|
|
2037
|
+
}
|
|
2038
|
+
return {
|
|
2039
|
+
parentRunId: parentRunIdOrRunType,
|
|
2040
|
+
runName: runNameOrParentRunId
|
|
2041
|
+
};
|
|
2042
|
+
}
|
|
2023
2043
|
function convertMessage(message) {
|
|
2024
2044
|
if (typeof message !== "object" || message === null) {
|
|
2025
2045
|
return { role: "unknown", content: String(message) };
|
|
@@ -2231,6 +2251,7 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2231
2251
|
const willHide = tags?.includes(LANGSMITH_HIDDEN_TAG) === true;
|
|
2232
2252
|
let invocation;
|
|
2233
2253
|
let effectiveParentId;
|
|
2254
|
+
let isRootInvocation = false;
|
|
2234
2255
|
if (parentSpan) {
|
|
2235
2256
|
const existing = this.invocations.get(parentSpan.rootRunId);
|
|
2236
2257
|
if (existing) {
|
|
@@ -2261,6 +2282,7 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2261
2282
|
};
|
|
2262
2283
|
this.invocations.set(runId, invocation);
|
|
2263
2284
|
effectiveParentId = activeContext?.spanId ?? null;
|
|
2285
|
+
isRootInvocation = true;
|
|
2264
2286
|
}
|
|
2265
2287
|
const lgMetadata = extractLangGraphMetadata(metadata);
|
|
2266
2288
|
const contexts = Object.keys(lgMetadata).length > 0 ? [lgMetadata] : [];
|
|
@@ -2283,6 +2305,9 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2283
2305
|
spanInfo.hidden = true;
|
|
2284
2306
|
}
|
|
2285
2307
|
this.runToSpan.set(runId, spanInfo);
|
|
2308
|
+
if (isRootInvocation) {
|
|
2309
|
+
this.sendTraceStart(spanInfo);
|
|
2310
|
+
}
|
|
2286
2311
|
return spanInfo;
|
|
2287
2312
|
}
|
|
2288
2313
|
completeSpan(runId, output, error, extraContexts) {
|
|
@@ -2373,11 +2398,35 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2373
2398
|
} catch {
|
|
2374
2399
|
}
|
|
2375
2400
|
}
|
|
2401
|
+
sendTraceStart(rootSpan) {
|
|
2402
|
+
const traceData = {
|
|
2403
|
+
type: "sdk-function",
|
|
2404
|
+
source: "typescript-sdk-langgraph",
|
|
2405
|
+
traceFunctionKey: this.traceFunctionKey,
|
|
2406
|
+
externalTrace: {
|
|
2407
|
+
id: rootSpan.traceId,
|
|
2408
|
+
started_at: rootSpan.startedAt,
|
|
2409
|
+
workflow_name: this.traceFunctionKey
|
|
2410
|
+
},
|
|
2411
|
+
completed: false
|
|
2412
|
+
};
|
|
2413
|
+
const finalized = finalizeTracePayload(traceData);
|
|
2414
|
+
try {
|
|
2415
|
+
this.httpClient.sendExternalTrace(finalized);
|
|
2416
|
+
} catch {
|
|
2417
|
+
}
|
|
2418
|
+
}
|
|
2376
2419
|
// ── chain callbacks (graph nodes) ─────────────────────────────
|
|
2377
|
-
async handleChainStart(chain, inputs, runId,
|
|
2420
|
+
async handleChainStart(chain, inputs, runId, parentRunIdOrRunType, tags, metadata, runTypeOrRunName, runNameOrParentRunId) {
|
|
2378
2421
|
try {
|
|
2379
|
-
const
|
|
2380
|
-
|
|
2422
|
+
const { parentRunId, runName } = normalizeChainStartArgs(
|
|
2423
|
+
parentRunIdOrRunType,
|
|
2424
|
+
runTypeOrRunName,
|
|
2425
|
+
runNameOrParentRunId
|
|
2426
|
+
);
|
|
2427
|
+
const serialized = chain ?? {};
|
|
2428
|
+
const idArr = serialized.id;
|
|
2429
|
+
const name = runName ?? serialized.name ?? idArr?.[idArr.length - 1] ?? "chain";
|
|
2381
2430
|
this.startSpan(
|
|
2382
2431
|
runId,
|
|
2383
2432
|
parentRunId,
|
|
@@ -2412,11 +2461,12 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2412
2461
|
}
|
|
2413
2462
|
}
|
|
2414
2463
|
// ── LLM callbacks ─────────────────────────────────────────────
|
|
2415
|
-
async handleChatModelStart(llm, messages, runId, parentRunId, _extraParams, tags, metadata) {
|
|
2464
|
+
async handleChatModelStart(llm, messages, runId, parentRunId, _extraParams, tags, metadata, runName) {
|
|
2416
2465
|
try {
|
|
2417
|
-
const
|
|
2418
|
-
const
|
|
2419
|
-
const
|
|
2466
|
+
const serialized = llm ?? {};
|
|
2467
|
+
const model = extractModelName(serialized, metadata);
|
|
2468
|
+
const idArr = serialized.id;
|
|
2469
|
+
const name = runName ?? model ?? idArr?.[idArr.length - 1] ?? "llm";
|
|
2420
2470
|
const converted = messages.map((batch) => batch.map(convertMessage));
|
|
2421
2471
|
const spanInfo = this.startSpan(
|
|
2422
2472
|
runId,
|
|
@@ -2431,11 +2481,12 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2431
2481
|
} catch {
|
|
2432
2482
|
}
|
|
2433
2483
|
}
|
|
2434
|
-
async handleLLMStart(llm, prompts, runId, parentRunId, _extraParams, tags, metadata) {
|
|
2484
|
+
async handleLLMStart(llm, prompts, runId, parentRunId, _extraParams, tags, metadata, runName) {
|
|
2435
2485
|
try {
|
|
2436
|
-
const
|
|
2437
|
-
const
|
|
2438
|
-
const
|
|
2486
|
+
const serialized = llm ?? {};
|
|
2487
|
+
const model = extractModelName(serialized, metadata);
|
|
2488
|
+
const idArr = serialized.id;
|
|
2489
|
+
const name = runName ?? model ?? idArr?.[idArr.length - 1] ?? "llm";
|
|
2439
2490
|
const spanInfo = this.startSpan(
|
|
2440
2491
|
runId,
|
|
2441
2492
|
parentRunId,
|
|
@@ -2488,9 +2539,10 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2488
2539
|
async handleLLMNewToken() {
|
|
2489
2540
|
}
|
|
2490
2541
|
// ── tool callbacks ────────────────────────────────────────────
|
|
2491
|
-
async handleToolStart(tool, input, runId, parentRunId, tags, metadata) {
|
|
2542
|
+
async handleToolStart(tool, input, runId, parentRunId, tags, metadata, runName) {
|
|
2492
2543
|
try {
|
|
2493
|
-
const
|
|
2544
|
+
const serialized = tool ?? {};
|
|
2545
|
+
const name = runName ?? serialized.name ?? "tool";
|
|
2494
2546
|
this.startSpan(
|
|
2495
2547
|
runId,
|
|
2496
2548
|
parentRunId,
|
|
@@ -2520,9 +2572,10 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2520
2572
|
}
|
|
2521
2573
|
}
|
|
2522
2574
|
// ── retriever callbacks ───────────────────────────────────────
|
|
2523
|
-
async handleRetrieverStart(retriever, query, runId, parentRunId, tags, metadata) {
|
|
2575
|
+
async handleRetrieverStart(retriever, query, runId, parentRunId, tags, metadata, runName) {
|
|
2524
2576
|
try {
|
|
2525
|
-
const
|
|
2577
|
+
const serialized = retriever ?? {};
|
|
2578
|
+
const name = runName ?? serialized.name ?? "retriever";
|
|
2526
2579
|
this.startSpan(
|
|
2527
2580
|
runId,
|
|
2528
2581
|
parentRunId,
|
|
@@ -3320,6 +3373,12 @@ function getCurrentTrace() {
|
|
|
3320
3373
|
}
|
|
3321
3374
|
};
|
|
3322
3375
|
}
|
|
3376
|
+
function readEnv(name) {
|
|
3377
|
+
if (typeof process !== "undefined" && process.env) {
|
|
3378
|
+
return process.env[name];
|
|
3379
|
+
}
|
|
3380
|
+
return void 0;
|
|
3381
|
+
}
|
|
3323
3382
|
var Bitfab = class {
|
|
3324
3383
|
/**
|
|
3325
3384
|
* Initialize the Bitfab client.
|
|
@@ -3327,30 +3386,75 @@ var Bitfab = class {
|
|
|
3327
3386
|
* @param config - Configuration options for the client
|
|
3328
3387
|
*/
|
|
3329
3388
|
constructor(config) {
|
|
3330
|
-
|
|
3389
|
+
/** Gate the empty-key warning to fire at most once. */
|
|
3390
|
+
this.apiKeyWarned = false;
|
|
3391
|
+
this.apiKeyConfig = config.apiKey;
|
|
3331
3392
|
this.serviceUrl = config.serviceUrl ?? DEFAULT_SERVICE_URL;
|
|
3332
3393
|
this.timeout = config.timeout ?? 12e4;
|
|
3333
3394
|
this.envVars = config.envVars ?? {};
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
console.warn(
|
|
3337
|
-
"Bitfab: apiKey is empty \u2014 tracing is disabled. Provide a valid API key to enable tracing."
|
|
3338
|
-
);
|
|
3339
|
-
this.enabled = false;
|
|
3340
|
-
} else {
|
|
3341
|
-
this.enabled = enabled;
|
|
3342
|
-
}
|
|
3395
|
+
this.explicitlyEnabled = config.enabled ?? true;
|
|
3396
|
+
this.strict = config.strict ?? false;
|
|
3343
3397
|
this.bamlClient = config.bamlClient ?? null;
|
|
3344
3398
|
if (config.dbSnapshot) {
|
|
3345
3399
|
validateDbSnapshotConfig(config.dbSnapshot);
|
|
3346
3400
|
}
|
|
3347
3401
|
this.dbSnapshot = config.dbSnapshot;
|
|
3348
3402
|
this.httpClient = new HttpClient({
|
|
3349
|
-
apiKey: this.
|
|
3403
|
+
apiKey: () => this.resolveApiKey(),
|
|
3350
3404
|
serviceUrl: this.serviceUrl,
|
|
3351
3405
|
timeout: this.timeout
|
|
3352
3406
|
});
|
|
3353
3407
|
}
|
|
3408
|
+
/**
|
|
3409
|
+
* Resolve the API key lazily, the first time a span actually needs it.
|
|
3410
|
+
*
|
|
3411
|
+
* The key is intentionally NOT read at construction. In ESM, a shim that
|
|
3412
|
+
* does `new Bitfab({ apiKey: process.env.BITFAB_API_KEY })` is hoisted and
|
|
3413
|
+
* evaluated before the importing script's body runs `dotenv.config()`, so
|
|
3414
|
+
* the key would be empty at construction even though it is set moments
|
|
3415
|
+
* later. Resolving here (at first `withSpan` call / first request) reads
|
|
3416
|
+
* the key after env loading has run.
|
|
3417
|
+
*
|
|
3418
|
+
* Resolution order: the configured value (string, or function called each
|
|
3419
|
+
* time it is still unresolved), then a fallback read of `BITFAB_API_KEY`
|
|
3420
|
+
* from the environment. Once a non-empty key is found it is cached, so an
|
|
3421
|
+
* early resolve that found nothing never poisons a later one.
|
|
3422
|
+
*/
|
|
3423
|
+
resolveApiKey() {
|
|
3424
|
+
if (this.resolvedApiKey !== void 0) {
|
|
3425
|
+
return this.resolvedApiKey;
|
|
3426
|
+
}
|
|
3427
|
+
const fromConfig = typeof this.apiKeyConfig === "function" ? this.apiKeyConfig() : this.apiKeyConfig;
|
|
3428
|
+
const candidate = fromConfig && fromConfig.trim() !== "" ? fromConfig : readEnv("BITFAB_API_KEY");
|
|
3429
|
+
const key = candidate && candidate.trim() !== "" ? candidate : void 0;
|
|
3430
|
+
if (key) {
|
|
3431
|
+
this.resolvedApiKey = key;
|
|
3432
|
+
return key;
|
|
3433
|
+
}
|
|
3434
|
+
if (this.strict) {
|
|
3435
|
+
throw new BitfabError(
|
|
3436
|
+
"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`."
|
|
3437
|
+
);
|
|
3438
|
+
}
|
|
3439
|
+
if (this.explicitlyEnabled && !this.apiKeyWarned) {
|
|
3440
|
+
this.apiKeyWarned = true;
|
|
3441
|
+
console.warn(
|
|
3442
|
+
"Bitfab: apiKey is empty \u2014 tracing is disabled. Provide a valid API key to enable tracing."
|
|
3443
|
+
);
|
|
3444
|
+
}
|
|
3445
|
+
return void 0;
|
|
3446
|
+
}
|
|
3447
|
+
/**
|
|
3448
|
+
* Whether tracing should run, decided lazily at call time (not frozen at
|
|
3449
|
+
* construction). An explicit `enabled: false` short-circuits without ever
|
|
3450
|
+
* touching the key.
|
|
3451
|
+
*/
|
|
3452
|
+
isTracingEnabled() {
|
|
3453
|
+
if (!this.explicitlyEnabled) {
|
|
3454
|
+
return false;
|
|
3455
|
+
}
|
|
3456
|
+
return this.resolveApiKey() !== void 0;
|
|
3457
|
+
}
|
|
3354
3458
|
/**
|
|
3355
3459
|
* Fetch the function with its current version and BAML prompt from the server.
|
|
3356
3460
|
*
|
|
@@ -3443,7 +3547,9 @@ var Bitfab = class {
|
|
|
3443
3547
|
*/
|
|
3444
3548
|
getOpenAiTracingProcessor() {
|
|
3445
3549
|
return new BitfabOpenAITracingProcessor({
|
|
3446
|
-
|
|
3550
|
+
// Resolved at getter-call time (framework handlers are set up after env
|
|
3551
|
+
// loads); the withSpan path stays lazy via the constructor HttpClient thunk.
|
|
3552
|
+
apiKey: this.resolveApiKey(),
|
|
3447
3553
|
serviceUrl: this.serviceUrl,
|
|
3448
3554
|
getActiveSpanContext: () => {
|
|
3449
3555
|
const stack = getSpanStack();
|
|
@@ -3502,7 +3608,7 @@ var Bitfab = class {
|
|
|
3502
3608
|
*/
|
|
3503
3609
|
getLangGraphCallbackHandler(traceFunctionKey) {
|
|
3504
3610
|
return new BitfabLangGraphCallbackHandler({
|
|
3505
|
-
apiKey: this.
|
|
3611
|
+
apiKey: this.resolveApiKey(),
|
|
3506
3612
|
traceFunctionKey,
|
|
3507
3613
|
serviceUrl: this.serviceUrl,
|
|
3508
3614
|
getActiveSpanContext: () => {
|
|
@@ -3554,7 +3660,7 @@ var Bitfab = class {
|
|
|
3554
3660
|
*/
|
|
3555
3661
|
getClaudeAgentHandler(traceFunctionKey) {
|
|
3556
3662
|
return new BitfabClaudeAgentHandler({
|
|
3557
|
-
apiKey: this.
|
|
3663
|
+
apiKey: this.resolveApiKey(),
|
|
3558
3664
|
traceFunctionKey,
|
|
3559
3665
|
serviceUrl: this.serviceUrl,
|
|
3560
3666
|
getActiveSpanContext: () => {
|
|
@@ -3726,9 +3832,8 @@ var Bitfab = class {
|
|
|
3726
3832
|
* @returns A wrapped function with the same signature that creates spans for inputs and outputs
|
|
3727
3833
|
*/
|
|
3728
3834
|
withSpan(traceFunctionKey, optionsOrFn, maybeFn) {
|
|
3729
|
-
if (!this.
|
|
3730
|
-
|
|
3731
|
-
return fn2;
|
|
3835
|
+
if (!this.explicitlyEnabled) {
|
|
3836
|
+
return typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
|
|
3732
3837
|
}
|
|
3733
3838
|
const options = typeof optionsOrFn === "function" ? {} : optionsOrFn;
|
|
3734
3839
|
const fn = typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
|
|
@@ -3743,6 +3848,9 @@ var Bitfab = class {
|
|
|
3743
3848
|
}
|
|
3744
3849
|
})();
|
|
3745
3850
|
const wrappedFn = function(...args) {
|
|
3851
|
+
if (!self.isTracingEnabled()) {
|
|
3852
|
+
return fn.apply(this, args);
|
|
3853
|
+
}
|
|
3746
3854
|
if (!asyncLocalStorage && !isAsyncStorageInitDone()) {
|
|
3747
3855
|
return asyncLocalStorageReady.then(
|
|
3748
3856
|
() => wrappedFn.apply(this, args)
|
|
@@ -4003,7 +4111,7 @@ var Bitfab = class {
|
|
|
4003
4111
|
return {
|
|
4004
4112
|
traceId,
|
|
4005
4113
|
addContext: (context) => {
|
|
4006
|
-
if (!this.
|
|
4114
|
+
if (!this.isTracingEnabled()) {
|
|
4007
4115
|
return Promise.resolve();
|
|
4008
4116
|
}
|
|
4009
4117
|
if (typeof context !== "object" || context === null) {
|
|
@@ -4014,7 +4122,7 @@ var Bitfab = class {
|
|
|
4014
4122
|
});
|
|
4015
4123
|
},
|
|
4016
4124
|
setMetadata: (metadata) => {
|
|
4017
|
-
if (!this.
|
|
4125
|
+
if (!this.isTracingEnabled()) {
|
|
4018
4126
|
return Promise.resolve();
|
|
4019
4127
|
}
|
|
4020
4128
|
if (typeof metadata !== "object" || metadata === null) {
|
|
@@ -4023,7 +4131,7 @@ var Bitfab = class {
|
|
|
4023
4131
|
return this.httpClient.patchTrace(traceId, { mergeMetadata: metadata });
|
|
4024
4132
|
},
|
|
4025
4133
|
setSessionId: (sessionId) => {
|
|
4026
|
-
if (!this.
|
|
4134
|
+
if (!this.isTracingEnabled()) {
|
|
4027
4135
|
return Promise.resolve();
|
|
4028
4136
|
}
|
|
4029
4137
|
if (typeof sessionId !== "string" || sessionId.length === 0) {
|