@bitfab/sdk 0.27.2 → 0.28.1
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-DW246LVL.js → chunk-3YNAPGPA.js} +89 -27
- package/dist/chunk-3YNAPGPA.js.map +1 -0
- package/dist/{chunk-MD4XQGAF.js → chunk-FTXZWRTG.js} +10 -2
- package/dist/chunk-FTXZWRTG.js.map +1 -0
- package/dist/index.cjs +95 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +157 -85
- package/dist/index.d.ts +157 -85
- package/dist/index.js +2 -2
- package/dist/node.cjs +95 -25
- package/dist/node.cjs.map +1 -1
- package/dist/node.js +2 -2
- package/dist/{replay-J3YTYE7V.js → replay-HBOBYYR3.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-DW246LVL.js.map +0 -1
- package/dist/chunk-MD4XQGAF.js.map +0 -1
- /package/dist/{replay-J3YTYE7V.js.map → replay-HBOBYYR3.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -14,12 +14,12 @@ import {
|
|
|
14
14
|
flushTraces,
|
|
15
15
|
getCurrentSpan,
|
|
16
16
|
getCurrentTrace
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-3YNAPGPA.js";
|
|
18
18
|
import {
|
|
19
19
|
BITFAB_PROGRESS_PREFIX,
|
|
20
20
|
BitfabError,
|
|
21
21
|
reportReplayProgress
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-FTXZWRTG.js";
|
|
23
23
|
export {
|
|
24
24
|
BITFAB_PROGRESS_PREFIX,
|
|
25
25
|
Bitfab,
|
package/dist/node.cjs
CHANGED
|
@@ -536,6 +536,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options) {
|
|
|
536
536
|
}
|
|
537
537
|
try {
|
|
538
538
|
options?.onProgress?.({
|
|
539
|
+
testRunId,
|
|
539
540
|
completed,
|
|
540
541
|
total,
|
|
541
542
|
succeeded,
|
|
@@ -545,8 +546,15 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options) {
|
|
|
545
546
|
// that just settled. The item's own traceId is the new replay
|
|
546
547
|
// trace and is assigned later (below), so use the server item.
|
|
547
548
|
traceId: serverItems[index]?.traceId ?? null,
|
|
549
|
+
replayTraceId: item.traceId,
|
|
550
|
+
input: item.input,
|
|
551
|
+
result: item.result,
|
|
552
|
+
originalOutput: item.originalOutput,
|
|
548
553
|
error: item.error,
|
|
549
|
-
durationMs: item.durationMs
|
|
554
|
+
durationMs: item.durationMs,
|
|
555
|
+
tokens: item.tokens,
|
|
556
|
+
model: item.model,
|
|
557
|
+
dbSnapshotRef: item.dbSnapshotRef
|
|
550
558
|
}
|
|
551
559
|
});
|
|
552
560
|
} catch {
|
|
@@ -650,7 +658,7 @@ registerAsyncLocalStorageClass(
|
|
|
650
658
|
);
|
|
651
659
|
|
|
652
660
|
// src/version.generated.ts
|
|
653
|
-
var __version__ = "0.
|
|
661
|
+
var __version__ = "0.28.1";
|
|
654
662
|
|
|
655
663
|
// src/constants.ts
|
|
656
664
|
var DEFAULT_SERVICE_URL = "https://bitfab.ai";
|
|
@@ -809,6 +817,13 @@ var HttpClient = class {
|
|
|
809
817
|
this.serviceUrl = config.serviceUrl;
|
|
810
818
|
this.timeout = config.timeout ?? 12e4;
|
|
811
819
|
}
|
|
820
|
+
/**
|
|
821
|
+
* Resolve the API key at the moment it is needed (request time), invoking
|
|
822
|
+
* the function form if one was supplied. Never read at construction.
|
|
823
|
+
*/
|
|
824
|
+
resolveApiKey() {
|
|
825
|
+
return typeof this.apiKey === "function" ? this.apiKey() : this.apiKey;
|
|
826
|
+
}
|
|
812
827
|
/**
|
|
813
828
|
* Make an HTTP request to the Bitfab API. Defaults to POST; pass
|
|
814
829
|
* `options.method` to use a different verb (e.g. "PATCH").
|
|
@@ -839,7 +854,7 @@ var HttpClient = class {
|
|
|
839
854
|
method,
|
|
840
855
|
headers: {
|
|
841
856
|
"Content-Type": "application/json",
|
|
842
|
-
Authorization: `Bearer ${this.
|
|
857
|
+
Authorization: `Bearer ${this.resolveApiKey() ?? ""}`
|
|
843
858
|
},
|
|
844
859
|
body,
|
|
845
860
|
signal: controller.signal
|
|
@@ -1000,7 +1015,7 @@ var HttpClient = class {
|
|
|
1000
1015
|
try {
|
|
1001
1016
|
const response = await fetch(url, {
|
|
1002
1017
|
method: "GET",
|
|
1003
|
-
headers: { Authorization: `Bearer ${this.
|
|
1018
|
+
headers: { Authorization: `Bearer ${this.resolveApiKey() ?? ""}` },
|
|
1004
1019
|
signal: controller.signal
|
|
1005
1020
|
});
|
|
1006
1021
|
if (!response.ok) {
|
|
@@ -1036,7 +1051,7 @@ var HttpClient = class {
|
|
|
1036
1051
|
try {
|
|
1037
1052
|
const response = await fetch(url, {
|
|
1038
1053
|
method: "GET",
|
|
1039
|
-
headers: { Authorization: `Bearer ${this.
|
|
1054
|
+
headers: { Authorization: `Bearer ${this.resolveApiKey() ?? ""}` },
|
|
1040
1055
|
signal: controller.signal
|
|
1041
1056
|
});
|
|
1042
1057
|
if (!response.ok) {
|
|
@@ -3366,6 +3381,12 @@ function getCurrentTrace() {
|
|
|
3366
3381
|
}
|
|
3367
3382
|
};
|
|
3368
3383
|
}
|
|
3384
|
+
function readEnv(name) {
|
|
3385
|
+
if (typeof process !== "undefined" && process.env) {
|
|
3386
|
+
return process.env[name];
|
|
3387
|
+
}
|
|
3388
|
+
return void 0;
|
|
3389
|
+
}
|
|
3369
3390
|
var Bitfab = class {
|
|
3370
3391
|
/**
|
|
3371
3392
|
* Initialize the Bitfab client.
|
|
@@ -3373,30 +3394,75 @@ var Bitfab = class {
|
|
|
3373
3394
|
* @param config - Configuration options for the client
|
|
3374
3395
|
*/
|
|
3375
3396
|
constructor(config) {
|
|
3376
|
-
|
|
3397
|
+
/** Gate the empty-key warning to fire at most once. */
|
|
3398
|
+
this.apiKeyWarned = false;
|
|
3399
|
+
this.apiKeyConfig = config.apiKey;
|
|
3377
3400
|
this.serviceUrl = config.serviceUrl ?? DEFAULT_SERVICE_URL;
|
|
3378
3401
|
this.timeout = config.timeout ?? 12e4;
|
|
3379
3402
|
this.envVars = config.envVars ?? {};
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
console.warn(
|
|
3383
|
-
"Bitfab: apiKey is empty \u2014 tracing is disabled. Provide a valid API key to enable tracing."
|
|
3384
|
-
);
|
|
3385
|
-
this.enabled = false;
|
|
3386
|
-
} else {
|
|
3387
|
-
this.enabled = enabled;
|
|
3388
|
-
}
|
|
3403
|
+
this.explicitlyEnabled = config.enabled ?? true;
|
|
3404
|
+
this.strict = config.strict ?? false;
|
|
3389
3405
|
this.bamlClient = config.bamlClient ?? null;
|
|
3390
3406
|
if (config.dbSnapshot) {
|
|
3391
3407
|
validateDbSnapshotConfig(config.dbSnapshot);
|
|
3392
3408
|
}
|
|
3393
3409
|
this.dbSnapshot = config.dbSnapshot;
|
|
3394
3410
|
this.httpClient = new HttpClient({
|
|
3395
|
-
apiKey: this.
|
|
3411
|
+
apiKey: () => this.resolveApiKey(),
|
|
3396
3412
|
serviceUrl: this.serviceUrl,
|
|
3397
3413
|
timeout: this.timeout
|
|
3398
3414
|
});
|
|
3399
3415
|
}
|
|
3416
|
+
/**
|
|
3417
|
+
* Resolve the API key lazily, the first time a span actually needs it.
|
|
3418
|
+
*
|
|
3419
|
+
* The key is intentionally NOT read at construction. In ESM, a shim that
|
|
3420
|
+
* does `new Bitfab({ apiKey: process.env.BITFAB_API_KEY })` is hoisted and
|
|
3421
|
+
* evaluated before the importing script's body runs `dotenv.config()`, so
|
|
3422
|
+
* the key would be empty at construction even though it is set moments
|
|
3423
|
+
* later. Resolving here (at first `withSpan` call / first request) reads
|
|
3424
|
+
* the key after env loading has run.
|
|
3425
|
+
*
|
|
3426
|
+
* Resolution order: the configured value (string, or function called each
|
|
3427
|
+
* time it is still unresolved), then a fallback read of `BITFAB_API_KEY`
|
|
3428
|
+
* from the environment. Once a non-empty key is found it is cached, so an
|
|
3429
|
+
* early resolve that found nothing never poisons a later one.
|
|
3430
|
+
*/
|
|
3431
|
+
resolveApiKey() {
|
|
3432
|
+
if (this.resolvedApiKey !== void 0) {
|
|
3433
|
+
return this.resolvedApiKey;
|
|
3434
|
+
}
|
|
3435
|
+
const fromConfig = typeof this.apiKeyConfig === "function" ? this.apiKeyConfig() : this.apiKeyConfig;
|
|
3436
|
+
const candidate = fromConfig && fromConfig.trim() !== "" ? fromConfig : readEnv("BITFAB_API_KEY");
|
|
3437
|
+
const key = candidate && candidate.trim() !== "" ? candidate : void 0;
|
|
3438
|
+
if (key) {
|
|
3439
|
+
this.resolvedApiKey = key;
|
|
3440
|
+
return key;
|
|
3441
|
+
}
|
|
3442
|
+
if (this.strict) {
|
|
3443
|
+
throw new BitfabError(
|
|
3444
|
+
"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`."
|
|
3445
|
+
);
|
|
3446
|
+
}
|
|
3447
|
+
if (this.explicitlyEnabled && !this.apiKeyWarned) {
|
|
3448
|
+
this.apiKeyWarned = true;
|
|
3449
|
+
console.warn(
|
|
3450
|
+
"Bitfab: apiKey is empty \u2014 tracing is disabled. Provide a valid API key to enable tracing."
|
|
3451
|
+
);
|
|
3452
|
+
}
|
|
3453
|
+
return void 0;
|
|
3454
|
+
}
|
|
3455
|
+
/**
|
|
3456
|
+
* Whether tracing should run, decided lazily at call time (not frozen at
|
|
3457
|
+
* construction). An explicit `enabled: false` short-circuits without ever
|
|
3458
|
+
* touching the key.
|
|
3459
|
+
*/
|
|
3460
|
+
isTracingEnabled() {
|
|
3461
|
+
if (!this.explicitlyEnabled) {
|
|
3462
|
+
return false;
|
|
3463
|
+
}
|
|
3464
|
+
return this.resolveApiKey() !== void 0;
|
|
3465
|
+
}
|
|
3400
3466
|
/**
|
|
3401
3467
|
* Fetch the function with its current version and BAML prompt from the server.
|
|
3402
3468
|
*
|
|
@@ -3489,7 +3555,9 @@ var Bitfab = class {
|
|
|
3489
3555
|
*/
|
|
3490
3556
|
getOpenAiTracingProcessor() {
|
|
3491
3557
|
return new BitfabOpenAITracingProcessor({
|
|
3492
|
-
|
|
3558
|
+
// Resolved at getter-call time (framework handlers are set up after env
|
|
3559
|
+
// loads); the withSpan path stays lazy via the constructor HttpClient thunk.
|
|
3560
|
+
apiKey: this.resolveApiKey(),
|
|
3493
3561
|
serviceUrl: this.serviceUrl,
|
|
3494
3562
|
getActiveSpanContext: () => {
|
|
3495
3563
|
const stack = getSpanStack();
|
|
@@ -3548,7 +3616,7 @@ var Bitfab = class {
|
|
|
3548
3616
|
*/
|
|
3549
3617
|
getLangGraphCallbackHandler(traceFunctionKey) {
|
|
3550
3618
|
return new BitfabLangGraphCallbackHandler({
|
|
3551
|
-
apiKey: this.
|
|
3619
|
+
apiKey: this.resolveApiKey(),
|
|
3552
3620
|
traceFunctionKey,
|
|
3553
3621
|
serviceUrl: this.serviceUrl,
|
|
3554
3622
|
getActiveSpanContext: () => {
|
|
@@ -3600,7 +3668,7 @@ var Bitfab = class {
|
|
|
3600
3668
|
*/
|
|
3601
3669
|
getClaudeAgentHandler(traceFunctionKey) {
|
|
3602
3670
|
return new BitfabClaudeAgentHandler({
|
|
3603
|
-
apiKey: this.
|
|
3671
|
+
apiKey: this.resolveApiKey(),
|
|
3604
3672
|
traceFunctionKey,
|
|
3605
3673
|
serviceUrl: this.serviceUrl,
|
|
3606
3674
|
getActiveSpanContext: () => {
|
|
@@ -3772,9 +3840,8 @@ var Bitfab = class {
|
|
|
3772
3840
|
* @returns A wrapped function with the same signature that creates spans for inputs and outputs
|
|
3773
3841
|
*/
|
|
3774
3842
|
withSpan(traceFunctionKey, optionsOrFn, maybeFn) {
|
|
3775
|
-
if (!this.
|
|
3776
|
-
|
|
3777
|
-
return fn2;
|
|
3843
|
+
if (!this.explicitlyEnabled) {
|
|
3844
|
+
return typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
|
|
3778
3845
|
}
|
|
3779
3846
|
const options = typeof optionsOrFn === "function" ? {} : optionsOrFn;
|
|
3780
3847
|
const fn = typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
|
|
@@ -3789,6 +3856,9 @@ var Bitfab = class {
|
|
|
3789
3856
|
}
|
|
3790
3857
|
})();
|
|
3791
3858
|
const wrappedFn = function(...args) {
|
|
3859
|
+
if (!self.isTracingEnabled()) {
|
|
3860
|
+
return fn.apply(this, args);
|
|
3861
|
+
}
|
|
3792
3862
|
if (!asyncLocalStorage && !isAsyncStorageInitDone()) {
|
|
3793
3863
|
return asyncLocalStorageReady.then(
|
|
3794
3864
|
() => wrappedFn.apply(this, args)
|
|
@@ -4049,7 +4119,7 @@ var Bitfab = class {
|
|
|
4049
4119
|
return {
|
|
4050
4120
|
traceId,
|
|
4051
4121
|
addContext: (context) => {
|
|
4052
|
-
if (!this.
|
|
4122
|
+
if (!this.isTracingEnabled()) {
|
|
4053
4123
|
return Promise.resolve();
|
|
4054
4124
|
}
|
|
4055
4125
|
if (typeof context !== "object" || context === null) {
|
|
@@ -4060,7 +4130,7 @@ var Bitfab = class {
|
|
|
4060
4130
|
});
|
|
4061
4131
|
},
|
|
4062
4132
|
setMetadata: (metadata) => {
|
|
4063
|
-
if (!this.
|
|
4133
|
+
if (!this.isTracingEnabled()) {
|
|
4064
4134
|
return Promise.resolve();
|
|
4065
4135
|
}
|
|
4066
4136
|
if (typeof metadata !== "object" || metadata === null) {
|
|
@@ -4069,7 +4139,7 @@ var Bitfab = class {
|
|
|
4069
4139
|
return this.httpClient.patchTrace(traceId, { mergeMetadata: metadata });
|
|
4070
4140
|
},
|
|
4071
4141
|
setSessionId: (sessionId) => {
|
|
4072
|
-
if (!this.
|
|
4142
|
+
if (!this.isTracingEnabled()) {
|
|
4073
4143
|
return Promise.resolve();
|
|
4074
4144
|
}
|
|
4075
4145
|
if (typeof sessionId !== "string" || sessionId.length === 0) {
|