braintrust 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1155,6 +1155,29 @@ declare function logError(span: Span, error: unknown): void;
1155
1155
  * See {@link Span.traced} for full details.
1156
1156
  */
1157
1157
  declare function traced<IsAsyncFlush extends boolean = true, R = void>(callback: (span: Span) => R, args?: StartSpanArgs & SetCurrentArg & AsyncFlushArg<IsAsyncFlush> & OptionalStateArg): PromiseUnless<IsAsyncFlush, R>;
1158
+ /**
1159
+ * Check if a function is a sync generator function.
1160
+ *
1161
+ * Note: This uses Object.prototype.toString which is sufficient for environments that
1162
+ * support generator functions (ES6+). While our code is compiled to ES2022, consumers
1163
+ * may run it in various environments. However, if generators aren't supported in their
1164
+ * environment, the generator functions themselves won't work anyway, making detection moot.
1165
+ *
1166
+ * @param fn The function to check.
1167
+ * @returns True if the function is a sync generator function.
1168
+ */
1169
+ declare function isGeneratorFunction(fn: any): boolean;
1170
+ /**
1171
+ * Check if a function is an async generator function.
1172
+ *
1173
+ * Note: see isGeneratorFunction disclaimer
1174
+ * @param fn The function to check.
1175
+ * @returns True if the function is an async generator function.
1176
+ */
1177
+ declare function isAsyncGeneratorFunction(fn: any): boolean;
1178
+ type WrapTracedArgs = {
1179
+ noTraceIO?: boolean;
1180
+ };
1158
1181
  /**
1159
1182
  * Wrap a function with `traced`, using the arguments as `input` and return value as `output`.
1160
1183
  * Any functions wrapped this way will automatically be traced, similar to the `@traced` decorator
@@ -1180,7 +1203,7 @@ declare function traced<IsAsyncFlush extends boolean = true, R = void>(callback:
1180
1203
  * @param args Span-level arguments (e.g. a custom name or type) to pass to `traced`.
1181
1204
  * @returns The wrapped function.
1182
1205
  */
1183
- declare function wrapTraced<F extends (...args: any[]) => any, IsAsyncFlush extends boolean = true>(fn: F, args?: StartSpanArgs & SetCurrentArg & AsyncFlushArg<IsAsyncFlush>): IsAsyncFlush extends false ? (...args: Parameters<F>) => Promise<Awaited<ReturnType<F>>> : F;
1206
+ declare function wrapTraced<F extends (...args: any[]) => any, IsAsyncFlush extends boolean = true>(fn: F, args?: StartSpanArgs & SetCurrentArg & AsyncFlushArg<IsAsyncFlush> & WrapTracedArgs): IsAsyncFlush extends false ? (...args: Parameters<F>) => Promise<Awaited<ReturnType<F>>> : F;
1184
1207
  /**
1185
1208
  * A synonym for `wrapTraced`. If you're porting from systems that use `traceable`, you can use this to
1186
1209
  * make your codebase more consistent.
@@ -1701,6 +1724,8 @@ declare const _exportsForTestingOnly: {
1701
1724
  simulateLoginForTests: typeof simulateLoginForTests;
1702
1725
  simulateLogoutForTests: typeof simulateLogoutForTests;
1703
1726
  setInitialTestState: typeof setInitialTestState;
1727
+ isGeneratorFunction: typeof isGeneratorFunction;
1728
+ isAsyncGeneratorFunction: typeof isAsyncGeneratorFunction;
1704
1729
  };
1705
1730
 
1706
1731
  declare const braintrustStreamChunkSchema: z.ZodUnion<[z.ZodObject<{
package/dist/browser.d.ts CHANGED
@@ -1155,6 +1155,29 @@ declare function logError(span: Span, error: unknown): void;
1155
1155
  * See {@link Span.traced} for full details.
1156
1156
  */
1157
1157
  declare function traced<IsAsyncFlush extends boolean = true, R = void>(callback: (span: Span) => R, args?: StartSpanArgs & SetCurrentArg & AsyncFlushArg<IsAsyncFlush> & OptionalStateArg): PromiseUnless<IsAsyncFlush, R>;
1158
+ /**
1159
+ * Check if a function is a sync generator function.
1160
+ *
1161
+ * Note: This uses Object.prototype.toString which is sufficient for environments that
1162
+ * support generator functions (ES6+). While our code is compiled to ES2022, consumers
1163
+ * may run it in various environments. However, if generators aren't supported in their
1164
+ * environment, the generator functions themselves won't work anyway, making detection moot.
1165
+ *
1166
+ * @param fn The function to check.
1167
+ * @returns True if the function is a sync generator function.
1168
+ */
1169
+ declare function isGeneratorFunction(fn: any): boolean;
1170
+ /**
1171
+ * Check if a function is an async generator function.
1172
+ *
1173
+ * Note: see isGeneratorFunction disclaimer
1174
+ * @param fn The function to check.
1175
+ * @returns True if the function is an async generator function.
1176
+ */
1177
+ declare function isAsyncGeneratorFunction(fn: any): boolean;
1178
+ type WrapTracedArgs = {
1179
+ noTraceIO?: boolean;
1180
+ };
1158
1181
  /**
1159
1182
  * Wrap a function with `traced`, using the arguments as `input` and return value as `output`.
1160
1183
  * Any functions wrapped this way will automatically be traced, similar to the `@traced` decorator
@@ -1180,7 +1203,7 @@ declare function traced<IsAsyncFlush extends boolean = true, R = void>(callback:
1180
1203
  * @param args Span-level arguments (e.g. a custom name or type) to pass to `traced`.
1181
1204
  * @returns The wrapped function.
1182
1205
  */
