braintrust 0.2.1 → 0.2.2

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/index.mjs CHANGED
@@ -6413,6 +6413,110 @@ function traced(callback, args) {
6413
6413
  })();
6414
6414
  }
6415
6415
  }
6416
+ function isGeneratorFunction(fn) {
6417
+ return Object.prototype.toString.call(fn) === "[object GeneratorFunction]";
6418
+ }
6419
+ function isAsyncGeneratorFunction(fn) {
6420
+ return Object.prototype.toString.call(fn) === "[object AsyncGeneratorFunction]";
6421
+ }
6422
+ function wrapTracedSyncGenerator(fn, spanArgs, noTraceIO) {
6423
+ const wrapper = function* (...fnArgs) {
6424
+ const span = startSpan(spanArgs);
6425
+ try {
6426
+ if (!noTraceIO) {
6427
+ span.log({ input: fnArgs });
6428
+ }
6429
+ const envValue = isomorph_default.getEnv("BRAINTRUST_MAX_GENERATOR_ITEMS");
6430
+ const maxItems = envValue !== void 0 ? Number(envValue) : 1e3;
6431
+ if (!noTraceIO && maxItems !== 0) {
6432
+ let collected = [];
6433
+ let truncated = false;
6434
+ const gen = generatorWithCurrent(span, fn.apply(this, fnArgs));
6435
+ try {
6436
+ for (const value of gen) {
6437
+ if (maxItems === -1 || !truncated && collected.length < maxItems) {
6438
+ collected.push(value);
6439
+ } else {
6440
+ truncated = true;
6441
+ collected = [];
6442
+ console.warn(
6443
+ `Generator output exceeded limit of ${maxItems} items, output not logged. Increase BRAINTRUST_MAX_GENERATOR_ITEMS or set to -1 to disable limit.`
6444
+ );
6445
+ }
6446
+ yield value;
6447
+ }
6448
+ if (!truncated) {
6449
+ span.log({ output: collected });
6450
+ }
6451
+ } catch (error2) {
6452
+ logError(span, error2);
6453
+ if (!truncated && collected.length > 0) {
6454
+ span.log({ output: collected });
6455
+ }
6456
+ throw error2;
6457
+ }
6458
+ } else {
6459
+ const gen = generatorWithCurrent(span, fn.apply(this, fnArgs));
6460
+ for (const value of gen) {
6461
+ yield value;
6462
+ }
6463
+ }
6464
+ } finally {
6465
+ span.end();
6466
+ }
6467
+ };
6468
+ Object.defineProperty(wrapper, "name", { value: fn.name });
6469
+ return wrapper;
6470
+ }
6471
+ function wrapTracedAsyncGenerator(fn, spanArgs, noTraceIO) {
6472
+ const wrapper = async function* (...fnArgs) {
6473
+ const span = startSpan(spanArgs);
6474
+ try {
6475
+ if (!noTraceIO) {
6476
+ span.log({ input: fnArgs });
6477
+ }
6478
+ const envValue = isomorph_default.getEnv("BRAINTRUST_MAX_GENERATOR_ITEMS");
6479
+ const maxItems = envValue !== void 0 ? Number(envValue) : 1e3;
6480
+ if (!noTraceIO && maxItems !== 0) {
6481
+ let collected = [];
6482
+ let truncated = false;
6483
+ const gen = asyncGeneratorWithCurrent(span, fn.apply(this, fnArgs));
6484
+ try {
6485
+ for await (const value of gen) {
6486
+ if (maxItems === -1 || !truncated && collected.length < maxItems) {
6487
+ collected.push(value);
6488
+ } else {
6489
+ truncated = true;
6490
+ collected = [];
6491
+ console.warn(
6492
+ `Generator output exceeded limit of ${maxItems} items, output not logged. Increase BRAINTRUST_MAX_GENERATOR_ITEMS or set to -1 to disable limit.`
6493
+ );
6494
+ }
6495
+ yield value;
6496
+ }
6497
+ if (!truncated) {
6498
+ span.log({ output: collected });
6499
+ }
6500
+ } catch (error2) {
6501
+ logError(span, error2);
6502
+ if (!truncated && collected.length > 0) {
6503
+ span.log({ output: collected });
6504
+ }
6505
+ throw error2;
6506
+ }
6507
+ } else {
6508
+ const gen = asyncGeneratorWithCurrent(span, fn.apply(this, fnArgs));
6509
+ for await (const value of gen) {
6510
+ yield value;
6511
+ }
6512
+ }
6513
+ } finally {
6514
+ span.end();
6515
+ }
6516
+ };
6517
+ Object.defineProperty(wrapper, "name", { value: fn.name });
6518
+ return wrapper;
6519
+ }
6416
6520
  function wrapTraced(fn, args) {
6417
6521
  const spanArgs = {
6418
6522
  name: fn.name,
@@ -6421,6 +6525,13 @@ function wrapTraced(fn, args) {
6421
6525
  };
6422
6526
  const hasExplicitInput = args && args.event && "input" in args.event && args.event.input !== void 0;
6423
6527
  const hasExplicitOutput = args && args.event && args.event.output !== void 0;
6528
+ const noTraceIO = args?.noTraceIO || hasExplicitInput || hasExplicitOutput;
6529
+ if (isGeneratorFunction(fn)) {
6530
+ return wrapTracedSyncGenerator(fn, spanArgs, !!noTraceIO);
6531
+ }
6532
+ if (isAsyncGeneratorFunction(fn)) {
6533
+ return wrapTracedAsyncGenerator(fn, spanArgs, !!noTraceIO);
6534
+ }
6424
6535
  if (args?.asyncFlush) {
6425
6536
  return (...fnArgs) => traced((span) => {
6426
6537
  if (!hasExplicitInput) {
@@ -6506,6 +6617,52 @@ function startSpanAndIsLogger(args) {
6506
6617
  function withCurrent(span, callback, state = void 0) {
6507
6618
  return (state ?? _globalState).currentSpan.run(span, () => callback(span));
6508
6619
  }
6620
+ function* generatorWithCurrent(span, gen, state = void 0) {
6621
+ let nextValue;
6622
+ while (true) {
6623
+ const result = withCurrent(
6624
+ span,
6625
+ () => {
6626
+ try {
6627
+ return gen.next(nextValue);
6628
+ } catch (e) {
6629
+ return { value: void 0, done: true, error: e };
6630
+ }
6631
+ },
6632
+ state
6633
+ );
6634
+ if ("error" in result) {
6635
+ throw result.error;
6636
+ }
6637
+ if (result.done) {
6638
+ return result.value;
6639
+ }
6640
+ nextValue = yield result.value;
6641
+ }
6642
+ }
6643
+ async function* asyncGeneratorWithCurrent(span, gen, state = void 0) {
6644
+ let nextValue;
6645
+ while (true) {
6646
+ const result = await withCurrent(
6647
+ span,
6648
+ async () => {
6649
+ try {
6650
+ return await gen.next(nextValue);
6651
+ } catch (e) {
6652
+ return { value: void 0, done: true, error: e };
6653
+ }
6654
+ },
6655
+ state
6656
+ );
6657
+ if ("error" in result) {
6658
+ throw result.error;
6659
+ }
6660
+ if (result.done) {
6661
+ return result.value;
6662
+ }
6663
+ nextValue = yield result.value;
6664
+ }
6665
+ }
6509
6666
  function withParent(parent, callback, state = void 0) {
6510
6667
  return (state ?? _globalState).currentParent.run(parent, () => callback());
6511
6668
  }
@@ -8002,7 +8159,9 @@ var _exportsForTestingOnly = {
8002
8159
  clearTestBackgroundLogger,
8003
8160
  simulateLoginForTests,
8004
8161
  simulateLogoutForTests,
8005
- setInitialTestState
8162
+ setInitialTestState,
8163
+ isGeneratorFunction,
8164
+ isAsyncGeneratorFunction
8006
8165
  };
8007
8166
 
8008
8167
  // src/node.ts
@@ -10611,6 +10770,8 @@ function responsesProxy(openai) {
10611
10770
  return responsesCreateProxy(target.create.bind(target));
10612
10771
  } else if (name === "stream") {
10613
10772
  return responsesStreamProxy(target.stream.bind(target));
10773
+ } else if (name === "parse") {
10774
+ return responsesParseProxy(target.parse.bind(target));
10614
10775
  }
10615
10776
  return Reflect.get(target, name, receiver);
10616
10777
  }
@@ -10655,6 +10816,36 @@ function parseEventFromResponseCreateResult(result) {
10655
10816
  metrics: parseMetricsFromUsage(result?.usage)
10656
10817
  };
10657
10818
  }
10819
+ function parseSpanFromResponseParseParams(params) {
10820
+ const input = [{ role: "user", content: params.input }];
10821
+ if (params.instructions) {
10822
+ input.push({ role: "system", content: params.instructions });
10823
+ }
10824
+ const spanArgs = {
10825
+ name: "openai.responses.parse",
10826
+ spanAttributes: {
10827
+ type: "llm"
10828
+ },
10829
+ event: {
10830
+ input,
10831
+ metadata: {
10832
+ ...filterFrom(params, ["input", "instructions"]),
10833
+ provider: "openai"
10834
+ }
10835
+ },
10836
+ startTime: getCurrentUnixTimestamp()
10837
+ };
10838
+ return {
10839
+ span: startSpan(spanArgs),
10840
+ start: spanArgs.startTime
10841
+ };
10842
+ }
10843
+ function parseEventFromResponseParseResult(result) {
10844
+ return {
10845
+ output: result?.output_parsed || result?.output_text || "",
10846
+ metrics: parseMetricsFromUsage(result?.usage)
10847
+ };
10848
+ }
10658
10849
  function traceResponseCreateStream(stream, timedSpan) {
10659
10850
  const span = timedSpan.span;
10660
10851
  let ttft = -1;
@@ -10729,6 +10920,16 @@ function responsesStreamProxy(target) {
10729
10920
  }
10730
10921
  });
10731
10922
  }
10923
+ function responsesParseProxy(target) {
10924
+ const hooks = {
10925
+ name: "openai.responses.parse",
10926
+ toSpanFunc: parseSpanFromResponseParseParams,
10927
+ resultToEventFunc: parseEventFromResponseParseResult,
10928
+ traceStreamFunc: traceResponseCreateStream
10929
+ // Reuse the same stream tracing
10930
+ };
10931
+ return proxyCreate(target, hooks);
10932
+ }
10732
10933
  var TOKEN_NAME_MAP = {
10733
10934
  input_tokens: "prompt_tokens",
10734
10935
  output_tokens: "completion_tokens",
@@ -11698,14 +11899,26 @@ function postProcessPrompt(prompt) {
11698
11899
  });
11699
11900
  }
11700
11901
  function postProcessOutput(text, toolCalls, finishReason) {
11701
- return {
11702
- index: 0,
11703
- message: {
11704
- role: "assistant",
11705
- content: text ?? (toolCalls ? toolCalls.length === 1 && toolCalls[0].toolName === "json" ? toolCalls[0].args : JSON.stringify(toolCalls) : "")
11706
- },
11707
- finish_reason: finishReason
11708
- };
11902
+ return [
11903
+ {
11904
+ index: 0,
11905
+ message: {
11906
+ role: "assistant",
11907
+ content: text ?? "",
11908
+ ...toolCalls && toolCalls.length > 0 ? {
11909
+ tool_calls: toolCalls.map((toolCall) => ({
11910
+ id: toolCall.toolCallId,
11911
+ function: {
11912
+ name: toolCall.toolName,
11913
+ arguments: toolCall.args
11914
+ },
11915
+ type: "function"
11916
+ }))
11917
+ } : {}
11918
+ },
11919
+ finish_reason: finishReason
11920
+ }
11921
+ ];
11709
11922
  }
11710
11923
 
11711
11924
  // src/wrappers/anthropic.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "braintrust",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
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.91",
95
+ "@braintrust/core": "0.0.92",
96
96
  "@next/env": "^14.2.3",
97
97
  "@vercel/functions": "^1.0.2",
98
98
  "argparse": "^2.0.1",