braintrust 3.31.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 (62) hide show
  1. package/README.md +0 -43
  2. package/dev/dist/index.d.mts +767 -0
  3. package/dev/dist/index.d.ts +767 -0
  4. package/dev/dist/index.js +3115 -908
  5. package/dev/dist/index.mjs +2466 -259
  6. package/dist/apply-auto-instrumentation.js +325 -221
  7. package/dist/apply-auto-instrumentation.mjs +110 -6
  8. package/dist/auto-instrumentations/bundler/esbuild.cjs +182 -7
  9. package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
  10. package/dist/auto-instrumentations/bundler/next.cjs +182 -7
  11. package/dist/auto-instrumentations/bundler/next.mjs +3 -3
  12. package/dist/auto-instrumentations/bundler/rollup.cjs +182 -7
  13. package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
  14. package/dist/auto-instrumentations/bundler/vite.cjs +182 -7
  15. package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
  16. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +182 -7
  17. package/dist/auto-instrumentations/bundler/webpack.cjs +182 -7
  18. package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
  19. package/dist/auto-instrumentations/{chunk-U64OYU4Q.mjs → chunk-T2DMPWFI.mjs} +113 -6
  20. package/dist/auto-instrumentations/{chunk-LW4HDHXT.mjs → chunk-UHJ2DNYJ.mjs} +74 -2
  21. package/dist/auto-instrumentations/{chunk-OXINGIEZ.mjs → chunk-W5QNG3PV.mjs} +1 -1
  22. package/dist/auto-instrumentations/hook.mjs +209 -9
  23. package/dist/auto-instrumentations/index.cjs +115 -6
  24. package/dist/auto-instrumentations/index.d.mts +5 -1
  25. package/dist/auto-instrumentations/index.d.ts +5 -1
  26. package/dist/auto-instrumentations/index.mjs +5 -1
  27. package/dist/browser.d.mts +2324 -342
  28. package/dist/browser.d.ts +2324 -342
  29. package/dist/browser.js +3573 -626
  30. package/dist/browser.mjs +3573 -626
  31. package/dist/chunk-7P6ASYW6.mjs +9 -0
  32. package/dist/{chunk-V32LW47Z.js → chunk-AXJTOUOC.js} +3022 -1131
  33. package/dist/{chunk-4AQGZS6X.js → chunk-G3VHOHRC.js} +85 -11
  34. package/dist/chunk-MLKGABMK.js +9 -0
  35. package/dist/{chunk-AJT4FR25.mjs → chunk-MZLBAFVJ.mjs} +2051 -160
  36. package/dist/{chunk-CE3BLB2L.mjs → chunk-TZVZN2JJ.mjs} +84 -10
  37. package/dist/cli.js +2614 -297
  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 +3573 -626
  45. package/dist/edge-light.mjs +3573 -626
  46. package/dist/index.d.mts +2324 -342
  47. package/dist/index.d.ts +2324 -342
  48. package/dist/index.js +1959 -969
  49. package/dist/index.mjs +1450 -460
  50. package/dist/instrumentation/index.d.mts +439 -245
  51. package/dist/instrumentation/index.d.ts +439 -245
  52. package/dist/instrumentation/index.js +2550 -258
  53. package/dist/instrumentation/index.mjs +2550 -258
  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 +3573 -626
  59. package/dist/workerd.mjs +3573 -626
  60. package/package.json +10 -2
  61. package/util/dist/index.d.mts +326 -0
  62. package/util/dist/index.d.ts +326 -0
@@ -3115,6 +3115,14 @@ var ChatCompletionContentPartImageWithTitle = z6.object({
3115
3115
  ttl: z6.enum(["5m", "1h"]).optional()
3116
3116
  }).optional()
3117
3117
  });
3118
+ var ChatCompletionContentPartInputAudioWithTitle = z6.object({
3119
+ input_audio: z6.object({ data: z6.string(), format: z6.enum(["wav", "mp3"]) }),
3120
+ type: z6.literal("input_audio"),
3121
+ cache_control: z6.object({
3122
+ type: z6.literal("ephemeral"),
3123
+ ttl: z6.enum(["5m", "1h"]).optional()
3124
+ }).optional()
3125
+ });
3118
3126
  var ChatCompletionContentPartFileFile = z6.object({ file_data: z6.string(), filename: z6.string(), file_id: z6.string() }).partial();
