braintrust 0.2.6 → 0.3.6

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/browser.js CHANGED
@@ -6413,19 +6413,15 @@ function responsesCreateProxy(target) {
6413
6413
  return proxyCreate(target, hooks);
6414
6414
  }
6415
6415
  function parseSpanFromResponseCreateParams(params) {
6416
- const input = [{ role: "user", content: params.input }];
6417
- if (params.instructions) {
6418
- input.push({ role: "system", content: params.instructions });
6419
- }
6420
6416
  const spanArgs = {
6421
6417
  name: "openai.responses.create",
6422
6418
  spanAttributes: {
6423
6419
  type: "llm"
6424
6420
  },
6425
6421
  event: {
6426
- input,
6422
+ input: params.input,
6427
6423
  metadata: {
6428
- ...filterFrom(params, ["input", "instructions"]),
6424
+ ...filterFrom(params, ["input"]),
6429
6425
  provider: "openai"
6430
6426
  }
6431
6427
  },
@@ -6437,25 +6433,29 @@ function parseSpanFromResponseCreateParams(params) {
6437
6433
  };
6438
6434
  }
6439
6435
  function parseEventFromResponseCreateResult(result) {
6440
- return {
6441
- output: _optionalChain([result, 'optionalAccess', _84 => _84.output_text]) || "",
6442
- metrics: parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _85 => _85.usage]))
6443
- };
6436
+ const data = {};
6437
+ if (_optionalChain([result, 'optionalAccess', _84 => _84.output]) !== void 0) {
6438
+ data.output = result.output;
6439
+ }
6440
+ if (result) {
6441
+ const { output, usage, ...metadata } = result;
6442
+ if (Object.keys(metadata).length > 0) {
6443
+ data.metadata = metadata;
6444
+ }
6445
+ }
6446
+ data.metrics = parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _85 => _85.usage]));
6447
+ return data;
6444
6448
  }
6445
6449
  function parseSpanFromResponseParseParams(params) {
6446
- const input = [{ role: "user", content: params.input }];
6447
- if (params.instructions) {
6448
- input.push({ role: "system", content: params.instructions });
6449
- }
6450
6450
  const spanArgs = {
6451
6451
  name: "openai.responses.parse",
6452
6452
  spanAttributes: {
6453
6453
  type: "llm"
6454
6454
  },
6455
6455
  event: {
6456
- input,
6456
+ input: params.input,
6457
6457
  metadata: {
6458
- ...filterFrom(params, ["input", "instructions"]),
6458
+ ...filterFrom(params, ["input"]),
6459
6459
  provider: "openai"
6460
6460
  }
6461
6461
  },
@@ -6467,10 +6467,18 @@ function parseSpanFromResponseParseParams(params) {
6467
6467
  };
6468
6468
  }
6469
6469
  function parseEventFromResponseParseResult(result) {
6470
- return {
6471
- output: _optionalChain([result, 'optionalAccess', _86 => _86.output_parsed]) || _optionalChain([result, 'optionalAccess', _87 => _87.output_text]) || "",
6472
- metrics: parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _88 => _88.usage]))
6473
- };
6470
+ const data = {};
6471
+ if (_optionalChain([result, 'optionalAccess', _86 => _86.output]) !== void 0) {
6472
+ data.output = result.output;
6473
+ }
6474
+ if (result) {
6475
+ const { output, usage, ...metadata } = result;
6476
+ if (Object.keys(metadata).length > 0) {
6477
+ data.metadata = metadata;
6478
+ }
6479
+ }
6480
+ data.metrics = parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _87 => _87.usage]));
6481
+ return data;
6474
6482
  }
