braintrust 0.4.1 → 0.4.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.
@@ -7454,6 +7454,12 @@ interface Span extends Exportable {
7454
7454
  */
7455
7455
  startSpanWithParents(spanId: string, spanParents: string[], args?: StartSpanArgs): Span;
7456
7456
  state(): BraintrustState;
7457
+ /**
7458
+ * Internal method to get the OTEL parent string for this span.
7459
+ * This is used by OtelContextManager to set the braintrust.parent attribute.
7460
+ * @returns A string like "project_id:X" or "experiment_id:X", or undefined if no parent
7461
+ */
7462
+ _getOtelParent(): string | undefined;
7457
7463
  kind: "span";
7458
7464
  }
7459
7465
  declare abstract class ContextManager {
@@ -7484,6 +7490,7 @@ declare class NoopSpan implements Span {
7484
7490
  setAttributes(_args: Omit<StartSpanArgs, "event">): void;
7485
7491
  startSpanWithParents(_spanId: string, _spanParents: string[], _args?: StartSpanArgs): Span;
7486
7492
  state(): BraintrustState;
7493
+ _getOtelParent(): string | undefined;
7487
7494
  toString(): string;
7488
7495
  }
7489
7496
  declare const NOOP_SPAN: NoopSpan;
@@ -7861,6 +7868,12 @@ declare class Experiment extends ObjectFetcher<ExperimentEvent> implements Expor
7861
7868
  kind: "experiment";
7862
7869
  constructor(state: BraintrustState, lazyMetadata: LazyValue<ProjectExperimentMetadata>, dataset?: AnyDataset);
7863
7870
  get id(): Promise<string>;
7871
+ /**
7872
+ * Wait for the experiment ID to be resolved. This is useful for ensuring the ID
7873
+ * is available synchronously in child spans (for OTEL parent attributes).
7874
+ * @internal
7875
+ */
7876
+ _waitForId(): Promise<void>;
7864
7877
  get name(): Promise<string>;
7865
7878
  get project(): Promise<ObjectMetadata>;
7866
7879
  private parentObjectType;
@@ -7454,6 +7454,12 @@ interface Span extends Exportable {
7454
7454
  */
7455
7455
  startSpanWithParents(spanId: string, spanParents: string[], args?: StartSpanArgs): Span;
7456
7456
  state(): BraintrustState;
7457
+ /**
7458
+ * Internal method to get the OTEL parent string for this span.
7459
+ * This is used by OtelContextManager to set the braintrust.parent attribute.
7460
+ * @returns A string like "project_id:X" or "experiment_id:X", or undefined if no parent
7461
+ */
7462
+ _getOtelParent(): string | undefined;
7457
7463
  kind: "span";
7458
7464
  }
7459
7465
  declare abstract class ContextManager {
@@ -7484,6 +7490,7 @@ declare class NoopSpan implements Span {
7484
7490
  setAttributes(_args: Omit<StartSpanArgs, "event">): void;
7485
7491
  startSpanWithParents(_spanId: string, _spanParents: string[], _args?: StartSpanArgs): Span;
7486
7492
  state(): BraintrustState;
7493
+ _getOtelParent(): string | undefined;
7487
7494
  toString(): string;
7488
7495
  }
7489
7496
  declare const NOOP_SPAN: NoopSpan;
@@ -7861,6 +7868,12 @@ declare class Experiment extends ObjectFetcher<ExperimentEvent> implements Expor
7861
7868
  kind: "experiment";
7862
7869
  constructor(state: BraintrustState, lazyMetadata: LazyValue<ProjectExperimentMetadata>, dataset?: AnyDataset);
7863
7870
  get id(): Promise<string>;
7871
+ /**
7872
+ * Wait for the experiment ID to be resolved. This is useful for ensuring the ID
7873
+ * is available synchronously in child spans (for OTEL parent attributes).
7874
+ * @internal
7875
+ */
7876
+ _waitForId(): Promise<void>;
7864
7877
  get name(): Promise<string>;
7865
7878
  get project(): Promise<ObjectMetadata>;
7866
7879
  private parentObjectType;
package/dev/dist/index.js CHANGED
@@ -5141,7 +5141,6 @@ var init_context3 = __esm({
5141
5141
  "src/otel/context.ts"() {
5142
5142
  "use strict";
5143
5143
  init_logger();
5144
- init_util();
5145
5144
  OTEL_NOT_INSTALLED_MESSAGE = "OpenTelemetry packages are not installed. Install them with: npm install @opentelemetry/api @opentelemetry/sdk-trace-base";
5146
5145
  otelTrace = null;
5147
5146
  otelContext = null;
@@ -5204,6 +5203,10 @@ var init_context3 = __esm({
5204
5203
  const currentContext = otelContext.active();
5205
5204
  let newContext = otelTrace.setSpan(currentContext, wrappedContext);
5206
5205
  newContext = newContext.setValue("braintrust_span", span);
5206
+ const parentValue = span._getOtelParent();
5207
+ if (parentValue) {
5208
+ newContext = newContext.setValue("braintrust.parent", parentValue);
5209
+ }
5207
5210
  return otelContext.with(newContext, callback);
5208
5211
  }
5209
5212
  } catch (error2) {
@@ -5219,34 +5222,6 @@ var init_context3 = __esm({
5219
5222
  }
5220
5223
  return void 0;
5221
5224
  }
5222
- _getOtelParent(span) {
5223
- if (!span.parentObjectType || !span.parentObjectId) {
5224
- return void 0;
5225
- }
5226
- try {
5227
- const parentType = span.parentObjectType;
5228
- const parentId = span.parentObjectId;
5229
- if (parentType === 2 /* PROJECT_LOGS */) {
5230
- const id = typeof parentId === "object" && parentId !== null && "get" in parentId ? (
5231
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Type guard ensures object has get method
5232
- parentId.get()
5233
- ) : parentId;
5234
- if (typeof id === "string") {
5235
- return `project_id:${id}`;
5236
- }
5237
- } else if (parentType === 1 /* EXPERIMENT */) {
5238
- const id = typeof parentId === "object" && parentId !== null && "get" in parentId ? (
5239
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Type guard ensures object has get method
5240
- parentId.get()
5241
- ) : parentId;
5242
- if (typeof id === "string") {
5243
- return `experiment_id:${id}`;
5244
- }
5245
- }
5246
- } catch (e9) {
5247
- }
5248
- return void 0;
5249
- }
5250
5225
  };
5251
5226
  }
5252
5227
  });
@@ -5282,7 +5257,7 @@ function getContextManager() {
5282
5257
  try {
5283
5258
  const { OtelContextManager: OtelContextManager2 } = (init_context3(), __toCommonJS(context_exports));
5284
5259
  return new OtelContextManager2();
5285
- } catch (e10) {
5260
+ } catch (e9) {
5286
5261
  console.warn(
5287
5262
  "OTEL not available, falling back to Braintrust-only context manager"
5288
5263
  );
@@ -6521,6 +6496,9 @@ var init_logger = __esm({
6521
6496
  state() {
6522
6497
  return _internalGetGlobalState();
6523
6498
  }
6499
+ _getOtelParent() {
6500
+ return void 0;
6501
+ }
6524
6502
  // Custom inspect for Node.js console.log
6525
6503
  [Symbol.for("nodejs.util.inspect.custom")]() {
6526
6504
  return `NoopSpan {
@@ -7908,6 +7886,15 @@ Error: ${errorText}`;
7908
7886
  return (await this.lazyMetadata.get()).experiment.id;
7909
7887
  })();
7910
7888
  }
7889
+ /**
7890
+ * Wait for the experiment ID to be resolved. This is useful for ensuring the ID
7891
+ * is available synchronously in child spans (for OTEL parent attributes).
7892
+ * @internal
7893
+ */
7894
+ async _waitForId() {
7895
+ await this.lazyId.get().catch(() => {
7896
+ });
7897
+ }
7911
7898
  get name() {
7912
7899
  return (async () => {
7913
7900
  return (await this.lazyMetadata.get()).experiment.name;
@@ -8460,6 +8447,42 @@ View complete results in Braintrust or run experiment.summarize() again.`
8460
8447
  state() {
8461
8448
  return this._state;
8462
8449
  }
8450
+ /**
8451
+ * Internal method to get the OTEL parent string for this span.
8452
+ * This is used by OtelContextManager to set the braintrust.parent attribute.
8453
+ * @returns A string like "project_id:X" or "experiment_id:X", or undefined if no parent
8454
+ */
8455
+ _getOtelParent() {
8456
+ if (!this.parentObjectType) {
8457
+ return void 0;
8458
+ }
8459
+ try {
8460
+ if (this.parentObjectType === 2 /* PROJECT_LOGS */) {
8461
+ const syncResult = this.parentObjectId.getSync();
8462
+ const id = syncResult.value;
8463
+ const args = this.parentComputeObjectMetadataArgs;
8464
+ if (id) {
8465
+ return `project_id:${id}`;
8466
+ }
8467
+ const projectName = _optionalChain([args, 'optionalAccess', _94 => _94.project_name]);
8468
+ if (projectName) {
8469
+ return `project_name:${projectName}`;
8470
+ }
8471
+ } else if (this.parentObjectType === 1 /* EXPERIMENT */) {
8472
+ const syncResult = this.parentObjectId.getSync();
8473
+ const id = syncResult.value;
8474
+ if (!syncResult.resolved) {
8475
+ this.parentObjectId.get().catch(() => {
8476
+ });
8477
+ }
8478
+ if (id) {
8479
+ return `experiment_id:${id}`;
8480
+ }
8481
+ }
8482
+ } catch (e) {
8483
+ }
8484
+ return void 0;
8485
+ }
8463
8486
  // Custom inspect for Node.js console.log
8464
8487
  [Symbol.for("nodejs.util.inspect.custom")]() {
8465
8488
  return `SpanImpl {
@@ -8738,13 +8761,13 @@ View complete results in Braintrust or run experiment.summarize() again.`
8738
8761
  return "slug" in this.metadata ? this.metadata.slug : this.metadata.id;
8739
8762
  }
8740
8763
  get prompt() {
8741
- return _optionalChain([this, 'access', _94 => _94.getParsedPromptData, 'call', _95 => _95(), 'optionalAccess', _96 => _96.prompt]);
8764
+ return _optionalChain([this, 'access', _95 => _95.getParsedPromptData, 'call', _96 => _96(), 'optionalAccess', _97 => _97.prompt]);
8742
8765
  }
8743
8766
  get version() {
8744
8767
  return this.metadata[TRANSACTION_ID_FIELD];
8745
8768
  }
8746
8769
  get options() {
8747
- return _optionalChain([this, 'access', _97 => _97.getParsedPromptData, 'call', _98 => _98(), 'optionalAccess', _99 => _99.options]) || {};
8770
+ return _optionalChain([this, 'access', _98 => _98.getParsedPromptData, 'call', _99 => _99(), 'optionalAccess', _100 => _100.options]) || {};
8748
8771
  }
8749
8772
  get promptData() {
8750
8773
  return this.getParsedPromptData();
@@ -8895,7 +8918,7 @@ View complete results in Braintrust or run experiment.summarize() again.`
8895
8918
  return {
8896
8919
  type: "chat",
8897
8920
  messages,
8898
- ..._optionalChain([prompt, 'access', _100 => _100.tools, 'optionalAccess', _101 => _101.trim, 'call', _102 => _102()]) ? {
8921
+ ..._optionalChain([prompt, 'access', _101 => _101.tools, 'optionalAccess', _102 => _102.trim, 'call', _103 => _103()]) ? {
8899
8922
  tools: render(prompt.tools)
8900
8923
  } : void 0
8901
8924
  };
@@ -8976,7 +8999,7 @@ async function getBaseBranch(remote = void 0) {
8976
8999
  if (git === null) {
8977
9000
  throw new Error("Not in a git repo");
8978
9001
  }
8979
- const remoteName = await _asyncNullishCoalesce(remote, async () => ( await _asyncOptionalChain([(await git.getRemotes()), 'access', async _103 => _103[0], 'optionalAccess', async _104 => _104.name])));
9002
+ const remoteName = await _asyncNullishCoalesce(remote, async () => ( await _asyncOptionalChain([(await git.getRemotes()), 'access', async _104 => _104[0], 'optionalAccess', async _105 => _105.name])));
8980
9003
  if (!remoteName) {
8981
9004
  throw new Error("No remote found");
8982
9005
  }
@@ -8998,7 +9021,7 @@ async function getBaseBranch(remote = void 0) {
8998
9021
  throw new Error(`Could not find HEAD branch in remote ${remoteName}`);
8999
9022
  }
9000
9023
  branch = match[1];
9001
- } catch (e11) {
9024
+ } catch (e10) {
9002
9025
  branch = "main";
9003
9026
  }
9004
9027
  }
@@ -9069,7 +9092,7 @@ async function getRepoInfo(settings) {
9069
9092
  return repo;
9070
9093
  }
9071
9094
  let sanitized = {};
9072
- _optionalChain([settings, 'access', _105 => _105.fields, 'optionalAccess', _106 => _106.forEach, 'call', _107 => _107((field) => {
9095
+ _optionalChain([settings, 'access', _106 => _106.fields, 'optionalAccess', _107 => _107.forEach, 'call', _108 => _108((field) => {
9073
9096
  sanitized = { ...sanitized, [field]: repo[field] };
9074
9097
  })]);
9075
9098
  return sanitized;
@@ -9156,9 +9179,9 @@ function getCallerLocation() {
9156
9179
  const entries = getStackTrace();
9157
9180
  for (const frame of entries) {
9158
9181
  if (thisDir === void 0) {
9159
- thisDir = _optionalChain([isomorph_default, 'access', _108 => _108.pathDirname, 'optionalCall', _109 => _109(frame.fileName)]);
9182
+ thisDir = _optionalChain([isomorph_default, 'access', _109 => _109.pathDirname, 'optionalCall', _110 => _110(frame.fileName)]);
9160
9183
  }
9161
- if (_optionalChain([isomorph_default, 'access', _110 => _110.pathDirname, 'optionalCall', _111 => _111(frame.fileName)]) !== thisDir) {
9184
+ if (_optionalChain([isomorph_default, 'access', _111 => _111.pathDirname, 'optionalCall', _112 => _112(frame.fileName)]) !== thisDir) {
9162
9185
  return {
9163
9186
  caller_functionname: frame.functionName,
9164
9187
  caller_filename: frame.fileName,
@@ -10791,6 +10814,9 @@ async function Eval(name, evaluator, reporterOrOpts) {
10791
10814
  repoInfo: evaluator.repoInfo,
10792
10815
  dataset: Dataset2.isDataset(data) ? data : void 0
10793
10816
  });
10817
+ if (experiment && typeof process !== "undefined" && _optionalChain([process, 'access', _113 => _113.env, 'optionalAccess', _114 => _114.BRAINTRUST_OTEL_COMPAT, 'optionalAccess', _115 => _115.toLowerCase, 'call', _116 => _116()]) === "true") {
10818
+ await experiment._waitForId();
10819
+ }
10794
10820
  if (experiment && options.onStart) {
10795
10821
  const summary = await experiment.summarize({ summarizeScores: false });
10796
10822
  options.onStart(summary);
@@ -10973,10 +10999,10 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
10973
10999
  span,
10974
11000
  parameters: _nullishCoalesce(parameters, () => ( {})),
10975
11001
  reportProgress: (event) => {
10976
- _optionalChain([stream, 'optionalCall', _112 => _112({
11002
+ _optionalChain([stream, 'optionalCall', _117 => _117({
10977
11003
  ...event,
10978
11004
  id: rootSpan.id,
10979
- origin: _optionalChain([baseEvent, 'access', _113 => _113.event, 'optionalAccess', _114 => _114.origin]),
11005
+ origin: _optionalChain([baseEvent, 'access', _118 => _118.event, 'optionalAccess', _119 => _119.origin]),
10980
11006
  name: evaluator.evalName,
10981
11007
  object_type: "task"
10982
11008
  })]);
@@ -11126,7 +11152,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
11126
11152
  ...scores
11127
11153
  },
11128
11154
  error: error2,
11129
- origin: _optionalChain([baseEvent, 'access', _115 => _115.event, 'optionalAccess', _116 => _116.origin])
11155
+ origin: _optionalChain([baseEvent, 'access', _120 => _120.event, 'optionalAccess', _121 => _121.origin])
11130
11156
  });
11131
11157
  };
11132
11158
  if (!experiment) {
@@ -11351,12 +11377,12 @@ async function cachedLogin(options) {
11351
11377
  }
11352
11378
  function makeCheckAuthorized(allowedOrgName) {
11353
11379
  return async (req, _res, next) => {
11354
- if (!_optionalChain([req, 'access', _117 => _117.ctx, 'optionalAccess', _118 => _118.token])) {
11380
+ if (!_optionalChain([req, 'access', _122 => _122.ctx, 'optionalAccess', _123 => _123.token])) {
11355
11381
  return next(_httperrors2.default.call(void 0, 401, "Unauthorized"));
11356
11382
  }
11357
11383
  try {
11358
11384
  const state = await cachedLogin({
11359
- apiKey: _optionalChain([req, 'access', _119 => _119.ctx, 'optionalAccess', _120 => _120.token]),
11385
+ apiKey: _optionalChain([req, 'access', _124 => _124.ctx, 'optionalAccess', _125 => _125.token]),
11360
11386
  orgName: allowedOrgName
11361
11387
  });
11362
11388
  req.ctx.state = state;
@@ -11567,7 +11593,7 @@ function runDevServer(evaluators, opts) {
11567
11593
  scores,
11568
11594
  stream
11569
11595
  } = evalBodySchema.parse(req.body);
11570
- if (!_optionalChain([req, 'access', _121 => _121.ctx, 'optionalAccess', _122 => _122.state])) {
11596
+ if (!_optionalChain([req, 'access', _126 => _126.ctx, 'optionalAccess', _127 => _127.state])) {
11571
11597
  res.status(500).json({ error: "Braintrust state not initialized in request" });
11572
11598
  return;
11573
11599
  }
@@ -11624,7 +11650,7 @@ function runDevServer(evaluators, opts) {
11624
11650
  ...evaluator,
11625
11651
  data: evalData.data,
11626
11652
  scores: evaluator.scores.concat(
11627
- _nullishCoalesce(_optionalChain([scores, 'optionalAccess', _123 => _123.map, 'call', _124 => _124(
11653
+ _nullishCoalesce(_optionalChain([scores, 'optionalAccess', _128 => _128.map, 'call', _129 => _129(
11628
11654
  (score) => makeScorer(state, score.name, score.function_id)
11629
11655
  )]), () => ( []))
11630
11656
  ),
@@ -5141,7 +5141,6 @@ var init_context3 = __esm({
5141
5141
  "src/otel/context.ts"() {
5142
5142
  "use strict";
5143
5143
  init_logger();
5144
- init_util();
5145
5144
  OTEL_NOT_INSTALLED_MESSAGE = "OpenTelemetry packages are not installed. Install them with: npm install @opentelemetry/api @opentelemetry/sdk-trace-base";
5146
5145
  otelTrace = null;
5147
5146
  otelContext = null;
@@ -5204,6 +5203,10 @@ var init_context3 = __esm({
5204
5203
  const currentContext = otelContext.active();
5205
5204
  let newContext = otelTrace.setSpan(currentContext, wrappedContext);
5206
5205
  newContext = newContext.setValue("braintrust_span", span);
5206
+ const parentValue = span._getOtelParent();
5207
+ if (parentValue) {
5208
+ newContext = newContext.setValue("braintrust.parent", parentValue);
5209
+ }
5207
5210
  return otelContext.with(newContext, callback);
5208
5211
  }
5209
5212
  } catch (error2) {
@@ -5219,34 +5222,6 @@ var init_context3 = __esm({
5219
5222
  }
5220
5223
  return void 0;
5221
5224
  }
5222
- _getOtelParent(span) {
5223
- if (!span.parentObjectType || !span.parentObjectId) {
5224
- return void 0;
5225
- }
5226
- try {
5227
- const parentType = span.parentObjectType;
5228
- const parentId = span.parentObjectId;
5229
- if (parentType === 2 /* PROJECT_LOGS */) {
5230
- const id = typeof parentId === "object" && parentId !== null && "get" in parentId ? (
5231
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Type guard ensures object has get method
5232
- parentId.get()
5233
- ) : parentId;
5234
- if (typeof id === "string") {
5235
- return `project_id:${id}`;
5236
- }
5237
- } else if (parentType === 1 /* EXPERIMENT */) {
5238
- const id = typeof parentId === "object" && parentId !== null && "get" in parentId ? (
5239
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Type guard ensures object has get method
5240
- parentId.get()
5241
- ) : parentId;
5242
- if (typeof id === "string") {
5243
- return `experiment_id:${id}`;
5244
- }
5245
- }
5246
- } catch {
5247
- }
5248
- return void 0;
5249
- }
5250
5225
  };
5251
5226
  }
5252
5227
  });
@@ -6521,6 +6496,9 @@ var init_logger = __esm({
6521
6496
  state() {
6522
6497
  return _internalGetGlobalState();
6523
6498
  }
6499
+ _getOtelParent() {
6500
+ return void 0;
6501
+ }
6524
6502
  // Custom inspect for Node.js console.log
6525
6503
  [Symbol.for("nodejs.util.inspect.custom")]() {
6526
6504
  return `NoopSpan {
@@ -7908,6 +7886,15 @@ Error: ${errorText}`;
7908
7886
  return (await this.lazyMetadata.get()).experiment.id;
7909
7887
  })();
7910
7888
  }
7889
+ /**
7890
+ * Wait for the experiment ID to be resolved. This is useful for ensuring the ID
7891
+ * is available synchronously in child spans (for OTEL parent attributes).
7892
+ * @internal
7893
+ */
7894
+ async _waitForId() {
7895
+ await this.lazyId.get().catch(() => {
7896
+ });
7897
+ }
7911
7898
  get name() {
7912
7899
  return (async () => {
7913
7900
  return (await this.lazyMetadata.get()).experiment.name;
@@ -8460,6 +8447,42 @@ View complete results in Braintrust or run experiment.summarize() again.`
8460
8447
  state() {
8461
8448
  return this._state;
8462
8449
  }
8450
+ /**
8451
+ * Internal method to get the OTEL parent string for this span.
8452
+ * This is used by OtelContextManager to set the braintrust.parent attribute.
8453
+ * @returns A string like "project_id:X" or "experiment_id:X", or undefined if no parent
8454
+ */
8455
+ _getOtelParent() {
8456
+ if (!this.parentObjectType) {
8457
+ return void 0;
8458
+ }
8459
+ try {
8460
+ if (this.parentObjectType === 2 /* PROJECT_LOGS */) {
8461
+ const syncResult = this.parentObjectId.getSync();
8462
+ const id = syncResult.value;
8463
+ const args = this.parentComputeObjectMetadataArgs;
8464
+ if (id) {
8465
+ return `project_id:${id}`;
8466
+ }
8467
+ const projectName = args?.project_name;
8468
+ if (projectName) {
8469
+ return `project_name:${projectName}`;
8470
+ }
8471
+ } else if (this.parentObjectType === 1 /* EXPERIMENT */) {
8472
+ const syncResult = this.parentObjectId.getSync();
8473
+ const id = syncResult.value;
8474
+ if (!syncResult.resolved) {
8475
+ this.parentObjectId.get().catch(() => {
8476
+ });
8477
+ }
8478
+ if (id) {
8479
+ return `experiment_id:${id}`;
8480
+ }
8481
+ }
8482
+ } catch (e) {
8483
+ }
8484
+ return void 0;
8485
+ }
8463
8486
  // Custom inspect for Node.js console.log
8464
8487
  [Symbol.for("nodejs.util.inspect.custom")]() {
8465
8488
  return `SpanImpl {
@@ -10791,6 +10814,9 @@ async function Eval(name, evaluator, reporterOrOpts) {
10791
10814
  repoInfo: evaluator.repoInfo,
10792
10815
  dataset: Dataset2.isDataset(data) ? data : void 0
10793
10816
  });
10817
+ if (experiment && typeof process !== "undefined" && process.env?.BRAINTRUST_OTEL_COMPAT?.toLowerCase() === "true") {
10818
+ await experiment._waitForId();
10819
+ }
10794
10820
  if (experiment && options.onStart) {
10795
10821
  const summary = await experiment.summarize({ summarizeScores: false });
10796
10822
  options.onStart(summary);
@@ -8028,6 +8028,12 @@ interface Span extends Exportable {
8028
8028
  */
8029
8029
  startSpanWithParents(spanId: string, spanParents: string[], args?: StartSpanArgs): Span;
8030
8030
  state(): BraintrustState;
8031
+ /**
8032
+ * Internal method to get the OTEL parent string for this span.
8033
+ * This is used by OtelContextManager to set the braintrust.parent attribute.
8034
+ * @returns A string like "project_id:X" or "experiment_id:X", or undefined if no parent
8035
+ */
8036
+ _getOtelParent(): string | undefined;
8031
8037
  kind: "span";
8032
8038
  }
8033
8039
  declare abstract class ContextManager {
@@ -8059,6 +8065,7 @@ declare class NoopSpan implements Span {
8059
8065
  setAttributes(_args: Omit<StartSpanArgs, "event">): void;
8060
8066
  startSpanWithParents(_spanId: string, _spanParents: string[], _args?: StartSpanArgs): Span;
8061
8067
  state(): BraintrustState;
8068
+ _getOtelParent(): string | undefined;
8062
8069
  toString(): string;
8063
8070
  }
8064
8071
  declare const NOOP_SPAN: NoopSpan;
@@ -9030,6 +9037,12 @@ declare class Experiment extends ObjectFetcher<ExperimentEvent> implements Expor
9030
9037
  kind: "experiment";
9031
9038
  constructor(state: BraintrustState, lazyMetadata: LazyValue<ProjectExperimentMetadata>, dataset?: AnyDataset);
9032
9039
  get id(): Promise<string>;
9040
+ /**
9041
+ * Wait for the experiment ID to be resolved. This is useful for ensuring the ID
9042
+ * is available synchronously in child spans (for OTEL parent attributes).
9043
+ * @internal
9044
+ */
9045
+ _waitForId(): Promise<void>;
9033
9046
  get name(): Promise<string>;
9034
9047
  get project(): Promise<ObjectMetadata>;
9035
9048
  private parentObjectType;
@@ -9179,6 +9192,12 @@ declare class SpanImpl implements Span {
9179
9192
  flush(): Promise<void>;
9180
9193
  close(args?: EndSpanArgs): number;
9181
9194
  state(): BraintrustState;
9195
+ /**
9196
+ * Internal method to get the OTEL parent string for this span.
9197
+ * This is used by OtelContextManager to set the braintrust.parent attribute.
9198
+ * @returns A string like "project_id:X" or "experiment_id:X", or undefined if no parent
9199
+ */
9200
+ _getOtelParent(): string | undefined;
9182
9201
  toString(): string;
9183
9202
  }
9184
9203
  /**
package/dist/browser.d.ts CHANGED
@@ -8028,6 +8028,12 @@ interface Span extends Exportable {
8028
8028
  */
8029
8029
  startSpanWithParents(spanId: string, spanParents: string[], args?: StartSpanArgs): Span;
8030
8030
  state(): BraintrustState;
8031
+ /**
8032
+ * Internal method to get the OTEL parent string for this span.
8033
+ * This is used by OtelContextManager to set the braintrust.parent attribute.
8034
+ * @returns A string like "project_id:X" or "experiment_id:X", or undefined if no parent
8035
+ */
8036
+ _getOtelParent(): string | undefined;
8031
8037
  kind: "span";
8032
8038
  }
8033
8039
  declare abstract class ContextManager {
@@ -8059,6 +8065,7 @@ declare class NoopSpan implements Span {
8059
8065
  setAttributes(_args: Omit<StartSpanArgs, "event">): void;
8060
8066
  startSpanWithParents(_spanId: string, _spanParents: string[], _args?: StartSpanArgs): Span;
8061
8067
  state(): BraintrustState;
8068
+ _getOtelParent(): string | undefined;
8062
8069
  toString(): string;
8063
8070
  }
8064
8071
  declare const NOOP_SPAN: NoopSpan;
@@ -9030,6 +9037,12 @@ declare class Experiment extends ObjectFetcher<ExperimentEvent> implements Expor
9030
9037
  kind: "experiment";
9031
9038
  constructor(state: BraintrustState, lazyMetadata: LazyValue<ProjectExperimentMetadata>, dataset?: AnyDataset);
9032
9039
  get id(): Promise<string>;
9040
+ /**
9041
+ * Wait for the experiment ID to be resolved. This is useful for ensuring the ID
9042
+ * is available synchronously in child spans (for OTEL parent attributes).
9043
+ * @internal
9044
+ */
9045
+ _waitForId(): Promise<void>;
9033
9046
  get name(): Promise<string>;
9034
9047
  get project(): Promise<ObjectMetadata>;
9035
9048
  private parentObjectType;
@@ -9179,6 +9192,12 @@ declare class SpanImpl implements Span {
9179
9192
  flush(): Promise<void>;
9180
9193
  close(args?: EndSpanArgs): number;
9181
9194
  state(): BraintrustState;
9195
+ /**
9196
+ * Internal method to get the OTEL parent string for this span.
9197
+ * This is used by OtelContextManager to set the braintrust.parent attribute.
9198
+ * @returns A string like "project_id:X" or "experiment_id:X", or undefined if no parent
9199
+ */
9200
+ _getOtelParent(): string | undefined;
9182
9201
  toString(): string;
9183
9202
  }
9184
9203
  /**