3119
3127
  var ChatCompletionContentPartFileWithTitle = z6.object({
3120
3128
  file: ChatCompletionContentPartFileFile,
@@ -3127,6 +3135,7 @@ var ChatCompletionContentPartFileWithTitle = z6.object({
3127
3135
  var ChatCompletionContentPart = z6.union([
3128
3136
  ChatCompletionContentPartTextWithTitle,
3129
3137
  ChatCompletionContentPartImageWithTitle,
3138
+ ChatCompletionContentPartInputAudioWithTitle,
3130
3139
  ChatCompletionContentPartFileWithTitle
3131
3140
  ]);
3132
3141
  var ChatCompletionContentPartText = z6.object({
@@ -5954,6 +5963,7 @@ var INSTRUMENTATION_NAMES = {
5954
5963
  GENKIT: "genkit",
5955
5964
  GITHUB_COPILOT: "github-copilot",
5956
5965
  GOOGLE_ADK: "google-adk",
5966
+ GOOGLE_GENERATIVE_AI: "google-generative-ai",
5957
5967
  GOOGLE_GENAI: "google-genai",
5958
5968
  GROQ: "groq",
5959
5969
  HUGGINGFACE: "huggingface",
@@ -5961,6 +5971,7 @@ var INSTRUMENTATION_NAMES = {
5961
5971
  LANGSMITH: "langsmith",
5962
5972
  MASTRA: "mastra",
5963
5973
  MISTRAL: "mistral",
5974
+ LANGGRAPH_SDK: "langgraph-sdk",
5964
5975
  OLLAMA: "ollama",
5965
5976
  OPENAI: "openai",
5966
5977
  OPENAI_AGENTS: "openai-agents",
@@ -5969,12 +5980,13 @@ var INSTRUMENTATION_NAMES = {
5969
5980
  OPENROUTER_AGENT: "openrouter-agent",
5970
5981
  PI_CODING_AGENT: "pi-coding-agent",
5971
5982
  STRANDS_AGENT_SDK: "strands-agent-sdk",
5972
- VOYAGEAI: "voyageai"
5983
+ VOYAGEAI: "voyageai",
5984
+ ELEVENLABS: "elevenlabs"
5973
5985
  };
5974
5986
  var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
5975
5987
  "braintrust.spanInstrumentationName"
5976
5988
  );
5977
- var SDK_VERSION = true ? "3.31.0" : "0.0.0";
5989
+ var SDK_VERSION = true ? "3.33.0" : "0.0.0";
5978
5990
  function withSpanInstrumentationName(args, instrumentationName) {
5979
5991
  return {
5980
5992
  ...args,
@@ -9215,6 +9227,38 @@ function getSpanParentObjectAndPropagatedState(options) {
9215
9227
  function getSpanParentObject(options) {
9216
9228
  return getSpanParentObjectAndPropagatedState(options).parentObject;
9217
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
+ }
9218
9262
  function currentBraintrustParent(state) {
9219
9263
  const resolvedState = state ?? _globalState;
9220
9264
  const experiment = currentExperiment({ state: resolvedState });
@@ -10595,10 +10639,16 @@ var SpanImpl = class _SpanImpl {
10595
10639
  inject(carrier) {
10596
10640
  const resolvedCarrier = carrier ?? {};
10597
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
+ }
10598
10648
  _injectIntoCarrier(resolvedCarrier, {
10599
10649
  traceId: this._rootSpanId,
10600
10650
  spanId: this._spanId,
10601
- braintrustParent: this._getOtelParent() ?? this._propagatedState?.braintrustParent,
10651
+ braintrustParent,
10602
10652
  propagatedState: this._propagatedState
10603
10653
  });
10604
10654
  } catch (e) {
@@ -11148,6 +11198,16 @@ function renderMessageImpl(render, message, variables) {
11148
11198
  }
11149
11199
  }
11150
11200
  ];
11201
+ case "input_audio":
11202
+ return [
11203
+ {
11204
+ ...c,
11205
+ input_audio: {
11206
+ ...c.input_audio,
11207
+ data: render(c.input_audio.data)
11208
+ }
11209
+ }
11210
+ ];
11151
11211
  case "file":
11152
11212
  return [
11153
11213
  {
@@ -12895,6 +12955,18 @@ function defineChannels(pkg, channels, options) {
12895
12955
  var openAIChannels = defineChannels(
12896
12956
  "openai",
12897
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
+ }),
12898
12970
  filesCreateTraced: channel({
12899
12971
  channelName: "files.create-traced",
12900
12972
  kind: "async"
@@ -13263,6 +13335,23 @@ function getCachedMetricFromHeaders(headers) {
13263
13335
  return parseCachedHeader(headers.get(LEGACY_CACHED_HEADER));
13264
13336
  }
13265
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
+
13266
13355
  // src/instrumentation/plugins/openai-batch-instrumentation.ts
13267
13356
  var SUPPORTED_ENDPOINTS = /* @__PURE__ */ new Set(["/v1/chat/completions", "/v1/responses"]);
13268
13357
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
@@ -13303,21 +13392,6 @@ async function exportParent(parent) {
13303
13392
  }
13304
13393
  return void 0;
13305
13394
  }
13306
- async function deterministicDigest(namespace, ...parts) {
13307
- const encoded = new TextEncoder().encode(
13308
- [namespace, ...parts].map((part) => `${part.length}:${part}`).join("\0")
13309
- );
13310
- return new Uint8Array(
13311
- await globalThis.crypto.subtle.digest("SHA-256", encoded)
13312
- );
13313
- }
13314
- function digestHex(bytes, length) {
13315
- return Array.from(bytes.slice(0, length)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
13316
- }
13317
- function digestUuid(bytes) {
13318
- const hex = digestHex(bytes, 16);
13319
- return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
13320
- }
13321
13395
  async function batchSpanIds(inputFileId) {
13322
13396
  const [row, span, root] = await Promise.all([
13323
13397
  deterministicDigest("openai:batch:row", inputFileId),
@@ -13808,6 +13882,628 @@ var interceptOpenAIBatchTraceComplete = (target, thisArg, args) => Promise.resol
13808
13882
  return result;
13809
13883
  });
13810
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
+
13811
14507
  // src/instrumentation/plugins/openai-plugin.ts
13812
14508
  var OpenAIPlugin = class extends BasePlugin {
13813
14509
  constructor() {
@@ -13815,6 +14511,13 @@ var OpenAIPlugin = class extends BasePlugin {
13815
14511
  }
13816
14512
  onEnable() {
13817
14513
  this.unsubscribers.push(
14514
+ openAIChannels.agentsTraceStart.intercept(
14515
+ interceptOpenAIAgentsTraceStart
14516
+ ),
14517
+ openAIChannels.agentsTraceCapture.intercept(
14518
+ interceptOpenAIAgentsTraceCapture
14519
+ ),
14520
+ openAIChannels.agentsTraceFail.intercept(interceptOpenAIAgentsTraceFail),
13818
14521
  openAIChannels.filesCreateTraced.intercept(
13819
14522
  interceptOpenAIFilesCreateTraced
13820
14523
  ),
@@ -14375,7 +15078,7 @@ async function* patchCodexEventStream(events, state) {
14375
15078
  try {
14376
15079
  await handleCodexEvent(state, event);
14377
15080
  } catch (error) {
14378
- logInstrumentationError("OpenAI Codex stream event", error);
15081
+ logInstrumentationError2("OpenAI Codex stream event", error);
14379
15082
  }
14380
15083
  yield event;
14381
15084
  }
@@ -14875,10 +15578,10 @@ function safeLog(span, event) {
14875
15578
  try {
14876
15579
  span.log(event);
14877
15580
  } catch (error) {
14878
- logInstrumentationError("OpenAI Codex span log", error);
15581
+ logInstrumentationError2("OpenAI Codex span log", error);
14879
15582
  }
14880
15583
  }
14881
- function logInstrumentationError(context, error) {
15584
+ function logInstrumentationError2(context, error) {
14882
15585
  debugLogger.error(`Error processing ${context}:`, error);
14883
15586
  }
14884
15587
 
@@ -16260,27 +16963,8 @@ function continuationParentFromCreateSessionParams(params) {
16260
16963
  }
16261
16964
  return context.parent;
16262
16965
  }
16263
- function exportSpanSynchronously(span) {
16264
- const parentInfo = span.getParentInfo();
16265
- if (!parentInfo) {
16266
- return void 0;
16267
- }
16268
- const objectId = parentInfo.objectId.getSync().value;
16269
- if (!objectId && !parentInfo.computeObjectMetadataArgs) {
16270
- return void 0;
16271
- }
16272
- return new SpanComponentsV4({
16273
- object_type: parentInfo.objectType,
16274
- ...objectId ? { object_id: objectId } : {
16275
- compute_object_metadata_args: parentInfo.computeObjectMetadataArgs ?? {}
16276
- },
16277
- row_id: span.id,
16278
- root_span_id: span.rootSpanId,
16279
- span_id: span.spanId
16280
- }).toStr();
16281
- }
16282
16966
  function exportedParent(parent) {
16283
- return typeof parent === "string" ? parent : exportSpanSynchronously(parent);
16967
+ return typeof parent === "string" ? parent : _internalExportParentSynchronously(parent);
16284
16968
  }
16285
16969
  function addSerializedContext(args) {
16286
16970
  if (!isObject(args.continuation) || args.sessionId === void 0) {
@@ -17037,16 +17721,16 @@ function braintrustAISDKTelemetry() {
17037
17721
  if (!toolCallId || !state) {
17038
17722
  return;
17039
17723
  }
17040
- const toolOutput = event.toolOutput;
17724
+ const toolOutput2 = event.toolOutput;
17041
17725
  const workflowToolError = event.success === false && "error" in event ? event.error : void 0;
17042
- if (toolOutput?.type === "tool-error" || workflowToolError !== void 0) {
17043
- const error = toolOutput?.error ?? workflowToolError;
17726
+ if (toolOutput2?.type === "tool-error" || workflowToolError !== void 0) {
17727
+ const error = toolOutput2?.error ?? workflowToolError;
17044
17728
  state.span.log({
17045
17729
  error: error instanceof Error ? error.message : String(error),
17046
17730
  metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
17047
17731
  });
17048
17732
  } else {
17049
- const output = toolOutput && "output" in toolOutput ? toolOutput.output : event.output;
17733
+ const output = toolOutput2 && "output" in toolOutput2 ? toolOutput2.output : event.output;
17050
17734
  state.span.log({
17051
17735
  ...shouldRecordOutputs(event) ? { output } : {},
17052
17736
  metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
@@ -19505,9 +20189,9 @@ function patchAISDKStreamingResult(args) {
19505
20189
  }
19506
20190
  finalize({ metrics, output });
19507
20191
  } catch (error) {
19508
- const loggedError = toLoggedError(error);
20192
+ const loggedError2 = toLoggedError(error);
19509
20193
  try {
19510
- span.log({ error: loggedError });
20194
+ span.log({ error: loggedError2 });
19511
20195
  } catch (loggingError) {
19512
20196
  debugLogger.error(
19513
20197
  "Error logging AI SDK streaming failure:",
@@ -19515,7 +20199,7 @@ function patchAISDKStreamingResult(args) {
19515
20199
  );
19516
20200
  }
19517
20201
  finalize({
19518
- error: error instanceof Error ? error : new Error(String(loggedError))
20202
+ error: error instanceof Error ? error : new Error(String(loggedError2))
19519
20203
  });
19520
20204
  }
19521
20205
  };
@@ -19628,9 +20312,9 @@ function patchAISDKStreamingResult(args) {
19628
20312
  }
19629
20313
  controller.enqueue(value);
19630
20314
  } catch (error) {
19631
- const loggedError = toLoggedError(error);
20315
+ const loggedError2 = toLoggedError(error);
19632
20316
  try {
19633
- span.log({ error: loggedError });
20317
+ span.log({ error: loggedError2 });
19634
20318
  } catch (loggingError) {
19635
20319
  debugLogger.error(
19636
20320
  "Error logging AI SDK base stream failure:",
@@ -19638,7 +20322,7 @@ function patchAISDKStreamingResult(args) {
19638
20322
  );
19639
20323
  }
19640
20324
  finalize({
19641
- error: error instanceof Error ? error : new Error(String(loggedError))
20325
+ error: error instanceof Error ? error : new Error(String(loggedError2))
19642
20326
  });
19643
20327
  controller.error(error);
19644
20328
  }
@@ -22532,7 +23216,7 @@ function wrapSendOptionsCallbacks(options, state) {
22532
23216
  try {
22533
23217
  await handleInteractionUpdate(state, args.update);
22534
23218
  } catch (error) {
22535
- logInstrumentationError2("Cursor SDK onDelta", error);
23219
+ logInstrumentationError3("Cursor SDK onDelta", error);
22536
23220
  }
22537
23221
  if (originalOnDelta) {
22538
23222
  return originalOnDelta(args);
@@ -22542,7 +23226,7 @@ function wrapSendOptionsCallbacks(options, state) {
22542
23226
  try {
22543
23227
  handleStepUpdate(state, args.step);
22544
23228
  } catch (error) {
22545
- logInstrumentationError2("Cursor SDK onStep", error);
23229
+ logInstrumentationError3("Cursor SDK onStep", error);
22546
23230
  }
22547
23231
  if (originalOnStep) {
22548
23232
  return originalOnStep(args);
@@ -22624,7 +23308,7 @@ async function* patchCursorStream(stream, state) {
22624
23308
  try {
22625
23309
  await handleStreamMessage2(state, message);
22626
23310
  } catch (error) {
22627
- logInstrumentationError2("Cursor SDK stream", error);
23311
+ logInstrumentationError3("Cursor SDK stream", error);
22628
23312
  }
22629
23313
  yield message;
22630
23314
  }
@@ -22688,7 +23372,7 @@ async function handleToolUpdate(state, update) {
22688
23372
  if (!state.activeToolSpans.has(callId)) {
22689
23373
  state.activeToolSpans.set(
22690
23374
  callId,
22691
- await startToolSpan(state, {
23375
+ await startToolSpan2(state, {
22692
23376
  args,
22693
23377
  callId,
22694
23378
  name,
@@ -22699,7 +23383,7 @@ async function handleToolUpdate(state, update) {
22699
23383
  }
22700
23384
  return;
22701
23385
  }
22702
- const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan(state, {
23386
+ const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan2(state, {
22703
23387
  args,
22704
23388
  callId,
22705
23389
  name,
@@ -22736,7 +23420,7 @@ async function handleStreamMessage2(state, message) {
22736
23420
  } else if (block?.type === "tool_use" && block.id) {
22737
23421
  state.activeToolSpans.set(
22738
23422
  block.id,
22739
- await startToolSpan(state, {
23423
+ await startToolSpan2(state, {
22740
23424
  args: block.input,
22741
23425
  callId: block.id,
22742
23426
  name: block.name,
@@ -22771,7 +23455,7 @@ async function handleToolMessage(state, message) {
22771
23455
  if (!state.activeToolSpans.has(callId)) {
22772
23456
  state.activeToolSpans.set(
22773
23457
  callId,
22774
- await startToolSpan(state, {
23458
+ await startToolSpan2(state, {
22775
23459
  args: message.args,
22776
23460
  callId,
22777
23461
  name: message.name,
@@ -22782,7 +23466,7 @@ async function handleToolMessage(state, message) {
22782
23466
  }
22783
23467
  return;
22784
23468
  }
22785
- const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan(state, {
23469
+ const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan2(state, {
22786
23470
  args: message.args,
22787
23471
  callId,
22788
23472
  name: message.name,
@@ -22809,7 +23493,7 @@ async function handleConversation(state, turns) {
22809
23493
  const command = turn.turn?.shellCommand?.command;
22810
23494
  if (command) {
22811
23495
  const callId = `shell:${state.activeToolSpans.size}:${command}`;
22812
- const toolState = await startToolSpan(state, {
23496
+ const toolState = await startToolSpan2(state, {
22813
23497
  args: turn.turn?.shellCommand,
22814
23498
  callId,
22815
23499
  name: "shell",
@@ -22833,7 +23517,7 @@ async function handleConversationStep(state, step) {
22833
23517
  }
22834
23518
  const toolCall = step.message;
22835
23519
  const callId = typeof toolCall?.callId === "string" ? toolCall.callId : `conversation-tool:${state.activeToolSpans.size}`;
22836
- const toolState = await startToolSpan(state, {
23520
+ const toolState = await startToolSpan2(state, {
22837
23521
  args: extractToolArgs(toolCall),
22838
23522
  callId,
22839
23523
  name: extractToolName(toolCall),
@@ -22864,7 +23548,7 @@ function handleStepUpdate(state, step) {
22864
23548
  state.stepText.push(step.message.text);
22865
23549
  }
22866
23550
  }
22867
- async function startToolSpan(state, args) {
23551
+ async function startToolSpan2(state, args) {
22868
23552
  const name = args.name || "unknown";
22869
23553
  const metadata = {
22870
23554
  "cursor_sdk.tool.status": args.status,
@@ -23151,10 +23835,10 @@ function safeLog2(span, event) {
23151
23835
  try {
23152
23836
  span.log(event);
23153
23837
  } catch (error) {
23154
- logInstrumentationError2("Cursor SDK span log", error);
23838
+ logInstrumentationError3("Cursor SDK span log", error);
23155
23839
  }
23156
23840
  }
23157
- function logInstrumentationError2(context, error) {
23841
+ function logInstrumentationError3(context, error) {
23158
23842
  debugLogger.error(`Error processing ${context}:`, error);
23159
23843
  }
23160
23844
  function cleanMetrics2(metrics) {
@@ -23640,6 +24324,342 @@ var OpenAIAgentsPlugin = class extends BasePlugin {
23640
24324
  }
23641
24325
  };
23642
24326
 
24327
+ // src/instrumentation/plugins/google-generative-ai-channels.ts
24328
+ var googleGenerativeAIChannels = defineChannels(
24329
+ "@google/generative-ai",
24330
+ {
24331
+ generateContent: channel({ channelName: "GenerativeModel.generateContent", kind: "async" }),
24332
+ generateContentStream: channel({ channelName: "GenerativeModel.generateContentStream", kind: "async" }),
24333
+ embedContent: channel({ channelName: "GenerativeModel.embedContent", kind: "async" }),
24334
+ batchEmbedContents: channel({ channelName: "GenerativeModel.batchEmbedContents", kind: "async" }),
24335
+ sendMessage: channel({ channelName: "ChatSession.sendMessage", kind: "async" }),
24336
+ sendMessageStream: channel({ channelName: "ChatSession.sendMessageStream", kind: "async" })
24337
+ },
24338
+ { instrumentationName: INSTRUMENTATION_NAMES.GOOGLE_GENERATIVE_AI }
24339
+ );
24340
+
24341
+ // src/instrumentation/plugins/google-generative-ai-plugin.ts
24342
+ var GENERATION_CONFIG_KEYS = [
24343
+ "temperature",
24344
+ "topP",
24345
+ "topK",
24346
+ "candidateCount",
24347
+ "maxOutputTokens",
24348
+ "stopSequences",
24349
+ "responseMimeType",
24350
+ "responseSchema",
24351
+ "presencePenalty",
24352
+ "frequencyPenalty",
24353
+ "responseLogprobs",
24354
+ "logprobs",
24355
+ "thinkingConfig"
24356
+ ];
24357
+ var GoogleGenerativeAIPlugin = class extends BasePlugin {
24358
+ onEnable() {
24359
+ this.unsubscribers.push(
24360
+ interceptCall(
24361
+ googleGenerativeAIChannels.generateContent,
24362
+ "generateContent"
24363
+ ),
24364
+ interceptCall(
24365
+ googleGenerativeAIChannels.generateContentStream,
24366
+ "generateContentStream"
24367
+ ),
24368
+ interceptCall(googleGenerativeAIChannels.sendMessage, "sendMessage"),
24369
+ interceptCall(
24370
+ googleGenerativeAIChannels.sendMessageStream,
24371
+ "sendMessageStream"
24372
+ ),
24373
+ interceptCall(googleGenerativeAIChannels.embedContent, "embedContent"),
24374
+ interceptCall(
24375
+ googleGenerativeAIChannels.batchEmbedContents,
24376
+ "batchEmbedContents"
24377
+ )
24378
+ );
24379
+ }
24380
+ onDisable() {
24381
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
24382
+ }
24383
+ };
24384
+ function interceptCall(channel2, operation) {
24385
+ return channel2.intercept((target, thisArg, args) => {
24386
+ const invokeTarget = () => Reflect.apply(target, thisArg, args);
24387
+ if (isAutoInstrumentationSuppressed()) return invokeTarget();
24388
+ const self = thisArg;
24389
+ const chat = operation.startsWith("sendMessage");
24390
+ const embedding = operation === "embedContent" || operation === "batchEmbedContents";
24391
+ const start = getCurrentUnixTimestamp();
24392
+ let span;
24393
+ try {
24394
+ span = startSpan(
24395
+ withSpanInstrumentationName(
24396
+ {
24397
+ name: embedding ? operation === "embedContent" ? "embed_content" : "batch_embed_contents" : "generate_content",
24398
+ spanAttributes: { type: "llm" /* LLM */ },
24399
+ event: extractInput(self, args[0], operation)
24400
+ },
24401
+ INSTRUMENTATION_NAMES.GOOGLE_GENERATIVE_AI
24402
+ )
24403
+ );
24404
+ } catch (error) {
24405
+ debugLogger.error("Error starting Google Generative AI span:", error);
24406
+ return invokeTarget();
24407
+ }
24408
+ let ended = false;
24409
+ const finish = (log2) => {
24410
+ if (ended) return;
24411
+ ended = true;
24412
+ try {
24413
+ log2();
24414
+ } catch (error) {
24415
+ debugLogger.error("Error logging Google Generative AI span:", error);
24416
+ }
24417
+ try {
24418
+ span.end();
24419
+ } catch (error) {
24420
+ debugLogger.error("Error ending Google Generative AI span:", error);
24421
+ }
24422
+ };
24423
+ if (chat) {
24424
+ try {
24425
+ void self._sendPromise.then(
24426
+ () => {
24427
+ try {
24428
+ span.log(extractInput(self, args[0], operation));
24429
+ } catch (error) {
24430
+ debugLogger.error("Error capturing Google chat history:", error);
24431
+ }
24432
+ },
24433
+ () => {
24434
+ }
24435
+ );
24436
+ } catch (error) {
24437
+ debugLogger.error("Error observing Google chat history:", error);
24438
+ }
24439
+ }
24440
+ let result;
24441
+ try {
24442
+ result = withCurrent(
24443
+ span,
24444
+ () => runWithAutoInstrumentationSuppressed(invokeTarget)
24445
+ );
24446
+ } catch (error) {
24447
+ finish(() => span.log({ error }));
24448
+ throw error;
24449
+ }
24450
+ void Promise.resolve(result).then(
24451
+ (value) => {
24452
+ try {
24453
+ if ("stream" in value) {
24454
+ let firstToken = false;
24455
+ const partial = { candidates: [] };
24456
+ const candidates = /* @__PURE__ */ new Map();
24457
+ patchStreamIfNeeded(value.stream, {
24458
+ aroundNext: (callback) => withCurrent(span, callback),
24459
+ onChunk: (chunk) => {
24460
+ for (const candidate of chunk.candidates ?? []) {
24461
+ const index = candidate.index ?? 0;
24462
+ const previous = candidates.get(index);
24463
+ const parts = [...previous?.content?.parts ?? []];
24464
+ for (const part of candidate.content?.parts ?? []) {
24465
+ const last = parts[parts.length - 1];
24466
+ if (part.text !== void 0 && last?.text !== void 0) {
24467
+ parts[parts.length - 1] = {
24468
+ ...last,
24469
+ text: last.text + part.text
24470
+ };
24471
+ } else parts.push(part);
24472
+ }
24473
+ candidates.set(index, {
24474
+ ...previous,
24475
+ ...candidate,
24476
+ content: {
24477
+ role: candidate.content?.role ?? previous?.content?.role ?? "model",
24478
+ parts
24479
+ }
24480
+ });
24481
+ }
24482
+ partial.candidates = Array.from(candidates.values());
24483
+ if (chunk.usageMetadata)
24484
+ partial.usageMetadata = chunk.usageMetadata;
24485
+ if (!firstToken && chunk.candidates?.some(
24486
+ (candidate) => candidate.content?.parts.some(
24487
+ (part) => part.text !== void 0 ? part.text.length > 0 : Object.keys(part).length > 0
24488
+ )
24489
+ )) {
24490
+ firstToken = true;
24491
+ span.log({
24492
+ metrics: {
24493
+ time_to_first_token: getCurrentUnixTimestamp() - start
24494
+ }
24495
+ });
24496
+ }
24497
+ },
24498
+ onComplete: () => {
24499
+ },
24500
+ onError: (error) => finish(() => {
24501
+ logResponse(span, partial);
24502
+ span.log({ error });
24503
+ }),
24504
+ onCancel: () => finish(() => logResponse(span, partial))
24505
+ });
24506
+ void value.response.then(
24507
+ (response) => finish(() => logResponse(span, response)),
24508
+ (error) => finish(() => {
24509
+ logResponse(span, partial);
24510
+ span.log({ error });
24511
+ })
24512
+ );
24513
+ } else if ("response" in value) {
24514
+ finish(() => logResponse(span, value.response));
24515
+ } else {
24516
+ const metrics = {};
24517
+ const promptTokens = value.usageMetadata?.promptTokenCount;
24518
+ if (typeof promptTokens === "number" && Number.isFinite(promptTokens) && promptTokens >= 0) {
24519
+ metrics.prompt_tokens = promptTokens;
24520
+ metrics.tokens = promptTokens;
24521
+ }
24522
+ for (const detail of value.usageMetadata?.promptTokenDetails ?? []) {
24523
+ if (detail.modality === "AUDIO" && typeof detail.tokenCount === "number" && Number.isFinite(detail.tokenCount) && detail.tokenCount >= 0) {
24524
+ metrics.prompt_audio_tokens = (metrics.prompt_audio_tokens ?? 0) + detail.tokenCount;
24525
+ }
24526
+ }
24527
+ finish(
24528
+ () => span.log({
24529
+ metrics,
24530
+ output: {
24531
+ count: value.embeddings?.length ?? (value.embedding ? 1 : 0)
24532
+ }
24533
+ })
24534
+ );
24535
+ }
24536
+ } catch (error) {
24537
+ debugLogger.error(
24538
+ "Error observing Google Generative AI result:",
24539
+ error
24540
+ );
24541
+ finish(() => {
24542
+ });
24543
+ }
24544
+ },
24545
+ (error) => finish(() => span.log({ error }))
24546
+ );
24547
+ return result;
24548
+ });
24549
+ }
24550
+ function normalizeContent(message) {
24551
+ const parts = (typeof message === "string" ? [message] : message).map(
24552
+ (part) => typeof part === "string" ? { text: part } : part
24553
+ );
24554
+ return {
24555
+ role: parts.some((part) => part.functionResponse) ? "function" : "user",
24556
+ parts
24557
+ };
24558
+ }
24559
+ function extractInput(self, request, operation) {
24560
+ const model = self.model.replace(/^models\//, "");
24561
+ if (operation === "embedContent" || operation === "batchEmbedContents") {
24562
+ const requests = operation === "batchEmbedContents" ? request.requests : [
24563
+ typeof request === "string" || Array.isArray(request) ? { content: normalizeContent(request) } : request
24564
+ ];
24565
+ const dimensions = requests[0]?.outputDimensionality;
24566
+ return {
24567
+ input: {
24568
+ inputs: convertAttachments(requests).map((item) => ({
24569
+ content: item.content.parts.length === 1 && item.content.parts[0].text !== void 0 ? item.content.parts[0].text : item.content.parts.map((part) => {
24570
+ if (part.text !== void 0)
24571
+ return { type: "text", text: part.text };
24572
+ const mimeType = part.inlineData?.mimeType ?? part.fileData?.mimeType;
24573
+ const data = part.inlineData ? typeof part.inlineData.data === "string" ? `data:${mimeType};base64,${part.inlineData.data}` : part.inlineData.data : part.fileData?.fileUri;
24574
+ return mimeType?.startsWith("image/") ? { type: "image_url", image_url: { url: data } } : { type: "file", file: { file_data: data } };
24575
+ })
24576
+ })),
24577
+ ...dimensions !== void 0 && requests.every((item) => item.outputDimensionality === dimensions) ? { output_dimensions: dimensions } : {}
24578
+ },
24579
+ metadata: { model, provider: "google" }
24580
+ };
24581
+ }
24582
+ const chat = operation.startsWith("sendMessage");
24583
+ const config = chat ? self.params ?? {} : self;
24584
+ const params = typeof request === "string" || Array.isArray(request) ? { contents: [normalizeContent(request)] } : request;
24585
+ const system = params.systemInstruction ?? config.systemInstruction;
24586
+ const systemContent = typeof system === "string" ? { role: "system", parts: [{ text: system }] } : system && "parts" in system ? { ...system, role: "system" } : system ? { role: "system", parts: [system] } : void 0;
24587
+ const contents = [
24588
+ ...systemContent ? [systemContent] : [],
24589
+ ...chat ? self._history : [],
24590
+ ...params.contents
24591
+ ];
24592
+ const metadata = { model, provider: "google" };
24593
+ const generation = params.generationConfig ?? config.generationConfig;
24594
+ for (const key of GENERATION_CONFIG_KEYS) {
24595
+ if (generation && Object.hasOwn(generation, key))
24596
+ metadata[key] = generation[key];
24597
+ }
24598
+ for (const key of ["tools", "toolConfig", "safetySettings"]) {
24599
+ const value = params[key] ?? config[key];
24600
+ if (value !== void 0) metadata[key] = value;
24601
+ }
24602
+ const cached = params.cachedContent ?? config.cachedContent;
24603
+ if (cached)
24604
+ metadata.cachedContent = typeof cached === "string" ? cached : cached.name;
24605
+ return { input: convertAttachments({ model, contents }), metadata };
24606
+ }
24607
+ function convertAttachments(value) {
24608
+ const convert = (node) => {
24609
+ if (Array.isArray(node)) return node.map(convert);
24610
+ if (!isObject(node)) return node;
24611
+ if (isObject(node.inlineData)) {
24612
+ const { data, mimeType } = node.inlineData;
24613
+ const processed = processInputAttachments({
24614
+ type: "file",
24615
+ file: { file_data: `data:${mimeType};base64,${data}` }
24616
+ });
24617
+ if (typeof processed.file.file_data === "string")
24618
+ throw new Error("Unable to convert Google inline data");
24619
+ return {
24620
+ ...node,
24621
+ inlineData: { ...node.inlineData, data: processed.file.file_data }
24622
+ };
24623
+ }
24624
+ return Object.fromEntries(
24625
+ Object.entries(node).map(([key, item]) => [key, convert(item)])
24626
+ );
24627
+ };
24628
+ try {
24629
+ return convert(value);
24630
+ } catch (error) {
24631
+ debugLogger.error(
24632
+ "Error converting Google Generative AI attachments:",
24633
+ error
24634
+ );
24635
+ return value;
24636
+ }
24637
+ }
24638
+ function logResponse(span, response) {
24639
+ const usage = response.usageMetadata;
24640
+ const metrics = {};
24641
+ if (usage) {
24642
+ if (usage.promptTokenCount !== void 0)
24643
+ metrics.prompt_tokens = usage.promptTokenCount;
24644
+ if (usage.candidatesTokenCount !== void 0 || usage.thoughtsTokenCount !== void 0)
24645
+ metrics.completion_tokens = (usage.candidatesTokenCount ?? 0) + (usage.thoughtsTokenCount ?? 0);
24646
+ if (usage.totalTokenCount !== void 0)
24647
+ metrics.tokens = usage.totalTokenCount;
24648
+ if (usage.cachedContentTokenCount !== void 0)
24649
+ metrics.prompt_cached_tokens = usage.cachedContentTokenCount;
24650
+ if (usage.thoughtsTokenCount !== void 0)
24651
+ metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
24652
+ }
24653
+ span.log({
24654
+ output: convertAttachments({
24655
+ candidates: response.candidates,
24656
+ promptFeedback: response.promptFeedback
24657
+ }),
24658
+ metrics,
24659
+ ...response.modelVersion ? { metadata: { model: response.modelVersion } } : {}
24660
+ });
24661
+ }
24662
+
23643
24663
  // src/instrumentation/plugins/google-genai-channels.ts
23644
24664
  var googleGenAIChannels = defineChannels(
23645
24665
  "@google/genai",
@@ -23656,6 +24676,10 @@ var googleGenAIChannels = defineChannels(
23656
24676
  channelName: "models.embedContent",
23657
24677
  kind: "async"
23658
24678
  }),
24679
+ httpResponseJson: channel({
24680
+ channelName: "httpResponse.json",
24681
+ kind: "async"
24682
+ }),
23659
24683
  interactionsCreate: channel({
23660
24684
  channelName: "interactions.create",
23661
24685
  kind: "async"
@@ -23804,13 +24828,45 @@ var GoogleGenAIPlugin = class extends BasePlugin {
23804
24828
  subscribeToEmbedContentChannel() {
23805
24829
  const tracingChannel = googleGenAIChannels.embedContent.tracingChannel();
23806
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
+ );
23807
24863
  const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
23808
24864
  tracingChannel,
23809
24865
  states,
23810
24866
  (event) => {
23811
24867
  const params = event.arguments[0];
23812
24868
  const input = serializeEmbedContentInput(params);
23813
- const metadata = extractEmbedContentMetadata(params);
24869
+ const metadata = { provider: "google", model: params.model };
23814
24870
  const span = startSpan(
23815
24871
  withSpanInstrumentationName(
23816
24872
  {
@@ -23823,6 +24879,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
23823
24879
  INSTRUMENTATION_NAMES.GOOGLE_GENAI
23824
24880
  )
23825
24881
  );
24882
+ embeddingSpans.add(span);
23826
24883
  return {
23827
24884
  span,
23828
24885
  startTime: getCurrentUnixTimestamp()
@@ -23834,7 +24891,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
23834
24891
  ensureSpanState(states, event, () => {
23835
24892
  const params = event.arguments[0];
23836
24893
  const input = serializeEmbedContentInput(params);
23837
- const metadata = extractEmbedContentMetadata(params);
24894
+ const metadata = { provider: "google", model: params.model };
23838
24895
  const span = startSpan(
23839
24896
  withSpanInstrumentationName(
23840
24897
  {
@@ -23847,6 +24904,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
23847
24904
  INSTRUMENTATION_NAMES.GOOGLE_GENAI
23848
24905
  )
23849
24906
  );
24907
+ embeddingSpans.add(span);
23850
24908
  return {
23851
24909
  span,
23852
24910
  startTime: getCurrentUnixTimestamp()
@@ -23859,20 +24917,28 @@ var GoogleGenAIPlugin = class extends BasePlugin {
23859
24917
  return;
23860
24918
  }
23861
24919
  try {
23862
- const output = summarizeEmbedContentOutput(event.result);
23863
24920
  spanState.span.log({
23864
- ...output ? { output } : {},
24921
+ output: summarizeEmbedContentOutput(event.result),
23865
24922
  metrics: cleanMetrics3(
23866
24923
  extractEmbedContentMetrics(event.result, spanState.startTime)
23867
24924
  )
23868
24925
  });
23869
24926
  } finally {
24927
+ embeddingSpans.delete(spanState.span);
23870
24928
  spanState.span.end();
23871
24929
  states.delete(event);
23872
24930
  }
23873
24931
  },
23874
24932
  error: (event) => {
23875
- 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
+ }
23876
24942
  }
23877
24943
  };
23878
24944
  tracingChannel.subscribe(handlers);
@@ -24107,15 +25173,53 @@ function serializeGenerateContentInput(params) {
24107
25173
  return input;
24108
25174
  }
24109
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
+ }
24110
25182
  const input = {
24111
- model: params.model,
24112
- 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 } : {}
24113
25206
  };
24114
- const config = params.config ? tryToDict(params.config) : null;
24115
- if (config) {
24116
- 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;
24117
25222
  }
24118
- return input;
24119
25223
  }
24120
25224
  function serializeInteractionInput(params) {
24121
25225
  const input = {
@@ -24303,19 +25407,6 @@ function extractGenerateContentMetadata(params) {
24303
25407
  }
24304
25408
  return metadata;
24305
25409
  }
24306
- function extractEmbedContentMetadata(params) {
24307
- const metadata = {};
24308
- if (params.model) {
24309
- metadata.model = params.model;
24310
- }
24311
- const config = params.config ? tryToDict(params.config) : null;
24312
- if (config) {
24313
- Object.keys(config).forEach((key) => {
24314
- metadata[key] = config[key];
24315
- });
24316
- }
24317
- return metadata;
24318
- }
24319
25410
  function extractGenerateContentMetrics(response, startTime) {
24320
25411
  const metrics = {};
24321
25412
  if (startTime !== void 0) {
@@ -24335,15 +25426,23 @@ function extractEmbedContentMetrics(response, startTime) {
24335
25426
  const end = getCurrentUnixTimestamp();
24336
25427
  metrics.start = startTime;
24337
25428
  metrics.end = end;
24338
- metrics.duration = end - startTime;
24339
- }
24340
- if (response?.usageMetadata) {
24341
- populateUsageMetrics(metrics, response.usageMetadata);
24342
25429
  }
24343
25430
  const embeddingTokenCount = extractEmbedPromptTokenCount(response);
24344
25431
  if (embeddingTokenCount !== void 0) {
24345
25432
  metrics.prompt_tokens = embeddingTokenCount;
24346
- 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
+ );
24347
25446
  }
24348
25447
  return metrics;
24349
25448
  }
@@ -24382,41 +25481,25 @@ function extractEmbedPromptTokenCount(response) {
24382
25481
  if (typeof usagePromptTokens === "number" && Number.isFinite(usagePromptTokens)) {
24383
25482
  return usagePromptTokens;
24384
25483
  }
24385
- const usageTotalTokens = response.usageMetadata?.totalTokenCount;
24386
- if (typeof usageTotalTokens === "number" && Number.isFinite(usageTotalTokens)) {
24387
- return usageTotalTokens;
24388
- }
24389
25484
  const embeddings = Array.isArray(response.embeddings) ? response.embeddings : response.embedding ? [response.embedding] : [];
24390
25485
  if (embeddings.length === 0) {
24391
25486
  return void 0;
24392
25487
  }
24393
25488
  let total = 0;
24394
- let sawAny = false;
24395
25489
  for (const embedding of embeddings) {
24396
25490
  const embeddingStats = tryToDict(tryToDict(embedding)?.statistics);
24397
25491
  const tokenCount2 = embeddingStats?.tokenCount;
24398
25492
  if (typeof tokenCount2 === "number" && Number.isFinite(tokenCount2)) {
24399
25493
  total += tokenCount2;
24400
- sawAny = true;
25494
+ } else {
25495
+ return void 0;
24401
25496
  }
24402
25497
  }
24403
- return sawAny ? total : void 0;
25498
+ return total;
24404
25499
  }
24405
25500
  function summarizeEmbedContentOutput(response) {
24406
- if (!response) {
24407
- return void 0;
24408
- }
24409
- const embeddings = Array.isArray(response.embeddings) ? response.embeddings : response.embedding ? [response.embedding] : [];
24410
- if (embeddings.length === 0) {
24411
- return void 0;
24412
- }
24413
- const firstValues = embeddings[0]?.values;
24414
- if (!Array.isArray(firstValues)) {
24415
- return void 0;
24416
- }
24417
25501
  return {
24418
- embedding_count: embeddings.length,
24419
- embedding_length: firstValues.length
25502
+ count: Array.isArray(response?.embeddings) ? response.embeddings.length : response?.embedding ? 1 : 0
24420
25503
  };
24421
25504
  }
24422
25505
  function populateUsageMetrics(metrics, usage) {
@@ -25283,7 +26366,7 @@ var HuggingFaceTransformersPlugin = class extends BasePlugin {
25283
26366
  getTask(event)
25284
26367
  ),
25285
26368
  extractInput: (args, event) => ({
25286
- input: extractInput(
26369
+ input: extractInput2(
25287
26370
  getTask(event),
25288
26371
  args
25289
26372
  ),
@@ -25373,7 +26456,7 @@ function modelIdentifier(pipeline) {
25373
26456
  }
25374
26457
  return void 0;
25375
26458
  }
25376
- function extractInput(task, args) {
26459
+ function extractInput2(task, args) {
25377
26460
  switch (task) {
25378
26461
  case "feature-extraction":
25379
26462
  return args[0];
@@ -28043,6 +29126,379 @@ function aggregateMistralStreamChunks(chunks) {
28043
29126
  };
28044
29127
  }
28045
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
+
28046
29502
  // src/instrumentation/plugins/ollama-channels.ts
28047
29503
  var ollamaChannels = defineChannels(
28048
29504
  "ollama",
@@ -28252,7 +29708,7 @@ function normalizeTextAndImages(content, images) {
28252
29708
  ...unrecognizedImages.length > 0 ? { unrecognizedImages } : {}
28253
29709
  };
28254
29710
  }
28255
- function normalizeMessage(message, toolCallId, syntheticToolCallIdOffset = 0) {
29711
+ function normalizeMessage2(message, toolCallId, syntheticToolCallIdOffset = 0) {
28256
29712
  if (typeof message.role !== "string") {
28257
29713
  return void 0;
28258
29714
  }
@@ -28298,7 +29754,7 @@ function normalizeMessages(messages) {
28298
29754
  toolCallId = pendingToolCallIds.get(toolName)?.shift();
28299
29755
  }
28300
29756
  }
28301
- const normalized = normalizeMessage(
29757
+ const normalized = normalizeMessage2(
28302
29758
  ollamaMessage,
28303
29759
  toolCallId,
28304
29760
  syntheticToolCallIdOffset
@@ -28417,7 +29873,7 @@ function extractOllamaChatOutput(result, syntheticToolCallIdOffset = 0) {
28417
29873
  if (!isObject(result) || !isObject(result.message)) {
28418
29874
  return void 0;
28419
29875
  }
28420
- const message = normalizeMessage(
29876
+ const message = normalizeMessage2(
28421
29877
  result.message,
28422
29878
  void 0,
28423
29879
  syntheticToolCallIdOffset
@@ -31137,14 +32593,14 @@ function extractActionSpanMetadata(args) {
31137
32593
  const options = extractRunInNewSpanOptions(args);
31138
32594
  const labels = isObject(options?.labels) ? options.labels : void 0;
31139
32595
  const metadata = isObject(options?.metadata) ? options.metadata : void 0;
31140
- const actionType = stringValue(labels?.["genkit:metadata:subtype"]);
31141
- const name = stringValue(metadata?.name);
32596
+ const actionType = stringValue2(labels?.["genkit:metadata:subtype"]);
32597
+ const name = stringValue2(metadata?.name);
31142
32598
  if (!actionType || !name) {
31143
32599
  return void 0;
31144
32600
  }
31145
32601
  return {
31146
32602
  actionType,
31147
- key: stringValue(labels?.["genkit:key"]),
32603
+ key: stringValue2(labels?.["genkit:key"]),
31148
32604
  name
31149
32605
  };
31150
32606
  }
@@ -31254,7 +32710,7 @@ function pickNumberMetrics(values) {
31254
32710
  })
31255
32711
  );
31256
32712
  }
31257
- function stringValue(value) {
32713
+ function stringValue2(value) {
31258
32714
  return typeof value === "string" ? value : void 0;
31259
32715
  }
31260
32716
 
@@ -31939,7 +33395,7 @@ function subscribeToFlueContext(value, state) {
31939
33395
  try {
31940
33396
  unsubscribe?.();
31941
33397
  } catch (error) {
31942
- logInstrumentationError3("Flue context unsubscribe", error);
33398
+ logInstrumentationError4("Flue context unsubscribe", error);
31943
33399
  }
31944
33400
  };
31945
33401
  try {
@@ -31955,7 +33411,7 @@ function subscribeToFlueContext(value, state) {
31955
33411
  });
31956
33412
  state.contexts.add(value);
31957
33413
  } catch (error) {
31958
- logInstrumentationError3("Flue context subscription", error);
33414
+ logInstrumentationError4("Flue context subscription", error);
31959
33415
  }
31960
33416
  }
31961
33417
  function isAutoContextTerminalEvent(event, ctx) {
@@ -32011,7 +33467,7 @@ var FlueObserveBridge = class {
32011
33467
  try {
32012
33468
  this.handleEvent(event, flueContextFromUnknown(ctx));
32013
33469
  } catch (error) {
32014
- logInstrumentationError3("Flue observe", error);
33470
+ logInstrumentationError4("Flue observe", error);
32015
33471
  }
32016
33472
  }
32017
33473
  reset() {
@@ -32028,7 +33484,7 @@ var FlueObserveBridge = class {
32028
33484
  try {
32029
33485
  span = this.spanForExecutionOperation(operation, executionContext);
32030
33486
  } catch (error) {
32031
- logInstrumentationError3("Flue execution interceptor", error);
33487
+ logInstrumentationError4("Flue execution interceptor", error);
32032
33488
  }
32033
33489
  return span ? runWithCurrentSpanStore(span, next) : next();
32034
33490
  }
@@ -32234,7 +33690,7 @@ var FlueObserveBridge = class {
32234
33690
  this.runsById.delete(event.runId);
32235
33691
  }
32236
33692
  void flush().catch((error) => {
32237
- logInstrumentationError3("Flue flush", error);
33693
+ logInstrumentationError4("Flue flush", error);
32238
33694
  });
32239
33695
  }
32240
33696
  handleOperationStart(event) {
@@ -33009,17 +34465,17 @@ function safeLog3(span, event) {
33009
34465
  try {
33010
34466
  span.log(event);
33011
34467
  } catch (error) {
33012
- logInstrumentationError3("Flue span log", error);
34468
+ logInstrumentationError4("Flue span log", error);
33013
34469
  }
33014
34470
  }
33015
34471
  function safeEnd(span, endTime) {
33016
34472
  try {
33017
34473
  span.end(endTime === void 0 ? void 0 : { endTime });
33018
34474
  } catch (error) {
33019
- logInstrumentationError3("Flue span end", error);
34475
+ logInstrumentationError4("Flue span end", error);
33020
34476
  }
33021
34477
  }
33022
- function logInstrumentationError3(label, error) {
34478
+ function logInstrumentationError4(label, error) {
33023
34479
  debugLogger.debug(`Error in ${label} instrumentation:`, error);
33024
34480
  }
33025
34481
 
@@ -33587,10 +35043,10 @@ var LangSmithPlugin = class extends BasePlugin {
33587
35043
  const creates = ownValue(batch, "runCreates");
33588
35044
  if (Array.isArray(creates)) {
33589
35045
  const parentFirst = [...creates].sort((left, right) => {
33590
- const leftId = stringValue2(ownValue(left, "id"));
33591
- const rightId = stringValue2(ownValue(right, "id"));
33592
- const leftParent = stringValue2(ownValue(left, "parent_run_id"));
33593
- 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"));
33594
35050
  if (leftParent && leftParent === rightId) {
33595
35051
  return 1;
33596
35052
  }
@@ -33609,13 +35065,13 @@ var LangSmithPlugin = class extends BasePlugin {
33609
35065
  if (Array.isArray(updates)) {
33610
35066
  for (const run of updates) {
33611
35067
  this.containLifecycleFailure("batchIngestRuns update", () => {
33612
- this.processUpdate(stringValue2(ownValue(run, "id")) ?? "", run);
35068
+ this.processUpdate(stringValue3(ownValue(run, "id")) ?? "", run);
33613
35069
  });
33614
35070
  }
33615
35071
  }
33616
35072
  }
33617
35073
  processCreate(run) {
33618
- const id = stringValue2(ownValue(run, "id"));
35074
+ const id = stringValue3(ownValue(run, "id"));
33619
35075
  if (!id || this.completedRuns.get(id)) {
33620
35076
  return;
33621
35077
  }
@@ -33648,7 +35104,7 @@ var LangSmithPlugin = class extends BasePlugin {
33648
35104
  this.endIfComplete(id, activeRun, run);
33649
35105
  }
33650
35106
  processUpdate(explicitId, run) {
33651
- const id = stringValue2(explicitId) ?? stringValue2(ownValue(run, "id"));
35107
+ const id = stringValue3(explicitId) ?? stringValue3(ownValue(run, "id"));
33652
35108
  if (!id || this.completedRuns.get(id)) {
33653
35109
  return;
33654
35110
  }
@@ -33671,13 +35127,13 @@ var LangSmithPlugin = class extends BasePlugin {
33671
35127
  this.endIfComplete(id, active, active.run);
33672
35128
  }
33673
35129
  startRunSpan(id, run) {
33674
- const traceId = stringValue2(ownValue(run, "trace_id")) ?? id;
33675
- 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"));
33676
35132
  const startTime = timestampSeconds(ownValue(run, "start_time"));
33677
35133
  return startSpan(
33678
35134
  withSpanInstrumentationName(
33679
35135
  {
33680
- name: stringValue2(ownValue(run, "name")) ?? "LangSmith run",
35136
+ name: stringValue3(ownValue(run, "name")) ?? "LangSmith run",
33681
35137
  spanId: id,
33682
35138
  parentSpanIds: {
33683
35139
  parentSpanIds: parentId ? [parentId] : [],
@@ -33769,7 +35225,7 @@ function mergeRuns(previous, current) {
33769
35225
  function isRecord2(value) {
33770
35226
  return typeof value === "object" && value !== null && !Array.isArray(value);
33771
35227
  }
33772
- function stringValue2(value) {
35228
+ function stringValue3(value) {
33773
35229
  return typeof value === "string" && value.length > 0 ? value : void 0;
33774
35230
  }
33775
35231
  function timestampSeconds(value) {
@@ -33787,7 +35243,7 @@ function timestampSeconds(value) {
33787
35243
  return void 0;
33788
35244
  }
33789
35245
  function dottedOrderDepth(run) {
33790
- const dottedOrder = stringValue2(ownValue(run, "dotted_order"));
35246
+ const dottedOrder = stringValue3(ownValue(run, "dotted_order"));
33791
35247
  return dottedOrder ? dottedOrder.split(".").length : Number.MAX_SAFE_INTEGER;
33792
35248
  }
33793
35249
  function mapRunType(runType) {
@@ -33992,7 +35448,7 @@ var PiCodingAgentPlugin = class extends BasePlugin {
33992
35448
  }
33993
35449
  );
33994
35450
  } catch (error) {
33995
- logInstrumentationError4("Pi Coding Agent prompt start", error);
35451
+ logInstrumentationError5("Pi Coding Agent prompt start", error);
33996
35452
  }
33997
35453
  if (!state) {
33998
35454
  return runWithAutoInstrumentationSuppressed(invokeTarget);
@@ -34125,12 +35581,12 @@ function installPiAgentInstrumentation(agent) {
34125
35581
  () => handlePiAgentEvent(state, event)
34126
35582
  );
34127
35583
  } catch (error) {
34128
- logInstrumentationError4("Pi Coding Agent event", error);
35584
+ logInstrumentationError5("Pi Coding Agent event", error);
34129
35585
  }
34130
35586
  });
34131
35587
  piAgentEventSubscriptions.add(agent);
34132
35588
  } catch (error) {
34133
- logInstrumentationError4("Pi Coding Agent event subscription", error);
35589
+ logInstrumentationError5("Pi Coding Agent event subscription", error);
34134
35590
  }
34135
35591
  }
34136
35592
  function makeInstrumentedStreamFunction(agent, originalStreamFunction, property) {
@@ -34180,7 +35636,7 @@ function wrapPiToolExecutors(tools) {
34180
35636
  });
34181
35637
  tool.execute = wrappedExecute;
34182
35638
  } catch (error) {
34183
- logInstrumentationError4("Pi Coding Agent tool wrapping", error);
35639
+ logInstrumentationError5("Pi Coding Agent tool wrapping", error);
34184
35640
  }
34185
35641
  }
34186
35642
  }
@@ -34259,7 +35715,7 @@ function patchAssistantMessageStream(stream, promptState, llmState) {
34259
35715
  try {
34260
35716
  await iterator.return();
34261
35717
  } catch (cleanupError) {
34262
- logInstrumentationError4(
35718
+ logInstrumentationError5(
34263
35719
  "Pi Coding Agent stream cleanup",
34264
35720
  cleanupError
34265
35721
  );
@@ -34424,7 +35880,7 @@ function finishPiPromptRun(state, error) {
34424
35880
  try {
34425
35881
  state.span.end();
34426
35882
  } catch (endError) {
34427
- logInstrumentationError4("Pi Coding Agent prompt end", endError);
35883
+ logInstrumentationError5("Pi Coding Agent prompt end", endError);
34428
35884
  }
34429
35885
  }
34430
35886
  }
@@ -34756,10 +36212,10 @@ function safeLog4(span, event) {
34756
36212
  try {
34757
36213
  span.log(event);
34758
36214
  } catch (error) {
34759
- logInstrumentationError4("Pi Coding Agent span log", error);
36215
+ logInstrumentationError5("Pi Coding Agent span log", error);
34760
36216
  }
34761
36217
  }
34762
- function logInstrumentationError4(context, error) {
36218
+ function logInstrumentationError5(context, error) {
34763
36219
  debugLogger.debug(`${context}:`, error);
34764
36220
  }
34765
36221
 
@@ -34997,7 +36453,7 @@ function handleAgentStreamEvent(state, event) {
34997
36453
  finalizeModelSpan(state, event);
34998
36454
  break;
34999
36455
  case "beforeToolCallEvent":
35000
- startToolSpan2(state, event);
36456
+ startToolSpan3(state, event);
35001
36457
  break;
35002
36458
  case "afterToolCallEvent":
35003
36459
  finalizeToolSpan(state, event);
@@ -35022,7 +36478,7 @@ function handleAgentStreamEvent(state, event) {
35022
36478
  break;
35023
36479
  }
35024
36480
  } catch (error) {
35025
- logInstrumentationError5("Strands Agent SDK event", error);
36481
+ logInstrumentationError6("Strands Agent SDK event", error);
35026
36482
  }
35027
36483
  }
35028
36484
  function handleMultiAgentStreamEvent(state, event, activeChildParents) {
@@ -35058,7 +36514,7 @@ function handleMultiAgentStreamEvent(state, event, activeChildParents) {
35058
36514
  break;
35059
36515
  }
35060
36516
  } catch (error) {
35061
- logInstrumentationError5("Strands Agent SDK multi-agent event", error);
36517
+ logInstrumentationError6("Strands Agent SDK multi-agent event", error);
35062
36518
  }
35063
36519
  }
35064
36520
  function buildModelSpanInput(event, attachmentCache) {
@@ -35137,7 +36593,7 @@ function finalizeModelSpan(state, event) {
35137
36593
  });
35138
36594
  modelState.span.end();
35139
36595
  }
35140
- function startToolSpan2(state, event) {
36596
+ function startToolSpan3(state, event) {
35141
36597
  const toolUse = event.toolUse;
35142
36598
  const key = toolKey2(toolUse);
35143
36599
  if (state.activeTools.has(key)) {
@@ -35417,7 +36873,7 @@ function getModelConfig(model) {
35417
36873
  try {
35418
36874
  return model.getConfig();
35419
36875
  } catch (error) {
35420
- logInstrumentationError5("Strands Agent SDK model config", error);
36876
+ logInstrumentationError6("Strands Agent SDK model config", error);
35421
36877
  return void 0;
35422
36878
  }
35423
36879
  }
@@ -35500,7 +36956,7 @@ function processStrandsInputAttachments(input, cache = createStrandsAttachmentCa
35500
36956
  try {
35501
36957
  return processStrandsInputNode(input, cache);
35502
36958
  } catch (error) {
35503
- logInstrumentationError5("Strands Agent SDK input attachments", error);
36959
+ logInstrumentationError6("Strands Agent SDK input attachments", error);
35504
36960
  return input;
35505
36961
  }
35506
36962
  }
@@ -35720,13 +37176,484 @@ function safeLog5(span, event) {
35720
37176
  try {
35721
37177
  span.log(event);
35722
37178
  } catch (error) {
35723
- logInstrumentationError5("Strands Agent SDK span log", error);
37179
+ logInstrumentationError6("Strands Agent SDK span log", error);
35724
37180
  }
35725
37181
  }
35726
- function logInstrumentationError5(context, error) {
37182
+ function logInstrumentationError6(context, error) {
35727
37183
  debugLogger.debug(`${context}:`, error);
35728
37184
  }
35729
37185
 
37186
+ // src/instrumentation/plugins/elevenlabs-channels.ts
37187
+ var elevenLabsChannels = defineChannels(
37188
+ "@elevenlabs/elevenlabs-js",
37189
+ {
37190
+ convert: channel({
37191
+ channelName: "textToSpeech.convert",
37192
+ kind: "async"
37193
+ }),
37194
+ stream: channel({
37195
+ channelName: "textToSpeech.stream",
37196
+ kind: "async"
37197
+ }),
37198
+ convertWithTimestamps: channel({ channelName: "textToSpeech.convertWithTimestamps", kind: "async" }),
37199
+ streamWithTimestamps: channel({ channelName: "textToSpeech.streamWithTimestamps", kind: "async" }),
37200
+ transcribe: channel({ channelName: "speechToText.convert", kind: "async" })
37201
+ },
37202
+ { instrumentationName: INSTRUMENTATION_NAMES.ELEVENLABS }
37203
+ );
37204
+
37205
+ // src/instrumentation/plugins/elevenlabs-plugin.ts
37206
+ var ElevenLabsPlugin = class extends BasePlugin {
37207
+ onEnable() {
37208
+ for (const method of [
37209
+ "convert",
37210
+ "stream",
37211
+ "convertWithTimestamps",
37212
+ "streamWithTimestamps"
37213
+ ]) {
37214
+ this.unsubscribers.push(
37215
+ interceptCall2(
37216
+ elevenLabsChannels[method],
37217
+ `elevenlabs.textToSpeech.${method}`,
37218
+ ([voice, request]) => ({
37219
+ input: {
37220
+ operation: "speech",
37221
+ prompt: request.text,
37222
+ parameters: {
37223
+ voice,
37224
+ format: request.outputFormat,
37225
+ language: request.languageCode,
37226
+ speed: request.voiceSettings?.speed
37227
+ }
37228
+ },
37229
+ metadata: {
37230
+ provider: "elevenlabs",
37231
+ model: request.modelId ?? "eleven_multilingual_v2"
37232
+ }
37233
+ }),
37234
+ (value, args, span, finish, headers, started) => captureSpeech(
37235
+ value,
37236
+ args[1],
37237
+ method,
37238
+ span,
37239
+ finish,
37240
+ started,
37241
+ headers
37242
+ )
37243
+ )
37244
+ );
37245
+ }
37246
+ this.unsubscribers.push(
37247
+ interceptCall2(
37248
+ elevenLabsChannels.transcribe,
37249
+ "elevenlabs.speechToText.convert",
37250
+ ([request]) => {
37251
+ if (request.webhook) return void 0;
37252
+ const file = request.file;
37253
+ const filename = typeof File !== "undefined" && file instanceof File ? file.name : "audio";
37254
+ const contentType = file instanceof Blob ? file.type || "application/octet-stream" : "application/octet-stream";
37255
+ const blob = file instanceof Blob ? file : file instanceof Uint8Array ? new Blob([new Uint8Array(file)], { type: contentType }) : file instanceof ArrayBuffer ? new Blob([file.slice(0)], { type: contentType }) : void 0;
37256
+ const fileData = blob ? new Attachment({ data: blob, filename, contentType }) : request.cloudStorageUrl;
37257
+ return {
37258
+ input: {
37259
+ operation: "transcribe",
37260
+ content: fileData ? [{ type: "file", file: { filename, file_data: fileData } }] : [],
37261
+ parameters: {
37262
+ language: request.languageCode,
37263
+ timestamp_granularities: request.timestampsGranularity
37264
+ }
37265
+ },
37266
+ metadata: { provider: "elevenlabs", model: request.modelId }
37267
+ };
37268
+ },
37269
+ (value, _args, span, finish) => {
37270
+ const result = value;
37271
+ const transcripts = result.transcripts ?? [result];
37272
+ span.log({
37273
+ output: {
37274
+ content: transcripts.flatMap(
37275
+ (transcript) => typeof transcript.text === "string" ? [{ type: "text", text: transcript.text }] : []
37276
+ ),
37277
+ annotations: {
37278
+ language: result.languageCode,
37279
+ words: result.words ?? (result.transcripts ? result.transcripts.flatMap(
37280
+ (transcript) => transcript.words ?? []
37281
+ ) : void 0)
37282
+ }
37283
+ }
37284
+ });
37285
+ finish();
37286
+ },
37287
+ ([request], span) => {
37288
+ const file = request.file;
37289
+ if (!isAsyncIterable(file)) return;
37290
+ const chunks = [];
37291
+ const filename = isObject(file) && typeof file.path === "string" ? file.path.split(/[\\/]/).pop() || "audio" : "audio";
37292
+ observeAudioStream(
37293
+ file,
37294
+ (chunk) => chunks.push(new Uint8Array(chunk)),
37295
+ () => {
37296
+ const contentType = "application/octet-stream";
37297
+ const data = new Blob(chunks, {
37298
+ type: contentType
37299
+ });
37300
+ chunks.length = 0;
37301
+ span.log({
37302
+ input: {
37303
+ content: [
37304
+ {
37305
+ type: "file",
37306
+ file: {
37307
+ filename,
37308
+ file_data: new Attachment({
37309
+ data,
37310
+ filename,
37311
+ contentType
37312
+ })
37313
+ }
37314
+ }
37315
+ ]
37316
+ }
37317
+ });
37318
+ },
37319
+ () => {
37320
+ chunks.length = 0;
37321
+ },
37322
+ span
37323
+ );
37324
+ }
37325
+ )
37326
+ );
37327
+ }
37328
+ onDisable() {
37329
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
37330
+ }
37331
+ };
37332
+ function interceptCall2(channel2, name, input, output, beforeInvoke) {
37333
+ return channel2.intercept((target, self, args) => {
37334
+ const invoke2 = () => Reflect.apply(target, self, args);
37335
+ if (isAutoInstrumentationSuppressed()) return invoke2();
37336
+ const started = Date.now() / 1e3;
37337
+ let span;
37338
+ try {
37339
+ const event = input(args);
37340
+ if (event !== void 0)
37341
+ span = startSpan(
37342
+ withSpanInstrumentationName(
37343
+ {
37344
+ name,
37345
+ spanAttributes: { type: "llm" /* LLM */ },
37346
+ event
37347
+ },
37348
+ INSTRUMENTATION_NAMES.ELEVENLABS
37349
+ )
37350
+ );
37351
+ } catch (error) {
37352
+ debugLogger.error("Error starting ElevenLabs span", error);
37353
+ return invoke2();
37354
+ }
37355
+ if (!span) return invoke2();
37356
+ const activeSpan = span;
37357
+ let ended = false;
37358
+ const finish = (error) => {
37359
+ if (ended) return;
37360
+ ended = true;
37361
+ try {
37362
+ if (error !== void 0) activeSpan.log({ error });
37363
+ activeSpan.end();
37364
+ } catch (loggingError) {
37365
+ debugLogger.error("Error ending ElevenLabs span", loggingError);
37366
+ }
37367
+ };
37368
+ try {
37369
+ beforeInvoke?.(args, span);
37370
+ } catch (error) {
37371
+ debugLogger.error("Error observing ElevenLabs input", error);
37372
+ }
37373
+ let result;
37374
+ try {
37375
+ result = withCurrent(
37376
+ span,
37377
+ () => runWithAutoInstrumentationSuppressed(invoke2)
37378
+ );
37379
+ } catch (error) {
37380
+ finish(error);
37381
+ throw error;
37382
+ }
37383
+ const capture = (value, headers) => {
37384
+ try {
37385
+ output(value, args, span, finish, headers, started);
37386
+ } catch (error) {
37387
+ debugLogger.error("Error capturing ElevenLabs output", error);
37388
+ finish();
37389
+ }
37390
+ };
37391
+ try {
37392
+ if (isObject(result) && typeof result.withRawResponse === "function") {
37393
+ void result.withRawResponse().then(
37394
+ ({
37395
+ data,
37396
+ rawResponse
37397
+ }) => capture(data, rawResponse?.headers),
37398
+ finish
37399
+ );
37400
+ } else {
37401
+ void Promise.resolve(result).then((value) => capture(value), finish);
37402
+ }
37403
+ } catch (error) {
37404
+ debugLogger.error("Error observing ElevenLabs result", error);
37405
+ finish();
37406
+ }
37407
+ return result;
37408
+ });
37409
+ }
37410
+ function captureSpeech(value, request, method, span, finish, started, headers) {
37411
+ const format = request.outputFormat ?? "mp3_44100_128";
37412
+ const formatType = format.startsWith("mp3_") ? "audio/mpeg" : format.startsWith("pcm_") ? "audio/pcm" : format.startsWith("opus_") ? "audio/ogg" : format.startsWith("ulaw_") ? "audio/basic" : format.startsWith("alaw_") ? "audio/x-alaw" : void 0;
37413
+ const headerType = headers?.get("content-type")?.split(";")[0];
37414
+ const contentType = headerType?.startsWith("audio/") ? headerType : formatType;
37415
+ const disposition = headers?.get("content-disposition");
37416
+ const headerFilename = disposition?.match(
37417
+ /filename="([^"]+)"|filename=([^;]+)/i
37418
+ );
37419
+ const filename = headerFilename?.[1] ?? headerFilename?.[2]?.trim() ?? `speech.${contentType ? getExtensionFromMediaType(contentType) : "bin"}`;
37420
+ const chunks = [];
37421
+ const alignments = [];
37422
+ let bytes = 0;
37423
+ let first = true;
37424
+ let stopped = false;
37425
+ const observe = (chunk) => {
37426
+ if (stopped || chunk.byteLength === 0) return;
37427
+ if (first && method.startsWith("stream")) {
37428
+ span.log({
37429
+ metrics: { time_to_first_token: Date.now() / 1e3 - started }
37430
+ });
37431
+ }
37432
+ first = false;
37433
+ chunks.push(new Uint8Array(chunk));
37434
+ bytes += chunk.byteLength;
37435
+ };
37436
+ const complete = () => {
37437
+ if (stopped) return;
37438
+ stopped = true;
37439
+ try {
37440
+ const content = [];
37441
+ if (contentType && bytes) {
37442
+ const data = new Uint8Array(bytes);
37443
+ let offset = 0;
37444
+ for (const chunk of chunks) {
37445
+ data.set(chunk, offset);
37446
+ offset += chunk.length;
37447
+ }
37448
+ content.push({
37449
+ type: "file",
37450
+ file: {
37451
+ filename,
37452
+ byte_size: bytes,
37453
+ file_data: new Attachment({
37454
+ data: new Blob([data], { type: contentType }),
37455
+ filename,
37456
+ contentType
37457
+ })
37458
+ }
37459
+ });
37460
+ }
37461
+ span.log({
37462
+ output: {
37463
+ content,
37464
+ ...alignments.length ? { annotations: alignments } : {}
37465
+ }
37466
+ });
37467
+ } finally {
37468
+ chunks.length = 0;
37469
+ finish();
37470
+ }
37471
+ };
37472
+ const cancel = (error) => {
37473
+ stopped = true;
37474
+ chunks.length = 0;
37475
+ finish(error);
37476
+ };
37477
+ const timestampChunk = (chunk) => {
37478
+ const binary = atob(chunk.audioBase64);
37479
+ observe(Uint8Array.from(binary, (character) => character.charCodeAt(0)));
37480
+ if (chunk.alignment || chunk.normalizedAlignment)
37481
+ alignments.push({
37482
+ alignment: chunk.alignment,
37483
+ normalized_alignment: chunk.normalizedAlignment
37484
+ });
37485
+ };
37486
+ if (method === "convertWithTimestamps") {
37487
+ timestampChunk(value);
37488
+ complete();
37489
+ } else if (method === "streamWithTimestamps") {
37490
+ patchStreamIfNeeded(value, {
37491
+ shouldCollect: (chunk) => {
37492
+ try {
37493
+ timestampChunk(chunk);
37494
+ } catch (error) {
37495
+ debugLogger.error("Error collecting ElevenLabs timestamps", error);
37496
+ cancel();
37497
+ }
37498
+ return false;
37499
+ },
37500
+ onComplete: complete,
37501
+ onCancel: () => cancel(),
37502
+ onError: cancel,
37503
+ aroundNext: (next) => withCurrent(span, next)
37504
+ });
37505
+ } else {
37506
+ observeAudioStream(value, observe, complete, cancel, span);
37507
+ }
37508
+ }
37509
+ function observeAudioStream(value, observe, complete, cancel, span) {
37510
+ let ended = false;
37511
+ const safeObserve = (chunk) => {
37512
+ if (ended) return;
37513
+ try {
37514
+ observe(chunk);
37515
+ } catch (error) {
37516
+ debugLogger.error("Error collecting ElevenLabs audio", error);
37517
+ end(false);
37518
+ }
37519
+ };
37520
+ const end = (success, error) => {
37521
+ if (ended) return;
37522
+ ended = true;
37523
+ try {
37524
+ if (success) complete();
37525
+ else cancel(error);
37526
+ } catch (loggingError) {
37527
+ debugLogger.error("Error logging ElevenLabs audio", loggingError);
37528
+ cancel();
37529
+ }
37530
+ };
37531
+ if (!isObject(value) || !Object.isExtensible(value)) {
37532
+ end(false);
37533
+ return;
37534
+ }
37535
+ if (typeof value.read === "function" && typeof value.on === "function") {
37536
+ value.on("end", () => end(true));
37537
+ value.on("close", () => end(false));
37538
+ const emit2 = value.emit;
37539
+ if (typeof emit2 === "function")
37540
+ value.emit = function(event, ...args) {
37541
+ if (event === "data" && args[0] instanceof Uint8Array)
37542
+ safeObserve(args[0]);
37543
+ if (event === "error") end(false, args[0]);
37544
+ return Reflect.apply(emit2, this, [event, ...args]);
37545
+ };
37546
+ return;
37547
+ }
37548
+ if (typeof value.getReader === "function") {
37549
+ const webStream = value;
37550
+ const pipeTo = webStream.pipeTo;
37551
+ const pipeThrough = webStream.pipeThrough;
37552
+ webStream.pipeTo = function(destination, options) {
37553
+ if (!isObject(destination) || this.locked || destination.locked)
37554
+ return pipeTo.call(this, destination, options);
37555
+ const tap = new TransformStream({
37556
+ transform(chunk, controller) {
37557
+ safeObserve(chunk);
37558
+ controller.enqueue(chunk);
37559
+ },
37560
+ flush() {
37561
+ end(true);
37562
+ }
37563
+ });
37564
+ const observed = pipeThrough.call(
37565
+ this,
37566
+ tap,
37567
+ options
37568
+ );
37569
+ return observed.pipeTo(destination, options).catch((error) => {
37570
+ end(false, error);
37571
+ throw error;
37572
+ });
37573
+ };
37574
+ webStream.pipeThrough = function(transform, options) {
37575
+ if (this.locked || transform.writable.locked || transform.readable.locked)
37576
+ return pipeThrough.call(this, transform, options);
37577
+ const result = webStream.pipeTo.call(this, transform.writable, options);
37578
+ void result.catch(() => {
37579
+ });
37580
+ return transform.readable;
37581
+ };
37582
+ const getReader = value.getReader;
37583
+ value.getReader = function(...args) {
37584
+ const reader = Reflect.apply(getReader, this, args);
37585
+ const read3 = reader.read;
37586
+ reader.read = function(...readArgs) {
37587
+ return Promise.resolve(
37588
+ withCurrent(span, () => Reflect.apply(read3, this, readArgs))
37589
+ ).then(
37590
+ (result) => {
37591
+ if (result.value) safeObserve(result.value);
37592
+ if (result.done) end(true);
37593
+ return result;
37594
+ },
37595
+ (error) => {
37596
+ end(false, error);
37597
+ throw error;
37598
+ }
37599
+ );
37600
+ };
37601
+ const readerCancel = reader.cancel;
37602
+ reader.cancel = function(...cancelArgs) {
37603
+ const result = Reflect.apply(readerCancel, this, cancelArgs);
37604
+ end(false);
37605
+ return result;
37606
+ };
37607
+ return reader;
37608
+ };
37609
+ const streamCancel = value.cancel;
37610
+ if (typeof streamCancel === "function")
37611
+ value.cancel = function(...args) {
37612
+ const result = Reflect.apply(streamCancel, this, args);
37613
+ void Promise.resolve(result).then(
37614
+ () => end(false),
37615
+ () => {
37616
+ }
37617
+ );
37618
+ return result;
37619
+ };
37620
+ }
37621
+ if (typeof value.getReader === "function" && typeof value.values === "function") {
37622
+ const values = value.values;
37623
+ const iterate = function(...args) {
37624
+ const iterator = Reflect.apply(values, this, args);
37625
+ patchStreamIfNeeded(iterator, {
37626
+ shouldCollect(chunk) {
37627
+ safeObserve(chunk);
37628
+ return false;
37629
+ },
37630
+ onComplete: () => end(true),
37631
+ onCancel: () => end(false),
37632
+ onError: (error) => end(false, error),
37633
+ aroundNext: (next) => withCurrent(span, next)
37634
+ });
37635
+ return iterator;
37636
+ };
37637
+ value.values = iterate;
37638
+ Object.defineProperty(value, Symbol.asyncIterator, {
37639
+ configurable: true,
37640
+ writable: true,
37641
+ value: iterate
37642
+ });
37643
+ } else if (isAsyncIterable(value)) {
37644
+ patchStreamIfNeeded(value, {
37645
+ shouldCollect: (chunk) => {
37646
+ safeObserve(chunk);
37647
+ return false;
37648
+ },
37649
+ onComplete: () => end(true),
37650
+ onCancel: () => end(false),
37651
+ onError: (error) => end(false, error),
37652
+ aroundNext: (next) => withCurrent(span, next)
37653
+ });
37654
+ } else if (typeof value.getReader !== "function") end(false);
37655
+ }
37656
+
35730
37657
  // src/instrumentation/plugins/voyageai-channels.ts
35731
37658
  var voyageAIChannels = defineChannels(
35732
37659
  "voyageai",
@@ -35794,7 +37721,7 @@ var VoyageAIPlugin = class extends BasePlugin {
35794
37721
  this.unsubscribers = unsubscribeAll(this.unsubscribers);
35795
37722
  }
35796
37723
  };
35797
- function interceptVoyageAICall(channel2, name, extractInput2, extractOutput2, extractMetrics2 = extractUsageMetrics3) {
37724
+ function interceptVoyageAICall(channel2, name, extractInput3, extractOutput2, extractMetrics2 = extractUsageMetrics3) {
35798
37725
  return channel2.intercept((target, thisArg, args) => {
35799
37726
  const invokeTarget = () => Reflect.apply(target, thisArg, args);
35800
37727
  if (isAutoInstrumentationSuppressed()) {
@@ -35802,7 +37729,7 @@ function interceptVoyageAICall(channel2, name, extractInput2, extractOutput2, ex
35802
37729
  }
35803
37730
  let span;
35804
37731
  try {
35805
- const { input, metadata } = extractInput2(args);
37732
+ const { input, metadata } = extractInput3(args);
35806
37733
  span = startSpan(
35807
37734
  withSpanInstrumentationName(
35808
37735
  {
@@ -36152,14 +38079,14 @@ var CloudflareAIChatPlugin = class extends BasePlugin {
36152
38079
  const result = event.arguments[0];
36153
38080
  state = agent ? this.findResponseState(
36154
38081
  agent,
36155
- stringValue3(ownValue2(result, "requestId"))
38082
+ stringValue4(ownValue2(result, "requestId"))
36156
38083
  ) : void 0;
36157
38084
  if (!state) {
36158
38085
  return;
36159
38086
  }
36160
38087
  state.responseObserved = true;
36161
38088
  const output = serializeMessage(ownValue2(result, "message"));
36162
- const status = stringValue3(ownValue2(result, "status"));
38089
+ const status = stringValue4(ownValue2(result, "status"));
36163
38090
  const error = ownValue2(result, "error");
36164
38091
  const input = ownValue2(result, "continuation") === true ? state.input : serializeMessages(readProperty(agent, "messages"))?.filter(
36165
38092
  (message) => typeof output?.id !== "string" || message.id !== output.id
@@ -36206,7 +38133,7 @@ var CloudflareAIChatPlugin = class extends BasePlugin {
36206
38133
  }
36207
38134
  try {
36208
38135
  const agent = asObject(event.self);
36209
- const requestId = stringValue3(event.arguments[0]);
38136
+ const requestId = stringValue4(event.arguments[0]);
36210
38137
  const key = requestId ?? /* @__PURE__ */ Symbol("cloudflare-ai-chat-turn");
36211
38138
  const activeForAgent = agent ? this.getActiveTurns(agent) : void 0;
36212
38139
  const existing = activeForAgent?.get(key);
@@ -36375,7 +38302,7 @@ function ownValue2(value, key) {
36375
38302
  const descriptor = Object.getOwnPropertyDescriptor(object, key);
36376
38303
  return descriptor && "value" in descriptor ? descriptor.value : void 0;
36377
38304
  }
36378
- function stringValue3(value) {
38305
+ function stringValue4(value) {
36379
38306
  return typeof value === "string" ? value : void 0;
36380
38307
  }
36381
38308
  function serializeMessages(value) {
@@ -36493,7 +38420,7 @@ var CloudflareAgentsPlugin = class extends BasePlugin {
36493
38420
  );
36494
38421
  spans.set(event, span);
36495
38422
  } catch (error) {
36496
- logInstrumentationError6("start", error);
38423
+ logInstrumentationError7("start", error);
36497
38424
  }
36498
38425
  },
36499
38426
  asyncEnd: (event) => {
@@ -36513,7 +38440,7 @@ var CloudflareAgentsPlugin = class extends BasePlugin {
36513
38440
  }
36514
38441
  }
36515
38442
  } catch (error) {
36516
- logInstrumentationError6("completion", error);
38443
+ logInstrumentationError7("completion", error);
36517
38444
  } finally {
36518
38445
  safelyEndSpan(span);
36519
38446
  }
@@ -36527,7 +38454,7 @@ var CloudflareAgentsPlugin = class extends BasePlugin {
36527
38454
  try {
36528
38455
  span.log({ error: event.error });
36529
38456
  } catch (error) {
36530
- logInstrumentationError6("rejection", error);
38457
+ logInstrumentationError7("rejection", error);
36531
38458
  } finally {
36532
38459
  safelyEndSpan(span);
36533
38460
  }
@@ -36557,10 +38484,10 @@ function safelyEndSpan(span) {
36557
38484
  try {
36558
38485
  span.end();
36559
38486
  } catch (error) {
36560
- logInstrumentationError6("span end", error);
38487
+ logInstrumentationError7("span end", error);
36561
38488
  }
36562
38489
  }
36563
- function logInstrumentationError6(operation, error) {
38490
+ function logInstrumentationError7(operation, error) {
36564
38491
  debugLogger.error(
36565
38492
  `Failed to process Cloudflare Agents ${operation} instrumentation:`,
36566
38493
  error
@@ -36578,12 +38505,14 @@ var BraintrustPlugin = class extends BasePlugin {
36578
38505
  cloudflareThinkPlugin = null;
36579
38506
  cursorSDKPlugin = null;
36580
38507
  openAIAgentsPlugin = null;
38508
+ googleGenerativeAIPlugin = null;
36581
38509
  googleGenAIPlugin = null;
36582
38510
  huggingFacePlugin = null;
36583
38511
  huggingFaceTransformersPlugin = null;
36584
38512
  openRouterPlugin = null;
36585
38513
  openRouterAgentPlugin = null;
36586
38514
  mistralPlugin = null;
38515
+ langGraphSDKPlugin = null;
36587
38516
  ollamaPlugin = null;
36588
38517
  googleADKPlugin = null;
36589
38518
  coherePlugin = null;
@@ -36596,6 +38525,7 @@ var BraintrustPlugin = class extends BasePlugin {
36596
38525
  langSmithPlugin = null;
36597
38526
  piCodingAgentPlugin = null;
36598
38527
  strandsAgentSDKPlugin = null;
38528
+ elevenLabsPlugin = null;
36599
38529
  voyageAIPlugin = null;
36600
38530
  cloudflareAIChatPlugin = null;
36601
38531
  cloudflareAgentsPlugin = null;
@@ -36637,6 +38567,10 @@ var BraintrustPlugin = class extends BasePlugin {
36637
38567
  this.openAIAgentsPlugin = new OpenAIAgentsPlugin();
36638
38568
  this.openAIAgentsPlugin.enable();
36639
38569
  }
38570
+ if (integrations.googleGenerativeAI !== false) {
38571
+ this.googleGenerativeAIPlugin = new GoogleGenerativeAIPlugin();
38572
+ this.googleGenerativeAIPlugin.enable();
38573
+ }
36640
38574
  if (integrations.googleGenAI !== false && integrations.google !== false) {
36641
38575
  this.googleGenAIPlugin = new GoogleGenAIPlugin();
36642
38576
  this.googleGenAIPlugin.enable();
@@ -36659,6 +38593,10 @@ var BraintrustPlugin = class extends BasePlugin {
36659
38593
  this.mistralPlugin = new MistralPlugin();
36660
38594
  this.mistralPlugin.enable();
36661
38595
  }
38596
+ if (integrations.langgraphSDK !== false) {
38597
+ this.langGraphSDKPlugin = new LangGraphSDKPlugin();
38598
+ this.langGraphSDKPlugin.enable();
38599
+ }
36662
38600
  if (integrations.ollama !== false) {
36663
38601
  this.ollamaPlugin = new OllamaPlugin();
36664
38602
  this.ollamaPlugin.enable();
@@ -36671,6 +38609,10 @@ var BraintrustPlugin = class extends BasePlugin {
36671
38609
  this.coherePlugin = new CoherePlugin();
36672
38610
  this.coherePlugin.enable();
36673
38611
  }
38612
+ if (integrations.elevenlabs !== false) {
38613
+ this.elevenLabsPlugin = new ElevenLabsPlugin();
38614
+ this.elevenLabsPlugin.enable();
38615
+ }
36674
38616
  if (integrations.voyageai !== false) {
36675
38617
  this.voyageAIPlugin = new VoyageAIPlugin();
36676
38618
  this.voyageAIPlugin.enable();
@@ -36755,6 +38697,10 @@ var BraintrustPlugin = class extends BasePlugin {
36755
38697
  this.openAIAgentsPlugin.disable();
36756
38698
  this.openAIAgentsPlugin = null;
36757
38699
  }
38700
+ if (this.googleGenerativeAIPlugin) {
38701
+ this.googleGenerativeAIPlugin.disable();
38702
+ this.googleGenerativeAIPlugin = null;
38703
+ }
36758
38704
  if (this.googleGenAIPlugin) {
36759
38705
  this.googleGenAIPlugin.disable();
36760
38706
  this.googleGenAIPlugin = null;
@@ -36779,6 +38725,10 @@ var BraintrustPlugin = class extends BasePlugin {
36779
38725
  this.mistralPlugin.disable();
36780
38726
  this.mistralPlugin = null;
36781
38727
  }
38728
+ if (this.langGraphSDKPlugin) {
38729
+ this.langGraphSDKPlugin.disable();
38730
+ this.langGraphSDKPlugin = null;
38731
+ }
36782
38732
  if (this.ollamaPlugin) {
36783
38733
  this.ollamaPlugin.disable();
36784
38734
  this.ollamaPlugin = null;
@@ -36791,6 +38741,10 @@ var BraintrustPlugin = class extends BasePlugin {
36791
38741
  this.coherePlugin.disable();
36792
38742
  this.coherePlugin = null;
36793
38743
  }
38744
+ if (this.elevenLabsPlugin) {
38745
+ this.elevenLabsPlugin.disable();
38746
+ this.elevenLabsPlugin = null;
38747
+ }
36794
38748
  if (this.voyageAIPlugin) {
36795
38749
  this.voyageAIPlugin.disable();
36796
38750
  this.voyageAIPlugin = null;
@@ -36884,6 +38838,8 @@ var envIntegrationAliases = {
36884
38838
  "openai-agents-core": "openAIAgents",
36885
38839
  openaiagentscore: "openAIAgents",
36886
38840
  google: "google",
38841
+ "google-generative-ai": "googleGenerativeAI",
38842
+ googlegenerativeai: "googleGenerativeAI",
36887
38843
  "google-genai": "googleGenAI",
36888
38844
  googlegenai: "googleGenAI",
36889
38845
  huggingface: "huggingface",
@@ -36914,10 +38870,15 @@ var envIntegrationAliases = {
36914
38870
  "langchain-js": "langchain",
36915
38871
  "@langchain": "langchain",
36916
38872
  langgraph: "langgraph",
38873
+ langgraphsdk: "langgraphSDK",
38874
+ "langgraph-sdk": "langgraphSDK",
38875
+ "@langchain/langgraph-sdk": "langgraphSDK",
36917
38876
  langsmith: "langsmith",
36918
38877
  voyage: "voyageai",
36919
38878
  "voyage-ai": "voyageai",
36920
- voyageai: "voyageai"
38879
+ voyageai: "voyageai",
38880
+ elevenlabs: "elevenlabs",
38881
+ "@elevenlabs/elevenlabs-js": "elevenlabs"
36921
38882
  };
36922
38883
  function getDefaultInstrumentationIntegrations() {
36923
38884
  return {
@@ -36928,6 +38889,7 @@ function getDefaultInstrumentationIntegrations() {
36928
38889
  aisdk: true,
36929
38890
  google: true,
36930
38891
  googleGenAI: true,
38892
+ googleGenerativeAI: true,
36931
38893
  googleADK: true,
36932
38894
  huggingface: true,
36933
38895
  claudeAgentSDK: true,
@@ -36951,8 +38913,10 @@ function getDefaultInstrumentationIntegrations() {
36951
38913
  gitHubCopilot: true,
36952
38914
  langchain: true,
36953
38915
  langgraph: true,
38916
+ langgraphSDK: true,
36954
38917
  langsmith: true,
36955
38918
  voyageai: true,
38919
+ elevenlabs: true,
36956
38920
  piCodingAgent: true,
36957
38921
  strandsAgentSDK: true,
36958
38922
  cloudflareAgents: true
@@ -38513,6 +40477,9 @@ function waterfall(tasks, callback) {
38513
40477
  }
38514
40478
  var waterfall$1 = awaitify(waterfall);
38515
40479
 
40480
+ // src/framework.ts
40481
+ import { v5 as uuidv5 } from "uuid";
40482
+
38516
40483
  // src/functions/invoke.ts
38517
40484
  async function invoke(args) {
38518
40485
  const {
@@ -38595,11 +40562,268 @@ async function invoke(args) {
38595
40562
  }
38596
40563
 
38597
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
+ }
38598
40821
  var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
38599
- 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);
38600
40824
  const filterExpr = _SpanFetcher.buildFilter(
38601
40825
  rootSpanId,
38602
- spanTypeFilter,
40826
+ normalizedFilters,
38603
40827
  includeScorers
38604
40828
  );
38605
40829
  super(
@@ -38620,42 +40844,22 @@ var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
38620
40844
  rootSpanId;
38621
40845
  _state;
38622
40846
  spanTypeFilter;
38623
- static buildFilter(rootSpanId, spanTypeFilter, includeScorers = false) {
40847
+ static buildFilter(rootSpanId, filters, includeScorers = false) {
40848
+ const purpose = ["span_attributes", "purpose"];
38624
40849
  const children = [
38625
- // Base filter: root_span_id = 'value'
38626
- {
38627
- op: "eq",
38628
- left: { op: "ident", name: ["root_span_id"] },
38629
- right: { op: "literal", value: rootSpanId }
38630
- }
40850
+ btqlComparison("eq", ["root_span_id"], rootSpanId)
38631
40851
  ];
38632
40852
  if (!includeScorers) {
38633
40853
  children.push({
38634
40854
  op: "or",
38635
40855
  children: [
38636
- {
38637
- op: "isnull",
38638
- expr: { op: "ident", name: ["span_attributes", "purpose"] }
38639
- },
38640
- {
38641
- op: "ne",
38642
- left: { op: "ident", name: ["span_attributes", "purpose"] },
38643
- right: { op: "literal", value: "scorer" }
38644
- }
40856
+ btqlNullCheck("isnull", purpose),
40857
+ btqlComparison("ne", purpose, "scorer")
38645
40858
  ]
38646
40859
  });
38647
40860
  }
38648
- if (spanTypeFilter && spanTypeFilter.length > 0) {
38649
- children.push({
38650
- op: "in",
38651
- left: { op: "ident", name: ["span_attributes", "type"] },
38652
- right: { op: "literal", value: spanTypeFilter }
38653
- });
38654
- }
38655
- return {
38656
- op: "and",
38657
- children
38658
- };
40861
+ children.push(...spanFilterClauses(filters));
40862
+ return { op: "and", children };
38659
40863
  }
38660
40864
  get id() {
38661
40865
  return Promise.resolve(this._objectId);
@@ -38670,67 +40874,80 @@ var CachedSpanFetcher = class {
38670
40874
  fetchFn;
38671
40875
  constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState, brainstoreRealtime = true) {
38672
40876
  if (typeof objectTypeOrFetchFn === "function") {
38673
- this.fetchFn = (spanType) => objectTypeOrFetchFn(spanType);
40877
+ this.fetchFn = async (filters) => (await objectTypeOrFetchFn(filters.filters.spanType)).filter(
40878
+ (span) => matchesSpanFilters(span, filters)
40879
+ );
38674
40880
  } else {
38675
40881
  const objectType = objectTypeOrFetchFn;
38676
- this.fetchFn = async (spanType, includeScorers) => {
40882
+ this.fetchFn = async (filters, includeScorers) => {
38677
40883
  const state = await getState();
38678
40884
  const fetcher = new SpanFetcher(
38679
40885
  objectType,
38680
40886
  objectId,
38681
40887
  rootSpanId,
38682
40888
  state,
38683
- spanType,
40889
+ void 0,
38684
40890
  includeScorers,
38685
- brainstoreRealtime
40891
+ brainstoreRealtime,
40892
+ filters.filters
38686
40893
  );
38687
- const rows = await fetcher.fetchedData();
38688
- return rows.map((row) => ({
38689
- input: row.input,
38690
- output: row.output,
38691
- expected: row.expected,
38692
- error: row.error,
38693
- scores: row.scores,
38694
- metrics: row.metrics,
38695
- metadata: row.metadata,
38696
- span_id: row.span_id,
38697
- span_parents: row.span_parents,
38698
- is_root: row.is_root,
38699
- span_attributes: row.span_attributes,
38700
- id: row.id,
38701
- _xact_id: row._xact_id,
38702
- _pagination_key: row._pagination_key,
38703
- root_span_id: row.root_span_id,
38704
- created: row.created,
38705
- tags: row.tags
38706
- }));
40894
+ let spans = (await fetcher.fetchedData()).map(
40895
+ (row) => ({ ...row })
40896
+ );
40897
+ if (filters.filters.metadata !== void 0) {
40898
+ spans = spans.filter((span) => matchesSpanFilters(span, filters));
40899
+ }
40900
+ return spans;
38707
40901
  };
38708
40902
  }
38709
40903
  }
38710
40904
  async getSpans({
38711
- spanType,
40905
+ spanType: requestedSpanType,
40906
+ filters,
38712
40907
  includeScorers = false
38713
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
+ }
38714
40917
  if (includeScorers) {
38715
- return this.fetchFn(spanType, true);
40918
+ return this.fetchFn(normalizedFilters, true);
38716
40919
  }
38717
40920
  if (this.allFetched) {
38718
- return this.getFromCache(spanType);
40921
+ const spans = this.getFromCache(spanType);
40922
+ return hasAdvancedFilters ? spans.filter((span) => matchesSpanFilters(span, normalizedFilters)) : spans;
38719
40923
  }
38720
- 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();
38721
40934
  await this.fetchSpans(void 0);
38722
- this.allFetched = true;
40935
+ if (this.spanCache.size > 0) {
40936
+ this.allFetched = true;
40937
+ }
38723
40938
  return this.getFromCache(void 0);
38724
40939
  }
38725
- const missingTypes = spanType.filter((t) => !this.spanCache.has(t));
38726
- if (missingTypes.length === 0) {
38727
- return this.getFromCache(spanType);
40940
+ const missingTypes = spanType.filter((type) => !this.spanCache.has(type));
40941
+ if (missingTypes.length > 0) {
40942
+ await this.fetchSpans(missingTypes);
38728
40943
  }
38729
- await this.fetchSpans(missingTypes);
38730
40944
  return this.getFromCache(spanType);
38731
40945
  }
38732
40946
  async fetchSpans(spanType) {
38733
- const spans = await this.fetchFn(spanType, false);
40947
+ const spans = await this.fetchFn(
40948
+ normalizeSpanFilters(spanType ? { spanType } : void 0),
40949
+ false
40950
+ );
38734
40951
  for (const span of spans) {
38735
40952
  const type = span.span_attributes?.type ?? "";
38736
40953
  const existing = this.spanCache.get(type) ?? [];
@@ -38810,34 +41027,20 @@ var LocalTrace = class {
38810
41027
  */
38811
41028
  async getSpans({
38812
41029
  spanType,
41030
+ filters,
38813
41031
  includeScorers = false
38814
41032
  } = {}) {
41033
+ const normalizedFilters = normalizeSpanFilters(filters, spanType);
38815
41034
  const cachedSpans = this.state.spanCache.getByRootSpanId(this.rootSpanId);
38816
41035
  if (cachedSpans && cachedSpans.length > 0) {
38817
- let spans = includeScorers ? cachedSpans : cachedSpans.filter(
38818
- (span) => span.span_attributes?.purpose !== "scorer"
38819
- );
38820
- if (spanType && spanType.length > 0) {
38821
- spans = spans.filter(
38822
- (span) => spanType.includes(span.span_attributes?.type ?? "")
38823
- );
38824
- }
38825
- return spans.map((span) => ({
38826
- input: span.input,
38827
- output: span.output,
38828
- expected: span.expected,
38829
- error: span.error,
38830
- scores: span.scores,
38831
- metrics: span.metrics,
38832
- metadata: span.metadata,
38833
- span_id: span.span_id,
38834
- span_parents: span.span_parents,
38835
- is_root: span.is_root,
38836
- span_attributes: span.span_attributes,
38837
- tags: span.tags
38838
- }));
38839
- }
38840
- 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
+ });
38841
41044
  }
38842
41045
  /**
38843
41046
  * Get the thread (preprocessed messages) for this trace.
@@ -39257,7 +41460,7 @@ async function Eval(name, evaluator, reporterOrOpts) {
39257
41460
  data,
39258
41461
  { disabled: Boolean(options.parent || options.noSendLogs) }
39259
41462
  );
39260
- if (experiment && typeof process !== "undefined" && globalThis.BRAINTRUST_CONTEXT_MANAGER !== void 0) {
41463
+ if (experiment) {
39261
41464
  await experiment._waitForId();
39262
41465
  }
39263
41466
  if (experiment && options.onStart) {
@@ -39563,6 +41766,10 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
39563
41766
  } : void 0;
39564
41767
  const parsedDatumOrigin = ObjectReference.safeParse(datum.origin);
39565
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;
39566
41773
  const baseEvent = {
39567
41774
  name: "eval",
39568
41775
  spanAttributes: {
@@ -39573,7 +41780,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
39573
41780
  expected: "expected" in datum ? datum.expected : void 0,
39574
41781
  tags: datum.tags,
39575
41782
  origin,
39576
- ...datum.upsert_id ? { id: datum.upsert_id } : {}
41783
+ ...upsertId ? { id: upsertId } : {}
39577
41784
  }
39578
41785
  };
39579
41786
  const callback = async (rootSpan) => {