braintrust 3.4.0 → 3.5.0

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.
Files changed (50) hide show
  1. package/dev/dist/index.d.mts +45 -5
  2. package/dev/dist/index.d.ts +45 -5
  3. package/dev/dist/index.js +992 -245
  4. package/dev/dist/index.mjs +914 -167
  5. package/dist/auto-instrumentations/bundler/esbuild.cjs +208 -10
  6. package/dist/auto-instrumentations/bundler/esbuild.d.mts +2 -2
  7. package/dist/auto-instrumentations/bundler/esbuild.d.ts +2 -2
  8. package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
  9. package/dist/auto-instrumentations/bundler/rollup.cjs +208 -10
  10. package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
  11. package/dist/auto-instrumentations/bundler/vite.cjs +208 -10
  12. package/dist/auto-instrumentations/bundler/vite.d.mts +2 -2
  13. package/dist/auto-instrumentations/bundler/vite.d.ts +2 -2
  14. package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
  15. package/dist/auto-instrumentations/bundler/webpack.cjs +208 -10
  16. package/dist/auto-instrumentations/bundler/webpack.d.mts +2 -2
  17. package/dist/auto-instrumentations/bundler/webpack.d.ts +2 -2
  18. package/dist/auto-instrumentations/bundler/webpack.mjs +2 -2
  19. package/dist/auto-instrumentations/{chunk-LVWWLUMN.mjs → chunk-DQTPSXJB.mjs} +208 -10
  20. package/dist/auto-instrumentations/chunk-EVUKFMHG.mjs +41 -0
  21. package/dist/auto-instrumentations/{chunk-D5ZPIUEL.mjs → chunk-F3TJZ3Z2.mjs} +1 -1
  22. package/dist/auto-instrumentations/chunk-VLEJ5AEK.mjs +41 -0
  23. package/dist/auto-instrumentations/hook.mjs +238 -18
  24. package/dist/auto-instrumentations/index.cjs +208 -10
  25. package/dist/auto-instrumentations/index.mjs +1 -1
  26. package/dist/auto-instrumentations/loader/cjs-patch.cjs +32 -10
  27. package/dist/auto-instrumentations/loader/cjs-patch.mjs +10 -5
  28. package/dist/auto-instrumentations/loader/esm-hook.mjs +4 -4
  29. package/dist/auto-instrumentations/loader/get-package-version.cjs +28 -8
  30. package/dist/auto-instrumentations/loader/get-package-version.d.mts +2 -1
  31. package/dist/auto-instrumentations/loader/get-package-version.d.ts +2 -1
  32. package/dist/auto-instrumentations/loader/get-package-version.mjs +3 -1
  33. package/dist/browser.d.mts +342 -269
  34. package/dist/browser.d.ts +342 -269
  35. package/dist/browser.js +996 -241
  36. package/dist/browser.mjs +996 -241
  37. package/dist/cli.js +1029 -289
  38. package/dist/edge-light.js +1007 -220
  39. package/dist/edge-light.mjs +1007 -220
  40. package/dist/index.d.mts +342 -269
  41. package/dist/index.d.ts +342 -269
  42. package/dist/index.js +1182 -427
  43. package/dist/index.mjs +996 -241
  44. package/dist/instrumentation/index.js +781 -107
  45. package/dist/instrumentation/index.mjs +781 -107
  46. package/dist/workerd.js +1007 -220
  47. package/dist/workerd.mjs +1007 -220
  48. package/package.json +22 -6
  49. package/dist/auto-instrumentations/chunk-XDBPUTVE.mjs +0 -22
  50. package/dist/auto-instrumentations/chunk-ZEC7BCL4.mjs +0 -22
@@ -17,8 +17,54 @@ var DefaultAsyncLocalStorage = class {
17
17
  return void 0;
18
18
  }
19
19
  };