6475
6483
  function traceResponseCreateStream(stream, timedSpan) {
6476
6484
  const span = timedSpan.span;
@@ -6486,7 +6494,7 @@ function traceResponseCreateStream(stream, timedSpan) {
6486
6494
  return result;
6487
6495
  }
6488
6496
  const item = result.value;
6489
- if (!item || !_optionalChain([item, 'optionalAccess', _89 => _89.type]) || !_optionalChain([item, 'optionalAccess', _90 => _90.response])) {
6497
+ if (!item || !_optionalChain([item, 'optionalAccess', _88 => _88.type]) || !_optionalChain([item, 'optionalAccess', _89 => _89.response])) {
6490
6498
  return result;
6491
6499
  }
6492
6500
  const event = parseLogFromItem(item);
@@ -6497,24 +6505,24 @@ function traceResponseCreateStream(stream, timedSpan) {
6497
6505
  };
6498
6506
  }
6499
6507
  function parseLogFromItem(item) {
6500
- if (!item || !_optionalChain([item, 'optionalAccess', _91 => _91.type]) || !_optionalChain([item, 'optionalAccess', _92 => _92.response])) {
6508
+ if (!item || !_optionalChain([item, 'optionalAccess', _90 => _90.type]) || !_optionalChain([item, 'optionalAccess', _91 => _91.response])) {
6501
6509
  return {};
6502
6510
  }
6503
6511
  const response = item.response;
6504
6512
  switch (item.type) {
6505
6513
  case "response.completed":
6506
- const texts = [];
6507
- for (const output of _optionalChain([response, 'optionalAccess', _93 => _93.output]) || []) {
6508
- for (const content of _optionalChain([output, 'optionalAccess', _94 => _94.content]) || []) {
6509
- if (_optionalChain([content, 'optionalAccess', _95 => _95.type]) === "output_text") {
6510
- texts.push(content.text);
6511
- }
6514
+ const data = {};
6515
+ if (_optionalChain([response, 'optionalAccess', _92 => _92.output]) !== void 0) {
6516
+ data.output = response.output;
6517
+ }
6518
+ if (response) {
6519
+ const { usage, output, ...metadata } = response;
6520
+ if (Object.keys(metadata).length > 0) {
6521
+ data.metadata = metadata;
6512
6522
  }
6513
6523
  }
6514
- return {
6515
- output: texts.join(""),
6516
- metrics: parseMetricsFromUsage(_optionalChain([response, 'optionalAccess', _96 => _96.usage]))
6517
- };
6524
+ data.metrics = parseMetricsFromUsage(_optionalChain([response, 'optionalAccess', _93 => _93.usage]));
6525
+ return data;
6518
6526
  default:
6519
6527
  return {};
6520
6528
  }
@@ -6697,8 +6705,8 @@ function wrapOpenAIv4(openai) {
6697
6705
  const embeddingProxy = createEndpointProxy(openai.embeddings, wrapEmbeddings);
6698
6706
  const moderationProxy = createEndpointProxy(openai.moderations, wrapModerations);
6699
6707
  let betaProxy;
6700
- if (_optionalChain([openai, 'access', _97 => _97.beta, 'optionalAccess', _98 => _98.chat, 'optionalAccess', _99 => _99.completions, 'optionalAccess', _100 => _100.stream])) {
6701
- const betaChatCompletionProxy = new Proxy(_optionalChain([openai, 'optionalAccess', _101 => _101.beta, 'optionalAccess', _102 => _102.chat, 'access', _103 => _103.completions]), {
6708
+ if (_optionalChain([openai, 'access', _94 => _94.beta, 'optionalAccess', _95 => _95.chat, 'optionalAccess', _96 => _96.completions, 'optionalAccess', _97 => _97.stream])) {
6709
+ const betaChatCompletionProxy = new Proxy(_optionalChain([openai, 'optionalAccess', _98 => _98.beta, 'optionalAccess', _99 => _99.chat, 'access', _100 => _100.completions]), {
6702
6710
  get(target, name, receiver) {
6703
6711
  const baseVal = Reflect.get(target, name, receiver);
6704
6712
  if (name === "parse") {
@@ -6746,7 +6754,7 @@ function wrapOpenAIv4(openai) {
6746
6754
  });
6747
6755
  }
6748
6756
  function logCompletionResponse(startTime, response, span) {
6749
- const metrics = parseMetricsFromUsage(_optionalChain([response, 'optionalAccess', _104 => _104.usage]));
6757
+ const metrics = parseMetricsFromUsage(_optionalChain([response, 'optionalAccess', _101 => _101.usage]));
6750
6758
  metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
6751
6759
  span.log({
6752
6760
  output: response.choices,
@@ -6841,55 +6849,80 @@ function logHeaders(response, span) {
6841
6849
  }
6842
6850
  }
6843
6851
  function wrapChatCompletion(completion) {
6844
- return async (allParams, options) => {
6852
+ return (allParams, options) => {
6845
6853
  const { span_info: _, ...params } = allParams;
6846
- const span = startSpan(
6847
- _core.mergeDicts.call(void 0,
6848
- {
6849
- name: "Chat Completion",
6850
- spanAttributes: {
6851
- type: _core.SpanTypeAttribute.LLM
6852
- }
6853
- },
6854
- parseChatCompletionParams(allParams)
6855
- )
6856
- );
6857
- const startTime = getCurrentUnixTimestamp();
6858
- if (params.stream) {
6859
- const { data: ret, response } = await completion(
6860
- // We could get rid of this type coercion if we could somehow enforce
6861
- // that `P extends ChatParams` BUT does not have the property
6862
- // `span_info`.
6863
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
6864
- params,
6865
- options
6866
- ).withResponse();
6867
- logHeaders(response, span);
6868
- const wrapperStream = new WrapperStream(span, startTime, ret.iterator());
6869
- ret.iterator = () => wrapperStream[Symbol.asyncIterator]();
6870
- return ret;
6871
- } else {
6872
- try {
6873
- const completionResponse = completion(
6874
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
6875
- params,
6876
- options
6877
- );
6878
- const { data: ret, response } = await completionResponse.withResponse();
6879
- logHeaders(response, span);
6880
- const { messages, ...rest } = params;
6881
- span.log({
6882
- input: messages,
6883
- metadata: {
6884
- ...rest
6854
+ let executionPromise = null;
6855
+ const executeWrapped = () => {
6856
+ if (!executionPromise) {
6857
+ executionPromise = (async () => {
6858
+ const span = startSpan(
6859
+ _core.mergeDicts.call(void 0,
6860
+ {
6861
+ name: "Chat Completion",
6862
+ spanAttributes: {
6863
+ type: _core.SpanTypeAttribute.LLM
6864
+ }
6865
+ },
6866
+ parseChatCompletionParams(allParams)
6867
+ )
6868
+ );
6869
+ const startTime = getCurrentUnixTimestamp();
6870
+ if (params.stream) {
6871
+ const { data: ret, response } = await completion(
6872
+ // We could get rid of this type coercion if we could somehow enforce
6873
+ // that `P extends ChatParams` BUT does not have the property
6874
+ // `span_info`.
6875
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
6876
+ params,
6877
+ options
6878
+ ).withResponse();
6879
+ logHeaders(response, span);
6880
+ const wrapperStream = new WrapperStream(
6881
+ span,
6882
+ startTime,
6883
+ ret.iterator()
6884
+ );
6885
+ ret.iterator = () => wrapperStream[Symbol.asyncIterator]();
6886
+ return { data: ret, response };
6887
+ } else {
6888
+ try {
6889
+ const completionResponse = completion(
6890
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
6891
+ params,
6892
+ options
6893
+ );
6894
+ const { data: ret, response } = await completionResponse.withResponse();
6895
+ logHeaders(response, span);
6896
+ const { messages, ...rest } = params;
6897
+ span.log({
6898
+ input: messages,
6899
+ metadata: {
6900
+ ...rest
6901
+ }
6902
+ });
6903
+ logCompletionResponse(startTime, ret, span);
6904
+ return { data: ret, response };
6905
+ } finally {
6906
+ span.end();
6907
+ }
6885
6908
  }
6886
- });
6887
- logCompletionResponse(startTime, ret, span);
6888
- return ret;
6889
- } finally {
6890
- span.end();
6909
+ })();
6891
6910
  }
6892
- }
6911
+ return executionPromise;
6912
+ };
6913
+ const dataPromise = executeWrapped().then((result) => result.data);
6914
+ return new Proxy(dataPromise, {
6915
+ get(target, prop, receiver) {
6916
+ if (prop === "withResponse") {
6917
+ return executeWrapped;
6918
+ }
6919
+ const value = Reflect.get(target, prop, receiver);
6920
+ if (typeof value === "function") {
6921
+ return value.bind(target);
6922
+ }
6923
+ return value;
6924
+ }
6925
+ });
6893
6926
  };
6894
6927
  }
6895
6928
  function parseBaseParams(allParams, inputField) {
@@ -6948,7 +6981,7 @@ function parseChatCompletionParams(params) {
6948
6981
  function processEmbeddingResponse(result, span) {
6949
6982
  span.log({
6950
6983
  output: { embedding_length: result.data[0].embedding.length },
6951
- metrics: parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _105 => _105.usage]))
6984
+ metrics: parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _102 => _102.usage]))
6952
6985
  });
6953
6986
  }
6954
6987
  function processModerationResponse(result, span) {
@@ -6978,10 +7011,10 @@ function postprocessStreamingResults(allResults) {
6978
7011
  if (result.usage) {
6979
7012
  metrics = {
6980
7013
  ...metrics,
6981
- ...parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _106 => _106.usage]))
7014
+ ...parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _103 => _103.usage]))
6982
7015
  };
6983
7016
  }
6984
- const delta = _optionalChain([result, 'access', _107 => _107.choices, 'optionalAccess', _108 => _108[0], 'optionalAccess', _109 => _109.delta]);
7017
+ const delta = _optionalChain([result, 'access', _104 => _104.choices, 'optionalAccess', _105 => _105[0], 'optionalAccess', _106 => _106.delta]);
6985
7018
  if (!delta) {
6986
7019
  continue;
6987
7020
  }
package/dist/browser.mjs CHANGED
@@ -6413,19 +6413,15 @@ function responsesCreateProxy(target) {
6413
6413
  return proxyCreate(target, hooks);
6414
6414
  }
6415
6415
  function parseSpanFromResponseCreateParams(params) {
6416
- const input = [{ role: "user", content: params.input }];
6417
- if (params.instructions) {
6418
- input.push({ role: "system", content: params.instructions });
6419
- }
6420
6416
  const spanArgs = {
6421
6417
  name: "openai.responses.create",
6422
6418
  spanAttributes: {
6423
6419
  type: "llm"
6424
6420
  },
6425
6421
  event: {
6426
- input,
6422
+ input: params.input,
6427
6423
  metadata: {
6428
- ...filterFrom(params, ["input", "instructions"]),
6424
+ ...filterFrom(params, ["input"]),
6429
6425
  provider: "openai"
6430
6426
  }
6431
6427
  },
@@ -6437,25 +6433,29 @@ function parseSpanFromResponseCreateParams(params) {
6437
6433
  };
6438
6434
  }
6439
6435
  function parseEventFromResponseCreateResult(result) {
6440
- return {
6441
- output: result?.output_text || "",
6442
- metrics: parseMetricsFromUsage(result?.usage)
6443
- };
6436
+ const data = {};
6437
+ if (result?.output !== void 0) {
6438
+ data.output = result.output;
6439
+ }
6440
+ if (result) {
6441
+ const { output, usage, ...metadata } = result;
6442
+ if (Object.keys(metadata).length > 0) {
6443
+ data.metadata = metadata;
6444
+ }
6445
+ }
6446
+ data.metrics = parseMetricsFromUsage(result?.usage);
6447
+ return data;
6444
6448
  }
6445
6449
  function parseSpanFromResponseParseParams(params) {
6446
- const input = [{ role: "user", content: params.input }];
6447
- if (params.instructions) {
6448
- input.push({ role: "system", content: params.instructions });
6449
- }
6450
6450
  const spanArgs = {
6451
6451
  name: "openai.responses.parse",
6452
6452
  spanAttributes: {
6453
6453
  type: "llm"
6454
6454
  },
6455
6455
  event: {
6456
- input,
6456
+ input: params.input,
6457
6457
  metadata: {
6458
- ...filterFrom(params, ["input", "instructions"]),
6458
+ ...filterFrom(params, ["input"]),
6459
6459
  provider: "openai"
6460
6460
  }
6461
6461
  },
@@ -6467,10 +6467,18 @@ function parseSpanFromResponseParseParams(params) {
6467
6467
  };
6468
6468
  }
6469
6469
  function parseEventFromResponseParseResult(result) {
6470
- return {
6471
- output: result?.output_parsed || result?.output_text || "",
6472
- metrics: parseMetricsFromUsage(result?.usage)
6473
- };
6470
+ const data = {};
6471
+ if (result?.output !== void 0) {
6472
+ data.output = result.output;
6473
+ }
6474
+ if (result) {
6475
+ const { output, usage, ...metadata } = result;
6476
+ if (Object.keys(metadata).length > 0) {
6477
+ data.metadata = metadata;
6478
+ }
6479
+ }
6480
+ data.metrics = parseMetricsFromUsage(result?.usage);
6481
+ return data;
6474
6482
  }
6475
6483
  function traceResponseCreateStream(stream, timedSpan) {
6476
6484
  const span = timedSpan.span;
@@ -6503,18 +6511,18 @@ function parseLogFromItem(item) {
6503
6511
  const response = item.response;
6504
6512
  switch (item.type) {
6505
6513
  case "response.completed":
6506
- const texts = [];
6507
- for (const output of response?.output || []) {
6508
- for (const content of output?.content || []) {
6509
- if (content?.type === "output_text") {
6510
- texts.push(content.text);
6511
- }
6514
+ const data = {};
6515
+ if (response?.output !== void 0) {
6516
+ data.output = response.output;
6517
+ }
6518
+ if (response) {
6519
+ const { usage, output, ...metadata } = response;
6520
+ if (Object.keys(metadata).length > 0) {
6521
+ data.metadata = metadata;
6512
6522
  }
6513
6523
  }
6514
- return {
6515
- output: texts.join(""),
6516
- metrics: parseMetricsFromUsage(response?.usage)
6517
- };
6524
+ data.metrics = parseMetricsFromUsage(response?.usage);
6525
+ return data;
6518
6526
  default:
6519
6527
  return {};
6520
6528
  }
@@ -6841,55 +6849,80 @@ function logHeaders(response, span) {
6841
6849
  }
6842
6850
  }
6843
6851
  function wrapChatCompletion(completion) {
6844
- return async (allParams, options) => {
6852
+ return (allParams, options) => {
6845
6853
  const { span_info: _, ...params } = allParams;
6846
- const span = startSpan(
6847
- mergeDicts2(
6848
- {
6849
- name: "Chat Completion",
6850
- spanAttributes: {
6851
- type: SpanTypeAttribute2.LLM
6852
- }
6853
- },
6854
- parseChatCompletionParams(allParams)
6855
- )
6856
- );
6857
- const startTime = getCurrentUnixTimestamp();
6858
- if (params.stream) {
6859
- const { data: ret, response } = await completion(
6860
- // We could get rid of this type coercion if we could somehow enforce
6861
- // that `P extends ChatParams` BUT does not have the property
6862
- // `span_info`.
6863
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
6864
- params,
6865
- options
6866
- ).withResponse();
6867
- logHeaders(response, span);
6868
- const wrapperStream = new WrapperStream(span, startTime, ret.iterator());
6869
- ret.iterator = () => wrapperStream[Symbol.asyncIterator]();
6870
- return ret;
6871
- } else {
6872
- try {
6873
- const completionResponse = completion(
6874
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
6875
- params,
6876
- options
6877
- );
6878
- const { data: ret, response } = await completionResponse.withResponse();
6879
- logHeaders(response, span);
6880
- const { messages, ...rest } = params;
6881
- span.log({
6882
- input: messages,
6883
- metadata: {
6884
- ...rest
6854
+ let executionPromise = null;
6855
+ const executeWrapped = () => {
6856
+ if (!executionPromise) {
6857
+ executionPromise = (async () => {
6858
+ const span = startSpan(
6859
+ mergeDicts2(
6860
+ {
6861
+ name: "Chat Completion",
6862
+ spanAttributes: {
6863
+ type: SpanTypeAttribute2.LLM
6864
+ }
6865
+ },
6866
+ parseChatCompletionParams(allParams)
6867
+ )
6868
+ );
6869
+ const startTime = getCurrentUnixTimestamp();
6870
+ if (params.stream) {
6871
+ const { data: ret, response } = await completion(
6872
+ // We could get rid of this type coercion if we could somehow enforce
6873
+ // that `P extends ChatParams` BUT does not have the property
6874
+ // `span_info`.
6875
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
6876
+ params,
6877
+ options
6878
+ ).withResponse();
6879
+ logHeaders(response, span);
6880
+ const wrapperStream = new WrapperStream(
6881
+ span,
6882
+ startTime,
6883
+ ret.iterator()
6884
+ );
6885
+ ret.iterator = () => wrapperStream[Symbol.asyncIterator]();
6886
+ return { data: ret, response };
6887
+ } else {
6888
+ try {
6889
+ const completionResponse = completion(
6890
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
6891
+ params,
6892
+ options
6893
+ );
6894
+ const { data: ret, response } = await completionResponse.withResponse();
6895
+ logHeaders(response, span);
6896
+ const { messages, ...rest } = params;
6897
+ span.log({
6898
+ input: messages,
6899
+ metadata: {
6900
+ ...rest
6901
+ }
6902
+ });
6903
+ logCompletionResponse(startTime, ret, span);
6904
+ return { data: ret, response };
6905
+ } finally {
6906
+ span.end();
6907
+ }
6885
6908
  }
6886
- });
6887
- logCompletionResponse(startTime, ret, span);
6888
- return ret;
6889
- } finally {
6890
- span.end();
6909
+ })();
6891
6910
  }
6892
- }
6911
+ return executionPromise;
6912
+ };
6913
+ const dataPromise = executeWrapped().then((result) => result.data);
6914
+ return new Proxy(dataPromise, {
6915
+ get(target, prop, receiver) {
6916
+ if (prop === "withResponse") {
6917
+ return executeWrapped;
6918
+ }
6919
+ const value = Reflect.get(target, prop, receiver);
6920
+ if (typeof value === "function") {
6921
+ return value.bind(target);
6922
+ }
6923
+ return value;
6924
+ }
6925
+ });
6893
6926
  };
6894
6927
  }
6895
6928
  function parseBaseParams(allParams, inputField) {
package/dist/cli.js CHANGED
@@ -1232,7 +1232,7 @@ var require_package = __commonJS({
1232
1232
  "package.json"(exports2, module2) {
1233
1233
  module2.exports = {
1234
1234
  name: "braintrust",
1235
- version: "0.2.6",
1235
+ version: "0.3.6",
1236
1236
  description: "SDK for integrating Braintrust",
1237
1237
  repository: {
1238
1238
  type: "git",
package/dist/index.js CHANGED
@@ -12228,19 +12228,15 @@ function responsesCreateProxy(target) {
12228
12228
  return proxyCreate(target, hooks);
12229
12229
  }
12230
12230
  function parseSpanFromResponseCreateParams(params) {
12231
- const input = [{ role: "user", content: params.input }];
12232
- if (params.instructions) {
12233
- input.push({ role: "system", content: params.instructions });
12234
- }
12235
12231
  const spanArgs = {
12236
12232
  name: "openai.responses.create",
12237
12233
  spanAttributes: {
12238
12234
  type: "llm"
12239
12235
  },
12240
12236
  event: {
12241
- input,
12237
+ input: params.input,
12242
12238
  metadata: {
12243
- ...filterFrom(params, ["input", "instructions"]),
12239
+ ...filterFrom(params, ["input"]),
12244
12240
  provider: "openai"
12245
12241
  }
12246
12242
  },
@@ -12252,25 +12248,29 @@ function parseSpanFromResponseCreateParams(params) {
12252
12248
  };
12253
12249
  }
12254
12250
  function parseEventFromResponseCreateResult(result) {
12255
- return {
12256
- output: _optionalChain([result, 'optionalAccess', _161 => _161.output_text]) || "",
12257
- metrics: parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _162 => _162.usage]))
12258
- };
12251
+ const data = {};
12252
+ if (_optionalChain([result, 'optionalAccess', _161 => _161.output]) !== void 0) {
12253
+ data.output = result.output;
12254
+ }
12255
+ if (result) {
12256
+ const { output, usage, ...metadata } = result;
12257
+ if (Object.keys(metadata).length > 0) {
12258
+ data.metadata = metadata;
12259
+ }
12260
+ }
12261
+ data.metrics = parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _162 => _162.usage]));
12262
+ return data;
12259
12263
  }
12260
12264
  function parseSpanFromResponseParseParams(params) {
12261
- const input = [{ role: "user", content: params.input }];
12262
- if (params.instructions) {
12263
- input.push({ role: "system", content: params.instructions });
12264
- }
12265
12265
  const spanArgs = {
12266
12266
  name: "openai.responses.parse",
12267
12267
  spanAttributes: {
12268
12268
  type: "llm"
12269
12269
  },
12270
12270
  event: {
12271
- input,
12271
+ input: params.input,
12272
12272
  metadata: {
12273
- ...filterFrom(params, ["input", "instructions"]),
12273
+ ...filterFrom(params, ["input"]),
12274
12274
  provider: "openai"
12275
12275
  }
12276
12276
  },
@@ -12282,10 +12282,18 @@ function parseSpanFromResponseParseParams(params) {
12282
12282
  };
12283
12283
  }
12284
12284
  function parseEventFromResponseParseResult(result) {
12285
- return {
12286
- output: _optionalChain([result, 'optionalAccess', _163 => _163.output_parsed]) || _optionalChain([result, 'optionalAccess', _164 => _164.output_text]) || "",
12287
- metrics: parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _165 => _165.usage]))
12288
- };
12285
+ const data = {};
12286
+ if (_optionalChain([result, 'optionalAccess', _163 => _163.output]) !== void 0) {
12287
+ data.output = result.output;
12288
+ }
12289
+ if (result) {
12290
+ const { output, usage, ...metadata } = result;
12291
+ if (Object.keys(metadata).length > 0) {
12292
+ data.metadata = metadata;
12293
+ }
12294
+ }
12295
+ data.metrics = parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _164 => _164.usage]));
12296
+ return data;
12289
12297
  }
12290
12298
  function traceResponseCreateStream(stream, timedSpan) {
12291
12299
  const span = timedSpan.span;
@@ -12301,7 +12309,7 @@ function traceResponseCreateStream(stream, timedSpan) {
12301
12309
  return result;
12302
12310
  }
12303
12311
  const item = result.value;
12304
- if (!item || !_optionalChain([item, 'optionalAccess', _166 => _166.type]) || !_optionalChain([item, 'optionalAccess', _167 => _167.response])) {
12312
+ if (!item || !_optionalChain([item, 'optionalAccess', _165 => _165.type]) || !_optionalChain([item, 'optionalAccess', _166 => _166.response])) {
12305
12313
  return result;
12306
12314
  }
12307
12315
  const event = parseLogFromItem(item);
@@ -12312,24 +12320,24 @@ function traceResponseCreateStream(stream, timedSpan) {
12312
12320
  };
12313
12321
  }
12314
12322
  function parseLogFromItem(item) {
12315
- if (!item || !_optionalChain([item, 'optionalAccess', _168 => _168.type]) || !_optionalChain([item, 'optionalAccess', _169 => _169.response])) {
12323
+ if (!item || !_optionalChain([item, 'optionalAccess', _167 => _167.type]) || !_optionalChain([item, 'optionalAccess', _168 => _168.response])) {
12316
12324
  return {};
12317
12325
  }
12318
12326
  const response = item.response;
12319
12327
  switch (item.type) {
12320
12328
  case "response.completed":
12321
- const texts = [];
12322
- for (const output of _optionalChain([response, 'optionalAccess', _170 => _170.output]) || []) {
12323
- for (const content of _optionalChain([output, 'optionalAccess', _171 => _171.content]) || []) {
12324
- if (_optionalChain([content, 'optionalAccess', _172 => _172.type]) === "output_text") {
12325
- texts.push(content.text);
12326
- }
12329
+ const data = {};
12330
+ if (_optionalChain([response, 'optionalAccess', _169 => _169.output]) !== void 0) {
12331
+ data.output = response.output;
12332
+ }
12333
+ if (response) {
12334
+ const { usage, output, ...metadata } = response;
12335
+ if (Object.keys(metadata).length > 0) {
12336
+ data.metadata = metadata;
12327
12337
  }
12328
12338
  }
12329
- return {
12330
- output: texts.join(""),
12331
- metrics: parseMetricsFromUsage(_optionalChain([response, 'optionalAccess', _173 => _173.usage]))
12332
- };
12339
+ data.metrics = parseMetricsFromUsage(_optionalChain([response, 'optionalAccess', _170 => _170.usage]));
12340
+ return data;
12333
12341
  default:
12334
12342
  return {};
12335
12343
  }
@@ -12512,8 +12520,8 @@ function wrapOpenAIv4(openai) {
12512
12520
  const embeddingProxy = createEndpointProxy(openai.embeddings, wrapEmbeddings);
12513
12521
  const moderationProxy = createEndpointProxy(openai.moderations, wrapModerations);
12514
12522
  let betaProxy2;
12515
- if (_optionalChain([openai, 'access', _174 => _174.beta, 'optionalAccess', _175 => _175.chat, 'optionalAccess', _176 => _176.completions, 'optionalAccess', _177 => _177.stream])) {
12516
- const betaChatCompletionProxy = new Proxy(_optionalChain([openai, 'optionalAccess', _178 => _178.beta, 'optionalAccess', _179 => _179.chat, 'access', _180 => _180.completions]), {
12523
+ if (_optionalChain([openai, 'access', _171 => _171.beta, 'optionalAccess', _172 => _172.chat, 'optionalAccess', _173 => _173.completions, 'optionalAccess', _174 => _174.stream])) {
12524
+ const betaChatCompletionProxy = new Proxy(_optionalChain([openai, 'optionalAccess', _175 => _175.beta, 'optionalAccess', _176 => _176.chat, 'access', _177 => _177.completions]), {
12517
12525
  get(target, name, receiver) {
12518
12526
  const baseVal = Reflect.get(target, name, receiver);
12519
12527
  if (name === "parse") {
@@ -12561,7 +12569,7 @@ function wrapOpenAIv4(openai) {
12561
12569
  });
12562
12570
  }
12563
12571
  function logCompletionResponse(startTime, response, span) {
12564
- const metrics = parseMetricsFromUsage(_optionalChain([response, 'optionalAccess', _181 => _181.usage]));
12572
+ const metrics = parseMetricsFromUsage(_optionalChain([response, 'optionalAccess', _178 => _178.usage]));
12565
12573
  metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
12566
12574
  span.log({
12567
12575
  output: response.choices,
@@ -12656,55 +12664,80 @@ function logHeaders(response, span) {
12656
12664
  }
12657
12665
  }
12658
12666
  function wrapChatCompletion(completion) {
12659
- return async (allParams, options) => {
12667
+ return (allParams, options) => {
12660
12668
  const { span_info: _, ...params } = allParams;
12661
- const span = startSpan(
12662
- _core.mergeDicts.call(void 0,
12663
- {
12664
- name: "Chat Completion",
12665
- spanAttributes: {
12666
- type: _core.SpanTypeAttribute.LLM
12667
- }
12668
- },
12669
- parseChatCompletionParams(allParams)
12670
- )
12671
- );
12672
- const startTime = getCurrentUnixTimestamp();
12673
- if (params.stream) {
12674
- const { data: ret, response } = await completion(
12675
- // We could get rid of this type coercion if we could somehow enforce
12676
- // that `P extends ChatParams` BUT does not have the property
12677
- // `span_info`.
12678
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
12679
- params,
12680
- options
12681
- ).withResponse();
12682
- logHeaders(response, span);
12683
- const wrapperStream = new WrapperStream(span, startTime, ret.iterator());
12684
- ret.iterator = () => wrapperStream[Symbol.asyncIterator]();
12685
- return ret;
12686
- } else {
12687
- try {
12688
- const completionResponse = completion(
12689
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
12690
- params,
12691
- options
12692
- );
12693
- const { data: ret, response } = await completionResponse.withResponse();
12694
- logHeaders(response, span);
12695
- const { messages, ...rest } = params;
12696
- span.log({
12697
- input: messages,
12698
- metadata: {
12699
- ...rest
12669
+ let executionPromise = null;
12670
+ const executeWrapped = () => {
12671
+ if (!executionPromise) {
12672
+ executionPromise = (async () => {
12673
+ const span = startSpan(
12674
+ _core.mergeDicts.call(void 0,
12675
+ {
12676
+ name: "Chat Completion",
12677
+ spanAttributes: {
12678
+ type: _core.SpanTypeAttribute.LLM
12679
+ }
12680
+ },
12681
+ parseChatCompletionParams(allParams)
12682
+ )
12683
+ );
12684
+ const startTime = getCurrentUnixTimestamp();
12685
+ if (params.stream) {
12686
+ const { data: ret, response } = await completion(
12687
+ // We could get rid of this type coercion if we could somehow enforce
12688
+ // that `P extends ChatParams` BUT does not have the property
12689
+ // `span_info`.
12690
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
12691
+ params,
12692
+ options
12693
+ ).withResponse();
12694
+ logHeaders(response, span);
12695
+ const wrapperStream = new WrapperStream(
12696
+ span,
12697
+ startTime,
12698
+ ret.iterator()
12699
+ );
12700
+ ret.iterator = () => wrapperStream[Symbol.asyncIterator]();
12701
+ return { data: ret, response };
12702
+ } else {
12703
+ try {
12704
+ const completionResponse = completion(
12705
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
12706
+ params,
12707
+ options
12708
+ );
12709
+ const { data: ret, response } = await completionResponse.withResponse();
12710
+ logHeaders(response, span);
12711
+ const { messages, ...rest } = params;
12712
+ span.log({
12713
+ input: messages,
12714
+ metadata: {
12715
+ ...rest
12716
+ }
12717
+ });
12718
+ logCompletionResponse(startTime, ret, span);
12719
+ return { data: ret, response };
12720
+ } finally {
12721
+ span.end();
12722
+ }
12700
12723
  }
12701
- });
12702
- logCompletionResponse(startTime, ret, span);
12703
- return ret;
12704
- } finally {
12705
- span.end();
12724
+ })();
12706
12725
  }
12707
- }
12726
+ return executionPromise;
12727
+ };
12728
+ const dataPromise = executeWrapped().then((result) => result.data);
12729
+ return new Proxy(dataPromise, {
12730
+ get(target, prop, receiver) {
12731
+ if (prop === "withResponse") {
12732
+ return executeWrapped;
12733
+ }
12734
+ const value = Reflect.get(target, prop, receiver);
12735
+ if (typeof value === "function") {
12736
+ return value.bind(target);
12737
+ }
12738
+ return value;
12739
+ }
12740
+ });
12708
12741
  };
12709
12742
  }
12710
12743
  function parseBaseParams(allParams, inputField) {
@@ -12763,7 +12796,7 @@ function parseChatCompletionParams(params) {
12763
12796
  function processEmbeddingResponse(result, span) {
12764
12797
  span.log({
12765
12798
  output: { embedding_length: result.data[0].embedding.length },
12766
- metrics: parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _182 => _182.usage]))
12799
+ metrics: parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _179 => _179.usage]))
12767
12800
  });
12768
12801
  }
12769
12802
  function processModerationResponse(result, span) {
@@ -12793,10 +12826,10 @@ function postprocessStreamingResults(allResults) {
12793
12826
  if (result.usage) {
12794
12827
  metrics = {
12795
12828
  ...metrics,
12796
- ...parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _183 => _183.usage]))
12829
+ ...parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _180 => _180.usage]))
12797
12830
  };
12798
12831
  }
12799
- const delta = _optionalChain([result, 'access', _184 => _184.choices, 'optionalAccess', _185 => _185[0], 'optionalAccess', _186 => _186.delta]);
12832
+ const delta = _optionalChain([result, 'access', _181 => _181.choices, 'optionalAccess', _182 => _182[0], 'optionalAccess', _183 => _183.delta]);
12800
12833
  if (!delta) {
12801
12834
  continue;
12802
12835
  }
@@ -12901,17 +12934,17 @@ function extractAnthropicCacheTokens(cacheReadTokens = 0, cacheCreationTokens =
12901
12934
 
12902
12935
  // src/wrappers/ai-sdk-v2.ts
12903
12936
  function detectProviderFromResult(result) {
12904
- if (!_optionalChain([result, 'optionalAccess', _187 => _187.providerMetadata])) {
12937
+ if (!_optionalChain([result, 'optionalAccess', _184 => _184.providerMetadata])) {
12905
12938
  return void 0;
12906
12939
  }
12907
12940
  const keys = Object.keys(result.providerMetadata);
12908
- return _optionalChain([keys, 'optionalAccess', _188 => _188.at, 'call', _189 => _189(0)]);
12941
+ return _optionalChain([keys, 'optionalAccess', _185 => _185.at, 'call', _186 => _186(0)]);
12909
12942
  }
12910
12943
  function extractModelFromResult(result) {
12911
- if (_optionalChain([result, 'optionalAccess', _190 => _190.response, 'optionalAccess', _191 => _191.modelId])) {
12944
+ if (_optionalChain([result, 'optionalAccess', _187 => _187.response, 'optionalAccess', _188 => _188.modelId])) {
12912
12945
  return result.response.modelId;
12913
12946
  }
12914
- if (_optionalChain([result, 'optionalAccess', _192 => _192.request, 'optionalAccess', _193 => _193.body, 'optionalAccess', _194 => _194.model])) {
12947
+ if (_optionalChain([result, 'optionalAccess', _189 => _189.request, 'optionalAccess', _190 => _190.body, 'optionalAccess', _191 => _191.model])) {
12915
12948
  return result.request.body.model;
12916
12949
  }
12917
12950
  return void 0;
@@ -12971,7 +13004,7 @@ function normalizeUsageMetrics(usage, provider, providerMetadata) {
12971
13004
  metrics.prompt_cached_tokens = cachedInputTokens;
12972
13005
  }
12973
13006
  if (provider === "anthropic") {
12974
- const anthropicMetadata = _optionalChain([providerMetadata, 'optionalAccess', _195 => _195.anthropic]);
13007
+ const anthropicMetadata = _optionalChain([providerMetadata, 'optionalAccess', _192 => _192.anthropic]);
12975
13008
  if (anthropicMetadata) {
12976
13009
  const cacheReadTokens = getNumberProperty(anthropicMetadata.usage, "cache_read_input_tokens") || 0;
12977
13010
  const cacheCreationTokens = getNumberProperty(
@@ -13136,7 +13169,7 @@ function BraintrustMiddleware(config = {}) {
13136
13169
  // src/wrappers/ai-sdk-v1.ts
13137
13170
  function wrapAISDKModel(model) {
13138
13171
  const m = model;
13139
- if (_optionalChain([m, 'optionalAccess', _196 => _196.specificationVersion]) === "v1" && typeof _optionalChain([m, 'optionalAccess', _197 => _197.provider]) === "string" && typeof _optionalChain([m, 'optionalAccess', _198 => _198.modelId]) === "string") {
13172
+ if (_optionalChain([m, 'optionalAccess', _193 => _193.specificationVersion]) === "v1" && typeof _optionalChain([m, 'optionalAccess', _194 => _194.provider]) === "string" && typeof _optionalChain([m, 'optionalAccess', _195 => _195.modelId]) === "string") {
13140
13173
  return new BraintrustLanguageModelWrapper(m);
13141
13174
  } else {
13142
13175
  console.warn("Unsupported AI SDK model. Not wrapping.");
@@ -13192,10 +13225,10 @@ var BraintrustLanguageModelWrapper = class {
13192
13225
  metrics: {
13193
13226
  time_to_first_token: getCurrentUnixTimestamp() - startTime,
13194
13227
  tokens: !isEmpty(ret.usage) ? ret.usage.promptTokens + ret.usage.completionTokens : void 0,
13195
- prompt_tokens: _optionalChain([ret, 'access', _199 => _199.usage, 'optionalAccess', _200 => _200.promptTokens]),
13196
- completion_tokens: _optionalChain([ret, 'access', _201 => _201.usage, 'optionalAccess', _202 => _202.completionTokens]),
13228
+ prompt_tokens: _optionalChain([ret, 'access', _196 => _196.usage, 'optionalAccess', _197 => _197.promptTokens]),
13229
+ completion_tokens: _optionalChain([ret, 'access', _198 => _198.usage, 'optionalAccess', _199 => _199.completionTokens]),
13197
13230
  cached: parseCachedHeader(
13198
- _nullishCoalesce(_optionalChain([ret, 'access', _203 => _203.rawResponse, 'optionalAccess', _204 => _204.headers, 'optionalAccess', _205 => _205[X_CACHED_HEADER]]), () => ( _optionalChain([ret, 'access', _206 => _206.rawResponse, 'optionalAccess', _207 => _207.headers, 'optionalAccess', _208 => _208[LEGACY_CACHED_HEADER]])))
13231
+ _nullishCoalesce(_optionalChain([ret, 'access', _200 => _200.rawResponse, 'optionalAccess', _201 => _201.headers, 'optionalAccess', _202 => _202[X_CACHED_HEADER]]), () => ( _optionalChain([ret, 'access', _203 => _203.rawResponse, 'optionalAccess', _204 => _204.headers, 'optionalAccess', _205 => _205[LEGACY_CACHED_HEADER]])))
13199
13232
  )
13200
13233
  }
13201
13234
  });
@@ -13287,10 +13320,10 @@ var BraintrustLanguageModelWrapper = class {
13287
13320
  metrics: {
13288
13321
  time_to_first_token,
13289
13322
  tokens: !isEmpty(usage) ? usage.promptTokens + usage.completionTokens : void 0,
13290
- prompt_tokens: _optionalChain([usage, 'optionalAccess', _209 => _209.promptTokens]),
13291
- completion_tokens: _optionalChain([usage, 'optionalAccess', _210 => _210.completionTokens]),
13323
+ prompt_tokens: _optionalChain([usage, 'optionalAccess', _206 => _206.promptTokens]),
13324
+ completion_tokens: _optionalChain([usage, 'optionalAccess', _207 => _207.completionTokens]),
13292
13325
  cached: parseCachedHeader(
13293
- _nullishCoalesce(_optionalChain([ret, 'access', _211 => _211.rawResponse, 'optionalAccess', _212 => _212.headers, 'optionalAccess', _213 => _213[X_CACHED_HEADER]]), () => ( _optionalChain([ret, 'access', _214 => _214.rawResponse, 'optionalAccess', _215 => _215.headers, 'optionalAccess', _216 => _216[LEGACY_CACHED_HEADER]])))
13326
+ _nullishCoalesce(_optionalChain([ret, 'access', _208 => _208.rawResponse, 'optionalAccess', _209 => _209.headers, 'optionalAccess', _210 => _210[X_CACHED_HEADER]]), () => ( _optionalChain([ret, 'access', _211 => _211.rawResponse, 'optionalAccess', _212 => _212.headers, 'optionalAccess', _213 => _213[LEGACY_CACHED_HEADER]])))
13294
13327
  )
13295
13328
  }
13296
13329
  });
@@ -13337,7 +13370,7 @@ function postProcessPrompt(prompt) {
13337
13370
  return [
13338
13371
  {
13339
13372
  role: "assistant",
13340
- content: _optionalChain([textPart, 'optionalAccess', _217 => _217.text]),
13373
+ content: _optionalChain([textPart, 'optionalAccess', _214 => _214.text]),
13341
13374
  ...toolCallParts.length > 0 ? {
13342
13375
  tool_calls: toolCallParts.map((part) => ({
13343
13376
  id: part.toolCallId,
@@ -13574,9 +13607,9 @@ function streamNextProxy(stream, sspan) {
13574
13607
  return result;
13575
13608
  }
13576
13609
  const item = result.value;
13577
- switch (_optionalChain([item, 'optionalAccess', _218 => _218.type])) {
13610
+ switch (_optionalChain([item, 'optionalAccess', _215 => _215.type])) {
13578
13611
  case "message_start":
13579
- const msg = _optionalChain([item, 'optionalAccess', _219 => _219.message]);
13612
+ const msg = _optionalChain([item, 'optionalAccess', _216 => _216.message]);
13580
13613
  if (msg) {
13581
13614
  const event = parseEventFromMessage(msg);
13582
13615
  totals = { ...totals, ...event.metrics };
@@ -13584,20 +13617,20 @@ function streamNextProxy(stream, sspan) {
13584
13617
  }
13585
13618
  break;
13586
13619
  case "content_block_delta":
13587
- if (_optionalChain([item, 'access', _220 => _220.delta, 'optionalAccess', _221 => _221.type]) === "text_delta") {
13588
- const text = _optionalChain([item, 'optionalAccess', _222 => _222.delta, 'optionalAccess', _223 => _223.text]);
13620
+ if (_optionalChain([item, 'access', _217 => _217.delta, 'optionalAccess', _218 => _218.type]) === "text_delta") {
13621
+ const text = _optionalChain([item, 'optionalAccess', _219 => _219.delta, 'optionalAccess', _220 => _220.text]);
13589
13622
  if (text) {
13590
13623
  deltas.push(text);
13591
13624
  }
13592
13625
  }
13593
13626
  break;
13594
13627
  case "message_delta":
13595
- const usage = _optionalChain([item, 'optionalAccess', _224 => _224.usage]);
13628
+ const usage = _optionalChain([item, 'optionalAccess', _221 => _221.usage]);
13596
13629
  if (usage) {
13597
13630
  const metrics = parseMetricsFromUsage2(usage);
13598
13631
  totals = { ...totals, ...metrics };
13599
13632
  }
13600
- const delta = _optionalChain([item, 'optionalAccess', _225 => _225.delta]);
13633
+ const delta = _optionalChain([item, 'optionalAccess', _222 => _222.delta]);
13601
13634
  if (delta) {
13602
13635
  metadata = { ...metadata, ...delta };
13603
13636
  }
@@ -13609,8 +13642,8 @@ function streamNextProxy(stream, sspan) {
13609
13642
  };
13610
13643
  }
13611
13644
  function parseEventFromMessage(message) {
13612
- const output = _optionalChain([message, 'optionalAccess', _226 => _226.content]) || null;
13613
- const metrics = parseMetricsFromUsage2(_optionalChain([message, 'optionalAccess', _227 => _227.usage]));
13645
+ const output = _optionalChain([message, 'optionalAccess', _223 => _223.content]) || null;
13646
+ const metrics = parseMetricsFromUsage2(_optionalChain([message, 'optionalAccess', _224 => _224.usage]));
13614
13647
  const metas = ["stop_reason", "stop_sequence"];
13615
13648
  const metadata = {};
13616
13649
  for (const m of metas) {
package/dist/index.mjs CHANGED
@@ -12228,19 +12228,15 @@ function responsesCreateProxy(target) {
12228
12228
  return proxyCreate(target, hooks);
12229
12229
  }
12230
12230
  function parseSpanFromResponseCreateParams(params) {
12231
- const input = [{ role: "user", content: params.input }];
12232
- if (params.instructions) {
12233
- input.push({ role: "system", content: params.instructions });
12234
- }
12235
12231
  const spanArgs = {
12236
12232
  name: "openai.responses.create",
12237
12233
  spanAttributes: {
12238
12234
  type: "llm"
12239
12235
  },
12240
12236
  event: {
12241
- input,
12237
+ input: params.input,
12242
12238
  metadata: {
12243
- ...filterFrom(params, ["input", "instructions"]),
12239
+ ...filterFrom(params, ["input"]),
12244
12240
  provider: "openai"
12245
12241
  }
12246
12242
  },
@@ -12252,25 +12248,29 @@ function parseSpanFromResponseCreateParams(params) {
12252
12248
  };
12253
12249
  }
12254
12250
  function parseEventFromResponseCreateResult(result) {
12255
- return {
12256
- output: result?.output_text || "",
12257
- metrics: parseMetricsFromUsage(result?.usage)
12258
- };
12251
+ const data = {};
12252
+ if (result?.output !== void 0) {
12253
+ data.output = result.output;
12254
+ }
12255
+ if (result) {
12256
+ const { output, usage, ...metadata } = result;
12257
+ if (Object.keys(metadata).length > 0) {
12258
+ data.metadata = metadata;
12259
+ }
12260
+ }
12261
+ data.metrics = parseMetricsFromUsage(result?.usage);
12262
+ return data;
12259
12263
  }
12260
12264
  function parseSpanFromResponseParseParams(params) {
12261
- const input = [{ role: "user", content: params.input }];
12262
- if (params.instructions) {
12263
- input.push({ role: "system", content: params.instructions });
12264
- }
12265
12265
  const spanArgs = {
12266
12266
  name: "openai.responses.parse",
12267
12267
  spanAttributes: {
12268
12268
  type: "llm"
12269
12269
  },
12270
12270
  event: {
12271
- input,
12271
+ input: params.input,
12272
12272
  metadata: {
12273
- ...filterFrom(params, ["input", "instructions"]),
12273
+ ...filterFrom(params, ["input"]),
12274
12274
  provider: "openai"
12275
12275
  }
12276
12276
  },
@@ -12282,10 +12282,18 @@ function parseSpanFromResponseParseParams(params) {
12282
12282
  };
12283
12283
  }
12284
12284
  function parseEventFromResponseParseResult(result) {
12285
- return {
12286
- output: result?.output_parsed || result?.output_text || "",
12287
- metrics: parseMetricsFromUsage(result?.usage)
12288
- };
12285
+ const data = {};
12286
+ if (result?.output !== void 0) {
12287
+ data.output = result.output;
12288
+ }
12289
+ if (result) {
12290
+ const { output, usage, ...metadata } = result;
12291
+ if (Object.keys(metadata).length > 0) {
12292
+ data.metadata = metadata;
12293
+ }
12294
+ }
12295
+ data.metrics = parseMetricsFromUsage(result?.usage);
12296
+ return data;
12289
12297
  }
12290
12298
  function traceResponseCreateStream(stream, timedSpan) {
12291
12299
  const span = timedSpan.span;
@@ -12318,18 +12326,18 @@ function parseLogFromItem(item) {
12318
12326
  const response = item.response;
12319
12327
  switch (item.type) {
12320
12328
  case "response.completed":
12321
- const texts = [];
12322
- for (const output of response?.output || []) {
12323
- for (const content of output?.content || []) {
12324
- if (content?.type === "output_text") {
12325
- texts.push(content.text);
12326
- }
12329
+ const data = {};
12330
+ if (response?.output !== void 0) {
12331
+ data.output = response.output;
12332
+ }
12333
+ if (response) {
12334
+ const { usage, output, ...metadata } = response;
12335
+ if (Object.keys(metadata).length > 0) {
12336
+ data.metadata = metadata;
12327
12337
  }
12328
12338
  }
12329
- return {
12330
- output: texts.join(""),
12331
- metrics: parseMetricsFromUsage(response?.usage)
12332
- };
12339
+ data.metrics = parseMetricsFromUsage(response?.usage);
12340
+ return data;
12333
12341
  default:
12334
12342
  return {};
12335
12343
  }
@@ -12656,55 +12664,80 @@ function logHeaders(response, span) {
12656
12664
  }
12657
12665
  }
12658
12666
  function wrapChatCompletion(completion) {
12659
- return async (allParams, options) => {
12667
+ return (allParams, options) => {
12660
12668
  const { span_info: _, ...params } = allParams;
12661
- const span = startSpan(
12662
- mergeDicts3(
12663
- {
12664
- name: "Chat Completion",
12665
- spanAttributes: {
12666
- type: SpanTypeAttribute3.LLM
12667
- }
12668
- },
12669
- parseChatCompletionParams(allParams)
12670
- )
12671
- );
12672
- const startTime = getCurrentUnixTimestamp();
12673
- if (params.stream) {
12674
- const { data: ret, response } = await completion(
12675
- // We could get rid of this type coercion if we could somehow enforce
12676
- // that `P extends ChatParams` BUT does not have the property
12677
- // `span_info`.
12678
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
12679
- params,
12680
- options
12681
- ).withResponse();
12682
- logHeaders(response, span);
12683
- const wrapperStream = new WrapperStream(span, startTime, ret.iterator());
12684
- ret.iterator = () => wrapperStream[Symbol.asyncIterator]();
12685
- return ret;
12686
- } else {
12687
- try {
12688
- const completionResponse = completion(
12689
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
12690
- params,
12691
- options
12692
- );
12693
- const { data: ret, response } = await completionResponse.withResponse();
12694
- logHeaders(response, span);
12695
- const { messages, ...rest } = params;
12696
- span.log({
12697
- input: messages,
12698
- metadata: {
12699
- ...rest
12669
+ let executionPromise = null;
12670
+ const executeWrapped = () => {
12671
+ if (!executionPromise) {
12672
+ executionPromise = (async () => {
12673
+ const span = startSpan(
12674
+ mergeDicts3(
12675
+ {
12676
+ name: "Chat Completion",
12677
+ spanAttributes: {
12678
+ type: SpanTypeAttribute3.LLM
12679
+ }
12680
+ },
12681
+ parseChatCompletionParams(allParams)
12682
+ )
12683
+ );
12684
+ const startTime = getCurrentUnixTimestamp();
12685
+ if (params.stream) {
12686
+ const { data: ret, response } = await completion(
12687
+ // We could get rid of this type coercion if we could somehow enforce
12688
+ // that `P extends ChatParams` BUT does not have the property
12689
+ // `span_info`.
12690
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
12691
+ params,
12692
+ options
12693
+ ).withResponse();
12694
+ logHeaders(response, span);
12695
+ const wrapperStream = new WrapperStream(
12696
+ span,
12697
+ startTime,
12698
+ ret.iterator()
12699
+ );
12700
+ ret.iterator = () => wrapperStream[Symbol.asyncIterator]();
12701
+ return { data: ret, response };
12702
+ } else {
12703
+ try {
12704
+ const completionResponse = completion(
12705
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
12706
+ params,
12707
+ options
12708
+ );
12709
+ const { data: ret, response } = await completionResponse.withResponse();
12710
+ logHeaders(response, span);
12711
+ const { messages, ...rest } = params;
12712
+ span.log({
12713
+ input: messages,
12714
+ metadata: {
12715
+ ...rest
12716
+ }
12717
+ });
12718
+ logCompletionResponse(startTime, ret, span);
12719
+ return { data: ret, response };
12720
+ } finally {
12721
+ span.end();
12722
+ }
12700
12723
  }
12701
- });
12702
- logCompletionResponse(startTime, ret, span);
12703
- return ret;
12704
- } finally {
12705
- span.end();
12724
+ })();
12706
12725
  }
12707
- }
12726
+ return executionPromise;
12727
+ };
12728
+ const dataPromise = executeWrapped().then((result) => result.data);
12729
+ return new Proxy(dataPromise, {
12730
+ get(target, prop, receiver) {
12731
+ if (prop === "withResponse") {
12732
+ return executeWrapped;
12733
+ }
12734
+ const value = Reflect.get(target, prop, receiver);
12735
+ if (typeof value === "function") {
12736
+ return value.bind(target);
12737
+ }
12738
+ return value;
12739
+ }
12740
+ });
12708
12741
  };
12709
12742
  }
12710
12743
  function parseBaseParams(allParams, inputField) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "braintrust",
3
- "version": "0.2.6",
3
+ "version": "0.3.6",
4
4
  "description": "SDK for integrating Braintrust",
5
5
  "repository": {
6
6
  "type": "git",