bitfab 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
|
@@ -23,12 +23,12 @@ import {
|
|
|
23
23
|
flushTraces,
|
|
24
24
|
getCurrentSpan,
|
|
25
25
|
getCurrentTrace
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-3YNAPGPA.js";
|
|
27
27
|
import {
|
|
28
28
|
BITFAB_PROGRESS_PREFIX,
|
|
29
29
|
BitfabError,
|
|
30
30
|
reportReplayProgress
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-FTXZWRTG.js";
|
|
32
32
|
export {
|
|
33
33
|
BITFAB_PROGRESS_PREFIX,
|
|
34
34
|
Bitfab,
|
package/dist/node.cjs
CHANGED
|
@@ -545,6 +545,7 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options) {
|
|
|
545
545
|
}
|
|
546
546
|
try {
|
|
547
547
|
options?.onProgress?.({
|
|
548
|
+
testRunId,
|
|
548
549
|
completed,
|
|
549
550
|
total,
|
|
550
551
|
succeeded,
|
|
@@ -554,8 +555,15 @@ async function replay(httpClient, serviceUrl, traceFunctionKey, fn, options) {
|
|
|
554
555
|
// that just settled. The item's own traceId is the new replay
|
|
555
556
|
// trace and is assigned later (below), so use the server item.
|
|
556
557
|
traceId: serverItems[index]?.traceId ?? null,
|
|
558
|
+
replayTraceId: item.traceId,
|
|
559
|
+
input: item.input,
|
|
560
|
+
result: item.result,
|
|
561
|
+
originalOutput: item.originalOutput,
|
|
557
562
|
error: item.error,
|
|
558
|
-
durationMs: item.durationMs
|
|
563
|
+
durationMs: item.durationMs,
|
|
564
|
+
tokens: item.tokens,
|
|
565
|
+
model: item.model,
|
|
566
|
+
dbSnapshotRef: item.dbSnapshotRef
|
|
559
567
|
}
|
|
560
568
|
});
|
|
561
569
|
} catch {
|
|
@@ -659,7 +667,7 @@ registerAsyncLocalStorageClass(
|
|
|
659
667
|
);
|
|
660
668
|
|
|
661
669
|
// src/version.generated.ts
|
|
662
|
-
var __version__ = "0.
|
|
670
|
+
var __version__ = "0.28.1";
|
|
663
671
|
|
|
664
672
|
// src/constants.ts
|
|
665
673
|
var DEFAULT_SERVICE_URL = "https://bitfab.ai";
|
|
@@ -818,6 +826,13 @@ var HttpClient = class {
|
|
|
818
826
|
this.serviceUrl = config.serviceUrl;
|
|
819
827
|
this.timeout = config.timeout ?? 12e4;
|
|
820
828
|
}
|
|
829
|
+
/**
|
|
830
|
+
* Resolve the API key at the moment it is needed (request time), invoking
|
|
831
|
+
* the function form if one was supplied. Never read at construction.
|
|
832
|
+
*/
|
|
833
|
+
resolveApiKey() {
|
|
834
|
+
return typeof this.apiKey === "function" ? this.apiKey() : this.apiKey;
|
|
835
|
+
}
|
|
821
836
|
/**
|
|
822
837
|
* Make an HTTP request to the Bitfab API. Defaults to POST; pass
|
|
823
838
|
* `options.method` to use a different verb (e.g. "PATCH").
|
|
@@ -848,7 +863,7 @@ var HttpClient = class {
|
|
|
848
863
|
method,
|
|
849
864
|
headers: {
|
|
850
865
|
"Content-Type": "application/json",
|
|
851
|
-
Authorization: `Bearer ${this.
|
|
866
|
+
Authorization: `Bearer ${this.resolveApiKey() ?? ""}`
|
|
852
867
|
},
|
|
853
868
|
body,
|
|
854
869
|
signal: controller.signal
|
|
@@ -1009,7 +1024,7 @@ var HttpClient = class {
|
|
|
1009
1024
|
try {
|
|
1010
1025
|
const response = await fetch(url, {
|
|
1011
1026
|
method: "GET",
|
|
1012
|
-
headers: { Authorization: `Bearer ${this.
|
|
1027
|
+
headers: { Authorization: `Bearer ${this.resolveApiKey() ?? ""}` },
|
|
1013
1028
|
signal: controller.signal
|
|
1014
1029
|
});
|
|
1015
1030
|
if (!response.ok) {
|
|
@@ -1045,7 +1060,7 @@ var HttpClient = class {
|
|
|
1045
1060
|
try {
|
|
1046
1061
|
const response = await fetch(url, {
|
|
1047
1062
|
method: "GET",
|
|
1048
|
-
headers: { Authorization: `Bearer ${this.
|
|
1063
|
+
headers: { Authorization: `Bearer ${this.resolveApiKey() ?? ""}` },
|
|
1049
1064
|
signal: controller.signal
|
|
1050
1065
|
});
|
|
1051
1066
|
if (!response.ok) {
|
|
@@ -3375,6 +3390,12 @@ function getCurrentTrace() {
|
|
|
3375
3390
|
}
|
|
3376
3391
|
};
|
|
3377
3392
|
}
|
|
3393
|
+
function readEnv(name) {
|
|
3394
|
+
if (typeof process !== "undefined" && process.env) {
|
|
3395
|
+
return process.env[name];
|
|
3396
|
+
}
|
|
3397
|
+
return void 0;
|
|
3398
|
+
}
|
|
3378
3399
|
var Bitfab = class {
|
|
3379
3400
|
/**
|
|
3380
3401
|
* Initialize the Bitfab client.
|
|
@@ -3382,30 +3403,75 @@ var Bitfab = class {
|
|
|
3382
3403
|
* @param config - Configuration options for the client
|
|
3383
3404
|
*/
|
|
3384
3405
|
constructor(config) {
|
|
3385
|
-
|
|
3406
|
+
/** Gate the empty-key warning to fire at most once. */
|
|
3407
|
+
this.apiKeyWarned = false;
|
|
3408
|
+
this.apiKeyConfig = config.apiKey;
|
|
3386
3409
|
this.serviceUrl = config.serviceUrl ?? DEFAULT_SERVICE_URL;
|
|
3387
3410
|
this.timeout = config.timeout ?? 12e4;
|
|
3388
3411
|
this.envVars = config.envVars ?? {};
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
console.warn(
|
|
3392
|
-
"Bitfab: apiKey is empty \u2014 tracing is disabled. Provide a valid API key to enable tracing."
|
|
3393
|
-
);
|
|
3394
|
-
this.enabled = false;
|
|
3395
|
-
} else {
|
|
3396
|
-
this.enabled = enabled;
|
|
3397
|
-
}
|
|
3412
|
+
this.explicitlyEnabled = config.enabled ?? true;
|
|
3413
|
+
this.strict = config.strict ?? false;
|
|
3398
3414
|
this.bamlClient = config.bamlClient ?? null;
|
|
3399
3415
|
if (config.dbSnapshot) {
|
|
3400
3416
|
validateDbSnapshotConfig(config.dbSnapshot);
|
|
3401
3417
|
}
|
|
3402
3418
|
this.dbSnapshot = config.dbSnapshot;
|
|
3403
3419
|
this.httpClient = new HttpClient({
|
|
3404
|
-
apiKey: this.
|
|
3420
|
+
apiKey: () => this.resolveApiKey(),
|
|
3405
3421
|
serviceUrl: this.serviceUrl,
|
|
3406
3422
|
timeout: this.timeout
|
|
3407
3423
|
});
|
|
3408
3424
|
}
|
|
3425
|
+
/**
|
|
3426
|
+
* Resolve the API key lazily, the first time a span actually needs it.
|
|
3427
|
+
*
|
|
3428
|
+
* The key is intentionally NOT read at construction. In ESM, a shim that
|
|
3429
|
+
* does `new Bitfab({ apiKey: process.env.BITFAB_API_KEY })` is hoisted and
|
|
3430
|
+
* evaluated before the importing script's body runs `dotenv.config()`, so
|
|
3431
|
+
* the key would be empty at construction even though it is set moments
|
|
3432
|
+
* later. Resolving here (at first `withSpan` call / first request) reads
|
|
3433
|
+
* the key after env loading has run.
|
|
3434
|
+
*
|
|
3435
|
+
* Resolution order: the configured value (string, or function called each
|
|
3436
|
+
* time it is still unresolved), then a fallback read of `BITFAB_API_KEY`
|
|
3437
|
+
* from the environment. Once a non-empty key is found it is cached, so an
|
|
3438
|
+
* early resolve that found nothing never poisons a later one.
|
|
3439
|
+
*/
|
|
3440
|
+
resolveApiKey() {
|
|
3441
|
+
if (this.resolvedApiKey !== void 0) {
|
|
3442
|
+
return this.resolvedApiKey;
|
|
3443
|
+
}
|
|
3444
|
+
const fromConfig = typeof this.apiKeyConfig === "function" ? this.apiKeyConfig() : this.apiKeyConfig;
|
|
3445
|
+
const candidate = fromConfig && fromConfig.trim() !== "" ? fromConfig : readEnv("BITFAB_API_KEY");
|
|
3446
|
+
const key = candidate && candidate.trim() !== "" ? candidate : void 0;
|
|
3447
|
+
if (key) {
|
|
3448
|
+
this.resolvedApiKey = key;
|
|
3449
|
+
return key;
|
|
3450
|
+
}
|
|
3451
|
+
if (this.strict) {
|
|
3452
|
+
throw new BitfabError(
|
|
3453
|
+
"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`."
|
|
3454
|
+
);
|
|
3455
|
+
}
|
|
3456
|
+
if (this.explicitlyEnabled && !this.apiKeyWarned) {
|
|
3457
|
+
this.apiKeyWarned = true;
|
|
3458
|
+
console.warn(
|
|
3459
|
+
"Bitfab: apiKey is empty \u2014 tracing is disabled. Provide a valid API key to enable tracing."
|
|
3460
|
+
);
|
|
3461
|
+
}
|
|
3462
|
+
return void 0;
|
|
3463
|
+
}
|
|
3464
|
+
/**
|
|
3465
|
+
* Whether tracing should run, decided lazily at call time (not frozen at
|
|
3466
|
+
* construction). An explicit `enabled: false` short-circuits without ever
|
|
3467
|
+
* touching the key.
|
|
3468
|
+
*/
|
|
3469
|
+
isTracingEnabled() {
|
|
3470
|
+
if (!this.explicitlyEnabled) {
|
|
3471
|
+
return false;
|
|
3472
|
+
}
|
|
3473
|
+
return this.resolveApiKey() !== void 0;
|
|
3474
|
+
}
|
|
3409
3475
|
/**
|
|
3410
3476
|
* Fetch the function with its current version and BAML prompt from the server.
|
|
3411
3477
|
*
|
|
@@ -3498,7 +3564,9 @@ var Bitfab = class {
|
|
|
3498
3564
|
*/
|
|
3499
3565
|
getOpenAiTracingProcessor() {
|
|
3500
3566
|
return new BitfabOpenAITracingProcessor({
|
|
3501
|
-
|
|
3567
|
+
// Resolved at getter-call time (framework handlers are set up after env
|
|
3568
|
+
// loads); the withSpan path stays lazy via the constructor HttpClient thunk.
|
|
3569
|
+
apiKey: this.resolveApiKey(),
|
|
3502
3570
|
serviceUrl: this.serviceUrl,
|
|
3503
3571
|
getActiveSpanContext: () => {
|
|
3504
3572
|
const stack = getSpanStack();
|
|
@@ -3557,7 +3625,7 @@ var Bitfab = class {
|
|
|
3557
3625
|
*/
|
|
3558
3626
|
getLangGraphCallbackHandler(traceFunctionKey) {
|
|
3559
3627
|
return new BitfabLangGraphCallbackHandler({
|
|
3560
|
-
apiKey: this.
|
|
3628
|
+
apiKey: this.resolveApiKey(),
|
|
3561
3629
|
traceFunctionKey,
|
|
3562
3630
|
serviceUrl: this.serviceUrl,
|
|
3563
3631
|
getActiveSpanContext: () => {
|
|
@@ -3609,7 +3677,7 @@ var Bitfab = class {
|
|
|
3609
3677
|
*/
|
|
3610
3678
|
getClaudeAgentHandler(traceFunctionKey) {
|
|
3611
3679
|
return new BitfabClaudeAgentHandler({
|
|
3612
|
-
apiKey: this.
|
|
3680
|
+
apiKey: this.resolveApiKey(),
|
|
3613
3681
|
traceFunctionKey,
|
|
3614
3682
|
serviceUrl: this.serviceUrl,
|
|
3615
3683
|
getActiveSpanContext: () => {
|
|
@@ -3781,9 +3849,8 @@ var Bitfab = class {
|
|
|
3781
3849
|
* @returns A wrapped function with the same signature that creates spans for inputs and outputs
|
|
3782
3850
|
*/
|
|
3783
3851
|
withSpan(traceFunctionKey, optionsOrFn, maybeFn) {
|
|
3784
|
-
if (!this.
|
|
3785
|
-
|
|
3786
|
-
return fn2;
|
|
3852
|
+
if (!this.explicitlyEnabled) {
|
|
3853
|
+
return typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
|
|
3787
3854
|
}
|
|
3788
3855
|
const options = typeof optionsOrFn === "function" ? {} : optionsOrFn;
|
|
3789
3856
|
const fn = typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
|
|
@@ -3798,6 +3865,9 @@ var Bitfab = class {
|
|
|
3798
3865
|
}
|
|
3799
3866
|
})();
|
|
3800
3867
|
const wrappedFn = function(...args) {
|
|
3868
|
+
if (!self.isTracingEnabled()) {
|
|
3869
|
+
return fn.apply(this, args);
|
|
3870
|
+
}
|
|
3801
3871
|
if (!asyncLocalStorage && !isAsyncStorageInitDone()) {
|
|
3802
3872
|
return asyncLocalStorageReady.then(
|
|
3803
3873
|
() => wrappedFn.apply(this, args)
|
|
@@ -4058,7 +4128,7 @@ var Bitfab = class {
|
|
|
4058
4128
|
return {
|
|
4059
4129
|
traceId,
|
|
4060
4130
|
addContext: (context) => {
|
|
4061
|
-
if (!this.
|
|
4131
|
+
if (!this.isTracingEnabled()) {
|
|
4062
4132
|
return Promise.resolve();
|
|
4063
4133
|
}
|
|
4064
4134
|
if (typeof context !== "object" || context === null) {
|
|
@@ -4069,7 +4139,7 @@ var Bitfab = class {
|
|
|
4069
4139
|
});
|
|
4070
4140
|
},
|
|
4071
4141
|
setMetadata: (metadata) => {
|
|
4072
|
-
if (!this.
|
|
4142
|
+
if (!this.isTracingEnabled()) {
|
|
4073
4143
|
return Promise.resolve();
|
|
4074
4144
|
}
|
|
4075
4145
|
if (typeof metadata !== "object" || metadata === null) {
|
|
@@ -4078,7 +4148,7 @@ var Bitfab = class {
|
|
|
4078
4148
|
return this.httpClient.patchTrace(traceId, { mergeMetadata: metadata });
|
|
4079
4149
|
},
|
|
4080
4150
|
setSessionId: (sessionId) => {
|
|
4081
|
-
if (!this.
|
|
4151
|
+
if (!this.isTracingEnabled()) {
|
|
4082
4152
|
return Promise.resolve();
|
|
4083
4153
|
}
|
|
4084
4154
|
if (typeof sessionId !== "string" || sessionId.length === 0) {
|