braintrust 3.32.0 → 3.33.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 (60) hide show
  1. package/README.md +0 -43
  2. package/dev/dist/index.d.mts +31 -0
  3. package/dev/dist/index.d.ts +31 -0
  4. package/dev/dist/index.js +2275 -920
  5. package/dev/dist/index.mjs +1610 -255
  6. package/dist/apply-auto-instrumentation.js +263 -224
  7. package/dist/apply-auto-instrumentation.mjs +45 -6
  8. package/dist/auto-instrumentations/bundler/esbuild.cjs +78 -5
  9. package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
  10. package/dist/auto-instrumentations/bundler/next.cjs +78 -5
  11. package/dist/auto-instrumentations/bundler/next.mjs +3 -3
  12. package/dist/auto-instrumentations/bundler/rollup.cjs +78 -5
  13. package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
  14. package/dist/auto-instrumentations/bundler/vite.cjs +78 -5
  15. package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
  16. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +78 -5
  17. package/dist/auto-instrumentations/bundler/webpack.cjs +78 -5
  18. package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
  19. package/dist/auto-instrumentations/{chunk-AFND2U7E.mjs → chunk-T2DMPWFI.mjs} +75 -5
  20. package/dist/auto-instrumentations/{chunk-RI4Y55ZF.mjs → chunk-UHJ2DNYJ.mjs} +6 -1
  21. package/dist/auto-instrumentations/{chunk-QEEPRBIS.mjs → chunk-W5QNG3PV.mjs} +1 -1
  22. package/dist/auto-instrumentations/hook.mjs +86 -7
  23. package/dist/auto-instrumentations/index.cjs +76 -5
  24. package/dist/auto-instrumentations/index.d.mts +3 -1
  25. package/dist/auto-instrumentations/index.d.ts +3 -1
  26. package/dist/auto-instrumentations/index.mjs +3 -1
  27. package/dist/browser.d.mts +202 -342
  28. package/dist/browser.d.ts +202 -342
  29. package/dist/browser.js +2586 -623
  30. package/dist/browser.mjs +2586 -623
  31. package/dist/chunk-7P6ASYW6.mjs +9 -0
  32. package/dist/{chunk-BTRLPQG5.js → chunk-AXJTOUOC.js} +2250 -1172
  33. package/dist/{chunk-AW4QECG5.js → chunk-G3VHOHRC.js} +40 -9
  34. package/dist/chunk-MLKGABMK.js +9 -0
  35. package/dist/{chunk-4QSAHP7D.mjs → chunk-MZLBAFVJ.mjs} +1236 -158
  36. package/dist/{chunk-WV6QZI2W.mjs → chunk-TZVZN2JJ.mjs} +39 -8
  37. package/dist/cli.js +1695 -293
  38. package/dist/custom-views.d.mts +112 -0
  39. package/dist/custom-views.d.ts +112 -0
  40. package/dist/custom-views.js +13 -0
  41. package/dist/custom-views.mjs +13 -0
  42. package/dist/edge-light.d.mts +1 -1
  43. package/dist/edge-light.d.ts +1 -1
  44. package/dist/edge-light.js +2586 -623
  45. package/dist/edge-light.mjs +2586 -623
  46. package/dist/index.d.mts +202 -342
  47. package/dist/index.d.ts +202 -342
  48. package/dist/index.js +1842 -986
  49. package/dist/index.mjs +1310 -454
  50. package/dist/instrumentation/index.d.mts +5 -245
  51. package/dist/instrumentation/index.d.ts +5 -245
  52. package/dist/instrumentation/index.js +1694 -254
  53. package/dist/instrumentation/index.mjs +1694 -254
  54. package/dist/vitest-evals-reporter.js +17 -16
  55. package/dist/vitest-evals-reporter.mjs +3 -2
  56. package/dist/workerd.d.mts +1 -1
  57. package/dist/workerd.d.ts +1 -1
  58. package/dist/workerd.js +2586 -623
  59. package/dist/workerd.mjs +2586 -623
  60. package/package.json +10 -2
