bitfab 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
|
@@ -659,7 +659,7 @@ registerAsyncLocalStorageClass(
|
|
|
659
659
|
);
|
|
660
660
|
|
|
661
661
|
// src/version.generated.ts
|
|
662
|
-
var __version__ = "0.
|
|
662
|
+
var __version__ = "0.28.0";
|
|
663
663
|
|
|
664
664
|
// src/constants.ts
|
|
665
665
|
var DEFAULT_SERVICE_URL = "https://bitfab.ai";
|
|
@@ -818,6 +818,13 @@ var HttpClient = class {
|
|
|
818
818
|
this.serviceUrl = config.serviceUrl;
|
|
819
819
|
this.timeout = config.timeout ?? 12e4;
|
|
820
820
|
}
|
|
821
|
+
/**
|
|
822
|
+
* Resolve the API key at the moment it is needed (request time), invoking
|
|
823
|
+
* the function form if one was supplied. Never read at construction.
|
|
824
|
+
*/
|
|
825
|
+
resolveApiKey() {
|
|
826
|
+
return typeof this.apiKey === "function" ? this.apiKey() : this.apiKey;
|
|
827
|
+
}
|
|
821
828
|
/**
|
|
822
829
|
* Make an HTTP request to the Bitfab API. Defaults to POST; pass
|
|
823
830
|
* `options.method` to use a different verb (e.g. "PATCH").
|
|
@@ -848,7 +855,7 @@ var HttpClient = class {
|
|
|
848
855
|
method,
|
|
849
856
|
headers: {
|
|
850
857
|
"Content-Type": "application/json",
|
|
851
|
-
Authorization: `Bearer ${this.
|
|
858
|
+
Authorization: `Bearer ${this.resolveApiKey() ?? ""}`
|
|
852
859
|
},
|
|
853
860
|
body,
|
|
854
861
|
signal: controller.signal
|
|
@@ -1009,7 +1016,7 @@ var HttpClient = class {
|
|
|
1009
1016
|
try {
|
|
1010
1017
|
const response = await fetch(url, {
|
|
1011
1018
|
method: "GET",
|
|
1012
|
-
headers: { Authorization: `Bearer ${this.
|
|
1019
|
+
headers: { Authorization: `Bearer ${this.resolveApiKey() ?? ""}` },
|
|
1013
1020
|
signal: controller.signal
|
|
1014
1021
|
});
|
|
1015
1022
|
if (!response.ok) {
|
|
@@ -1045,7 +1052,7 @@ var HttpClient = class {
|
|
|
1045
1052
|
try {
|
|
1046
1053
|
const response = await fetch(url, {
|
|
1047
1054
|
method: "GET",
|
|
1048
|
-
headers: { Authorization: `Bearer ${this.
|
|
1055
|
+
headers: { Authorization: `Bearer ${this.resolveApiKey() ?? ""}` },
|
|
1049
1056
|
signal: controller.signal
|
|
1050
1057
|
});
|
|
1051
1058
|
if (!response.ok) {
|
|
@@ -2019,6 +2026,7 @@ function buildSnapshotRef(config, sdkWallClockBeforeFn) {
|
|
|
2019
2026
|
init_randomUuid();
|
|
2020
2027
|
init_serialize();
|
|
2021
2028
|
var LANGSMITH_HIDDEN_TAG = "langsmith:hidden";
|
|
2029
|
+
var CHAIN_RUN_TYPES = /* @__PURE__ */ new Set(["chain", "parser", "prompt"]);
|
|
2022
2030
|
var LANGGRAPH_METADATA_KEYS = [
|
|
2023
2031
|
"langgraph_step",
|
|
2024
2032
|
"langgraph_node",
|
|
@@ -2029,6 +2037,18 @@ var LANGGRAPH_METADATA_KEYS = [
|
|
|
2029
2037
|
function nowIso2() {
|
|
2030
2038
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
2031
2039
|
}
|
|
2040
|
+
function normalizeChainStartArgs(parentRunIdOrRunType, runTypeOrRunName, runNameOrParentRunId) {
|
|
2041
|
+
if (parentRunIdOrRunType && CHAIN_RUN_TYPES.has(parentRunIdOrRunType)) {
|
|
2042
|
+
return {
|
|
2043
|
+
parentRunId: runNameOrParentRunId,
|
|
2044
|
+
runName: runTypeOrRunName
|
|
2045
|
+
};
|
|
2046
|
+
}
|
|
2047
|
+
return {
|
|
2048
|
+
parentRunId: parentRunIdOrRunType,
|
|
2049
|
+
runName: runNameOrParentRunId
|
|
2050
|
+
};
|
|
2051
|
+
}
|
|
2032
2052
|
function convertMessage(message) {
|
|
2033
2053
|
if (typeof message !== "object" || message === null) {
|
|
2034
2054
|
return { role: "unknown", content: String(message) };
|
|
@@ -2240,6 +2260,7 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2240
2260
|
const willHide = tags?.includes(LANGSMITH_HIDDEN_TAG) === true;
|
|
2241
2261
|
let invocation;
|
|
2242
2262
|
let effectiveParentId;
|
|
2263
|
+
let isRootInvocation = false;
|
|
2243
2264
|
if (parentSpan) {
|
|
2244
2265
|
const existing = this.invocations.get(parentSpan.rootRunId);
|
|
2245
2266
|
if (existing) {
|
|
@@ -2270,6 +2291,7 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2270
2291
|
};
|
|
2271
2292
|
this.invocations.set(runId, invocation);
|
|
2272
2293
|
effectiveParentId = activeContext?.spanId ?? null;
|
|
2294
|
+
isRootInvocation = true;
|
|
2273
2295
|
}
|
|
2274
2296
|
const lgMetadata = extractLangGraphMetadata(metadata);
|
|
2275
2297
|
const contexts = Object.keys(lgMetadata).length > 0 ? [lgMetadata] : [];
|
|
@@ -2292,6 +2314,9 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2292
2314
|
spanInfo.hidden = true;
|
|
2293
2315
|
}
|
|
2294
2316
|
this.runToSpan.set(runId, spanInfo);
|
|
2317
|
+
if (isRootInvocation) {
|
|
2318
|
+
this.sendTraceStart(spanInfo);
|
|
2319
|
+
}
|
|
2295
2320
|
return spanInfo;
|
|
2296
2321
|
}
|
|
2297
2322
|
completeSpan(runId, output, error, extraContexts) {
|
|
@@ -2382,11 +2407,35 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2382
2407
|
} catch {
|
|
2383
2408
|
}
|
|
2384
2409
|
}
|
|
2410
|
+
sendTraceStart(rootSpan) {
|
|
2411
|
+
const traceData = {
|
|
2412
|
+
type: "sdk-function",
|
|
2413
|
+
source: "typescript-sdk-langgraph",
|
|
2414
|
+
traceFunctionKey: this.traceFunctionKey,
|
|
2415
|
+
externalTrace: {
|
|
2416
|
+
id: rootSpan.traceId,
|
|
2417
|
+
started_at: rootSpan.startedAt,
|
|
2418
|
+
workflow_name: this.traceFunctionKey
|
|
2419
|
+
},
|
|
2420
|
+
completed: false
|
|
2421
|
+
};
|
|
2422
|
+
const finalized = finalizeTracePayload(traceData);
|
|
2423
|
+
try {
|
|
2424
|
+
this.httpClient.sendExternalTrace(finalized);
|
|
2425
|
+
} catch {
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2385
2428
|
// ── chain callbacks (graph nodes) ─────────────────────────────
|
|
2386
|
-
async handleChainStart(chain, inputs, runId,
|
|
2429
|
+
async handleChainStart(chain, inputs, runId, parentRunIdOrRunType, tags, metadata, runTypeOrRunName, runNameOrParentRunId) {
|
|
2387
2430
|
try {
|
|
2388
|
-
const
|
|
2389
|
-
|
|
2431
|
+
const { parentRunId, runName } = normalizeChainStartArgs(
|
|
2432
|
+
parentRunIdOrRunType,
|
|
2433
|
+
runTypeOrRunName,
|
|
2434
|
+
runNameOrParentRunId
|
|
2435
|
+
);
|
|
2436
|
+
const serialized = chain ?? {};
|
|
2437
|
+
const idArr = serialized.id;
|
|
2438
|
+
const name = runName ?? serialized.name ?? idArr?.[idArr.length - 1] ?? "chain";
|
|
2390
2439
|
this.startSpan(
|
|
2391
2440
|
runId,
|
|
2392
2441
|
parentRunId,
|
|
@@ -2421,11 +2470,12 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2421
2470
|
}
|
|
2422
2471
|
}
|
|
2423
2472
|
// ── LLM callbacks ─────────────────────────────────────────────
|
|
2424
|
-
async handleChatModelStart(llm, messages, runId, parentRunId, _extraParams, tags, metadata) {
|
|
2473
|
+
async handleChatModelStart(llm, messages, runId, parentRunId, _extraParams, tags, metadata, runName) {
|
|
2425
2474
|
try {
|
|
2426
|
-
const
|
|
2427
|
-
const
|
|
2428
|
-
const
|
|
2475
|
+
const serialized = llm ?? {};
|
|
2476
|
+
const model = extractModelName(serialized, metadata);
|
|
2477
|
+
const idArr = serialized.id;
|
|
2478
|
+
const name = runName ?? model ?? idArr?.[idArr.length - 1] ?? "llm";
|
|
2429
2479
|
const converted = messages.map((batch) => batch.map(convertMessage));
|
|
2430
2480
|
const spanInfo = this.startSpan(
|
|
2431
2481
|
runId,
|
|
@@ -2440,11 +2490,12 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2440
2490
|
} catch {
|
|
2441
2491
|
}
|
|
2442
2492
|
}
|
|
2443
|
-
async handleLLMStart(llm, prompts, runId, parentRunId, _extraParams, tags, metadata) {
|
|
2493
|
+
async handleLLMStart(llm, prompts, runId, parentRunId, _extraParams, tags, metadata, runName) {
|
|
2444
2494
|
try {
|
|
2445
|
-
const
|
|
2446
|
-
const
|
|
2447
|
-
const
|
|
2495
|
+
const serialized = llm ?? {};
|
|
2496
|
+
const model = extractModelName(serialized, metadata);
|
|
2497
|
+
const idArr = serialized.id;
|
|
2498
|
+
const name = runName ?? model ?? idArr?.[idArr.length - 1] ?? "llm";
|
|
2448
2499
|
const spanInfo = this.startSpan(
|
|
2449
2500
|
runId,
|
|
2450
2501
|
parentRunId,
|
|
@@ -2497,9 +2548,10 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2497
2548
|
async handleLLMNewToken() {
|
|
2498
2549
|
}
|
|
2499
2550
|
// ── tool callbacks ────────────────────────────────────────────
|
|
2500
|
-
async handleToolStart(tool, input, runId, parentRunId, tags, metadata) {
|
|
2551
|
+
async handleToolStart(tool, input, runId, parentRunId, tags, metadata, runName) {
|
|
2501
2552
|
try {
|
|
2502
|
-
const
|
|
2553
|
+
const serialized = tool ?? {};
|
|
2554
|
+
const name = runName ?? serialized.name ?? "tool";
|
|
2503
2555
|
this.startSpan(
|
|
2504
2556
|
runId,
|
|
2505
2557
|
parentRunId,
|
|
@@ -2529,9 +2581,10 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2529
2581
|
}
|
|
2530
2582
|
}
|
|
2531
2583
|
// ── retriever callbacks ───────────────────────────────────────
|
|
2532
|
-
async handleRetrieverStart(retriever, query, runId, parentRunId, tags, metadata) {
|
|
2584
|
+
async handleRetrieverStart(retriever, query, runId, parentRunId, tags, metadata, runName) {
|
|
2533
2585
|
try {
|
|
2534
|
-
const
|
|
2586
|
+
const serialized = retriever ?? {};
|
|
2587
|
+
const name = runName ?? serialized.name ?? "retriever";
|
|
2535
2588
|
this.startSpan(
|
|
2536
2589
|
runId,
|
|
2537
2590
|
parentRunId,
|
|
@@ -3329,6 +3382,12 @@ function getCurrentTrace() {
|
|
|
3329
3382
|
}
|
|
3330
3383
|
};
|
|
3331
3384
|
}
|
|
3385
|
+
function readEnv(name) {
|
|
3386
|
+
if (typeof process !== "undefined" && process.env) {
|
|
3387
|
+
return process.env[name];
|
|
3388
|
+
}
|
|
3389
|
+
return void 0;
|
|
3390
|
+
}
|
|
3332
3391
|
var Bitfab = class {
|
|
3333
3392
|
/**
|
|
3334
3393
|
* Initialize the Bitfab client.
|
|
@@ -3336,30 +3395,75 @@ var Bitfab = class {
|
|
|
3336
3395
|
* @param config - Configuration options for the client
|
|
3337
3396
|
*/
|
|
3338
3397
|
constructor(config) {
|
|
3339
|
-
|
|
3398
|
+
/** Gate the empty-key warning to fire at most once. */
|
|
3399
|
+
this.apiKeyWarned = false;
|
|
3400
|
+
this.apiKeyConfig = config.apiKey;
|
|
3340
3401
|
this.serviceUrl = config.serviceUrl ?? DEFAULT_SERVICE_URL;
|
|
3341
3402
|
this.timeout = config.timeout ?? 12e4;
|
|
3342
3403
|
this.envVars = config.envVars ?? {};
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
console.warn(
|
|
3346
|
-
"Bitfab: apiKey is empty \u2014 tracing is disabled. Provide a valid API key to enable tracing."
|
|
3347
|
-
);
|
|
3348
|
-
this.enabled = false;
|
|
3349
|
-
} else {
|
|
3350
|
-
this.enabled = enabled;
|
|
3351
|
-
}
|
|
3404
|
+
this.explicitlyEnabled = config.enabled ?? true;
|
|
3405
|
+
this.strict = config.strict ?? false;
|
|
3352
3406
|
this.bamlClient = config.bamlClient ?? null;
|
|
3353
3407
|
if (config.dbSnapshot) {
|
|
3354
3408
|
validateDbSnapshotConfig(config.dbSnapshot);
|
|
3355
3409
|
}
|
|
3356
3410
|
this.dbSnapshot = config.dbSnapshot;
|
|
3357
3411
|
this.httpClient = new HttpClient({
|
|
3358
|
-
apiKey: this.
|
|
3412
|
+
apiKey: () => this.resolveApiKey(),
|
|
3359
3413
|
serviceUrl: this.serviceUrl,
|
|
3360
3414
|
timeout: this.timeout
|
|
3361
3415
|
});
|
|
3362
3416
|
}
|
|
3417
|
+
/**
|
|
3418
|
+
* Resolve the API key lazily, the first time a span actually needs it.
|
|
3419
|
+
*
|
|
3420
|
+
* The key is intentionally NOT read at construction. In ESM, a shim that
|
|
3421
|
+
* does `new Bitfab({ apiKey: process.env.BITFAB_API_KEY })` is hoisted and
|
|
3422
|
+
* evaluated before the importing script's body runs `dotenv.config()`, so
|
|
3423
|
+
* the key would be empty at construction even though it is set moments
|
|
3424
|
+
* later. Resolving here (at first `withSpan` call / first request) reads
|
|
3425
|
+
* the key after env loading has run.
|
|
3426
|
+
*
|
|
3427
|
+
* Resolution order: the configured value (string, or function called each
|
|
3428
|
+
* time it is still unresolved), then a fallback read of `BITFAB_API_KEY`
|
|
3429
|
+
* from the environment. Once a non-empty key is found it is cached, so an
|
|
3430
|
+
* early resolve that found nothing never poisons a later one.
|
|
3431
|
+
*/
|
|
3432
|
+
resolveApiKey() {
|
|
3433
|
+
if (this.resolvedApiKey !== void 0) {
|
|
3434
|
+
return this.resolvedApiKey;
|
|
3435
|
+
}
|
|
3436
|
+
const fromConfig = typeof this.apiKeyConfig === "function" ? this.apiKeyConfig() : this.apiKeyConfig;
|
|
3437
|
+
const candidate = fromConfig && fromConfig.trim() !== "" ? fromConfig : readEnv("BITFAB_API_KEY");
|
|
3438
|
+
const key = candidate && candidate.trim() !== "" ? candidate : void 0;
|
|
3439
|
+
if (key) {
|
|
3440
|
+
this.resolvedApiKey = key;
|
|
3441
|
+
return key;
|
|
3442
|
+
}
|
|
3443
|
+
if (this.strict) {
|
|
3444
|
+
throw new BitfabError(
|
|
3445
|
+
"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`."
|
|
3446
|
+
);
|
|
3447
|
+
}
|
|
3448
|
+
if (this.explicitlyEnabled && !this.apiKeyWarned) {
|
|
3449
|
+
this.apiKeyWarned = true;
|
|
3450
|
+
console.warn(
|
|
3451
|
+
"Bitfab: apiKey is empty \u2014 tracing is disabled. Provide a valid API key to enable tracing."
|
|
3452
|
+
);
|
|
3453
|
+
}
|
|
3454
|
+
return void 0;
|
|
3455
|
+
}
|
|
3456
|
+
/**
|
|
3457
|
+
* Whether tracing should run, decided lazily at call time (not frozen at
|
|
3458
|
+
* construction). An explicit `enabled: false` short-circuits without ever
|
|
3459
|
+
* touching the key.
|
|
3460
|
+
*/
|
|
3461
|
+
isTracingEnabled() {
|
|
3462
|
+
if (!this.explicitlyEnabled) {
|
|
3463
|
+
return false;
|
|
3464
|
+
}
|
|
3465
|
+
return this.resolveApiKey() !== void 0;
|
|
3466
|
+
}
|
|
3363
3467
|
/**
|
|
3364
3468
|
* Fetch the function with its current version and BAML prompt from the server.
|
|
3365
3469
|
*
|
|
@@ -3452,7 +3556,9 @@ var Bitfab = class {
|
|
|
3452
3556
|
*/
|
|
3453
3557
|
getOpenAiTracingProcessor() {
|
|
3454
3558
|
return new BitfabOpenAITracingProcessor({
|
|
3455
|
-
|
|
3559
|
+
// Resolved at getter-call time (framework handlers are set up after env
|
|
3560
|
+
// loads); the withSpan path stays lazy via the constructor HttpClient thunk.
|
|
3561
|
+
apiKey: this.resolveApiKey(),
|
|
3456
3562
|
serviceUrl: this.serviceUrl,
|
|
3457
3563
|
getActiveSpanContext: () => {
|
|
3458
3564
|
const stack = getSpanStack();
|
|
@@ -3511,7 +3617,7 @@ var Bitfab = class {
|
|
|
3511
3617
|
*/
|
|
3512
3618
|
getLangGraphCallbackHandler(traceFunctionKey) {
|
|
3513
3619
|
return new BitfabLangGraphCallbackHandler({
|
|
3514
|
-
apiKey: this.
|
|
3620
|
+
apiKey: this.resolveApiKey(),
|
|
3515
3621
|
traceFunctionKey,
|
|
3516
3622
|
serviceUrl: this.serviceUrl,
|
|
3517
3623
|
getActiveSpanContext: () => {
|
|
@@ -3563,7 +3669,7 @@ var Bitfab = class {
|
|
|
3563
3669
|
*/
|
|
3564
3670
|
getClaudeAgentHandler(traceFunctionKey) {
|
|
3565
3671
|
return new BitfabClaudeAgentHandler({
|
|
3566
|
-
apiKey: this.
|
|
3672
|
+
apiKey: this.resolveApiKey(),
|
|
3567
3673
|
traceFunctionKey,
|
|
3568
3674
|
serviceUrl: this.serviceUrl,
|
|
3569
3675
|
getActiveSpanContext: () => {
|
|
@@ -3735,9 +3841,8 @@ var Bitfab = class {
|
|
|
3735
3841
|
* @returns A wrapped function with the same signature that creates spans for inputs and outputs
|
|
3736
3842
|
*/
|
|
3737
3843
|
withSpan(traceFunctionKey, optionsOrFn, maybeFn) {
|
|
3738
|
-
if (!this.
|
|
3739
|
-
|
|
3740
|
-
return fn2;
|
|
3844
|
+
if (!this.explicitlyEnabled) {
|
|
3845
|
+
return typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
|
|
3741
3846
|
}
|
|
3742
3847
|
const options = typeof optionsOrFn === "function" ? {} : optionsOrFn;
|
|
3743
3848
|
const fn = typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
|
|
@@ -3752,6 +3857,9 @@ var Bitfab = class {
|
|
|
3752
3857
|
}
|
|
3753
3858
|
})();
|
|
3754
3859
|
const wrappedFn = function(...args) {
|
|
3860
|
+
if (!self.isTracingEnabled()) {
|
|
3861
|
+
return fn.apply(this, args);
|
|
3862
|
+
}
|
|
3755
3863
|
if (!asyncLocalStorage && !isAsyncStorageInitDone()) {
|
|
3756
3864
|
return asyncLocalStorageReady.then(
|
|
3757
3865
|
() => wrappedFn.apply(this, args)
|
|
@@ -4012,7 +4120,7 @@ var Bitfab = class {
|
|
|
4012
4120
|
return {
|
|
4013
4121
|
traceId,
|
|
4014
4122
|
addContext: (context) => {
|
|
4015
|
-
if (!this.
|
|
4123
|
+
if (!this.isTracingEnabled()) {
|
|
4016
4124
|
return Promise.resolve();
|
|
4017
4125
|
}
|
|
4018
4126
|
if (typeof context !== "object" || context === null) {
|
|
@@ -4023,7 +4131,7 @@ var Bitfab = class {
|
|
|
4023
4131
|
});
|
|
4024
4132
|
},
|
|
4025
4133
|
setMetadata: (metadata) => {
|
|
4026
|
-
if (!this.
|
|
4134
|
+
if (!this.isTracingEnabled()) {
|
|
4027
4135
|
return Promise.resolve();
|
|
4028
4136
|
}
|
|
4029
4137
|
if (typeof metadata !== "object" || metadata === null) {
|
|
@@ -4032,7 +4140,7 @@ var Bitfab = class {
|
|
|
4032
4140
|
return this.httpClient.patchTrace(traceId, { mergeMetadata: metadata });
|
|
4033
4141
|
},
|
|
4034
4142
|
setSessionId: (sessionId) => {
|
|
4035
|
-
if (!this.
|
|
4143
|
+
if (!this.isTracingEnabled()) {
|
|
4036
4144
|
return Promise.resolve();
|
|
4037
4145
|
}
|
|
4038
4146
|
if (typeof sessionId !== "string" || sessionId.length === 0) {
|