20
- var DefaultTracingChannel = class {
20
+ var DefaultChannel = class {
21
+ constructor(name) {
22
+ this.name = name;
23
+ }
21
24
  hasSubscribers = false;
25
+ subscribe(_subscription) {
26
+ }
27
+ unsubscribe(_subscription) {
28
+ return false;
29
+ }
30
+ bindStore(_store, _transform) {
31
+ }
32
+ unbindStore(_store) {
33
+ return false;
34
+ }
35
+ publish(_message) {
36
+ }
37
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
+ runStores(_message, fn, thisArg, ...args) {
39
+ return fn.apply(thisArg, args);
40
+ }
41
+ };
42
+ var DefaultTracingChannel = class {
43
+ start;
44
+ end;
45
+ asyncStart;
46
+ asyncEnd;
47
+ error;
48
+ constructor(nameOrChannels) {
49
+ if (typeof nameOrChannels === "string") {
50
+ this.start = new DefaultChannel(`tracing:${nameOrChannels}:start`);
51
+ this.end = new DefaultChannel(`tracing:${nameOrChannels}:end`);
52
+ this.asyncStart = new DefaultChannel(
53
+ `tracing:${nameOrChannels}:asyncStart`
54
+ );
55
+ this.asyncEnd = new DefaultChannel(`tracing:${nameOrChannels}:asyncEnd`);
56
+ this.error = new DefaultChannel(`tracing:${nameOrChannels}:error`);
57
+ return;
58
+ }
59
+ this.start = nameOrChannels.start ?? new DefaultChannel("tracing:start");
60
+ this.end = nameOrChannels.end ?? new DefaultChannel("tracing:end");
61
+ this.asyncStart = nameOrChannels.asyncStart ?? new DefaultChannel("tracing:asyncStart");
62
+ this.asyncEnd = nameOrChannels.asyncEnd ?? new DefaultChannel("tracing:asyncEnd");
63
+ this.error = nameOrChannels.error ?? new DefaultChannel("tracing:error");
64
+ }
65
+ get hasSubscribers() {
66
+ return this.start.hasSubscribers || this.end.hasSubscribers || this.asyncStart.hasSubscribers || this.asyncEnd.hasSubscribers || this.error.hasSubscribers;
67
+ }
22
68
  subscribe(_handlers) {
23
69
  }
24
70
  unsubscribe(_handlers) {
@@ -46,7 +92,7 @@ var iso = {
46
92
  getCallerLocation: () => void 0,
47
93
  newAsyncLocalStorage: () => new DefaultAsyncLocalStorage(),
48
94
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
49
- newTracingChannel: (_nameOrChannels) => new DefaultTracingChannel(),
95
+ newTracingChannel: (nameOrChannels) => new DefaultTracingChannel(nameOrChannels),
50
96
  processOn: (_0, _1) => {
51
97
  },
52
98
  basename: (filepath) => filepath.split(/[\\/]/).pop() || filepath,
@@ -2113,6 +2159,8 @@ var Experiment = z6.object({
2113
2159
  deleted_at: z6.union([z6.string(), z6.null()]).optional(),
2114
2160
  dataset_id: z6.union([z6.string(), z6.null()]).optional(),
2115
2161
  dataset_version: z6.union([z6.string(), z6.null()]).optional(),
2162
+ parameters_id: z6.union([z6.string(), z6.null()]).optional(),
2163
+ parameters_version: z6.union([z6.string(), z6.null()]).optional(),
2116
2164
  public: z6.boolean(),
2117
2165
  user_id: z6.union([z6.string(), z6.null()]).optional(),
2118
2166
  metadata: z6.union([z6.object({}).partial().passthrough(), z6.null()]).optional(),
@@ -2135,7 +2183,11 @@ var SpanType = z6.union([
2135
2183
  z6.null()
2136
2184
  ]);
2137
2185
  var SpanAttributes = z6.union([
2138
- z6.object({ name: z6.union([z6.string(), z6.null()]), type: SpanType }).partial().passthrough(),
2186
+ z6.object({
2187
+ name: z6.union([z6.string(), z6.null()]),
2188
+ type: SpanType,
2189
+ purpose: z6.union([z6.literal("scorer"), z6.null()])
2190
+ }).partial().passthrough(),
2139
2191
  z6.null()
2140
2192
  ]);
2141
2193
  var ExperimentEvent = z6.object({
@@ -2575,6 +2627,7 @@ var FunctionId = z6.union([
2575
2627
  version: z6.string()
2576
2628
  }),
2577
2629
  code: z6.string(),
2630
+ function_type: FunctionTypeEnum.and(z6.unknown()).optional(),
2578
2631
  name: z6.union([z6.string(), z6.null()]).optional()
2579
2632
  }),
2580
2633
  z6.object({
@@ -2804,7 +2857,12 @@ var TopicAutomationConfig = z6.object({
2804
2857
  topic_map_functions: z6.array(TopicMapFunctionAutomation),
2805
2858
  scope: z6.union([SpanScope, TraceScope, GroupScope, z6.null()]).optional(),
2806
2859
  data_scope: TopicAutomationDataScope.optional(),
2807
- btql_filter: z6.union([z6.string(), z6.null()]).optional()
2860
+ btql_filter: z6.union([z6.string(), z6.null()]).optional(),
2861
+ backfill_time_range: z6.union([
2862
+ z6.string(),
2863
+ z6.object({ from: z6.string(), to: z6.string() }),
2864
+ z6.null()
2865
+ ]).optional()
2808
2866
  });
2809
2867
  var ProjectAutomation = z6.object({
2810
2868
  id: z6.string().uuid(),
@@ -4243,6 +4301,12 @@ var parametersRowSchema = z8.object({
4243
4301
  }),
4244
4302
  metadata: z8.union([z8.object({}).partial().passthrough(), z8.null()]).optional()
4245
4303
  });
4304
+ var InlineAttachmentReferenceSchema = z8.object({
4305
+ type: z8.literal("inline_attachment"),
4306
+ src: z8.string().min(1),
4307
+ content_type: z8.string().optional(),
4308
+ filename: z8.string().optional()
4309
+ });
4246
4310
  var LoginInvalidOrgError = class extends Error {
4247
4311
  constructor(message) {
4248
4312
  super(message);
@@ -6444,6 +6508,7 @@ function init(projectOrOptions, optionalOptions) {
6444
6508
  experiment,
6445
6509
  description,
6446
6510
  dataset,
6511
+ parameters,
6447
6512
  baseExperiment,
6448
6513
  isPublic,
6449
6514
  open,
@@ -6561,6 +6626,17 @@ function init(projectOrOptions, optionalOptions) {
6561
6626
  args["dataset_version"] = await dataset.version();
6562
6627
  }
6563
6628
  }
6629
+ if (parameters !== void 0) {
6630
+ if (RemoteEvalParameters.isParameters(parameters)) {
6631
+ args["parameters_id"] = parameters.id;
6632
+ args["parameters_version"] = parameters.version;
6633
+ } else {
6634
+ args["parameters_id"] = parameters.id;
6635
+ if (parameters.version !== void 0) {
6636
+ args["parameters_version"] = parameters.version;
6637
+ }
6638
+ }
6639
+ }
6564
6640
  if (isPublic !== void 0) {
6565
6641
  args["public"] = isPublic;
6566
6642
  }
@@ -8759,40 +8835,85 @@ var Dataset2 = class extends ObjectFetcher {
8759
8835
  return typeof data === "object" && data !== null && "__braintrust_dataset_marker" in data;
8760
8836
  }
8761
8837
  };
8838
+ function isAttachmentObject(value) {
8839
+ return BraintrustAttachmentReference.safeParse(value).success || InlineAttachmentReferenceSchema.safeParse(value).success || ExternalAttachmentReference.safeParse(value).success;
8840
+ }
8841
+ function isURL(url) {
8842
+ try {
8843
+ const parsedUrl = new URL(url.trim());
8844
+ return parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:";
8845
+ } catch {
8846
+ return false;
8847
+ }
8848
+ }
8849
+ function expandAttachmentArrayPreTemplate(content, variables) {
8850
+ if (typeof content !== "string") return null;
8851
+ const match = content.match(/^\{\{\s*([\w.]+)\s*\}\}$/);
8852
+ if (!match) return null;
8853
+ const varPath = match[1];
8854
+ const value = varPath.includes(".") ? getObjValueByPath(variables, varPath.split(".")) : variables[varPath];
8855
+ if (!Array.isArray(value)) return null;
8856
+ const allValid = value.every(
8857
+ (v) => isAttachmentObject(v) || typeof v === "string" && isURL(v)
8858
+ );
8859
+ if (!allValid) return null;
8860
+ return value.map((item) => ({
8861
+ type: "image_url",
8862
+ image_url: { url: item }
8863
+ }));
8864
+ }
8762
8865
  function renderMessage(render, message) {
8866
+ return renderMessageImpl(render, message, {});
8867
+ }
8868
+ function renderMessageImpl(render, message, variables) {
8763
8869
  return {
8764
8870
  ...message,
8765
8871
  ..."content" in message ? {
8766
- content: isEmpty2(message.content) ? void 0 : typeof message.content === "string" ? render(message.content) : message.content.map((c) => {
8872
+ content: isEmpty2(message.content) ? void 0 : typeof message.content === "string" ? render(message.content) : message.content.flatMap((c) => {
8767
8873
  switch (c.type) {
8768
8874
  case "text":
8769
- return { ...c, text: render(c.text) };
8875
+ return [{ ...c, text: render(c.text) }];
8770
8876
  case "image_url":
8771
8877
  if (isObject(c.image_url.url)) {
8772
8878
  throw new Error(
8773
8879
  "Attachments must be replaced with URLs before calling `build()`"
8774
8880
  );
8775
8881
  }
8776
- return {
8777
- ...c,
8778
- image_url: {
8779
- ...c.image_url,
8780
- url: render(c.image_url.url)
8882
+ if (variables) {
8883
+ const expanded = expandAttachmentArrayPreTemplate(
8884
+ c.image_url.url,
8885
+ variables
8886
+ );
8887
+ if (expanded) {
8888
+ return expanded;
8781
8889
  }
8782
- };
8890
+ }
8891
+ return [
8892
+ {
8893
+ ...c,
8894
+ image_url: {
8895
+ ...c.image_url,
8896
+ url: render(c.image_url.url)
8897
+ }
8898
+ }
8899
+ ];
8783
8900
  case "file":
8784
- return {
8785
- ...c,
8786
- file: {
8787
- file_data: render(c.file.file_data || ""),
8788
- ...c.file.file_id && {
8789
- file_id: render(c.file.file_id)
8790
- },
8791
- ...c.file.filename && {
8792
- filename: render(c.file.filename)
8901
+ return [
8902
+ {
8903
+ ...c,
8904
+ file: {
8905
+ ...c.file.file_data && {
8906
+ file_data: render(c.file.file_data)
8907
+ },
8908
+ ...c.file.file_id && {
8909
+ file_id: render(c.file.file_id)
8910
+ },
8911
+ ...c.file.filename && {
8912
+ filename: render(c.file.filename)
8913
+ }
8793
8914
  }
8794
8915
  }
8795
- };
8916
+ ];
8796
8917
  default:
8797
8918
  const _exhaustiveCheck = c;
8798
8919
  return _exhaustiveCheck;
@@ -8949,17 +9070,19 @@ var Prompt2 = class _Prompt {
8949
9070
  }
8950
9071
  runBuild(buildArgs, options) {
8951
9072
  const { flavor } = options;
8952
- const params = {
8953
- ...this.defaults,
8954
- ...Object.fromEntries(
8955
- Object.entries(this.options.params || {}).filter(
8956
- ([k, _v]) => !BRAINTRUST_PARAMS.includes(k)
8957
- )
8958
- ),
8959
- ...!isEmpty2(this.options.model) ? {
8960
- model: this.options.model
8961
- } : {}
8962
- };
9073
+ const params = Object.fromEntries(
9074
+ Object.entries({
9075
+ ...this.defaults,
9076
+ ...Object.fromEntries(
9077
+ Object.entries(this.options.params || {}).filter(
9078
+ ([k, _v]) => !BRAINTRUST_PARAMS.includes(k)
9079
+ )
9080
+ ),
9081
+ ...!isEmpty2(this.options.model) ? {
9082
+ model: this.options.model
9083
+ } : {}
9084
+ }).filter(([key, value]) => key !== "response_format" || value !== null)
9085
+ );
8963
9086
  if (!("model" in params) || isEmpty2(params.model)) {
8964
9087
  throw new Error(
8965
9088
  "No model specified. Either specify it in the prompt or as a default"
@@ -9059,7 +9182,7 @@ var Prompt2 = class _Prompt {
9059
9182
  templateFormat
9060
9183
  });
9061
9184
  const baseMessages = (prompt.messages || []).map(
9062
- (m) => renderMessage(render, m)
9185
+ (m) => renderMessageImpl(render, m, variables)
9063
9186
  );
9064
9187
  const hasSystemPrompt = baseMessages.some((m) => m.role === "system");
9065
9188
  const messages = [
@@ -9257,6 +9380,40 @@ var _exportsForTestingOnly = {
9257
9380
  // Expose isomorph for build type detection
9258
9381
  };
9259
9382
 
9383
+ // src/runtime-async-local-storage.ts
9384
+ function isAsyncLocalStorageConstructor(candidate) {
9385
+ return typeof candidate === "function";
9386
+ }
9387
+ function resolveRuntimeAsyncLocalStorage() {
9388
+ try {
9389
+ const globalAsyncLocalStorage = Reflect.get(
9390
+ globalThis,
9391
+ "AsyncLocalStorage"
9392
+ );
9393
+ if (isAsyncLocalStorageConstructor(globalAsyncLocalStorage)) {
9394
+ return globalAsyncLocalStorage;
9395
+ }
9396
+ if (typeof process === "undefined") {
9397
+ return void 0;
9398
+ }
9399
+ const getBuiltinModule = Reflect.get(process, "getBuiltinModule");
9400
+ if (typeof getBuiltinModule !== "function") {
9401
+ return void 0;
9402
+ }
9403
+ const asyncHooksModule = getBuiltinModule("node:async_hooks");
9404
+ if (typeof asyncHooksModule !== "object" || asyncHooksModule === null) {
9405
+ return void 0;
9406
+ }
9407
+ if (!("AsyncLocalStorage" in asyncHooksModule)) {
9408
+ return void 0;
9409
+ }
9410
+ const { AsyncLocalStorage: runtimeAsyncLocalStorage } = asyncHooksModule;
9411
+ return isAsyncLocalStorageConstructor(runtimeAsyncLocalStorage) ? runtimeAsyncLocalStorage : void 0;
9412
+ } catch {
9413
+ return void 0;
9414
+ }
9415
+ }
9416
+
9260
9417
  // src/edge-light/config.ts
9261
9418
  var edgeLightConfigured = false;
9262
9419
  function configureEdgeLight() {
@@ -9264,11 +9421,9 @@ function configureEdgeLight() {
9264
9421
  return;
9265
9422
  }
9266
9423
  isomorph_default.buildType = "edge-light";
9267
- try {
9268
- if (typeof AsyncLocalStorage !== "undefined") {
9269
- isomorph_default.newAsyncLocalStorage = () => new AsyncLocalStorage();
9270
- }
9271
- } catch {
9424
+ const runtimeAsyncLocalStorage = resolveRuntimeAsyncLocalStorage();
9425
+ if (runtimeAsyncLocalStorage) {
9426
+ isomorph_default.newAsyncLocalStorage = () => new runtimeAsyncLocalStorage();
9272
9427
  }
9273
9428
  isomorph_default.getEnv = (name) => {
9274
9429
  if (typeof process === "undefined" || typeof process.env === "undefined") {
@@ -10029,15 +10184,23 @@ function createEndpointProxy(target, wrapperFn) {
10029
10184
  });
10030
10185
  }
10031
10186
  function wrapApiCreateWithChannel(create, channel2) {
10032
- return async (allParams, options) => {
10187
+ return (allParams, options) => {
10033
10188
  const { span_info, params } = splitSpanInfo(allParams);
10034
- const traceContext = createChannelContext(channel2, params, span_info);
10035
- const { data } = await tracePromiseWithResponse(
10036
- channel2,
10037
- traceContext,
10038
- create(params, options)
10039
- );
10040
- return data;
10189
+ let executionPromise = null;
10190
+ const ensureExecuted = () => {
10191
+ if (!executionPromise) {
10192
+ executionPromise = (async () => {
10193
+ const traceContext = createChannelContext(channel2, params, span_info);
10194
+ return tracePromiseWithResponse(
10195
+ channel2,
10196
+ traceContext,
10197
+ create(params, options)
10198
+ );
10199
+ })();
10200
+ }
10201
+ return executionPromise;
10202
+ };
10203
+ return createLazyAPIPromise(ensureExecuted);
10041
10204
  };
10042
10205
  }
10043
10206
  var wrapEmbeddings = (create) => wrapApiCreateWithChannel(create, openAIChannels.embeddingsCreate);
@@ -10217,6 +10380,93 @@ function zodToJsonSchema(schema) {
10217
10380
  return zodToJsonSchemaV3(schema);
10218
10381
  }
10219
10382
 
10383
+ // src/wrappers/ai-sdk/normalize-logged-output.ts
10384
+ var REMOVE_NORMALIZED_VALUE = Symbol("braintrust.ai-sdk.remove-normalized");
10385
+ function normalizeAISDKLoggedOutput(value) {
10386
+ const normalized = normalizeAISDKLoggedValue(value);
10387
+ return normalized === REMOVE_NORMALIZED_VALUE ? {} : normalized;
10388
+ }
10389
+ function normalizeAISDKLoggedValue(value, context = {}) {
10390
+ if (Array.isArray(value)) {
10391
+ return value.map((entry) => normalizeAISDKLoggedValue(entry, context)).filter((entry) => entry !== REMOVE_NORMALIZED_VALUE);
10392
+ }
10393
+ if (!value || typeof value !== "object") {
10394
+ return value;
10395
+ }
10396
+ const nextInProviderMetadata = context.inProviderMetadata || context.parentKey === "providerMetadata" || context.parentKey === "experimental_providerMetadata";
10397
+ const normalizedEntries = [];
10398
+ for (const [key, entry] of Object.entries(value)) {
10399
+ if (key === "cachedPromptTokens" && entry === 0) {
10400
+ continue;
10401
+ }
10402
+ if (context.parentKey === "request" && key === "body" && entry === "<omitted>") {
10403
+ continue;
10404
+ }
10405
+ const normalizedEntry = normalizeAISDKLoggedValue(entry, {
10406
+ inProviderMetadata: nextInProviderMetadata,
10407
+ parentKey: key
10408
+ });
10409
+ if (normalizedEntry === REMOVE_NORMALIZED_VALUE) {
10410
+ continue;
10411
+ }
10412
+ normalizedEntries.push([key, normalizedEntry]);
10413
+ }
10414
+ if (normalizedEntries.length === 0) {
10415
+ if (context.parentKey === "request" || nextInProviderMetadata) {
10416
+ return REMOVE_NORMALIZED_VALUE;
10417
+ }
10418
+ return {};
10419
+ }
10420
+ return Object.fromEntries(normalizedEntries);
10421
+ }
10422
+
10423
+ // src/wrappers/ai-sdk/tool-serialization.ts
10424
+ function isZodSchema(value) {
10425
+ return value != null && typeof value === "object" && "_def" in value && typeof value._def === "object";
10426
+ }
10427
+ function serializeZodSchema(schema) {
10428
+ try {
10429
+ return zodToJsonSchema(schema);
10430
+ } catch {
10431
+ return {
10432
+ type: "object",
10433
+ description: "Zod schema (conversion failed)"
10434
+ };
10435
+ }
10436
+ }
10437
+ function serializeTool(tool) {
10438
+ if (!tool || typeof tool !== "object") {
10439
+ return tool;
10440
+ }
10441
+ const serialized = { ...tool };
10442
+ if (isZodSchema(serialized.inputSchema)) {
10443
+ serialized.inputSchema = serializeZodSchema(serialized.inputSchema);
10444
+ }
10445
+ if (isZodSchema(serialized.parameters)) {
10446
+ serialized.parameters = serializeZodSchema(serialized.parameters);
10447
+ }
10448
+ if ("execute" in serialized) {
10449
+ delete serialized.execute;
10450
+ }
10451
+ if ("render" in serialized) {
10452
+ delete serialized.render;
10453
+ }
10454
+ return serialized;
10455
+ }
10456
+ function serializeAISDKToolsForLogging(tools) {
10457
+ if (!tools || typeof tools !== "object") {
10458
+ return tools;
10459
+ }
10460
+ if (Array.isArray(tools)) {
10461
+ return tools.map(serializeTool);
10462
+ }
10463
+ const serialized = {};
10464
+ for (const [key, tool] of Object.entries(tools)) {
10465
+ serialized[key] = serializeTool(tool);
10466
+ }
10467
+ return serialized;
10468
+ }
10469
+
10220
10470
  // src/wrappers/ai-sdk/ai-sdk.ts
10221
10471
  var DENY_OUTPUT_PATHS = [
10222
10472
  // v3
@@ -10311,9 +10561,11 @@ var wrapAgentGenerate = (generate, instance, options = {}) => {
10311
10561
  return async (params) => makeGenerateTextWrapper(
10312
10562
  `${instance.constructor.name}.generate`,
10313
10563
  options,
10314
- generate.bind(instance)
10564
+ generate.bind(instance),
10315
10565
  // as of v5 this is just streamText under the hood
10316
10566
  // Follows what the AI SDK does under the hood when calling generateText
10567
+ void 0,
10568
+ "function" /* FUNCTION */
10317
10569
  )({ ...instance.settings, ...params });
10318
10570
  };
10319
10571
  var wrapAgentStream = (stream, instance, options = {}) => {
@@ -10322,11 +10574,12 @@ var wrapAgentStream = (stream, instance, options = {}) => {
10322
10574
  options,
10323
10575
  stream.bind(instance),
10324
10576
  // as of v5 this is just streamText under the hood
10325
- void 0
10577
+ void 0,
10326
10578
  // aiSDK not needed since model is already on instance
10579
+ "function" /* FUNCTION */
10327
10580
  )({ ...instance.settings, ...params });
10328
10581
  };
10329
- var makeGenerateTextWrapper = (name, options, generateText, aiSDK) => {
10582
+ var makeGenerateTextWrapper = (name, options, generateText, aiSDK, spanType = "llm" /* LLM */) => {
10330
10583
  const wrapper = async function(allParams) {
10331
10584
  const { span_info, ...params } = allParams;
10332
10585
  const {
@@ -10335,6 +10588,7 @@ var makeGenerateTextWrapper = (name, options, generateText, aiSDK) => {
10335
10588
  spanAttributes: spanInfoAttrs
10336
10589
  } = span_info ?? {};
10337
10590
  const { model, provider } = serializeModelWithProvider(params.model);
10591
+ const serializedTools = serializeAISDKToolsForLogging(params.tools);
10338
10592
  const processedInput = await processInputAttachments2(params);
10339
10593
  return traced(
10340
10594
  async (span) => {
@@ -10365,7 +10619,7 @@ var makeGenerateTextWrapper = (name, options, generateText, aiSDK) => {
10365
10619
  {
10366
10620
  name: spanName || name,
10367
10621
  spanAttributes: {
10368
- type: "llm" /* LLM */,
10622
+ type: spanType,
10369
10623
  ...spanInfoAttrs
10370
10624
  },
10371
10625
  event: {
@@ -10374,6 +10628,7 @@ var makeGenerateTextWrapper = (name, options, generateText, aiSDK) => {
10374
10628
  ...spanInfoMetadata,
10375
10629
  model,
10376
10630
  ...provider ? { provider } : {},
10631
+ ...serializedTools ? { tools: serializedTools } : {},
10377
10632
  braintrust: {
10378
10633
  integration_name: "ai-sdk",
10379
10634
  sdk_language: "typescript"
@@ -10408,6 +10663,7 @@ var wrapModel = (model, ai) => {
10408
10663
  const originalDoStream = resolvedModel.doStream?.bind(resolvedModel);
10409
10664
  const { model: modelId, provider } = serializeModelWithProvider(resolvedModel);
10410
10665
  const wrappedDoGenerate = async (options) => {
10666
+ const serializedTools = serializeAISDKToolsForLogging(options.tools);
10411
10667
  const processedInput = await processInputAttachments2(options);
10412
10668
  return traced(
10413
10669
  async (span) => {
@@ -10440,6 +10696,7 @@ var wrapModel = (model, ai) => {
10440
10696
  metadata: {
10441
10697
  model: modelId,
10442
10698
  ...provider ? { provider } : {},
10699
+ ...serializedTools ? { tools: serializedTools } : {},
10443
10700
  braintrust: {
10444
10701
  integration_name: "ai-sdk",
10445
10702
  sdk_language: "typescript"
@@ -10452,6 +10709,7 @@ var wrapModel = (model, ai) => {
10452
10709
  const wrappedDoStream = async (options) => {
10453
10710
  const startTime = Date.now();
10454
10711
  let receivedFirst = false;
10712
+ const serializedTools = serializeAISDKToolsForLogging(options.tools);
10455
10713
  const processedInput = await processInputAttachments2(options);
10456
10714
  const span = startSpan({
10457
10715
  name: "doStream",
@@ -10463,6 +10721,7 @@ var wrapModel = (model, ai) => {
10463
10721
  metadata: {
10464
10722
  model: modelId,
10465
10723
  ...provider ? { provider } : {},
10724
+ ...serializedTools ? { tools: serializedTools } : {},
10466
10725
  braintrust: {
10467
10726
  integration_name: "ai-sdk",
10468
10727
  sdk_language: "typescript"
@@ -10476,7 +10735,7 @@ var wrapModel = (model, ai) => {
10476
10735
  let reasoning = "";
10477
10736
  const toolCalls = [];
10478
10737
  let object = void 0;
10479
- const extractTextDelta = (chunk) => {
10738
+ const extractTextDelta2 = (chunk) => {
10480
10739
  if (typeof chunk.textDelta === "string") return chunk.textDelta;
10481
10740
  if (typeof chunk.delta === "string") return chunk.delta;
10482
10741
  if (typeof chunk.text === "string") return chunk.text;
@@ -10495,7 +10754,7 @@ var wrapModel = (model, ai) => {
10495
10754
  }
10496
10755
  switch (chunk.type) {
10497
10756
  case "text-delta":
10498
- text += extractTextDelta(chunk);
10757
+ text += extractTextDelta2(chunk);
10499
10758
  break;
10500
10759
  case "reasoning-delta":
10501
10760
  if (chunk.delta) {
@@ -10595,6 +10854,7 @@ var wrapGenerateObject = (generateObject, options = {}, aiSDK) => {
10595
10854
  spanAttributes: spanInfoAttrs
10596
10855
  } = span_info ?? {};
10597
10856
  const { model, provider } = serializeModelWithProvider(params.model);
10857
+ const serializedTools = serializeAISDKToolsForLogging(params.tools);
10598
10858
  const processedInput = await processInputAttachments2(params);
10599
10859
  return traced(
10600
10860
  async (span) => {
@@ -10635,6 +10895,7 @@ var wrapGenerateObject = (generateObject, options = {}, aiSDK) => {
10635
10895
  ...spanInfoMetadata,
10636
10896
  model,
10637
10897
  ...provider ? { provider } : {},
10898
+ ...serializedTools ? { tools: serializedTools } : {},
10638
10899
  braintrust: {
10639
10900
  integration_name: "ai-sdk",
10640
10901
  sdk_language: "typescript"
@@ -10645,7 +10906,7 @@ var wrapGenerateObject = (generateObject, options = {}, aiSDK) => {
10645
10906
  );
10646
10907
  };
10647
10908
  };
10648
- var makeStreamTextWrapper = (name, options, streamText, aiSDK) => {
10909
+ var makeStreamTextWrapper = (name, options, streamText, aiSDK, spanType = "llm" /* LLM */) => {
10649
10910
  const wrapper = function(allParams) {
10650
10911
  const { span_info, ...params } = allParams;
10651
10912
  const {
@@ -10654,11 +10915,12 @@ var makeStreamTextWrapper = (name, options, streamText, aiSDK) => {
10654
10915
  spanAttributes: spanInfoAttrs
10655
10916
  } = span_info ?? {};
10656
10917
  const { model, provider } = serializeModelWithProvider(params.model);
10918
+ const serializedTools = serializeAISDKToolsForLogging(params.tools);
10657
10919
  const { input: processedInput, outputPromise } = processInputAttachmentsSync(params);
10658
10920
  const span = startSpan({
10659
10921
  name: spanName || name,
10660
10922
  spanAttributes: {
10661
- type: "llm" /* LLM */,
10923
+ type: spanType,
10662
10924
  ...spanInfoAttrs
10663
10925
  },
10664
10926
  event: {
@@ -10667,6 +10929,7 @@ var makeStreamTextWrapper = (name, options, streamText, aiSDK) => {
10667
10929
  ...spanInfoMetadata,
10668
10930
  model,
10669
10931
  ...provider ? { provider } : {},
10932
+ ...serializedTools ? { tools: serializedTools } : {},
10670
10933
  braintrust: {
10671
10934
  integration_name: "ai-sdk",
10672
10935
  sdk_language: "typescript"
@@ -10782,6 +11045,7 @@ var wrapStreamObject = (streamObject, options = {}, aiSDK) => {
10782
11045
  spanAttributes: spanInfoAttrs
10783
11046
  } = span_info ?? {};
10784
11047
  const { model, provider } = serializeModelWithProvider(params.model);
11048
+ const serializedTools = serializeAISDKToolsForLogging(params.tools);
10785
11049
  const { input: processedInput, outputPromise } = processInputAttachmentsSync(params);
10786
11050
  const span = startSpan({
10787
11051
  name: spanName || "streamObject",
@@ -10795,6 +11059,7 @@ var wrapStreamObject = (streamObject, options = {}, aiSDK) => {
10795
11059
  ...spanInfoMetadata,
10796
11060
  model,
10797
11061
  ...provider ? { provider } : {},
11062
+ ...serializedTools ? { tools: serializedTools } : {},
10798
11063
  braintrust: {
10799
11064
  integration_name: "ai-sdk",
10800
11065
  sdk_language: "typescript"
@@ -11061,10 +11326,10 @@ function extractGatewayRoutingInfo(result) {
11061
11326
  }
11062
11327
  return null;
11063
11328
  }
11064
- var isZodSchema = (value) => {
11329
+ var isZodSchema2 = (value) => {
11065
11330
  return value != null && typeof value === "object" && "_def" in value && typeof value._def === "object";
11066
11331
  };
11067
- var serializeZodSchema = (schema) => {
11332
+ var serializeZodSchema2 = (schema) => {
11068
11333
  try {
11069
11334
  return zodToJsonSchema(schema);
11070
11335
  } catch {
@@ -11074,34 +11339,6 @@ var serializeZodSchema = (schema) => {
11074
11339
  };
11075
11340
  }
11076
11341
  };
11077
- var processTools = (tools) => {
11078
- if (!tools || typeof tools !== "object") return tools;
11079
- if (Array.isArray(tools)) {
11080
- return tools.map(processTool);
11081
- }
11082
- const processed = {};
11083
- for (const [key, tool] of Object.entries(tools)) {
11084
- processed[key] = processTool(tool);
11085
- }
11086
- return processed;
11087
- };
11088
- var processTool = (tool) => {
11089
- if (!tool || typeof tool !== "object") return tool;
11090
- const processed = { ...tool };
11091
- if (isZodSchema(processed.inputSchema)) {
11092
- processed.inputSchema = serializeZodSchema(processed.inputSchema);
11093
- }
11094
- if (isZodSchema(processed.parameters)) {
11095
- processed.parameters = serializeZodSchema(processed.parameters);
11096
- }
11097
- if ("execute" in processed) {
11098
- processed.execute = "[Function]";
11099
- }
11100
- if ("render" in processed) {
11101
- processed.render = "[Function]";
11102
- }
11103
- return processed;
11104
- };
11105
11342
  var isOutputObject = (value) => {
11106
11343
  if (value == null || typeof value !== "object") {
11107
11344
  return false;
@@ -11140,10 +11377,10 @@ var serializeOutputObject = (output, model) => {
11140
11377
  if (typeof responseFormat.then === "function") {
11141
11378
  result.response_format = Promise.resolve(responseFormat).then(
11142
11379
  (resolved) => {
11143
- if (resolved.schema && isZodSchema(resolved.schema)) {
11380
+ if (resolved.schema && isZodSchema2(resolved.schema)) {
11144
11381
  return {
11145
11382
  ...resolved,
11146
- schema: serializeZodSchema(resolved.schema)
11383
+ schema: serializeZodSchema2(resolved.schema)
11147
11384
  };
11148
11385
  }
11149
11386
  return resolved;
@@ -11151,10 +11388,10 @@ var serializeOutputObject = (output, model) => {
11151
11388
  );
11152
11389
  } else {
11153
11390
  const syncResponseFormat = responseFormat;
11154
- if (syncResponseFormat.schema && isZodSchema(syncResponseFormat.schema)) {
11391
+ if (syncResponseFormat.schema && isZodSchema2(syncResponseFormat.schema)) {
11155
11392
  responseFormat = {
11156
11393
  ...syncResponseFormat,
11157
- schema: serializeZodSchema(syncResponseFormat.schema)
11394
+ schema: serializeZodSchema2(syncResponseFormat.schema)
11158
11395
  };
11159
11396
  }
11160
11397
  result.response_format = responseFormat;
@@ -11180,14 +11417,14 @@ var processInputAttachmentsSync = (input) => {
11180
11417
  processed.prompt = processPromptContent(input.prompt);
11181
11418
  }
11182
11419
  }
11183
- if (input.tools) {
11184
- processed.tools = processTools(input.tools);
11420
+ if (input.schema && isZodSchema2(input.schema)) {
11421
+ processed.schema = serializeZodSchema2(input.schema);
11185
11422
  }
11186
- if (input.schema && isZodSchema(input.schema)) {
11187
- processed.schema = serializeZodSchema(input.schema);
11423
+ if (input.callOptionsSchema && isZodSchema2(input.callOptionsSchema)) {
11424
+ processed.callOptionsSchema = serializeZodSchema2(input.callOptionsSchema);
11188
11425
  }
11189
- if (input.callOptionsSchema && isZodSchema(input.callOptionsSchema)) {
11190
- processed.callOptionsSchema = serializeZodSchema(input.callOptionsSchema);
11426
+ if (input.tools) {
11427
+ processed.tools = serializeAISDKToolsForLogging(input.tools);
11191
11428
  }
11192
11429
  let outputPromise;
11193
11430
  if (input.output && isOutputObject(input.output)) {
@@ -11221,14 +11458,14 @@ var processInputAttachments2 = async (input) => {
11221
11458
  processed.prompt = processPromptContent(input.prompt);
11222
11459
  }
11223
11460
  }
11224
- if (input.tools) {
11225
- processed.tools = processTools(input.tools);
11461
+ if (input.schema && isZodSchema2(input.schema)) {
11462
+ processed.schema = serializeZodSchema2(input.schema);
11226
11463
  }
11227
- if (input.schema && isZodSchema(input.schema)) {
11228
- processed.schema = serializeZodSchema(input.schema);
11464
+ if (input.callOptionsSchema && isZodSchema2(input.callOptionsSchema)) {
11465
+ processed.callOptionsSchema = serializeZodSchema2(input.callOptionsSchema);
11229
11466
  }
11230
- if (input.callOptionsSchema && isZodSchema(input.callOptionsSchema)) {
11231
- processed.callOptionsSchema = serializeZodSchema(input.callOptionsSchema);
11467
+ if (input.tools) {
11468
+ processed.tools = serializeAISDKToolsForLogging(input.tools);
11232
11469
  }
11233
11470
  if (input.output && isOutputObject(input.output)) {
11234
11471
  const serialized = serializeOutputObject(input.output, input.model);
@@ -11429,7 +11666,9 @@ var processOutput = async (output, denyOutputPaths) => {
11429
11666
  const getterValues = extractGetterValues(output);
11430
11667
  const processed = await processOutputAttachments(output);
11431
11668
  const merged = { ...processed, ...getterValues };
11432
- return omit(merged, denyOutputPaths ?? DENY_OUTPUT_PATHS);
11669
+ return normalizeAISDKLoggedOutput(
11670
+ omit(merged, denyOutputPaths ?? DENY_OUTPUT_PATHS)
11671
+ );
11433
11672
  };
11434
11673
  var processOutputAttachments = async (output) => {
11435
11674
  try {
@@ -13507,11 +13746,13 @@ function serializeInput(params) {
13507
13746
  if (params.config) {
13508
13747
  const config = tryToDict(params.config);
13509
13748
  if (config) {
13510
- const tools = serializeTools(params);
13511
- if (tools) {
13512
- config.tools = tools;
13513
- }
13514
- input.config = config;
13749
+ const filteredConfig = {};
13750
+ Object.keys(config).forEach((key) => {
13751
+ if (key !== "tools") {
13752
+ filteredConfig[key] = config[key];
13753
+ }
13754
+ });
13755
+ input.config = filteredConfig;
13515
13756
  }
13516
13757
  }
13517
13758
  return input;
@@ -13592,6 +13833,10 @@ function extractMetadata(params) {
13592
13833
  });
13593
13834
  }
13594
13835
  }
13836
+ const tools = serializeTools(params);
13837
+ if (tools) {
13838
+ metadata.tools = tools;
13839
+ }
13595
13840
  return metadata;
13596
13841
  }
13597
13842
  function extractGenerateContentMetrics(response, start) {
@@ -14629,7 +14874,7 @@ function unescapePath(path) {
14629
14874
  }
14630
14875
  var graph_framework_default = { createGraph };
14631
14876
 
14632
- // ../node_modules/async/dist/async.mjs
14877
+ // ../node_modules/.pnpm/async@3.2.5/node_modules/async/dist/async.mjs
14633
14878
  function initialParams(fn) {
14634
14879
  return function(...args) {
14635
14880
  var callback = args.pop();
@@ -14754,6 +14999,7 @@ function isArrayLike(value) {
14754
14999
  return value && typeof value.length === "number" && value.length >= 0 && value.length % 1 === 0;
14755
15000
  }
14756
15001
  var breakLoop = {};
15002
+ var breakLoop$1 = breakLoop;
14757
15003
  function once(fn) {
14758
15004
  function wrapper(...args) {
14759
15005
  if (fn === null) return;
@@ -14845,7 +15091,7 @@ function asyncEachOfLimit(generator, limit, iteratee, callback) {
14845
15091
  canceled = true;
14846
15092
  return;
14847
15093
  }
14848
- if (result === breakLoop || done && running <= 0) {
15094
+ if (result === breakLoop$1 || done && running <= 0) {
14849
15095
  done = true;
14850
15096
  return callback(null);
14851
15097
  }
@@ -14888,7 +15134,7 @@ var eachOfLimit$2 = (limit) => {
14888
15134
  } else if (err === false) {
14889
15135
  done = true;
14890
15136
  canceled = true;
14891
- } else if (value === breakLoop || done && running <= 0) {
15137
+ } else if (value === breakLoop$1 || done && running <= 0) {
14892
15138
  done = true;
14893
15139
  return callback(null);
14894
15140
  } else if (!looping) {
@@ -14931,7 +15177,7 @@ function eachOfArrayLike(coll, iteratee, callback) {
14931
15177
  if (canceled === true) return;
14932
15178
  if (err) {
14933
15179
  callback(err);
14934
- } else if (++completed === length || value === breakLoop) {
15180
+ } else if (++completed === length || value === breakLoop$1) {
14935
15181
  callback(null);
14936
15182
  }
14937
15183
  }
@@ -15327,7 +15573,7 @@ function _createTester(check, getResult) {
15327
15573
  if (check(result) && !testResult) {
15328
15574
  testPassed = true;
15329
15575
  testResult = getResult(true, value);
15330
- return callback(null, breakLoop);
15576
+ return callback(null, breakLoop$1);
15331
15577
  }
15332
15578
  callback();
15333
15579
  });
@@ -15951,7 +16197,8 @@ var promptDefinitionSchema = promptContentsSchema.and(
15951
16197
  z10.object({
15952
16198
  model: z10.string(),
15953
16199
  params: ModelParams.optional(),
15954
- templateFormat: z10.enum(["mustache", "nunjucks", "none"]).optional()
16200
+ templateFormat: z10.enum(["mustache", "nunjucks", "none"]).optional(),
16201
+ environments: z10.array(z10.string()).optional()
15955
16202
  })
15956
16203
  );
15957
16204
  var promptDefinitionWithToolsSchema = promptDefinitionSchema.and(
@@ -16110,6 +16357,22 @@ function initExperiment2(state, options = {}) {
16110
16357
  setCurrent: false
16111
16358
  });
16112
16359
  }
16360
+ async function getExperimentParametersRef(parameters) {
16361
+ if (!parameters) {
16362
+ return void 0;
16363
+ }
16364
+ const resolvedParameters = parameters instanceof Promise ? await parameters : parameters;
16365
+ if (!RemoteEvalParameters.isParameters(resolvedParameters)) {
16366
+ return void 0;
16367
+ }
16368
+ if (resolvedParameters.id === void 0) {
16369
+ return void 0;
16370
+ }
16371
+ return {
16372
+ id: resolvedParameters.id,
16373
+ version: resolvedParameters.version
16374
+ };
16375
+ }
16113
16376
  function callEvaluatorData(data) {
16114
16377
  const dataResult = typeof data === "function" ? data() : data;
16115
16378
  let baseExperiment = void 0;
@@ -16176,6 +16439,7 @@ async function Eval(name, evaluator, reporterOrOpts) {
16176
16439
  const { data, baseExperiment: defaultBaseExperiment } = callEvaluatorData(
16177
16440
  evaluator.data
16178
16441
  );
16442
+ const parameters = await getExperimentParametersRef(evaluator.parameters);
16179
16443
  const experiment = options.parent || options.noSendLogs ? null : initExperiment2(evaluator.state, {
16180
16444
  ...evaluator.projectId ? { projectId: evaluator.projectId } : { project: name },
16181
16445
  experiment: evaluator.experimentName,
@@ -16188,7 +16452,8 @@ async function Eval(name, evaluator, reporterOrOpts) {
16188
16452
  baseExperimentId: evaluator.baseExperimentId,
16189
16453
  gitMetadataSettings: evaluator.gitMetadataSettings,
16190
16454
  repoInfo: evaluator.repoInfo,
16191
- dataset: Dataset2.isDataset(data) ? data : void 0
16455
+ dataset: Dataset2.isDataset(data) ? data : void 0,
16456
+ parameters
16192
16457
  });
16193
16458
  if (experiment && typeof process !== "undefined" && globalThis.BRAINTRUST_CONTEXT_MANAGER !== void 0) {
16194
16459
  await experiment._waitForId();
@@ -16243,7 +16508,7 @@ async function Eval(name, evaluator, reporterOrOpts) {
16243
16508
  if (experiment) {
16244
16509
  await experiment.flush().catch(console.error);
16245
16510
  } else if (options.parent) {
16246
- await flush().catch(console.error);
16511
+ await flush({ state: evaluator.state }).catch(console.error);
16247
16512
  }
16248
16513
  }
16249
16514
  } finally {
@@ -16631,6 +16896,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
16631
16896
  },
16632
16897
  Math.max(evaluator.maxConcurrency ?? Number.MAX_SAFE_INTEGER, 1)
16633
16898
  );
16899
+ const queueErrors = [];
16634
16900
  const enqueuePromise = (async () => {
16635
16901
  for await (const datum of dataIterable) {
16636
16902
  if (cancelled) {
@@ -16646,7 +16912,11 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
16646
16912
  }
16647
16913
  scheduledTrials++;
16648
16914
  progressReporter.setTotal?.(evaluator.evalName, scheduledTrials);
16649
- q.push({ datum, trialIndex });
16915
+ q.pushAsync({ datum, trialIndex }).catch((e) => {
16916
+ if (queueErrors.length < 5) {
16917
+ queueErrors.push(e);
16918
+ }
16919
+ });
16650
16920
  }
16651
16921
  }
16652
16922
  })();
@@ -16694,6 +16964,12 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
16694
16964
  })();
16695
16965
  try {
16696
16966
  await Promise.race([waitForQueue, cancel()]);
16967
+ if (queueErrors.length > 0) {
16968
+ throw new AggregateError(
16969
+ queueErrors,
16970
+ `Encountered ${queueErrors.length} unhandled task errors`
16971
+ );
16972
+ }
16697
16973
  } catch (e) {
16698
16974
  q.kill();
16699
16975
  if (e instanceof InternalAbortError) {
@@ -17097,6 +17373,7 @@ var CodePrompt = class {
17097
17373
  toolFunctions;
17098
17374
  tags;
17099
17375
  metadata;
17376
+ environmentSlugs;
17100
17377
  constructor(project, prompt, toolFunctions, opts, functionType) {
17101
17378
  this.project = project;
17102
17379
  this.name = opts.name;
@@ -17109,6 +17386,7 @@ var CodePrompt = class {
17109
17386
  this.functionType = functionType;
17110
17387
  this.tags = opts.tags;
17111
17388
  this.metadata = opts.metadata;
17389
+ this.environmentSlugs = opts.environments;
17112
17390
  }
17113
17391
  async toFunctionDefinition(projectNameToId) {
17114
17392
  const prompt_data = {
@@ -17143,7 +17421,8 @@ var CodePrompt = class {
17143
17421
  prompt_data,
17144
17422
  if_exists: this.ifExists,
17145
17423
  tags: this.tags,
17146
- metadata: this.metadata
17424
+ metadata: this.metadata,
17425
+ environments: this.environmentSlugs && this.environmentSlugs.length > 0 ? this.environmentSlugs.map((slug) => ({ slug })) : void 0
17147
17426
  };
17148
17427
  }
17149
17428
  };
@@ -17925,7 +18204,11 @@ function startSpanForEvent(config, event, channelName) {
17925
18204
  });
17926
18205
  const startTime = getCurrentUnixTimestamp();
17927
18206
  try {
17928
- const { input, metadata } = config.extractInput(event.arguments);
18207
+ const { input, metadata } = config.extractInput(
18208
+ event.arguments,
18209
+ event,
18210
+ span
18211
+ );
17929
18212
  span.log({
17930
18213
  input,
17931
18214
  metadata: mergeInputMetadata(metadata, spanInfoMetadata)
@@ -18089,6 +18372,16 @@ function traceStreamingChannel(channel2, config) {
18089
18372
  });
18090
18373
  return;
18091
18374
  }
18375
+ if (config.patchResult?.({
18376
+ channelName,
18377
+ endEvent: asyncEndEvent,
18378
+ result: asyncEndEvent.result,
18379
+ span,
18380
+ startTime
18381
+ })) {
18382
+ states.delete(event);
18383
+ return;
18384
+ }
18092
18385
  try {
18093
18386
  const output = config.extractOutput(
18094
18387
  asyncEndEvent.result,
@@ -18145,8 +18438,17 @@ function traceSyncStreamChannel(channel2, config) {
18145
18438
  return;
18146
18439
  }
18147
18440
  const { span, startTime } = spanData;
18148
- const resultEvent = event;
18149
- const stream = resultEvent.result;
18441
+ const endEvent = event;
18442
+ if (config.patchResult?.({
18443
+ channelName,
18444
+ endEvent,
18445
+ result: endEvent.result,
18446
+ span,
18447
+ startTime
18448
+ })) {
18449
+ return;
18450
+ }
18451
+ const stream = endEvent.result;
18150
18452
  if (!isSyncStreamLike(stream)) {
18151
18453
  span.end();
18152
18454
  states.delete(event);
@@ -18811,6 +19113,10 @@ var aiSDKChannels = defineChannels("ai", {
18811
19113
  channelName: "streamText",
18812
19114
  kind: "async"
18813
19115
  }),
19116
+ streamTextSync: channel({
19117
+ channelName: "streamText.sync",
19118
+ kind: "sync-stream"
19119
+ }),
18814
19120
  generateObject: channel({
18815
19121
  channelName: "generateObject",
18816
19122
  kind: "async"
@@ -18819,6 +19125,10 @@ var aiSDKChannels = defineChannels("ai", {
18819
19125
  channelName: "streamObject",
18820
19126
  kind: "async"
18821
19127
  }),
19128
+ streamObjectSync: channel({
19129
+ channelName: "streamObject.sync",
19130
+ kind: "sync-stream"
19131
+ }),
18822
19132
  agentGenerate: channel({
18823
19133
  channelName: "Agent.generate",
18824
19134
  kind: "async"
@@ -18826,6 +19136,14 @@ var aiSDKChannels = defineChannels("ai", {
18826
19136
  agentStream: channel({
18827
19137
  channelName: "Agent.stream",
18828
19138
  kind: "async"
19139
+ }),
19140
+ toolLoopAgentGenerate: channel({
19141
+ channelName: "ToolLoopAgent.generate",
19142
+ kind: "async"
19143
+ }),
19144
+ toolLoopAgentStream: channel({
19145
+ channelName: "ToolLoopAgent.stream",
19146
+ kind: "async"
18829
19147
  })
18830
19148
  });
18831
19149
 
@@ -18844,6 +19162,8 @@ var DEFAULT_DENY_OUTPUT_PATHS = [
18844
19162
  "steps[].response.body",
18845
19163
  "steps[].response.headers"
18846
19164
  ];
19165
+ var AUTO_PATCHED_MODEL = Symbol.for("braintrust.ai-sdk.auto-patched-model");
19166
+ var AUTO_PATCHED_TOOL = Symbol.for("braintrust.ai-sdk.auto-patched-tool");
18847
19167
  var AISDKPlugin = class extends BasePlugin {
18848
19168
  config;
18849
19169
  constructor(config = {}) {
@@ -18862,22 +19182,12 @@ var AISDKPlugin = class extends BasePlugin {
18862
19182
  traceStreamingChannel(aiSDKChannels.generateText, {
18863
19183
  name: "generateText",
18864
19184
  type: "llm" /* LLM */,
18865
- extractInput: ([params]) => {
18866
- return {
18867
- input: processAISDKInput(params),
18868
- metadata: extractMetadataFromParams(params)
18869
- };
18870
- },
18871
- extractOutput: (result) => {
19185
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
19186
+ extractOutput: (result, endEvent) => {
19187
+ finalizeAISDKChildTracing(endEvent);
18872
19188
  return processAISDKOutput(result, denyOutputPaths);
18873
19189
  },
18874
- extractMetrics: (result, startTime) => {
18875
- const metrics = extractTokenMetrics2(result);
18876
- if (startTime) {
18877
- metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
18878
- }
18879
- return metrics;
18880
- },
19190
+ extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
18881
19191
  aggregateChunks: aggregateAISDKChunks
18882
19192
  })
18883
19193
  );
@@ -18885,45 +19195,43 @@ var AISDKPlugin = class extends BasePlugin {
18885
19195
  traceStreamingChannel(aiSDKChannels.streamText, {
18886
19196
  name: "streamText",
18887
19197
  type: "llm" /* LLM */,
18888
- extractInput: ([params]) => {
18889
- return {
18890
- input: processAISDKInput(params),
18891
- metadata: extractMetadataFromParams(params)
18892
- };
18893
- },
18894
- extractOutput: (result) => {
18895
- return processAISDKOutput(result, denyOutputPaths);
18896
- },
18897
- extractMetrics: (result, startTime) => {
18898
- const metrics = extractTokenMetrics2(result);
18899
- if (startTime) {
18900
- metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
18901
- }
18902
- return metrics;
18903
- },
18904
- aggregateChunks: aggregateAISDKChunks
19198
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
19199
+ extractOutput: (result) => processAISDKOutput(result, denyOutputPaths),
19200
+ extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
19201
+ aggregateChunks: aggregateAISDKChunks,
19202
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
19203
+ denyOutputPaths,
19204
+ endEvent,
19205
+ result,
19206
+ span,
19207
+ startTime
19208
+ })
19209
+ })
19210
+ );
19211
+ this.unsubscribers.push(
19212
+ traceSyncStreamChannel(aiSDKChannels.streamTextSync, {
19213
+ name: "streamText",
19214
+ type: "llm" /* LLM */,
19215
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
19216
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
19217
+ denyOutputPaths,
19218
+ endEvent,
19219
+ result,
19220
+ span,
19221
+ startTime
19222
+ })
18905
19223
  })
18906
19224
  );
18907
19225
  this.unsubscribers.push(
18908
19226
  traceStreamingChannel(aiSDKChannels.generateObject, {
18909
19227
  name: "generateObject",
18910
19228
  type: "llm" /* LLM */,
18911
- extractInput: ([params]) => {
18912
- return {
18913
- input: processAISDKInput(params),
18914
- metadata: extractMetadataFromParams(params)
18915
- };
18916
- },
18917
- extractOutput: (result) => {
19229
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
19230
+ extractOutput: (result, endEvent) => {
19231
+ finalizeAISDKChildTracing(endEvent);
18918
19232
  return processAISDKOutput(result, denyOutputPaths);
18919
19233
  },
18920
- extractMetrics: (result, startTime) => {
18921
- const metrics = extractTokenMetrics2(result);
18922
- if (startTime) {
18923
- metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
18924
- }
18925
- return metrics;
18926
- },
19234
+ extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
18927
19235
  aggregateChunks: aggregateAISDKChunks
18928
19236
  })
18929
19237
  );
@@ -18931,45 +19239,43 @@ var AISDKPlugin = class extends BasePlugin {
18931
19239
  traceStreamingChannel(aiSDKChannels.streamObject, {
18932
19240
  name: "streamObject",
18933
19241
  type: "llm" /* LLM */,
18934
- extractInput: ([params]) => {
18935
- return {
18936
- input: processAISDKInput(params),
18937
- metadata: extractMetadataFromParams(params)
18938
- };
18939
- },
18940
- extractOutput: (result) => {
18941
- return processAISDKOutput(result, denyOutputPaths);
18942
- },
18943
- extractMetrics: (result, startTime) => {
18944
- const metrics = extractTokenMetrics2(result);
18945
- if (startTime) {
18946
- metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
18947
- }
18948
- return metrics;
18949
- },
18950
- aggregateChunks: aggregateAISDKChunks
19242
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
19243
+ extractOutput: (result) => processAISDKOutput(result, denyOutputPaths),
19244
+ extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
19245
+ aggregateChunks: aggregateAISDKChunks,
19246
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
19247
+ denyOutputPaths,
19248
+ endEvent,
19249
+ result,
19250
+ span,
19251
+ startTime
19252
+ })
19253
+ })
19254
+ );
19255
+ this.unsubscribers.push(
19256
+ traceSyncStreamChannel(aiSDKChannels.streamObjectSync, {
19257
+ name: "streamObject",
19258
+ type: "llm" /* LLM */,
19259
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
19260
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
19261
+ denyOutputPaths,
19262
+ endEvent,
19263
+ result,
19264
+ span,
19265
+ startTime
19266
+ })
18951
19267
  })
18952
19268
  );
18953
19269
  this.unsubscribers.push(
18954
19270
  traceStreamingChannel(aiSDKChannels.agentGenerate, {
18955
19271
  name: "Agent.generate",
18956
19272
  type: "llm" /* LLM */,
18957
- extractInput: ([params]) => {
18958
- return {
18959
- input: processAISDKInput(params),
18960
- metadata: extractMetadataFromParams(params)
18961
- };
18962
- },
18963
- extractOutput: (result) => {
19273
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
19274
+ extractOutput: (result, endEvent) => {
19275
+ finalizeAISDKChildTracing(endEvent);
18964
19276
  return processAISDKOutput(result, denyOutputPaths);
18965
19277
  },
18966
- extractMetrics: (result, startTime) => {
18967
- const metrics = extractTokenMetrics2(result);
18968
- if (startTime) {
18969
- metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
18970
- }
18971
- return metrics;
18972
- },
19278
+ extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
18973
19279
  aggregateChunks: aggregateAISDKChunks
18974
19280
  })
18975
19281
  );
@@ -18977,52 +19283,470 @@ var AISDKPlugin = class extends BasePlugin {
18977
19283
  traceStreamingChannel(aiSDKChannels.agentStream, {
18978
19284
  name: "Agent.stream",
18979
19285
  type: "llm" /* LLM */,
18980
- extractInput: ([params]) => {
18981
- return {
18982
- input: processAISDKInput(params),
18983
- metadata: extractMetadataFromParams(params)
18984
- };
18985
- },
18986
- extractOutput: (result) => {
19286
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
19287
+ extractOutput: (result) => processAISDKOutput(result, denyOutputPaths),
19288
+ extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
19289
+ aggregateChunks: aggregateAISDKChunks,
19290
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
19291
+ denyOutputPaths,
19292
+ endEvent,
19293
+ result,
19294
+ span,
19295
+ startTime
19296
+ })
19297
+ })
19298
+ );
19299
+ this.unsubscribers.push(
19300
+ traceStreamingChannel(aiSDKChannels.toolLoopAgentGenerate, {
19301
+ name: "ToolLoopAgent.generate",
19302
+ type: "llm" /* LLM */,
19303
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
19304
+ extractOutput: (result, endEvent) => {
19305
+ finalizeAISDKChildTracing(endEvent);
18987
19306
  return processAISDKOutput(result, denyOutputPaths);
18988
19307
  },
18989
- extractMetrics: (result, startTime) => {
18990
- const metrics = extractTokenMetrics2(result);
18991
- if (startTime) {
18992
- metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
18993
- }
18994
- return metrics;
18995
- },
19308
+ extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
18996
19309
  aggregateChunks: aggregateAISDKChunks
18997
19310
  })
18998
19311
  );
19312
+ this.unsubscribers.push(
19313
+ traceStreamingChannel(aiSDKChannels.toolLoopAgentStream, {
19314
+ name: "ToolLoopAgent.stream",
19315
+ type: "llm" /* LLM */,
19316
+ extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
19317
+ extractOutput: (result) => processAISDKOutput(result, denyOutputPaths),
19318
+ extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
19319
+ aggregateChunks: aggregateAISDKChunks,
19320
+ patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
19321
+ denyOutputPaths,
19322
+ endEvent,
19323
+ result,
19324
+ span,
19325
+ startTime
19326
+ })
19327
+ })
19328
+ );
18999
19329
  }
19000
19330
  };
19001
19331
  function processAISDKInput(params) {
19002
19332
  if (!params) return params;
19003
- return processInputAttachments(params);
19333
+ const input = processInputAttachments(params);
19334
+ if (!input || typeof input !== "object" || Array.isArray(input)) {
19335
+ return input;
19336
+ }
19337
+ const { tools: _tools, ...rest } = input;
19338
+ return rest;
19004
19339
  }
19005
- function extractMetadataFromParams(params) {
19340
+ function prepareAISDKInput(params, event, span, denyOutputPaths) {
19341
+ const input = processAISDKInput(params);
19342
+ const metadata = extractMetadataFromParams(params, event.self);
19343
+ const childTracing = prepareAISDKChildTracing(
19344
+ params,
19345
+ event.self,
19346
+ span,
19347
+ denyOutputPaths
19348
+ );
19349
+ event.__braintrust_ai_sdk_model_wrapped = childTracing.modelWrapped;
19350
+ if (childTracing.cleanup) {
19351
+ event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
19352
+ }
19353
+ return {
19354
+ input,
19355
+ metadata
19356
+ };
19357
+ }
19358
+ function extractTopLevelAISDKMetrics(result, event, startTime) {
19359
+ const metrics = hasModelChildTracing(event) ? {} : extractTokenMetrics2(result);
19360
+ if (startTime) {
19361
+ metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
19362
+ }
19363
+ return metrics;
19364
+ }
19365
+ function hasModelChildTracing(event) {
19366
+ return event?.__braintrust_ai_sdk_model_wrapped === true;
19367
+ }
19368
+ function extractMetadataFromParams(params, self) {
19006
19369
  const metadata = {
19007
19370
  braintrust: {
19008
19371
  integration_name: "ai-sdk",
19009
19372
  sdk_language: "typescript"
19010
19373
  }
19011
19374
  };
19012
- const { model, provider } = serializeModelWithProvider2(params.model);
19375
+ const agentModel = self && typeof self === "object" && "model" in self && self.model ? self.model : self && typeof self === "object" && "settings" in self && self.settings?.model ? self.settings?.model : void 0;
19376
+ const { model, provider } = serializeModelWithProvider2(
19377
+ params.model ?? agentModel
19378
+ );
19013
19379
  if (model) {
19014
19380
  metadata.model = model;
19015
19381
  }
19016
19382
  if (provider) {
19017
19383
  metadata.provider = provider;
19018
19384
  }
19385
+ const tools = serializeAISDKToolsForLogging(params.tools);
19386
+ if (tools) {
19387
+ metadata.tools = tools;
19388
+ }
19019
19389
  return metadata;
19020
19390
  }
19391
+ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
19392
+ const cleanup = [];
19393
+ const patchedModels = /* @__PURE__ */ new WeakSet();
19394
+ const patchedTools = /* @__PURE__ */ new WeakSet();
19395
+ let modelWrapped = false;
19396
+ const patchModel = (model) => {
19397
+ const resolvedModel = resolveAISDKModel(model);
19398
+ if (!resolvedModel || typeof resolvedModel !== "object" || typeof resolvedModel.doGenerate !== "function" || patchedModels.has(resolvedModel) || resolvedModel[AUTO_PATCHED_MODEL]) {
19399
+ return;
19400
+ }
19401
+ patchedModels.add(resolvedModel);
19402
+ resolvedModel[AUTO_PATCHED_MODEL] = true;
19403
+ modelWrapped = true;
19404
+ const originalDoGenerate = resolvedModel.doGenerate;
19405
+ const originalDoStream = resolvedModel.doStream;
19406
+ const baseMetadata = buildAISDKChildMetadata(resolvedModel);
19407
+ resolvedModel.doGenerate = async function doGeneratePatched(options) {
19408
+ return parentSpan.traced(
19409
+ async (span) => {
19410
+ const result = await Reflect.apply(
19411
+ originalDoGenerate,
19412
+ resolvedModel,
19413
+ [options]
19414
+ );
19415
+ span.log({
19416
+ output: processAISDKOutput(result, denyOutputPaths),
19417
+ metrics: extractTokenMetrics2(result),
19418
+ ...buildResolvedMetadataPayload(result)
19419
+ });
19420
+ return result;
19421
+ },
19422
+ {
19423
+ name: "doGenerate",
19424
+ spanAttributes: {
19425
+ type: "llm" /* LLM */
19426
+ },
19427
+ event: {
19428
+ input: processAISDKInput(options),
19429
+ metadata: baseMetadata
19430
+ }
19431
+ }
19432
+ );
19433
+ };
19434
+ if (originalDoStream) {
19435
+ resolvedModel.doStream = async function doStreamPatched(options) {
19436
+ const span = parentSpan.startSpan({
19437
+ name: "doStream",
19438
+ spanAttributes: {
19439
+ type: "llm" /* LLM */
19440
+ },
19441
+ event: {
19442
+ input: processAISDKInput(options),
19443
+ metadata: baseMetadata
19444
+ }
19445
+ });
19446
+ const result = await withCurrent(
19447
+ span,
19448
+ () => Reflect.apply(originalDoStream, resolvedModel, [options])
19449
+ );
19450
+ const output = {};
19451
+ let text = "";
19452
+ let reasoning = "";
19453
+ const toolCalls = [];
19454
+ let object = void 0;
19455
+ const transformStream = new TransformStream({
19456
+ transform(chunk, controller) {
19457
+ switch (chunk.type) {
19458
+ case "text-delta":
19459
+ text += extractTextDelta(chunk);
19460
+ break;
19461
+ case "reasoning-delta":
19462
+ if (chunk.delta) {
19463
+ reasoning += chunk.delta;
19464
+ } else if (chunk.text) {
19465
+ reasoning += chunk.text;
19466
+ }
19467
+ break;
19468
+ case "tool-call":
19469
+ toolCalls.push(chunk);
19470
+ break;
19471
+ case "object":
19472
+ object = chunk.object;
19473
+ break;
19474
+ case "raw":
19475
+ if (chunk.rawValue) {
19476
+ const rawVal = chunk.rawValue;
19477
+ if (rawVal.delta?.content) {
19478
+ text += rawVal.delta.content;
19479
+ } else if (rawVal.choices?.[0]?.delta?.content) {
19480
+ text += rawVal.choices[0].delta.content;
19481
+ } else if (typeof rawVal.text === "string") {
19482
+ text += rawVal.text;
19483
+ } else if (typeof rawVal.content === "string") {
19484
+ text += rawVal.content;
19485
+ }
19486
+ }
19487
+ break;
19488
+ case "finish":
19489
+ output.text = text;
19490
+ output.reasoning = reasoning;
19491
+ output.toolCalls = toolCalls;
19492
+ output.finishReason = chunk.finishReason;
19493
+ output.usage = chunk.usage;
19494
+ if (object !== void 0) {
19495
+ output.object = object;
19496
+ }
19497
+ span.log({
19498
+ output: processAISDKOutput(
19499
+ output,
19500
+ denyOutputPaths
19501
+ ),
19502
+ metrics: extractTokenMetrics2(output),
19503
+ ...buildResolvedMetadataPayload(output)
19504
+ });
19505
+ span.end();
19506
+ break;
19507
+ }
19508
+ controller.enqueue(chunk);
19509
+ }
19510
+ });
19511
+ return {
19512
+ ...result,
19513
+ stream: result.stream.pipeThrough(transformStream)
19514
+ };
19515
+ };
19516
+ }
19517
+ cleanup.push(() => {
19518
+ resolvedModel.doGenerate = originalDoGenerate;
19519
+ if (originalDoStream) {
19520
+ resolvedModel.doStream = originalDoStream;
19521
+ }
19522
+ delete resolvedModel[AUTO_PATCHED_MODEL];
19523
+ });
19524
+ };
19525
+ const patchTool = (tool, name) => {
19526
+ if (tool == null || typeof tool !== "object" || !("execute" in tool) || typeof tool.execute !== "function" || patchedTools.has(tool) || tool[AUTO_PATCHED_TOOL]) {
19527
+ return;
19528
+ }
19529
+ patchedTools.add(tool);
19530
+ tool[AUTO_PATCHED_TOOL] = true;
19531
+ const originalExecute = tool.execute;
19532
+ tool.execute = function executePatched(...args) {
19533
+ const result = Reflect.apply(originalExecute, this, args);
19534
+ if (isAsyncGenerator3(result)) {
19535
+ return (async function* () {
19536
+ const span = parentSpan.startSpan({
19537
+ name,
19538
+ spanAttributes: {
19539
+ type: "tool" /* TOOL */
19540
+ }
19541
+ });
19542
+ span.log({ input: args.length === 1 ? args[0] : args });
19543
+ try {
19544
+ let lastValue;
19545
+ for await (const value of result) {
19546
+ lastValue = value;
19547
+ yield value;
19548
+ }
19549
+ span.log({ output: lastValue });
19550
+ } catch (error) {
19551
+ span.log({
19552
+ error: error instanceof Error ? error.message : String(error)
19553
+ });
19554
+ throw error;
19555
+ } finally {
19556
+ span.end();
19557
+ }
19558
+ })();
19559
+ }
19560
+ return parentSpan.traced(
19561
+ async (span) => {
19562
+ span.log({ input: args.length === 1 ? args[0] : args });
19563
+ const awaitedResult = await result;
19564
+ span.log({ output: awaitedResult });
19565
+ return awaitedResult;
19566
+ },
19567
+ {
19568
+ name,
19569
+ spanAttributes: {
19570
+ type: "tool" /* TOOL */
19571
+ }
19572
+ }
19573
+ );
19574
+ };
19575
+ cleanup.push(() => {
19576
+ tool.execute = originalExecute;
19577
+ delete tool[AUTO_PATCHED_TOOL];
19578
+ });
19579
+ };
19580
+ const patchTools = (tools) => {
19581
+ if (!tools) {
19582
+ return;
19583
+ }
19584
+ const inferName = (tool, fallback2) => tool && (tool.name || tool.toolName || tool.id) || fallback2;
19585
+ if (Array.isArray(tools)) {
19586
+ tools.forEach(
19587
+ (tool, index) => patchTool(tool, inferName(tool, `tool[${index}]`))
19588
+ );
19589
+ return;
19590
+ }
19591
+ for (const [key, tool] of Object.entries(tools)) {
19592
+ patchTool(tool, key);
19593
+ }
19594
+ };
19595
+ if (params && typeof params === "object") {
19596
+ patchModel(params.model);
19597
+ patchTools(params.tools);
19598
+ }
19599
+ if (self && typeof self === "object") {
19600
+ const selfRecord = self;
19601
+ if (selfRecord.model !== void 0) {
19602
+ patchModel(selfRecord.model);
19603
+ }
19604
+ if (selfRecord.settings && typeof selfRecord.settings === "object") {
19605
+ if (selfRecord.settings.model !== void 0) {
19606
+ patchModel(selfRecord.settings.model);
19607
+ }
19608
+ if (selfRecord.settings.tools !== void 0) {
19609
+ patchTools(selfRecord.settings.tools);
19610
+ }
19611
+ }
19612
+ }
19613
+ return {
19614
+ cleanup: cleanup.length > 0 ? () => {
19615
+ while (cleanup.length > 0) {
19616
+ cleanup.pop()?.();
19617
+ }
19618
+ } : void 0,
19619
+ modelWrapped
19620
+ };
19621
+ }
19622
+ function finalizeAISDKChildTracing(event) {
19623
+ const cleanup = event?.__braintrust_ai_sdk_cleanup;
19624
+ if (event && typeof cleanup === "function") {
19625
+ cleanup();
19626
+ delete event.__braintrust_ai_sdk_cleanup;
19627
+ }
19628
+ }
19629
+ function patchAISDKStreamingResult(args) {
19630
+ const { denyOutputPaths, endEvent, result, span, startTime } = args;
19631
+ if (!result || typeof result !== "object") {
19632
+ return false;
19633
+ }
19634
+ const resultRecord = result;
19635
+ if (!isReadableStreamLike(resultRecord.baseStream)) {
19636
+ return false;
19637
+ }
19638
+ let firstChunkTime;
19639
+ const wrappedBaseStream = resultRecord.baseStream.pipeThrough(
19640
+ new TransformStream({
19641
+ transform(chunk, controller) {
19642
+ if (firstChunkTime === void 0) {
19643
+ firstChunkTime = getCurrentUnixTimestamp();
19644
+ }
19645
+ controller.enqueue(chunk);
19646
+ },
19647
+ async flush() {
19648
+ const metrics = extractTopLevelAISDKMetrics(result, endEvent);
19649
+ if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
19650
+ metrics.time_to_first_token = firstChunkTime - startTime;
19651
+ }
19652
+ const output = await processAISDKStreamingOutput(
19653
+ result,
19654
+ denyOutputPaths
19655
+ );
19656
+ const metadata = buildResolvedMetadataPayload(result).metadata;
19657
+ span.log({
19658
+ output,
19659
+ ...metadata ? { metadata } : {},
19660
+ metrics
19661
+ });
19662
+ finalizeAISDKChildTracing(endEvent);
19663
+ span.end();
19664
+ }
19665
+ })
19666
+ );
19667
+ Object.defineProperty(resultRecord, "baseStream", {
19668
+ configurable: true,
19669
+ enumerable: true,
19670
+ value: wrappedBaseStream,
19671
+ writable: true
19672
+ });
19673
+ return true;
19674
+ }
19675
+ function isReadableStreamLike(value) {
19676
+ return value != null && typeof value === "object" && typeof value.pipeThrough === "function";
19677
+ }
19678
+ async function processAISDKStreamingOutput(result, denyOutputPaths) {
19679
+ const output = processAISDKOutput(result, denyOutputPaths);
19680
+ if (!output || typeof output !== "object") {
19681
+ return output;
19682
+ }
19683
+ const outputRecord = output;
19684
+ try {
19685
+ if ("text" in result && typeof result.text === "string") {
19686
+ outputRecord.text = result.text;
19687
+ }
19688
+ } catch {
19689
+ }
19690
+ try {
19691
+ if ("object" in result) {
19692
+ const resolvedObject = await Promise.resolve(result.object);
19693
+ if (resolvedObject !== void 0) {
19694
+ outputRecord.object = resolvedObject;
19695
+ }
19696
+ }
19697
+ } catch {
19698
+ }
19699
+ return outputRecord;
19700
+ }
19701
+ function buildAISDKChildMetadata(model) {
19702
+ const { model: modelId, provider } = serializeModelWithProvider2(model);
19703
+ return {
19704
+ ...modelId ? { model: modelId } : {},
19705
+ ...provider ? { provider } : {},
19706
+ braintrust: {
19707
+ integration_name: "ai-sdk",
19708
+ sdk_language: "typescript"
19709
+ }
19710
+ };
19711
+ }
19712
+ function buildResolvedMetadataPayload(result) {
19713
+ const gatewayInfo = extractGatewayRoutingInfo2(result);
19714
+ const metadata = {};
19715
+ if (gatewayInfo?.provider) {
19716
+ metadata.provider = gatewayInfo.provider;
19717
+ }
19718
+ if (gatewayInfo?.model) {
19719
+ metadata.model = gatewayInfo.model;
19720
+ }
19721
+ if (result.finishReason !== void 0) {
19722
+ metadata.finish_reason = result.finishReason;
19723
+ }
19724
+ return Object.keys(metadata).length > 0 ? { metadata } : {};
19725
+ }
19726
+ function resolveAISDKModel(model) {
19727
+ if (typeof model !== "string") {
19728
+ return model;
19729
+ }
19730
+ const provider = globalThis.AI_SDK_DEFAULT_PROVIDER ?? null;
19731
+ if (provider && typeof provider.languageModel === "function") {
19732
+ return provider.languageModel(model);
19733
+ }
19734
+ return model;
19735
+ }
19736
+ function extractTextDelta(chunk) {
19737
+ if (typeof chunk.textDelta === "string") return chunk.textDelta;
19738
+ if (typeof chunk.delta === "string") return chunk.delta;
19739
+ if (typeof chunk.text === "string") return chunk.text;
19740
+ if (typeof chunk.content === "string") return chunk.content;
19741
+ return "";
19742
+ }
19743
+ function isAsyncGenerator3(value) {
19744
+ return value != null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function" && typeof value.next === "function" && typeof value.return === "function" && typeof value.throw === "function";
19745
+ }
19021
19746
  function processAISDKOutput(output, denyOutputPaths) {
19022
19747
  if (!output) return output;
19023
- const getterValues = extractGetterValues2(output);
19024
- const merged = { ...output, ...getterValues };
19025
- return omit2(merged, denyOutputPaths);
19748
+ const merged = extractSerializableOutputFields(output);
19749
+ return normalizeAISDKLoggedOutput(omit2(merged, denyOutputPaths));
19026
19750
  }
19027
19751
  function extractTokenMetrics2(result) {
19028
19752
  const metrics = {};
@@ -19072,12 +19796,14 @@ function extractTokenMetrics2(result) {
19072
19796
  }
19073
19797
  return metrics;
19074
19798
  }
19075
- function aggregateAISDKChunks(chunks) {
19799
+ function aggregateAISDKChunks(chunks, _result, endEvent) {
19076
19800
  const lastChunk = chunks[chunks.length - 1];
19077
19801
  const output = {};
19078
19802
  let metrics = {};
19803
+ let metadata;
19079
19804
  if (lastChunk) {
19080
- metrics = extractTokenMetrics2(lastChunk);
19805
+ metrics = hasModelChildTracing(endEvent) ? {} : extractTokenMetrics2(lastChunk);
19806
+ metadata = buildResolvedMetadataPayload(lastChunk).metadata;
19081
19807
  if (lastChunk.text !== void 0) {
19082
19808
  output.text = lastChunk.text;
19083
19809
  }
@@ -19091,7 +19817,8 @@ function aggregateAISDKChunks(chunks) {
19091
19817
  output.toolCalls = lastChunk.toolCalls;
19092
19818
  }
19093
19819
  }
19094
- return { output, metrics };
19820
+ finalizeAISDKChildTracing(endEvent);
19821
+ return { output, metrics, metadata };
19095
19822
  }
19096
19823
  function extractGetterValues2(obj) {
19097
19824
  const getterValues = {};
@@ -19111,7 +19838,7 @@ function extractGetterValues2(obj) {
19111
19838
  ];
19112
19839
  for (const name of getterNames) {
19113
19840
  try {
19114
- if (obj && name in obj && typeof obj[name] !== "function") {
19841
+ if (obj && name in obj && isSerializableOutputValue(obj[name])) {
19115
19842
  getterValues[name] = obj[name];
19116
19843
  }
19117
19844
  } catch {
@@ -19119,6 +19846,47 @@ function extractGetterValues2(obj) {
19119
19846
  }
19120
19847
  return getterValues;
19121
19848
  }
19849
+ function extractSerializableOutputFields(output) {
19850
+ const serialized = {};
19851
+ const directFieldNames = [
19852
+ "steps",
19853
+ "request",
19854
+ "responseMessages",
19855
+ "warnings",
19856
+ "rawResponse",
19857
+ "response",
19858
+ "providerMetadata",
19859
+ "experimental_providerMetadata"
19860
+ ];
19861
+ for (const name of directFieldNames) {
19862
+ try {
19863
+ const value = output?.[name];
19864
+ if (isSerializableOutputValue(value)) {
19865
+ serialized[name] = value;
19866
+ }
19867
+ } catch {
19868
+ }
19869
+ }
19870
+ return {
19871
+ ...serialized,
19872
+ ...extractGetterValues2(output)
19873
+ };
19874
+ }
19875
+ function isSerializableOutputValue(value) {
19876
+ if (typeof value === "function") {
19877
+ return false;
19878
+ }
19879
+ if (value && typeof value === "object" && typeof value.then === "function") {
19880
+ return false;
19881
+ }
19882
+ if (value && typeof value === "object" && typeof value.getReader === "function") {
19883
+ return false;
19884
+ }
19885
+ if (value && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function") {
19886
+ return false;
19887
+ }
19888
+ return true;
19889
+ }
19122
19890
  function serializeModelWithProvider2(model) {
19123
19891
  const modelId = typeof model === "string" ? model : model?.modelId;
19124
19892
  const explicitProvider = typeof model === "object" ? model?.provider : void 0;
@@ -19144,6 +19912,25 @@ function parseGatewayModelString2(modelString) {
19144
19912
  }
19145
19913
  return { model: modelString };
19146
19914
  }
19915
+ function extractGatewayRoutingInfo2(result) {
19916
+ if (result?.steps && Array.isArray(result.steps) && result.steps.length > 0) {
19917
+ const routing2 = result.steps[0]?.providerMetadata?.gateway?.routing;
19918
+ if (routing2) {
19919
+ return {
19920
+ provider: routing2.resolvedProvider || routing2.finalProvider,
19921
+ model: routing2.resolvedProviderApiModelId
19922
+ };
19923
+ }
19924
+ }
19925
+ const routing = result?.providerMetadata?.gateway?.routing;
19926
+ if (routing) {
19927
+ return {
19928
+ provider: routing.resolvedProvider || routing.finalProvider,
19929
+ model: routing.resolvedProviderApiModelId
19930
+ };
19931
+ }
19932
+ return null;
19933
+ }
19147
19934
  function extractCostFromResult2(result) {
19148
19935
  if (result?.steps && Array.isArray(result.steps) && result.steps.length > 0) {
19149
19936
  let totalCost = 0;