@@ -5971,6 +5971,7 @@ var INSTRUMENTATION_NAMES = {
5971
5971
  LANGSMITH: "langsmith",
5972
5972
  MASTRA: "mastra",
5973
5973
  MISTRAL: "mistral",
5974
+ LANGGRAPH_SDK: "langgraph-sdk",
5974
5975
  OLLAMA: "ollama",
5975
5976
  OPENAI: "openai",
5976
5977
  OPENAI_AGENTS: "openai-agents",
@@ -5985,7 +5986,7 @@ var INSTRUMENTATION_NAMES = {
5985
5986
  var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
5986
5987
  "braintrust.spanInstrumentationName"
5987
5988
  );
5988
- var SDK_VERSION = true ? "3.32.0" : "0.0.0";
5989
+ var SDK_VERSION = true ? "3.33.0" : "0.0.0";
5989
5990
  function withSpanInstrumentationName(args, instrumentationName) {
5990
5991
  return {
5991
5992
  ...args,
@@ -9226,6 +9227,38 @@ function getSpanParentObjectAndPropagatedState(options) {
9226
9227
  function getSpanParentObject(options) {
9227
9228
  return getSpanParentObjectAndPropagatedState(options).parentObject;
9228
9229
  }
9230
+ function _internalExportParentSynchronously(parent) {
9231
+ if ("toStr" in parent) {
9232
+ return parent.toStr();
9233
+ }
9234
+ if ("getParentInfo" in parent) {
9235
+ const parentInfo = parent.getParentInfo();
9236
+ if (!parentInfo) {
9237
+ return void 0;
9238
+ }
9239
+ const objectId = parentInfo.objectId.getSync().value;
9240
+ if (!objectId && !parentInfo.computeObjectMetadataArgs) {
9241
+ return void 0;
9242
+ }
9243
+ return new SpanComponentsV4({
9244
+ object_type: parentInfo.objectType,
9245
+ ...objectId ? { object_id: objectId } : {
9246
+ compute_object_metadata_args: parentInfo.computeObjectMetadataArgs ?? {}
9247
+ },
9248
+ row_id: parent.id,
9249
+ root_span_id: parent.rootSpanId,
9250
+ span_id: parent.spanId
9251
+ }).toStr();
9252
+ }
9253
+ const components = braintrustParentToComponents(parent._getOtelParent());
9254
+ if (!components) {
9255
+ return void 0;
9256
+ }
9257
+ return new SpanComponentsV4({
9258
+ object_type: components.objectType,
9259
+ ...components.objectId ? { object_id: components.objectId } : { compute_object_metadata_args: components.computeArgs ?? {} }
9260
+ }).toStr();
9261
+ }
9229
9262
  function currentBraintrustParent(state) {
9230
9263
  const resolvedState = state ?? _globalState;
9231
9264
  const experiment = currentExperiment({ state: resolvedState });
@@ -10606,10 +10639,16 @@ var SpanImpl = class _SpanImpl {
10606
10639
  inject(carrier) {
10607
10640
  const resolvedCarrier = carrier ?? {};
10608
10641
  try {
10642
+ const braintrustParent = this._getOtelParent() ?? this._propagatedState?.braintrustParent;
10643
+ if (!braintrustParent) {
10644
+ debugLogger.forState(this._state).warn(
10645
+ "Injecting trace context without braintrust.parent because the span's destination is not available yet. The receiver will start a new local trace instead of continuing this one."
10646
+ );
10647
+ }
10609
10648
  _injectIntoCarrier(resolvedCarrier, {
10610
10649
  traceId: this._rootSpanId,
10611
10650
  spanId: this._spanId,
10612
- braintrustParent: this._getOtelParent() ?? this._propagatedState?.braintrustParent,
10651
+ braintrustParent,
10613
10652
  propagatedState: this._propagatedState
10614
10653
  });
10615
10654
  } catch (e) {
@@ -12916,6 +12955,18 @@ function defineChannels(pkg, channels, options) {
12916
12955
  var openAIChannels = defineChannels(
12917
12956
  "openai",
12918
12957
  {
12958
+ agentsTraceStart: channel({
12959
+ channelName: "agents.trace.start",
12960
+ kind: "async"
12961
+ }),
12962
+ agentsTraceCapture: channel({
12963
+ channelName: "agents.trace.capture",
12964
+ kind: "async"
12965
+ }),
12966
+ agentsTraceFail: channel({
12967
+ channelName: "agents.trace.fail",
12968
+ kind: "async"
12969
+ }),
12919
12970
  filesCreateTraced: channel({
12920
12971
  channelName: "files.create-traced",
12921
12972
  kind: "async"
@@ -13284,6 +13335,23 @@ function getCachedMetricFromHeaders(headers) {
13284
13335
  return parseCachedHeader(headers.get(LEGACY_CACHED_HEADER));
13285
13336
  }
13286
13337
 
13338
+ // src/instrumentation/plugins/openai-manual-instrumentation-utils.ts
13339
+ async function deterministicDigest(namespace, ...parts) {
13340
+ const encoded = new TextEncoder().encode(
13341
+ [namespace, ...parts].map((part) => `${part.length}:${part}`).join("\0")
13342
+ );
13343
+ return new Uint8Array(
13344
+ await globalThis.crypto.subtle.digest("SHA-256", encoded)
13345
+ );
13346
+ }
13347
+ function digestHex(bytes, length) {
13348
+ return Array.from(bytes.slice(0, length)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
13349
+ }
13350
+ function digestUuid(bytes) {
13351
+ const hex = digestHex(bytes, 16);
13352
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
13353
+ }
13354
+
13287
13355
  // src/instrumentation/plugins/openai-batch-instrumentation.ts
13288
13356
  var SUPPORTED_ENDPOINTS = /* @__PURE__ */ new Set(["/v1/chat/completions", "/v1/responses"]);
13289
13357
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
@@ -13324,21 +13392,6 @@ async function exportParent(parent) {
13324
13392
  }
13325
13393
  return void 0;
13326
13394
  }
13327
- async function deterministicDigest(namespace, ...parts) {
13328
- const encoded = new TextEncoder().encode(
13329
- [namespace, ...parts].map((part) => `${part.length}:${part}`).join("\0")
13330
- );
13331
- return new Uint8Array(
13332
- await globalThis.crypto.subtle.digest("SHA-256", encoded)
13333
- );
13334
- }
13335
- function digestHex(bytes, length) {
13336
- return Array.from(bytes.slice(0, length)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
13337
- }
13338
- function digestUuid(bytes) {
13339
- const hex = digestHex(bytes, 16);
13340
- return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
13341
- }
13342
13395
  async function batchSpanIds(inputFileId) {
13343
13396
  const [row, span, root] = await Promise.all([
13344
13397
  deterministicDigest("openai:batch:row", inputFileId),
@@ -13829,6 +13882,628 @@ var interceptOpenAIBatchTraceComplete = (target, thisArg, args) => Promise.resol
13829
13882
  return result;
13830
13883
  });
13831
13884
 
13885
+ // src/instrumentation/plugins/openai-agents-api-instrumentation.ts
13886
+ var TERMINAL_TURN_EVENTS = /* @__PURE__ */ new Set([
13887
+ "agent.session.turn.completed",
13888
+ "agent.session.turn.failed",
13889
+ "agent.session.turn.cancelled"
13890
+ ]);
13891
+ var TURN_LIFECYCLE_EVENTS = /* @__PURE__ */ new Set([
13892
+ "agent.session.turn.created",
13893
+ "agent.session.turn.in_progress",
13894
+ ...TERMINAL_TURN_EVENTS
13895
+ ]);
13896
+ var SESSION_EVENTS = /* @__PURE__ */ new Set([
13897
+ "agent.session.created",
13898
+ "agent.session.failed",
13899
+ "agent.session.idle",
13900
+ "agent.session.in_progress",
13901
+ "agent.session.requires_action"
13902
+ ]);
13903
+ var SUBAGENT_EVENTS = /* @__PURE__ */ new Set([
13904
+ "agent.session.subagent.active",
13905
+ "agent.session.subagent.closed",
13906
+ "agent.session.subagent.created"
13907
+ ]);
13908
+ function read2(value, key) {
13909
+ if (!isObject(value)) {
13910
+ return void 0;
13911
+ }
13912
+ try {
13913
+ return Reflect.get(value, key);
13914
+ } catch {
13915
+ return void 0;
13916
+ }
13917
+ }
13918
+ function stringValue(value) {
13919
+ return typeof value === "string" && value.length > 0 ? value : void 0;
13920
+ }
13921
+ function recordValue(record, key) {
13922
+ return Object.hasOwn(record, key) ? record[key] : void 0;
13923
+ }
13924
+ function setRecordValue(record, key, value) {
13925
+ Object.defineProperty(record, key, {
13926
+ configurable: true,
13927
+ enumerable: true,
13928
+ value,
13929
+ writable: true
13930
+ });
13931
+ }
13932
+ function loggedError(value, fallback2) {
13933
+ if (value instanceof Error) {
13934
+ return value;
13935
+ }
13936
+ const message = stringValue(read2(value, "message"));
13937
+ return new Error(message ?? (typeof value === "string" ? value : fallback2));
13938
+ }
13939
+ function logInstrumentationError(context, error) {
13940
+ debugLogger.debug(`OpenAI Agents API instrumentation ${context}:`, error);
13941
+ }
13942
+ async function childSpanIds2(rootKey, kind, providerId) {
13943
+ const [row, span] = await Promise.all([
13944
+ deterministicDigest("openai:agents:row", rootKey, kind, providerId),
13945
+ deterministicDigest("openai:agents:span", rootKey, kind, providerId)
13946
+ ]);
13947
+ return { rowId: digestUuid(row), spanId: digestHex(span, 8) };
13948
+ }
13949
+ function traceMetadata(args) {
13950
+ const metadata = {};
13951
+ const suppliedMetadata = read2(args, "metadata");
13952
+ if (isObject(suppliedMetadata)) {
13953
+ try {
13954
+ for (const key of Object.keys(suppliedMetadata)) {
13955
+ metadata[key] = read2(suppliedMetadata, key);
13956
+ }
13957
+ } catch (error) {
13958
+ logInstrumentationError("could not read supplied metadata", error);
13959
+ }
13960
+ }
13961
+ const agent = read2(args, "agent");
13962
+ const agentId = stringValue(read2(agent, "id")) ?? stringValue(read2(args, "agent_id"));
13963
+ const agentName = stringValue(read2(agent, "name"));
13964
+ const model = stringValue(read2(agent, "model"));
13965
+ return {
13966
+ ...metadata,
13967
+ api: "agents",
13968
+ ...agentId ? { agent_id: agentId } : {},
13969
+ ...agentName ? { agent_name: agentName } : {},
13970
+ ...model ? { model } : {},
13971
+ provider: "openai"
13972
+ };
13973
+ }
13974
+ function copyState(state) {
13975
+ return {
13976
+ ...state,
13977
+ callItems: { ...state.callItems },
13978
+ eventIds: [...state.eventIds],
13979
+ openTools: { ...state.openTools },
13980
+ subagents: { ...state.subagents },
13981
+ turnSubagents: { ...state.turnSubagents }
13982
+ };
13983
+ }
13984
+ function startRootSpan(state) {
13985
+ const root = SpanComponentsV4.fromStr(state.root);
13986
+ const parent = SpanComponentsV4.fromStr(state.rootParent);
13987
+ const rowId = stringValue(root.data.row_id);
13988
+ const rootSpanId = stringValue(root.data.root_span_id);
13989
+ const spanId = stringValue(root.data.span_id);
13990
+ if (!rowId || !rootSpanId || !spanId) {
13991
+ throw new Error("OpenAI Agents trace root is invalid");
13992
+ }
13993
+ const hasParentSpan = Boolean(
13994
+ parent.data.row_id && parent.data.span_id && parent.data.root_span_id
13995
+ );
13996
+ return withCurrent(
13997
+ NOOP_SPAN,
13998
+ () => _internalStartSpanWithInitialMergeAndParentSpanIds(
13999
+ withSpanInstrumentationName(
14000
+ {
14001
+ name: "openai.agents.turn",
14002
+ type: "task" /* TASK */,
14003
+ parent: state.rootParent,
14004
+ ...!hasParentSpan ? {
14005
+ parentSpanIds: {
14006
+ parentSpanIds: [],
14007
+ rootSpanId
14008
+ }
14009
+ } : {},
14010
+ spanId,
14011
+ startTime: state.startTime,
14012
+ event: { id: rowId }
14013
+ },
14014
+ INSTRUMENTATION_NAMES.OPENAI
14015
+ )
14016
+ )
14017
+ );
14018
+ }
14019
+ async function startSubagentSpan(state, subagentId, input, metadata, visiting = /* @__PURE__ */ new Set()) {
14020
+ const subagent = recordValue(state.subagents, subagentId);
14021
+ let parent = state.root;
14022
+ if (subagent?.parentAgentId && subagent.parentAgentId !== subagentId && recordValue(state.subagents, subagent.parentAgentId) && !visiting.has(subagent.parentAgentId)) {
14023
+ visiting.add(subagentId);
14024
+ parent = await (await startSubagentSpan(
14025
+ state,
14026
+ subagent.parentAgentId,
14027
+ void 0,
14028
+ void 0,
14029
+ visiting
14030
+ )).export();
14031
+ }
14032
+ const ids = await childSpanIds2(state.rootKey, "subagent", subagentId);
14033
+ return withCurrent(
14034
+ NOOP_SPAN,
14035
+ () => _internalStartSpanWithInitialMerge(
14036
+ withSpanInstrumentationName(
14037
+ {
14038
+ name: "openai.agents.subagent",
14039
+ type: "task" /* TASK */,
14040
+ parent,
14041
+ spanId: ids.spanId,
14042
+ startTime: subagent?.openedAt,
14043
+ event: {
14044
+ id: ids.rowId,
14045
+ ...input !== void 0 ? { input } : {},
14046
+ metadata: {
14047
+ ...metadata,
14048
+ agent_id: subagentId,
14049
+ ...subagent?.parentAgentId ? { parent_agent_id: subagent.parentAgentId } : {},
14050
+ provider: "openai"
14051
+ }
14052
+ }
14053
+ },
14054
+ INSTRUMENTATION_NAMES.OPENAI
14055
+ )
14056
+ )
14057
+ );
14058
+ }
14059
+ async function parentForTurn(state, turnId) {
14060
+ const subagentId = turnId ? recordValue(state.turnSubagents, turnId) : void 0;
14061
+ if (!subagentId) {
14062
+ return state.root;
14063
+ }
14064
+ return await (await startSubagentSpan(state, subagentId)).export();
14065
+ }
14066
+ async function startToolSpan(state, tool, input) {
14067
+ const ids = await childSpanIds2(state.rootKey, "tool", tool.itemId);
14068
+ return withCurrent(
14069
+ NOOP_SPAN,
14070
+ async () => _internalStartSpanWithInitialMerge(
14071
+ withSpanInstrumentationName(
14072
+ {
14073
+ name: tool.name,
14074
+ type: "tool" /* TOOL */,
14075
+ parent: await parentForTurn(state, tool.turnId),
14076
+ spanId: ids.spanId,
14077
+ startTime: tool.startTime,
14078
+ event: {
14079
+ id: ids.rowId,
14080
+ ...input !== void 0 ? { input } : {},
14081
+ metadata: {
14082
+ item_id: tool.itemId,
14083
+ provider: "openai",
14084
+ tool_type: tool.toolType,
14085
+ ...tool.turnId ? { turn_id: tool.turnId } : {}
14086
+ }
14087
+ }
14088
+ },
14089
+ INSTRUMENTATION_NAMES.OPENAI
14090
+ )
14091
+ )
14092
+ );
14093
+ }
14094
+ function toolFromItem(item, observedAt) {
14095
+ const itemId = stringValue(read2(item, "id"));
14096
+ const toolType = stringValue(read2(item, "type"));
14097
+ if (!itemId || !toolType) {
14098
+ return void 0;
14099
+ }
14100
+ const turnId = stringValue(read2(item, "turn_id"));
14101
+ switch (toolType) {
14102
+ case "function_call":
14103
+ return {
14104
+ input: read2(item, "arguments"),
14105
+ tool: {
14106
+ itemId,
14107
+ name: stringValue(read2(item, "name")) ?? "Function call",
14108
+ startTime: observedAt,
14109
+ toolType,
14110
+ ...turnId ? { turnId } : {}
14111
+ }
14112
+ };
14113
+ case "mcp_call": {
14114
+ const name = stringValue(read2(item, "name")) ?? "MCP call";
14115
+ const server = stringValue(read2(item, "server_label"));
14116
+ return {
14117
+ input: read2(item, "arguments"),
14118
+ tool: {
14119
+ itemId,
14120
+ name: server ? `${server}.${name}` : name,
14121
+ startTime: observedAt,
14122
+ toolType,
14123
+ ...turnId ? { turnId } : {}
14124
+ }
14125
+ };
14126
+ }
14127
+ case "web_search_call":
14128
+ return {
14129
+ input: read2(item, "action"),
14130
+ tool: {
14131
+ itemId,
14132
+ name: "Web search",
14133
+ startTime: observedAt,
14134
+ toolType,
14135
+ ...turnId ? { turnId } : {}
14136
+ }
14137
+ };
14138
+ case "command_execution":
14139
+ return {
14140
+ input: {
14141
+ command: read2(item, "command"),
14142
+ cwd: read2(item, "cwd")
14143
+ },
14144
+ tool: {
14145
+ itemId,
14146
+ name: "Command execution",
14147
+ startTime: observedAt,
14148
+ toolType,
14149
+ ...turnId ? { turnId } : {}
14150
+ }
14151
+ };
14152
+ default:
14153
+ return void 0;
14154
+ }
14155
+ }
14156
+ function textFromContent(content) {
14157
+ if (!Array.isArray(content)) {
14158
+ return void 0;
14159
+ }
14160
+ const text = [];
14161
+ for (const part of content) {
14162
+ const partText = read2(part, "text");
14163
+ if (read2(part, "type") === "output_text" && typeof partText === "string") {
14164
+ text.push(partText);
14165
+ }
14166
+ }
14167
+ return text.length > 0 ? text.join("") : void 0;
14168
+ }
14169
+ function toolOutput(item, toolType) {
14170
+ switch (toolType) {
14171
+ case "function_call":
14172
+ return read2(item, "output");
14173
+ case "mcp_call":
14174
+ return read2(item, "output");
14175
+ case "web_search_call":
14176
+ return read2(item, "action");
14177
+ case "command_execution":
14178
+ return read2(item, "output");
14179
+ default:
14180
+ return void 0;
14181
+ }
14182
+ }
14183
+ function toolFailed(item, toolType) {
14184
+ const status = read2(item, "status");
14185
+ const explicitError = read2(item, "error");
14186
+ if (explicitError !== void 0 && explicitError !== null) {
14187
+ return loggedError(explicitError, `OpenAI ${toolType} failed`);
14188
+ }
14189
+ if (status === "failed" || status === "incomplete") {
14190
+ return new Error(`OpenAI ${toolType} ${status}`);
14191
+ }
14192
+ if (toolType === "command_execution" && typeof read2(item, "exit_code") === "number" && read2(item, "exit_code") !== 0) {
14193
+ return new Error(
14194
+ `OpenAI command exited with code ${read2(item, "exit_code")}`
14195
+ );
14196
+ }
14197
+ return void 0;
14198
+ }
14199
+ async function completeTool(state, tool, item, endTime) {
14200
+ const span = await startToolSpan(state, tool);
14201
+ const output = toolOutput(item, tool.toolType);
14202
+ const error = toolFailed(item, tool.toolType);
14203
+ span.log({
14204
+ ...output !== void 0 ? { output } : {},
14205
+ ...error ? { error } : {},
14206
+ metadata: {
14207
+ status: read2(item, "status"),
14208
+ ...tool.toolType === "command_execution" ? { exit_code: read2(item, "exit_code") } : {}
14209
+ }
14210
+ });
14211
+ span.end({ endTime });
14212
+ Reflect.deleteProperty(state.openTools, tool.itemId);
14213
+ }
14214
+ async function captureMessage(state, item) {
14215
+ if (read2(item, "type") !== "message" || read2(item, "role") !== "assistant" || read2(item, "phase") !== "final_answer") {
14216
+ return;
14217
+ }
14218
+ const output = textFromContent(read2(item, "content"));
14219
+ if (output === void 0) {
14220
+ return;
14221
+ }
14222
+ const turnId = stringValue(read2(item, "turn_id"));
14223
+ const subagentId = turnId ? recordValue(state.turnSubagents, turnId) : void 0;
14224
+ if (subagentId) {
14225
+ (await startSubagentSpan(state, subagentId)).log({ output });
14226
+ } else {
14227
+ startRootSpan(state).log({ output });
14228
+ }
14229
+ }
14230
+ async function captureItem(state, item, isDone, observedAt) {
14231
+ await captureMessage(state, item);
14232
+ const itemType = stringValue(read2(item, "type"));
14233
+ if (itemType === "function_call_output") {
14234
+ const callId = stringValue(read2(item, "call_id"));
14235
+ const itemId = callId ? recordValue(state.callItems, callId) : void 0;
14236
+ const tool2 = itemId ? recordValue(state.openTools, itemId) : void 0;
14237
+ if (tool2) {
14238
+ await completeTool(state, tool2, item, observedAt);
14239
+ }
14240
+ return;
14241
+ }
14242
+ const descriptor = toolFromItem(item, observedAt);
14243
+ if (!descriptor) {
14244
+ return;
14245
+ }
14246
+ const existing = recordValue(state.openTools, descriptor.tool.itemId);
14247
+ const tool = existing ?? descriptor.tool;
14248
+ setRecordValue(state.openTools, tool.itemId, tool);
14249
+ if (itemType === "function_call") {
14250
+ const callId = stringValue(read2(item, "call_id"));
14251
+ if (callId) {
14252
+ setRecordValue(state.callItems, callId, tool.itemId);
14253
+ }
14254
+ }
14255
+ await startToolSpan(state, tool, descriptor.input);
14256
+ const status = read2(item, "status");
14257
+ const terminalFunctionCall = itemType === "function_call" && (status === "failed" || status === "incomplete");
14258
+ if (itemType !== "function_call" && (isDone || status !== "in_progress") || terminalFunctionCall) {
14259
+ await completeTool(state, tool, item, observedAt);
14260
+ }
14261
+ }
14262
+ function updateSessionMetadata(state, session) {
14263
+ const sessionId = stringValue(read2(session, "id"));
14264
+ const agent = read2(session, "agent");
14265
+ startRootSpan(state).log({
14266
+ metadata: {
14267
+ ...sessionId ? { session_id: sessionId } : {},
14268
+ ...stringValue(read2(agent, "id")) ? { agent_id: read2(agent, "id") } : {},
14269
+ ...stringValue(read2(agent, "name")) ? { agent_name: read2(agent, "name") } : {},
14270
+ ...stringValue(read2(agent, "model")) ? { model: read2(agent, "model") } : {}
14271
+ }
14272
+ });
14273
+ }
14274
+ async function captureSubagent(state, eventType, subagent, observedAt) {
14275
+ const subagentId = stringValue(read2(subagent, "id"));
14276
+ if (!subagentId) {
14277
+ return;
14278
+ }
14279
+ const existing = recordValue(state.subagents, subagentId);
14280
+ const observedOpenedAt = read2(subagent, "opened_at");
14281
+ const openedAt = typeof observedOpenedAt === "number" && Number.isFinite(observedOpenedAt) && observedOpenedAt >= 0 ? observedOpenedAt : existing?.openedAt ?? observedAt;
14282
+ const observedClosedAt = read2(subagent, "closed_at");
14283
+ const closedAt = typeof observedClosedAt === "number" && Number.isFinite(observedClosedAt) && observedClosedAt >= 0 ? observedClosedAt : existing?.closedAt;
14284
+ const parentAgentId = stringValue(read2(subagent, "parent_agent_id")) ?? existing?.parentAgentId;
14285
+ setRecordValue(state.subagents, subagentId, {
14286
+ ...closedAt !== void 0 ? { closedAt } : {},
14287
+ openedAt,
14288
+ ...parentAgentId ? { parentAgentId } : {}
14289
+ });
14290
+ const span = await startSubagentSpan(
14291
+ state,
14292
+ subagentId,
14293
+ read2(subagent, "instructions"),
14294
+ {
14295
+ ...stringValue(read2(subagent, "name")) ? { agent_name: read2(subagent, "name") } : {},
14296
+ status: read2(subagent, "status")
14297
+ }
14298
+ );
14299
+ if (eventType === "agent.session.subagent.closed") {
14300
+ span.end({ endTime: closedAt ?? observedAt });
14301
+ }
14302
+ }
14303
+ async function closeTrace(state, endTime, error, usage) {
14304
+ if (state.ended) {
14305
+ return;
14306
+ }
14307
+ for (const tool of Object.values(state.openTools)) {
14308
+ const span = await startToolSpan(state, tool);
14309
+ span.log({
14310
+ error: error ?? new Error("OpenAI Agents turn ended before tool completion")
14311
+ });
14312
+ span.end({ endTime });
14313
+ }
14314
+ state.openTools = {};
14315
+ for (const subagentId of Object.keys(state.subagents)) {
14316
+ const subagent = state.subagents[subagentId];
14317
+ const span = await startSubagentSpan(state, subagentId);
14318
+ span.end({ endTime: subagent.closedAt ?? endTime });
14319
+ }
14320
+ const root = startRootSpan(state);
14321
+ root.log({
14322
+ ...error ? { error } : {},
14323
+ metrics: parseMetricsFromUsage(usage)
14324
+ });
14325
+ root.end({ endTime });
14326
+ state.ended = true;
14327
+ }
14328
+ async function captureTurnLifecycle(state, event, eventType, observedAt) {
14329
+ const turn = read2(event, "turn");
14330
+ const turnId = stringValue(read2(event, "turn_id")) ?? stringValue(read2(turn, "id"));
14331
+ const subagentId = stringValue(read2(turn, "subagent_id"));
14332
+ if (turnId && subagentId) {
14333
+ setRecordValue(state.turnSubagents, turnId, subagentId);
14334
+ if (!recordValue(state.subagents, subagentId)) {
14335
+ const createdAt = read2(turn, "created_at");
14336
+ setRecordValue(state.subagents, subagentId, {
14337
+ openedAt: typeof createdAt === "number" && Number.isFinite(createdAt) && createdAt >= 0 ? createdAt : observedAt
14338
+ });
14339
+ }
14340
+ await startSubagentSpan(state, subagentId);
14341
+ }
14342
+ const sessionId = stringValue(read2(event, "session_id"));
14343
+ if (sessionId) {
14344
+ startRootSpan(state).log({ metadata: { session_id: sessionId } });
14345
+ }
14346
+ if (!TERMINAL_TURN_EVENTS.has(eventType) || subagentId) {
14347
+ if (subagentId && eventType === "agent.session.turn.failed") {
14348
+ (await startSubagentSpan(state, subagentId)).log({
14349
+ error: loggedError(read2(turn, "error"), "OpenAI subagent turn failed")
14350
+ });
14351
+ }
14352
+ return;
14353
+ }
14354
+ const completedAt = read2(turn, "completed_at");
14355
+ const endTime = typeof completedAt === "number" && Number.isFinite(completedAt) && completedAt >= 0 ? completedAt : observedAt;
14356
+ const usage = read2(event, "usage") ?? read2(turn, "usage");
14357
+ const error = eventType === "agent.session.turn.completed" ? void 0 : loggedError(
14358
+ read2(turn, "error"),
14359
+ eventType === "agent.session.turn.cancelled" ? "OpenAI Agents turn cancelled" : "OpenAI Agents turn failed"
14360
+ );
14361
+ await closeTrace(state, endTime, error, usage);
14362
+ }
14363
+ async function captureEvent(state, event) {
14364
+ if (state.ended) {
14365
+ return state;
14366
+ }
14367
+ const eventType = stringValue(read2(event, "type"));
14368
+ const eventId = stringValue(read2(event, "event_id"));
14369
+ if (!eventType || eventId && state.eventIds.includes(eventId)) {
14370
+ return state;
14371
+ }
14372
+ const next = copyState(state);
14373
+ const observedAt = getCurrentUnixTimestamp();
14374
+ let handled = false;
14375
+ if (SESSION_EVENTS.has(eventType)) {
14376
+ const session = read2(event, "session");
14377
+ if (session) {
14378
+ updateSessionMetadata(next, session);
14379
+ }
14380
+ handled = true;
14381
+ }
14382
+ if (eventType === "agent.session.turn.item.added") {
14383
+ await captureItem(next, read2(event, "item"), false, observedAt);
14384
+ handled = true;
14385
+ } else if (eventType === "agent.session.turn.item.done") {
14386
+ await captureItem(next, read2(event, "item"), true, observedAt);
14387
+ handled = true;
14388
+ } else if (TURN_LIFECYCLE_EVENTS.has(eventType)) {
14389
+ await captureTurnLifecycle(next, event, eventType, observedAt);
14390
+ handled = true;
14391
+ } else if (SUBAGENT_EVENTS.has(eventType)) {
14392
+ await captureSubagent(next, eventType, read2(event, "subagent"), observedAt);
14393
+ handled = true;
14394
+ } else if (eventType === "agent.session.turn.output_text.delta" && next.firstTokenAt === void 0 && stringValue(read2(event, "delta"))) {
14395
+ next.firstTokenAt = observedAt;
14396
+ startRootSpan(next).log({
14397
+ metrics: { time_to_first_token: observedAt - next.startTime }
14398
+ });
14399
+ handled = true;
14400
+ } else if (eventType === "agent.session.failed") {
14401
+ const session = read2(event, "session");
14402
+ const lastActiveAt = read2(session, "last_active_at");
14403
+ const endTime = typeof lastActiveAt === "number" && Number.isFinite(lastActiveAt) && lastActiveAt >= 0 ? lastActiveAt : observedAt;
14404
+ await closeTrace(
14405
+ next,
14406
+ endTime,
14407
+ loggedError(read2(session, "error"), "OpenAI Agents session failed"),
14408
+ read2(session, "usage")
14409
+ );
14410
+ handled = true;
14411
+ } else if (eventType === "error") {
14412
+ await closeTrace(
14413
+ next,
14414
+ observedAt,
14415
+ loggedError(read2(event, "error"), "OpenAI Agents session failed")
14416
+ );
14417
+ handled = true;
14418
+ }
14419
+ if (!handled) {
14420
+ return state;
14421
+ }
14422
+ if (eventId) {
14423
+ next.eventIds.push(eventId);
14424
+ }
14425
+ return next;
14426
+ }
14427
+ var interceptOpenAIAgentsTraceStart = async (target, thisArg, args) => {
14428
+ const fallback2 = await Reflect.apply(target, thisArg, args);
14429
+ try {
14430
+ const state = args[0].state;
14431
+ const parent = state.rootParent;
14432
+ const traceArgs = args[0].args;
14433
+ const parentComponents = SpanComponentsV4.fromStr(parent);
14434
+ const hasParentSpan = Boolean(
14435
+ parentComponents.data.row_id && parentComponents.data.span_id && parentComponents.data.root_span_id
14436
+ );
14437
+ const rootComponents = SpanComponentsV4.fromStr(state.root);
14438
+ const rowId = stringValue(rootComponents.data.row_id);
14439
+ const rootSpanId = stringValue(rootComponents.data.root_span_id);
14440
+ const spanId = stringValue(rootComponents.data.span_id);
14441
+ if (!rowId || !rootSpanId || !spanId) {
14442
+ throw new Error("OpenAI Agents trace root is invalid");
14443
+ }
14444
+ withCurrent(
14445
+ NOOP_SPAN,
14446
+ () => _internalStartSpanWithInitialMergeAndParentSpanIds(
14447
+ withSpanInstrumentationName(
14448
+ {
14449
+ name: "openai.agents.turn",
14450
+ type: "task" /* TASK */,
14451
+ parent,
14452
+ ...!hasParentSpan ? {
14453
+ parentSpanIds: {
14454
+ parentSpanIds: [],
14455
+ rootSpanId
14456
+ }
14457
+ } : {},
14458
+ spanId,
14459
+ startTime: state.startTime,
14460
+ event: {
14461
+ id: rowId,
14462
+ input: read2(traceArgs, "input"),
14463
+ metadata: traceMetadata(traceArgs)
14464
+ }
14465
+ },
14466
+ INSTRUMENTATION_NAMES.OPENAI
14467
+ )
14468
+ )
14469
+ );
14470
+ return state;
14471
+ } catch (error) {
14472
+ logInstrumentationError("could not start trace", error);
14473
+ return fallback2;
14474
+ }
14475
+ };
14476
+ var interceptOpenAIAgentsTraceCapture = async (target, thisArg, args) => {
14477
+ const fallback2 = await Reflect.apply(target, thisArg, args);
14478
+ if (!args[0].state) {
14479
+ return fallback2;
14480
+ }
14481
+ try {
14482
+ return await captureEvent(args[0].state, args[0].event);
14483
+ } catch (error) {
14484
+ logInstrumentationError("could not capture event", error);
14485
+ return fallback2;
14486
+ }
14487
+ };
14488
+ var interceptOpenAIAgentsTraceFail = async (target, thisArg, args) => {
14489
+ const fallback2 = await Reflect.apply(target, thisArg, args);
14490
+ if (!args[0].state) {
14491
+ return fallback2;
14492
+ }
14493
+ try {
14494
+ const next = copyState(args[0].state);
14495
+ await closeTrace(
14496
+ next,
14497
+ getCurrentUnixTimestamp(),
14498
+ loggedError(args[0].error, "OpenAI Agents request failed")
14499
+ );
14500
+ return next;
14501
+ } catch (error) {
14502
+ logInstrumentationError("could not fail trace", error);
14503
+ return fallback2;
14504
+ }
14505
+ };
14506
+
13832
14507
  // src/instrumentation/plugins/openai-plugin.ts
13833
14508
  var OpenAIPlugin = class extends BasePlugin {
13834
14509
  constructor() {
@@ -13836,6 +14511,13 @@ var OpenAIPlugin = class extends BasePlugin {
13836
14511
  }
13837
14512
  onEnable() {
13838
14513
  this.unsubscribers.push(
14514
+ openAIChannels.agentsTraceStart.intercept(
14515
+ interceptOpenAIAgentsTraceStart
14516
+ ),
14517
+ openAIChannels.agentsTraceCapture.intercept(
14518
+ interceptOpenAIAgentsTraceCapture
14519
+ ),
14520
+ openAIChannels.agentsTraceFail.intercept(interceptOpenAIAgentsTraceFail),
13839
14521
  openAIChannels.filesCreateTraced.intercept(
13840
14522
  interceptOpenAIFilesCreateTraced
13841
14523
  ),
@@ -14396,7 +15078,7 @@ async function* patchCodexEventStream(events, state) {
14396
15078
  try {
14397
15079
  await handleCodexEvent(state, event);
14398
15080
  } catch (error) {
14399
- logInstrumentationError("OpenAI Codex stream event", error);
15081
+ logInstrumentationError2("OpenAI Codex stream event", error);
14400
15082
  }
14401
15083
  yield event;
14402
15084
  }
@@ -14896,10 +15578,10 @@ function safeLog(span, event) {
14896
15578
  try {
14897
15579
  span.log(event);
14898
15580
  } catch (error) {
14899
- logInstrumentationError("OpenAI Codex span log", error);
15581
+ logInstrumentationError2("OpenAI Codex span log", error);
14900
15582
  }
14901
15583
  }
14902
- function logInstrumentationError(context, error) {
15584
+ function logInstrumentationError2(context, error) {
14903
15585
  debugLogger.error(`Error processing ${context}:`, error);
14904
15586
  }
14905
15587
 
@@ -16281,27 +16963,8 @@ function continuationParentFromCreateSessionParams(params) {
16281
16963
  }
16282
16964
  return context.parent;
16283
16965
  }
16284
- function exportSpanSynchronously(span) {
16285
- const parentInfo = span.getParentInfo();
16286
- if (!parentInfo) {
16287
- return void 0;
16288
- }
16289
- const objectId = parentInfo.objectId.getSync().value;
16290
- if (!objectId && !parentInfo.computeObjectMetadataArgs) {
16291
- return void 0;
16292
- }
16293
- return new SpanComponentsV4({
16294
- object_type: parentInfo.objectType,
16295
- ...objectId ? { object_id: objectId } : {
16296
- compute_object_metadata_args: parentInfo.computeObjectMetadataArgs ?? {}
16297
- },
16298
- row_id: span.id,
16299
- root_span_id: span.rootSpanId,
16300
- span_id: span.spanId
16301
- }).toStr();
16302
- }
16303
16966
  function exportedParent(parent) {
16304
- return typeof parent === "string" ? parent : exportSpanSynchronously(parent);
16967
+ return typeof parent === "string" ? parent : _internalExportParentSynchronously(parent);
16305
16968
  }
16306
16969
  function addSerializedContext(args) {
16307
16970
  if (!isObject(args.continuation) || args.sessionId === void 0) {
@@ -17058,16 +17721,16 @@ function braintrustAISDKTelemetry() {
17058
17721
  if (!toolCallId || !state) {
17059
17722
  return;
17060
17723
  }
17061
- const toolOutput = event.toolOutput;
17724
+ const toolOutput2 = event.toolOutput;
17062
17725
  const workflowToolError = event.success === false && "error" in event ? event.error : void 0;
17063
- if (toolOutput?.type === "tool-error" || workflowToolError !== void 0) {
17064
- const error = toolOutput?.error ?? workflowToolError;
17726
+ if (toolOutput2?.type === "tool-error" || workflowToolError !== void 0) {
17727
+ const error = toolOutput2?.error ?? workflowToolError;
17065
17728
  state.span.log({
17066
17729
  error: error instanceof Error ? error.message : String(error),
17067
17730
  metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
17068
17731
  });
17069
17732
  } else {
17070
- const output = toolOutput && "output" in toolOutput ? toolOutput.output : event.output;
17733
+ const output = toolOutput2 && "output" in toolOutput2 ? toolOutput2.output : event.output;
17071
17734
  state.span.log({
17072
17735
  ...shouldRecordOutputs(event) ? { output } : {},
17073
17736
  metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
@@ -19526,9 +20189,9 @@ function patchAISDKStreamingResult(args) {
19526
20189
  }
19527
20190
  finalize({ metrics, output });
19528
20191
  } catch (error) {
19529
- const loggedError = toLoggedError(error);
20192
+ const loggedError2 = toLoggedError(error);
19530
20193
  try {
19531
- span.log({ error: loggedError });
20194
+ span.log({ error: loggedError2 });
19532
20195
  } catch (loggingError) {
19533
20196
  debugLogger.error(
19534
20197
  "Error logging AI SDK streaming failure:",
@@ -19536,7 +20199,7 @@ function patchAISDKStreamingResult(args) {
19536
20199
  );
19537
20200
  }
19538
20201
  finalize({
19539
- error: error instanceof Error ? error : new Error(String(loggedError))
20202
+ error: error instanceof Error ? error : new Error(String(loggedError2))
19540
20203
  });
19541
20204
  }
19542
20205
  };
@@ -19649,9 +20312,9 @@ function patchAISDKStreamingResult(args) {
19649
20312
  }
19650
20313
  controller.enqueue(value);
19651
20314
  } catch (error) {
19652
- const loggedError = toLoggedError(error);
20315
+ const loggedError2 = toLoggedError(error);
19653
20316
  try {
19654
- span.log({ error: loggedError });
20317
+ span.log({ error: loggedError2 });
19655
20318
  } catch (loggingError) {
19656
20319
  debugLogger.error(
19657
20320
  "Error logging AI SDK base stream failure:",
@@ -19659,7 +20322,7 @@ function patchAISDKStreamingResult(args) {
19659
20322
  );
19660
20323
  }
19661
20324
  finalize({
19662
- error: error instanceof Error ? error : new Error(String(loggedError))
20325
+ error: error instanceof Error ? error : new Error(String(loggedError2))
19663
20326
  });
19664
20327
  controller.error(error);
19665
20328
  }
@@ -22553,7 +23216,7 @@ function wrapSendOptionsCallbacks(options, state) {
22553
23216
  try {
22554
23217
  await handleInteractionUpdate(state, args.update);
22555
23218
  } catch (error) {
22556
- logInstrumentationError2("Cursor SDK onDelta", error);
23219
+ logInstrumentationError3("Cursor SDK onDelta", error);
22557
23220
  }
22558
23221
  if (originalOnDelta) {
22559
23222
  return originalOnDelta(args);
@@ -22563,7 +23226,7 @@ function wrapSendOptionsCallbacks(options, state) {
22563
23226
  try {
22564
23227
  handleStepUpdate(state, args.step);
22565
23228
  } catch (error) {
22566
- logInstrumentationError2("Cursor SDK onStep", error);
23229
+ logInstrumentationError3("Cursor SDK onStep", error);
22567
23230
  }
22568
23231
  if (originalOnStep) {
22569
23232
  return originalOnStep(args);
@@ -22645,7 +23308,7 @@ async function* patchCursorStream(stream, state) {
22645
23308
  try {
22646
23309
  await handleStreamMessage2(state, message);
22647
23310
  } catch (error) {
22648
- logInstrumentationError2("Cursor SDK stream", error);
23311
+ logInstrumentationError3("Cursor SDK stream", error);
22649
23312
  }
22650
23313
  yield message;
22651
23314
  }
@@ -22709,7 +23372,7 @@ async function handleToolUpdate(state, update) {
22709
23372
  if (!state.activeToolSpans.has(callId)) {
22710
23373
  state.activeToolSpans.set(
22711
23374
  callId,
22712
- await startToolSpan(state, {
23375
+ await startToolSpan2(state, {
22713
23376
  args,
22714
23377
  callId,
22715
23378
  name,
@@ -22720,7 +23383,7 @@ async function handleToolUpdate(state, update) {
22720
23383
  }
22721
23384
  return;
22722
23385
  }
22723
- const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan(state, {
23386
+ const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan2(state, {
22724
23387
  args,
22725
23388
  callId,
22726
23389
  name,
@@ -22757,7 +23420,7 @@ async function handleStreamMessage2(state, message) {
22757
23420
  } else if (block?.type === "tool_use" && block.id) {
22758
23421
  state.activeToolSpans.set(
22759
23422
  block.id,
22760
- await startToolSpan(state, {
23423
+ await startToolSpan2(state, {
22761
23424
  args: block.input,
22762
23425
  callId: block.id,
22763
23426
  name: block.name,
@@ -22792,7 +23455,7 @@ async function handleToolMessage(state, message) {
22792
23455
  if (!state.activeToolSpans.has(callId)) {
22793
23456
  state.activeToolSpans.set(
22794
23457
  callId,
22795
- await startToolSpan(state, {
23458
+ await startToolSpan2(state, {
22796
23459
  args: message.args,
22797
23460
  callId,
22798
23461
  name: message.name,
@@ -22803,7 +23466,7 @@ async function handleToolMessage(state, message) {
22803
23466
  }
22804
23467
  return;
22805
23468
  }
22806
- const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan(state, {
23469
+ const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan2(state, {
22807
23470
  args: message.args,
22808
23471
  callId,
22809
23472
  name: message.name,
@@ -22830,7 +23493,7 @@ async function handleConversation(state, turns) {
22830
23493
  const command = turn.turn?.shellCommand?.command;
22831
23494
  if (command) {
22832
23495
  const callId = `shell:${state.activeToolSpans.size}:${command}`;
22833
- const toolState = await startToolSpan(state, {
23496
+ const toolState = await startToolSpan2(state, {
22834
23497
  args: turn.turn?.shellCommand,
22835
23498
  callId,
22836
23499
  name: "shell",
@@ -22854,7 +23517,7 @@ async function handleConversationStep(state, step) {
22854
23517
  }
22855
23518
  const toolCall = step.message;
22856
23519
  const callId = typeof toolCall?.callId === "string" ? toolCall.callId : `conversation-tool:${state.activeToolSpans.size}`;
22857
- const toolState = await startToolSpan(state, {
23520
+ const toolState = await startToolSpan2(state, {
22858
23521
  args: extractToolArgs(toolCall),
22859
23522
  callId,
22860
23523
  name: extractToolName(toolCall),
@@ -22885,7 +23548,7 @@ function handleStepUpdate(state, step) {
22885
23548
  state.stepText.push(step.message.text);
22886
23549
  }
22887
23550
  }
22888
- async function startToolSpan(state, args) {
23551
+ async function startToolSpan2(state, args) {
22889
23552
  const name = args.name || "unknown";
22890
23553
  const metadata = {
22891
23554
  "cursor_sdk.tool.status": args.status,
@@ -23172,10 +23835,10 @@ function safeLog2(span, event) {
23172
23835
  try {
23173
23836
  span.log(event);
23174
23837
  } catch (error) {
23175
- logInstrumentationError2("Cursor SDK span log", error);
23838
+ logInstrumentationError3("Cursor SDK span log", error);
23176
23839
  }
23177
23840
  }
23178
- function logInstrumentationError2(context, error) {
23841
+ function logInstrumentationError3(context, error) {
23179
23842
  debugLogger.error(`Error processing ${context}:`, error);
23180
23843
  }
23181
23844
  function cleanMetrics2(metrics) {
@@ -24013,6 +24676,10 @@ var googleGenAIChannels = defineChannels(
24013
24676
  channelName: "models.embedContent",
24014
24677
  kind: "async"
24015
24678
  }),
24679
+ httpResponseJson: channel({
24680
+ channelName: "httpResponse.json",
24681
+ kind: "async"
24682
+ }),
24016
24683
  interactionsCreate: channel({
24017
24684
  channelName: "interactions.create",
24018
24685
  kind: "async"
@@ -24161,13 +24828,45 @@ var GoogleGenAIPlugin = class extends BasePlugin {
24161
24828
  subscribeToEmbedContentChannel() {
24162
24829
  const tracingChannel = googleGenAIChannels.embedContent.tracingChannel();
24163
24830
  const states = /* @__PURE__ */ new WeakMap();
24831
+ const embeddingSpans = /* @__PURE__ */ new WeakSet();
24832
+ this.unsubscribers.push(
24833
+ googleGenAIChannels.httpResponseJson.intercept(
24834
+ (target, thisArg, args) => {
24835
+ const span = currentSpan();
24836
+ const result = Reflect.apply(target, thisArg, args);
24837
+ if (embeddingSpans.has(span)) {
24838
+ void Promise.resolve(result).then(
24839
+ (response) => {
24840
+ try {
24841
+ const metrics = cleanMetrics3(
24842
+ extractEmbedContentMetrics(response)
24843
+ );
24844
+ if (embeddingSpans.has(span) && Object.keys(metrics).length > 0) {
24845
+ span.log({ metrics });
24846
+ }
24847
+ } catch (error) {
24848
+ debugLogger.error(
24849
+ "Error reading Google GenAI embedding usage:",
24850
+ error
24851
+ );
24852
+ }
24853
+ },
24854
+ () => {
24855
+ }
24856
+ // The embedding channel handles the original rejection.
24857
+ );
24858
+ }
24859
+ return result;
24860
+ }
24861
+ )
24862
+ );
24164
24863
  const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
24165
24864
  tracingChannel,
24166
24865
  states,
24167
24866
  (event) => {
24168
24867
  const params = event.arguments[0];
24169
24868
  const input = serializeEmbedContentInput(params);
24170
- const metadata = extractEmbedContentMetadata(params);
24869
+ const metadata = { provider: "google", model: params.model };
24171
24870
  const span = startSpan(
24172
24871
  withSpanInstrumentationName(
24173
24872
  {
@@ -24180,6 +24879,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
24180
24879
  INSTRUMENTATION_NAMES.GOOGLE_GENAI
24181
24880
  )
24182
24881
  );
24882
+ embeddingSpans.add(span);
24183
24883
  return {
24184
24884
  span,
24185
24885
  startTime: getCurrentUnixTimestamp()
@@ -24191,7 +24891,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
24191
24891
  ensureSpanState(states, event, () => {
24192
24892
  const params = event.arguments[0];
24193
24893
  const input = serializeEmbedContentInput(params);
24194
- const metadata = extractEmbedContentMetadata(params);
24894
+ const metadata = { provider: "google", model: params.model };
24195
24895
  const span = startSpan(
24196
24896
  withSpanInstrumentationName(
24197
24897
  {
@@ -24204,6 +24904,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
24204
24904
  INSTRUMENTATION_NAMES.GOOGLE_GENAI
24205
24905
  )
24206
24906
  );
24907
+ embeddingSpans.add(span);
24207
24908
  return {
24208
24909
  span,
24209
24910
  startTime: getCurrentUnixTimestamp()
@@ -24216,20 +24917,28 @@ var GoogleGenAIPlugin = class extends BasePlugin {
24216
24917
  return;
24217
24918
  }
24218
24919
  try {
24219
- const output = summarizeEmbedContentOutput(event.result);
24220
24920
  spanState.span.log({
24221
- ...output ? { output } : {},
24921
+ output: summarizeEmbedContentOutput(event.result),
24222
24922
  metrics: cleanMetrics3(
24223
24923
  extractEmbedContentMetrics(event.result, spanState.startTime)
24224
24924
  )
24225
24925
  });
24226
24926
  } finally {
24927
+ embeddingSpans.delete(spanState.span);
24227
24928
  spanState.span.end();
24228
24929
  states.delete(event);
24229
24930
  }
24230
24931
  },
24231
24932
  error: (event) => {
24232
- logErrorAndEndSpan(states, event);
24933
+ const spanState = states.get(event);
24934
+ if (!spanState) return;
24935
+ try {
24936
+ spanState.span.log({ error: event.error, output: { count: 0 } });
24937
+ } finally {
24938
+ embeddingSpans.delete(spanState.span);
24939
+ spanState.span.end();
24940
+ states.delete(event);
24941
+ }
24233
24942
  }
24234
24943
  };
24235
24944
  tracingChannel.subscribe(handlers);
@@ -24464,15 +25173,53 @@ function serializeGenerateContentInput(params) {
24464
25173
  return input;
24465
25174
  }
24466
25175
  function serializeEmbedContentInput(params) {
25176
+ let contents = Array.isArray(params.contents) ? params.contents : [params.contents];
25177
+ if (params.model.includes("gemini-embedding-2") && contents.length > 0 && contents.every(
25178
+ (content) => typeof content === "string" || !Array.isArray(content) && !("parts" in content)
25179
+ )) {
25180
+ contents = [contents];
25181
+ }
24467
25182
  const input = {
24468
- model: params.model,
24469
- contents: serializeContentCollection(params.contents)
25183
+ inputs: contents.map((content) => {
25184
+ const parts = typeof content === "string" ? [content] : Array.isArray(content) ? content : "parts" in content ? content.parts : [content];
25185
+ const normalized = parts.flatMap((part) => {
25186
+ if (typeof part === "string") return [{ type: "text", text: part }];
25187
+ if (part.text !== void 0) return [{ type: "text", text: part.text }];
25188
+ const media = part.inlineData ?? part.fileData;
25189
+ if (!media) return [];
25190
+ const data = "data" in media ? `data:${media.mimeType};base64,${typeof media.data === "string" ? media.data : uint8ArrayToBase64(media.data)}` : media.fileUri;
25191
+ return media.mimeType?.startsWith("image/") ? [{ type: "image_url", image_url: { url: data } }] : [
25192
+ {
25193
+ type: "file",
25194
+ file: {
25195
+ file_data: data,
25196
+ ..."displayName" in media && media.displayName ? { filename: media.displayName } : {}
25197
+ }
25198
+ }
25199
+ ];
25200
+ });
25201
+ return {
25202
+ content: normalized.length === 1 && normalized[0].type === "text" ? normalized[0].text : normalized
25203
+ };
25204
+ }),
25205
+ ...params.config?.outputDimensionality !== void 0 ? { output_dimensions: params.config.outputDimensionality } : {}
24470
25206
  };
24471
- const config = params.config ? tryToDict(params.config) : null;
24472
- if (config) {
24473
- input.config = config;
25207
+ try {
25208
+ const processed = processInputAttachments(input);
25209
+ const hasInlineMedia = processed.inputs.some(
25210
+ ({ content }) => Array.isArray(content) && content.some((part) => {
25211
+ const data = part.type === "image_url" ? part.image_url.url : part.type === "file" ? part.file.file_data : void 0;
25212
+ return typeof data === "string" && data.startsWith("data:");
25213
+ })
25214
+ );
25215
+ return hasInlineMedia ? input : processed;
25216
+ } catch (error) {
25217
+ debugLogger.error(
25218
+ "Error processing Google GenAI embedding attachments:",
25219
+ error
25220
+ );
25221
+ return input;
24474
25222
  }
24475
- return input;
24476
25223
  }
24477
25224
  function serializeInteractionInput(params) {
24478
25225
  const input = {
@@ -24660,19 +25407,6 @@ function extractGenerateContentMetadata(params) {
24660
25407
  }
24661
25408
  return metadata;
24662
25409
  }
24663
- function extractEmbedContentMetadata(params) {
24664
- const metadata = {};
24665
- if (params.model) {
24666
- metadata.model = params.model;
24667
- }
24668
- const config = params.config ? tryToDict(params.config) : null;
24669
- if (config) {
24670
- Object.keys(config).forEach((key) => {
24671
- metadata[key] = config[key];
24672
- });
24673
- }
24674
- return metadata;
24675
- }
24676
25410
  function extractGenerateContentMetrics(response, startTime) {
24677
25411
  const metrics = {};
24678
25412
  if (startTime !== void 0) {
@@ -24692,15 +25426,23 @@ function extractEmbedContentMetrics(response, startTime) {
24692
25426
  const end = getCurrentUnixTimestamp();
24693
25427
  metrics.start = startTime;
24694
25428
  metrics.end = end;
24695
- metrics.duration = end - startTime;
24696
- }
24697
- if (response?.usageMetadata) {
24698
- populateUsageMetrics(metrics, response.usageMetadata);
24699
25429
  }
24700
25430
  const embeddingTokenCount = extractEmbedPromptTokenCount(response);
24701
25431
  if (embeddingTokenCount !== void 0) {
24702
25432
  metrics.prompt_tokens = embeddingTokenCount;
24703
- metrics.tokens = embeddingTokenCount;
25433
+ }
25434
+ const totalTokens = response?.usageMetadata?.totalTokenCount ?? embeddingTokenCount;
25435
+ if (totalTokens !== void 0) {
25436
+ metrics.tokens = totalTokens;
25437
+ }
25438
+ const audioTokens = (response?.usageMetadata?.promptTokenDetails ?? response?.usageMetadata?.promptTokensDetails)?.filter(
25439
+ (detail) => detail.modality === "AUDIO" && detail.tokenCount !== void 0
25440
+ );
25441
+ if (audioTokens?.length) {
25442
+ metrics.prompt_audio_tokens = audioTokens.reduce(
25443
+ (sum, detail) => sum + (detail.tokenCount ?? 0),
25444
+ 0
25445
+ );
24704
25446
  }
24705
25447
  return metrics;
24706
25448
  }
@@ -24739,41 +25481,25 @@ function extractEmbedPromptTokenCount(response) {
24739
25481
  if (typeof usagePromptTokens === "number" && Number.isFinite(usagePromptTokens)) {
24740
25482
  return usagePromptTokens;
24741
25483
  }
24742
- const usageTotalTokens = response.usageMetadata?.totalTokenCount;
24743
- if (typeof usageTotalTokens === "number" && Number.isFinite(usageTotalTokens)) {
24744
- return usageTotalTokens;
24745
- }
24746
25484
  const embeddings = Array.isArray(response.embeddings) ? response.embeddings : response.embedding ? [response.embedding] : [];
24747
25485
  if (embeddings.length === 0) {
24748
25486
  return void 0;
24749
25487
  }
24750
25488
  let total = 0;
24751
- let sawAny = false;
24752
25489
  for (const embedding of embeddings) {
24753
25490
  const embeddingStats = tryToDict(tryToDict(embedding)?.statistics);
24754
25491
  const tokenCount2 = embeddingStats?.tokenCount;
24755
25492
  if (typeof tokenCount2 === "number" && Number.isFinite(tokenCount2)) {
24756
25493
  total += tokenCount2;
24757
- sawAny = true;
25494
+ } else {
25495
+ return void 0;
24758
25496
  }
24759
25497
  }
24760
- return sawAny ? total : void 0;
25498
+ return total;
24761
25499
  }
24762
25500
  function summarizeEmbedContentOutput(response) {
24763
- if (!response) {
24764
- return void 0;
24765
- }
24766
- const embeddings = Array.isArray(response.embeddings) ? response.embeddings : response.embedding ? [response.embedding] : [];
24767
- if (embeddings.length === 0) {
24768
- return void 0;
24769
- }
24770
- const firstValues = embeddings[0]?.values;
24771
- if (!Array.isArray(firstValues)) {
24772
- return void 0;
24773
- }
24774
25501
  return {
24775
- embedding_count: embeddings.length,
24776
- embedding_length: firstValues.length
25502
+ count: Array.isArray(response?.embeddings) ? response.embeddings.length : response?.embedding ? 1 : 0
24777
25503
  };
24778
25504
  }
24779
25505
  function populateUsageMetrics(metrics, usage) {
@@ -28400,6 +29126,379 @@ function aggregateMistralStreamChunks(chunks) {
28400
29126
  };
28401
29127
  }
28402
29128
 
29129
+ // src/instrumentation/plugins/langgraph-sdk-channels.ts
29130
+ var langGraphSDKChannels = defineChannels(
29131
+ "@langchain/langgraph-sdk",
29132
+ {
29133
+ wait: channel({
29134
+ channelName: "runs.wait",
29135
+ kind: "async"
29136
+ }),
29137
+ stream: channel({
29138
+ channelName: "runs.stream",
29139
+ kind: "sync-stream"
29140
+ })
29141
+ },
29142
+ { instrumentationName: INSTRUMENTATION_NAMES.LANGGRAPH_SDK }
29143
+ );
29144
+
29145
+ // src/instrumentation/plugins/langgraph-sdk-plugin.ts
29146
+ var LangGraphSDKPlugin = class extends BasePlugin {
29147
+ onEnable() {
29148
+ this.unsubscribers.push(
29149
+ langGraphSDKChannels.wait.intercept(
29150
+ (target, self, args) => instrumentRun("wait", args, () => Reflect.apply(target, self, args))
29151
+ ),
29152
+ langGraphSDKChannels.stream.intercept(
29153
+ (target, self, args) => instrumentRun("stream", args, () => Reflect.apply(target, self, args))
29154
+ )
29155
+ );
29156
+ }
29157
+ onDisable() {
29158
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
29159
+ }
29160
+ };
29161
+ function normalizeMessage(value) {
29162
+ if (!isObject(value)) return value;
29163
+ const role = value.role ?? (value.type === "human" ? "user" : value.type === "ai" || value.type === "AIMessageChunk" ? "assistant" : value.type === "system" || value.type === "tool" || value.type === "function" ? value.type : void 0);
29164
+ if (typeof role !== "string") return value;
29165
+ const message = {
29166
+ role,
29167
+ content: value.content ?? ""
29168
+ };
29169
+ for (const key of ["name", "tool_call_id", "refusal"]) {
29170
+ if (value[key] !== void 0) message[key] = value[key];
29171
+ }
29172
+ const additional = isObject(value.additional_kwargs) ? value.additional_kwargs : {};
29173
+ const toolCalls = Array.isArray(value.tool_calls) && value.tool_calls.length ? value.tool_calls : additional.tool_calls;
29174
+ if (Array.isArray(toolCalls) && toolCalls.length > 0) {
29175
+ message.tool_calls = toolCalls.map((call) => {
29176
+ if (!isObject(call)) return call;
29177
+ if (isObject(call.function)) return call;
29178
+ return {
29179
+ id: call.id,
29180
+ type: "function",
29181
+ function: {
29182
+ name: call.name,
29183
+ arguments: typeof call.args === "string" ? call.args : JSON.stringify(call.args ?? {})
29184
+ }
29185
+ };
29186
+ });
29187
+ }
29188
+ if (Array.isArray(value.invalid_tool_calls) && value.invalid_tool_calls.length > 0)
29189
+ message.invalid_tool_calls = value.invalid_tool_calls;
29190
+ if (message.refusal === void 0 && additional.refusal !== void 0)
29191
+ message.refusal = additional.refusal;
29192
+ return message;
29193
+ }
29194
+ function normalizeRunError(value) {
29195
+ let name;
29196
+ let message;
29197
+ if (value instanceof Error) {
29198
+ name = value.name;
29199
+ message = value.message;
29200
+ } else if (isObject(value) && typeof value.error === "string" && typeof value.message === "string") {
29201
+ name = value.error;
29202
+ message = value.message;
29203
+ } else {
29204
+ return value;
29205
+ }
29206
+ for (let depth = 0; depth < 3; depth++) {
29207
+ try {
29208
+ const nested = JSON.parse(
29209
+ message.startsWith(`${name}: `) ? message.slice(name.length + 2) : message
29210
+ );
29211
+ if (!isObject(nested) || typeof nested.error !== "string" || typeof nested.message !== "string")
29212
+ break;
29213
+ name = nested.error;
29214
+ message = nested.message;
29215
+ } catch {
29216
+ break;
29217
+ }
29218
+ }
29219
+ if (value instanceof Error && name === value.name && message === value.message)
29220
+ return value;
29221
+ return Object.assign(new Error(message), { name });
29222
+ }
29223
+ function normalizeState(value) {
29224
+ if (!isObject(value)) return value;
29225
+ return Object.fromEntries(
29226
+ Object.entries(value).map(([key, field]) => {
29227
+ if (key === "messages" && Array.isArray(field))
29228
+ return [key, field.map(normalizeMessage)];
29229
+ if (key === "__error__") {
29230
+ const error = normalizeRunError(field);
29231
+ if (error instanceof Error)
29232
+ return [key, { error: error.name, message: error.message }];
29233
+ }
29234
+ return [key, field];
29235
+ })
29236
+ );
29237
+ }
29238
+ function normalizeRunOutput(value, input) {
29239
+ if (!isObject(value)) return value;
29240
+ if (Array.isArray(value.messages)) {
29241
+ if (value.__interrupt__ !== void 0 || value.__error__ !== void 0)
29242
+ return void 0;
29243
+ const inputMessages = isObject(input) && Array.isArray(input.messages) ? input.messages : [];
29244
+ let inputPrefixLength = 0;
29245
+ while (inputPrefixLength < inputMessages.length) {
29246
+ const previous = inputMessages[inputPrefixLength];
29247
+ const message = value.messages[inputPrefixLength];
29248
+ if (isObject(previous) && isObject(message) && previous.id !== void 0 && message.id !== void 0 && previous.id !== message.id || JSON.stringify(normalizeMessage(previous)) !== JSON.stringify(normalizeMessage(message)))
29249
+ break;
29250
+ inputPrefixLength++;
29251
+ }
29252
+ for (let index = value.messages.length - 1; index >= inputPrefixLength; index--) {
29253
+ const message = value.messages[index];
29254
+ const normalized = normalizeMessage(message);
29255
+ if (!isObject(normalized)) continue;
29256
+ if (normalized.role === "user") return void 0;
29257
+ if (normalized.role !== "assistant") continue;
29258
+ if (inputMessages.some((previous) => {
29259
+ if (!isObject(previous) || !isObject(message)) return false;
29260
+ return previous.id !== void 0 && previous.id === message.id && JSON.stringify(normalizeMessage(previous)) === JSON.stringify(normalized);
29261
+ }))
29262
+ continue;
29263
+ return normalized;
29264
+ }
29265
+ return void 0;
29266
+ }
29267
+ const result = Object.fromEntries(
29268
+ Object.entries(value).filter(
29269
+ ([key]) => key !== "__interrupt__" && key !== "__error__"
29270
+ )
29271
+ );
29272
+ return !Object.keys(result).length && (value.__interrupt__ !== void 0 || value.__error__ !== void 0) ? void 0 : result;
29273
+ }
29274
+ function instrumentRun(operation, [threadId, assistantId, options], invoke2) {
29275
+ if (isAutoInstrumentationSuppressed()) return invoke2();
29276
+ const start = getCurrentUnixTimestamp();
29277
+ let span;
29278
+ try {
29279
+ const metadata = {
29280
+ "langgraph.thread_id": threadId,
29281
+ "langgraph.assistant_id": assistantId
29282
+ };
29283
+ for (const key of [
29284
+ "streamMode",
29285
+ "streamSubgraphs",
29286
+ "interruptBefore",
29287
+ "interruptAfter",
29288
+ "multitaskStrategy",
29289
+ "durability"
29290
+ ]) {
29291
+ if (options?.[key] !== void 0) metadata[key] = options[key];
29292
+ }
29293
+ span = startSpan(
29294
+ withSpanInstrumentationName(
29295
+ {
29296
+ name: `langgraph.runs.${operation}`,
29297
+ spanAttributes: { type: "task" /* TASK */ },
29298
+ event: {
29299
+ input: options?.command === void 0 ? normalizeState(options?.input) : {
29300
+ input: normalizeState(options.input),
29301
+ command: options.command
29302
+ },
29303
+ metadata
29304
+ }
29305
+ },
29306
+ INSTRUMENTATION_NAMES.LANGGRAPH_SDK
29307
+ )
29308
+ );
29309
+ } catch (error) {
29310
+ debugLogger.error("Error starting LangGraph SDK span:", error);
29311
+ return invoke2();
29312
+ }
29313
+ let ended = false;
29314
+ let output;
29315
+ let streamError;
29316
+ let firstToken;
29317
+ const updates = [];
29318
+ const usageByMessage = /* @__PURE__ */ new Map();
29319
+ const captureUsage = (id, usage) => {
29320
+ if (!isObject(usage)) return;
29321
+ const metrics = {};
29322
+ for (const [source, destination] of [
29323
+ ["input_tokens", "prompt_tokens"],
29324
+ ["output_tokens", "completion_tokens"],
29325
+ ["total_tokens", "tokens"]
29326
+ ]) {
29327
+ const value = usage[source];
29328
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0)
29329
+ metrics[destination] = value;
29330
+ }
29331
+ if (metrics.tokens === void 0 && metrics.prompt_tokens !== void 0 && metrics.completion_tokens !== void 0)
29332
+ metrics.tokens = metrics.prompt_tokens + metrics.completion_tokens;
29333
+ usageByMessage.set(id, { ...usageByMessage.get(id), ...metrics });
29334
+ };
29335
+ const messages = /* @__PURE__ */ new Map();
29336
+ const messageSnapshots = /* @__PURE__ */ new Map();
29337
+ const finish = (error) => {
29338
+ if (ended) return;
29339
+ ended = true;
29340
+ try {
29341
+ const metrics = {};
29342
+ for (const usage of usageByMessage.values()) {
29343
+ for (const [key, value] of Object.entries(usage))
29344
+ metrics[key] = (metrics[key] ?? 0) + value;
29345
+ }
29346
+ if (firstToken !== void 0)
29347
+ metrics.time_to_first_token = firstToken - start;
29348
+ const finalMessages = [
29349
+ ...new Map([...messages, ...messageSnapshots]).values()
29350
+ ];
29351
+ let loggedOutput = normalizeRunOutput(output, options?.input);
29352
+ if (loggedOutput === void 0 && finalMessages.length)
29353
+ loggedOutput = normalizeRunOutput(
29354
+ { messages: finalMessages },
29355
+ void 0
29356
+ );
29357
+ if (output === void 0 && !finalMessages.length && updates.length) {
29358
+ const results = updates.map((update) => normalizeRunOutput(update, options?.input)).filter((update) => update !== void 0);
29359
+ if (results.length) loggedOutput = { updates: results };
29360
+ }
29361
+ const interrupted = [output, ...updates].find(
29362
+ (state) => isObject(state) && state.__interrupt__ !== void 0
29363
+ );
29364
+ span.log({
29365
+ ...loggedOutput !== void 0 ? { output: loggedOutput } : {},
29366
+ ...isObject(interrupted) ? { metadata: { "langgraph.interrupts": interrupted.__interrupt__ } } : {},
29367
+ ...error !== void 0 || streamError !== void 0 ? { error: normalizeRunError(error ?? streamError) } : {},
29368
+ metrics
29369
+ });
29370
+ } catch (error2) {
29371
+ debugLogger.error("Error logging LangGraph SDK span:", error2);
29372
+ }
29373
+ try {
29374
+ span.end();
29375
+ } catch (error2) {
29376
+ debugLogger.error("Error ending LangGraph SDK span:", error2);
29377
+ }
29378
+ };
29379
+ const observeMessages = (value, streaming) => {
29380
+ if (!isObject(value) || !Array.isArray(value.messages)) return;
29381
+ const inputMessages = isObject(options?.input) && Array.isArray(options.input.messages) ? options.input.messages : [];
29382
+ for (const message of value.messages) {
29383
+ if (!isObject(message) || message.type !== "ai" && message.role !== "assistant")
29384
+ continue;
29385
+ if (message.id !== void 0 && inputMessages.some(
29386
+ (input) => isObject(input) && input.id === message.id
29387
+ ))
29388
+ continue;
29389
+ captureUsage(
29390
+ typeof message.id === "string" ? message.id : "message",
29391
+ message.usage_metadata
29392
+ );
29393
+ if (streaming && (typeof message.content === "string" ? message.content.length > 0 : Array.isArray(message.content) && message.content.some(
29394
+ (part) => isObject(part) && typeof part.text === "string" && part.text.length > 0
29395
+ )))
29396
+ firstToken ??= getCurrentUnixTimestamp();
29397
+ }
29398
+ };
29399
+ const onChunk = ({ event, data }) => {
29400
+ if (ended) return;
29401
+ if (event === "metadata" && isObject(data)) {
29402
+ if (typeof data.run_id === "string")
29403
+ span.log({ metadata: { "langgraph.run_id": data.run_id } });
29404
+ } else if (event === "error") {
29405
+ streamError = normalizeRunError(data);
29406
+ } else if (event === "values") {
29407
+ output = data;
29408
+ observeMessages(data, true);
29409
+ } else if (event === "updates") {
29410
+ if (isObject(data)) {
29411
+ const stateUpdates = [];
29412
+ for (const [node, update] of Object.entries(data)) {
29413
+ observeMessages(update, true);
29414
+ if (isObject(update) && Array.isArray(update.messages)) {
29415
+ for (const message of update.messages) {
29416
+ if (isObject(message))
29417
+ messageSnapshots.set(
29418
+ typeof message.id === "string" ? message.id : `update-${messageSnapshots.size}`,
29419
+ message
29420
+ );
29421
+ }
29422
+ const state = Object.fromEntries(
29423
+ Object.entries(update).filter(([key]) => key !== "messages")
29424
+ );
29425
+ if (Object.keys(state).length) stateUpdates.push([node, state]);
29426
+ } else {
29427
+ stateUpdates.push([node, update]);
29428
+ }
29429
+ }
29430
+ if (stateUpdates.length) updates.push(Object.fromEntries(stateUpdates));
29431
+ } else {
29432
+ updates.push(data);
29433
+ }
29434
+ } else if ((event === "messages" || event === "messages/partial" || event === "messages/complete") && Array.isArray(data)) {
29435
+ const parts = event === "messages" ? [data[0]] : data;
29436
+ for (const part of parts) {
29437
+ if (!isObject(part)) continue;
29438
+ const id = typeof part.id === "string" ? part.id : "message";
29439
+ captureUsage(id, part.usage_metadata);
29440
+ const previous = messages.get(id);
29441
+ messages.set(
29442
+ id,
29443
+ event === "messages" && previous && typeof part.content === "string" && typeof previous.content === "string" ? { ...part, content: previous.content + part.content } : part
29444
+ );
29445
+ if (typeof part.content === "string" && part.content.length > 0)
29446
+ firstToken ??= getCurrentUnixTimestamp();
29447
+ }
29448
+ }
29449
+ };
29450
+ let result;
29451
+ try {
29452
+ result = withCurrent(
29453
+ span,
29454
+ () => runWithAutoInstrumentationSuppressed(invoke2)
29455
+ );
29456
+ } catch (error) {
29457
+ finish(error);
29458
+ throw error;
29459
+ }
29460
+ if (operation === "stream") {
29461
+ try {
29462
+ patchStreamIfNeeded(result, {
29463
+ shouldCollect: (chunk) => {
29464
+ try {
29465
+ onChunk(chunk);
29466
+ } catch (error) {
29467
+ debugLogger.error(
29468
+ "Error processing LangGraph stream event:",
29469
+ error
29470
+ );
29471
+ }
29472
+ return false;
29473
+ },
29474
+ aroundNext: (next) => withCurrent(span, () => runWithAutoInstrumentationSuppressed(next)),
29475
+ onComplete: () => finish(),
29476
+ onCancel: () => finish(),
29477
+ onError: (error) => finish(error)
29478
+ });
29479
+ } catch (error) {
29480
+ debugLogger.error("Error observing LangGraph stream:", error);
29481
+ finish();
29482
+ }
29483
+ } else {
29484
+ void Promise.resolve(result).then(
29485
+ (value) => {
29486
+ try {
29487
+ output = value;
29488
+ observeMessages(value, false);
29489
+ if (isObject(value) && isObject(value.__error__))
29490
+ streamError = normalizeRunError(value.__error__);
29491
+ finish();
29492
+ } catch (error) {
29493
+ finish(error);
29494
+ }
29495
+ },
29496
+ (error) => finish(error)
29497
+ );
29498
+ }
29499
+ return result;
29500
+ }
29501
+
28403
29502
  // src/instrumentation/plugins/ollama-channels.ts
28404
29503
  var ollamaChannels = defineChannels(
28405
29504
  "ollama",
@@ -28609,7 +29708,7 @@ function normalizeTextAndImages(content, images) {
28609
29708
  ...unrecognizedImages.length > 0 ? { unrecognizedImages } : {}
28610
29709
  };
28611
29710
  }
28612
- function normalizeMessage(message, toolCallId, syntheticToolCallIdOffset = 0) {
29711
+ function normalizeMessage2(message, toolCallId, syntheticToolCallIdOffset = 0) {
28613
29712
  if (typeof message.role !== "string") {
28614
29713
  return void 0;
28615
29714
  }
@@ -28655,7 +29754,7 @@ function normalizeMessages(messages) {
28655
29754
  toolCallId = pendingToolCallIds.get(toolName)?.shift();
28656
29755
  }
28657
29756
  }
28658
- const normalized = normalizeMessage(
29757
+ const normalized = normalizeMessage2(
28659
29758
  ollamaMessage,
28660
29759
  toolCallId,
28661
29760
  syntheticToolCallIdOffset
@@ -28774,7 +29873,7 @@ function extractOllamaChatOutput(result, syntheticToolCallIdOffset = 0) {
28774
29873
  if (!isObject(result) || !isObject(result.message)) {
28775
29874
  return void 0;
28776
29875
  }
28777
- const message = normalizeMessage(
29876
+ const message = normalizeMessage2(
28778
29877
  result.message,
28779
29878
  void 0,
28780
29879
  syntheticToolCallIdOffset
@@ -31494,14 +32593,14 @@ function extractActionSpanMetadata(args) {
31494
32593
  const options = extractRunInNewSpanOptions(args);
31495
32594
  const labels = isObject(options?.labels) ? options.labels : void 0;
31496
32595
  const metadata = isObject(options?.metadata) ? options.metadata : void 0;
31497
- const actionType = stringValue(labels?.["genkit:metadata:subtype"]);
31498
- const name = stringValue(metadata?.name);
32596
+ const actionType = stringValue2(labels?.["genkit:metadata:subtype"]);
32597
+ const name = stringValue2(metadata?.name);
31499
32598
  if (!actionType || !name) {
31500
32599
  return void 0;
31501
32600
  }
31502
32601
  return {
31503
32602
  actionType,
31504
- key: stringValue(labels?.["genkit:key"]),
32603
+ key: stringValue2(labels?.["genkit:key"]),
31505
32604
  name
31506
32605
  };
31507
32606
  }
@@ -31611,7 +32710,7 @@ function pickNumberMetrics(values) {
31611
32710
  })
31612
32711
  );
31613
32712
  }
31614
- function stringValue(value) {
32713
+ function stringValue2(value) {
31615
32714
  return typeof value === "string" ? value : void 0;
31616
32715
  }
31617
32716
 
@@ -32296,7 +33395,7 @@ function subscribeToFlueContext(value, state) {
32296
33395
  try {
32297
33396
  unsubscribe?.();
32298
33397
  } catch (error) {
32299
- logInstrumentationError3("Flue context unsubscribe", error);
33398
+ logInstrumentationError4("Flue context unsubscribe", error);
32300
33399
  }
32301
33400
  };
32302
33401
  try {
@@ -32312,7 +33411,7 @@ function subscribeToFlueContext(value, state) {
32312
33411
  });
32313
33412
  state.contexts.add(value);
32314
33413
  } catch (error) {
32315
- logInstrumentationError3("Flue context subscription", error);
33414
+ logInstrumentationError4("Flue context subscription", error);
32316
33415
  }
32317
33416
  }
32318
33417
  function isAutoContextTerminalEvent(event, ctx) {
@@ -32368,7 +33467,7 @@ var FlueObserveBridge = class {
32368
33467
  try {
32369
33468
  this.handleEvent(event, flueContextFromUnknown(ctx));
32370
33469
  } catch (error) {
32371
- logInstrumentationError3("Flue observe", error);
33470
+ logInstrumentationError4("Flue observe", error);
32372
33471
  }
32373
33472
  }
32374
33473
  reset() {
@@ -32385,7 +33484,7 @@ var FlueObserveBridge = class {
32385
33484
  try {
32386
33485
  span = this.spanForExecutionOperation(operation, executionContext);
32387
33486
  } catch (error) {
32388
- logInstrumentationError3("Flue execution interceptor", error);
33487
+ logInstrumentationError4("Flue execution interceptor", error);
32389
33488
  }
32390
33489
  return span ? runWithCurrentSpanStore(span, next) : next();
32391
33490
  }
@@ -32591,7 +33690,7 @@ var FlueObserveBridge = class {
32591
33690
  this.runsById.delete(event.runId);
32592
33691
  }
32593
33692
  void flush().catch((error) => {
32594
- logInstrumentationError3("Flue flush", error);
33693
+ logInstrumentationError4("Flue flush", error);
32595
33694
  });
32596
33695
  }
32597
33696
  handleOperationStart(event) {
@@ -33366,17 +34465,17 @@ function safeLog3(span, event) {
33366
34465
  try {
33367
34466
  span.log(event);
33368
34467
  } catch (error) {
33369
- logInstrumentationError3("Flue span log", error);
34468
+ logInstrumentationError4("Flue span log", error);
33370
34469
  }
33371
34470
  }
33372
34471
  function safeEnd(span, endTime) {
33373
34472
  try {
33374
34473
  span.end(endTime === void 0 ? void 0 : { endTime });
33375
34474
  } catch (error) {
33376
- logInstrumentationError3("Flue span end", error);
34475
+ logInstrumentationError4("Flue span end", error);
33377
34476
  }
33378
34477
  }
33379
- function logInstrumentationError3(label, error) {
34478
+ function logInstrumentationError4(label, error) {
33380
34479
  debugLogger.debug(`Error in ${label} instrumentation:`, error);
33381
34480
  }
33382
34481
 
@@ -33944,10 +35043,10 @@ var LangSmithPlugin = class extends BasePlugin {
33944
35043
  const creates = ownValue(batch, "runCreates");
33945
35044
  if (Array.isArray(creates)) {
33946
35045
  const parentFirst = [...creates].sort((left, right) => {
33947
- const leftId = stringValue2(ownValue(left, "id"));
33948
- const rightId = stringValue2(ownValue(right, "id"));
33949
- const leftParent = stringValue2(ownValue(left, "parent_run_id"));
33950
- const rightParent = stringValue2(ownValue(right, "parent_run_id"));
35046
+ const leftId = stringValue3(ownValue(left, "id"));
35047
+ const rightId = stringValue3(ownValue(right, "id"));
35048
+ const leftParent = stringValue3(ownValue(left, "parent_run_id"));
35049
+ const rightParent = stringValue3(ownValue(right, "parent_run_id"));
33951
35050
  if (leftParent && leftParent === rightId) {
33952
35051
  return 1;
33953
35052
  }
@@ -33966,13 +35065,13 @@ var LangSmithPlugin = class extends BasePlugin {
33966
35065
  if (Array.isArray(updates)) {
33967
35066
  for (const run of updates) {
33968
35067
  this.containLifecycleFailure("batchIngestRuns update", () => {
33969
- this.processUpdate(stringValue2(ownValue(run, "id")) ?? "", run);
35068
+ this.processUpdate(stringValue3(ownValue(run, "id")) ?? "", run);
33970
35069
  });
33971
35070
  }
33972
35071
  }
33973
35072
  }
33974
35073
  processCreate(run) {
33975
- const id = stringValue2(ownValue(run, "id"));
35074
+ const id = stringValue3(ownValue(run, "id"));
33976
35075
  if (!id || this.completedRuns.get(id)) {
33977
35076
  return;
33978
35077
  }
@@ -34005,7 +35104,7 @@ var LangSmithPlugin = class extends BasePlugin {
34005
35104
  this.endIfComplete(id, activeRun, run);
34006
35105
  }
34007
35106
  processUpdate(explicitId, run) {
34008
- const id = stringValue2(explicitId) ?? stringValue2(ownValue(run, "id"));
35107
+ const id = stringValue3(explicitId) ?? stringValue3(ownValue(run, "id"));
34009
35108
  if (!id || this.completedRuns.get(id)) {
34010
35109
  return;
34011
35110
  }
@@ -34028,13 +35127,13 @@ var LangSmithPlugin = class extends BasePlugin {
34028
35127
  this.endIfComplete(id, active, active.run);
34029
35128
  }
34030
35129
  startRunSpan(id, run) {
34031
- const traceId = stringValue2(ownValue(run, "trace_id")) ?? id;
34032
- const parentId = stringValue2(ownValue(run, "parent_run_id")) ?? stringValue2(ownValue(ownValue(run, "parent_run"), "id"));
35130
+ const traceId = stringValue3(ownValue(run, "trace_id")) ?? id;
35131
+ const parentId = stringValue3(ownValue(run, "parent_run_id")) ?? stringValue3(ownValue(ownValue(run, "parent_run"), "id"));
34033
35132
  const startTime = timestampSeconds(ownValue(run, "start_time"));
34034
35133
  return startSpan(
34035
35134
  withSpanInstrumentationName(
34036
35135
  {
34037
- name: stringValue2(ownValue(run, "name")) ?? "LangSmith run",
35136
+ name: stringValue3(ownValue(run, "name")) ?? "LangSmith run",
34038
35137
  spanId: id,
34039
35138
  parentSpanIds: {
34040
35139
  parentSpanIds: parentId ? [parentId] : [],
@@ -34126,7 +35225,7 @@ function mergeRuns(previous, current) {
34126
35225
  function isRecord2(value) {
34127
35226
  return typeof value === "object" && value !== null && !Array.isArray(value);
34128
35227
  }
34129
- function stringValue2(value) {
35228
+ function stringValue3(value) {
34130
35229
  return typeof value === "string" && value.length > 0 ? value : void 0;
34131
35230
  }
34132
35231
  function timestampSeconds(value) {
@@ -34144,7 +35243,7 @@ function timestampSeconds(value) {
34144
35243
  return void 0;
34145
35244
  }
34146
35245
  function dottedOrderDepth(run) {
34147
- const dottedOrder = stringValue2(ownValue(run, "dotted_order"));
35246
+ const dottedOrder = stringValue3(ownValue(run, "dotted_order"));
34148
35247
  return dottedOrder ? dottedOrder.split(".").length : Number.MAX_SAFE_INTEGER;
34149
35248
  }
34150
35249
  function mapRunType(runType) {
@@ -34349,7 +35448,7 @@ var PiCodingAgentPlugin = class extends BasePlugin {
34349
35448
  }
34350
35449
  );
34351
35450
  } catch (error) {
34352
- logInstrumentationError4("Pi Coding Agent prompt start", error);
35451
+ logInstrumentationError5("Pi Coding Agent prompt start", error);
34353
35452
  }
34354
35453
  if (!state) {
34355
35454
  return runWithAutoInstrumentationSuppressed(invokeTarget);
@@ -34482,12 +35581,12 @@ function installPiAgentInstrumentation(agent) {
34482
35581
  () => handlePiAgentEvent(state, event)
34483
35582
  );
34484
35583
  } catch (error) {
34485
- logInstrumentationError4("Pi Coding Agent event", error);
35584
+ logInstrumentationError5("Pi Coding Agent event", error);
34486
35585
  }
34487
35586
  });
34488
35587
  piAgentEventSubscriptions.add(agent);
34489
35588
  } catch (error) {
34490
- logInstrumentationError4("Pi Coding Agent event subscription", error);
35589
+ logInstrumentationError5("Pi Coding Agent event subscription", error);
34491
35590
  }
34492
35591
  }
34493
35592
  function makeInstrumentedStreamFunction(agent, originalStreamFunction, property) {
@@ -34537,7 +35636,7 @@ function wrapPiToolExecutors(tools) {
34537
35636
  });
34538
35637
  tool.execute = wrappedExecute;
34539
35638
  } catch (error) {
34540
- logInstrumentationError4("Pi Coding Agent tool wrapping", error);
35639
+ logInstrumentationError5("Pi Coding Agent tool wrapping", error);
34541
35640
  }
34542
35641
  }
34543
35642
  }
@@ -34616,7 +35715,7 @@ function patchAssistantMessageStream(stream, promptState, llmState) {
34616
35715
  try {
34617
35716
  await iterator.return();
34618
35717
  } catch (cleanupError) {
34619
- logInstrumentationError4(
35718
+ logInstrumentationError5(
34620
35719
  "Pi Coding Agent stream cleanup",
34621
35720
  cleanupError
34622
35721
  );
@@ -34781,7 +35880,7 @@ function finishPiPromptRun(state, error) {
34781
35880
  try {
34782
35881
  state.span.end();
34783
35882
  } catch (endError) {
34784
- logInstrumentationError4("Pi Coding Agent prompt end", endError);
35883
+ logInstrumentationError5("Pi Coding Agent prompt end", endError);
34785
35884
  }
34786
35885
  }
34787
35886
  }
@@ -35113,10 +36212,10 @@ function safeLog4(span, event) {
35113
36212
  try {
35114
36213
  span.log(event);
35115
36214
  } catch (error) {
35116
- logInstrumentationError4("Pi Coding Agent span log", error);
36215
+ logInstrumentationError5("Pi Coding Agent span log", error);
35117
36216
  }
35118
36217
  }
35119
- function logInstrumentationError4(context, error) {
36218
+ function logInstrumentationError5(context, error) {
35120
36219
  debugLogger.debug(`${context}:`, error);
35121
36220
  }
35122
36221
 
@@ -35354,7 +36453,7 @@ function handleAgentStreamEvent(state, event) {
35354
36453
  finalizeModelSpan(state, event);
35355
36454
  break;
35356
36455
  case "beforeToolCallEvent":
35357
- startToolSpan2(state, event);
36456
+ startToolSpan3(state, event);
35358
36457
  break;
35359
36458
  case "afterToolCallEvent":
35360
36459
  finalizeToolSpan(state, event);
@@ -35379,7 +36478,7 @@ function handleAgentStreamEvent(state, event) {
35379
36478
  break;
35380
36479
  }
35381
36480
  } catch (error) {
35382
- logInstrumentationError5("Strands Agent SDK event", error);
36481
+ logInstrumentationError6("Strands Agent SDK event", error);
35383
36482
  }
35384
36483
  }
35385
36484
  function handleMultiAgentStreamEvent(state, event, activeChildParents) {
@@ -35415,7 +36514,7 @@ function handleMultiAgentStreamEvent(state, event, activeChildParents) {
35415
36514
  break;
35416
36515
  }
35417
36516
  } catch (error) {
35418
- logInstrumentationError5("Strands Agent SDK multi-agent event", error);
36517
+ logInstrumentationError6("Strands Agent SDK multi-agent event", error);
35419
36518
  }
35420
36519
  }
35421
36520
  function buildModelSpanInput(event, attachmentCache) {
@@ -35494,7 +36593,7 @@ function finalizeModelSpan(state, event) {
35494
36593
  });
35495
36594
  modelState.span.end();
35496
36595
  }
35497
- function startToolSpan2(state, event) {
36596
+ function startToolSpan3(state, event) {
35498
36597
  const toolUse = event.toolUse;
35499
36598
  const key = toolKey2(toolUse);
35500
36599
  if (state.activeTools.has(key)) {
@@ -35774,7 +36873,7 @@ function getModelConfig(model) {
35774
36873
  try {
35775
36874
  return model.getConfig();
35776
36875
  } catch (error) {
35777
- logInstrumentationError5("Strands Agent SDK model config", error);
36876
+ logInstrumentationError6("Strands Agent SDK model config", error);
35778
36877
  return void 0;
35779
36878
  }
35780
36879
  }
@@ -35857,7 +36956,7 @@ function processStrandsInputAttachments(input, cache = createStrandsAttachmentCa
35857
36956
  try {
35858
36957
  return processStrandsInputNode(input, cache);
35859
36958
  } catch (error) {
35860
- logInstrumentationError5("Strands Agent SDK input attachments", error);
36959
+ logInstrumentationError6("Strands Agent SDK input attachments", error);
35861
36960
  return input;
35862
36961
  }
35863
36962
  }
@@ -36077,10 +37176,10 @@ function safeLog5(span, event) {
36077
37176
  try {
36078
37177
  span.log(event);
36079
37178
  } catch (error) {
36080
- logInstrumentationError5("Strands Agent SDK span log", error);
37179
+ logInstrumentationError6("Strands Agent SDK span log", error);
36081
37180
  }
36082
37181
  }
36083
- function logInstrumentationError5(context, error) {
37182
+ function logInstrumentationError6(context, error) {
36084
37183
  debugLogger.debug(`${context}:`, error);
36085
37184
  }
36086
37185
 
@@ -36483,10 +37582,10 @@ function observeAudioStream(value, observe, complete, cancel, span) {
36483
37582
  const getReader = value.getReader;
36484
37583
  value.getReader = function(...args) {
36485
37584
  const reader = Reflect.apply(getReader, this, args);
36486
- const read2 = reader.read;
37585
+ const read3 = reader.read;
36487
37586
  reader.read = function(...readArgs) {
36488
37587
  return Promise.resolve(
36489
- withCurrent(span, () => Reflect.apply(read2, this, readArgs))
37588
+ withCurrent(span, () => Reflect.apply(read3, this, readArgs))
36490
37589
  ).then(
36491
37590
  (result) => {
36492
37591
  if (result.value) safeObserve(result.value);
@@ -36980,14 +38079,14 @@ var CloudflareAIChatPlugin = class extends BasePlugin {
36980
38079
  const result = event.arguments[0];
36981
38080
  state = agent ? this.findResponseState(
36982
38081
  agent,
36983
- stringValue3(ownValue2(result, "requestId"))
38082
+ stringValue4(ownValue2(result, "requestId"))
36984
38083
  ) : void 0;
36985
38084
  if (!state) {
36986
38085
  return;
36987
38086
  }
36988
38087
  state.responseObserved = true;
36989
38088
  const output = serializeMessage(ownValue2(result, "message"));
36990
- const status = stringValue3(ownValue2(result, "status"));
38089
+ const status = stringValue4(ownValue2(result, "status"));
36991
38090
  const error = ownValue2(result, "error");
36992
38091
  const input = ownValue2(result, "continuation") === true ? state.input : serializeMessages(readProperty(agent, "messages"))?.filter(
36993
38092
  (message) => typeof output?.id !== "string" || message.id !== output.id
@@ -37034,7 +38133,7 @@ var CloudflareAIChatPlugin = class extends BasePlugin {
37034
38133
  }
37035
38134
  try {
37036
38135
  const agent = asObject(event.self);
37037
- const requestId = stringValue3(event.arguments[0]);
38136
+ const requestId = stringValue4(event.arguments[0]);
37038
38137
  const key = requestId ?? /* @__PURE__ */ Symbol("cloudflare-ai-chat-turn");
37039
38138
  const activeForAgent = agent ? this.getActiveTurns(agent) : void 0;
37040
38139
  const existing = activeForAgent?.get(key);
@@ -37203,7 +38302,7 @@ function ownValue2(value, key) {
37203
38302
  const descriptor = Object.getOwnPropertyDescriptor(object, key);
37204
38303
  return descriptor && "value" in descriptor ? descriptor.value : void 0;
37205
38304
  }
37206
- function stringValue3(value) {
38305
+ function stringValue4(value) {
37207
38306
  return typeof value === "string" ? value : void 0;
37208
38307
  }
37209
38308
  function serializeMessages(value) {
@@ -37321,7 +38420,7 @@ var CloudflareAgentsPlugin = class extends BasePlugin {
37321
38420
  );
37322
38421
  spans.set(event, span);
37323
38422
  } catch (error) {
37324
- logInstrumentationError6("start", error);
38423
+ logInstrumentationError7("start", error);
37325
38424
  }
37326
38425
  },
37327
38426
  asyncEnd: (event) => {
@@ -37341,7 +38440,7 @@ var CloudflareAgentsPlugin = class extends BasePlugin {
37341
38440
  }
37342
38441
  }
37343
38442
  } catch (error) {
37344
- logInstrumentationError6("completion", error);
38443
+ logInstrumentationError7("completion", error);
37345
38444
  } finally {
37346
38445
  safelyEndSpan(span);
37347
38446
  }
@@ -37355,7 +38454,7 @@ var CloudflareAgentsPlugin = class extends BasePlugin {
37355
38454
  try {
37356
38455
  span.log({ error: event.error });
37357
38456
  } catch (error) {
37358
- logInstrumentationError6("rejection", error);
38457
+ logInstrumentationError7("rejection", error);
37359
38458
  } finally {
37360
38459
  safelyEndSpan(span);
37361
38460
  }
@@ -37385,10 +38484,10 @@ function safelyEndSpan(span) {
37385
38484
  try {
37386
38485
  span.end();
37387
38486
  } catch (error) {
37388
- logInstrumentationError6("span end", error);
38487
+ logInstrumentationError7("span end", error);
37389
38488
  }
37390
38489
  }
37391
- function logInstrumentationError6(operation, error) {
38490
+ function logInstrumentationError7(operation, error) {
37392
38491
  debugLogger.error(
37393
38492
  `Failed to process Cloudflare Agents ${operation} instrumentation:`,
37394
38493
  error
@@ -37413,6 +38512,7 @@ var BraintrustPlugin = class extends BasePlugin {
37413
38512
  openRouterPlugin = null;
37414
38513
  openRouterAgentPlugin = null;
37415
38514
  mistralPlugin = null;
38515
+ langGraphSDKPlugin = null;
37416
38516
  ollamaPlugin = null;
37417
38517
  googleADKPlugin = null;
37418
38518
  coherePlugin = null;
@@ -37493,6 +38593,10 @@ var BraintrustPlugin = class extends BasePlugin {
37493
38593
  this.mistralPlugin = new MistralPlugin();
37494
38594
  this.mistralPlugin.enable();
37495
38595
  }
38596
+ if (integrations.langgraphSDK !== false) {
38597
+ this.langGraphSDKPlugin = new LangGraphSDKPlugin();
38598
+ this.langGraphSDKPlugin.enable();
38599
+ }
37496
38600
  if (integrations.ollama !== false) {
37497
38601
  this.ollamaPlugin = new OllamaPlugin();
37498
38602
  this.ollamaPlugin.enable();
@@ -37621,6 +38725,10 @@ var BraintrustPlugin = class extends BasePlugin {
37621
38725
  this.mistralPlugin.disable();
37622
38726
  this.mistralPlugin = null;
37623
38727
  }
38728
+ if (this.langGraphSDKPlugin) {
38729
+ this.langGraphSDKPlugin.disable();
38730
+ this.langGraphSDKPlugin = null;
38731
+ }
37624
38732
  if (this.ollamaPlugin) {
37625
38733
  this.ollamaPlugin.disable();
37626
38734
  this.ollamaPlugin = null;
@@ -37762,6 +38870,9 @@ var envIntegrationAliases = {
37762
38870
  "langchain-js": "langchain",
37763
38871
  "@langchain": "langchain",
37764
38872
  langgraph: "langgraph",
38873
+ langgraphsdk: "langgraphSDK",
38874
+ "langgraph-sdk": "langgraphSDK",
38875
+ "@langchain/langgraph-sdk": "langgraphSDK",
37765
38876
  langsmith: "langsmith",
37766
38877
  voyage: "voyageai",
37767
38878
  "voyage-ai": "voyageai",
@@ -37802,6 +38913,7 @@ function getDefaultInstrumentationIntegrations() {
37802
38913
  gitHubCopilot: true,
37803
38914
  langchain: true,
37804
38915
  langgraph: true,
38916
+ langgraphSDK: true,
37805
38917
  langsmith: true,
37806
38918
  voyageai: true,
37807
38919
  elevenlabs: true,
@@ -39365,6 +40477,9 @@ function waterfall(tasks, callback) {
39365
40477
  }
39366
40478
  var waterfall$1 = awaitify(waterfall);
39367
40479
 
40480
+ // src/framework.ts
40481
+ import { v5 as uuidv5 } from "uuid";
40482
+
39368
40483
  // src/functions/invoke.ts
39369
40484
  async function invoke(args) {
39370
40485
  const {
@@ -39447,11 +40562,268 @@ async function invoke(args) {
39447
40562
  }
39448
40563
 
39449
40564
  // src/trace.ts
40565
+ var spanFilterFields = /* @__PURE__ */ new Set([
40566
+ "spanType",
40567
+ "name",
40568
+ "hasError",
40569
+ "metadata",
40570
+ "duration"
40571
+ ]);
40572
+ function isRecord3(value) {
40573
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
40574
+ return false;
40575
+ }
40576
+ const prototype = Object.getPrototypeOf(value);
40577
+ return prototype === Object.prototype || prototype === null;
40578
+ }
40579
+ function validateMetadataValue(value, ancestors) {
40580
+ if (value === null || typeof value === "string" || typeof value === "boolean") {
40581
+ return;
40582
+ }
40583
+ if (typeof value === "number") {
40584
+ if (Number.isFinite(value)) {
40585
+ return;
40586
+ }
40587
+ throw new Error("filters.metadata numbers must be finite");
40588
+ }
40589
+ if (typeof value !== "object" || value === null) {
40590
+ throw new Error("filters.metadata values must be JSON-serializable");
40591
+ }
40592
+ if (!Array.isArray(value) && !isRecord3(value)) {
40593
+ throw new Error("filters.metadata values must be JSON-serializable");
40594
+ }
40595
+ if (ancestors.has(value)) {
40596
+ throw new Error("filters.metadata must not contain cycles");
40597
+ }
40598
+ ancestors.add(value);
40599
+ if (Array.isArray(value)) {
40600
+ for (let index = 0; index < value.length; index++) {
40601
+ validateMetadataValue(value[index], ancestors);
40602
+ }
40603
+ } else {
40604
+ if (Object.getOwnPropertySymbols(value).length > 0) {
40605
+ throw new Error("filters.metadata keys must be strings");
40606
+ }
40607
+ for (const nested of Object.values(value)) {
40608
+ validateMetadataValue(nested, ancestors);
40609
+ }
40610
+ }
40611
+ ancestors.delete(value);
40612
+ }
40613
+ function compileMetadataLeaves(metadata, path3 = [], ancestors = /* @__PURE__ */ new WeakSet()) {
40614
+ if (Object.getOwnPropertySymbols(metadata).length > 0) {
40615
+ throw new Error("filters.metadata keys must be strings");
40616
+ }
40617
+ if (ancestors.has(metadata)) {
40618
+ throw new Error("filters.metadata must not contain cycles");
40619
+ }
40620
+ ancestors.add(metadata);
40621
+ const leaves = [];
40622
+ for (const [key, value] of Object.entries(metadata)) {
40623
+ const childPath = [...path3, key];
40624
+ if (isRecord3(value)) {
40625
+ leaves.push(...compileMetadataLeaves(value, childPath, ancestors));
40626
+ } else {
40627
+ validateMetadataValue(value, ancestors);
40628
+ leaves.push([childPath, value]);
40629
+ }
40630
+ }
40631
+ ancestors.delete(metadata);
40632
+ return leaves;
40633
+ }
40634
+ function normalizeSpanFilters(filters, spanType) {
40635
+ if (filters != null && !isRecord3(filters)) {
40636
+ throw new Error("filters must be an object");
40637
+ }
40638
+ const values = { ...filters ?? {} };
40639
+ if (spanType !== void 0) {
40640
+ if (!Array.isArray(spanType) || !spanType.every((item) => typeof item === "string")) {
40641
+ throw new Error("spanType must be an array of strings");
40642
+ }
40643
+ if (Object.hasOwn(values, "spanType")) {
40644
+ throw new Error(
40645
+ "spanType cannot be provided both directly and in filters"
40646
+ );
40647
+ }
40648
+ if (spanType.length > 0) {
40649
+ values.spanType = spanType;
40650
+ }
40651
+ }
40652
+ if (Object.keys(values).some((field) => !spanFilterFields.has(field))) {
40653
+ throw new Error("Unsupported span filter fields");
40654
+ }
40655
+ for (const field of ["spanType", "name"]) {
40656
+ if (Object.hasOwn(values, field)) {
40657
+ const items = values[field];
40658
+ if (!Array.isArray(items) || !items.every((item) => typeof item === "string")) {
40659
+ throw new Error(`filters.${field} must be an array of strings`);
40660
+ }
40661
+ }
40662
+ }
40663
+ if (Object.hasOwn(values, "hasError") && typeof values.hasError !== "boolean") {
40664
+ throw new Error("filters.hasError must be a boolean");
40665
+ }
40666
+ let compiledMetadataLeaves = [];
40667
+ if (Object.hasOwn(values, "metadata")) {
40668
+ if (!isRecord3(values.metadata)) {
40669
+ throw new Error("filters.metadata must be an object");
40670
+ }
40671
+ compiledMetadataLeaves = compileMetadataLeaves(values.metadata);
40672
+ }
40673
+ if (Object.hasOwn(values, "duration")) {
40674
+ if (!isRecord3(values.duration) || Object.keys(values.duration).some(
40675
+ (bound) => bound !== "min" && bound !== "max"
40676
+ )) {
40677
+ throw new Error("filters.duration must contain only min and/or max");
40678
+ }
40679
+ if (Object.values(values.duration).some(
40680
+ (bound) => typeof bound !== "number" || !Number.isFinite(bound)
40681
+ )) {
40682
+ throw new Error("filters.duration bounds must be finite numbers");
40683
+ }
40684
+ }
40685
+ const normalized = {};
40686
+ if (Array.isArray(values.spanType)) {
40687
+ normalized.spanType = values.spanType;
40688
+ }
40689
+ if (Array.isArray(values.name)) {
40690
+ normalized.name = values.name;
40691
+ }
40692
+ if (typeof values.hasError === "boolean") {
40693
+ normalized.hasError = values.hasError;
40694
+ }
40695
+ if (isRecord3(values.metadata)) {
40696
+ normalized.metadata = values.metadata;
40697
+ }
40698
+ if (isRecord3(values.duration)) {
40699
+ normalized.duration = {};
40700
+ if (typeof values.duration.min === "number") {
40701
+ normalized.duration.min = values.duration.min;
40702
+ }
40703
+ if (typeof values.duration.max === "number") {
40704
+ normalized.duration.max = values.duration.max;
40705
+ }
40706
+ }
40707
+ return { filters: normalized, metadataLeaves: compiledMetadataLeaves };
40708
+ }
40709
+ function metadataEqual(actual, expected) {
40710
+ if (expected === null) {
40711
+ return actual === null || actual === void 0;
40712
+ }
40713
+ if (Array.isArray(expected)) {
40714
+ return Array.isArray(actual) && actual.length === expected.length && expected.every((value, index) => metadataEqual(actual[index], value));
40715
+ }
40716
+ if (isRecord3(expected)) {
40717
+ if (!isRecord3(actual)) {
40718
+ return false;
40719
+ }
40720
+ const expectedKeys = Object.keys(expected);
40721
+ const actualKeys = Object.keys(actual);
40722
+ return actualKeys.length === expectedKeys.length && expectedKeys.every(
40723
+ (key) => Object.hasOwn(actual, key) && metadataEqual(actual[key], expected[key])
40724
+ );
40725
+ }
40726
+ return actual === expected;
40727
+ }
40728
+ function matchesSpanFilters(span, compiledFilters) {
40729
+ const { filters, metadataLeaves } = compiledFilters;
40730
+ if (filters.spanType !== void 0 && !filters.spanType.includes(span.span_attributes?.type ?? "")) {
40731
+ return false;
40732
+ }
40733
+ if (filters.name !== void 0 && !filters.name.includes(span.span_attributes?.name ?? "")) {
40734
+ return false;
40735
+ }
40736
+ if (filters.hasError !== void 0 && (span.error !== null && span.error !== void 0) !== filters.hasError) {
40737
+ return false;
40738
+ }
40739
+ for (const [path3, expected] of metadataLeaves) {
40740
+ let actual = span.metadata;
40741
+ for (const key of path3) {
40742
+ actual = isRecord3(actual) && Object.hasOwn(actual, key) ? actual[key] : void 0;
40743
+ }
40744
+ if (!metadataEqual(actual, expected)) {
40745
+ return false;
40746
+ }
40747
+ }
40748
+ if (filters.duration && Object.keys(filters.duration).length > 0) {
40749
+ const metrics = span.metrics;
40750
+ const start = isRecord3(metrics) ? metrics.start : void 0;
40751
+ const end = isRecord3(metrics) ? metrics.end : void 0;
40752
+ if (typeof start !== "number" || !Number.isFinite(start) || typeof end !== "number" || !Number.isFinite(end)) {
40753
+ return false;
40754
+ }
40755
+ const elapsed = end - start;
40756
+ if (filters.duration.min !== void 0 && elapsed < filters.duration.min) {
40757
+ return false;
40758
+ }
40759
+ if (filters.duration.max !== void 0 && elapsed > filters.duration.max) {
40760
+ return false;
40761
+ }
40762
+ }
40763
+ return true;
40764
+ }
40765
+ function btqlComparison(op, name, value) {
40766
+ return {
40767
+ op,
40768
+ left: { op: "ident", name },
40769
+ right: { op: "literal", value }
40770
+ };
40771
+ }
40772
+ function btqlNullCheck(op, name) {
40773
+ return { op, expr: { op: "ident", name } };
40774
+ }
40775
+ function spanFilterClauses(compiledFilters) {
40776
+ const { filters, metadataLeaves } = compiledFilters;
40777
+ const children = [];
40778
+ for (const [field, attribute] of [
40779
+ ["spanType", "type"],
40780
+ ["name", "name"]
40781
+ ]) {
40782
+ const values = filters[field];
40783
+ if (values !== void 0) {
40784
+ children.push(
40785
+ values.length > 0 ? btqlComparison("in", ["span_attributes", attribute], values) : { op: "literal", value: false }
40786
+ );
40787
+ }
40788
+ }
40789
+ if (filters.hasError !== void 0) {
40790
+ children.push(
40791
+ btqlNullCheck(filters.hasError ? "isnotnull" : "isnull", ["error"])
40792
+ );
40793
+ }
40794
+ for (const [path3, value] of metadataLeaves) {
40795
+ const name = ["metadata", ...path3];
40796
+ children.push(
40797
+ value === null ? btqlNullCheck("isnull", name) : btqlComparison("eq", name, value)
40798
+ );
40799
+ }
40800
+ const elapsed = {
40801
+ op: "sub",
40802
+ left: { op: "ident", name: ["metrics", "end"] },
40803
+ right: { op: "ident", name: ["metrics", "start"] }
40804
+ };
40805
+ if (filters.duration?.min !== void 0) {
40806
+ children.push({
40807
+ op: "ge",
40808
+ left: elapsed,
40809
+ right: { op: "literal", value: filters.duration.min }
40810
+ });
40811
+ }
40812
+ if (filters.duration?.max !== void 0) {
40813
+ children.push({
40814
+ op: "le",
40815
+ left: elapsed,
40816
+ right: { op: "literal", value: filters.duration.max }
40817
+ });
40818
+ }
40819
+ return children;
40820
+ }
39450
40821
  var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
39451
- constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false, brainstoreRealtime = true) {
40822
+ constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false, brainstoreRealtime = true, filters) {
40823
+ const normalizedFilters = normalizeSpanFilters(filters, spanTypeFilter);
39452
40824
  const filterExpr = _SpanFetcher.buildFilter(
39453
40825
  rootSpanId,
39454
- spanTypeFilter,
40826
+ normalizedFilters,
39455
40827
  includeScorers
39456
40828
  );
39457
40829
  super(
@@ -39472,42 +40844,22 @@ var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
39472
40844
  rootSpanId;
39473
40845
  _state;
39474
40846
  spanTypeFilter;
39475
- static buildFilter(rootSpanId, spanTypeFilter, includeScorers = false) {
40847
+ static buildFilter(rootSpanId, filters, includeScorers = false) {
40848
+ const purpose = ["span_attributes", "purpose"];
39476
40849
  const children = [
39477
- // Base filter: root_span_id = 'value'
39478
- {
39479
- op: "eq",
39480
- left: { op: "ident", name: ["root_span_id"] },
39481
- right: { op: "literal", value: rootSpanId }
39482
- }
40850
+ btqlComparison("eq", ["root_span_id"], rootSpanId)
39483
40851
  ];
39484
40852
  if (!includeScorers) {
39485
40853
  children.push({
39486
40854
  op: "or",
39487
40855
  children: [
39488
- {
39489
- op: "isnull",
39490
- expr: { op: "ident", name: ["span_attributes", "purpose"] }
39491
- },
39492
- {
39493
- op: "ne",
39494
- left: { op: "ident", name: ["span_attributes", "purpose"] },
39495
- right: { op: "literal", value: "scorer" }
39496
- }
40856
+ btqlNullCheck("isnull", purpose),
40857
+ btqlComparison("ne", purpose, "scorer")
39497
40858
  ]
39498
40859
  });
39499
40860
  }
39500
- if (spanTypeFilter && spanTypeFilter.length > 0) {
39501
- children.push({
39502
- op: "in",
39503
- left: { op: "ident", name: ["span_attributes", "type"] },
39504
- right: { op: "literal", value: spanTypeFilter }
39505
- });
39506
- }
39507
- return {
39508
- op: "and",
39509
- children
39510
- };
40861
+ children.push(...spanFilterClauses(filters));
40862
+ return { op: "and", children };
39511
40863
  }
39512
40864
  get id() {
39513
40865
  return Promise.resolve(this._objectId);
@@ -39522,67 +40874,80 @@ var CachedSpanFetcher = class {
39522
40874
  fetchFn;
39523
40875
  constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState, brainstoreRealtime = true) {
39524
40876
  if (typeof objectTypeOrFetchFn === "function") {
39525
- this.fetchFn = (spanType) => objectTypeOrFetchFn(spanType);
40877
+ this.fetchFn = async (filters) => (await objectTypeOrFetchFn(filters.filters.spanType)).filter(
40878
+ (span) => matchesSpanFilters(span, filters)
40879
+ );
39526
40880
  } else {
39527
40881
  const objectType = objectTypeOrFetchFn;
39528
- this.fetchFn = async (spanType, includeScorers) => {
40882
+ this.fetchFn = async (filters, includeScorers) => {
39529
40883
  const state = await getState();
39530
40884
  const fetcher = new SpanFetcher(
39531
40885
  objectType,
39532
40886
  objectId,
39533
40887
  rootSpanId,
39534
40888
  state,
39535
- spanType,
40889
+ void 0,
39536
40890
  includeScorers,
39537
- brainstoreRealtime
40891
+ brainstoreRealtime,
40892
+ filters.filters
40893
+ );
40894
+ let spans = (await fetcher.fetchedData()).map(
40895
+ (row) => ({ ...row })
39538
40896
  );
39539
- const rows = await fetcher.fetchedData();
39540
- return rows.map((row) => ({
39541
- input: row.input,
39542
- output: row.output,
39543
- expected: row.expected,
39544
- error: row.error,
39545
- scores: row.scores,
39546
- metrics: row.metrics,
39547
- metadata: row.metadata,
39548
- span_id: row.span_id,
39549
- span_parents: row.span_parents,
39550
- is_root: row.is_root,
39551
- span_attributes: row.span_attributes,
39552
- id: row.id,
39553
- _xact_id: row._xact_id,
39554
- _pagination_key: row._pagination_key,
39555
- root_span_id: row.root_span_id,
39556
- created: row.created,
39557
- tags: row.tags
39558
- }));
40897
+ if (filters.filters.metadata !== void 0) {
40898
+ spans = spans.filter((span) => matchesSpanFilters(span, filters));
40899
+ }
40900
+ return spans;
39559
40901
  };
39560
40902
  }
39561
40903
  }
39562
40904
  async getSpans({
39563
- spanType,
40905
+ spanType: requestedSpanType,
40906
+ filters,
39564
40907
  includeScorers = false
39565
40908
  } = {}) {
40909
+ const normalizedFilters = normalizeSpanFilters(filters, requestedSpanType);
40910
+ const spanType = normalizedFilters.filters.spanType;
40911
+ const hasAdvancedFilters = Object.keys(normalizedFilters.filters).some(
40912
+ (field) => field !== "spanType"
40913
+ );
40914
+ if (spanType?.length === 0) {
40915
+ return [];
40916
+ }
39566
40917
  if (includeScorers) {
39567
- return this.fetchFn(spanType, true);
40918
+ return this.fetchFn(normalizedFilters, true);
39568
40919
  }
39569
40920
  if (this.allFetched) {
39570
- return this.getFromCache(spanType);
40921
+ const spans = this.getFromCache(spanType);
40922
+ return hasAdvancedFilters ? spans.filter((span) => matchesSpanFilters(span, normalizedFilters)) : spans;
39571
40923
  }
39572
- if (!spanType || spanType.length === 0) {
40924
+ if (hasAdvancedFilters && spanType && spanType.every((type) => this.spanCache.has(type))) {
40925
+ return this.getFromCache(spanType).filter(
40926
+ (span) => matchesSpanFilters(span, normalizedFilters)
40927
+ );
40928
+ }
40929
+ if (hasAdvancedFilters) {
40930
+ return this.fetchFn(normalizedFilters, false);
40931
+ }
40932
+ if (!spanType) {
40933
+ this.spanCache.clear();
39573
40934
  await this.fetchSpans(void 0);
39574
- this.allFetched = true;
40935
+ if (this.spanCache.size > 0) {
40936
+ this.allFetched = true;
40937
+ }
39575
40938
  return this.getFromCache(void 0);
39576
40939
  }
39577
- const missingTypes = spanType.filter((t) => !this.spanCache.has(t));
39578
- if (missingTypes.length === 0) {
39579
- return this.getFromCache(spanType);
40940
+ const missingTypes = spanType.filter((type) => !this.spanCache.has(type));
40941
+ if (missingTypes.length > 0) {
40942
+ await this.fetchSpans(missingTypes);
39580
40943
  }
39581
- await this.fetchSpans(missingTypes);
39582
40944
  return this.getFromCache(spanType);
39583
40945
  }
39584
40946
  async fetchSpans(spanType) {
39585
- const spans = await this.fetchFn(spanType, false);
40947
+ const spans = await this.fetchFn(
40948
+ normalizeSpanFilters(spanType ? { spanType } : void 0),
40949
+ false
40950
+ );
39586
40951
  for (const span of spans) {
39587
40952
  const type = span.span_attributes?.type ?? "";
39588
40953
  const existing = this.spanCache.get(type) ?? [];
@@ -39662,34 +41027,20 @@ var LocalTrace = class {
39662
41027
  */
39663
41028
  async getSpans({
39664
41029
  spanType,
41030
+ filters,
39665
41031
  includeScorers = false
39666
41032
  } = {}) {
41033
+ const normalizedFilters = normalizeSpanFilters(filters, spanType);
39667
41034
  const cachedSpans = this.state.spanCache.getByRootSpanId(this.rootSpanId);
39668
41035
  if (cachedSpans && cachedSpans.length > 0) {
39669
- let spans = includeScorers ? cachedSpans : cachedSpans.filter(
39670
- (span) => span.span_attributes?.purpose !== "scorer"
39671
- );
39672
- if (spanType && spanType.length > 0) {
39673
- spans = spans.filter(
39674
- (span) => spanType.includes(span.span_attributes?.type ?? "")
39675
- );
39676
- }
39677
- return spans.map((span) => ({
39678
- input: span.input,
39679
- output: span.output,
39680
- expected: span.expected,
39681
- error: span.error,
39682
- scores: span.scores,
39683
- metrics: span.metrics,
39684
- metadata: span.metadata,
39685
- span_id: span.span_id,
39686
- span_parents: span.span_parents,
39687
- is_root: span.is_root,
39688
- span_attributes: span.span_attributes,
39689
- tags: span.tags
39690
- }));
39691
- }
39692
- return this.cachedFetcher.getSpans({ spanType, includeScorers });
41036
+ return cachedSpans.filter(
41037
+ (span) => (includeScorers || span.span_attributes?.purpose !== "scorer") && matchesSpanFilters({ ...span }, normalizedFilters)
41038
+ ).map((span) => ({ ...span }));
41039
+ }
41040
+ return this.cachedFetcher.getSpans({
41041
+ filters: normalizedFilters.filters,
41042
+ includeScorers
41043
+ });
39693
41044
  }
39694
41045
  /**
39695
41046
  * Get the thread (preprocessed messages) for this trace.
@@ -40109,7 +41460,7 @@ async function Eval(name, evaluator, reporterOrOpts) {
40109
41460
  data,
40110
41461
  { disabled: Boolean(options.parent || options.noSendLogs) }
40111
41462
  );
40112
- if (experiment && typeof process !== "undefined" && globalThis.BRAINTRUST_CONTEXT_MANAGER !== void 0) {
41463
+ if (experiment) {
40113
41464
  await experiment._waitForId();
40114
41465
  }
40115
41466
  if (experiment && options.onStart) {
@@ -40415,6 +41766,10 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
40415
41766
  } : void 0;
40416
41767
  const parsedDatumOrigin = ObjectReference.safeParse(datum.origin);
40417
41768
  const origin = inlineDatasetOrigin ?? (parsedDatumOrigin?.success ? parsedDatumOrigin.data : void 0);
41769
+ const upsertId = datum.upsert_id && trialIndex > 0 ? uuidv5(
41770
+ `braintrust:eval:${datum.upsert_id}:trial:${trialIndex}`,
41771
+ uuidv5.URL
41772
+ ) : datum.upsert_id;
40418
41773
  const baseEvent = {
40419
41774
  name: "eval",
40420
41775
  spanAttributes: {
@@ -40425,7 +41780,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
40425
41780
  expected: "expected" in datum ? datum.expected : void 0,
40426
41781
  tags: datum.tags,
40427
41782
  origin,
40428
- ...datum.upsert_id ? { id: datum.upsert_id } : {}
41783
+ ...upsertId ? { id: upsertId } : {}
40429
41784
  }
40430
41785
  };
40431
41786
  const callback = async (rootSpan) => {