1183
- declare function wrapTraced<F extends (...args: any[]) => any, IsAsyncFlush extends boolean = true>(fn: F, args?: StartSpanArgs & SetCurrentArg & AsyncFlushArg<IsAsyncFlush>): IsAsyncFlush extends false ? (...args: Parameters<F>) => Promise<Awaited<ReturnType<F>>> : F;
1206
+ declare function wrapTraced<F extends (...args: any[]) => any, IsAsyncFlush extends boolean = true>(fn: F, args?: StartSpanArgs & SetCurrentArg & AsyncFlushArg<IsAsyncFlush> & WrapTracedArgs): IsAsyncFlush extends false ? (...args: Parameters<F>) => Promise<Awaited<ReturnType<F>>> : F;
1184
1207
  /**
1185
1208
  * A synonym for `wrapTraced`. If you're porting from systems that use `traceable`, you can use this to
1186
1209
  * make your codebase more consistent.
@@ -1701,6 +1724,8 @@ declare const _exportsForTestingOnly: {
1701
1724
  simulateLoginForTests: typeof simulateLoginForTests;
1702
1725
  simulateLogoutForTests: typeof simulateLogoutForTests;
1703
1726
  setInitialTestState: typeof setInitialTestState;
1727
+ isGeneratorFunction: typeof isGeneratorFunction;
1728
+ isAsyncGeneratorFunction: typeof isAsyncGeneratorFunction;
1704
1729
  };
1705
1730
 
1706
1731
  declare const braintrustStreamChunkSchema: z.ZodUnion<[z.ZodObject<{
package/dist/browser.js CHANGED
@@ -2997,6 +2997,110 @@ function traced(callback, args) {
2997
2997
  })();
2998
2998
  }
2999
2999
  }
3000
+ function isGeneratorFunction(fn) {
3001
+ return Object.prototype.toString.call(fn) === "[object GeneratorFunction]";
3002
+ }
3003
+ function isAsyncGeneratorFunction(fn) {
3004
+ return Object.prototype.toString.call(fn) === "[object AsyncGeneratorFunction]";
3005
+ }
3006
+ function wrapTracedSyncGenerator(fn, spanArgs, noTraceIO) {
3007
+ const wrapper = function* (...fnArgs) {
3008
+ const span = startSpan(spanArgs);
3009
+ try {
3010
+ if (!noTraceIO) {
3011
+ span.log({ input: fnArgs });
3012
+ }
3013
+ const envValue = isomorph_default.getEnv("BRAINTRUST_MAX_GENERATOR_ITEMS");
3014
+ const maxItems = envValue !== void 0 ? Number(envValue) : 1e3;
3015
+ if (!noTraceIO && maxItems !== 0) {
3016
+ let collected = [];
3017
+ let truncated = false;
3018
+ const gen = generatorWithCurrent(span, fn.apply(this, fnArgs));
3019
+ try {
3020
+ for (const value of gen) {
3021
+ if (maxItems === -1 || !truncated && collected.length < maxItems) {
3022
+ collected.push(value);
3023
+ } else {
3024
+ truncated = true;
3025
+ collected = [];
3026
+ console.warn(
3027
+ `Generator output exceeded limit of ${maxItems} items, output not logged. Increase BRAINTRUST_MAX_GENERATOR_ITEMS or set to -1 to disable limit.`
3028
+ );
3029
+ }
3030
+ yield value;
3031
+ }
3032
+ if (!truncated) {
3033
+ span.log({ output: collected });
3034
+ }
3035
+ } catch (error) {
3036
+ logError(span, error);
3037
+ if (!truncated && collected.length > 0) {
3038
+ span.log({ output: collected });
3039
+ }
3040
+ throw error;
3041
+ }
3042
+ } else {
3043
+ const gen = generatorWithCurrent(span, fn.apply(this, fnArgs));
3044
+ for (const value of gen) {
3045
+ yield value;
3046
+ }
3047
+ }
3048
+ } finally {
3049
+ span.end();
3050
+ }
3051
+ };
3052
+ Object.defineProperty(wrapper, "name", { value: fn.name });
3053
+ return wrapper;
3054
+ }
3055
+ function wrapTracedAsyncGenerator(fn, spanArgs, noTraceIO) {
3056
+ const wrapper = async function* (...fnArgs) {
3057
+ const span = startSpan(spanArgs);
3058
+ try {
3059
+ if (!noTraceIO) {
3060
+ span.log({ input: fnArgs });
3061
+ }
3062
+ const envValue = isomorph_default.getEnv("BRAINTRUST_MAX_GENERATOR_ITEMS");
3063
+ const maxItems = envValue !== void 0 ? Number(envValue) : 1e3;
3064
+ if (!noTraceIO && maxItems !== 0) {
3065
+ let collected = [];
3066
+ let truncated = false;
3067
+ const gen = asyncGeneratorWithCurrent(span, fn.apply(this, fnArgs));
3068
+ try {
3069
+ for await (const value of gen) {
3070
+ if (maxItems === -1 || !truncated && collected.length < maxItems) {
3071
+ collected.push(value);
3072
+ } else {
3073
+ truncated = true;
3074
+ collected = [];
3075
+ console.warn(
3076
+ `Generator output exceeded limit of ${maxItems} items, output not logged. Increase BRAINTRUST_MAX_GENERATOR_ITEMS or set to -1 to disable limit.`
3077
+ );
3078
+ }
3079
+ yield value;
3080
+ }
3081
+ if (!truncated) {
3082
+ span.log({ output: collected });
3083
+ }
3084
+ } catch (error) {
3085
+ logError(span, error);
3086
+ if (!truncated && collected.length > 0) {
3087
+ span.log({ output: collected });
3088
+ }
3089
+ throw error;
3090
+ }
3091
+ } else {
3092
+ const gen = asyncGeneratorWithCurrent(span, fn.apply(this, fnArgs));
3093
+ for await (const value of gen) {
3094
+ yield value;
3095
+ }
3096
+ }
3097
+ } finally {
3098
+ span.end();
3099
+ }
3100
+ };
3101
+ Object.defineProperty(wrapper, "name", { value: fn.name });
3102
+ return wrapper;
3103
+ }
3000
3104
  function wrapTraced(fn, args) {
3001
3105
  const spanArgs = {
3002
3106
  name: fn.name,
@@ -3005,7 +3109,14 @@ function wrapTraced(fn, args) {
3005
3109
  };
3006
3110
  const hasExplicitInput = args && args.event && "input" in args.event && args.event.input !== void 0;
3007
3111
  const hasExplicitOutput = args && args.event && args.event.output !== void 0;
3008
- if (_optionalChain([args, 'optionalAccess', _32 => _32.asyncFlush])) {
3112
+ const noTraceIO = _optionalChain([args, 'optionalAccess', _32 => _32.noTraceIO]) || hasExplicitInput || hasExplicitOutput;
3113
+ if (isGeneratorFunction(fn)) {
3114
+ return wrapTracedSyncGenerator(fn, spanArgs, !!noTraceIO);
3115
+ }
3116
+ if (isAsyncGeneratorFunction(fn)) {
3117
+ return wrapTracedAsyncGenerator(fn, spanArgs, !!noTraceIO);
3118
+ }
3119
+ if (_optionalChain([args, 'optionalAccess', _33 => _33.asyncFlush])) {
3009
3120
  return (...fnArgs) => traced((span) => {
3010
3121
  if (!hasExplicitInput) {
3011
3122
  span.log({ input: fnArgs });
@@ -3043,15 +3154,15 @@ function startSpan(args) {
3043
3154
  return startSpanAndIsLogger(args).span;
3044
3155
  }
3045
3156
  async function flush(options) {
3046
- const state = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _33 => _33.state]), () => ( _globalState));
3157
+ const state = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _34 => _34.state]), () => ( _globalState));
3047
3158
  return await state.bgLogger().flush();
3048
3159
  }
3049
3160
  function setFetch(fetch2) {
3050
3161
  _globalState.setFetch(fetch2);
3051
3162
  }
3052
3163
  function startSpanAndIsLogger(args) {
3053
- const state = _nullishCoalesce(_optionalChain([args, 'optionalAccess', _34 => _34.state]), () => ( _globalState));
3054
- const parentStr = _nullishCoalesce(_optionalChain([args, 'optionalAccess', _35 => _35.parent]), () => ( state.currentParent.getStore()));
3164
+ const state = _nullishCoalesce(_optionalChain([args, 'optionalAccess', _35 => _35.state]), () => ( _globalState));
3165
+ const parentStr = _nullishCoalesce(_optionalChain([args, 'optionalAccess', _36 => _36.parent]), () => ( state.currentParent.getStore()));
3055
3166
  const components = parentStr ? _core.SpanComponentsV3.fromStr(parentStr) : void 0;
3056
3167
  if (components) {
3057
3168
  const parentSpanIds = components.data.row_id ? {
@@ -3067,18 +3178,18 @@ function startSpanAndIsLogger(args) {
3067
3178
  ),
3068
3179
  parentComputeObjectMetadataArgs: _nullishCoalesce(components.data.compute_object_metadata_args, () => ( void 0)),
3069
3180
  parentSpanIds,
3070
- propagatedEvent: _nullishCoalesce(_optionalChain([args, 'optionalAccess', _36 => _36.propagatedEvent]), () => ( // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
3181
+ propagatedEvent: _nullishCoalesce(_optionalChain([args, 'optionalAccess', _37 => _37.propagatedEvent]), () => ( // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
3071
3182
  (_nullishCoalesce(components.data.propagated_event, () => ( void 0)))))
3072
3183
  });
3073
3184
  return {
3074
3185
  span,
3075
3186
  isSyncFlushLogger: components.data.object_type === _core.SpanObjectTypeV3.PROJECT_LOGS && // Since there's no parent logger here, we're free to choose the async flush
3076
3187
  // behavior, and therefore propagate along whatever we get from the arguments
3077
- _optionalChain([args, 'optionalAccess', _37 => _37.asyncFlush]) === false
3188
+ _optionalChain([args, 'optionalAccess', _38 => _38.asyncFlush]) === false
3078
3189
  };
3079
3190
  } else {
3080
3191
  const parentObject = getSpanParentObject({
3081
- asyncFlush: _optionalChain([args, 'optionalAccess', _38 => _38.asyncFlush])
3192
+ asyncFlush: _optionalChain([args, 'optionalAccess', _39 => _39.asyncFlush])
3082
3193
  });
3083
3194
  const span = parentObject.startSpan(args);
3084
3195
  return {
@@ -3090,6 +3201,52 @@ function startSpanAndIsLogger(args) {
3090
3201
  function withCurrent(span, callback, state = void 0) {
3091
3202
  return (_nullishCoalesce(state, () => ( _globalState))).currentSpan.run(span, () => callback(span));
3092
3203
  }
3204
+ function* generatorWithCurrent(span, gen, state = void 0) {
3205
+ let nextValue;
3206
+ while (true) {
3207
+ const result = withCurrent(
3208
+ span,
3209
+ () => {
3210
+ try {
3211
+ return gen.next(nextValue);
3212
+ } catch (e) {
3213
+ return { value: void 0, done: true, error: e };
3214
+ }
3215
+ },
3216
+ state
3217
+ );
3218
+ if ("error" in result) {
3219
+ throw result.error;
3220
+ }
3221
+ if (result.done) {
3222
+ return result.value;
3223
+ }
3224
+ nextValue = yield result.value;
3225
+ }
3226
+ }
3227
+ async function* asyncGeneratorWithCurrent(span, gen, state = void 0) {
3228
+ let nextValue;
3229
+ while (true) {
3230
+ const result = await withCurrent(
3231
+ span,
3232
+ async () => {
3233
+ try {
3234
+ return await gen.next(nextValue);
3235
+ } catch (e) {
3236
+ return { value: void 0, done: true, error: e };
3237
+ }
3238
+ },
3239
+ state
3240
+ );
3241
+ if ("error" in result) {
3242
+ throw result.error;
3243
+ }
3244
+ if (result.done) {
3245
+ return result.value;
3246
+ }
3247
+ nextValue = yield result.value;
3248
+ }
3249
+ }
3093
3250
  function withParent(parent, callback, state = void 0) {
3094
3251
  return (_nullishCoalesce(state, () => ( _globalState))).currentParent.run(parent, () => callback());
3095
3252
  }
@@ -3220,10 +3377,10 @@ function extractAttachments(event, attachments) {
3220
3377
  event[key] = value.reference;
3221
3378
  continue;
3222
3379
  }
3223
- if (_optionalChain([value, 'optionalAccess', _39 => _39.type]) === _typespecs.BRAINTRUST_ATTACHMENT && value.key && !value.uploader) {
3380
+ if (_optionalChain([value, 'optionalAccess', _40 => _40.type]) === _typespecs.BRAINTRUST_ATTACHMENT && value.key && !value.uploader) {
3224
3381
  continue;
3225
3382
  }
3226
- if (_optionalChain([value, 'optionalAccess', _40 => _40.reference, 'optionalAccess', _41 => _41.type]) === _typespecs.BRAINTRUST_ATTACHMENT && _optionalChain([value, 'optionalAccess', _42 => _42.uploader])) {
3383
+ if (_optionalChain([value, 'optionalAccess', _41 => _41.reference, 'optionalAccess', _42 => _42.type]) === _typespecs.BRAINTRUST_ATTACHMENT && _optionalChain([value, 'optionalAccess', _43 => _43.uploader])) {
3227
3384
  const attachment = new Attachment({
3228
3385
  data: value.dataDebugString,
3229
3386
  filename: value.reference.filename,
@@ -3361,7 +3518,7 @@ var ObjectFetcher = (_class9 = class {
3361
3518
  throw new Error("Too many BTQL iterations");
3362
3519
  }
3363
3520
  }
3364
- this._fetchedData = this.mutateRecord ? _optionalChain([data, 'optionalAccess', _43 => _43.map, 'call', _44 => _44(this.mutateRecord)]) : data;
3521
+ this._fetchedData = this.mutateRecord ? _optionalChain([data, 'optionalAccess', _44 => _44.map, 'call', _45 => _45(this.mutateRecord)]) : data;
3365
3522
  }
3366
3523
  return this._fetchedData || [];
3367
3524
  }
@@ -3442,7 +3599,7 @@ var Experiment = (_class10 = class extends ObjectFetcher {
3442
3599
  * @returns The `id` of the logged event.
3443
3600
  */
