@bitfab/sdk 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
package/dist/index.cjs
CHANGED
|
@@ -433,7 +433,7 @@ __export(index_exports, {
|
|
|
433
433
|
module.exports = __toCommonJS(index_exports);
|
|
434
434
|
|
|
435
435
|
// src/version.generated.ts
|
|
436
|
-
var __version__ = "0.
|
|
436
|
+
var __version__ = "0.18.1";
|
|
437
437
|
|
|
438
438
|
// src/constants.ts
|
|
439
439
|
var DEFAULT_SERVICE_URL = "https://bitfab.ai";
|
|
@@ -1663,21 +1663,131 @@ function extractModelName(serialized, metadata) {
|
|
|
1663
1663
|
}
|
|
1664
1664
|
return void 0;
|
|
1665
1665
|
}
|
|
1666
|
+
function asTokenCount(value) {
|
|
1667
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
1668
|
+
}
|
|
1669
|
+
function normalizeTokenUsage(raw) {
|
|
1670
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
1671
|
+
return null;
|
|
1672
|
+
}
|
|
1673
|
+
const u = raw;
|
|
1674
|
+
if ("cache_read_input_tokens" in u || "cache_creation_input_tokens" in u) {
|
|
1675
|
+
const cacheRead = asTokenCount(u.cache_read_input_tokens);
|
|
1676
|
+
const cacheCreation = asTokenCount(u.cache_creation_input_tokens);
|
|
1677
|
+
const baseInput = asTokenCount(u.input_tokens);
|
|
1678
|
+
const outputTokens = asTokenCount(u.output_tokens);
|
|
1679
|
+
if (cacheRead === null && cacheCreation === null && baseInput === null && outputTokens === null) {
|
|
1680
|
+
return null;
|
|
1681
|
+
}
|
|
1682
|
+
const inputTokens = (baseInput ?? 0) + (cacheRead ?? 0) + (cacheCreation ?? 0);
|
|
1683
|
+
return {
|
|
1684
|
+
inputTokens,
|
|
1685
|
+
outputTokens,
|
|
1686
|
+
totalTokens: inputTokens + (outputTokens ?? 0),
|
|
1687
|
+
cachedInputTokens: cacheRead
|
|
1688
|
+
};
|
|
1689
|
+
}
|
|
1690
|
+
if ("prompt_tokens" in u || "completion_tokens" in u || "promptTokens" in u || "completionTokens" in u) {
|
|
1691
|
+
const promptDetails = u.prompt_tokens_details ?? {};
|
|
1692
|
+
return withAnyTokenCount({
|
|
1693
|
+
inputTokens: asTokenCount(u.prompt_tokens) ?? asTokenCount(u.promptTokens),
|
|
1694
|
+
outputTokens: asTokenCount(u.completion_tokens) ?? asTokenCount(u.completionTokens),
|
|
1695
|
+
totalTokens: asTokenCount(u.total_tokens) ?? asTokenCount(u.totalTokens),
|
|
1696
|
+
cachedInputTokens: asTokenCount(promptDetails.cached_tokens)
|
|
1697
|
+
});
|
|
1698
|
+
}
|
|
1699
|
+
if ("prompt_token_count" in u || "candidates_token_count" in u) {
|
|
1700
|
+
return withAnyTokenCount({
|
|
1701
|
+
inputTokens: asTokenCount(u.prompt_token_count),
|
|
1702
|
+
outputTokens: asTokenCount(u.candidates_token_count),
|
|
1703
|
+
totalTokens: asTokenCount(u.total_token_count),
|
|
1704
|
+
cachedInputTokens: asTokenCount(u.cached_content_token_count)
|
|
1705
|
+
});
|
|
1706
|
+
}
|
|
1707
|
+
if ("input_tokens" in u || "output_tokens" in u) {
|
|
1708
|
+
const inputDetails = u.input_token_details ?? {};
|
|
1709
|
+
const inputTokens = asTokenCount(u.input_tokens);
|
|
1710
|
+
const outputTokens = asTokenCount(u.output_tokens);
|
|
1711
|
+
let totalTokens = asTokenCount(u.total_tokens);
|
|
1712
|
+
if (totalTokens === null && inputTokens !== null && outputTokens !== null) {
|
|
1713
|
+
totalTokens = inputTokens + outputTokens;
|
|
1714
|
+
}
|
|
1715
|
+
return withAnyTokenCount({
|
|
1716
|
+
inputTokens,
|
|
1717
|
+
outputTokens,
|
|
1718
|
+
totalTokens,
|
|
1719
|
+
cachedInputTokens: asTokenCount(inputDetails.cache_read)
|
|
1720
|
+
});
|
|
1721
|
+
}
|
|
1722
|
+
return null;
|
|
1723
|
+
}
|
|
1724
|
+
function withAnyTokenCount(usage) {
|
|
1725
|
+
const hasCount = usage.inputTokens !== null || usage.outputTokens !== null || usage.totalTokens !== null || usage.cachedInputTokens !== null;
|
|
1726
|
+
return hasCount ? usage : null;
|
|
1727
|
+
}
|
|
1728
|
+
function addUsage(totals, usage) {
|
|
1729
|
+
for (const key of [
|
|
1730
|
+
"inputTokens",
|
|
1731
|
+
"outputTokens",
|
|
1732
|
+
"totalTokens",
|
|
1733
|
+
"cachedInputTokens"
|
|
1734
|
+
]) {
|
|
1735
|
+
const value = usage[key];
|
|
1736
|
+
if (value !== null) {
|
|
1737
|
+
totals[key] = (totals[key] ?? 0) + value;
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
function usageFromGenerations(generations) {
|
|
1742
|
+
if (!generations?.length) {
|
|
1743
|
+
return null;
|
|
1744
|
+
}
|
|
1745
|
+
const totals = {
|
|
1746
|
+
inputTokens: null,
|
|
1747
|
+
outputTokens: null,
|
|
1748
|
+
totalTokens: null,
|
|
1749
|
+
cachedInputTokens: null
|
|
1750
|
+
};
|
|
1751
|
+
let found = false;
|
|
1752
|
+
for (const batch of generations) {
|
|
1753
|
+
if (!Array.isArray(batch)) {
|
|
1754
|
+
continue;
|
|
1755
|
+
}
|
|
1756
|
+
for (const gen of batch) {
|
|
1757
|
+
const msg = gen?.message;
|
|
1758
|
+
if (!msg || typeof msg !== "object") {
|
|
1759
|
+
continue;
|
|
1760
|
+
}
|
|
1761
|
+
const responseMetadata = msg.response_metadata;
|
|
1762
|
+
const usage = normalizeTokenUsage(msg.usage_metadata) ?? normalizeTokenUsage(responseMetadata?.token_usage) ?? normalizeTokenUsage(responseMetadata?.usage) ?? normalizeTokenUsage(responseMetadata?.tokenUsage);
|
|
1763
|
+
if (!usage) {
|
|
1764
|
+
continue;
|
|
1765
|
+
}
|
|
1766
|
+
found = true;
|
|
1767
|
+
addUsage(totals, usage);
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
return found ? totals : null;
|
|
1771
|
+
}
|
|
1666
1772
|
function extractUsage2(output) {
|
|
1773
|
+
const generations = output.generations;
|
|
1774
|
+
const llmOutput = output.llmOutput ?? output.llm_output;
|
|
1775
|
+
const normalized = usageFromGenerations(generations) ?? normalizeTokenUsage(llmOutput?.tokenUsage) ?? normalizeTokenUsage(llmOutput?.token_usage) ?? normalizeTokenUsage(llmOutput?.usage);
|
|
1667
1776
|
const usage = {};
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1777
|
+
if (!normalized) {
|
|
1778
|
+
return usage;
|
|
1779
|
+
}
|
|
1780
|
+
if (normalized.inputTokens !== null) {
|
|
1781
|
+
usage.inputTokens = normalized.inputTokens;
|
|
1782
|
+
}
|
|
1783
|
+
if (normalized.outputTokens !== null) {
|
|
1784
|
+
usage.outputTokens = normalized.outputTokens;
|
|
1675
1785
|
}
|
|
1676
|
-
if (
|
|
1677
|
-
usage.
|
|
1786
|
+
if (normalized.totalTokens !== null) {
|
|
1787
|
+
usage.totalTokens = normalized.totalTokens;
|
|
1678
1788
|
}
|
|
1679
|
-
if (
|
|
1680
|
-
usage.
|
|
1789
|
+
if (normalized.cachedInputTokens !== null) {
|
|
1790
|
+
usage.cachedInputTokens = normalized.cachedInputTokens;
|
|
1681
1791
|
}
|
|
1682
1792
|
return usage;
|
|
1683
1793
|
}
|
|
@@ -3065,6 +3175,9 @@ var Bitfab = class {
|
|
|
3065
3175
|
};
|
|
3066
3176
|
return runWithSpanStack(newStack, executeWithContext);
|
|
3067
3177
|
};
|
|
3178
|
+
Object.defineProperty(wrappedFn, "_bitfabTraceFunctionKey", {
|
|
3179
|
+
value: traceFunctionKey
|
|
3180
|
+
});
|
|
3068
3181
|
return wrappedFn;
|
|
3069
3182
|
}
|
|
3070
3183
|
/**
|
|
@@ -3236,23 +3349,40 @@ var Bitfab = class {
|
|
|
3236
3349
|
* Fetches the last N traces for the given trace function key, re-runs each
|
|
3237
3350
|
* through the provided function, and returns comparison data.
|
|
3238
3351
|
*
|
|
3239
|
-
*
|
|
3240
|
-
*
|
|
3352
|
+
* Accepts either a `withSpan`-wrapped function (under the same key) or any
|
|
3353
|
+
* plain callable: plain callables are wrapped internally so each replayed
|
|
3354
|
+
* invocation records a trace tied to the test run. The plain-callable form
|
|
3355
|
+
* is how handler-instrumented workflows (LangGraph/LangChain, Claude Agent
|
|
3356
|
+
* SDK) replay — those record traces under a key with no `withSpan`-wrapped
|
|
3357
|
+
* root in the app.
|
|
3241
3358
|
*
|
|
3242
3359
|
* @param traceFunctionKey - The trace function key to replay
|
|
3243
|
-
* @param fn - The function to
|
|
3360
|
+
* @param fn - The function to run recorded inputs through
|
|
3244
3361
|
* @param options - Optional replay options. When `traceIds` is passed,
|
|
3245
3362
|
* `limit` is ignored (with a warning): an explicit ID list already
|
|
3246
3363
|
* determines how many traces replay.
|
|
3247
3364
|
* @returns ReplayResult with items, testRunId, and testRunUrl
|
|
3248
3365
|
*/
|
|
3249
3366
|
async replay(traceFunctionKey, fn, options) {
|
|
3367
|
+
const wrappedKey = fn._bitfabTraceFunctionKey;
|
|
3368
|
+
let replayFn = fn;
|
|
3369
|
+
if (wrappedKey === void 0) {
|
|
3370
|
+
replayFn = this.withSpan(
|
|
3371
|
+
traceFunctionKey,
|
|
3372
|
+
{ name: fn.name || "Replay", type: "agent" },
|
|
3373
|
+
fn
|
|
3374
|
+
);
|
|
3375
|
+
} else if (wrappedKey !== traceFunctionKey) {
|
|
3376
|
+
throw new BitfabError(
|
|
3377
|
+
`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.`
|
|
3378
|
+
);
|
|
3379
|
+
}
|
|
3250
3380
|
const { replay: doReplay } = await Promise.resolve().then(() => (init_replay(), replay_exports));
|
|
3251
3381
|
return doReplay(
|
|
3252
3382
|
this.httpClient,
|
|
3253
3383
|
this.serviceUrl,
|
|
3254
3384
|
traceFunctionKey,
|
|
3255
|
-
|
|
3385
|
+
replayFn,
|
|
3256
3386
|
options
|
|
3257
3387
|
);
|
|
3258
3388
|
}
|