braintrust 0.2.1 → 0.2.3
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/dev/dist/index.d.mts +24 -12
- package/dev/dist/index.d.ts +24 -12
- package/dev/dist/index.js +1 -1
- package/dev/dist/index.mjs +1 -1
- package/dist/browser.d.mts +115 -45
- package/dist/browser.d.ts +115 -45
- package/dist/browser.js +259 -45
- package/dist/browser.mjs +217 -3
- package/dist/cli.js +74 -20
- package/dist/index.d.mts +131 -51
- package/dist/index.d.ts +131 -51
- package/dist/index.js +311 -79
- package/dist/index.mjs +246 -14
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -6131,6 +6131,7 @@ async function loadPrompt({
|
|
|
6131
6131
|
projectId,
|
|
6132
6132
|
slug,
|
|
6133
6133
|
version,
|
|
6134
|
+
environment,
|
|
6134
6135
|
id,
|
|
6135
6136
|
defaults,
|
|
6136
6137
|
noTrace = false,
|
|
@@ -6141,6 +6142,11 @@ async function loadPrompt({
|
|
|
6141
6142
|
forceLogin,
|
|
6142
6143
|
state: stateArg
|
|
6143
6144
|
}) {
|
|
6145
|
+
if (version && environment) {
|
|
6146
|
+
throw new Error(
|
|
6147
|
+
"Cannot specify both 'version' and 'environment' parameters. Please use only one (remove the other)."
|
|
6148
|
+
);
|
|
6149
|
+
}
|
|
6144
6150
|
if (id) {
|
|
6145
6151
|
} else if (isEmpty(projectName) && isEmpty(projectId)) {
|
|
6146
6152
|
throw new Error("Must specify either projectName or projectId");
|
|
@@ -6158,7 +6164,10 @@ async function loadPrompt({
|
|
|
6158
6164
|
forceLogin
|
|
6159
6165
|
});
|
|
6160
6166
|
if (id) {
|
|
6161
|
-
response = await state.apiConn().get_json(`v1/prompt/${id}`, {
|
|
6167
|
+
response = await state.apiConn().get_json(`v1/prompt/${id}`, {
|
|
6168
|
+
...version && { version },
|
|
6169
|
+
...environment && { environment }
|
|
6170
|
+
});
|
|
6162
6171
|
if (response) {
|
|
6163
6172
|
response = { objects: [response] };
|
|
6164
6173
|
}
|
|
@@ -6167,10 +6176,14 @@ async function loadPrompt({
|
|
|
6167
6176
|
project_name: projectName,
|
|
6168
6177
|
project_id: projectId,
|
|
6169
6178
|
slug,
|
|
6170
|
-
version
|
|
6179
|
+
version,
|
|
6180
|
+
...environment && { environment }
|
|
6171
6181
|
});
|
|
6172
6182
|
}
|
|
6173
6183
|
} catch (e) {
|
|
6184
|
+
if (environment || version) {
|
|
6185
|
+
throw new Error(`Prompt not found with specified parameters: ${e}`);
|
|
6186
|
+
}
|
|
6174
6187
|
console.warn("Failed to load prompt, attempting to fall back to cache:", e);
|
|
6175
6188
|
let prompt2;
|
|
6176
6189
|
if (id) {
|
|
@@ -6413,6 +6426,110 @@ function traced(callback, args) {
|
|
|
6413
6426
|
})();
|
|
6414
6427
|
}
|
|
6415
6428
|
}
|
|
6429
|
+
function isGeneratorFunction(fn) {
|
|
6430
|
+
return Object.prototype.toString.call(fn) === "[object GeneratorFunction]";
|
|
6431
|
+
}
|
|
6432
|
+
function isAsyncGeneratorFunction(fn) {
|
|
6433
|
+
return Object.prototype.toString.call(fn) === "[object AsyncGeneratorFunction]";
|
|
6434
|
+
}
|
|
6435
|
+
function wrapTracedSyncGenerator(fn, spanArgs, noTraceIO) {
|
|
6436
|
+
const wrapper = function* (...fnArgs) {
|
|
6437
|
+
const span = startSpan(spanArgs);
|
|
6438
|
+
try {
|
|
6439
|
+
if (!noTraceIO) {
|
|
6440
|
+
span.log({ input: fnArgs });
|
|
6441
|
+
}
|
|
6442
|
+
const envValue = isomorph_default.getEnv("BRAINTRUST_MAX_GENERATOR_ITEMS");
|
|
6443
|
+
const maxItems = envValue !== void 0 ? Number(envValue) : 1e3;
|
|
6444
|
+
if (!noTraceIO && maxItems !== 0) {
|
|
6445
|
+
let collected = [];
|
|
6446
|
+
let truncated = false;
|
|
6447
|
+
const gen = generatorWithCurrent(span, fn.apply(this, fnArgs));
|
|
6448
|
+
try {
|
|
6449
|
+
for (const value of gen) {
|
|
6450
|
+
if (maxItems === -1 || !truncated && collected.length < maxItems) {
|
|
6451
|
+
collected.push(value);
|
|
6452
|
+
} else {
|
|
6453
|
+
truncated = true;
|
|
6454
|
+
collected = [];
|
|
6455
|
+
console.warn(
|
|
6456
|
+
`Generator output exceeded limit of ${maxItems} items, output not logged. Increase BRAINTRUST_MAX_GENERATOR_ITEMS or set to -1 to disable limit.`
|
|
6457
|
+
);
|
|
6458
|
+
}
|
|
6459
|
+
yield value;
|
|
6460
|
+
}
|
|
6461
|
+
if (!truncated) {
|
|
6462
|
+
span.log({ output: collected });
|
|
6463
|
+
}
|
|
6464
|
+
} catch (error2) {
|
|
6465
|
+
logError(span, error2);
|
|
6466
|
+
if (!truncated && collected.length > 0) {
|
|
6467
|
+
span.log({ output: collected });
|
|
6468
|
+
}
|
|
6469
|
+
throw error2;
|
|
6470
|
+
}
|
|
6471
|
+
} else {
|
|
6472
|
+
const gen = generatorWithCurrent(span, fn.apply(this, fnArgs));
|
|
6473
|
+
for (const value of gen) {
|
|
6474
|
+
yield value;
|
|
6475
|
+
}
|
|
6476
|
+
}
|
|
6477
|
+
} finally {
|
|
6478
|
+
span.end();
|
|
6479
|
+
}
|
|
6480
|
+
};
|
|
6481
|
+
Object.defineProperty(wrapper, "name", { value: fn.name });
|
|
6482
|
+
return wrapper;
|
|
6483
|
+
}
|
|
6484
|
+
function wrapTracedAsyncGenerator(fn, spanArgs, noTraceIO) {
|
|
6485
|
+
const wrapper = async function* (...fnArgs) {
|
|
6486
|
+
const span = startSpan(spanArgs);
|
|
6487
|
+
try {
|
|
6488
|
+
if (!noTraceIO) {
|
|
6489
|
+
span.log({ input: fnArgs });
|
|
6490
|
+
}
|
|
6491
|
+
const envValue = isomorph_default.getEnv("BRAINTRUST_MAX_GENERATOR_ITEMS");
|
|
6492
|
+
const maxItems = envValue !== void 0 ? Number(envValue) : 1e3;
|
|
6493
|
+
if (!noTraceIO && maxItems !== 0) {
|
|
6494
|
+
let collected = [];
|
|
6495
|
+
let truncated = false;
|
|
6496
|
+
const gen = asyncGeneratorWithCurrent(span, fn.apply(this, fnArgs));
|
|
6497
|
+
try {
|
|
6498
|
+
for await (const value of gen) {
|
|
6499
|
+
if (maxItems === -1 || !truncated && collected.length < maxItems) {
|
|
6500
|
+
collected.push(value);
|
|
6501
|
+
} else {
|
|
6502
|
+
truncated = true;
|
|
6503
|
+
collected = [];
|
|
6504
|
+
console.warn(
|
|
6505
|
+
`Generator output exceeded limit of ${maxItems} items, output not logged. Increase BRAINTRUST_MAX_GENERATOR_ITEMS or set to -1 to disable limit.`
|
|
6506
|
+
);
|
|
6507
|
+
}
|
|
6508
|
+
yield value;
|
|
6509
|
+
}
|
|
6510
|
+
if (!truncated) {
|
|
6511
|
+
span.log({ output: collected });
|
|
6512
|
+
}
|
|
6513
|
+
} catch (error2) {
|
|
6514
|
+
logError(span, error2);
|
|
6515
|
+
if (!truncated && collected.length > 0) {
|
|
6516
|
+
span.log({ output: collected });
|
|
6517
|
+
}
|
|
6518
|
+
throw error2;
|
|
6519
|
+
}
|
|
6520
|
+
} else {
|
|
6521
|
+
const gen = asyncGeneratorWithCurrent(span, fn.apply(this, fnArgs));
|
|
6522
|
+
for await (const value of gen) {
|
|
6523
|
+
yield value;
|
|
6524
|
+
}
|
|
6525
|
+
}
|
|
6526
|
+
} finally {
|
|
6527
|
+
span.end();
|
|
6528
|
+
}
|
|
6529
|
+
};
|
|
6530
|
+
Object.defineProperty(wrapper, "name", { value: fn.name });
|
|
6531
|
+
return wrapper;
|
|
6532
|
+
}
|
|
6416
6533
|
function wrapTraced(fn, args) {
|
|
6417
6534
|
const spanArgs = {
|
|
6418
6535
|
name: fn.name,
|
|
@@ -6421,6 +6538,13 @@ function wrapTraced(fn, args) {
|
|
|
6421
6538
|
};
|
|
6422
6539
|
const hasExplicitInput = args && args.event && "input" in args.event && args.event.input !== void 0;
|
|
6423
6540
|
const hasExplicitOutput = args && args.event && args.event.output !== void 0;
|
|
6541
|
+
const noTraceIO = args?.noTraceIO || hasExplicitInput || hasExplicitOutput;
|
|
6542
|
+
if (isGeneratorFunction(fn)) {
|
|
6543
|
+
return wrapTracedSyncGenerator(fn, spanArgs, !!noTraceIO);
|
|
6544
|
+
}
|
|
6545
|
+
if (isAsyncGeneratorFunction(fn)) {
|
|
6546
|
+
return wrapTracedAsyncGenerator(fn, spanArgs, !!noTraceIO);
|
|
6547
|
+
}
|
|
6424
6548
|
if (args?.asyncFlush) {
|
|
6425
6549
|
return (...fnArgs) => traced((span) => {
|
|
6426
6550
|
if (!hasExplicitInput) {
|
|
@@ -6506,6 +6630,52 @@ function startSpanAndIsLogger(args) {
|
|
|
6506
6630
|
function withCurrent(span, callback, state = void 0) {
|
|
6507
6631
|
return (state ?? _globalState).currentSpan.run(span, () => callback(span));
|
|
6508
6632
|
}
|
|
6633
|
+
function* generatorWithCurrent(span, gen, state = void 0) {
|
|
6634
|
+
let nextValue;
|
|
6635
|
+
while (true) {
|
|
6636
|
+
const result = withCurrent(
|
|
6637
|
+
span,
|
|
6638
|
+
() => {
|
|
6639
|
+
try {
|
|
6640
|
+
return gen.next(nextValue);
|
|
6641
|
+
} catch (e) {
|
|
6642
|
+
return { value: void 0, done: true, error: e };
|
|
6643
|
+
}
|
|
6644
|
+
},
|
|
6645
|
+
state
|
|
6646
|
+
);
|
|
6647
|
+
if ("error" in result) {
|
|
6648
|
+
throw result.error;
|
|
6649
|
+
}
|
|
6650
|
+
if (result.done) {
|
|
6651
|
+
return result.value;
|
|
6652
|
+
}
|
|
6653
|
+
nextValue = yield result.value;
|
|
6654
|
+
}
|
|
6655
|
+
}
|
|
6656
|
+
async function* asyncGeneratorWithCurrent(span, gen, state = void 0) {
|
|
6657
|
+
let nextValue;
|
|
6658
|
+
while (true) {
|
|
6659
|
+
const result = await withCurrent(
|
|
6660
|
+
span,
|
|
6661
|
+
async () => {
|
|
6662
|
+
try {
|
|
6663
|
+
return await gen.next(nextValue);
|
|
6664
|
+
} catch (e) {
|
|
6665
|
+
return { value: void 0, done: true, error: e };
|
|
6666
|
+
}
|
|
6667
|
+
},
|
|
6668
|
+
state
|
|
6669
|
+
);
|
|
6670
|
+
if ("error" in result) {
|
|
6671
|
+
throw result.error;
|
|
6672
|
+
}
|
|
6673
|
+
if (result.done) {
|
|
6674
|
+
return result.value;
|
|
6675
|
+
}
|
|
6676
|
+
nextValue = yield result.value;
|
|
6677
|
+
}
|
|
6678
|
+
}
|
|
6509
6679
|
function withParent(parent, callback, state = void 0) {
|
|
6510
6680
|
return (state ?? _globalState).currentParent.run(parent, () => callback());
|
|
6511
6681
|
}
|
|
@@ -8002,7 +8172,9 @@ var _exportsForTestingOnly = {
|
|
|
8002
8172
|
clearTestBackgroundLogger,
|
|
8003
8173
|
simulateLoginForTests,
|
|
8004
8174
|
simulateLogoutForTests,
|
|
8005
|
-
setInitialTestState
|
|
8175
|
+
setInitialTestState,
|
|
8176
|
+
isGeneratorFunction,
|
|
8177
|
+
isAsyncGeneratorFunction
|
|
8006
8178
|
};
|
|
8007
8179
|
|
|
8008
8180
|
// src/node.ts
|
|
@@ -9799,7 +9971,7 @@ async function Eval(name, evaluator, reporterOrOpts) {
|
|
|
9799
9971
|
const { data, baseExperiment: defaultBaseExperiment } = callEvaluatorData(
|
|
9800
9972
|
evaluator.data
|
|
9801
9973
|
);
|
|
9802
|
-
const experiment = options.parent ? null : initExperiment2(evaluator.state, {
|
|
9974
|
+
const experiment = options.parent || options.noSendLogs ? null : initExperiment2(evaluator.state, {
|
|
9803
9975
|
...evaluator.projectId ? { projectId: evaluator.projectId } : { project: name },
|
|
9804
9976
|
experiment: evaluator.experimentName,
|
|
9805
9977
|
description: evaluator.description,
|
|
@@ -10611,6 +10783,8 @@ function responsesProxy(openai) {
|
|
|
10611
10783
|
return responsesCreateProxy(target.create.bind(target));
|
|
10612
10784
|
} else if (name === "stream") {
|
|
10613
10785
|
return responsesStreamProxy(target.stream.bind(target));
|
|
10786
|
+
} else if (name === "parse") {
|
|
10787
|
+
return responsesParseProxy(target.parse.bind(target));
|
|
10614
10788
|
}
|
|
10615
10789
|
return Reflect.get(target, name, receiver);
|
|
10616
10790
|
}
|
|
@@ -10655,6 +10829,36 @@ function parseEventFromResponseCreateResult(result) {
|
|
|
10655
10829
|
metrics: parseMetricsFromUsage(result?.usage)
|
|
10656
10830
|
};
|
|
10657
10831
|
}
|
|
10832
|
+
function parseSpanFromResponseParseParams(params) {
|
|
10833
|
+
const input = [{ role: "user", content: params.input }];
|
|
10834
|
+
if (params.instructions) {
|
|
10835
|
+
input.push({ role: "system", content: params.instructions });
|
|
10836
|
+
}
|
|
10837
|
+
const spanArgs = {
|
|
10838
|
+
name: "openai.responses.parse",
|
|
10839
|
+
spanAttributes: {
|
|
10840
|
+
type: "llm"
|
|
10841
|
+
},
|
|
10842
|
+
event: {
|
|
10843
|
+
input,
|
|
10844
|
+
metadata: {
|
|
10845
|
+
...filterFrom(params, ["input", "instructions"]),
|
|
10846
|
+
provider: "openai"
|
|
10847
|
+
}
|
|
10848
|
+
},
|
|
10849
|
+
startTime: getCurrentUnixTimestamp()
|
|
10850
|
+
};
|
|
10851
|
+
return {
|
|
10852
|
+
span: startSpan(spanArgs),
|
|
10853
|
+
start: spanArgs.startTime
|
|
10854
|
+
};
|
|
10855
|
+
}
|
|
10856
|
+
function parseEventFromResponseParseResult(result) {
|
|
10857
|
+
return {
|
|
10858
|
+
output: result?.output_parsed || result?.output_text || "",
|
|
10859
|
+
metrics: parseMetricsFromUsage(result?.usage)
|
|
10860
|
+
};
|
|
10861
|
+
}
|
|
10658
10862
|
function traceResponseCreateStream(stream, timedSpan) {
|
|
10659
10863
|
const span = timedSpan.span;
|
|
10660
10864
|
let ttft = -1;
|
|
@@ -10729,6 +10933,16 @@ function responsesStreamProxy(target) {
|
|
|
10729
10933
|
}
|
|
10730
10934
|
});
|
|
10731
10935
|
}
|
|
10936
|
+
function responsesParseProxy(target) {
|
|
10937
|
+
const hooks = {
|
|
10938
|
+
name: "openai.responses.parse",
|
|
10939
|
+
toSpanFunc: parseSpanFromResponseParseParams,
|
|
10940
|
+
resultToEventFunc: parseEventFromResponseParseResult,
|
|
10941
|
+
traceStreamFunc: traceResponseCreateStream
|
|
10942
|
+
// Reuse the same stream tracing
|
|
10943
|
+
};
|
|
10944
|
+
return proxyCreate(target, hooks);
|
|
10945
|
+
}
|
|
10732
10946
|
var TOKEN_NAME_MAP = {
|
|
10733
10947
|
input_tokens: "prompt_tokens",
|
|
10734
10948
|
output_tokens: "completion_tokens",
|
|
@@ -11698,14 +11912,26 @@ function postProcessPrompt(prompt) {
|
|
|
11698
11912
|
});
|
|
11699
11913
|
}
|
|
11700
11914
|
function postProcessOutput(text, toolCalls, finishReason) {
|
|
11701
|
-
return
|
|
11702
|
-
|
|
11703
|
-
|
|
11704
|
-
|
|
11705
|
-
|
|
11706
|
-
|
|
11707
|
-
|
|
11708
|
-
|
|
11915
|
+
return [
|
|
11916
|
+
{
|
|
11917
|
+
index: 0,
|
|
11918
|
+
message: {
|
|
11919
|
+
role: "assistant",
|
|
11920
|
+
content: text ?? "",
|
|
11921
|
+
...toolCalls && toolCalls.length > 0 ? {
|
|
11922
|
+
tool_calls: toolCalls.map((toolCall) => ({
|
|
11923
|
+
id: toolCall.toolCallId,
|
|
11924
|
+
function: {
|
|
11925
|
+
name: toolCall.toolName,
|
|
11926
|
+
arguments: toolCall.args
|
|
11927
|
+
},
|
|
11928
|
+
type: "function"
|
|
11929
|
+
}))
|
|
11930
|
+
} : {}
|
|
11931
|
+
},
|
|
11932
|
+
finish_reason: finishReason
|
|
11933
|
+
}
|
|
11934
|
+
];
|
|
11709
11935
|
}
|
|
11710
11936
|
|
|
11711
11937
|
// src/wrappers/anthropic.ts
|
|
@@ -11972,7 +12198,13 @@ try {
|
|
|
11972
12198
|
);
|
|
11973
12199
|
OTEL_AVAILABLE = false;
|
|
11974
12200
|
}
|
|
11975
|
-
var FILTER_PREFIXES = [
|
|
12201
|
+
var FILTER_PREFIXES = [
|
|
12202
|
+
"gen_ai.",
|
|
12203
|
+
"braintrust.",
|
|
12204
|
+
"llm.",
|
|
12205
|
+
"ai.",
|
|
12206
|
+
"traceloop."
|
|
12207
|
+
];
|
|
11976
12208
|
var AISpanProcessor = class _AISpanProcessor {
|
|
11977
12209
|
static checkOtelAvailable() {
|
|
11978
12210
|
if (!OTEL_AVAILABLE) {
|
|
@@ -12029,7 +12261,7 @@ var AISpanProcessor = class _AISpanProcessor {
|
|
|
12029
12261
|
* Keep spans if:
|
|
12030
12262
|
* 1. It's a root span (no parent)
|
|
12031
12263
|
* 2. Custom filter returns true/false (if provided)
|
|
12032
|
-
* 3. Span name starts with 'gen_ai.', 'braintrust.', 'llm.', or '
|
|
12264
|
+
* 3. Span name starts with 'gen_ai.', 'braintrust.', 'llm.', 'ai.', or 'traceloop.'
|
|
12033
12265
|
* 4. Any attribute name starts with those prefixes
|
|
12034
12266
|
*/
|
|
12035
12267
|
shouldKeepFilteredSpan(span) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "braintrust",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "SDK for integrating Braintrust",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
},
|
|
93
93
|
"dependencies": {
|
|
94
94
|
"@ai-sdk/provider": "^1.1.3",
|
|
95
|
-
"@braintrust/core": "0.0.
|
|
95
|
+
"@braintrust/core": "0.0.93",
|
|
96
96
|
"@next/env": "^14.2.3",
|
|
97
97
|
"@vercel/functions": "^1.0.2",
|
|
98
98
|
"argparse": "^2.0.1",
|