3444
3601
  log(event, options) {
3445
- if (this.calledStartSpan && !_optionalChain([options, 'optionalAccess', _45 => _45.allowConcurrentWithSpans])) {
3602
+ if (this.calledStartSpan && !_optionalChain([options, 'optionalAccess', _46 => _46.allowConcurrentWithSpans])) {
3446
3603
  throw new Error(
3447
3604
  "Cannot run toplevel `log` method while using spans. To log to the span, call `experiment.traced` and then log with `span.log`"
3448
3605
  );
@@ -3495,12 +3652,12 @@ var Experiment = (_class10 = class extends ObjectFetcher {
3495
3652
  state: this.state,
3496
3653
  ...startSpanParentArgs({
3497
3654
  state: this.state,
3498
- parent: _optionalChain([args, 'optionalAccess', _46 => _46.parent]),
3655
+ parent: _optionalChain([args, 'optionalAccess', _47 => _47.parent]),
3499
3656
  parentObjectType: this.parentObjectType(),
3500
3657
  parentObjectId: this.lazyId,
3501
3658
  parentComputeObjectMetadataArgs: void 0,
3502
3659
  parentSpanIds: void 0,
3503
- propagatedEvent: _optionalChain([args, 'optionalAccess', _47 => _47.propagatedEvent])
3660
+ propagatedEvent: _optionalChain([args, 'optionalAccess', _48 => _48.propagatedEvent])
3504
3661
  }),
3505
3662
  defaultRootType: _core.SpanTypeAttribute.EVAL
3506
3663
  });
@@ -3792,10 +3949,10 @@ var SpanImpl = (_class11 = class _SpanImpl {
3792
3949
  ...serializableInternalData,
3793
3950
  [_core.IS_MERGE_FIELD]: this.isMerge
3794
3951
  });
3795
- if (_optionalChain([partialRecord, 'access', _48 => _48.metrics, 'optionalAccess', _49 => _49.end])) {
3796
- this.loggedEndTime = _optionalChain([partialRecord, 'access', _50 => _50.metrics, 'optionalAccess', _51 => _51.end]);
3952
+ if (_optionalChain([partialRecord, 'access', _49 => _49.metrics, 'optionalAccess', _50 => _50.end])) {
3953
+ this.loggedEndTime = _optionalChain([partialRecord, 'access', _51 => _51.metrics, 'optionalAccess', _52 => _52.end]);
3797
3954
  }
3798
- if ((_nullishCoalesce(partialRecord.tags, () => ( []))).length > 0 && _optionalChain([this, 'access', _52 => _52._spanParents, 'optionalAccess', _53 => _53.length])) {
3955
+ if ((_nullishCoalesce(partialRecord.tags, () => ( []))).length > 0 && _optionalChain([this, 'access', _53 => _53._spanParents, 'optionalAccess', _54 => _54.length])) {
3799
3956
  throw new Error("Tags can only be logged to the root span");
3800
3957
  }
3801
3958
  const computeRecord = async () => ({
@@ -3840,18 +3997,18 @@ var SpanImpl = (_class11 = class _SpanImpl {
3840
3997
  );
3841
3998
  }
3842
3999
  startSpan(args) {
3843
- const parentSpanIds = _optionalChain([args, 'optionalAccess', _54 => _54.parent]) ? void 0 : { spanId: this._spanId, rootSpanId: this._rootSpanId };
4000
+ const parentSpanIds = _optionalChain([args, 'optionalAccess', _55 => _55.parent]) ? void 0 : { spanId: this._spanId, rootSpanId: this._rootSpanId };
3844
4001
  return new _SpanImpl({
3845
4002
  state: this._state,
3846
4003
  ...args,
3847
4004
  ...startSpanParentArgs({
3848
4005
  state: this._state,
3849
- parent: _optionalChain([args, 'optionalAccess', _55 => _55.parent]),
4006
+ parent: _optionalChain([args, 'optionalAccess', _56 => _56.parent]),
3850
4007
  parentObjectType: this.parentObjectType,
3851
4008
  parentObjectId: this.parentObjectId,
3852
4009
  parentComputeObjectMetadataArgs: this.parentComputeObjectMetadataArgs,
3853
4010
  parentSpanIds,
3854
- propagatedEvent: _nullishCoalesce(_optionalChain([args, 'optionalAccess', _56 => _56.propagatedEvent]), () => ( this.propagatedEvent))
4011
+ propagatedEvent: _nullishCoalesce(_optionalChain([args, 'optionalAccess', _57 => _57.propagatedEvent]), () => ( this.propagatedEvent))
3855
4012
  })
3856
4013
  });
3857
4014
  }
@@ -3865,12 +4022,12 @@ var SpanImpl = (_class11 = class _SpanImpl {
3865
4022
  ...args,
3866
4023
  ...startSpanParentArgs({
3867
4024
  state: this._state,
3868
- parent: _optionalChain([args, 'optionalAccess', _57 => _57.parent]),
4025
+ parent: _optionalChain([args, 'optionalAccess', _58 => _58.parent]),
3869
4026
  parentObjectType: this.parentObjectType,
3870
4027
  parentObjectId: this.parentObjectId,
3871
4028
  parentComputeObjectMetadataArgs: this.parentComputeObjectMetadataArgs,
3872
4029
  parentSpanIds,
3873
- propagatedEvent: _nullishCoalesce(_optionalChain([args, 'optionalAccess', _58 => _58.propagatedEvent]), () => ( this.propagatedEvent))
4030
+ propagatedEvent: _nullishCoalesce(_optionalChain([args, 'optionalAccess', _59 => _59.propagatedEvent]), () => ( this.propagatedEvent))
3874
4031
  }),
3875
4032
  spanId
3876
4033
  });
@@ -3879,7 +4036,7 @@ var SpanImpl = (_class11 = class _SpanImpl {
3879
4036
  let endTime;
3880
4037
  let internalData = {};
3881
4038
  if (!this.loggedEndTime) {
3882
- endTime = _nullishCoalesce(_optionalChain([args, 'optionalAccess', _59 => _59.endTime]), () => ( getCurrentUnixTimestamp()));
4039
+ endTime = _nullishCoalesce(_optionalChain([args, 'optionalAccess', _60 => _60.endTime]), () => ( getCurrentUnixTimestamp()));
3883
4040
  internalData = { metrics: { end: endTime } };
3884
4041
  } else {
3885
4042
  endTime = this.loggedEndTime;
@@ -3922,8 +4079,8 @@ var SpanImpl = (_class11 = class _SpanImpl {
3922
4079
  const args = this.parentComputeObjectMetadataArgs;
3923
4080
  switch (this.parentObjectType) {
3924
4081
  case _core.SpanObjectTypeV3.PROJECT_LOGS: {
3925
- const projectID = _optionalChain([args, 'optionalAccess', _60 => _60.project_id]) || this.parentObjectId.getSync().value;
3926
- const projectName = _optionalChain([args, 'optionalAccess', _61 => _61.project_name]);
4082
+ const projectID = _optionalChain([args, 'optionalAccess', _61 => _61.project_id]) || this.parentObjectId.getSync().value;
4083
+ const projectName = _optionalChain([args, 'optionalAccess', _62 => _62.project_name]);
3927
4084
  if (projectID) {
3928
4085
  return `${baseUrl}/object?object_type=project_logs&object_id=${projectID}&id=${this._id}`;
3929
4086
  } else if (projectName) {
@@ -3933,7 +4090,7 @@ var SpanImpl = (_class11 = class _SpanImpl {
3933
4090
  }
3934
4091
  }
3935
4092
  case _core.SpanObjectTypeV3.EXPERIMENT: {
3936
- const expID = _optionalChain([args, 'optionalAccess', _62 => _62.experiment_id]) || _optionalChain([this, 'access', _63 => _63.parentObjectId, 'optionalAccess', _64 => _64.getSync, 'call', _65 => _65(), 'optionalAccess', _66 => _66.value]);
4093
+ const expID = _optionalChain([args, 'optionalAccess', _63 => _63.experiment_id]) || _optionalChain([this, 'access', _64 => _64.parentObjectId, 'optionalAccess', _65 => _65.getSync, 'call', _66 => _66(), 'optionalAccess', _67 => _67.value]);
3937
4094
  if (!expID) {
3938
4095
  return getErrPermlink("provide-experiment-id");
3939
4096
  } else {
@@ -4359,13 +4516,13 @@ var Prompt = (_class13 = class _Prompt {
4359
4516
  return "slug" in this.metadata ? this.metadata.slug : this.metadata.id;
4360
4517
  }
4361
4518
  get prompt() {
4362
- return _optionalChain([this, 'access', _67 => _67.getParsedPromptData, 'call', _68 => _68(), 'optionalAccess', _69 => _69.prompt]);
4519
+ return _optionalChain([this, 'access', _68 => _68.getParsedPromptData, 'call', _69 => _69(), 'optionalAccess', _70 => _70.prompt]);
4363
4520
  }
4364
4521
  get version() {
4365
4522
  return this.metadata[_core.TRANSACTION_ID_FIELD];
4366
4523
  }
4367
4524
  get options() {
4368
- return _optionalChain([this, 'access', _70 => _70.getParsedPromptData, 'call', _71 => _71(), 'optionalAccess', _72 => _72.options]) || {};
4525
+ return _optionalChain([this, 'access', _71 => _71.getParsedPromptData, 'call', _72 => _72(), 'optionalAccess', _73 => _73.options]) || {};
4369
4526
  }
4370
4527
  get promptData() {
4371
4528
  return this.getParsedPromptData();
@@ -4516,7 +4673,7 @@ var Prompt = (_class13 = class _Prompt {
4516
4673
  return {
4517
4674
  type: "chat",
4518
4675
  messages,
4519
- ..._optionalChain([prompt, 'access', _73 => _73.tools, 'optionalAccess', _74 => _74.trim, 'call', _75 => _75()]) ? {
4676
+ ..._optionalChain([prompt, 'access', _74 => _74.tools, 'optionalAccess', _75 => _75.trim, 'call', _76 => _76()]) ? {
4520
4677
  tools: render(prompt.tools)
4521
4678
  } : void 0
4522
4679
  };
@@ -4586,7 +4743,9 @@ var _exportsForTestingOnly = {
4586
4743
  clearTestBackgroundLogger,
4587
4744
  simulateLoginForTests,
4588
4745
  simulateLogoutForTests,
4589
- setInitialTestState
4746
+ setInitialTestState,
4747
+ isGeneratorFunction,
4748
+ isAsyncGeneratorFunction
4590
4749
  };
4591
4750
 
4592
4751
  // src/browser-config.ts
@@ -4799,6 +4958,8 @@ function responsesProxy(openai) {
4799
4958
  return responsesCreateProxy(target.create.bind(target));
4800
4959
  } else if (name === "stream") {
4801
4960
  return responsesStreamProxy(target.stream.bind(target));
4961
+ } else if (name === "parse") {
4962
+ return responsesParseProxy(target.parse.bind(target));
4802
4963
  }
4803
4964
  return Reflect.get(target, name, receiver);
4804
4965
  }
@@ -4839,8 +5000,38 @@ function parseSpanFromResponseCreateParams(params) {
4839
5000
  }
4840
5001
  function parseEventFromResponseCreateResult(result) {
4841
5002
  return {
4842
- output: _optionalChain([result, 'optionalAccess', _76 => _76.output_text]) || "",
4843
- metrics: parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _77 => _77.usage]))
5003
+ output: _optionalChain([result, 'optionalAccess', _77 => _77.output_text]) || "",
5004
+ metrics: parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _78 => _78.usage]))
5005
+ };
5006
+ }
5007
+ function parseSpanFromResponseParseParams(params) {
5008
+ const input = [{ role: "user", content: params.input }];
5009
+ if (params.instructions) {
5010
+ input.push({ role: "system", content: params.instructions });
5011
+ }
5012
+ const spanArgs = {
5013
+ name: "openai.responses.parse",
5014
+ spanAttributes: {
5015
+ type: "llm"
5016
+ },
5017
+ event: {
5018
+ input,
5019
+ metadata: {
5020
+ ...filterFrom(params, ["input", "instructions"]),
5021
+ provider: "openai"
5022
+ }
5023
+ },
5024
+ startTime: getCurrentUnixTimestamp()
5025
+ };
5026
+ return {
5027
+ span: startSpan(spanArgs),
5028
+ start: spanArgs.startTime
5029
+ };
5030
+ }
5031
+ function parseEventFromResponseParseResult(result) {
5032
+ return {
5033
+ output: _optionalChain([result, 'optionalAccess', _79 => _79.output_parsed]) || _optionalChain([result, 'optionalAccess', _80 => _80.output_text]) || "",
5034
+ metrics: parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _81 => _81.usage]))
4844
5035
  };
4845
5036
  }
4846
5037
  function traceResponseCreateStream(stream, timedSpan) {
@@ -4857,7 +5048,7 @@ function traceResponseCreateStream(stream, timedSpan) {
4857
5048
  return result;
4858
5049
  }
4859
5050
  const item = result.value;
4860
- if (!item || !_optionalChain([item, 'optionalAccess', _78 => _78.type]) || !_optionalChain([item, 'optionalAccess', _79 => _79.response])) {
5051
+ if (!item || !_optionalChain([item, 'optionalAccess', _82 => _82.type]) || !_optionalChain([item, 'optionalAccess', _83 => _83.response])) {
4861
5052
  return result;
4862
5053
  }
4863
5054
  const event = parseLogFromItem(item);
@@ -4868,23 +5059,23 @@ function traceResponseCreateStream(stream, timedSpan) {
4868
5059
  };
4869
5060
  }
4870
5061
  function parseLogFromItem(item) {
4871
- if (!item || !_optionalChain([item, 'optionalAccess', _80 => _80.type]) || !_optionalChain([item, 'optionalAccess', _81 => _81.response])) {
5062
+ if (!item || !_optionalChain([item, 'optionalAccess', _84 => _84.type]) || !_optionalChain([item, 'optionalAccess', _85 => _85.response])) {
4872
5063
  return {};
4873
5064
  }
4874
5065
  const response = item.response;
4875
5066
  switch (item.type) {
4876
5067
  case "response.completed":
4877
5068
  const texts = [];
4878
- for (const output of _optionalChain([response, 'optionalAccess', _82 => _82.output]) || []) {
4879
- for (const content of _optionalChain([output, 'optionalAccess', _83 => _83.content]) || []) {
4880
- if (_optionalChain([content, 'optionalAccess', _84 => _84.type]) === "output_text") {
5069
+ for (const output of _optionalChain([response, 'optionalAccess', _86 => _86.output]) || []) {
5070
+ for (const content of _optionalChain([output, 'optionalAccess', _87 => _87.content]) || []) {
5071
+ if (_optionalChain([content, 'optionalAccess', _88 => _88.type]) === "output_text") {
4881
5072
  texts.push(content.text);
4882
5073
  }
4883
5074
  }
4884
5075
  }
4885
5076
  return {
4886
5077
  output: texts.join(""),
4887
- metrics: parseMetricsFromUsage(_optionalChain([response, 'optionalAccess', _85 => _85.usage]))
5078
+ metrics: parseMetricsFromUsage(_optionalChain([response, 'optionalAccess', _89 => _89.usage]))
4888
5079
  };
4889
5080
  default:
4890
5081
  return {};
@@ -4917,6 +5108,16 @@ function responsesStreamProxy(target) {
4917
5108
  }
4918
5109
  });
4919
5110
  }
5111
+ function responsesParseProxy(target) {
5112
+ const hooks = {
5113
+ name: "openai.responses.parse",
5114
+ toSpanFunc: parseSpanFromResponseParseParams,
5115
+ resultToEventFunc: parseEventFromResponseParseResult,
5116
+ traceStreamFunc: traceResponseCreateStream
5117
+ // Reuse the same stream tracing
5118
+ };
5119
+ return proxyCreate(target, hooks);
5120
+ }
4920
5121
  var TOKEN_NAME_MAP = {
4921
5122
  input_tokens: "prompt_tokens",
4922
5123
  output_tokens: "completion_tokens",
@@ -5058,8 +5259,8 @@ function wrapOpenAIv4(openai) {
5058
5259
  const embeddingProxy = createEndpointProxy(openai.embeddings, wrapEmbeddings);
5059
5260
  const moderationProxy = createEndpointProxy(openai.moderations, wrapModerations);
5060
5261
  let betaProxy;
5061
- if (_optionalChain([openai, 'access', _86 => _86.beta, 'optionalAccess', _87 => _87.chat, 'optionalAccess', _88 => _88.completions, 'optionalAccess', _89 => _89.stream])) {
5062
- const betaChatCompletionProxy = new Proxy(_optionalChain([openai, 'optionalAccess', _90 => _90.beta, 'optionalAccess', _91 => _91.chat, 'access', _92 => _92.completions]), {
5262
+ if (_optionalChain([openai, 'access', _90 => _90.beta, 'optionalAccess', _91 => _91.chat, 'optionalAccess', _92 => _92.completions, 'optionalAccess', _93 => _93.stream])) {
5263
+ const betaChatCompletionProxy = new Proxy(_optionalChain([openai, 'optionalAccess', _94 => _94.beta, 'optionalAccess', _95 => _95.chat, 'access', _96 => _96.completions]), {
5063
5264
  get(target, name, receiver) {
5064
5265
  const baseVal = Reflect.get(target, name, receiver);
5065
5266
  if (name === "parse") {
@@ -5107,7 +5308,7 @@ function wrapOpenAIv4(openai) {
5107
5308
  });
5108
5309
  }
5109
5310
  function logCompletionResponse(startTime, response, span) {
5110
- const metrics = parseMetricsFromUsage(_optionalChain([response, 'optionalAccess', _93 => _93.usage]));
5311
+ const metrics = parseMetricsFromUsage(_optionalChain([response, 'optionalAccess', _97 => _97.usage]));
5111
5312
  metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
5112
5313
  span.log({
5113
5314
  output: response.choices,
@@ -5309,7 +5510,7 @@ function parseChatCompletionParams(params) {
5309
5510
  function processEmbeddingResponse(result, span) {
5310
5511
  span.log({
5311
5512
  output: { embedding_length: result.data[0].embedding.length },
5312
- metrics: parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _94 => _94.usage]))
5513
+ metrics: parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _98 => _98.usage]))
5313
5514
  });
5314
5515
  }
5315
5516
  function processModerationResponse(result, span) {
@@ -5339,10 +5540,10 @@ function postprocessStreamingResults(allResults) {
5339
5540
  if (result.usage) {
5340
5541
  metrics = {
5341
5542
  ...metrics,
5342
- ...parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _95 => _95.usage]))
5543
+ ...parseMetricsFromUsage(_optionalChain([result, 'optionalAccess', _99 => _99.usage]))
5343
5544
  };
5344
5545
  }
5345
- const delta = _optionalChain([result, 'access', _96 => _96.choices, 'optionalAccess', _97 => _97[0], 'optionalAccess', _98 => _98.delta]);
5546
+ const delta = _optionalChain([result, 'access', _100 => _100.choices, 'optionalAccess', _101 => _101[0], 'optionalAccess', _102 => _102.delta]);
5346
5547
  if (!delta) {
5347
5548
  continue;
5348
5549
  }