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.cjs
CHANGED
|
@@ -645,7 +645,7 @@ __export(index_exports, {
|
|
|
645
645
|
module.exports = __toCommonJS(index_exports);
|
|
646
646
|
|
|
647
647
|
// src/version.generated.ts
|
|
648
|
-
var __version__ = "0.
|
|
648
|
+
var __version__ = "0.28.0";
|
|
649
649
|
|
|
650
650
|
// src/constants.ts
|
|
651
651
|
var DEFAULT_SERVICE_URL = "https://bitfab.ai";
|
|
@@ -804,6 +804,13 @@ var HttpClient = class {
|
|
|
804
804
|
this.serviceUrl = config.serviceUrl;
|
|
805
805
|
this.timeout = config.timeout ?? 12e4;
|
|
806
806
|
}
|
|
807
|
+
/**
|
|
808
|
+
* Resolve the API key at the moment it is needed (request time), invoking
|
|
809
|
+
* the function form if one was supplied. Never read at construction.
|
|
810
|
+
*/
|
|
811
|
+
resolveApiKey() {
|
|
812
|
+
return typeof this.apiKey === "function" ? this.apiKey() : this.apiKey;
|
|
813
|
+
}
|
|
807
814
|
/**
|
|
808
815
|
* Make an HTTP request to the Bitfab API. Defaults to POST; pass
|
|
809
816
|
* `options.method` to use a different verb (e.g. "PATCH").
|
|
@@ -834,7 +841,7 @@ var HttpClient = class {
|
|
|
834
841
|
method,
|
|
835
842
|
headers: {
|
|
836
843
|
"Content-Type": "application/json",
|
|
837
|
-
Authorization: `Bearer ${this.
|
|
844
|
+
Authorization: `Bearer ${this.resolveApiKey() ?? ""}`
|
|
838
845
|
},
|
|
839
846
|
body,
|
|
840
847
|
signal: controller.signal
|
|
@@ -995,7 +1002,7 @@ var HttpClient = class {
|
|
|
995
1002
|
try {
|
|
996
1003
|
const response = await fetch(url, {
|
|
997
1004
|
method: "GET",
|
|
998
|
-
headers: { Authorization: `Bearer ${this.
|
|
1005
|
+
headers: { Authorization: `Bearer ${this.resolveApiKey() ?? ""}` },
|
|
999
1006
|
signal: controller.signal
|
|
1000
1007
|
});
|
|
1001
1008
|
if (!response.ok) {
|
|
@@ -1031,7 +1038,7 @@ var HttpClient = class {
|
|
|
1031
1038
|
try {
|
|
1032
1039
|
const response = await fetch(url, {
|
|
1033
1040
|
method: "GET",
|
|
1034
|
-
headers: { Authorization: `Bearer ${this.
|
|
1041
|
+
headers: { Authorization: `Bearer ${this.resolveApiKey() ?? ""}` },
|
|
1035
1042
|
signal: controller.signal
|
|
1036
1043
|
});
|
|
1037
1044
|
if (!response.ok) {
|
|
@@ -2005,6 +2012,7 @@ function buildSnapshotRef(config, sdkWallClockBeforeFn) {
|
|
|
2005
2012
|
init_randomUuid();
|
|
2006
2013
|
init_serialize();
|
|
2007
2014
|
var LANGSMITH_HIDDEN_TAG = "langsmith:hidden";
|
|
2015
|
+
var CHAIN_RUN_TYPES = /* @__PURE__ */ new Set(["chain", "parser", "prompt"]);
|
|
2008
2016
|
var LANGGRAPH_METADATA_KEYS = [
|
|
2009
2017
|
"langgraph_step",
|
|
2010
2018
|
"langgraph_node",
|
|
@@ -2015,6 +2023,18 @@ var LANGGRAPH_METADATA_KEYS = [
|
|
|
2015
2023
|
function nowIso2() {
|
|
2016
2024
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
2017
2025
|
}
|
|
2026
|
+
function normalizeChainStartArgs(parentRunIdOrRunType, runTypeOrRunName, runNameOrParentRunId) {
|
|
2027
|
+
if (parentRunIdOrRunType && CHAIN_RUN_TYPES.has(parentRunIdOrRunType)) {
|
|
2028
|
+
return {
|
|
2029
|
+
parentRunId: runNameOrParentRunId,
|
|
2030
|
+
runName: runTypeOrRunName
|
|
2031
|
+
};
|
|
2032
|
+
}
|
|
2033
|
+
return {
|
|
2034
|
+
parentRunId: parentRunIdOrRunType,
|
|
2035
|
+
runName: runNameOrParentRunId
|
|
2036
|
+
};
|
|
2037
|
+
}
|
|
2018
2038
|
function convertMessage(message) {
|
|
2019
2039
|
if (typeof message !== "object" || message === null) {
|
|
2020
2040
|
return { role: "unknown", content: String(message) };
|
|
@@ -2226,6 +2246,7 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2226
2246
|
const willHide = tags?.includes(LANGSMITH_HIDDEN_TAG) === true;
|
|
2227
2247
|
let invocation;
|
|
2228
2248
|
let effectiveParentId;
|
|
2249
|
+
let isRootInvocation = false;
|
|
2229
2250
|
if (parentSpan) {
|
|
2230
2251
|
const existing = this.invocations.get(parentSpan.rootRunId);
|
|
2231
2252
|
if (existing) {
|
|
@@ -2256,6 +2277,7 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2256
2277
|
};
|
|
2257
2278
|
this.invocations.set(runId, invocation);
|
|
2258
2279
|
effectiveParentId = activeContext?.spanId ?? null;
|
|
2280
|
+
isRootInvocation = true;
|
|
2259
2281
|
}
|
|
2260
2282
|
const lgMetadata = extractLangGraphMetadata(metadata);
|
|
2261
2283
|
const contexts = Object.keys(lgMetadata).length > 0 ? [lgMetadata] : [];
|
|
@@ -2278,6 +2300,9 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2278
2300
|
spanInfo.hidden = true;
|
|
2279
2301
|
}
|
|
2280
2302
|
this.runToSpan.set(runId, spanInfo);
|
|
2303
|
+
if (isRootInvocation) {
|
|
2304
|
+
this.sendTraceStart(spanInfo);
|
|
2305
|
+
}
|
|
2281
2306
|
return spanInfo;
|
|
2282
2307
|
}
|
|
2283
2308
|
completeSpan(runId, output, error, extraContexts) {
|
|
@@ -2368,11 +2393,35 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2368
2393
|
} catch {
|
|
2369
2394
|
}
|
|
2370
2395
|
}
|
|
2396
|
+
sendTraceStart(rootSpan) {
|
|
2397
|
+
const traceData = {
|
|
2398
|
+
type: "sdk-function",
|
|
2399
|
+
source: "typescript-sdk-langgraph",
|
|
2400
|
+
traceFunctionKey: this.traceFunctionKey,
|
|
2401
|
+
externalTrace: {
|
|
2402
|
+
id: rootSpan.traceId,
|
|
2403
|
+
started_at: rootSpan.startedAt,
|
|
2404
|
+
workflow_name: this.traceFunctionKey
|
|
2405
|
+
},
|
|
2406
|
+
completed: false
|
|
2407
|
+
};
|
|
2408
|
+
const finalized = finalizeTracePayload(traceData);
|
|
2409
|
+
try {
|
|
2410
|
+
this.httpClient.sendExternalTrace(finalized);
|
|
2411
|
+
} catch {
|
|
2412
|
+
}
|
|
2413
|
+
}
|
|
2371
2414
|
// ── chain callbacks (graph nodes) ─────────────────────────────
|
|
2372
|
-
async handleChainStart(chain, inputs, runId,
|
|
2415
|
+
async handleChainStart(chain, inputs, runId, parentRunIdOrRunType, tags, metadata, runTypeOrRunName, runNameOrParentRunId) {
|
|
2373
2416
|
try {
|
|
2374
|
-
const
|
|
2375
|
-
|
|
2417
|
+
const { parentRunId, runName } = normalizeChainStartArgs(
|
|
2418
|
+
parentRunIdOrRunType,
|
|
2419
|
+
runTypeOrRunName,
|
|
2420
|
+
runNameOrParentRunId
|
|
2421
|
+
);
|
|
2422
|
+
const serialized = chain ?? {};
|
|
2423
|
+
const idArr = serialized.id;
|
|
2424
|
+
const name = runName ?? serialized.name ?? idArr?.[idArr.length - 1] ?? "chain";
|
|
2376
2425
|
this.startSpan(
|
|
2377
2426
|
runId,
|
|
2378
2427
|
parentRunId,
|
|
@@ -2407,11 +2456,12 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2407
2456
|
}
|
|
2408
2457
|
}
|
|
2409
2458
|
// ── LLM callbacks ─────────────────────────────────────────────
|
|
2410
|
-
async handleChatModelStart(llm, messages, runId, parentRunId, _extraParams, tags, metadata) {
|
|
2459
|
+
async handleChatModelStart(llm, messages, runId, parentRunId, _extraParams, tags, metadata, runName) {
|
|
2411
2460
|
try {
|
|
2412
|
-
const
|
|
2413
|
-
const
|
|
2414
|
-
const
|
|
2461
|
+
const serialized = llm ?? {};
|
|
2462
|
+
const model = extractModelName(serialized, metadata);
|
|
2463
|
+
const idArr = serialized.id;
|
|
2464
|
+
const name = runName ?? model ?? idArr?.[idArr.length - 1] ?? "llm";
|
|
2415
2465
|
const converted = messages.map((batch) => batch.map(convertMessage));
|
|
2416
2466
|
const spanInfo = this.startSpan(
|
|
2417
2467
|
runId,
|
|
@@ -2426,11 +2476,12 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2426
2476
|
} catch {
|
|
2427
2477
|
}
|
|
2428
2478
|
}
|
|
2429
|
-
async handleLLMStart(llm, prompts, runId, parentRunId, _extraParams, tags, metadata) {
|
|
2479
|
+
async handleLLMStart(llm, prompts, runId, parentRunId, _extraParams, tags, metadata, runName) {
|
|
2430
2480
|
try {
|
|
2431
|
-
const
|
|
2432
|
-
const
|
|
2433
|
-
const
|
|
2481
|
+
const serialized = llm ?? {};
|
|
2482
|
+
const model = extractModelName(serialized, metadata);
|
|
2483
|
+
const idArr = serialized.id;
|
|
2484
|
+
const name = runName ?? model ?? idArr?.[idArr.length - 1] ?? "llm";
|
|
2434
2485
|
const spanInfo = this.startSpan(
|
|
2435
2486
|
runId,
|
|
2436
2487
|
parentRunId,
|
|
@@ -2483,9 +2534,10 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2483
2534
|
async handleLLMNewToken() {
|
|
2484
2535
|
}
|
|
2485
2536
|
// ── tool callbacks ────────────────────────────────────────────
|
|
2486
|
-
async handleToolStart(tool, input, runId, parentRunId, tags, metadata) {
|
|
2537
|
+
async handleToolStart(tool, input, runId, parentRunId, tags, metadata, runName) {
|
|
2487
2538
|
try {
|
|
2488
|
-
const
|
|
2539
|
+
const serialized = tool ?? {};
|
|
2540
|
+
const name = runName ?? serialized.name ?? "tool";
|
|
2489
2541
|
this.startSpan(
|
|
2490
2542
|
runId,
|
|
2491
2543
|
parentRunId,
|
|
@@ -2515,9 +2567,10 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2515
2567
|
}
|
|
2516
2568
|
}
|
|
2517
2569
|
// ── retriever callbacks ───────────────────────────────────────
|
|
2518
|
-
async handleRetrieverStart(retriever, query, runId, parentRunId, tags, metadata) {
|
|
2570
|
+
async handleRetrieverStart(retriever, query, runId, parentRunId, tags, metadata, runName) {
|
|
2519
2571
|
try {
|
|
2520
|
-
const
|
|
2572
|
+
const serialized = retriever ?? {};
|
|
2573
|
+
const name = runName ?? serialized.name ?? "retriever";
|
|
2521
2574
|
this.startSpan(
|
|
2522
2575
|
runId,
|
|
2523
2576
|
parentRunId,
|
|
@@ -3315,6 +3368,12 @@ function getCurrentTrace() {
|
|
|
3315
3368
|
}
|
|
3316
3369
|
};
|
|
3317
3370
|
}
|
|
3371
|
+
function readEnv(name) {
|
|
3372
|
+
if (typeof process !== "undefined" && process.env) {
|
|
3373
|
+
return process.env[name];
|
|
3374
|
+
}
|
|
3375
|
+
return void 0;
|
|
3376
|
+
}
|
|
3318
3377
|
var Bitfab = class {
|
|
3319
3378
|
/**
|
|
3320
3379
|
* Initialize the Bitfab client.
|
|
@@ -3322,30 +3381,75 @@ var Bitfab = class {
|
|
|
3322
3381
|
* @param config - Configuration options for the client
|
|
3323
3382
|
*/
|
|
3324
3383
|
constructor(config) {
|
|
3325
|
-
|
|
3384
|
+
/** Gate the empty-key warning to fire at most once. */
|
|
3385
|
+
this.apiKeyWarned = false;
|
|
3386
|
+
this.apiKeyConfig = config.apiKey;
|
|
3326
3387
|
this.serviceUrl = config.serviceUrl ?? DEFAULT_SERVICE_URL;
|
|
3327
3388
|
this.timeout = config.timeout ?? 12e4;
|
|
3328
3389
|
this.envVars = config.envVars ?? {};
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
console.warn(
|
|
3332
|
-
"Bitfab: apiKey is empty \u2014 tracing is disabled. Provide a valid API key to enable tracing."
|
|
3333
|
-
);
|
|
3334
|
-
this.enabled = false;
|
|
3335
|
-
} else {
|
|
3336
|
-
this.enabled = enabled;
|
|
3337
|
-
}
|
|
3390
|
+
this.explicitlyEnabled = config.enabled ?? true;
|
|
3391
|
+
this.strict = config.strict ?? false;
|
|
3338
3392
|
this.bamlClient = config.bamlClient ?? null;
|
|
3339
3393
|
if (config.dbSnapshot) {
|
|
3340
3394
|
validateDbSnapshotConfig(config.dbSnapshot);
|
|
3341
3395
|
}
|
|
3342
3396
|
this.dbSnapshot = config.dbSnapshot;
|
|
3343
3397
|
this.httpClient = new HttpClient({
|
|
3344
|
-
apiKey: this.
|
|
3398
|
+
apiKey: () => this.resolveApiKey(),
|
|
3345
3399
|
serviceUrl: this.serviceUrl,
|
|
3346
3400
|
timeout: this.timeout
|
|
3347
3401
|
});
|
|
3348
3402
|
}
|
|
3403
|
+
/**
|
|
3404
|
+
* Resolve the API key lazily, the first time a span actually needs it.
|
|
3405
|
+
*
|
|
3406
|
+
* The key is intentionally NOT read at construction. In ESM, a shim that
|
|
3407
|
+
* does `new Bitfab({ apiKey: process.env.BITFAB_API_KEY })` is hoisted and
|
|
3408
|
+
* evaluated before the importing script's body runs `dotenv.config()`, so
|
|
3409
|
+
* the key would be empty at construction even though it is set moments
|
|
3410
|
+
* later. Resolving here (at first `withSpan` call / first request) reads
|
|
3411
|
+
* the key after env loading has run.
|
|
3412
|
+
*
|
|
3413
|
+
* Resolution order: the configured value (string, or function called each
|
|
3414
|
+
* time it is still unresolved), then a fallback read of `BITFAB_API_KEY`
|
|
3415
|
+
* from the environment. Once a non-empty key is found it is cached, so an
|
|
3416
|
+
* early resolve that found nothing never poisons a later one.
|
|
3417
|
+
*/
|
|
3418
|
+
resolveApiKey() {
|
|
3419
|
+
if (this.resolvedApiKey !== void 0) {
|
|
3420
|
+
return this.resolvedApiKey;
|
|
3421
|
+
}
|
|
3422
|
+
const fromConfig = typeof this.apiKeyConfig === "function" ? this.apiKeyConfig() : this.apiKeyConfig;
|
|
3423
|
+
const candidate = fromConfig && fromConfig.trim() !== "" ? fromConfig : readEnv("BITFAB_API_KEY");
|
|
3424
|
+
const key = candidate && candidate.trim() !== "" ? candidate : void 0;
|
|
3425
|
+
if (key) {
|
|
3426
|
+
this.resolvedApiKey = key;
|
|
3427
|
+
return key;
|
|
3428
|
+
}
|
|
3429
|
+
if (this.strict) {
|
|
3430
|
+
throw new BitfabError(
|
|
3431
|
+
"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`."
|
|
3432
|
+
);
|
|
3433
|
+
}
|
|
3434
|
+
if (this.explicitlyEnabled && !this.apiKeyWarned) {
|
|
3435
|
+
this.apiKeyWarned = true;
|
|
3436
|
+
console.warn(
|
|
3437
|
+
"Bitfab: apiKey is empty \u2014 tracing is disabled. Provide a valid API key to enable tracing."
|
|
3438
|
+
);
|
|
3439
|
+
}
|
|
3440
|
+
return void 0;
|
|
3441
|
+
}
|
|
3442
|
+
/**
|
|
3443
|
+
* Whether tracing should run, decided lazily at call time (not frozen at
|
|
3444
|
+
* construction). An explicit `enabled: false` short-circuits without ever
|
|
3445
|
+
* touching the key.
|
|
3446
|
+
*/
|
|
3447
|
+
isTracingEnabled() {
|
|
3448
|
+
if (!this.explicitlyEnabled) {
|
|
3449
|
+
return false;
|
|
3450
|
+
}
|
|
3451
|
+
return this.resolveApiKey() !== void 0;
|
|
3452
|
+
}
|
|
3349
3453
|
/**
|
|
3350
3454
|
* Fetch the function with its current version and BAML prompt from the server.
|
|
3351
3455
|
*
|
|
@@ -3438,7 +3542,9 @@ var Bitfab = class {
|
|
|
3438
3542
|
*/
|
|
3439
3543
|
getOpenAiTracingProcessor() {
|
|
3440
3544
|
return new BitfabOpenAITracingProcessor({
|
|
3441
|
-
|
|
3545
|
+
// Resolved at getter-call time (framework handlers are set up after env
|
|
3546
|
+
// loads); the withSpan path stays lazy via the constructor HttpClient thunk.
|
|
3547
|
+
apiKey: this.resolveApiKey(),
|
|
3442
3548
|
serviceUrl: this.serviceUrl,
|
|
3443
3549
|
getActiveSpanContext: () => {
|
|
3444
3550
|
const stack = getSpanStack();
|
|
@@ -3497,7 +3603,7 @@ var Bitfab = class {
|
|
|
3497
3603
|
*/
|
|
3498
3604
|
getLangGraphCallbackHandler(traceFunctionKey) {
|
|
3499
3605
|
return new BitfabLangGraphCallbackHandler({
|
|
3500
|
-
apiKey: this.
|
|
3606
|
+
apiKey: this.resolveApiKey(),
|
|
3501
3607
|
traceFunctionKey,
|
|
3502
3608
|
serviceUrl: this.serviceUrl,
|
|
3503
3609
|
getActiveSpanContext: () => {
|
|
@@ -3549,7 +3655,7 @@ var Bitfab = class {
|
|
|
3549
3655
|
*/
|
|
3550
3656
|
getClaudeAgentHandler(traceFunctionKey) {
|
|
3551
3657
|
return new BitfabClaudeAgentHandler({
|
|
3552
|
-
apiKey: this.
|
|
3658
|
+
apiKey: this.resolveApiKey(),
|
|
3553
3659
|
traceFunctionKey,
|
|
3554
3660
|
serviceUrl: this.serviceUrl,
|
|
3555
3661
|
getActiveSpanContext: () => {
|
|
@@ -3721,9 +3827,8 @@ var Bitfab = class {
|
|
|
3721
3827
|
* @returns A wrapped function with the same signature that creates spans for inputs and outputs
|
|
3722
3828
|
*/
|
|
3723
3829
|
withSpan(traceFunctionKey, optionsOrFn, maybeFn) {
|
|
3724
|
-
if (!this.
|
|
3725
|
-
|
|
3726
|
-
return fn2;
|
|
3830
|
+
if (!this.explicitlyEnabled) {
|
|
3831
|
+
return typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
|
|
3727
3832
|
}
|
|
3728
3833
|
const options = typeof optionsOrFn === "function" ? {} : optionsOrFn;
|
|
3729
3834
|
const fn = typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
|
|
@@ -3738,6 +3843,9 @@ var Bitfab = class {
|
|
|
3738
3843
|
}
|
|
3739
3844
|
})();
|
|
3740
3845
|
const wrappedFn = function(...args) {
|
|
3846
|
+
if (!self.isTracingEnabled()) {
|
|
3847
|
+
return fn.apply(this, args);
|
|
3848
|
+
}
|
|
3741
3849
|
if (!asyncLocalStorage && !isAsyncStorageInitDone()) {
|
|
3742
3850
|
return asyncLocalStorageReady.then(
|
|
3743
3851
|
() => wrappedFn.apply(this, args)
|
|
@@ -3998,7 +4106,7 @@ var Bitfab = class {
|
|
|
3998
4106
|
return {
|
|
3999
4107
|
traceId,
|
|
4000
4108
|
addContext: (context) => {
|
|
4001
|
-
if (!this.
|
|
4109
|
+
if (!this.isTracingEnabled()) {
|
|
4002
4110
|
return Promise.resolve();
|
|
4003
4111
|
}
|
|
4004
4112
|
if (typeof context !== "object" || context === null) {
|
|
@@ -4009,7 +4117,7 @@ var Bitfab = class {
|
|
|
4009
4117
|
});
|
|
4010
4118
|
},
|
|
4011
4119
|
setMetadata: (metadata) => {
|
|
4012
|
-
if (!this.
|
|
4120
|
+
if (!this.isTracingEnabled()) {
|
|
4013
4121
|
return Promise.resolve();
|
|
4014
4122
|
}
|
|
4015
4123
|
if (typeof metadata !== "object" || metadata === null) {
|
|
@@ -4018,7 +4126,7 @@ var Bitfab = class {
|
|
|
4018
4126
|
return this.httpClient.patchTrace(traceId, { mergeMetadata: metadata });
|
|
4019
4127
|
},
|
|
4020
4128
|
setSessionId: (sessionId) => {
|
|
4021
|
-
if (!this.
|
|
4129
|
+
if (!this.isTracingEnabled()) {
|
|
4022
4130
|
return Promise.resolve();
|
|
4023
4131
|
}
|
|
4024
4132
|
if (typeof sessionId !== "string" || sessionId.length === 0) {
|