@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.cjs
CHANGED
|
@@ -636,7 +636,7 @@ __export(index_exports, {
|
|
|
636
636
|
module.exports = __toCommonJS(index_exports);
|
|
637
637
|
|
|
638
638
|
// src/version.generated.ts
|
|
639
|
-
var __version__ = "0.
|
|
639
|
+
var __version__ = "0.28.0";
|
|
640
640
|
|
|
641
641
|
// src/constants.ts
|
|
642
642
|
var DEFAULT_SERVICE_URL = "https://bitfab.ai";
|
|
@@ -795,6 +795,13 @@ var HttpClient = class {
|
|
|
795
795
|
this.serviceUrl = config.serviceUrl;
|
|
796
796
|
this.timeout = config.timeout ?? 12e4;
|
|
797
797
|
}
|
|
798
|
+
/**
|
|
799
|
+
* Resolve the API key at the moment it is needed (request time), invoking
|
|
800
|
+
* the function form if one was supplied. Never read at construction.
|
|
801
|
+
*/
|
|
802
|
+
resolveApiKey() {
|
|
803
|
+
return typeof this.apiKey === "function" ? this.apiKey() : this.apiKey;
|
|
804
|
+
}
|
|
798
805
|
/**
|
|
799
806
|
* Make an HTTP request to the Bitfab API. Defaults to POST; pass
|
|
800
807
|
* `options.method` to use a different verb (e.g. "PATCH").
|
|
@@ -825,7 +832,7 @@ var HttpClient = class {
|
|
|
825
832
|
method,
|
|
826
833
|
headers: {
|
|
827
834
|
"Content-Type": "application/json",
|
|
828
|
-
Authorization: `Bearer ${this.
|
|
835
|
+
Authorization: `Bearer ${this.resolveApiKey() ?? ""}`
|
|
829
836
|
},
|
|
830
837
|
body,
|
|
831
838
|
signal: controller.signal
|
|
@@ -986,7 +993,7 @@ var HttpClient = class {
|
|
|
986
993
|
try {
|
|
987
994
|
const response = await fetch(url, {
|
|
988
995
|
method: "GET",
|
|
989
|
-
headers: { Authorization: `Bearer ${this.
|
|
996
|
+
headers: { Authorization: `Bearer ${this.resolveApiKey() ?? ""}` },
|
|
990
997
|
signal: controller.signal
|
|
991
998
|
});
|
|
992
999
|
if (!response.ok) {
|
|
@@ -1022,7 +1029,7 @@ var HttpClient = class {
|
|
|
1022
1029
|
try {
|
|
1023
1030
|
const response = await fetch(url, {
|
|
1024
1031
|
method: "GET",
|
|
1025
|
-
headers: { Authorization: `Bearer ${this.
|
|
1032
|
+
headers: { Authorization: `Bearer ${this.resolveApiKey() ?? ""}` },
|
|
1026
1033
|
signal: controller.signal
|
|
1027
1034
|
});
|
|
1028
1035
|
if (!response.ok) {
|
|
@@ -1996,6 +2003,7 @@ function buildSnapshotRef(config, sdkWallClockBeforeFn) {
|
|
|
1996
2003
|
init_randomUuid();
|
|
1997
2004
|
init_serialize();
|
|
1998
2005
|
var LANGSMITH_HIDDEN_TAG = "langsmith:hidden";
|
|
2006
|
+
var CHAIN_RUN_TYPES = /* @__PURE__ */ new Set(["chain", "parser", "prompt"]);
|
|
1999
2007
|
var LANGGRAPH_METADATA_KEYS = [
|
|
2000
2008
|
"langgraph_step",
|
|
2001
2009
|
"langgraph_node",
|
|
@@ -2006,6 +2014,18 @@ var LANGGRAPH_METADATA_KEYS = [
|
|
|
2006
2014
|
function nowIso2() {
|
|
2007
2015
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
2008
2016
|
}
|
|
2017
|
+
function normalizeChainStartArgs(parentRunIdOrRunType, runTypeOrRunName, runNameOrParentRunId) {
|
|
2018
|
+
if (parentRunIdOrRunType && CHAIN_RUN_TYPES.has(parentRunIdOrRunType)) {
|
|
2019
|
+
return {
|
|
2020
|
+
parentRunId: runNameOrParentRunId,
|
|
2021
|
+
runName: runTypeOrRunName
|
|
2022
|
+
};
|
|
2023
|
+
}
|
|
2024
|
+
return {
|
|
2025
|
+
parentRunId: parentRunIdOrRunType,
|
|
2026
|
+
runName: runNameOrParentRunId
|
|
2027
|
+
};
|
|
2028
|
+
}
|
|
2009
2029
|
function convertMessage(message) {
|
|
2010
2030
|
if (typeof message !== "object" || message === null) {
|
|
2011
2031
|
return { role: "unknown", content: String(message) };
|
|
@@ -2217,6 +2237,7 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2217
2237
|
const willHide = tags?.includes(LANGSMITH_HIDDEN_TAG) === true;
|
|
2218
2238
|
let invocation;
|
|
2219
2239
|
let effectiveParentId;
|
|
2240
|
+
let isRootInvocation = false;
|
|
2220
2241
|
if (parentSpan) {
|
|
2221
2242
|
const existing = this.invocations.get(parentSpan.rootRunId);
|
|
2222
2243
|
if (existing) {
|
|
@@ -2247,6 +2268,7 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2247
2268
|
};
|
|
2248
2269
|
this.invocations.set(runId, invocation);
|
|
2249
2270
|
effectiveParentId = activeContext?.spanId ?? null;
|
|
2271
|
+
isRootInvocation = true;
|
|
2250
2272
|
}
|
|
2251
2273
|
const lgMetadata = extractLangGraphMetadata(metadata);
|
|
2252
2274
|
const contexts = Object.keys(lgMetadata).length > 0 ? [lgMetadata] : [];
|
|
@@ -2269,6 +2291,9 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2269
2291
|
spanInfo.hidden = true;
|
|
2270
2292
|
}
|
|
2271
2293
|
this.runToSpan.set(runId, spanInfo);
|
|
2294
|
+
if (isRootInvocation) {
|
|
2295
|
+
this.sendTraceStart(spanInfo);
|
|
2296
|
+
}
|
|
2272
2297
|
return spanInfo;
|
|
2273
2298
|
}
|
|
2274
2299
|
completeSpan(runId, output, error, extraContexts) {
|
|
@@ -2359,11 +2384,35 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2359
2384
|
} catch {
|
|
2360
2385
|
}
|
|
2361
2386
|
}
|
|
2387
|
+
sendTraceStart(rootSpan) {
|
|
2388
|
+
const traceData = {
|
|
2389
|
+
type: "sdk-function",
|
|
2390
|
+
source: "typescript-sdk-langgraph",
|
|
2391
|
+
traceFunctionKey: this.traceFunctionKey,
|
|
2392
|
+
externalTrace: {
|
|
2393
|
+
id: rootSpan.traceId,
|
|
2394
|
+
started_at: rootSpan.startedAt,
|
|
2395
|
+
workflow_name: this.traceFunctionKey
|
|
2396
|
+
},
|
|
2397
|
+
completed: false
|
|
2398
|
+
};
|
|
2399
|
+
const finalized = finalizeTracePayload(traceData);
|
|
2400
|
+
try {
|
|
2401
|
+
this.httpClient.sendExternalTrace(finalized);
|
|
2402
|
+
} catch {
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2362
2405
|
// ── chain callbacks (graph nodes) ─────────────────────────────
|
|
2363
|
-
async handleChainStart(chain, inputs, runId,
|
|
2406
|
+
async handleChainStart(chain, inputs, runId, parentRunIdOrRunType, tags, metadata, runTypeOrRunName, runNameOrParentRunId) {
|
|
2364
2407
|
try {
|
|
2365
|
-
const
|
|
2366
|
-
|
|
2408
|
+
const { parentRunId, runName } = normalizeChainStartArgs(
|
|
2409
|
+
parentRunIdOrRunType,
|
|
2410
|
+
runTypeOrRunName,
|
|
2411
|
+
runNameOrParentRunId
|
|
2412
|
+
);
|
|
2413
|
+
const serialized = chain ?? {};
|
|
2414
|
+
const idArr = serialized.id;
|
|
2415
|
+
const name = runName ?? serialized.name ?? idArr?.[idArr.length - 1] ?? "chain";
|
|
2367
2416
|
this.startSpan(
|
|
2368
2417
|
runId,
|
|
2369
2418
|
parentRunId,
|
|
@@ -2398,11 +2447,12 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2398
2447
|
}
|
|
2399
2448
|
}
|
|
2400
2449
|
// ── LLM callbacks ─────────────────────────────────────────────
|
|
2401
|
-
async handleChatModelStart(llm, messages, runId, parentRunId, _extraParams, tags, metadata) {
|
|
2450
|
+
async handleChatModelStart(llm, messages, runId, parentRunId, _extraParams, tags, metadata, runName) {
|
|
2402
2451
|
try {
|
|
2403
|
-
const
|
|
2404
|
-
const
|
|
2405
|
-
const
|
|
2452
|
+
const serialized = llm ?? {};
|
|
2453
|
+
const model = extractModelName(serialized, metadata);
|
|
2454
|
+
const idArr = serialized.id;
|
|
2455
|
+
const name = runName ?? model ?? idArr?.[idArr.length - 1] ?? "llm";
|
|
2406
2456
|
const converted = messages.map((batch) => batch.map(convertMessage));
|
|
2407
2457
|
const spanInfo = this.startSpan(
|
|
2408
2458
|
runId,
|
|
@@ -2417,11 +2467,12 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2417
2467
|
} catch {
|
|
2418
2468
|
}
|
|
2419
2469
|
}
|
|
2420
|
-
async handleLLMStart(llm, prompts, runId, parentRunId, _extraParams, tags, metadata) {
|
|
2470
|
+
async handleLLMStart(llm, prompts, runId, parentRunId, _extraParams, tags, metadata, runName) {
|
|
2421
2471
|
try {
|
|
2422
|
-
const
|
|
2423
|
-
const
|
|
2424
|
-
const
|
|
2472
|
+
const serialized = llm ?? {};
|
|
2473
|
+
const model = extractModelName(serialized, metadata);
|
|
2474
|
+
const idArr = serialized.id;
|
|
2475
|
+
const name = runName ?? model ?? idArr?.[idArr.length - 1] ?? "llm";
|
|
2425
2476
|
const spanInfo = this.startSpan(
|
|
2426
2477
|
runId,
|
|
2427
2478
|
parentRunId,
|
|
@@ -2474,9 +2525,10 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2474
2525
|
async handleLLMNewToken() {
|
|
2475
2526
|
}
|
|
2476
2527
|
// ── tool callbacks ────────────────────────────────────────────
|
|
2477
|
-
async handleToolStart(tool, input, runId, parentRunId, tags, metadata) {
|
|
2528
|
+
async handleToolStart(tool, input, runId, parentRunId, tags, metadata, runName) {
|
|
2478
2529
|
try {
|
|
2479
|
-
const
|
|
2530
|
+
const serialized = tool ?? {};
|
|
2531
|
+
const name = runName ?? serialized.name ?? "tool";
|
|
2480
2532
|
this.startSpan(
|
|
2481
2533
|
runId,
|
|
2482
2534
|
parentRunId,
|
|
@@ -2506,9 +2558,10 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2506
2558
|
}
|
|
2507
2559
|
}
|
|
2508
2560
|
// ── retriever callbacks ───────────────────────────────────────
|
|
2509
|
-
async handleRetrieverStart(retriever, query, runId, parentRunId, tags, metadata) {
|
|
2561
|
+
async handleRetrieverStart(retriever, query, runId, parentRunId, tags, metadata, runName) {
|
|
2510
2562
|
try {
|
|
2511
|
-
const
|
|
2563
|
+
const serialized = retriever ?? {};
|
|
2564
|
+
const name = runName ?? serialized.name ?? "retriever";
|
|
2512
2565
|
this.startSpan(
|
|
2513
2566
|
runId,
|
|
2514
2567
|
parentRunId,
|
|
@@ -3306,6 +3359,12 @@ function getCurrentTrace() {
|
|
|
3306
3359
|
}
|
|
3307
3360
|
};
|
|
3308
3361
|
}
|
|
3362
|
+
function readEnv(name) {
|
|
3363
|
+
if (typeof process !== "undefined" && process.env) {
|
|
3364
|
+
return process.env[name];
|
|
3365
|
+
}
|
|
3366
|
+
return void 0;
|
|
3367
|
+
}
|
|
3309
3368
|
var Bitfab = class {
|
|
3310
3369
|
/**
|
|
3311
3370
|
* Initialize the Bitfab client.
|
|
@@ -3313,30 +3372,75 @@ var Bitfab = class {
|
|
|
3313
3372
|
* @param config - Configuration options for the client
|
|
3314
3373
|
*/
|
|
3315
3374
|
constructor(config) {
|
|
3316
|
-
|
|
3375
|
+
/** Gate the empty-key warning to fire at most once. */
|
|
3376
|
+
this.apiKeyWarned = false;
|
|
3377
|
+
this.apiKeyConfig = config.apiKey;
|
|
3317
3378
|
this.serviceUrl = config.serviceUrl ?? DEFAULT_SERVICE_URL;
|
|
3318
3379
|
this.timeout = config.timeout ?? 12e4;
|
|
3319
3380
|
this.envVars = config.envVars ?? {};
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
console.warn(
|
|
3323
|
-
"Bitfab: apiKey is empty \u2014 tracing is disabled. Provide a valid API key to enable tracing."
|
|
3324
|
-
);
|
|
3325
|
-
this.enabled = false;
|
|
3326
|
-
} else {
|
|
3327
|
-
this.enabled = enabled;
|
|
3328
|
-
}
|
|
3381
|
+
this.explicitlyEnabled = config.enabled ?? true;
|
|
3382
|
+
this.strict = config.strict ?? false;
|
|
3329
3383
|
this.bamlClient = config.bamlClient ?? null;
|
|
3330
3384
|
if (config.dbSnapshot) {
|
|
3331
3385
|
validateDbSnapshotConfig(config.dbSnapshot);
|
|
3332
3386
|
}
|
|
3333
3387
|
this.dbSnapshot = config.dbSnapshot;
|
|
3334
3388
|
this.httpClient = new HttpClient({
|
|
3335
|
-
apiKey: this.
|
|
3389
|
+
apiKey: () => this.resolveApiKey(),
|
|
3336
3390
|
serviceUrl: this.serviceUrl,
|
|
3337
3391
|
timeout: this.timeout
|
|
3338
3392
|
});
|
|
3339
3393
|
}
|
|
3394
|
+
/**
|
|
3395
|
+
* Resolve the API key lazily, the first time a span actually needs it.
|
|
3396
|
+
*
|
|
3397
|
+
* The key is intentionally NOT read at construction. In ESM, a shim that
|
|
3398
|
+
* does `new Bitfab({ apiKey: process.env.BITFAB_API_KEY })` is hoisted and
|
|
3399
|
+
* evaluated before the importing script's body runs `dotenv.config()`, so
|
|
3400
|
+
* the key would be empty at construction even though it is set moments
|
|
3401
|
+
* later. Resolving here (at first `withSpan` call / first request) reads
|
|
3402
|
+
* the key after env loading has run.
|
|
3403
|
+
*
|
|
3404
|
+
* Resolution order: the configured value (string, or function called each
|
|
3405
|
+
* time it is still unresolved), then a fallback read of `BITFAB_API_KEY`
|
|
3406
|
+
* from the environment. Once a non-empty key is found it is cached, so an
|
|
3407
|
+
* early resolve that found nothing never poisons a later one.
|
|
3408
|
+
*/
|
|
3409
|
+
resolveApiKey() {
|
|
3410
|
+
if (this.resolvedApiKey !== void 0) {
|
|
3411
|
+
return this.resolvedApiKey;
|
|
3412
|
+
}
|
|
3413
|
+
const fromConfig = typeof this.apiKeyConfig === "function" ? this.apiKeyConfig() : this.apiKeyConfig;
|
|
3414
|
+
const candidate = fromConfig && fromConfig.trim() !== "" ? fromConfig : readEnv("BITFAB_API_KEY");
|
|
3415
|
+
const key = candidate && candidate.trim() !== "" ? candidate : void 0;
|
|
3416
|
+
if (key) {
|
|
3417
|
+
this.resolvedApiKey = key;
|
|
3418
|
+
return key;
|
|
3419
|
+
}
|
|
3420
|
+
if (this.strict) {
|
|
3421
|
+
throw new BitfabError(
|
|
3422
|
+
"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`."
|
|
3423
|
+
);
|
|
3424
|
+
}
|
|
3425
|
+
if (this.explicitlyEnabled && !this.apiKeyWarned) {
|
|
3426
|
+
this.apiKeyWarned = true;
|
|
3427
|
+
console.warn(
|
|
3428
|
+
"Bitfab: apiKey is empty \u2014 tracing is disabled. Provide a valid API key to enable tracing."
|
|
3429
|
+
);
|
|
3430
|
+
}
|
|
3431
|
+
return void 0;
|
|
3432
|
+
}
|
|
3433
|
+
/**
|
|
3434
|
+
* Whether tracing should run, decided lazily at call time (not frozen at
|
|
3435
|
+
* construction). An explicit `enabled: false` short-circuits without ever
|
|
3436
|
+
* touching the key.
|
|
3437
|
+
*/
|
|
3438
|
+
isTracingEnabled() {
|
|
3439
|
+
if (!this.explicitlyEnabled) {
|
|
3440
|
+
return false;
|
|
3441
|
+
}
|
|
3442
|
+
return this.resolveApiKey() !== void 0;
|
|
3443
|
+
}
|
|
3340
3444
|
/**
|
|
3341
3445
|
* Fetch the function with its current version and BAML prompt from the server.
|
|
3342
3446
|
*
|
|
@@ -3429,7 +3533,9 @@ var Bitfab = class {
|
|
|
3429
3533
|
*/
|
|
3430
3534
|
getOpenAiTracingProcessor() {
|
|
3431
3535
|
return new BitfabOpenAITracingProcessor({
|
|
3432
|
-
|
|
3536
|
+
// Resolved at getter-call time (framework handlers are set up after env
|
|
3537
|
+
// loads); the withSpan path stays lazy via the constructor HttpClient thunk.
|
|
3538
|
+
apiKey: this.resolveApiKey(),
|
|
3433
3539
|
serviceUrl: this.serviceUrl,
|
|
3434
3540
|
getActiveSpanContext: () => {
|
|
3435
3541
|
const stack = getSpanStack();
|
|
@@ -3488,7 +3594,7 @@ var Bitfab = class {
|
|
|
3488
3594
|
*/
|
|
3489
3595
|
getLangGraphCallbackHandler(traceFunctionKey) {
|
|
3490
3596
|
return new BitfabLangGraphCallbackHandler({
|
|
3491
|
-
apiKey: this.
|
|
3597
|
+
apiKey: this.resolveApiKey(),
|
|
3492
3598
|
traceFunctionKey,
|
|
3493
3599
|
serviceUrl: this.serviceUrl,
|
|
3494
3600
|
getActiveSpanContext: () => {
|
|
@@ -3540,7 +3646,7 @@ var Bitfab = class {
|
|
|
3540
3646
|
*/
|
|
3541
3647
|
getClaudeAgentHandler(traceFunctionKey) {
|
|
3542
3648
|
return new BitfabClaudeAgentHandler({
|
|
3543
|
-
apiKey: this.
|
|
3649
|
+
apiKey: this.resolveApiKey(),
|
|
3544
3650
|
traceFunctionKey,
|
|
3545
3651
|
serviceUrl: this.serviceUrl,
|
|
3546
3652
|
getActiveSpanContext: () => {
|
|
@@ -3712,9 +3818,8 @@ var Bitfab = class {
|
|
|
3712
3818
|
* @returns A wrapped function with the same signature that creates spans for inputs and outputs
|
|
3713
3819
|
*/
|
|
3714
3820
|
withSpan(traceFunctionKey, optionsOrFn, maybeFn) {
|
|
3715
|
-
if (!this.
|
|
3716
|
-
|
|
3717
|
-
return fn2;
|
|
3821
|
+
if (!this.explicitlyEnabled) {
|
|
3822
|
+
return typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
|
|
3718
3823
|
}
|
|
3719
3824
|
const options = typeof optionsOrFn === "function" ? {} : optionsOrFn;
|
|
3720
3825
|
const fn = typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
|
|
@@ -3729,6 +3834,9 @@ var Bitfab = class {
|
|
|
3729
3834
|
}
|
|
3730
3835
|
})();
|
|
3731
3836
|
const wrappedFn = function(...args) {
|
|
3837
|
+
if (!self.isTracingEnabled()) {
|
|
3838
|
+
return fn.apply(this, args);
|
|
3839
|
+
}
|
|
3732
3840
|
if (!asyncLocalStorage && !isAsyncStorageInitDone()) {
|
|
3733
3841
|
return asyncLocalStorageReady.then(
|
|
3734
3842
|
() => wrappedFn.apply(this, args)
|
|
@@ -3989,7 +4097,7 @@ var Bitfab = class {
|
|
|
3989
4097
|
return {
|
|
3990
4098
|
traceId,
|
|
3991
4099
|
addContext: (context) => {
|
|
3992
|
-
if (!this.
|
|
4100
|
+
if (!this.isTracingEnabled()) {
|
|
3993
4101
|
return Promise.resolve();
|
|
3994
4102
|
}
|
|
3995
4103
|
if (typeof context !== "object" || context === null) {
|
|
@@ -4000,7 +4108,7 @@ var Bitfab = class {
|
|
|
4000
4108
|
});
|
|
4001
4109
|
},
|
|
4002
4110
|
setMetadata: (metadata) => {
|
|
4003
|
-
if (!this.
|
|
4111
|
+
if (!this.isTracingEnabled()) {
|
|
4004
4112
|
return Promise.resolve();
|
|
4005
4113
|
}
|
|
4006
4114
|
if (typeof metadata !== "object" || metadata === null) {
|
|
@@ -4009,7 +4117,7 @@ var Bitfab = class {
|
|
|
4009
4117
|
return this.httpClient.patchTrace(traceId, { mergeMetadata: metadata });
|
|
4010
4118
|
},
|
|
4011
4119
|
setSessionId: (sessionId) => {
|
|
4012
|
-
if (!this.
|
|
4120
|
+
if (!this.isTracingEnabled()) {
|
|
4013
4121
|
return Promise.resolve();
|
|
4014
4122
|
}
|
|
4015
4123
|
if (typeof sessionId !== "string" || sessionId.length === 0) {
|