bitfab 0.17.0 → 0.18.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-M6N633CX.js → chunk-ILIUTS5D.js} +147 -17
- package/dist/chunk-ILIUTS5D.js.map +1 -0
- package/dist/index.cjs +146 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -7
- package/dist/index.d.ts +11 -7
- package/dist/index.js +1 -1
- package/dist/node.cjs +146 -16
- package/dist/node.cjs.map +1 -1
- package/dist/node.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-M6N633CX.js.map +0 -1
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from "./chunk-QT7HWOKU.js";
|
|
10
10
|
|
|
11
11
|
// src/version.generated.ts
|
|
12
|
-
var __version__ = "0.
|
|
12
|
+
var __version__ = "0.18.1";
|
|
13
13
|
|
|
14
14
|
// src/constants.ts
|
|
15
15
|
var DEFAULT_SERVICE_URL = "https://bitfab.ai";
|
|
@@ -1234,21 +1234,131 @@ function extractModelName(serialized, metadata) {
|
|
|
1234
1234
|
}
|
|
1235
1235
|
return void 0;
|
|
1236
1236
|
}
|
|
1237
|
+
function asTokenCount(value) {
|
|
1238
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
1239
|
+
}
|
|
1240
|
+
function normalizeTokenUsage(raw) {
|
|
1241
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
1242
|
+
return null;
|
|
1243
|
+
}
|
|
1244
|
+
const u = raw;
|
|
1245
|
+
if ("cache_read_input_tokens" in u || "cache_creation_input_tokens" in u) {
|
|
1246
|
+
const cacheRead = asTokenCount(u.cache_read_input_tokens);
|
|
1247
|
+
const cacheCreation = asTokenCount(u.cache_creation_input_tokens);
|
|
1248
|
+
const baseInput = asTokenCount(u.input_tokens);
|
|
1249
|
+
const outputTokens = asTokenCount(u.output_tokens);
|
|
1250
|
+
if (cacheRead === null && cacheCreation === null && baseInput === null && outputTokens === null) {
|
|
1251
|
+
return null;
|
|
1252
|
+
}
|
|
1253
|
+
const inputTokens = (baseInput ?? 0) + (cacheRead ?? 0) + (cacheCreation ?? 0);
|
|
1254
|
+
return {
|
|
1255
|
+
inputTokens,
|
|
1256
|
+
outputTokens,
|
|
1257
|
+
totalTokens: inputTokens + (outputTokens ?? 0),
|
|
1258
|
+
cachedInputTokens: cacheRead
|
|
1259
|
+
};
|
|
1260
|
+
}
|
|
1261
|
+
if ("prompt_tokens" in u || "completion_tokens" in u || "promptTokens" in u || "completionTokens" in u) {
|
|
1262
|
+
const promptDetails = u.prompt_tokens_details ?? {};
|
|
1263
|
+
return withAnyTokenCount({
|
|
1264
|
+
inputTokens: asTokenCount(u.prompt_tokens) ?? asTokenCount(u.promptTokens),
|
|
1265
|
+
outputTokens: asTokenCount(u.completion_tokens) ?? asTokenCount(u.completionTokens),
|
|
1266
|
+
totalTokens: asTokenCount(u.total_tokens) ?? asTokenCount(u.totalTokens),
|
|
1267
|
+
cachedInputTokens: asTokenCount(promptDetails.cached_tokens)
|
|
1268
|
+
});
|
|
1269
|
+
}
|
|
1270
|
+
if ("prompt_token_count" in u || "candidates_token_count" in u) {
|
|
1271
|
+
return withAnyTokenCount({
|
|
1272
|
+
inputTokens: asTokenCount(u.prompt_token_count),
|
|
1273
|
+
outputTokens: asTokenCount(u.candidates_token_count),
|
|
1274
|
+
totalTokens: asTokenCount(u.total_token_count),
|
|
1275
|
+
cachedInputTokens: asTokenCount(u.cached_content_token_count)
|
|
1276
|
+
});
|
|
1277
|
+
}
|
|
1278
|
+
if ("input_tokens" in u || "output_tokens" in u) {
|
|
1279
|
+
const inputDetails = u.input_token_details ?? {};
|
|
1280
|
+
const inputTokens = asTokenCount(u.input_tokens);
|
|
1281
|
+
const outputTokens = asTokenCount(u.output_tokens);
|
|
1282
|
+
let totalTokens = asTokenCount(u.total_tokens);
|
|
1283
|
+
if (totalTokens === null && inputTokens !== null && outputTokens !== null) {
|
|
1284
|
+
totalTokens = inputTokens + outputTokens;
|
|
1285
|
+
}
|
|
1286
|
+
return withAnyTokenCount({
|
|
1287
|
+
inputTokens,
|
|
1288
|
+
outputTokens,
|
|
1289
|
+
totalTokens,
|
|
1290
|
+
cachedInputTokens: asTokenCount(inputDetails.cache_read)
|
|
1291
|
+
});
|
|
1292
|
+
}
|
|
1293
|
+
return null;
|
|
1294
|
+
}
|
|
1295
|
+
function withAnyTokenCount(usage) {
|
|
1296
|
+
const hasCount = usage.inputTokens !== null || usage.outputTokens !== null || usage.totalTokens !== null || usage.cachedInputTokens !== null;
|
|
1297
|
+
return hasCount ? usage : null;
|
|
1298
|
+
}
|
|
1299
|
+
function addUsage(totals, usage) {
|
|
1300
|
+
for (const key of [
|
|
1301
|
+
"inputTokens",
|
|
1302
|
+
"outputTokens",
|
|
1303
|
+
"totalTokens",
|
|
1304
|
+
"cachedInputTokens"
|
|
1305
|
+
]) {
|
|
1306
|
+
const value = usage[key];
|
|
1307
|
+
if (value !== null) {
|
|
1308
|
+
totals[key] = (totals[key] ?? 0) + value;
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
function usageFromGenerations(generations) {
|
|
1313
|
+
if (!generations?.length) {
|
|
1314
|
+
return null;
|
|
1315
|
+
}
|
|
1316
|
+
const totals = {
|
|
1317
|
+
inputTokens: null,
|
|
1318
|
+
outputTokens: null,
|
|
1319
|
+
totalTokens: null,
|
|
1320
|
+
cachedInputTokens: null
|
|
1321
|
+
};
|
|
1322
|
+
let found = false;
|
|
1323
|
+
for (const batch of generations) {
|
|
1324
|
+
if (!Array.isArray(batch)) {
|
|
1325
|
+
continue;
|
|
1326
|
+
}
|
|
1327
|
+
for (const gen of batch) {
|
|
1328
|
+
const msg = gen?.message;
|
|
1329
|
+
if (!msg || typeof msg !== "object") {
|
|
1330
|
+
continue;
|
|
1331
|
+
}
|
|
1332
|
+
const responseMetadata = msg.response_metadata;
|
|
1333
|
+
const usage = normalizeTokenUsage(msg.usage_metadata) ?? normalizeTokenUsage(responseMetadata?.token_usage) ?? normalizeTokenUsage(responseMetadata?.usage) ?? normalizeTokenUsage(responseMetadata?.tokenUsage);
|
|
1334
|
+
if (!usage) {
|
|
1335
|
+
continue;
|
|
1336
|
+
}
|
|
1337
|
+
found = true;
|
|
1338
|
+
addUsage(totals, usage);
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
return found ? totals : null;
|
|
1342
|
+
}
|
|
1237
1343
|
function extractUsage2(output) {
|
|
1344
|
+
const generations = output.generations;
|
|
1345
|
+
const llmOutput = output.llmOutput ?? output.llm_output;
|
|
1346
|
+
const normalized = usageFromGenerations(generations) ?? normalizeTokenUsage(llmOutput?.tokenUsage) ?? normalizeTokenUsage(llmOutput?.token_usage) ?? normalizeTokenUsage(llmOutput?.usage);
|
|
1238
1347
|
const usage = {};
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1348
|
+
if (!normalized) {
|
|
1349
|
+
return usage;
|
|
1350
|
+
}
|
|
1351
|
+
if (normalized.inputTokens !== null) {
|
|
1352
|
+
usage.inputTokens = normalized.inputTokens;
|
|
1353
|
+
}
|
|
1354
|
+
if (normalized.outputTokens !== null) {
|
|
1355
|
+
usage.outputTokens = normalized.outputTokens;
|
|
1246
1356
|
}
|
|
1247
|
-
if (
|
|
1248
|
-
usage.
|
|
1357
|
+
if (normalized.totalTokens !== null) {
|
|
1358
|
+
usage.totalTokens = normalized.totalTokens;
|
|
1249
1359
|
}
|
|
1250
|
-
if (
|
|
1251
|
-
usage.
|
|
1360
|
+
if (normalized.cachedInputTokens !== null) {
|
|
1361
|
+
usage.cachedInputTokens = normalized.cachedInputTokens;
|
|
1252
1362
|
}
|
|
1253
1363
|
return usage;
|
|
1254
1364
|
}
|
|
@@ -2629,6 +2739,9 @@ var Bitfab = class {
|
|
|
2629
2739
|
};
|
|
2630
2740
|
return runWithSpanStack(newStack, executeWithContext);
|
|
2631
2741
|
};
|
|
2742
|
+
Object.defineProperty(wrappedFn, "_bitfabTraceFunctionKey", {
|
|
2743
|
+
value: traceFunctionKey
|
|
2744
|
+
});
|
|
2632
2745
|
return wrappedFn;
|
|
2633
2746
|
}
|
|
2634
2747
|
/**
|
|
@@ -2800,23 +2913,40 @@ var Bitfab = class {
|
|
|
2800
2913
|
* Fetches the last N traces for the given trace function key, re-runs each
|
|
2801
2914
|
* through the provided function, and returns comparison data.
|
|
2802
2915
|
*
|
|
2803
|
-
*
|
|
2804
|
-
*
|
|
2916
|
+
* Accepts either a `withSpan`-wrapped function (under the same key) or any
|
|
2917
|
+
* plain callable: plain callables are wrapped internally so each replayed
|
|
2918
|
+
* invocation records a trace tied to the test run. The plain-callable form
|
|
2919
|
+
* is how handler-instrumented workflows (LangGraph/LangChain, Claude Agent
|
|
2920
|
+
* SDK) replay — those record traces under a key with no `withSpan`-wrapped
|
|
2921
|
+
* root in the app.
|
|
2805
2922
|
*
|
|
2806
2923
|
* @param traceFunctionKey - The trace function key to replay
|
|
2807
|
-
* @param fn - The function to
|
|
2924
|
+
* @param fn - The function to run recorded inputs through
|
|
2808
2925
|
* @param options - Optional replay options. When `traceIds` is passed,
|
|
2809
2926
|
* `limit` is ignored (with a warning): an explicit ID list already
|
|
2810
2927
|
* determines how many traces replay.
|
|
2811
2928
|
* @returns ReplayResult with items, testRunId, and testRunUrl
|
|
2812
2929
|
*/
|
|
2813
2930
|
async replay(traceFunctionKey, fn, options) {
|
|
2931
|
+
const wrappedKey = fn._bitfabTraceFunctionKey;
|
|
2932
|
+
let replayFn = fn;
|
|
2933
|
+
if (wrappedKey === void 0) {
|
|
2934
|
+
replayFn = this.withSpan(
|
|
2935
|
+
traceFunctionKey,
|
|
2936
|
+
{ name: fn.name || "Replay", type: "agent" },
|
|
2937
|
+
fn
|
|
2938
|
+
);
|
|
2939
|
+
} else if (wrappedKey !== traceFunctionKey) {
|
|
2940
|
+
throw new BitfabError(
|
|
2941
|
+
`Function is wrapped with trace function key '${wrappedKey}' but replay was called with '${traceFunctionKey}'. Pass matching keys, or pass the unwrapped function to replay it under the explicit key.`
|
|
2942
|
+
);
|
|
2943
|
+
}
|
|
2814
2944
|
const { replay: doReplay } = await import("./replay-BIPIDXX6.js");
|
|
2815
2945
|
return doReplay(
|
|
2816
2946
|
this.httpClient,
|
|
2817
2947
|
this.serviceUrl,
|
|
2818
2948
|
traceFunctionKey,
|
|
2819
|
-
|
|
2949
|
+
replayFn,
|
|
2820
2950
|
options
|
|
2821
2951
|
);
|
|
2822
2952
|
}
|
|
@@ -2890,4 +3020,4 @@ export {
|
|
|
2890
3020
|
Bitfab,
|
|
2891
3021
|
BitfabFunction
|
|
2892
3022
|
};
|
|
2893
|
-
//# sourceMappingURL=chunk-
|
|
3023
|
+
//# sourceMappingURL=chunk-ILIUTS5D.js.map
|