braintrust 3.32.0 → 3.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +0 -43
  2. package/dev/dist/index.d.mts +31 -0
  3. package/dev/dist/index.d.ts +31 -0
  4. package/dev/dist/index.js +2275 -920
  5. package/dev/dist/index.mjs +1610 -255
  6. package/dist/apply-auto-instrumentation.js +263 -224
  7. package/dist/apply-auto-instrumentation.mjs +45 -6
  8. package/dist/auto-instrumentations/bundler/esbuild.cjs +78 -5
  9. package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
  10. package/dist/auto-instrumentations/bundler/next.cjs +78 -5
  11. package/dist/auto-instrumentations/bundler/next.mjs +3 -3
  12. package/dist/auto-instrumentations/bundler/rollup.cjs +78 -5
  13. package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
  14. package/dist/auto-instrumentations/bundler/vite.cjs +78 -5
  15. package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
  16. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +78 -5
  17. package/dist/auto-instrumentations/bundler/webpack.cjs +78 -5
  18. package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
  19. package/dist/auto-instrumentations/{chunk-AFND2U7E.mjs → chunk-T2DMPWFI.mjs} +75 -5
  20. package/dist/auto-instrumentations/{chunk-RI4Y55ZF.mjs → chunk-UHJ2DNYJ.mjs} +6 -1
  21. package/dist/auto-instrumentations/{chunk-QEEPRBIS.mjs → chunk-W5QNG3PV.mjs} +1 -1
  22. package/dist/auto-instrumentations/hook.mjs +86 -7
  23. package/dist/auto-instrumentations/index.cjs +76 -5
  24. package/dist/auto-instrumentations/index.d.mts +3 -1
  25. package/dist/auto-instrumentations/index.d.ts +3 -1
  26. package/dist/auto-instrumentations/index.mjs +3 -1
  27. package/dist/browser.d.mts +202 -342
  28. package/dist/browser.d.ts +202 -342
  29. package/dist/browser.js +2586 -623
  30. package/dist/browser.mjs +2586 -623
  31. package/dist/chunk-7P6ASYW6.mjs +9 -0
  32. package/dist/{chunk-BTRLPQG5.js → chunk-AXJTOUOC.js} +2250 -1172
  33. package/dist/{chunk-AW4QECG5.js → chunk-G3VHOHRC.js} +40 -9
  34. package/dist/chunk-MLKGABMK.js +9 -0
  35. package/dist/{chunk-4QSAHP7D.mjs → chunk-MZLBAFVJ.mjs} +1236 -158
  36. package/dist/{chunk-WV6QZI2W.mjs → chunk-TZVZN2JJ.mjs} +39 -8
  37. package/dist/cli.js +1695 -293
  38. package/dist/custom-views.d.mts +112 -0
  39. package/dist/custom-views.d.ts +112 -0
  40. package/dist/custom-views.js +13 -0
  41. package/dist/custom-views.mjs +13 -0
  42. package/dist/edge-light.d.mts +1 -1
  43. package/dist/edge-light.d.ts +1 -1
  44. package/dist/edge-light.js +2586 -623
  45. package/dist/edge-light.mjs +2586 -623
  46. package/dist/index.d.mts +202 -342
  47. package/dist/index.d.ts +202 -342
  48. package/dist/index.js +1842 -986
  49. package/dist/index.mjs +1310 -454
  50. package/dist/instrumentation/index.d.mts +5 -245
  51. package/dist/instrumentation/index.d.ts +5 -245
  52. package/dist/instrumentation/index.js +1694 -254
  53. package/dist/instrumentation/index.mjs +1694 -254
  54. package/dist/vitest-evals-reporter.js +17 -16
  55. package/dist/vitest-evals-reporter.mjs +3 -2
  56. package/dist/workerd.d.mts +1 -1
  57. package/dist/workerd.d.ts +1 -1
  58. package/dist/workerd.js +2586 -623
  59. package/dist/workerd.mjs +2586 -623
  60. package/package.json +10 -2
@@ -38,8 +38,6 @@ __export(edge_light_exports, {
38
38
  BRAINTRUST_PARENT_KEY: () => BRAINTRUST_PARENT_KEY,
39
39
  BaseAttachment: () => BaseAttachment,
40
40
  BaseExperiment: () => BaseExperiment,
41
- BatchScorer: () => BatchScorer,
42
- BatchTask: () => BatchTask,
43
41
  BraintrustLangChainCallbackHandler: () => BraintrustLangChainCallbackHandler,
44
42
  BraintrustMiddleware: () => BraintrustMiddleware,
45
43
  BraintrustObservabilityExporter: () => BraintrustObservabilityExporter,
@@ -53,8 +51,6 @@ __export(edge_light_exports, {
53
51
  DEFAULT_MAX_REQUEST_SIZE: () => DEFAULT_MAX_REQUEST_SIZE,
54
52
  Dataset: () => Dataset2,
55
53
  DatasetPipeline: () => DatasetPipeline,
56
- DurableEvalMemoryStore: () => DurableEvalMemoryStore,
57
- DurableEvalRedisStore: () => DurableEvalRedisStore,
58
54
  ERR_PERMALINK: () => ERR_PERMALINK,
59
55
  Eval: () => Eval,
60
56
  EvalResultWithSummary: () => EvalResultWithSummary,
@@ -89,6 +85,10 @@ __export(edge_light_exports, {
89
85
  TestBackgroundLogger: () => TestBackgroundLogger,
90
86
  ToolBuilder: () => ToolBuilder,
91
87
  UUIDGenerator: () => UUIDGenerator,
88
+ WorkflowEvalMemoryStore: () => WorkflowEvalMemoryStore,
89
+ WorkflowEvalRedisStore: () => WorkflowEvalRedisStore,
90
+ WorkflowScorer: () => WorkflowScorer,
91
+ WorkflowTask: () => WorkflowTask,
92
92
  X_CACHED_HEADER: () => X_CACHED_HEADER,
93
93
  _exportsForTestingOnly: () => _exportsForTestingOnly,
94
94
  _internalGetGlobalState: () => _internalGetGlobalState,
@@ -114,12 +114,13 @@ __export(edge_light_exports, {
114
114
  deepCopyEvent: () => deepCopyEvent,
115
115
  default: () => exports_exports,
116
116
  defaultErrorScoreHandler: () => defaultErrorScoreHandler,
117
- defineDurableEval: () => defineDurableEval,
117
+ defineWorkflowEval: () => defineWorkflowEval,
118
118
  deserializePlainStringAsJSON: () => deserializePlainStringAsJSON,
119
119
  devNullWritableStream: () => devNullWritableStream,
120
120
  evaluatorDefinitionSchema: () => evaluatorDefinitionSchema,
121
121
  evaluatorDefinitionsSchema: () => evaluatorDefinitionsSchema,
122
122
  extractTraceContextFromHeaders: () => extractTraceContextFromHeaders,
123
+ failOpenAIAgentsTrace: () => failOpenAIAgentsTrace,
123
124
  flush: () => flush,
124
125
  getContextManager: () => getContextManager,
125
126
  getIdGenerator: () => getIdGenerator,
@@ -166,12 +167,14 @@ __export(edge_light_exports, {
166
167
  setFetch: () => setFetch,
167
168
  setMaskingFunction: () => setMaskingFunction,
168
169
  spanComponentsToObjectId: () => spanComponentsToObjectId,
170
+ startOpenAIAgentsTrace: () => startOpenAIAgentsTrace,
169
171
  startSpan: () => startSpan,
170
172
  summarize: () => summarize,
171
173
  templateRegistry: () => templateRegistry,
172
174
  toolFunctionDefinitionSchema: () => ToolFunctionDefinition,
173
175
  traceable: () => traceable,
174
176
  traced: () => traced,
177
+ updateOpenAIAgentsTrace: () => updateOpenAIAgentsTrace,
175
178
  updateSpan: () => updateSpan,
176
179
  uploadLogs3OverflowPayload: () => uploadLogs3OverflowPayload,
177
180
  utf8ByteLength: () => utf8ByteLength2,
@@ -200,6 +203,7 @@ __export(edge_light_exports, {
200
203
  wrapGroq: () => wrapGroq,
201
204
  wrapHuggingFace: () => wrapHuggingFace,
202
205
  wrapHuggingFaceTransformers: () => wrapHuggingFaceTransformers,
206
+ wrapLangGraphSDK: () => wrapLangGraphSDK,
203
207
  wrapLangSmithClient: () => wrapLangSmithClient,
204
208
  wrapLangSmithRunTrees: () => wrapLangSmithRunTrees,
205
209
  wrapLangSmithTraceable: () => wrapLangSmithTraceable,
@@ -5884,6 +5888,7 @@ var INSTRUMENTATION_NAMES = {
5884
5888
  LANGSMITH: "langsmith",
5885
5889
  MASTRA: "mastra",
5886
5890
  MISTRAL: "mistral",
5891
+ LANGGRAPH_SDK: "langgraph-sdk",
5887
5892
  OLLAMA: "ollama",
5888
5893
  OPENAI: "openai",
5889
5894
  OPENAI_AGENTS: "openai-agents",
@@ -5898,7 +5903,7 @@ var INSTRUMENTATION_NAMES = {
5898
5903
  var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
5899
5904
  "braintrust.spanInstrumentationName"
5900
5905
  );
5901
- var SDK_VERSION = true ? "3.32.0" : "0.0.0";
5906
+ var SDK_VERSION = true ? "3.33.0" : "0.0.0";
5902
5907
  function withSpanInstrumentationName(args, instrumentationName) {
5903
5908
  return {
5904
5909
  ...args,
@@ -9689,6 +9694,38 @@ function getSpanParentObjectAndPropagatedState(options) {
9689
9694
  function getSpanParentObject(options) {
9690
9695
  return getSpanParentObjectAndPropagatedState(options).parentObject;
9691
9696
  }
9697
+ function _internalExportParentSynchronously(parent) {
9698
+ if ("toStr" in parent) {
9699
+ return parent.toStr();
9700
+ }
9701
+ if ("getParentInfo" in parent) {
9702
+ const parentInfo = parent.getParentInfo();
9703
+ if (!parentInfo) {
9704
+ return void 0;
9705
+ }
9706
+ const objectId = parentInfo.objectId.getSync().value;
9707
+ if (!objectId && !parentInfo.computeObjectMetadataArgs) {
9708
+ return void 0;
9709
+ }
9710
+ return new SpanComponentsV4({
9711
+ object_type: parentInfo.objectType,
9712
+ ...objectId ? { object_id: objectId } : {
9713
+ compute_object_metadata_args: parentInfo.computeObjectMetadataArgs ?? {}
9714
+ },
9715
+ row_id: parent.id,
9716
+ root_span_id: parent.rootSpanId,
9717
+ span_id: parent.spanId
9718
+ }).toStr();
9719
+ }
9720
+ const components = braintrustParentToComponents(parent._getOtelParent());
9721
+ if (!components) {
9722
+ return void 0;
9723
+ }
9724
+ return new SpanComponentsV4({
9725
+ object_type: components.objectType,
9726
+ ...components.objectId ? { object_id: components.objectId } : { compute_object_metadata_args: components.computeArgs ?? {} }
9727
+ }).toStr();
9728
+ }
9692
9729
  function currentBraintrustParent(state) {
9693
9730
  const resolvedState = state ?? _globalState;
9694
9731
  const experiment = currentExperiment({ state: resolvedState });
@@ -11300,10 +11337,16 @@ var SpanImpl = class _SpanImpl {
11300
11337
  inject(carrier) {
11301
11338
  const resolvedCarrier = carrier ?? {};
11302
11339
  try {
11340
+ const braintrustParent = this._getOtelParent() ?? this._propagatedState?.braintrustParent;
11341
+ if (!braintrustParent) {
11342
+ debugLogger.forState(this._state).warn(
11343
+ "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."
11344
+ );
11345
+ }
11303
11346
  _injectIntoCarrier(resolvedCarrier, {
11304
11347
  traceId: this._rootSpanId,
11305
11348
  spanId: this._spanId,
11306
- braintrustParent: this._getOtelParent() ?? this._propagatedState?.braintrustParent,
11349
+ braintrustParent,
11307
11350
  propagatedState: this._propagatedState
11308
11351
  });
11309
11352
  } catch (e) {
@@ -13742,6 +13785,18 @@ function defineChannels(pkg, channels, options) {
13742
13785
  var openAIChannels = defineChannels(
13743
13786
  "openai",
13744
13787
  {
13788
+ agentsTraceStart: channel({
13789
+ channelName: "agents.trace.start",
13790
+ kind: "async"
13791
+ }),
13792
+ agentsTraceCapture: channel({
13793
+ channelName: "agents.trace.capture",
13794
+ kind: "async"
13795
+ }),
13796
+ agentsTraceFail: channel({
13797
+ channelName: "agents.trace.fail",
13798
+ kind: "async"
13799
+ }),
13745
13800
  filesCreateTraced: channel({
13746
13801
  channelName: "files.create-traced",
13747
13802
  kind: "async"
@@ -14110,6 +14165,23 @@ function getCachedMetricFromHeaders(headers) {
14110
14165
  return parseCachedHeader(headers.get(LEGACY_CACHED_HEADER));
14111
14166
  }
14112
14167
 
14168
+ // src/instrumentation/plugins/openai-manual-instrumentation-utils.ts
14169
+ async function deterministicDigest(namespace, ...parts) {
14170
+ const encoded = new TextEncoder().encode(
14171
+ [namespace, ...parts].map((part) => `${part.length}:${part}`).join("\0")
14172
+ );
14173
+ return new Uint8Array(
14174
+ await globalThis.crypto.subtle.digest("SHA-256", encoded)
14175
+ );
14176
+ }
14177
+ function digestHex(bytes, length) {
14178
+ return Array.from(bytes.slice(0, length)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
14179
+ }
14180
+ function digestUuid(bytes) {
14181
+ const hex = digestHex(bytes, 16);
14182
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
14183
+ }
14184
+
14113
14185
  // src/instrumentation/plugins/openai-batch-instrumentation.ts
14114
14186
  var SUPPORTED_ENDPOINTS = /* @__PURE__ */ new Set(["/v1/chat/completions", "/v1/responses"]);
14115
14187
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
@@ -14150,21 +14222,6 @@ async function exportParent(parent) {
14150
14222
  }
14151
14223
  return void 0;
14152
14224
  }
14153
- async function deterministicDigest(namespace, ...parts) {
14154
- const encoded = new TextEncoder().encode(
14155
- [namespace, ...parts].map((part) => `${part.length}:${part}`).join("\0")
14156
- );
14157
- return new Uint8Array(
14158
- await globalThis.crypto.subtle.digest("SHA-256", encoded)
14159
- );
14160
- }
14161
- function digestHex(bytes, length) {
14162
- return Array.from(bytes.slice(0, length)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
14163
- }
14164
- function digestUuid(bytes) {
14165
- const hex = digestHex(bytes, 16);
14166
- return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
14167
- }
14168
14225
  async function batchSpanIds(inputFileId) {
14169
14226
  const [row, span, root] = await Promise.all([
14170
14227
  deterministicDigest("openai:batch:row", inputFileId),
@@ -14655,6 +14712,628 @@ var interceptOpenAIBatchTraceComplete = (target, thisArg, args) => Promise.resol
14655
14712
  return result;
14656
14713
  });
14657
14714
 
14715
+ // src/instrumentation/plugins/openai-agents-api-instrumentation.ts
14716
+ var TERMINAL_TURN_EVENTS = /* @__PURE__ */ new Set([
14717
+ "agent.session.turn.completed",
14718
+ "agent.session.turn.failed",
14719
+ "agent.session.turn.cancelled"
14720
+ ]);
14721
+ var TURN_LIFECYCLE_EVENTS = /* @__PURE__ */ new Set([
14722
+ "agent.session.turn.created",
14723
+ "agent.session.turn.in_progress",
14724
+ ...TERMINAL_TURN_EVENTS
14725
+ ]);
14726
+ var SESSION_EVENTS = /* @__PURE__ */ new Set([
14727
+ "agent.session.created",
14728
+ "agent.session.failed",
14729
+ "agent.session.idle",
14730
+ "agent.session.in_progress",
14731
+ "agent.session.requires_action"
14732
+ ]);
14733
+ var SUBAGENT_EVENTS = /* @__PURE__ */ new Set([
14734
+ "agent.session.subagent.active",
14735
+ "agent.session.subagent.closed",
14736
+ "agent.session.subagent.created"
14737
+ ]);
14738
+ function read2(value, key) {
14739
+ if (!isObject(value)) {
14740
+ return void 0;
14741
+ }
14742
+ try {
14743
+ return Reflect.get(value, key);
14744
+ } catch {
14745
+ return void 0;
14746
+ }
14747
+ }
14748
+ function stringValue(value) {
14749
+ return typeof value === "string" && value.length > 0 ? value : void 0;
14750
+ }
14751
+ function recordValue(record, key) {
14752
+ return Object.hasOwn(record, key) ? record[key] : void 0;
14753
+ }
14754
+ function setRecordValue(record, key, value) {
14755
+ Object.defineProperty(record, key, {
14756
+ configurable: true,
14757
+ enumerable: true,
14758
+ value,
14759
+ writable: true
14760
+ });
14761
+ }
14762
+ function loggedError(value, fallback2) {
14763
+ if (value instanceof Error) {
14764
+ return value;
14765
+ }
14766
+ const message = stringValue(read2(value, "message"));
14767
+ return new Error(message ?? (typeof value === "string" ? value : fallback2));
14768
+ }
14769
+ function logInstrumentationError(context, error) {
14770
+ debugLogger.debug(`OpenAI Agents API instrumentation ${context}:`, error);
14771
+ }
14772
+ async function childSpanIds2(rootKey, kind, providerId) {
14773
+ const [row, span] = await Promise.all([
14774
+ deterministicDigest("openai:agents:row", rootKey, kind, providerId),
14775
+ deterministicDigest("openai:agents:span", rootKey, kind, providerId)
14776
+ ]);
14777
+ return { rowId: digestUuid(row), spanId: digestHex(span, 8) };
14778
+ }
14779
+ function traceMetadata(args) {
14780
+ const metadata = {};
14781
+ const suppliedMetadata = read2(args, "metadata");
14782
+ if (isObject(suppliedMetadata)) {
14783
+ try {
14784
+ for (const key of Object.keys(suppliedMetadata)) {
14785
+ metadata[key] = read2(suppliedMetadata, key);
14786
+ }
14787
+ } catch (error) {
14788
+ logInstrumentationError("could not read supplied metadata", error);
14789
+ }
14790
+ }
14791
+ const agent = read2(args, "agent");
14792
+ const agentId = stringValue(read2(agent, "id")) ?? stringValue(read2(args, "agent_id"));
14793
+ const agentName = stringValue(read2(agent, "name"));
14794
+ const model = stringValue(read2(agent, "model"));
14795
+ return {
14796
+ ...metadata,
14797
+ api: "agents",
14798
+ ...agentId ? { agent_id: agentId } : {},
14799
+ ...agentName ? { agent_name: agentName } : {},
14800
+ ...model ? { model } : {},
14801
+ provider: "openai"
14802
+ };
14803
+ }
14804
+ function copyState(state) {
14805
+ return {
14806
+ ...state,
14807
+ callItems: { ...state.callItems },
14808
+ eventIds: [...state.eventIds],
14809
+ openTools: { ...state.openTools },
14810
+ subagents: { ...state.subagents },
14811
+ turnSubagents: { ...state.turnSubagents }
14812
+ };
14813
+ }
14814
+ function startRootSpan(state) {
14815
+ const root = SpanComponentsV4.fromStr(state.root);
14816
+ const parent = SpanComponentsV4.fromStr(state.rootParent);
14817
+ const rowId = stringValue(root.data.row_id);
14818
+ const rootSpanId = stringValue(root.data.root_span_id);
14819
+ const spanId = stringValue(root.data.span_id);
14820
+ if (!rowId || !rootSpanId || !spanId) {
14821
+ throw new Error("OpenAI Agents trace root is invalid");
14822
+ }
14823
+ const hasParentSpan = Boolean(
14824
+ parent.data.row_id && parent.data.span_id && parent.data.root_span_id
14825
+ );
14826
+ return withCurrent(
14827
+ NOOP_SPAN,
14828
+ () => _internalStartSpanWithInitialMergeAndParentSpanIds(
14829
+ withSpanInstrumentationName(
14830
+ {
14831
+ name: "openai.agents.turn",
14832
+ type: "task" /* TASK */,
14833
+ parent: state.rootParent,
14834
+ ...!hasParentSpan ? {
14835
+ parentSpanIds: {
14836
+ parentSpanIds: [],
14837
+ rootSpanId
14838
+ }
14839
+ } : {},
14840
+ spanId,
14841
+ startTime: state.startTime,
14842
+ event: { id: rowId }
14843
+ },
14844
+ INSTRUMENTATION_NAMES.OPENAI
14845
+ )
14846
+ )
14847
+ );
14848
+ }
14849
+ async function startSubagentSpan(state, subagentId, input, metadata, visiting = /* @__PURE__ */ new Set()) {
14850
+ const subagent = recordValue(state.subagents, subagentId);
14851
+ let parent = state.root;
14852
+ if (subagent?.parentAgentId && subagent.parentAgentId !== subagentId && recordValue(state.subagents, subagent.parentAgentId) && !visiting.has(subagent.parentAgentId)) {
14853
+ visiting.add(subagentId);
14854
+ parent = await (await startSubagentSpan(
14855
+ state,
14856
+ subagent.parentAgentId,
14857
+ void 0,
14858
+ void 0,
14859
+ visiting
14860
+ )).export();
14861
+ }
14862
+ const ids = await childSpanIds2(state.rootKey, "subagent", subagentId);
14863
+ return withCurrent(
14864
+ NOOP_SPAN,
14865
+ () => _internalStartSpanWithInitialMerge(
14866
+ withSpanInstrumentationName(
14867
+ {
14868
+ name: "openai.agents.subagent",
14869
+ type: "task" /* TASK */,
14870
+ parent,
14871
+ spanId: ids.spanId,
14872
+ startTime: subagent?.openedAt,
14873
+ event: {
14874
+ id: ids.rowId,
14875
+ ...input !== void 0 ? { input } : {},
14876
+ metadata: {
14877
+ ...metadata,
14878
+ agent_id: subagentId,
14879
+ ...subagent?.parentAgentId ? { parent_agent_id: subagent.parentAgentId } : {},
14880
+ provider: "openai"
14881
+ }
14882
+ }
14883
+ },
14884
+ INSTRUMENTATION_NAMES.OPENAI
14885
+ )
14886
+ )
14887
+ );
14888
+ }
14889
+ async function parentForTurn(state, turnId) {
14890
+ const subagentId = turnId ? recordValue(state.turnSubagents, turnId) : void 0;
14891
+ if (!subagentId) {
14892
+ return state.root;
14893
+ }
14894
+ return await (await startSubagentSpan(state, subagentId)).export();
14895
+ }
14896
+ async function startToolSpan(state, tool, input) {
14897
+ const ids = await childSpanIds2(state.rootKey, "tool", tool.itemId);
14898
+ return withCurrent(
14899
+ NOOP_SPAN,
14900
+ async () => _internalStartSpanWithInitialMerge(
14901
+ withSpanInstrumentationName(
14902
+ {
14903
+ name: tool.name,
14904
+ type: "tool" /* TOOL */,
14905
+ parent: await parentForTurn(state, tool.turnId),
14906
+ spanId: ids.spanId,
14907
+ startTime: tool.startTime,
14908
+ event: {
14909
+ id: ids.rowId,
14910
+ ...input !== void 0 ? { input } : {},
14911
+ metadata: {
14912
+ item_id: tool.itemId,
14913
+ provider: "openai",
14914
+ tool_type: tool.toolType,
14915
+ ...tool.turnId ? { turn_id: tool.turnId } : {}
14916
+ }
14917
+ }
14918
+ },
14919
+ INSTRUMENTATION_NAMES.OPENAI
14920
+ )
14921
+ )
14922
+ );
14923
+ }
14924
+ function toolFromItem(item, observedAt) {
14925
+ const itemId = stringValue(read2(item, "id"));
14926
+ const toolType = stringValue(read2(item, "type"));
14927
+ if (!itemId || !toolType) {
14928
+ return void 0;
14929
+ }
14930
+ const turnId = stringValue(read2(item, "turn_id"));
14931
+ switch (toolType) {
14932
+ case "function_call":
14933
+ return {
14934
+ input: read2(item, "arguments"),
14935
+ tool: {
14936
+ itemId,
14937
+ name: stringValue(read2(item, "name")) ?? "Function call",
14938
+ startTime: observedAt,
14939
+ toolType,
14940
+ ...turnId ? { turnId } : {}
14941
+ }
14942
+ };
14943
+ case "mcp_call": {
14944
+ const name = stringValue(read2(item, "name")) ?? "MCP call";
14945
+ const server = stringValue(read2(item, "server_label"));
14946
+ return {
14947
+ input: read2(item, "arguments"),
14948
+ tool: {
14949
+ itemId,
14950
+ name: server ? `${server}.${name}` : name,
14951
+ startTime: observedAt,
14952
+ toolType,
14953
+ ...turnId ? { turnId } : {}
14954
+ }
14955
+ };
14956
+ }
14957
+ case "web_search_call":
14958
+ return {
14959
+ input: read2(item, "action"),
14960
+ tool: {
14961
+ itemId,
14962
+ name: "Web search",
14963
+ startTime: observedAt,
14964
+ toolType,
14965
+ ...turnId ? { turnId } : {}
14966
+ }
14967
+ };
14968
+ case "command_execution":
14969
+ return {
14970
+ input: {
14971
+ command: read2(item, "command"),
14972
+ cwd: read2(item, "cwd")
14973
+ },
14974
+ tool: {
14975
+ itemId,
14976
+ name: "Command execution",
14977
+ startTime: observedAt,
14978
+ toolType,
14979
+ ...turnId ? { turnId } : {}
14980
+ }
14981
+ };
14982
+ default:
14983
+ return void 0;
14984
+ }
14985
+ }
14986
+ function textFromContent(content) {
14987
+ if (!Array.isArray(content)) {
14988
+ return void 0;
14989
+ }
14990
+ const text = [];
14991
+ for (const part of content) {
14992
+ const partText = read2(part, "text");
14993
+ if (read2(part, "type") === "output_text" && typeof partText === "string") {
14994
+ text.push(partText);
14995
+ }
14996
+ }
14997
+ return text.length > 0 ? text.join("") : void 0;
14998
+ }
14999
+ function toolOutput(item, toolType) {
15000
+ switch (toolType) {
15001
+ case "function_call":
15002
+ return read2(item, "output");
15003
+ case "mcp_call":
15004
+ return read2(item, "output");
15005
+ case "web_search_call":
15006
+ return read2(item, "action");
15007
+ case "command_execution":
15008
+ return read2(item, "output");
15009
+ default:
15010
+ return void 0;
15011
+ }
15012
+ }
15013
+ function toolFailed(item, toolType) {
15014
+ const status = read2(item, "status");
15015
+ const explicitError = read2(item, "error");
15016
+ if (explicitError !== void 0 && explicitError !== null) {
15017
+ return loggedError(explicitError, `OpenAI ${toolType} failed`);
15018
+ }
15019
+ if (status === "failed" || status === "incomplete") {
15020
+ return new Error(`OpenAI ${toolType} ${status}`);
15021
+ }
15022
+ if (toolType === "command_execution" && typeof read2(item, "exit_code") === "number" && read2(item, "exit_code") !== 0) {
15023
+ return new Error(
15024
+ `OpenAI command exited with code ${read2(item, "exit_code")}`
15025
+ );
15026
+ }
15027
+ return void 0;
15028
+ }
15029
+ async function completeTool(state, tool, item, endTime) {
15030
+ const span = await startToolSpan(state, tool);
15031
+ const output = toolOutput(item, tool.toolType);
15032
+ const error = toolFailed(item, tool.toolType);
15033
+ span.log({
15034
+ ...output !== void 0 ? { output } : {},
15035
+ ...error ? { error } : {},
15036
+ metadata: {
15037
+ status: read2(item, "status"),
15038
+ ...tool.toolType === "command_execution" ? { exit_code: read2(item, "exit_code") } : {}
15039
+ }
15040
+ });
15041
+ span.end({ endTime });
15042
+ Reflect.deleteProperty(state.openTools, tool.itemId);
15043
+ }
15044
+ async function captureMessage(state, item) {
15045
+ if (read2(item, "type") !== "message" || read2(item, "role") !== "assistant" || read2(item, "phase") !== "final_answer") {
15046
+ return;
15047
+ }
15048
+ const output = textFromContent(read2(item, "content"));
15049
+ if (output === void 0) {
15050
+ return;
15051
+ }
15052
+ const turnId = stringValue(read2(item, "turn_id"));
15053
+ const subagentId = turnId ? recordValue(state.turnSubagents, turnId) : void 0;
15054
+ if (subagentId) {
15055
+ (await startSubagentSpan(state, subagentId)).log({ output });
15056
+ } else {
15057
+ startRootSpan(state).log({ output });
15058
+ }
15059
+ }
15060
+ async function captureItem(state, item, isDone, observedAt) {
15061
+ await captureMessage(state, item);
15062
+ const itemType = stringValue(read2(item, "type"));
15063
+ if (itemType === "function_call_output") {
15064
+ const callId = stringValue(read2(item, "call_id"));
15065
+ const itemId = callId ? recordValue(state.callItems, callId) : void 0;
15066
+ const tool2 = itemId ? recordValue(state.openTools, itemId) : void 0;
15067
+ if (tool2) {
15068
+ await completeTool(state, tool2, item, observedAt);
15069
+ }
15070
+ return;
15071
+ }
15072
+ const descriptor = toolFromItem(item, observedAt);
15073
+ if (!descriptor) {
15074
+ return;
15075
+ }
15076
+ const existing = recordValue(state.openTools, descriptor.tool.itemId);
15077
+ const tool = existing ?? descriptor.tool;
15078
+ setRecordValue(state.openTools, tool.itemId, tool);
15079
+ if (itemType === "function_call") {
15080
+ const callId = stringValue(read2(item, "call_id"));
15081
+ if (callId) {
15082
+ setRecordValue(state.callItems, callId, tool.itemId);
15083
+ }
15084
+ }
15085
+ await startToolSpan(state, tool, descriptor.input);
15086
+ const status = read2(item, "status");
15087
+ const terminalFunctionCall = itemType === "function_call" && (status === "failed" || status === "incomplete");
15088
+ if (itemType !== "function_call" && (isDone || status !== "in_progress") || terminalFunctionCall) {
15089
+ await completeTool(state, tool, item, observedAt);
15090
+ }
15091
+ }
15092
+ function updateSessionMetadata(state, session) {
15093
+ const sessionId = stringValue(read2(session, "id"));
15094
+ const agent = read2(session, "agent");
15095
+ startRootSpan(state).log({
15096
+ metadata: {
15097
+ ...sessionId ? { session_id: sessionId } : {},
15098
+ ...stringValue(read2(agent, "id")) ? { agent_id: read2(agent, "id") } : {},
15099
+ ...stringValue(read2(agent, "name")) ? { agent_name: read2(agent, "name") } : {},
15100
+ ...stringValue(read2(agent, "model")) ? { model: read2(agent, "model") } : {}
15101
+ }
15102
+ });
15103
+ }
15104
+ async function captureSubagent(state, eventType, subagent, observedAt) {
15105
+ const subagentId = stringValue(read2(subagent, "id"));
15106
+ if (!subagentId) {
15107
+ return;
15108
+ }
15109
+ const existing = recordValue(state.subagents, subagentId);
15110
+ const observedOpenedAt = read2(subagent, "opened_at");
15111
+ const openedAt = typeof observedOpenedAt === "number" && Number.isFinite(observedOpenedAt) && observedOpenedAt >= 0 ? observedOpenedAt : existing?.openedAt ?? observedAt;
15112
+ const observedClosedAt = read2(subagent, "closed_at");
15113
+ const closedAt = typeof observedClosedAt === "number" && Number.isFinite(observedClosedAt) && observedClosedAt >= 0 ? observedClosedAt : existing?.closedAt;
15114
+ const parentAgentId = stringValue(read2(subagent, "parent_agent_id")) ?? existing?.parentAgentId;
15115
+ setRecordValue(state.subagents, subagentId, {
15116
+ ...closedAt !== void 0 ? { closedAt } : {},
15117
+ openedAt,
15118
+ ...parentAgentId ? { parentAgentId } : {}
15119
+ });
15120
+ const span = await startSubagentSpan(
15121
+ state,
15122
+ subagentId,
15123
+ read2(subagent, "instructions"),
15124
+ {
15125
+ ...stringValue(read2(subagent, "name")) ? { agent_name: read2(subagent, "name") } : {},
15126
+ status: read2(subagent, "status")
15127
+ }
15128
+ );
15129
+ if (eventType === "agent.session.subagent.closed") {
15130
+ span.end({ endTime: closedAt ?? observedAt });
15131
+ }
15132
+ }
15133
+ async function closeTrace(state, endTime, error, usage) {
15134
+ if (state.ended) {
15135
+ return;
15136
+ }
15137
+ for (const tool of Object.values(state.openTools)) {
15138
+ const span = await startToolSpan(state, tool);
15139
+ span.log({
15140
+ error: error ?? new Error("OpenAI Agents turn ended before tool completion")
15141
+ });
15142
+ span.end({ endTime });
15143
+ }
15144
+ state.openTools = {};
15145
+ for (const subagentId of Object.keys(state.subagents)) {
15146
+ const subagent = state.subagents[subagentId];
15147
+ const span = await startSubagentSpan(state, subagentId);
15148
+ span.end({ endTime: subagent.closedAt ?? endTime });
15149
+ }
15150
+ const root = startRootSpan(state);
15151
+ root.log({
15152
+ ...error ? { error } : {},
15153
+ metrics: parseMetricsFromUsage(usage)
15154
+ });
15155
+ root.end({ endTime });
15156
+ state.ended = true;
15157
+ }
15158
+ async function captureTurnLifecycle(state, event, eventType, observedAt) {
15159
+ const turn = read2(event, "turn");
15160
+ const turnId = stringValue(read2(event, "turn_id")) ?? stringValue(read2(turn, "id"));
15161
+ const subagentId = stringValue(read2(turn, "subagent_id"));
15162
+ if (turnId && subagentId) {
15163
+ setRecordValue(state.turnSubagents, turnId, subagentId);
15164
+ if (!recordValue(state.subagents, subagentId)) {
15165
+ const createdAt = read2(turn, "created_at");
15166
+ setRecordValue(state.subagents, subagentId, {
15167
+ openedAt: typeof createdAt === "number" && Number.isFinite(createdAt) && createdAt >= 0 ? createdAt : observedAt
15168
+ });
15169
+ }
15170
+ await startSubagentSpan(state, subagentId);
15171
+ }
15172
+ const sessionId = stringValue(read2(event, "session_id"));
15173
+ if (sessionId) {
15174
+ startRootSpan(state).log({ metadata: { session_id: sessionId } });
15175
+ }
15176
+ if (!TERMINAL_TURN_EVENTS.has(eventType) || subagentId) {
15177
+ if (subagentId && eventType === "agent.session.turn.failed") {
15178
+ (await startSubagentSpan(state, subagentId)).log({
15179
+ error: loggedError(read2(turn, "error"), "OpenAI subagent turn failed")
15180
+ });
15181
+ }
15182
+ return;
15183
+ }
15184
+ const completedAt = read2(turn, "completed_at");
15185
+ const endTime = typeof completedAt === "number" && Number.isFinite(completedAt) && completedAt >= 0 ? completedAt : observedAt;
15186
+ const usage = read2(event, "usage") ?? read2(turn, "usage");
15187
+ const error = eventType === "agent.session.turn.completed" ? void 0 : loggedError(
15188
+ read2(turn, "error"),
15189
+ eventType === "agent.session.turn.cancelled" ? "OpenAI Agents turn cancelled" : "OpenAI Agents turn failed"
15190
+ );
15191
+ await closeTrace(state, endTime, error, usage);
15192
+ }
15193
+ async function captureEvent(state, event) {
15194
+ if (state.ended) {
15195
+ return state;
15196
+ }
15197
+ const eventType = stringValue(read2(event, "type"));
15198
+ const eventId = stringValue(read2(event, "event_id"));
15199
+ if (!eventType || eventId && state.eventIds.includes(eventId)) {
15200
+ return state;
15201
+ }
15202
+ const next = copyState(state);
15203
+ const observedAt = getCurrentUnixTimestamp();
15204
+ let handled = false;
15205
+ if (SESSION_EVENTS.has(eventType)) {
15206
+ const session = read2(event, "session");
15207
+ if (session) {
15208
+ updateSessionMetadata(next, session);
15209
+ }
15210
+ handled = true;
15211
+ }
15212
+ if (eventType === "agent.session.turn.item.added") {
15213
+ await captureItem(next, read2(event, "item"), false, observedAt);
15214
+ handled = true;
15215
+ } else if (eventType === "agent.session.turn.item.done") {
15216
+ await captureItem(next, read2(event, "item"), true, observedAt);
15217
+ handled = true;
15218
+ } else if (TURN_LIFECYCLE_EVENTS.has(eventType)) {
15219
+ await captureTurnLifecycle(next, event, eventType, observedAt);
15220
+ handled = true;
15221
+ } else if (SUBAGENT_EVENTS.has(eventType)) {
15222
+ await captureSubagent(next, eventType, read2(event, "subagent"), observedAt);
15223
+ handled = true;
15224
+ } else if (eventType === "agent.session.turn.output_text.delta" && next.firstTokenAt === void 0 && stringValue(read2(event, "delta"))) {
15225
+ next.firstTokenAt = observedAt;
15226
+ startRootSpan(next).log({
15227
+ metrics: { time_to_first_token: observedAt - next.startTime }
15228
+ });
15229
+ handled = true;
15230
+ } else if (eventType === "agent.session.failed") {
15231
+ const session = read2(event, "session");
15232
+ const lastActiveAt = read2(session, "last_active_at");
15233
+ const endTime = typeof lastActiveAt === "number" && Number.isFinite(lastActiveAt) && lastActiveAt >= 0 ? lastActiveAt : observedAt;
15234
+ await closeTrace(
15235
+ next,
15236
+ endTime,
15237
+ loggedError(read2(session, "error"), "OpenAI Agents session failed"),
15238
+ read2(session, "usage")
15239
+ );
15240
+ handled = true;
15241
+ } else if (eventType === "error") {
15242
+ await closeTrace(
15243
+ next,
15244
+ observedAt,
15245
+ loggedError(read2(event, "error"), "OpenAI Agents session failed")
15246
+ );
15247
+ handled = true;
15248
+ }
15249
+ if (!handled) {
15250
+ return state;
15251
+ }
15252
+ if (eventId) {
15253
+ next.eventIds.push(eventId);
15254
+ }
15255
+ return next;
15256
+ }
15257
+ var interceptOpenAIAgentsTraceStart = async (target, thisArg, args) => {
15258
+ const fallback2 = await Reflect.apply(target, thisArg, args);
15259
+ try {
15260
+ const state = args[0].state;
15261
+ const parent = state.rootParent;
15262
+ const traceArgs = args[0].args;
15263
+ const parentComponents = SpanComponentsV4.fromStr(parent);
15264
+ const hasParentSpan = Boolean(
15265
+ parentComponents.data.row_id && parentComponents.data.span_id && parentComponents.data.root_span_id
15266
+ );
15267
+ const rootComponents = SpanComponentsV4.fromStr(state.root);
15268
+ const rowId = stringValue(rootComponents.data.row_id);
15269
+ const rootSpanId = stringValue(rootComponents.data.root_span_id);
15270
+ const spanId = stringValue(rootComponents.data.span_id);
15271
+ if (!rowId || !rootSpanId || !spanId) {
15272
+ throw new Error("OpenAI Agents trace root is invalid");
15273
+ }
15274
+ withCurrent(
15275
+ NOOP_SPAN,
15276
+ () => _internalStartSpanWithInitialMergeAndParentSpanIds(
15277
+ withSpanInstrumentationName(
15278
+ {
15279
+ name: "openai.agents.turn",
15280
+ type: "task" /* TASK */,
15281
+ parent,
15282
+ ...!hasParentSpan ? {
15283
+ parentSpanIds: {
15284
+ parentSpanIds: [],
15285
+ rootSpanId
15286
+ }
15287
+ } : {},
15288
+ spanId,
15289
+ startTime: state.startTime,
15290
+ event: {
15291
+ id: rowId,
15292
+ input: read2(traceArgs, "input"),
15293
+ metadata: traceMetadata(traceArgs)
15294
+ }
15295
+ },
15296
+ INSTRUMENTATION_NAMES.OPENAI
15297
+ )
15298
+ )
15299
+ );
15300
+ return state;
15301
+ } catch (error) {
15302
+ logInstrumentationError("could not start trace", error);
15303
+ return fallback2;
15304
+ }
15305
+ };
15306
+ var interceptOpenAIAgentsTraceCapture = async (target, thisArg, args) => {
15307
+ const fallback2 = await Reflect.apply(target, thisArg, args);
15308
+ if (!args[0].state) {
15309
+ return fallback2;
15310
+ }
15311
+ try {
15312
+ return await captureEvent(args[0].state, args[0].event);
15313
+ } catch (error) {
15314
+ logInstrumentationError("could not capture event", error);
15315
+ return fallback2;
15316
+ }
15317
+ };
15318
+ var interceptOpenAIAgentsTraceFail = async (target, thisArg, args) => {
15319
+ const fallback2 = await Reflect.apply(target, thisArg, args);
15320
+ if (!args[0].state) {
15321
+ return fallback2;
15322
+ }
15323
+ try {
15324
+ const next = copyState(args[0].state);
15325
+ await closeTrace(
15326
+ next,
15327
+ getCurrentUnixTimestamp(),
15328
+ loggedError(args[0].error, "OpenAI Agents request failed")
15329
+ );
15330
+ return next;
15331
+ } catch (error) {
15332
+ logInstrumentationError("could not fail trace", error);
15333
+ return fallback2;
15334
+ }
15335
+ };
15336
+
14658
15337
  // src/instrumentation/plugins/openai-plugin.ts
14659
15338
  var OpenAIPlugin = class extends BasePlugin {
14660
15339
  constructor() {
@@ -14662,6 +15341,13 @@ var OpenAIPlugin = class extends BasePlugin {
14662
15341
  }
14663
15342
  onEnable() {
14664
15343
  this.unsubscribers.push(
15344
+ openAIChannels.agentsTraceStart.intercept(
15345
+ interceptOpenAIAgentsTraceStart
15346
+ ),
15347
+ openAIChannels.agentsTraceCapture.intercept(
15348
+ interceptOpenAIAgentsTraceCapture
15349
+ ),
15350
+ openAIChannels.agentsTraceFail.intercept(interceptOpenAIAgentsTraceFail),
14665
15351
  openAIChannels.filesCreateTraced.intercept(
14666
15352
  interceptOpenAIFilesCreateTraced
14667
15353
  ),
@@ -15222,7 +15908,7 @@ async function* patchCodexEventStream(events, state) {
15222
15908
  try {
15223
15909
  await handleCodexEvent(state, event);
15224
15910
  } catch (error) {
15225
- logInstrumentationError("OpenAI Codex stream event", error);
15911
+ logInstrumentationError2("OpenAI Codex stream event", error);
15226
15912
  }
15227
15913
  yield event;
15228
15914
  }
@@ -15722,10 +16408,10 @@ function safeLog(span, event) {
15722
16408
  try {
15723
16409
  span.log(event);
15724
16410
  } catch (error) {
15725
- logInstrumentationError("OpenAI Codex span log", error);
16411
+ logInstrumentationError2("OpenAI Codex span log", error);
15726
16412
  }
15727
16413
  }
15728
- function logInstrumentationError(context, error) {
16414
+ function logInstrumentationError2(context, error) {
15729
16415
  debugLogger.error(`Error processing ${context}:`, error);
15730
16416
  }
15731
16417
 
@@ -17120,27 +17806,8 @@ function continuationParentFromCreateSessionParams(params) {
17120
17806
  }
17121
17807
  return context.parent;
17122
17808
  }
17123
- function exportSpanSynchronously(span) {
17124
- const parentInfo = span.getParentInfo();
17125
- if (!parentInfo) {
17126
- return void 0;
17127
- }
17128
- const objectId = parentInfo.objectId.getSync().value;
17129
- if (!objectId && !parentInfo.computeObjectMetadataArgs) {
17130
- return void 0;
17131
- }
17132
- return new SpanComponentsV4({
17133
- object_type: parentInfo.objectType,
17134
- ...objectId ? { object_id: objectId } : {
17135
- compute_object_metadata_args: parentInfo.computeObjectMetadataArgs ?? {}
17136
- },
17137
- row_id: span.id,
17138
- root_span_id: span.rootSpanId,
17139
- span_id: span.spanId
17140
- }).toStr();
17141
- }
17142
17809
  function exportedParent(parent) {
17143
- return typeof parent === "string" ? parent : exportSpanSynchronously(parent);
17810
+ return typeof parent === "string" ? parent : _internalExportParentSynchronously(parent);
17144
17811
  }
17145
17812
  function addSerializedContext(args) {
17146
17813
  if (!isObject(args.continuation) || args.sessionId === void 0) {
@@ -17897,16 +18564,16 @@ function braintrustAISDKTelemetry() {
17897
18564
  if (!toolCallId || !state) {
17898
18565
  return;
17899
18566
  }
17900
- const toolOutput = event.toolOutput;
18567
+ const toolOutput2 = event.toolOutput;
17901
18568
  const workflowToolError = event.success === false && "error" in event ? event.error : void 0;
17902
- if (toolOutput?.type === "tool-error" || workflowToolError !== void 0) {
17903
- const error = toolOutput?.error ?? workflowToolError;
18569
+ if (toolOutput2?.type === "tool-error" || workflowToolError !== void 0) {
18570
+ const error = toolOutput2?.error ?? workflowToolError;
17904
18571
  state.span.log({
17905
18572
  error: error instanceof Error ? error.message : String(error),
17906
18573
  metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
17907
18574
  });
17908
18575
  } else {
17909
- const output = toolOutput && "output" in toolOutput ? toolOutput.output : event.output;
18576
+ const output = toolOutput2 && "output" in toolOutput2 ? toolOutput2.output : event.output;
17910
18577
  state.span.log({
17911
18578
  ...shouldRecordOutputs(event) ? { output } : {},
17912
18579
  metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
@@ -20365,9 +21032,9 @@ function patchAISDKStreamingResult(args) {
20365
21032
  }
20366
21033
  finalize({ metrics, output });
20367
21034
  } catch (error) {
20368
- const loggedError = toLoggedError(error);
21035
+ const loggedError2 = toLoggedError(error);
20369
21036
  try {
20370
- span.log({ error: loggedError });
21037
+ span.log({ error: loggedError2 });
20371
21038
  } catch (loggingError) {
20372
21039
  debugLogger.error(
20373
21040
  "Error logging AI SDK streaming failure:",
@@ -20375,7 +21042,7 @@ function patchAISDKStreamingResult(args) {
20375
21042
  );
20376
21043
  }
20377
21044
  finalize({
20378
- error: error instanceof Error ? error : new Error(String(loggedError))
21045
+ error: error instanceof Error ? error : new Error(String(loggedError2))
20379
21046
  });
20380
21047
  }
20381
21048
  };
@@ -20488,9 +21155,9 @@ function patchAISDKStreamingResult(args) {
20488
21155
  }
20489
21156
  controller.enqueue(value);
20490
21157
  } catch (error) {
20491
- const loggedError = toLoggedError(error);
21158
+ const loggedError2 = toLoggedError(error);
20492
21159
  try {
20493
- span.log({ error: loggedError });
21160
+ span.log({ error: loggedError2 });
20494
21161
  } catch (loggingError) {
20495
21162
  debugLogger.error(
20496
21163
  "Error logging AI SDK base stream failure:",
@@ -20498,7 +21165,7 @@ function patchAISDKStreamingResult(args) {
20498
21165
  );
20499
21166
  }
20500
21167
  finalize({
20501
- error: error instanceof Error ? error : new Error(String(loggedError))
21168
+ error: error instanceof Error ? error : new Error(String(loggedError2))
20502
21169
  });
20503
21170
  controller.error(error);
20504
21171
  }
@@ -23392,7 +24059,7 @@ function wrapSendOptionsCallbacks(options, state) {
23392
24059
  try {
23393
24060
  await handleInteractionUpdate(state, args.update);
23394
24061
  } catch (error) {
23395
- logInstrumentationError2("Cursor SDK onDelta", error);
24062
+ logInstrumentationError3("Cursor SDK onDelta", error);
23396
24063
  }
23397
24064
  if (originalOnDelta) {
23398
24065
  return originalOnDelta(args);
@@ -23402,7 +24069,7 @@ function wrapSendOptionsCallbacks(options, state) {
23402
24069
  try {
23403
24070
  handleStepUpdate(state, args.step);
23404
24071
  } catch (error) {
23405
- logInstrumentationError2("Cursor SDK onStep", error);
24072
+ logInstrumentationError3("Cursor SDK onStep", error);
23406
24073
  }
23407
24074
  if (originalOnStep) {
23408
24075
  return originalOnStep(args);
@@ -23484,7 +24151,7 @@ async function* patchCursorStream(stream, state) {
23484
24151
  try {
23485
24152
  await handleStreamMessage2(state, message);
23486
24153
  } catch (error) {
23487
- logInstrumentationError2("Cursor SDK stream", error);
24154
+ logInstrumentationError3("Cursor SDK stream", error);
23488
24155
  }
23489
24156
  yield message;
23490
24157
  }
@@ -23548,7 +24215,7 @@ async function handleToolUpdate(state, update) {
23548
24215
  if (!state.activeToolSpans.has(callId)) {
23549
24216
  state.activeToolSpans.set(
23550
24217
  callId,
23551
- await startToolSpan(state, {
24218
+ await startToolSpan2(state, {
23552
24219
  args,
23553
24220
  callId,
23554
24221
  name,
@@ -23559,7 +24226,7 @@ async function handleToolUpdate(state, update) {
23559
24226
  }
23560
24227
  return;
23561
24228
  }
23562
- const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan(state, {
24229
+ const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan2(state, {
23563
24230
  args,
23564
24231
  callId,
23565
24232
  name,
@@ -23596,7 +24263,7 @@ async function handleStreamMessage2(state, message) {
23596
24263
  } else if (block?.type === "tool_use" && block.id) {
23597
24264
  state.activeToolSpans.set(
23598
24265
  block.id,
23599
- await startToolSpan(state, {
24266
+ await startToolSpan2(state, {
23600
24267
  args: block.input,
23601
24268
  callId: block.id,
23602
24269
  name: block.name,
@@ -23631,7 +24298,7 @@ async function handleToolMessage(state, message) {
23631
24298
  if (!state.activeToolSpans.has(callId)) {
23632
24299
  state.activeToolSpans.set(
23633
24300
  callId,
23634
- await startToolSpan(state, {
24301
+ await startToolSpan2(state, {
23635
24302
  args: message.args,
23636
24303
  callId,
23637
24304
  name: message.name,
@@ -23642,7 +24309,7 @@ async function handleToolMessage(state, message) {
23642
24309
  }
23643
24310
  return;
23644
24311
  }
23645
- const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan(state, {
24312
+ const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan2(state, {
23646
24313
  args: message.args,
23647
24314
  callId,
23648
24315
  name: message.name,
@@ -23669,7 +24336,7 @@ async function handleConversation(state, turns) {
23669
24336
  const command = turn.turn?.shellCommand?.command;
23670
24337
  if (command) {
23671
24338
  const callId = `shell:${state.activeToolSpans.size}:${command}`;
23672
- const toolState = await startToolSpan(state, {
24339
+ const toolState = await startToolSpan2(state, {
23673
24340
  args: turn.turn?.shellCommand,
23674
24341
  callId,
23675
24342
  name: "shell",
@@ -23693,7 +24360,7 @@ async function handleConversationStep(state, step) {
23693
24360
  }
23694
24361
  const toolCall = step.message;
23695
24362
  const callId = typeof toolCall?.callId === "string" ? toolCall.callId : `conversation-tool:${state.activeToolSpans.size}`;
23696
- const toolState = await startToolSpan(state, {
24363
+ const toolState = await startToolSpan2(state, {
23697
24364
  args: extractToolArgs(toolCall),
23698
24365
  callId,
23699
24366
  name: extractToolName(toolCall),
@@ -23724,7 +24391,7 @@ function handleStepUpdate(state, step) {
23724
24391
  state.stepText.push(step.message.text);
23725
24392
  }
23726
24393
  }
23727
- async function startToolSpan(state, args) {
24394
+ async function startToolSpan2(state, args) {
23728
24395
  const name = args.name || "unknown";
23729
24396
  const metadata = {
23730
24397
  "cursor_sdk.tool.status": args.status,
@@ -24011,10 +24678,10 @@ function safeLog2(span, event) {
24011
24678
  try {
24012
24679
  span.log(event);
24013
24680
  } catch (error) {
24014
- logInstrumentationError2("Cursor SDK span log", error);
24681
+ logInstrumentationError3("Cursor SDK span log", error);
24015
24682
  }
24016
24683
  }
24017
- function logInstrumentationError2(context, error) {
24684
+ function logInstrumentationError3(context, error) {
24018
24685
  debugLogger.error(`Error processing ${context}:`, error);
24019
24686
  }
24020
24687
  function cleanMetrics2(metrics) {
@@ -24852,6 +25519,10 @@ var googleGenAIChannels = defineChannels(
24852
25519
  channelName: "models.embedContent",
24853
25520
  kind: "async"
24854
25521
  }),
25522
+ httpResponseJson: channel({
25523
+ channelName: "httpResponse.json",
25524
+ kind: "async"
25525
+ }),
24855
25526
  interactionsCreate: channel({
24856
25527
  channelName: "interactions.create",
24857
25528
  kind: "async"
@@ -25000,13 +25671,45 @@ var GoogleGenAIPlugin = class extends BasePlugin {
25000
25671
  subscribeToEmbedContentChannel() {
25001
25672
  const tracingChannel = googleGenAIChannels.embedContent.tracingChannel();
25002
25673
  const states = /* @__PURE__ */ new WeakMap();
25674
+ const embeddingSpans = /* @__PURE__ */ new WeakSet();
25675
+ this.unsubscribers.push(
25676
+ googleGenAIChannels.httpResponseJson.intercept(
25677
+ (target, thisArg, args) => {
25678
+ const span = currentSpan();
25679
+ const result = Reflect.apply(target, thisArg, args);
25680
+ if (embeddingSpans.has(span)) {
25681
+ void Promise.resolve(result).then(
25682
+ (response) => {
25683
+ try {
25684
+ const metrics = cleanMetrics3(
25685
+ extractEmbedContentMetrics(response)
25686
+ );
25687
+ if (embeddingSpans.has(span) && Object.keys(metrics).length > 0) {
25688
+ span.log({ metrics });
25689
+ }
25690
+ } catch (error) {
25691
+ debugLogger.error(
25692
+ "Error reading Google GenAI embedding usage:",
25693
+ error
25694
+ );
25695
+ }
25696
+ },
25697
+ () => {
25698
+ }
25699
+ // The embedding channel handles the original rejection.
25700
+ );
25701
+ }
25702
+ return result;
25703
+ }
25704
+ )
25705
+ );
25003
25706
  const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
25004
25707
  tracingChannel,
25005
25708
  states,
25006
25709
  (event) => {
25007
25710
  const params = event.arguments[0];
25008
25711
  const input = serializeEmbedContentInput(params);
25009
- const metadata = extractEmbedContentMetadata(params);
25712
+ const metadata = { provider: "google", model: params.model };
25010
25713
  const span = startSpan(
25011
25714
  withSpanInstrumentationName(
25012
25715
  {
@@ -25019,6 +25722,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
25019
25722
  INSTRUMENTATION_NAMES.GOOGLE_GENAI
25020
25723
  )
25021
25724
  );
25725
+ embeddingSpans.add(span);
25022
25726
  return {
25023
25727
  span,
25024
25728
  startTime: getCurrentUnixTimestamp()
@@ -25030,7 +25734,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
25030
25734
  ensureSpanState(states, event, () => {
25031
25735
  const params = event.arguments[0];
25032
25736
  const input = serializeEmbedContentInput(params);
25033
- const metadata = extractEmbedContentMetadata(params);
25737
+ const metadata = { provider: "google", model: params.model };
25034
25738
  const span = startSpan(
25035
25739
  withSpanInstrumentationName(
25036
25740
  {
@@ -25043,6 +25747,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
25043
25747
  INSTRUMENTATION_NAMES.GOOGLE_GENAI
25044
25748
  )
25045
25749
  );
25750
+ embeddingSpans.add(span);
25046
25751
  return {
25047
25752
  span,
25048
25753
  startTime: getCurrentUnixTimestamp()
@@ -25055,20 +25760,28 @@ var GoogleGenAIPlugin = class extends BasePlugin {
25055
25760
  return;
25056
25761
  }
25057
25762
  try {
25058
- const output = summarizeEmbedContentOutput(event.result);
25059
25763
  spanState.span.log({
25060
- ...output ? { output } : {},
25764
+ output: summarizeEmbedContentOutput(event.result),
25061
25765
  metrics: cleanMetrics3(
25062
25766
  extractEmbedContentMetrics(event.result, spanState.startTime)
25063
25767
  )
25064
25768
  });
25065
25769
  } finally {
25770
+ embeddingSpans.delete(spanState.span);
25066
25771
  spanState.span.end();
25067
25772
  states.delete(event);
25068
25773
  }
25069
25774
  },
25070
25775
  error: (event) => {
25071
- logErrorAndEndSpan(states, event);
25776
+ const spanState = states.get(event);
25777
+ if (!spanState) return;
25778
+ try {
25779
+ spanState.span.log({ error: event.error, output: { count: 0 } });
25780
+ } finally {
25781
+ embeddingSpans.delete(spanState.span);
25782
+ spanState.span.end();
25783
+ states.delete(event);
25784
+ }
25072
25785
  }
25073
25786
  };
25074
25787
  tracingChannel.subscribe(handlers);
@@ -25303,15 +26016,53 @@ function serializeGenerateContentInput(params) {
25303
26016
  return input;
25304
26017
  }
25305
26018
  function serializeEmbedContentInput(params) {
26019
+ let contents = Array.isArray(params.contents) ? params.contents : [params.contents];
26020
+ if (params.model.includes("gemini-embedding-2") && contents.length > 0 && contents.every(
26021
+ (content) => typeof content === "string" || !Array.isArray(content) && !("parts" in content)
26022
+ )) {
26023
+ contents = [contents];
26024
+ }
25306
26025
  const input = {
25307
- model: params.model,
25308
- contents: serializeContentCollection(params.contents)
26026
+ inputs: contents.map((content) => {
26027
+ const parts = typeof content === "string" ? [content] : Array.isArray(content) ? content : "parts" in content ? content.parts : [content];
26028
+ const normalized = parts.flatMap((part) => {
26029
+ if (typeof part === "string") return [{ type: "text", text: part }];
26030
+ if (part.text !== void 0) return [{ type: "text", text: part.text }];
26031
+ const media = part.inlineData ?? part.fileData;
26032
+ if (!media) return [];
26033
+ const data = "data" in media ? `data:${media.mimeType};base64,${typeof media.data === "string" ? media.data : uint8ArrayToBase64(media.data)}` : media.fileUri;
26034
+ return media.mimeType?.startsWith("image/") ? [{ type: "image_url", image_url: { url: data } }] : [
26035
+ {
26036
+ type: "file",
26037
+ file: {
26038
+ file_data: data,
26039
+ ..."displayName" in media && media.displayName ? { filename: media.displayName } : {}
26040
+ }
26041
+ }
26042
+ ];
26043
+ });
26044
+ return {
26045
+ content: normalized.length === 1 && normalized[0].type === "text" ? normalized[0].text : normalized
26046
+ };
26047
+ }),
26048
+ ...params.config?.outputDimensionality !== void 0 ? { output_dimensions: params.config.outputDimensionality } : {}
25309
26049
  };
25310
- const config = params.config ? tryToDict(params.config) : null;
25311
- if (config) {
25312
- input.config = config;
26050
+ try {
26051
+ const processed = processInputAttachments(input);
26052
+ const hasInlineMedia = processed.inputs.some(
26053
+ ({ content }) => Array.isArray(content) && content.some((part) => {
26054
+ const data = part.type === "image_url" ? part.image_url.url : part.type === "file" ? part.file.file_data : void 0;
26055
+ return typeof data === "string" && data.startsWith("data:");
26056
+ })
26057
+ );
26058
+ return hasInlineMedia ? input : processed;
26059
+ } catch (error) {
26060
+ debugLogger.error(
26061
+ "Error processing Google GenAI embedding attachments:",
26062
+ error
26063
+ );
26064
+ return input;
25313
26065
  }
25314
- return input;
25315
26066
  }
25316
26067
  function serializeInteractionInput(params) {
25317
26068
  const input = {
@@ -25499,19 +26250,6 @@ function extractGenerateContentMetadata(params) {
25499
26250
  }
25500
26251
  return metadata;
25501
26252
  }
25502
- function extractEmbedContentMetadata(params) {
25503
- const metadata = {};
25504
- if (params.model) {
25505
- metadata.model = params.model;
25506
- }
25507
- const config = params.config ? tryToDict(params.config) : null;
25508
- if (config) {
25509
- Object.keys(config).forEach((key) => {
25510
- metadata[key] = config[key];
25511
- });
25512
- }
25513
- return metadata;
25514
- }
25515
26253
  function extractGenerateContentMetrics(response, startTime) {
25516
26254
  const metrics = {};
25517
26255
  if (startTime !== void 0) {
@@ -25531,15 +26269,23 @@ function extractEmbedContentMetrics(response, startTime) {
25531
26269
  const end = getCurrentUnixTimestamp();
25532
26270
  metrics.start = startTime;
25533
26271
  metrics.end = end;
25534
- metrics.duration = end - startTime;
25535
- }
25536
- if (response?.usageMetadata) {
25537
- populateUsageMetrics(metrics, response.usageMetadata);
25538
26272
  }
25539
26273
  const embeddingTokenCount = extractEmbedPromptTokenCount(response);
25540
26274
  if (embeddingTokenCount !== void 0) {
25541
26275
  metrics.prompt_tokens = embeddingTokenCount;
25542
- metrics.tokens = embeddingTokenCount;
26276
+ }
26277
+ const totalTokens = response?.usageMetadata?.totalTokenCount ?? embeddingTokenCount;
26278
+ if (totalTokens !== void 0) {
26279
+ metrics.tokens = totalTokens;
26280
+ }
26281
+ const audioTokens = (response?.usageMetadata?.promptTokenDetails ?? response?.usageMetadata?.promptTokensDetails)?.filter(
26282
+ (detail) => detail.modality === "AUDIO" && detail.tokenCount !== void 0
26283
+ );
26284
+ if (audioTokens?.length) {
26285
+ metrics.prompt_audio_tokens = audioTokens.reduce(
26286
+ (sum, detail) => sum + (detail.tokenCount ?? 0),
26287
+ 0
26288
+ );
25543
26289
  }
25544
26290
  return metrics;
25545
26291
  }
@@ -25578,41 +26324,25 @@ function extractEmbedPromptTokenCount(response) {
25578
26324
  if (typeof usagePromptTokens === "number" && Number.isFinite(usagePromptTokens)) {
25579
26325
  return usagePromptTokens;
25580
26326
  }
25581
- const usageTotalTokens = response.usageMetadata?.totalTokenCount;
25582
- if (typeof usageTotalTokens === "number" && Number.isFinite(usageTotalTokens)) {
25583
- return usageTotalTokens;
25584
- }
25585
26327
  const embeddings = Array.isArray(response.embeddings) ? response.embeddings : response.embedding ? [response.embedding] : [];
25586
26328
  if (embeddings.length === 0) {
25587
26329
  return void 0;
25588
26330
  }
25589
26331
  let total = 0;
25590
- let sawAny = false;
25591
26332
  for (const embedding of embeddings) {
25592
26333
  const embeddingStats = tryToDict(tryToDict(embedding)?.statistics);
25593
26334
  const tokenCount2 = embeddingStats?.tokenCount;
25594
26335
  if (typeof tokenCount2 === "number" && Number.isFinite(tokenCount2)) {
25595
26336
  total += tokenCount2;
25596
- sawAny = true;
26337
+ } else {
26338
+ return void 0;
25597
26339
  }
25598
26340
  }
25599
- return sawAny ? total : void 0;
26341
+ return total;
25600
26342
  }
25601
26343
  function summarizeEmbedContentOutput(response) {
25602
- if (!response) {
25603
- return void 0;
25604
- }
25605
- const embeddings = Array.isArray(response.embeddings) ? response.embeddings : response.embedding ? [response.embedding] : [];
25606
- if (embeddings.length === 0) {
25607
- return void 0;
25608
- }
25609
- const firstValues = embeddings[0]?.values;
25610
- if (!Array.isArray(firstValues)) {
25611
- return void 0;
25612
- }
25613
26344
  return {
25614
- embedding_count: embeddings.length,
25615
- embedding_length: firstValues.length
26345
+ count: Array.isArray(response?.embeddings) ? response.embeddings.length : response?.embedding ? 1 : 0
25616
26346
  };
25617
26347
  }
25618
26348
  function populateUsageMetrics(metrics, usage) {
@@ -29239,6 +29969,379 @@ function aggregateMistralStreamChunks(chunks) {
29239
29969
  };
29240
29970
  }
29241
29971
 
29972
+ // src/instrumentation/plugins/langgraph-sdk-channels.ts
29973
+ var langGraphSDKChannels = defineChannels(
29974
+ "@langchain/langgraph-sdk",
29975
+ {
29976
+ wait: channel({
29977
+ channelName: "runs.wait",
29978
+ kind: "async"
29979
+ }),
29980
+ stream: channel({
29981
+ channelName: "runs.stream",
29982
+ kind: "sync-stream"
29983
+ })
29984
+ },
29985
+ { instrumentationName: INSTRUMENTATION_NAMES.LANGGRAPH_SDK }
29986
+ );
29987
+
29988
+ // src/instrumentation/plugins/langgraph-sdk-plugin.ts
29989
+ var LangGraphSDKPlugin = class extends BasePlugin {
29990
+ onEnable() {
29991
+ this.unsubscribers.push(
29992
+ langGraphSDKChannels.wait.intercept(
29993
+ (target, self, args) => instrumentRun("wait", args, () => Reflect.apply(target, self, args))
29994
+ ),
29995
+ langGraphSDKChannels.stream.intercept(
29996
+ (target, self, args) => instrumentRun("stream", args, () => Reflect.apply(target, self, args))
29997
+ )
29998
+ );
29999
+ }
30000
+ onDisable() {
30001
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
30002
+ }
30003
+ };
30004
+ function normalizeMessage(value) {
30005
+ if (!isObject(value)) return value;
30006
+ 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);
30007
+ if (typeof role !== "string") return value;
30008
+ const message = {
30009
+ role,
30010
+ content: value.content ?? ""
30011
+ };
30012
+ for (const key of ["name", "tool_call_id", "refusal"]) {
30013
+ if (value[key] !== void 0) message[key] = value[key];
30014
+ }
30015
+ const additional = isObject(value.additional_kwargs) ? value.additional_kwargs : {};
30016
+ const toolCalls2 = Array.isArray(value.tool_calls) && value.tool_calls.length ? value.tool_calls : additional.tool_calls;
30017
+ if (Array.isArray(toolCalls2) && toolCalls2.length > 0) {
30018
+ message.tool_calls = toolCalls2.map((call) => {
30019
+ if (!isObject(call)) return call;
30020
+ if (isObject(call.function)) return call;
30021
+ return {
30022
+ id: call.id,
30023
+ type: "function",
30024
+ function: {
30025
+ name: call.name,
30026
+ arguments: typeof call.args === "string" ? call.args : JSON.stringify(call.args ?? {})
30027
+ }
30028
+ };
30029
+ });
30030
+ }
30031
+ if (Array.isArray(value.invalid_tool_calls) && value.invalid_tool_calls.length > 0)
30032
+ message.invalid_tool_calls = value.invalid_tool_calls;
30033
+ if (message.refusal === void 0 && additional.refusal !== void 0)
30034
+ message.refusal = additional.refusal;
30035
+ return message;
30036
+ }
30037
+ function normalizeRunError(value) {
30038
+ let name;
30039
+ let message;
30040
+ if (value instanceof Error) {
30041
+ name = value.name;
30042
+ message = value.message;
30043
+ } else if (isObject(value) && typeof value.error === "string" && typeof value.message === "string") {
30044
+ name = value.error;
30045
+ message = value.message;
30046
+ } else {
30047
+ return value;
30048
+ }
30049
+ for (let depth = 0; depth < 3; depth++) {
30050
+ try {
30051
+ const nested = JSON.parse(
30052
+ message.startsWith(`${name}: `) ? message.slice(name.length + 2) : message
30053
+ );
30054
+ if (!isObject(nested) || typeof nested.error !== "string" || typeof nested.message !== "string")
30055
+ break;
30056
+ name = nested.error;
30057
+ message = nested.message;
30058
+ } catch {
30059
+ break;
30060
+ }
30061
+ }
30062
+ if (value instanceof Error && name === value.name && message === value.message)
30063
+ return value;
30064
+ return Object.assign(new Error(message), { name });
30065
+ }
30066
+ function normalizeState(value) {
30067
+ if (!isObject(value)) return value;
30068
+ return Object.fromEntries(
30069
+ Object.entries(value).map(([key, field]) => {
30070
+ if (key === "messages" && Array.isArray(field))
30071
+ return [key, field.map(normalizeMessage)];
30072
+ if (key === "__error__") {
30073
+ const error = normalizeRunError(field);
30074
+ if (error instanceof Error)
30075
+ return [key, { error: error.name, message: error.message }];
30076
+ }
30077
+ return [key, field];
30078
+ })
30079
+ );
30080
+ }
30081
+ function normalizeRunOutput(value, input) {
30082
+ if (!isObject(value)) return value;
30083
+ if (Array.isArray(value.messages)) {
30084
+ if (value.__interrupt__ !== void 0 || value.__error__ !== void 0)
30085
+ return void 0;
30086
+ const inputMessages = isObject(input) && Array.isArray(input.messages) ? input.messages : [];
30087
+ let inputPrefixLength = 0;
30088
+ while (inputPrefixLength < inputMessages.length) {
30089
+ const previous = inputMessages[inputPrefixLength];
30090
+ const message = value.messages[inputPrefixLength];
30091
+ 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)))
30092
+ break;
30093
+ inputPrefixLength++;
30094
+ }
30095
+ for (let index = value.messages.length - 1; index >= inputPrefixLength; index--) {
30096
+ const message = value.messages[index];
30097
+ const normalized = normalizeMessage(message);
30098
+ if (!isObject(normalized)) continue;
30099
+ if (normalized.role === "user") return void 0;
30100
+ if (normalized.role !== "assistant") continue;
30101
+ if (inputMessages.some((previous) => {
30102
+ if (!isObject(previous) || !isObject(message)) return false;
30103
+ return previous.id !== void 0 && previous.id === message.id && JSON.stringify(normalizeMessage(previous)) === JSON.stringify(normalized);
30104
+ }))
30105
+ continue;
30106
+ return normalized;
30107
+ }
30108
+ return void 0;
30109
+ }
30110
+ const result = Object.fromEntries(
30111
+ Object.entries(value).filter(
30112
+ ([key]) => key !== "__interrupt__" && key !== "__error__"
30113
+ )
30114
+ );
30115
+ return !Object.keys(result).length && (value.__interrupt__ !== void 0 || value.__error__ !== void 0) ? void 0 : result;
30116
+ }
30117
+ function instrumentRun(operation, [threadId, assistantId, options], invoke2) {
30118
+ if (isAutoInstrumentationSuppressed()) return invoke2();
30119
+ const start = getCurrentUnixTimestamp();
30120
+ let span;
30121
+ try {
30122
+ const metadata = {
30123
+ "langgraph.thread_id": threadId,
30124
+ "langgraph.assistant_id": assistantId
30125
+ };
30126
+ for (const key of [
30127
+ "streamMode",
30128
+ "streamSubgraphs",
30129
+ "interruptBefore",
30130
+ "interruptAfter",
30131
+ "multitaskStrategy",
30132
+ "durability"
30133
+ ]) {
30134
+ if (options?.[key] !== void 0) metadata[key] = options[key];
30135
+ }
30136
+ span = startSpan(
30137
+ withSpanInstrumentationName(
30138
+ {
30139
+ name: `langgraph.runs.${operation}`,
30140
+ spanAttributes: { type: "task" /* TASK */ },
30141
+ event: {
30142
+ input: options?.command === void 0 ? normalizeState(options?.input) : {
30143
+ input: normalizeState(options.input),
30144
+ command: options.command
30145
+ },
30146
+ metadata
30147
+ }
30148
+ },
30149
+ INSTRUMENTATION_NAMES.LANGGRAPH_SDK
30150
+ )
30151
+ );
30152
+ } catch (error) {
30153
+ debugLogger.error("Error starting LangGraph SDK span:", error);
30154
+ return invoke2();
30155
+ }
30156
+ let ended = false;
30157
+ let output;
30158
+ let streamError;
30159
+ let firstToken;
30160
+ const updates = [];
30161
+ const usageByMessage = /* @__PURE__ */ new Map();
30162
+ const captureUsage = (id, usage) => {
30163
+ if (!isObject(usage)) return;
30164
+ const metrics = {};
30165
+ for (const [source, destination] of [
30166
+ ["input_tokens", "prompt_tokens"],
30167
+ ["output_tokens", "completion_tokens"],
30168
+ ["total_tokens", "tokens"]
30169
+ ]) {
30170
+ const value = usage[source];
30171
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0)
30172
+ metrics[destination] = value;
30173
+ }
30174
+ if (metrics.tokens === void 0 && metrics.prompt_tokens !== void 0 && metrics.completion_tokens !== void 0)
30175
+ metrics.tokens = metrics.prompt_tokens + metrics.completion_tokens;
30176
+ usageByMessage.set(id, { ...usageByMessage.get(id), ...metrics });
30177
+ };
30178
+ const messages = /* @__PURE__ */ new Map();
30179
+ const messageSnapshots = /* @__PURE__ */ new Map();
30180
+ const finish = (error) => {
30181
+ if (ended) return;
30182
+ ended = true;
30183
+ try {
30184
+ const metrics = {};
30185
+ for (const usage of usageByMessage.values()) {
30186
+ for (const [key, value] of Object.entries(usage))
30187
+ metrics[key] = (metrics[key] ?? 0) + value;
30188
+ }
30189
+ if (firstToken !== void 0)
30190
+ metrics.time_to_first_token = firstToken - start;
30191
+ const finalMessages = [
30192
+ ...new Map([...messages, ...messageSnapshots]).values()
30193
+ ];
30194
+ let loggedOutput = normalizeRunOutput(output, options?.input);
30195
+ if (loggedOutput === void 0 && finalMessages.length)
30196
+ loggedOutput = normalizeRunOutput(
30197
+ { messages: finalMessages },
30198
+ void 0
30199
+ );
30200
+ if (output === void 0 && !finalMessages.length && updates.length) {
30201
+ const results = updates.map((update) => normalizeRunOutput(update, options?.input)).filter((update) => update !== void 0);
30202
+ if (results.length) loggedOutput = { updates: results };
30203
+ }
30204
+ const interrupted = [output, ...updates].find(
30205
+ (state) => isObject(state) && state.__interrupt__ !== void 0
30206
+ );
30207
+ span.log({
30208
+ ...loggedOutput !== void 0 ? { output: loggedOutput } : {},
30209
+ ...isObject(interrupted) ? { metadata: { "langgraph.interrupts": interrupted.__interrupt__ } } : {},
30210
+ ...error !== void 0 || streamError !== void 0 ? { error: normalizeRunError(error ?? streamError) } : {},
30211
+ metrics
30212
+ });
30213
+ } catch (error2) {
30214
+ debugLogger.error("Error logging LangGraph SDK span:", error2);
30215
+ }
30216
+ try {
30217
+ span.end();
30218
+ } catch (error2) {
30219
+ debugLogger.error("Error ending LangGraph SDK span:", error2);
30220
+ }
30221
+ };
30222
+ const observeMessages = (value, streaming) => {
30223
+ if (!isObject(value) || !Array.isArray(value.messages)) return;
30224
+ const inputMessages = isObject(options?.input) && Array.isArray(options.input.messages) ? options.input.messages : [];
30225
+ for (const message of value.messages) {
30226
+ if (!isObject(message) || message.type !== "ai" && message.role !== "assistant")
30227
+ continue;
30228
+ if (message.id !== void 0 && inputMessages.some(
30229
+ (input) => isObject(input) && input.id === message.id
30230
+ ))
30231
+ continue;
30232
+ captureUsage(
30233
+ typeof message.id === "string" ? message.id : "message",
30234
+ message.usage_metadata
30235
+ );
30236
+ if (streaming && (typeof message.content === "string" ? message.content.length > 0 : Array.isArray(message.content) && message.content.some(
30237
+ (part) => isObject(part) && typeof part.text === "string" && part.text.length > 0
30238
+ )))
30239
+ firstToken ??= getCurrentUnixTimestamp();
30240
+ }
30241
+ };
30242
+ const onChunk = ({ event, data }) => {
30243
+ if (ended) return;
30244
+ if (event === "metadata" && isObject(data)) {
30245
+ if (typeof data.run_id === "string")
30246
+ span.log({ metadata: { "langgraph.run_id": data.run_id } });
30247
+ } else if (event === "error") {
30248
+ streamError = normalizeRunError(data);
30249
+ } else if (event === "values") {
30250
+ output = data;
30251
+ observeMessages(data, true);
30252
+ } else if (event === "updates") {
30253
+ if (isObject(data)) {
30254
+ const stateUpdates = [];
30255
+ for (const [node, update] of Object.entries(data)) {
30256
+ observeMessages(update, true);
30257
+ if (isObject(update) && Array.isArray(update.messages)) {
30258
+ for (const message of update.messages) {
30259
+ if (isObject(message))
30260
+ messageSnapshots.set(
30261
+ typeof message.id === "string" ? message.id : `update-${messageSnapshots.size}`,
30262
+ message
30263
+ );
30264
+ }
30265
+ const state = Object.fromEntries(
30266
+ Object.entries(update).filter(([key]) => key !== "messages")
30267
+ );
30268
+ if (Object.keys(state).length) stateUpdates.push([node, state]);
30269
+ } else {
30270
+ stateUpdates.push([node, update]);
30271
+ }
30272
+ }
30273
+ if (stateUpdates.length) updates.push(Object.fromEntries(stateUpdates));
30274
+ } else {
30275
+ updates.push(data);
30276
+ }
30277
+ } else if ((event === "messages" || event === "messages/partial" || event === "messages/complete") && Array.isArray(data)) {
30278
+ const parts = event === "messages" ? [data[0]] : data;
30279
+ for (const part of parts) {
30280
+ if (!isObject(part)) continue;
30281
+ const id = typeof part.id === "string" ? part.id : "message";
30282
+ captureUsage(id, part.usage_metadata);
30283
+ const previous = messages.get(id);
30284
+ messages.set(
30285
+ id,
30286
+ event === "messages" && previous && typeof part.content === "string" && typeof previous.content === "string" ? { ...part, content: previous.content + part.content } : part
30287
+ );
30288
+ if (typeof part.content === "string" && part.content.length > 0)
30289
+ firstToken ??= getCurrentUnixTimestamp();
30290
+ }
30291
+ }
30292
+ };
30293
+ let result;
30294
+ try {
30295
+ result = withCurrent(
30296
+ span,
30297
+ () => runWithAutoInstrumentationSuppressed(invoke2)
30298
+ );
30299
+ } catch (error) {
30300
+ finish(error);
30301
+ throw error;
30302
+ }
30303
+ if (operation === "stream") {
30304
+ try {
30305
+ patchStreamIfNeeded(result, {
30306
+ shouldCollect: (chunk) => {
30307
+ try {
30308
+ onChunk(chunk);
30309
+ } catch (error) {
30310
+ debugLogger.error(
30311
+ "Error processing LangGraph stream event:",
30312
+ error
30313
+ );
30314
+ }
30315
+ return false;
30316
+ },
30317
+ aroundNext: (next) => withCurrent(span, () => runWithAutoInstrumentationSuppressed(next)),
30318
+ onComplete: () => finish(),
30319
+ onCancel: () => finish(),
30320
+ onError: (error) => finish(error)
30321
+ });
30322
+ } catch (error) {
30323
+ debugLogger.error("Error observing LangGraph stream:", error);
30324
+ finish();
30325
+ }
30326
+ } else {
30327
+ void Promise.resolve(result).then(
30328
+ (value) => {
30329
+ try {
30330
+ output = value;
30331
+ observeMessages(value, false);
30332
+ if (isObject(value) && isObject(value.__error__))
30333
+ streamError = normalizeRunError(value.__error__);
30334
+ finish();
30335
+ } catch (error) {
30336
+ finish(error);
30337
+ }
30338
+ },
30339
+ (error) => finish(error)
30340
+ );
30341
+ }
30342
+ return result;
30343
+ }
30344
+
29242
30345
  // src/instrumentation/plugins/ollama-channels.ts
29243
30346
  var ollamaChannels = defineChannels(
29244
30347
  "ollama",
@@ -29448,7 +30551,7 @@ function normalizeTextAndImages(content, images) {
29448
30551
  ...unrecognizedImages.length > 0 ? { unrecognizedImages } : {}
29449
30552
  };
29450
30553
  }
29451
- function normalizeMessage(message, toolCallId, syntheticToolCallIdOffset = 0) {
30554
+ function normalizeMessage2(message, toolCallId, syntheticToolCallIdOffset = 0) {
29452
30555
  if (typeof message.role !== "string") {
29453
30556
  return void 0;
29454
30557
  }
@@ -29494,7 +30597,7 @@ function normalizeMessages(messages) {
29494
30597
  toolCallId = pendingToolCallIds.get(toolName)?.shift();
29495
30598
  }
29496
30599
  }
29497
- const normalized = normalizeMessage(
30600
+ const normalized = normalizeMessage2(
29498
30601
  ollamaMessage,
29499
30602
  toolCallId,
29500
30603
  syntheticToolCallIdOffset
@@ -29613,7 +30716,7 @@ function extractOllamaChatOutput(result, syntheticToolCallIdOffset = 0) {
29613
30716
  if (!isObject(result) || !isObject(result.message)) {
29614
30717
  return void 0;
29615
30718
  }
29616
- const message = normalizeMessage(
30719
+ const message = normalizeMessage2(
29617
30720
  result.message,
29618
30721
  void 0,
29619
30722
  syntheticToolCallIdOffset
@@ -32333,14 +33436,14 @@ function extractActionSpanMetadata(args) {
32333
33436
  const options = extractRunInNewSpanOptions(args);
32334
33437
  const labels = isObject(options?.labels) ? options.labels : void 0;
32335
33438
  const metadata = isObject(options?.metadata) ? options.metadata : void 0;
32336
- const actionType = stringValue(labels?.["genkit:metadata:subtype"]);
32337
- const name = stringValue(metadata?.name);
33439
+ const actionType = stringValue2(labels?.["genkit:metadata:subtype"]);
33440
+ const name = stringValue2(metadata?.name);
32338
33441
  if (!actionType || !name) {
32339
33442
  return void 0;
32340
33443
  }
32341
33444
  return {
32342
33445
  actionType,
32343
- key: stringValue(labels?.["genkit:key"]),
33446
+ key: stringValue2(labels?.["genkit:key"]),
32344
33447
  name
32345
33448
  };
32346
33449
  }
@@ -32450,7 +33553,7 @@ function pickNumberMetrics(values) {
32450
33553
  })
32451
33554
  );
32452
33555
  }
32453
- function stringValue(value) {
33556
+ function stringValue2(value) {
32454
33557
  return typeof value === "string" ? value : void 0;
32455
33558
  }
32456
33559
 
@@ -33135,7 +34238,7 @@ function subscribeToFlueContext(value, state) {
33135
34238
  try {
33136
34239
  unsubscribe?.();
33137
34240
  } catch (error) {
33138
- logInstrumentationError3("Flue context unsubscribe", error);
34241
+ logInstrumentationError4("Flue context unsubscribe", error);
33139
34242
  }
33140
34243
  };
33141
34244
  try {
@@ -33151,7 +34254,7 @@ function subscribeToFlueContext(value, state) {
33151
34254
  });
33152
34255
  state.contexts.add(value);
33153
34256
  } catch (error) {
33154
- logInstrumentationError3("Flue context subscription", error);
34257
+ logInstrumentationError4("Flue context subscription", error);
33155
34258
  }
33156
34259
  }
33157
34260
  function isAutoContextTerminalEvent(event, ctx) {
@@ -33207,7 +34310,7 @@ var FlueObserveBridge = class {
33207
34310
  try {
33208
34311
  this.handleEvent(event, flueContextFromUnknown(ctx));
33209
34312
  } catch (error) {
33210
- logInstrumentationError3("Flue observe", error);
34313
+ logInstrumentationError4("Flue observe", error);
33211
34314
  }
33212
34315
  }
33213
34316
  reset() {
@@ -33224,7 +34327,7 @@ var FlueObserveBridge = class {
33224
34327
  try {
33225
34328
  span = this.spanForExecutionOperation(operation, executionContext);
33226
34329
  } catch (error) {
33227
- logInstrumentationError3("Flue execution interceptor", error);
34330
+ logInstrumentationError4("Flue execution interceptor", error);
33228
34331
  }
33229
34332
  return span ? runWithCurrentSpanStore(span, next) : next();
33230
34333
  }
@@ -33430,7 +34533,7 @@ var FlueObserveBridge = class {
33430
34533
  this.runsById.delete(event.runId);
33431
34534
  }
33432
34535
  void flush().catch((error) => {
33433
- logInstrumentationError3("Flue flush", error);
34536
+ logInstrumentationError4("Flue flush", error);
33434
34537
  });
33435
34538
  }
33436
34539
  handleOperationStart(event) {
@@ -34205,17 +35308,17 @@ function safeLog3(span, event) {
34205
35308
  try {
34206
35309
  span.log(event);
34207
35310
  } catch (error) {
34208
- logInstrumentationError3("Flue span log", error);
35311
+ logInstrumentationError4("Flue span log", error);
34209
35312
  }
34210
35313
  }
34211
35314
  function safeEnd(span, endTime) {
34212
35315
  try {
34213
35316
  span.end(endTime === void 0 ? void 0 : { endTime });
34214
35317
  } catch (error) {
34215
- logInstrumentationError3("Flue span end", error);
35318
+ logInstrumentationError4("Flue span end", error);
34216
35319
  }
34217
35320
  }
34218
- function logInstrumentationError3(label, error) {
35321
+ function logInstrumentationError4(label, error) {
34219
35322
  debugLogger.debug(`Error in ${label} instrumentation:`, error);
34220
35323
  }
34221
35324
 
@@ -34783,10 +35886,10 @@ var LangSmithPlugin = class extends BasePlugin {
34783
35886
  const creates = ownValue(batch, "runCreates");
34784
35887
  if (Array.isArray(creates)) {
34785
35888
  const parentFirst = [...creates].sort((left, right) => {
34786
- const leftId = stringValue2(ownValue(left, "id"));
34787
- const rightId = stringValue2(ownValue(right, "id"));
34788
- const leftParent = stringValue2(ownValue(left, "parent_run_id"));
34789
- const rightParent = stringValue2(ownValue(right, "parent_run_id"));
35889
+ const leftId = stringValue3(ownValue(left, "id"));
35890
+ const rightId = stringValue3(ownValue(right, "id"));
35891
+ const leftParent = stringValue3(ownValue(left, "parent_run_id"));
35892
+ const rightParent = stringValue3(ownValue(right, "parent_run_id"));
34790
35893
  if (leftParent && leftParent === rightId) {
34791
35894
  return 1;
34792
35895
  }
@@ -34805,13 +35908,13 @@ var LangSmithPlugin = class extends BasePlugin {
34805
35908
  if (Array.isArray(updates)) {
34806
35909
  for (const run of updates) {
34807
35910
  this.containLifecycleFailure("batchIngestRuns update", () => {
34808
- this.processUpdate(stringValue2(ownValue(run, "id")) ?? "", run);
35911
+ this.processUpdate(stringValue3(ownValue(run, "id")) ?? "", run);
34809
35912
  });
34810
35913
  }
34811
35914
  }
34812
35915
  }
34813
35916
  processCreate(run) {
34814
- const id = stringValue2(ownValue(run, "id"));
35917
+ const id = stringValue3(ownValue(run, "id"));
34815
35918
  if (!id || this.completedRuns.get(id)) {
34816
35919
  return;
34817
35920
  }
@@ -34844,7 +35947,7 @@ var LangSmithPlugin = class extends BasePlugin {
34844
35947
  this.endIfComplete(id, activeRun, run);
34845
35948
  }
34846
35949
  processUpdate(explicitId, run) {
34847
- const id = stringValue2(explicitId) ?? stringValue2(ownValue(run, "id"));
35950
+ const id = stringValue3(explicitId) ?? stringValue3(ownValue(run, "id"));
34848
35951
  if (!id || this.completedRuns.get(id)) {
34849
35952
  return;
34850
35953
  }
@@ -34867,13 +35970,13 @@ var LangSmithPlugin = class extends BasePlugin {
34867
35970
  this.endIfComplete(id, active, active.run);
34868
35971
  }
34869
35972
  startRunSpan(id, run) {
34870
- const traceId = stringValue2(ownValue(run, "trace_id")) ?? id;
34871
- const parentId = stringValue2(ownValue(run, "parent_run_id")) ?? stringValue2(ownValue(ownValue(run, "parent_run"), "id"));
35973
+ const traceId = stringValue3(ownValue(run, "trace_id")) ?? id;
35974
+ const parentId = stringValue3(ownValue(run, "parent_run_id")) ?? stringValue3(ownValue(ownValue(run, "parent_run"), "id"));
34872
35975
  const startTime = timestampSeconds(ownValue(run, "start_time"));
34873
35976
  return startSpan(
34874
35977
  withSpanInstrumentationName(
34875
35978
  {
34876
- name: stringValue2(ownValue(run, "name")) ?? "LangSmith run",
35979
+ name: stringValue3(ownValue(run, "name")) ?? "LangSmith run",
34877
35980
  spanId: id,
34878
35981
  parentSpanIds: {
34879
35982
  parentSpanIds: parentId ? [parentId] : [],
@@ -34965,7 +36068,7 @@ function mergeRuns(previous, current) {
34965
36068
  function isRecord2(value) {
34966
36069
  return typeof value === "object" && value !== null && !Array.isArray(value);
34967
36070
  }
34968
- function stringValue2(value) {
36071
+ function stringValue3(value) {
34969
36072
  return typeof value === "string" && value.length > 0 ? value : void 0;
34970
36073
  }
34971
36074
  function timestampSeconds(value) {
@@ -34983,7 +36086,7 @@ function timestampSeconds(value) {
34983
36086
  return void 0;
34984
36087
  }
34985
36088
  function dottedOrderDepth(run) {
34986
- const dottedOrder = stringValue2(ownValue(run, "dotted_order"));
36089
+ const dottedOrder = stringValue3(ownValue(run, "dotted_order"));
34987
36090
  return dottedOrder ? dottedOrder.split(".").length : Number.MAX_SAFE_INTEGER;
34988
36091
  }
34989
36092
  function mapRunType(runType) {
@@ -35188,7 +36291,7 @@ var PiCodingAgentPlugin = class extends BasePlugin {
35188
36291
  }
35189
36292
  );
35190
36293
  } catch (error) {
35191
- logInstrumentationError4("Pi Coding Agent prompt start", error);
36294
+ logInstrumentationError5("Pi Coding Agent prompt start", error);
35192
36295
  }
35193
36296
  if (!state) {
35194
36297
  return runWithAutoInstrumentationSuppressed(invokeTarget);
@@ -35321,12 +36424,12 @@ function installPiAgentInstrumentation(agent) {
35321
36424
  () => handlePiAgentEvent(state, event)
35322
36425
  );
35323
36426
  } catch (error) {
35324
- logInstrumentationError4("Pi Coding Agent event", error);
36427
+ logInstrumentationError5("Pi Coding Agent event", error);
35325
36428
  }
35326
36429
  });
35327
36430
  piAgentEventSubscriptions.add(agent);
35328
36431
  } catch (error) {
35329
- logInstrumentationError4("Pi Coding Agent event subscription", error);
36432
+ logInstrumentationError5("Pi Coding Agent event subscription", error);
35330
36433
  }
35331
36434
  }
35332
36435
  function makeInstrumentedStreamFunction(agent, originalStreamFunction, property) {
@@ -35376,7 +36479,7 @@ function wrapPiToolExecutors(tools) {
35376
36479
  });
35377
36480
  tool.execute = wrappedExecute;
35378
36481
  } catch (error) {
35379
- logInstrumentationError4("Pi Coding Agent tool wrapping", error);
36482
+ logInstrumentationError5("Pi Coding Agent tool wrapping", error);
35380
36483
  }
35381
36484
  }
35382
36485
  }
@@ -35455,7 +36558,7 @@ function patchAssistantMessageStream(stream, promptState, llmState) {
35455
36558
  try {
35456
36559
  await iterator.return();
35457
36560
  } catch (cleanupError) {
35458
- logInstrumentationError4(
36561
+ logInstrumentationError5(
35459
36562
  "Pi Coding Agent stream cleanup",
35460
36563
  cleanupError
35461
36564
  );
@@ -35620,7 +36723,7 @@ function finishPiPromptRun(state, error) {
35620
36723
  try {
35621
36724
  state.span.end();
35622
36725
  } catch (endError) {
35623
- logInstrumentationError4("Pi Coding Agent prompt end", endError);
36726
+ logInstrumentationError5("Pi Coding Agent prompt end", endError);
35624
36727
  }
35625
36728
  }
35626
36729
  }
@@ -35952,10 +37055,10 @@ function safeLog4(span, event) {
35952
37055
  try {
35953
37056
  span.log(event);
35954
37057
  } catch (error) {
35955
- logInstrumentationError4("Pi Coding Agent span log", error);
37058
+ logInstrumentationError5("Pi Coding Agent span log", error);
35956
37059
  }
35957
37060
  }
35958
- function logInstrumentationError4(context, error) {
37061
+ function logInstrumentationError5(context, error) {
35959
37062
  debugLogger.debug(`${context}:`, error);
35960
37063
  }
35961
37064
 
@@ -36193,7 +37296,7 @@ function handleAgentStreamEvent(state, event) {
36193
37296
  finalizeModelSpan(state, event);
36194
37297
  break;
36195
37298
  case "beforeToolCallEvent":
36196
- startToolSpan2(state, event);
37299
+ startToolSpan3(state, event);
36197
37300
  break;
36198
37301
  case "afterToolCallEvent":
36199
37302
  finalizeToolSpan(state, event);
@@ -36218,7 +37321,7 @@ function handleAgentStreamEvent(state, event) {
36218
37321
  break;
36219
37322
  }
36220
37323
  } catch (error) {
36221
- logInstrumentationError5("Strands Agent SDK event", error);
37324
+ logInstrumentationError6("Strands Agent SDK event", error);
36222
37325
  }
36223
37326
  }
36224
37327
  function handleMultiAgentStreamEvent(state, event, activeChildParents) {
@@ -36254,7 +37357,7 @@ function handleMultiAgentStreamEvent(state, event, activeChildParents) {
36254
37357
  break;
36255
37358
  }
36256
37359
  } catch (error) {
36257
- logInstrumentationError5("Strands Agent SDK multi-agent event", error);
37360
+ logInstrumentationError6("Strands Agent SDK multi-agent event", error);
36258
37361
  }
36259
37362
  }
36260
37363
  function buildModelSpanInput(event, attachmentCache) {
@@ -36333,7 +37436,7 @@ function finalizeModelSpan(state, event) {
36333
37436
  });
36334
37437
  modelState.span.end();
36335
37438
  }
36336
- function startToolSpan2(state, event) {
37439
+ function startToolSpan3(state, event) {
36337
37440
  const toolUse = event.toolUse;
36338
37441
  const key = toolKey2(toolUse);
36339
37442
  if (state.activeTools.has(key)) {
@@ -36613,7 +37716,7 @@ function getModelConfig(model) {
36613
37716
  try {
36614
37717
  return model.getConfig();
36615
37718
  } catch (error) {
36616
- logInstrumentationError5("Strands Agent SDK model config", error);
37719
+ logInstrumentationError6("Strands Agent SDK model config", error);
36617
37720
  return void 0;
36618
37721
  }
36619
37722
  }
@@ -36696,7 +37799,7 @@ function processStrandsInputAttachments(input, cache = createStrandsAttachmentCa
36696
37799
  try {
36697
37800
  return processStrandsInputNode(input, cache);
36698
37801
  } catch (error) {
36699
- logInstrumentationError5("Strands Agent SDK input attachments", error);
37802
+ logInstrumentationError6("Strands Agent SDK input attachments", error);
36700
37803
  return input;
36701
37804
  }
36702
37805
  }
@@ -36916,10 +38019,10 @@ function safeLog5(span, event) {
36916
38019
  try {
36917
38020
  span.log(event);
36918
38021
  } catch (error) {
36919
- logInstrumentationError5("Strands Agent SDK span log", error);
38022
+ logInstrumentationError6("Strands Agent SDK span log", error);
36920
38023
  }
36921
38024
  }
36922
- function logInstrumentationError5(context, error) {
38025
+ function logInstrumentationError6(context, error) {
36923
38026
  debugLogger.debug(`${context}:`, error);
36924
38027
  }
36925
38028
 
@@ -37322,10 +38425,10 @@ function observeAudioStream(value, observe, complete, cancel, span) {
37322
38425
  const getReader = value.getReader;
37323
38426
  value.getReader = function(...args) {
37324
38427
  const reader = Reflect.apply(getReader, this, args);
37325
- const read3 = reader.read;
38428
+ const read4 = reader.read;
37326
38429
  reader.read = function(...readArgs) {
37327
38430
  return Promise.resolve(
37328
- withCurrent(span, () => Reflect.apply(read3, this, readArgs))
38431
+ withCurrent(span, () => Reflect.apply(read4, this, readArgs))
37329
38432
  ).then(
37330
38433
  (result) => {
37331
38434
  if (result.value) safeObserve(result.value);
@@ -37842,14 +38945,14 @@ var CloudflareAIChatPlugin = class extends BasePlugin {
37842
38945
  const result = event.arguments[0];
37843
38946
  state = agent ? this.findResponseState(
37844
38947
  agent,
37845
- stringValue3(ownValue2(result, "requestId"))
38948
+ stringValue4(ownValue2(result, "requestId"))
37846
38949
  ) : void 0;
37847
38950
  if (!state) {
37848
38951
  return;
37849
38952
  }
37850
38953
  state.responseObserved = true;
37851
38954
  const output = serializeMessage(ownValue2(result, "message"));
37852
- const status = stringValue3(ownValue2(result, "status"));
38955
+ const status = stringValue4(ownValue2(result, "status"));
37853
38956
  const error = ownValue2(result, "error");
37854
38957
  const input = ownValue2(result, "continuation") === true ? state.input : serializeMessages(readProperty(agent, "messages"))?.filter(
37855
38958
  (message) => typeof output?.id !== "string" || message.id !== output.id
@@ -37896,7 +38999,7 @@ var CloudflareAIChatPlugin = class extends BasePlugin {
37896
38999
  }
37897
39000
  try {
37898
39001
  const agent = asObject(event.self);
37899
- const requestId = stringValue3(event.arguments[0]);
39002
+ const requestId = stringValue4(event.arguments[0]);
37900
39003
  const key = requestId ?? /* @__PURE__ */ Symbol("cloudflare-ai-chat-turn");
37901
39004
  const activeForAgent = agent ? this.getActiveTurns(agent) : void 0;
37902
39005
  const existing = activeForAgent?.get(key);
@@ -38065,7 +39168,7 @@ function ownValue2(value, key) {
38065
39168
  const descriptor = Object.getOwnPropertyDescriptor(object, key);
38066
39169
  return descriptor && "value" in descriptor ? descriptor.value : void 0;
38067
39170
  }
38068
- function stringValue3(value) {
39171
+ function stringValue4(value) {
38069
39172
  return typeof value === "string" ? value : void 0;
38070
39173
  }
38071
39174
  function serializeMessages(value) {
@@ -38183,7 +39286,7 @@ var CloudflareAgentsPlugin = class extends BasePlugin {
38183
39286
  );
38184
39287
  spans.set(event, span);
38185
39288
  } catch (error) {
38186
- logInstrumentationError6("start", error);
39289
+ logInstrumentationError7("start", error);
38187
39290
  }
38188
39291
  },
38189
39292
  asyncEnd: (event) => {
@@ -38203,7 +39306,7 @@ var CloudflareAgentsPlugin = class extends BasePlugin {
38203
39306
  }
38204
39307
  }
38205
39308
  } catch (error) {
38206
- logInstrumentationError6("completion", error);
39309
+ logInstrumentationError7("completion", error);
38207
39310
  } finally {
38208
39311
  safelyEndSpan(span);
38209
39312
  }
@@ -38217,7 +39320,7 @@ var CloudflareAgentsPlugin = class extends BasePlugin {
38217
39320
  try {
38218
39321
  span.log({ error: event.error });
38219
39322
  } catch (error) {
38220
- logInstrumentationError6("rejection", error);
39323
+ logInstrumentationError7("rejection", error);
38221
39324
  } finally {
38222
39325
  safelyEndSpan(span);
38223
39326
  }
@@ -38247,10 +39350,10 @@ function safelyEndSpan(span) {
38247
39350
  try {
38248
39351
  span.end();
38249
39352
  } catch (error) {
38250
- logInstrumentationError6("span end", error);
39353
+ logInstrumentationError7("span end", error);
38251
39354
  }
38252
39355
  }
38253
- function logInstrumentationError6(operation, error) {
39356
+ function logInstrumentationError7(operation, error) {
38254
39357
  debugLogger.error(
38255
39358
  `Failed to process Cloudflare Agents ${operation} instrumentation:`,
38256
39359
  error
@@ -38275,6 +39378,7 @@ var BraintrustPlugin = class extends BasePlugin {
38275
39378
  openRouterPlugin = null;
38276
39379
  openRouterAgentPlugin = null;
38277
39380
  mistralPlugin = null;
39381
+ langGraphSDKPlugin = null;
38278
39382
  ollamaPlugin = null;
38279
39383
  googleADKPlugin = null;
38280
39384
  coherePlugin = null;
@@ -38355,6 +39459,10 @@ var BraintrustPlugin = class extends BasePlugin {
38355
39459
  this.mistralPlugin = new MistralPlugin();
38356
39460
  this.mistralPlugin.enable();
38357
39461
  }
39462
+ if (integrations.langgraphSDK !== false) {
39463
+ this.langGraphSDKPlugin = new LangGraphSDKPlugin();
39464
+ this.langGraphSDKPlugin.enable();
39465
+ }
38358
39466
  if (integrations.ollama !== false) {
38359
39467
  this.ollamaPlugin = new OllamaPlugin();
38360
39468
  this.ollamaPlugin.enable();
@@ -38483,6 +39591,10 @@ var BraintrustPlugin = class extends BasePlugin {
38483
39591
  this.mistralPlugin.disable();
38484
39592
  this.mistralPlugin = null;
38485
39593
  }
39594
+ if (this.langGraphSDKPlugin) {
39595
+ this.langGraphSDKPlugin.disable();
39596
+ this.langGraphSDKPlugin = null;
39597
+ }
38486
39598
  if (this.ollamaPlugin) {
38487
39599
  this.ollamaPlugin.disable();
38488
39600
  this.ollamaPlugin = null;
@@ -38624,6 +39736,9 @@ var envIntegrationAliases = {
38624
39736
  "langchain-js": "langchain",
38625
39737
  "@langchain": "langchain",
38626
39738
  langgraph: "langgraph",
39739
+ langgraphsdk: "langgraphSDK",
39740
+ "langgraph-sdk": "langgraphSDK",
39741
+ "@langchain/langgraph-sdk": "langgraphSDK",
38627
39742
  langsmith: "langsmith",
38628
39743
  voyage: "voyageai",
38629
39744
  "voyage-ai": "voyageai",
@@ -38664,6 +39779,7 @@ function getDefaultInstrumentationIntegrations() {
38664
39779
  gitHubCopilot: true,
38665
39780
  langchain: true,
38666
39781
  langgraph: true,
39782
+ langgraphSDK: true,
38667
39783
  langsmith: true,
38668
39784
  voyageai: true,
38669
39785
  elevenlabs: true,
@@ -38830,8 +39946,6 @@ __export(exports_exports, {
38830
39946
  BRAINTRUST_PARENT_KEY: () => BRAINTRUST_PARENT_KEY,
38831
39947
  BaseAttachment: () => BaseAttachment,
38832
39948
  BaseExperiment: () => BaseExperiment,
38833
- BatchScorer: () => BatchScorer,
38834
- BatchTask: () => BatchTask,
38835
39949
  BraintrustLangChainCallbackHandler: () => BraintrustLangChainCallbackHandler,
38836
39950
  BraintrustMiddleware: () => BraintrustMiddleware,
38837
39951
  BraintrustObservabilityExporter: () => BraintrustObservabilityExporter,
@@ -38845,8 +39959,6 @@ __export(exports_exports, {
38845
39959
  DEFAULT_MAX_REQUEST_SIZE: () => DEFAULT_MAX_REQUEST_SIZE,
38846
39960
  Dataset: () => Dataset2,
38847
39961
  DatasetPipeline: () => DatasetPipeline,
38848
- DurableEvalMemoryStore: () => DurableEvalMemoryStore,
38849
- DurableEvalRedisStore: () => DurableEvalRedisStore,
38850
39962
  ERR_PERMALINK: () => ERR_PERMALINK,
38851
39963
  Eval: () => Eval,
38852
39964
  EvalResultWithSummary: () => EvalResultWithSummary,
@@ -38881,6 +39993,10 @@ __export(exports_exports, {
38881
39993
  TestBackgroundLogger: () => TestBackgroundLogger,
38882
39994
  ToolBuilder: () => ToolBuilder,
38883
39995
  UUIDGenerator: () => UUIDGenerator,
39996
+ WorkflowEvalMemoryStore: () => WorkflowEvalMemoryStore,
39997
+ WorkflowEvalRedisStore: () => WorkflowEvalRedisStore,
39998
+ WorkflowScorer: () => WorkflowScorer,
39999
+ WorkflowTask: () => WorkflowTask,
38884
40000
  X_CACHED_HEADER: () => X_CACHED_HEADER,
38885
40001
  _exportsForTestingOnly: () => _exportsForTestingOnly,
38886
40002
  _internalGetGlobalState: () => _internalGetGlobalState,
@@ -38905,12 +40021,13 @@ __export(exports_exports, {
38905
40021
  currentSpan: () => currentSpan,
38906
40022
  deepCopyEvent: () => deepCopyEvent,
38907
40023
  defaultErrorScoreHandler: () => defaultErrorScoreHandler,
38908
- defineDurableEval: () => defineDurableEval,
40024
+ defineWorkflowEval: () => defineWorkflowEval,
38909
40025
  deserializePlainStringAsJSON: () => deserializePlainStringAsJSON,
38910
40026
  devNullWritableStream: () => devNullWritableStream,
38911
40027
  evaluatorDefinitionSchema: () => evaluatorDefinitionSchema,
38912
40028
  evaluatorDefinitionsSchema: () => evaluatorDefinitionsSchema,
38913
40029
  extractTraceContextFromHeaders: () => extractTraceContextFromHeaders,
40030
+ failOpenAIAgentsTrace: () => failOpenAIAgentsTrace,
38914
40031
  flush: () => flush,
38915
40032
  getContextManager: () => getContextManager,
38916
40033
  getIdGenerator: () => getIdGenerator,
@@ -38957,12 +40074,14 @@ __export(exports_exports, {
38957
40074
  setFetch: () => setFetch,
38958
40075
  setMaskingFunction: () => setMaskingFunction,
38959
40076
  spanComponentsToObjectId: () => spanComponentsToObjectId,
40077
+ startOpenAIAgentsTrace: () => startOpenAIAgentsTrace,
38960
40078
  startSpan: () => startSpan,
38961
40079
  summarize: () => summarize,
38962
40080
  templateRegistry: () => templateRegistry,
38963
40081
  toolFunctionDefinitionSchema: () => ToolFunctionDefinition,
38964
40082
  traceable: () => traceable,
38965
40083
  traced: () => traced,
40084
+ updateOpenAIAgentsTrace: () => updateOpenAIAgentsTrace,
38966
40085
  updateSpan: () => updateSpan,
38967
40086
  uploadLogs3OverflowPayload: () => uploadLogs3OverflowPayload,
38968
40087
  utf8ByteLength: () => utf8ByteLength2,
@@ -38991,6 +40110,7 @@ __export(exports_exports, {
38991
40110
  wrapGroq: () => wrapGroq,
38992
40111
  wrapHuggingFace: () => wrapHuggingFace,
38993
40112
  wrapHuggingFaceTransformers: () => wrapHuggingFaceTransformers,
40113
+ wrapLangGraphSDK: () => wrapLangGraphSDK,
38994
40114
  wrapLangSmithClient: () => wrapLangSmithClient,
38995
40115
  wrapLangSmithRunTrees: () => wrapLangSmithRunTrees,
38996
40116
  wrapLangSmithTraceable: () => wrapLangSmithTraceable,
@@ -39190,7 +40310,7 @@ function createLazyAPIPromise(ensureExecuted, ensureResponse, getAPIPromise) {
39190
40310
  }
39191
40311
 
39192
40312
  // src/openai-batch.ts
39193
- function read2(value, key) {
40313
+ function read3(value, key) {
39194
40314
  if (value === null || typeof value !== "object" && typeof value !== "function") {
39195
40315
  return void 0;
39196
40316
  }
@@ -39201,7 +40321,7 @@ function read2(value, key) {
39201
40321
  }
39202
40322
  }
39203
40323
  function isAsyncIterable5(value) {
39204
- return typeof read2(value, Symbol.asyncIterator) === "function";
40324
+ return typeof read3(value, Symbol.asyncIterator) === "function";
39205
40325
  }
39206
40326
  function teeAsyncIterable(source) {
39207
40327
  const iterator = source[Symbol.asyncIterator]();
@@ -39244,7 +40364,7 @@ function teeAsyncIterable(source) {
39244
40364
  }
39245
40365
  }
39246
40366
  };
39247
- const path = read2(source, "path");
40367
+ const path = read3(source, "path");
39248
40368
  if (typeof path === "string") {
39249
40369
  Object.defineProperty(upload, "path", { value: path });
39250
40370
  }
@@ -39265,8 +40385,8 @@ function teeUpload(upload) {
39265
40385
  function openaiFilesCreateTraced(files) {
39266
40386
  return (params, options) => {
39267
40387
  const parent = getSpanParentObject();
39268
- const purpose = read2(params, "purpose");
39269
- const file = read2(params, "file");
40388
+ const purpose = read3(params, "purpose");
40389
+ const file = read3(params, "file");
39270
40390
  if (purpose !== "batch") {
39271
40391
  return files.create(params, options);
39272
40392
  }
@@ -39357,6 +40477,143 @@ async function completeOpenAIBatchTrace(args) {
39357
40477
  );
39358
40478
  }
39359
40479
 
40480
+ // src/openai-agents-api.ts
40481
+ function isRecord3(value) {
40482
+ return typeof value === "object" && value !== null && !Array.isArray(value);
40483
+ }
40484
+ function validateStartArgs(value) {
40485
+ if (!isRecord3(value)) {
40486
+ throw new TypeError(
40487
+ "startOpenAIAgentsTrace expected an OpenAI Agents parameters object"
40488
+ );
40489
+ }
40490
+ const agent = value.agent;
40491
+ if (agent !== void 0 && agent !== null && !isRecord3(agent)) {
40492
+ throw new TypeError(
40493
+ "startOpenAIAgentsTrace expected agent to be an object or null"
40494
+ );
40495
+ }
40496
+ if (isRecord3(agent) && (agent.id !== void 0 && typeof agent.id !== "string" || agent.model !== void 0 && typeof agent.model !== "string" || agent.name !== void 0 && agent.name !== null && typeof agent.name !== "string")) {
40497
+ throw new TypeError(
40498
+ "startOpenAIAgentsTrace received invalid agent identity fields"
40499
+ );
40500
+ }
40501
+ if (value.agent_id !== void 0 && typeof value.agent_id !== "string") {
40502
+ throw new TypeError(
40503
+ "startOpenAIAgentsTrace expected agent_id to be a string"
40504
+ );
40505
+ }
40506
+ if (value.metadata !== void 0 && value.metadata !== null && !isRecord3(value.metadata)) {
40507
+ throw new TypeError(
40508
+ "startOpenAIAgentsTrace expected metadata to be an object or null"
40509
+ );
40510
+ }
40511
+ return value;
40512
+ }
40513
+ function validateEvent(event) {
40514
+ if (!isRecord3(event) || typeof event.type !== "string" || event.type.length === 0) {
40515
+ throw new TypeError(
40516
+ "updateOpenAIAgentsTrace expected an OpenAI Agents event object"
40517
+ );
40518
+ }
40519
+ return event;
40520
+ }
40521
+ function createTraceState() {
40522
+ const parent = _internalExportParentSynchronously(getSpanParentObject());
40523
+ if (!parent) {
40524
+ return null;
40525
+ }
40526
+ const parentComponents = SpanComponentsV4.fromStr(parent);
40527
+ const rowId = newId();
40528
+ const useLegacyIds = resolveUseLegacyUuidIds();
40529
+ const spanId = useLegacyIds ? newId() : newId().replaceAll("-", "").slice(0, 16);
40530
+ const rootSpanId = useLegacyIds ? spanId : newId().replaceAll("-", "");
40531
+ const root = new SpanComponentsV4({
40532
+ object_type: parentComponents.data.object_type,
40533
+ ...parentComponents.data.object_id ? { object_id: parentComponents.data.object_id } : {
40534
+ compute_object_metadata_args: parentComponents.data.compute_object_metadata_args ?? {}
40535
+ },
40536
+ propagated_event: parentComponents.data.propagated_event,
40537
+ root_span_id: rootSpanId,
40538
+ row_id: rowId,
40539
+ span_id: spanId
40540
+ }).toStr();
40541
+ return {
40542
+ callItems: {},
40543
+ ended: false,
40544
+ eventIds: [],
40545
+ openTools: {},
40546
+ root,
40547
+ rootKey: spanId,
40548
+ rootParent: parent,
40549
+ startTime: getCurrentUnixTimestamp(),
40550
+ subagents: {},
40551
+ turnSubagents: {},
40552
+ version: 1
40553
+ };
40554
+ }
40555
+ function startOpenAIAgentsTrace(args) {
40556
+ const validatedArgs = validateStartArgs(args);
40557
+ const state = createTraceState();
40558
+ if (!state) {
40559
+ return null;
40560
+ }
40561
+ try {
40562
+ void openAIChannels.agentsTraceStart.invoke(
40563
+ async () => state,
40564
+ void 0,
40565
+ [{ args: validatedArgs, state }],
40566
+ {}
40567
+ ).catch((error) => {
40568
+ debugLogger.debug(
40569
+ "OpenAI Agents API instrumentation could not start:",
40570
+ error
40571
+ );
40572
+ });
40573
+ } catch (error) {
40574
+ debugLogger.debug(
40575
+ "OpenAI Agents API instrumentation could not start:",
40576
+ error
40577
+ );
40578
+ }
40579
+ return state;
40580
+ }
40581
+ async function updateOpenAIAgentsTrace(token, event) {
40582
+ const state = token;
40583
+ const validatedEvent = validateEvent(event);
40584
+ try {
40585
+ return await openAIChannels.agentsTraceCapture.invoke(
40586
+ async () => state,
40587
+ void 0,
40588
+ [{ state, event: validatedEvent }],
40589
+ {}
40590
+ );
40591
+ } catch (error) {
40592
+ debugLogger.debug(
40593
+ "OpenAI Agents API instrumentation could not update:",
40594
+ error
40595
+ );
40596
+ return token;
40597
+ }
40598
+ }
40599
+ async function failOpenAIAgentsTrace(token, error) {
40600
+ const state = token;
40601
+ try {
40602
+ return await openAIChannels.agentsTraceFail.invoke(
40603
+ async () => state,
40604
+ void 0,
40605
+ [{ state, error }],
40606
+ {}
40607
+ );
40608
+ } catch (instrumentationError) {
40609
+ debugLogger.debug(
40610
+ "OpenAI Agents API instrumentation could not record failure:",
40611
+ instrumentationError
40612
+ );
40613
+ return token;
40614
+ }
40615
+ }
40616
+
39360
40617
  // src/functions/invoke.ts
39361
40618
  async function invoke(args) {
39362
40619
  const {
@@ -40806,7 +42063,31 @@ var MAX_STORED_LLM_INPUTS = 100;
40806
42063
  var MAX_STORED_REASONING_BLOCKS = 100;
40807
42064
  var MAX_STORED_SPAN_REFERENCES = 1e4;
40808
42065
  var MAX_STORED_STEP_STARTS = 1e4;
42066
+ var EVE_HANDLED_EVENT_TYPES = /* @__PURE__ */ new Set([
42067
+ "action.result",
42068
+ "actions.requested",
42069
+ "message.completed",
42070
+ "message.received",
42071
+ "reasoning.completed",
42072
+ "result.completed",
42073
+ "session.completed",
42074
+ "session.failed",
42075
+ "session.started",
42076
+ "step.completed",
42077
+ "step.failed",
42078
+ "step.started",
42079
+ "subagent.called",
42080
+ "subagent.completed",
42081
+ "turn.completed",
42082
+ "turn.failed",
42083
+ "turn.started"
42084
+ ]);
40809
42085
  function braintrustEveHook(options) {
42086
+ if (!options || typeof options.defineState !== "function") {
42087
+ throw new TypeError(
42088
+ "braintrustEveHook requires Eve's defineState function"
42089
+ );
42090
+ }
40810
42091
  const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
40811
42092
  const bridge = new EveBridge(state);
40812
42093
  return {
@@ -40818,15 +42099,27 @@ function braintrustEveHook(options) {
40818
42099
  };
40819
42100
  }
40820
42101
  function createLegacyEveInstrumentation(options) {
42102
+ if (!options || typeof options.defineState !== "function") {
42103
+ throw new TypeError(
42104
+ "braintrustEveInstrumentation requires Eve's defineState function"
42105
+ );
42106
+ }
40821
42107
  const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
40822
42108
  return {
40823
42109
  events: {
40824
42110
  "step.started": (input) => {
40825
42111
  try {
42112
+ if (!isEveInstrumentationStepStartedEventInput(input)) {
42113
+ debugLogger.warn(
42114
+ "Ignoring malformed Eve instrumentation step.started event"
42115
+ );
42116
+ return void 0;
42117
+ }
40826
42118
  captureEveModelInput(state, input);
40827
42119
  } catch (error) {
40828
42120
  debugLogger.warn("Error in Eve LLM input capture:", error);
40829
42121
  }
42122
+ return void 0;
40830
42123
  }
40831
42124
  },
40832
42125
  recordInputs: false,
@@ -40835,7 +42128,77 @@ function createLegacyEveInstrumentation(options) {
40835
42128
  };
40836
42129
  }
40837
42130
  function isEveHandleMessageStreamEvent(event) {
40838
- return isObject(event) && typeof event["type"] === "string";
42131
+ if (!isObject(event) || typeof event["type"] !== "string") {
42132
+ return false;
42133
+ }
42134
+ const type = event["type"];
42135
+ if (type === "session.completed") {
42136
+ return true;
42137
+ }
42138
+ if (!isObject(event["data"])) {
42139
+ return false;
42140
+ }
42141
+ const data = event["data"];
42142
+ if (type === "session.started") {
42143
+ return true;
42144
+ }
42145
+ if (type === "session.failed") {
42146
+ return typeof data["sessionId"] === "string" && typeof data["code"] === "string" && typeof data["message"] === "string";
42147
+ }
42148
+ if (type === "session.waiting") {
42149
+ return data["wait"] === "next-user-message";
42150
+ }
42151
+ if (typeof data["turnId"] !== "string" || typeof data["sequence"] !== "number" || !Number.isFinite(data["sequence"])) {
42152
+ return false;
42153
+ }
42154
+ if (type === "turn.started" || type === "turn.completed" || type === "subagent.called" || type === "subagent.completed") {
42155
+ if (type === "subagent.called") {
42156
+ return typeof data["callId"] === "string" && typeof data["childSessionId"] === "string" && typeof data["name"] === "string";
42157
+ }
42158
+ if (type === "subagent.completed") {
42159
+ return typeof data["callId"] === "string" && typeof data["subagentName"] === "string";
42160
+ }
42161
+ return true;
42162
+ }
42163
+ if (type === "turn.failed") {
42164
+ return typeof data["code"] === "string" && typeof data["message"] === "string";
42165
+ }
42166
+ if (type === "message.received") {
42167
+ return typeof data["message"] === "string";
42168
+ }
42169
+ if (typeof data["stepIndex"] !== "number" || !Number.isFinite(data["stepIndex"]) || data["stepIndex"] < 0) {
42170
+ return false;
42171
+ }
42172
+ switch (type) {
42173
+ case "step.started":
42174
+ return true;
42175
+ case "message.completed":
42176
+ return typeof data["finishReason"] === "string" && (typeof data["message"] === "string" || data["message"] === null);
42177
+ case "reasoning.completed":
42178
+ return typeof data["reasoning"] === "string";
42179
+ case "result.completed":
42180
+ return true;
42181
+ case "step.completed":
42182
+ return typeof data["finishReason"] === "string";
42183
+ case "step.failed":
42184
+ return typeof data["code"] === "string" && typeof data["message"] === "string";
42185
+ case "actions.requested":
42186
+ return Array.isArray(data["actions"]);
42187
+ case "action.result":
42188
+ return isObject(data["result"]) && (data["status"] === "completed" || data["status"] === "failed" || data["status"] === "rejected");
42189
+ default:
42190
+ return false;
42191
+ }
42192
+ }
42193
+ function isEveInstrumentationStepStartedEventInput(input) {
42194
+ if (!isObject(input)) {
42195
+ return false;
42196
+ }
42197
+ const modelInput = input["modelInput"];
42198
+ const session = input["session"];
42199
+ const step = input["step"];
42200
+ const turn = input["turn"];
42201
+ return isObject(modelInput) && Array.isArray(modelInput["messages"]) && isObject(session) && typeof session["id"] === "string" && isObject(step) && typeof step["index"] === "number" && Number.isFinite(step["index"]) && step["index"] >= 0 && isObject(turn) && typeof turn["id"] === "string" && typeof turn["sequence"] === "number" && Number.isFinite(turn["sequence"]);
40839
42202
  }
40840
42203
  var ResumedEveSpan = class {
40841
42204
  constructor(reference) {
@@ -41004,7 +42367,17 @@ var EveBridge = class {
41004
42367
  });
41005
42368
  }
41006
42369
  async handle(event, ctx, hookMetadata) {
42370
+ try {
42371
+ await this.handleUnchecked(event, ctx, hookMetadata);
42372
+ } catch (error) {
42373
+ debugLogger.warn("Error in Eve hook instrumentation:", error);
42374
+ }
42375
+ }
42376
+ async handleUnchecked(event, ctx, hookMetadata) {
41007
42377
  if (!isEveHandleMessageStreamEvent(event)) {
42378
+ if (isObject(event) && typeof event["type"] === "string" && EVE_HANDLED_EVENT_TYPES.has(event["type"])) {
42379
+ debugLogger.warn(`Ignoring malformed Eve hook ${event["type"]} event`);
42380
+ }
41008
42381
  return;
41009
42382
  }
41010
42383
  const run = async () => {
@@ -41330,9 +42703,14 @@ var EveBridge = class {
41330
42703
  }
41331
42704
  for (const action of traceActions) {
41332
42705
  const name = action.kind === "tool-call" ? action.toolName : action.subagentName ?? action.name ?? "agent";
42706
+ let args = "null";
42707
+ try {
42708
+ args = JSON.stringify(action.input) ?? "null";
42709
+ } catch {
42710
+ }
41333
42711
  toolCallsById.set(action.callId, {
41334
42712
  function: {
41335
- arguments: JSON.stringify(action.input),
42713
+ arguments: args,
41336
42714
  name
41337
42715
  },
41338
42716
  id: action.callId,
@@ -42201,17 +43579,33 @@ function consumeCapturedEveModelInput(state, sessionId, turnId, stepIndex) {
42201
43579
  }
42202
43580
  }
42203
43581
  function capturedModelInput(modelInput) {
42204
- const { instructions, messages } = modelInput;
42205
- const value = [];
42206
- if (typeof instructions === "string") {
42207
- value.push({ content: instructions, role: "system" });
42208
- } else if (Array.isArray(instructions)) {
42209
- value.push(...instructions.map(capturedEveModelMessage));
42210
- } else if (instructions) {
42211
- value.push(capturedEveModelMessage(instructions));
42212
- }
42213
- value.push(...messages.map(capturedEveModelMessage));
42214
43582
  try {
43583
+ if (!isObject(modelInput) || !Array.isArray(modelInput["messages"])) {
43584
+ return void 0;
43585
+ }
43586
+ const value = [];
43587
+ const instructions = modelInput["instructions"];
43588
+ if (typeof instructions === "string") {
43589
+ value.push({ content: instructions, role: "system" });
43590
+ } else if (Array.isArray(instructions)) {
43591
+ for (const instruction of instructions) {
43592
+ const captured = capturedEveModelMessage(instruction);
43593
+ if (captured?.role === "system") {
43594
+ value.push(captured);
43595
+ }
43596
+ }
43597
+ } else {
43598
+ const captured = capturedEveModelMessage(instructions);
43599
+ if (captured?.role === "system") {
43600
+ value.push(captured);
43601
+ }
43602
+ }
43603
+ for (const message of modelInput["messages"]) {
43604
+ const captured = capturedEveModelMessage(message);
43605
+ if (captured) {
43606
+ value.push(captured);
43607
+ }
43608
+ }
42215
43609
  const cloned = JSON.parse(JSON.stringify(value));
42216
43610
  if (!Array.isArray(cloned)) {
42217
43611
  return void 0;
@@ -42222,116 +43616,202 @@ function capturedModelInput(modelInput) {
42222
43616
  }
42223
43617
  }
42224
43618
  function capturedEveModelMessage(message) {
42225
- const { content, role } = message;
43619
+ if (!isObject(message)) {
43620
+ return void 0;
43621
+ }
43622
+ const role = message["role"];
43623
+ if (role !== "system" && role !== "user" && role !== "assistant" && role !== "tool") {
43624
+ return void 0;
43625
+ }
43626
+ const content = message["content"];
42226
43627
  if (typeof content === "string") {
42227
43628
  return { content, role };
42228
43629
  }
42229
- return { content: content.map(capturedEveModelContentPart), role };
43630
+ if (!Array.isArray(content)) {
43631
+ return void 0;
43632
+ }
43633
+ const capturedContent = [];
43634
+ for (const part of content) {
43635
+ const captured = capturedEveModelContentPart(part);
43636
+ if (captured) {
43637
+ capturedContent.push(captured);
43638
+ }
43639
+ }
43640
+ return { content: capturedContent, role };
42230
43641
  }
42231
43642
  function capturedEveModelContentPart(part) {
42232
- switch (part.type) {
43643
+ if (!isObject(part) || typeof part["type"] !== "string") {
43644
+ return void 0;
43645
+ }
43646
+ switch (part["type"]) {
42233
43647
  case "text":
42234
- case "reasoning":
42235
- return { text: part.text, type: part.type };
43648
+ case "reasoning": {
43649
+ const text = part["text"];
43650
+ return typeof text === "string" ? { text, type: part["type"] } : void 0;
43651
+ }
42236
43652
  case "image":
43653
+ if (!Object.hasOwn(part, "image")) {
43654
+ return void 0;
43655
+ }
42237
43656
  return {
42238
- image: part.image,
42239
- ...part.mediaType !== void 0 ? { mediaType: part.mediaType } : {},
43657
+ image: part["image"],
43658
+ ...typeof part["mediaType"] === "string" ? { mediaType: part["mediaType"] } : {},
42240
43659
  type: "image"
42241
43660
  };
42242
43661
  case "file":
42243
- case "reasoning-file":
43662
+ case "reasoning-file": {
43663
+ if (!Object.hasOwn(part, "data") || typeof part["mediaType"] !== "string") {
43664
+ return void 0;
43665
+ }
42244
43666
  return {
42245
- data: part.data,
42246
- ...part.type === "file" && part.filename !== void 0 ? { filename: part.filename } : {},
42247
- mediaType: part.mediaType,
42248
- type: part.type
43667
+ data: part["data"],
43668
+ ...part["type"] === "file" && typeof part["filename"] === "string" ? { filename: part["filename"] } : {},
43669
+ mediaType: part["mediaType"],
43670
+ type: part["type"]
42249
43671
  };
43672
+ }
42250
43673
  case "custom":
42251
43674
  return {
42252
- ..."kind" in part ? { kind: part.kind } : {},
43675
+ ...typeof part["kind"] === "string" ? { kind: part["kind"] } : {},
42253
43676
  type: "custom"
42254
43677
  };
42255
- case "tool-call":
43678
+ case "tool-call": {
43679
+ if (typeof part["toolCallId"] !== "string" || typeof part["toolName"] !== "string") {
43680
+ return void 0;
43681
+ }
42256
43682
  return {
42257
- input: part.input,
42258
- ...part.providerExecuted !== void 0 ? { providerExecuted: part.providerExecuted } : {},
42259
- toolCallId: part.toolCallId,
42260
- toolName: part.toolName,
43683
+ input: part["input"],
43684
+ ...typeof part["providerExecuted"] === "boolean" ? { providerExecuted: part["providerExecuted"] } : {},
43685
+ toolCallId: part["toolCallId"],
43686
+ toolName: part["toolName"],
42261
43687
  type: "tool-call"
42262
43688
  };
43689
+ }
42263
43690
  case "tool-result": {
42264
- const output = part.output;
43691
+ const output = part["output"];
43692
+ if (typeof part["toolCallId"] !== "string" || typeof part["toolName"] !== "string" || !isObject(output) || typeof output["type"] !== "string") {
43693
+ return void 0;
43694
+ }
42265
43695
  let capturedOutput;
42266
- switch (output.type) {
43696
+ switch (output["type"]) {
42267
43697
  case "text":
42268
- case "error-text":
42269
- capturedOutput = { type: output.type, value: output.value };
43698
+ case "error-text": {
43699
+ if (typeof output["value"] !== "string") {
43700
+ return void 0;
43701
+ }
43702
+ capturedOutput = {
43703
+ type: output["type"],
43704
+ value: output["value"]
43705
+ };
42270
43706
  break;
43707
+ }
42271
43708
  case "json":
42272
43709
  case "error-json":
42273
- capturedOutput = { type: output.type, value: output.value };
43710
+ capturedOutput = {
43711
+ type: output["type"],
43712
+ value: output["value"]
43713
+ };
42274
43714
  break;
42275
43715
  case "execution-denied":
42276
43716
  capturedOutput = {
42277
- ...output.reason !== void 0 ? { reason: output.reason } : {},
43717
+ ...typeof output["reason"] === "string" ? { reason: output["reason"] } : {},
42278
43718
  type: "execution-denied"
42279
43719
  };
42280
43720
  break;
42281
- case "content":
43721
+ case "content": {
43722
+ if (!Array.isArray(output["value"])) {
43723
+ return void 0;
43724
+ }
43725
+ const value = [];
43726
+ for (const outputPart of output["value"]) {
43727
+ const captured = capturedEveModelContentPart(outputPart);
43728
+ if (captured) {
43729
+ value.push(captured);
43730
+ }
43731
+ }
42282
43732
  capturedOutput = {
42283
43733
  type: "content",
42284
- value: output.value.map(capturedEveModelContentPart)
43734
+ value
42285
43735
  };
42286
43736
  break;
43737
+ }
43738
+ default:
43739
+ return void 0;
42287
43740
  }
42288
43741
  return {
42289
43742
  output: capturedOutput,
42290
- toolCallId: part.toolCallId,
42291
- toolName: part.toolName,
43743
+ toolCallId: part["toolCallId"],
43744
+ toolName: part["toolName"],
42292
43745
  type: "tool-result"
42293
43746
  };
42294
43747
  }
42295
- case "tool-approval-request":
43748
+ case "tool-approval-request": {
43749
+ if (typeof part["approvalId"] !== "string" || typeof part["toolCallId"] !== "string") {
43750
+ return void 0;
43751
+ }
42296
43752
  return {
42297
- approvalId: part.approvalId,
42298
- ...part.isAutomatic !== void 0 ? { isAutomatic: part.isAutomatic } : {},
42299
- ...part.signature !== void 0 ? { signature: part.signature } : {},
42300
- toolCallId: part.toolCallId,
43753
+ approvalId: part["approvalId"],
43754
+ ...typeof part["isAutomatic"] === "boolean" ? { isAutomatic: part["isAutomatic"] } : {},
43755
+ ...typeof part["signature"] === "string" ? { signature: part["signature"] } : {},
43756
+ toolCallId: part["toolCallId"],
42301
43757
  type: "tool-approval-request"
42302
43758
  };
42303
- case "tool-approval-response":
43759
+ }
43760
+ case "tool-approval-response": {
43761
+ if (typeof part["approvalId"] !== "string" || typeof part["approved"] !== "boolean") {
43762
+ return void 0;
43763
+ }
42304
43764
  return {
42305
- approvalId: part.approvalId,
42306
- approved: part.approved,
42307
- ...part.providerExecuted !== void 0 ? { providerExecuted: part.providerExecuted } : {},
42308
- ...part.reason !== void 0 ? { reason: part.reason } : {},
43765
+ approvalId: part["approvalId"],
43766
+ approved: part["approved"],
43767
+ ...typeof part["providerExecuted"] === "boolean" ? { providerExecuted: part["providerExecuted"] } : {},
43768
+ ...typeof part["reason"] === "string" ? { reason: part["reason"] } : {},
42309
43769
  type: "tool-approval-response"
42310
43770
  };
43771
+ }
42311
43772
  case "file-data":
42312
- case "image-data":
43773
+ case "image-data": {
43774
+ if (typeof part["data"] !== "string" || typeof part["mediaType"] !== "string") {
43775
+ return void 0;
43776
+ }
42313
43777
  return {
42314
- data: part.data,
42315
- ...part.type === "file-data" && part.filename !== void 0 ? { filename: part.filename } : {},
42316
- mediaType: part.mediaType,
42317
- type: part.type
43778
+ data: part["data"],
43779
+ ...part["type"] === "file-data" && typeof part["filename"] === "string" ? { filename: part["filename"] } : {},
43780
+ mediaType: part["mediaType"],
43781
+ type: part["type"]
42318
43782
  };
43783
+ }
42319
43784
  case "file-url":
42320
- case "image-url":
43785
+ case "image-url": {
43786
+ if (typeof part["url"] !== "string") {
43787
+ return void 0;
43788
+ }
42321
43789
  return {
42322
- ...part.type === "file-url" && part.mediaType !== void 0 ? { mediaType: part.mediaType } : {},
42323
- type: part.type,
42324
- url: part.url
43790
+ ...part["type"] === "file-url" && typeof part["mediaType"] === "string" ? { mediaType: part["mediaType"] } : {},
43791
+ type: part["type"],
43792
+ url: part["url"]
42325
43793
  };
43794
+ }
42326
43795
  case "file-id":
42327
- case "image-file-id":
42328
- return { fileId: part.fileId, type: part.type };
43796
+ case "image-file-id": {
43797
+ const fileId = part["fileId"];
43798
+ if (typeof fileId !== "string" && !isObject(fileId)) {
43799
+ return void 0;
43800
+ }
43801
+ return { fileId, type: part["type"] };
43802
+ }
42329
43803
  case "file-reference":
42330
- case "image-file-reference":
43804
+ case "image-file-reference": {
43805
+ if (!isObject(part["providerReference"])) {
43806
+ return void 0;
43807
+ }
42331
43808
  return {
42332
- providerReference: part.providerReference,
42333
- type: part.type
43809
+ providerReference: part["providerReference"],
43810
+ type: part["type"]
42334
43811
  };
43812
+ }
43813
+ default:
43814
+ return void 0;
42335
43815
  }
42336
43816
  }
42337
43817
  function isCapturedModelInput(input) {
@@ -42467,18 +43947,54 @@ function createEveInstrumentationProvider(options = {}) {
42467
43947
  recordOutputs: true
42468
43948
  }),
42469
43949
  events: {
42470
- "action.completed": (event, context) => bridge.handleActionTerminal(event, context),
42471
- "action.failed": (event, context) => bridge.handleActionTerminal(event, context),
42472
- "action.started": (event, context) => bridge.handleActionStarted(event, context),
42473
- "model.call.completed": (event, context) => bridge.handleModelTerminal(event, context),
42474
- "model.call.failed": (event, context) => bridge.handleModelTerminal(event, context),
42475
- "model.call.started": (event, context) => bridge.handleModelStarted(event, context),
42476
- "step.attempt.completed": (event) => bridge.handleStepAttemptTerminal(event),
42477
- "step.attempt.failed": (event) => bridge.handleStepAttemptTerminal(event),
42478
- "turn.cancelled": (event, context) => bridge.handleTurnTerminal(event, context),
42479
- "turn.completed": (event, context) => bridge.handleTurnTerminal(event, context),
42480
- "turn.failed": (event, context) => bridge.handleTurnTerminal(event, context),
42481
- "turn.started": (event, context) => bridge.handleTurnStarted(event, context)
43950
+ "action.completed": providerHandler(
43951
+ "action.completed",
43952
+ bridge.handleActionTerminal.bind(bridge)
43953
+ ),
43954
+ "action.failed": providerHandler(
43955
+ "action.failed",
43956
+ bridge.handleActionTerminal.bind(bridge)
43957
+ ),
43958
+ "action.started": providerHandler(
43959
+ "action.started",
43960
+ bridge.handleActionStarted.bind(bridge)
43961
+ ),
43962
+ "model.call.completed": providerHandler(
43963
+ "model.call.completed",
43964
+ bridge.handleModelTerminal.bind(bridge)
43965
+ ),
43966
+ "model.call.failed": providerHandler(
43967
+ "model.call.failed",
43968
+ bridge.handleModelTerminal.bind(bridge)
43969
+ ),
43970
+ "model.call.started": providerHandler(
43971
+ "model.call.started",
43972
+ bridge.handleModelStarted.bind(bridge)
43973
+ ),
43974
+ "step.attempt.completed": providerHandler(
43975
+ "step.attempt.completed",
43976
+ (event) => bridge.handleStepAttemptTerminal(event)
43977
+ ),
43978
+ "step.attempt.failed": providerHandler(
43979
+ "step.attempt.failed",
43980
+ (event) => bridge.handleStepAttemptTerminal(event)
43981
+ ),
43982
+ "turn.cancelled": providerHandler(
43983
+ "turn.cancelled",
43984
+ bridge.handleTurnTerminal.bind(bridge)
43985
+ ),
43986
+ "turn.completed": providerHandler(
43987
+ "turn.completed",
43988
+ bridge.handleTurnTerminal.bind(bridge)
43989
+ ),
43990
+ "turn.failed": providerHandler(
43991
+ "turn.failed",
43992
+ bridge.handleTurnTerminal.bind(bridge)
43993
+ ),
43994
+ "turn.started": providerHandler(
43995
+ "turn.started",
43996
+ bridge.handleTurnStarted.bind(bridge)
43997
+ )
42482
43998
  },
42483
43999
  flush,
42484
44000
  setup: options.setup
@@ -42834,17 +44350,20 @@ function modelOutput(event) {
42834
44350
  const reasoning = [];
42835
44351
  const toolCalls2 = [];
42836
44352
  for (const part of content) {
42837
- if (part.type === "text") {
42838
- text += part.text;
42839
- } else if (part.type === "reasoning" && part.text.trim().length > 0) {
42840
- reasoning.push({ content: part.text });
42841
- } else if (part.type === "tool-call") {
44353
+ if (!isObject(part)) {
44354
+ continue;
44355
+ }
44356
+ if (part["type"] === "text" && typeof part["text"] === "string") {
44357
+ text += part["text"];
44358
+ } else if (part["type"] === "reasoning" && typeof part["text"] === "string" && part["text"].trim().length > 0) {
44359
+ reasoning.push({ content: part["text"] });
44360
+ } else if (part["type"] === "tool-call" && typeof part["toolName"] === "string" && typeof part["callId"] === "string") {
42842
44361
  toolCalls2.push({
42843
44362
  function: {
42844
- arguments: safeJsonStringify(part.input),
42845
- name: part.toolName
44363
+ arguments: safeJsonStringify(part["input"]),
44364
+ name: part["toolName"]
42846
44365
  },
42847
- id: part.callId,
44366
+ id: part["callId"],
42848
44367
  type: "function"
42849
44368
  });
42850
44369
  }
@@ -42863,13 +44382,13 @@ function modelOutput(event) {
42863
44382
  ];
42864
44383
  }
42865
44384
  function usageMetrics(usage) {
42866
- const promptTokens = nonNegativeNumber(usage.inputTokens);
42867
- const completionTokens = nonNegativeNumber(usage.outputTokens);
44385
+ const promptTokens = nonNegativeNumber(usage?.inputTokens);
44386
+ const completionTokens = nonNegativeNumber(usage?.outputTokens);
42868
44387
  const cachedTokens = nonNegativeNumber(
42869
- usage.inputTokenDetails?.cacheReadTokens
44388
+ usage?.inputTokenDetails?.cacheReadTokens
42870
44389
  );
42871
44390
  const cacheCreationTokens = nonNegativeNumber(
42872
- usage.inputTokenDetails?.cacheWriteTokens
44391
+ usage?.inputTokenDetails?.cacheWriteTokens
42873
44392
  );
42874
44393
  return {
42875
44394
  ...promptTokens !== void 0 ? { prompt_tokens: promptTokens } : {},
@@ -42906,10 +44425,76 @@ function turnIdempotencyKey(sessionId, turnId) {
42906
44425
  function actionIdempotencyKey(sessionId, turnId, callId) {
42907
44426
  return `action:${sessionId}:${turnId}:${callId}`;
42908
44427
  }
44428
+ function providerHandler(type, handler) {
44429
+ return async (event, context) => {
44430
+ try {
44431
+ if (!isEveProviderEvent(event, type) || !isEveProviderContext(context)) {
44432
+ debugLogger.warn(`Ignoring malformed Eve provider ${type} event`);
44433
+ return;
44434
+ }
44435
+ await handler(event, context);
44436
+ } catch (error) {
44437
+ debugLogger.warn(`Error in Eve provider ${type}:`, error);
44438
+ }
44439
+ };
44440
+ }
44441
+ function isEveProviderEvent(event, type) {
44442
+ if (!isObject(event) || event["type"] !== type || typeof event["idempotencyKey"] !== "string" || event["idempotencyKey"].length === 0) {
44443
+ return false;
44444
+ }
44445
+ if (type === "turn.started") {
44446
+ const parentLineage = event["parentLineage"];
44447
+ return typeof event["rootSessionId"] === "string" && typeof event["sessionId"] === "string" && typeof event["turnId"] === "string" && typeof event["sequence"] === "number" && Number.isFinite(event["sequence"]) && (parentLineage === void 0 || isEveProviderParentLineage(parentLineage));
44448
+ }
44449
+ if (type === "turn.cancelled" || type === "turn.completed" || type === "turn.failed") {
44450
+ return typeof event["sessionId"] === "string" && typeof event["turnId"] === "string";
44451
+ }
44452
+ if (!isEveProviderScope(event["scope"])) {
44453
+ return false;
44454
+ }
44455
+ if (type === "model.call.started") {
44456
+ const model = event["model"];
44457
+ return isObject(model) && typeof model["modelId"] === "string" && typeof model["provider"] === "string";
44458
+ }
44459
+ if (type === "model.call.completed") {
44460
+ return typeof event["finishReason"] === "string" && isObject(event["usage"]) && (event["content"] === void 0 || Array.isArray(event["content"]));
44461
+ }
44462
+ if (type === "model.call.failed") {
44463
+ return true;
44464
+ }
44465
+ if (type === "action.started") {
44466
+ return typeof event["callId"] === "string" && typeof event["name"] === "string" && (event["kind"] === "load-skill" || event["kind"] === "remote-agent-call" || event["kind"] === "subagent-call" || event["kind"] === "tool-call");
44467
+ }
44468
+ if (type === "action.completed") {
44469
+ const output = event["output"];
44470
+ return event["outcome"] === "completed" && isObject(output) && (output["type"] === "result" || output["type"] === "error");
44471
+ }
44472
+ if (type === "action.failed") {
44473
+ return event["outcome"] === "abandoned" || event["outcome"] === "cancelled" || event["outcome"] === "failed" || event["outcome"] === "rejected";
44474
+ }
44475
+ return type === "step.attempt.completed" || type === "step.attempt.failed";
44476
+ }
44477
+ function isEveProviderContext(value) {
44478
+ if (!isObject(value) || !isObject(value["state"])) {
44479
+ return false;
44480
+ }
44481
+ return typeof value["state"]["get"] === "function" && typeof value["state"]["set"] === "function";
44482
+ }
44483
+ function isEveProviderScope(value) {
44484
+ return isObject(value) && typeof value["attemptId"] === "string" && typeof value["attemptIndex"] === "number" && Number.isFinite(value["attemptIndex"]) && typeof value["sessionId"] === "string" && typeof value["stepIndex"] === "number" && Number.isFinite(value["stepIndex"]) && typeof value["turnId"] === "string" && (value["rootSessionId"] === void 0 || typeof value["rootSessionId"] === "string");
44485
+ }
44486
+ function isEveProviderParentLineage(value) {
44487
+ return isObject(value) && typeof value["callId"] === "string" && typeof value["sessionId"] === "string" && typeof value["turnId"] === "string";
44488
+ }
42909
44489
 
42910
44490
  // src/instrumentation/plugins/eve-instrumentation.ts
42911
44491
  var EVE_INSTRUMENTATION_PROVIDER = /* @__PURE__ */ Symbol.for("eve.instrumentation.provider");
42912
44492
  function braintrustEveInstrumentation(options) {
44493
+ if (!options || typeof options !== "object") {
44494
+ throw new TypeError(
44495
+ "braintrustEveInstrumentation requires an options object"
44496
+ );
44497
+ }
42913
44498
  const definition = "defineState" in options ? createLegacyEveInstrumentation(options) : createEveInstrumentationProvider(options);
42914
44499
  const declaration = {
42915
44500
  ...definition,
@@ -44146,6 +45731,7 @@ function wrapClient(client) {
44146
45731
  }
44147
45732
 
44148
45733
  // src/wrappers/google-genai.ts
45734
+ var patchedHttpResponses = /* @__PURE__ */ new WeakSet();
44149
45735
  function wrapGoogleGenAI(googleGenAI) {
44150
45736
  if (!googleGenAI || typeof googleGenAI !== "object") {
44151
45737
  console.warn("Invalid Google GenAI module. Not wrapping.");
@@ -44157,6 +45743,21 @@ function wrapGoogleGenAI(googleGenAI) {
44157
45743
  );
44158
45744
  return googleGenAI;
44159
45745
  }
45746
+ const httpResponse = googleGenAI.HttpResponse;
45747
+ if (typeof httpResponse === "function" && isObject(httpResponse.prototype) && typeof httpResponse.prototype.json === "function" && !patchedHttpResponses.has(httpResponse.prototype)) {
45748
+ const prototype = httpResponse.prototype;
45749
+ const originalJson = prototype.json;
45750
+ if (Reflect.set(prototype, "json", function() {
45751
+ return googleGenAIChannels.httpResponseJson.invoke(
45752
+ originalJson,
45753
+ this,
45754
+ [],
45755
+ {}
45756
+ );
45757
+ })) {
45758
+ patchedHttpResponses.add(prototype);
45759
+ }
45760
+ }
44160
45761
  return new Proxy(googleGenAI, {
44161
45762
  get(target, prop, receiver) {
44162
45763
  if (prop === "GoogleGenAI") {
@@ -44407,17 +46008,17 @@ function wrapGenkit(genkit) {
44407
46008
  console.warn("Unsupported Genkit object. Not wrapping.");
44408
46009
  return genkit;
44409
46010
  }
44410
- function isRecord3(value) {
46011
+ function isRecord4(value) {
44411
46012
  return typeof value === "object" && value !== null;
44412
46013
  }
44413
46014
  function isPropertyBag(value) {
44414
- return isRecord3(value) || typeof value === "function";
46015
+ return isRecord4(value) || typeof value === "function";
44415
46016
  }
44416
46017
  function hasFunction(value, methodName) {
44417
46018
  return isPropertyBag(value) && methodName in value && typeof value[methodName] === "function";
44418
46019
  }
44419
46020
  function isGenkitInstance(value) {
44420
- return isRecord3(value) && (hasFunction(value, "generate") || hasFunction(value, "generateStream") || hasFunction(value, "defineFlow") || hasFunction(value, "defineTool"));
46021
+ return isRecord4(value) && (hasFunction(value, "generate") || hasFunction(value, "generateStream") || hasFunction(value, "defineFlow") || hasFunction(value, "defineTool"));
44421
46022
  }
44422
46023
  function isGenkitModule(value) {
44423
46024
  return hasFunction(value, "genkit");
@@ -44471,7 +46072,7 @@ function patchGenkitRegistry(instance) {
44471
46072
  patchGenkitRegistryConstructor(registry2);
44472
46073
  }
44473
46074
  function patchGenkitRegistryLookup(registry2) {
44474
- if (!isRecord3(registry2) || hasRegistryPatchedFlag(registry2) || !hasFunction(registry2, "lookupAction")) {
46075
+ if (!isRecord4(registry2) || hasRegistryPatchedFlag(registry2) || !hasFunction(registry2, "lookupAction")) {
44475
46076
  return;
44476
46077
  }
44477
46078
  const originalLookupAction = registry2.lookupAction;
@@ -44497,7 +46098,7 @@ function patchGenkitRegistryLookup(registry2) {
44497
46098
  }
44498
46099
  }
44499
46100
  function patchGenkitRegistryConstructor(registry2) {
44500
- if (!isRecord3(registry2)) {
46101
+ if (!isRecord4(registry2)) {
44501
46102
  return;
44502
46103
  }
44503
46104
  const constructor = registry2.constructor;
@@ -44513,7 +46114,7 @@ function patchGenkitRegistryConstructor(registry2) {
44513
46114
  configurable: true,
44514
46115
  value: (...args) => {
44515
46116
  const childRegistry = originalWithParent.apply(constructor, args);
44516
- if (args.some((arg) => isRecord3(arg) && hasRegistryPatchedFlag(arg))) {
46117
+ if (args.some((arg) => isRecord4(arg) && hasRegistryPatchedFlag(arg))) {
44517
46118
  patchGenkitRegistryLookup(childRegistry);
44518
46119
  patchGenkitRegistryConstructor(childRegistry);
44519
46120
  }
@@ -44612,7 +46213,7 @@ function hasRegistryConstructorPatchedFlag(value) {
44612
46213
  );
44613
46214
  }
44614
46215
  function isPromiseLike2(value) {
44615
- return isRecord3(value) && "then" in value && typeof value.then === "function";
46216
+ return isRecord4(value) && "then" in value && typeof value.then === "function";
44616
46217
  }
44617
46218
 
44618
46219
  // src/wrappers/huggingface.ts
@@ -45089,14 +46690,14 @@ function wrapMistral(mistral) {
45089
46690
  console.warn("Unsupported Mistral library. Not wrapping.");
45090
46691
  return mistral;
45091
46692
  }
45092
- function isRecord4(value) {
46693
+ function isRecord5(value) {
45093
46694
  return typeof value === "object" && value !== null;
45094
46695
  }
45095
46696
  function hasFunction3(value, methodName) {
45096
- return isRecord4(value) && methodName in value && typeof value[methodName] === "function";
46697
+ return isRecord5(value) && methodName in value && typeof value[methodName] === "function";
45097
46698
  }
45098
46699
  function isSupportedMistralClient(value) {
45099
- if (!isRecord4(value)) {
46700
+ if (!isRecord5(value)) {
45100
46701
  return false;
45101
46702
  }
45102
46703
  return value.chat !== void 0 && hasChat(value.chat) || value.embeddings !== void 0 && hasEmbeddings(value.embeddings) || value.fim !== void 0 && hasFim(value.fim) || value.agents !== void 0 && hasAgents(value.agents) || value.classifiers !== void 0 && hasClassifiers(value.classifiers);
@@ -45271,6 +46872,42 @@ function wrapAgentsStream(stream) {
45271
46872
  });
45272
46873
  }
45273
46874
 
46875
+ // src/wrappers/langgraph-sdk.ts
46876
+ var clients = /* @__PURE__ */ new WeakMap();
46877
+ function wrapLangGraphSDK(client) {
46878
+ const runsClient = isObject(client) ? client.runs : void 0;
46879
+ if (!isObject(client) || !isObject(runsClient) || !["wait", "stream"].every((key) => typeof runsClient[key] === "function")) {
46880
+ debugLogger.warn("Unsupported LangGraph SDK client. Not wrapping.");
46881
+ return client;
46882
+ }
46883
+ const sdk = client;
46884
+ const cached = clients.get(sdk);
46885
+ if (cached) return cached;
46886
+ const runs = new Proxy(sdk.runs, {
46887
+ get(target, key) {
46888
+ switch (key) {
46889
+ case "wait":
46890
+ return (...args) => langGraphSDKChannels.wait.invoke(target.wait, target, args, {});
46891
+ case "stream":
46892
+ return (...args) => langGraphSDKChannels.stream.invoke(target.stream, target, args, {});
46893
+ default:
46894
+ const value = Reflect.get(target, key, target);
46895
+ return typeof value === "function" ? value.bind(target) : value;
46896
+ }
46897
+ }
46898
+ });
46899
+ const wrapped = new Proxy(sdk, {
46900
+ get(target, key) {
46901
+ if (key === "runs") return runs;
46902
+ const value = Reflect.get(target, key, target);
46903
+ return typeof value === "function" ? value.bind(target) : value;
46904
+ }
46905
+ });
46906
+ clients.set(sdk, wrapped);
46907
+ clients.set(wrapped, wrapped);
46908
+ return wrapped;
46909
+ }
46910
+
45274
46911
  // src/wrappers/ollama.ts
45275
46912
  function wrapOllama(ollama) {
45276
46913
  if (isSupportedOllamaClient(ollama)) {
@@ -45357,14 +46994,14 @@ function wrapCohere(cohere) {
45357
46994
  return cohere;
45358
46995
  }
45359
46996
  var cohereProxyCache = /* @__PURE__ */ new WeakMap();
45360
- function isRecord5(value) {
46997
+ function isRecord6(value) {
45361
46998
  return typeof value === "object" && value !== null;
45362
46999
  }
45363
47000
  function hasFunction4(value, methodName) {
45364
- return isRecord5(value) && methodName in value && typeof value[methodName] === "function";
47001
+ return isRecord6(value) && methodName in value && typeof value[methodName] === "function";
45365
47002
  }
45366
47003
  function isSupportedCohereClient(value) {
45367
- if (!isRecord5(value)) {
47004
+ if (!isRecord6(value)) {
45368
47005
  return false;
45369
47006
  }
45370
47007
  return hasFunction4(value, "chat") || hasFunction4(value, "chatStream") || hasFunction4(value, "embed") || hasFunction4(value, "rerank");
@@ -45502,20 +47139,20 @@ function wrapGroq(groq) {
45502
47139
  console.warn("Unsupported Groq library. Not wrapping.");
45503
47140
  return groq;
45504
47141
  }
45505
- function isRecord6(value) {
47142
+ function isRecord7(value) {
45506
47143
  return typeof value === "object" && value !== null;
45507
47144
  }
45508
47145
  function hasFunction6(value, methodName) {
45509
- return isRecord6(value) && methodName in value && typeof value[methodName] === "function";
47146
+ return isRecord7(value) && methodName in value && typeof value[methodName] === "function";
45510
47147
  }
45511
47148
  function hasChat2(value) {
45512
- return isRecord6(value) && isRecord6(value.completions) && hasFunction6(value.completions, "create");
47149
+ return isRecord7(value) && isRecord7(value.completions) && hasFunction6(value.completions, "create");
45513
47150
  }
45514
47151
  function hasEmbeddings2(value) {
45515
47152
  return hasFunction6(value, "create");
45516
47153
  }
45517
47154
  function isSupportedGroqClient(value) {
45518
- return isRecord6(value) && (value.chat !== void 0 && hasChat2(value.chat) || value.embeddings !== void 0 && hasEmbeddings2(value.embeddings));
47155
+ return isRecord7(value) && (value.chat !== void 0 && hasChat2(value.chat) || value.embeddings !== void 0 && hasEmbeddings2(value.embeddings));
45519
47156
  }
45520
47157
  function groqProxy(groq) {
45521
47158
  const privateMethodWorkaroundCache = /* @__PURE__ */ new WeakMap();
@@ -45598,11 +47235,11 @@ var BEDROCK_RUNTIME_OPERATION_METHODS = /* @__PURE__ */ new Set([
45598
47235
  "invokeModelWithBidirectionalStream",
45599
47236
  "invokeModelWithResponseStream"
45600
47237
  ]);
45601
- function isRecord7(value) {
47238
+ function isRecord8(value) {
45602
47239
  return typeof value === "object" && value !== null;
45603
47240
  }
45604
47241
  function isSupportedBedrockRuntimeClient(value) {
45605
- return isRecord7(value) && typeof value.send === "function";
47242
+ return isRecord8(value) && typeof value.send === "function";
45606
47243
  }
45607
47244
  function bedrockRuntimeProxy(client) {
45608
47245
  const cached = bedrockRuntimeProxyCache.get(client);
@@ -47928,12 +49565,272 @@ function waterfall(tasks, callback) {
47928
49565
  }
47929
49566
  var waterfall$1 = awaitify(waterfall);
47930
49567
 
49568
+ // src/framework.ts
49569
+ var import_uuid3 = require("uuid");
49570
+
47931
49571
  // src/trace.ts
49572
+ var spanFilterFields = /* @__PURE__ */ new Set([
49573
+ "spanType",
49574
+ "name",
49575
+ "hasError",
49576
+ "metadata",
49577
+ "duration"
49578
+ ]);
49579
+ function isRecord9(value) {
49580
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
49581
+ return false;
49582
+ }
49583
+ const prototype = Object.getPrototypeOf(value);
49584
+ return prototype === Object.prototype || prototype === null;
49585
+ }
49586
+ function validateMetadataValue(value, ancestors) {
49587
+ if (value === null || typeof value === "string" || typeof value === "boolean") {
49588
+ return;
49589
+ }
49590
+ if (typeof value === "number") {
49591
+ if (Number.isFinite(value)) {
49592
+ return;
49593
+ }
49594
+ throw new Error("filters.metadata numbers must be finite");
49595
+ }
49596
+ if (typeof value !== "object" || value === null) {
49597
+ throw new Error("filters.metadata values must be JSON-serializable");
49598
+ }
49599
+ if (!Array.isArray(value) && !isRecord9(value)) {
49600
+ throw new Error("filters.metadata values must be JSON-serializable");
49601
+ }
49602
+ if (ancestors.has(value)) {
49603
+ throw new Error("filters.metadata must not contain cycles");
49604
+ }
49605
+ ancestors.add(value);
49606
+ if (Array.isArray(value)) {
49607
+ for (let index = 0; index < value.length; index++) {
49608
+ validateMetadataValue(value[index], ancestors);
49609
+ }
49610
+ } else {
49611
+ if (Object.getOwnPropertySymbols(value).length > 0) {
49612
+ throw new Error("filters.metadata keys must be strings");
49613
+ }
49614
+ for (const nested of Object.values(value)) {
49615
+ validateMetadataValue(nested, ancestors);
49616
+ }
49617
+ }
49618
+ ancestors.delete(value);
49619
+ }
49620
+ function compileMetadataLeaves(metadata, path = [], ancestors = /* @__PURE__ */ new WeakSet()) {
49621
+ if (Object.getOwnPropertySymbols(metadata).length > 0) {
49622
+ throw new Error("filters.metadata keys must be strings");
49623
+ }
49624
+ if (ancestors.has(metadata)) {
49625
+ throw new Error("filters.metadata must not contain cycles");
49626
+ }
49627
+ ancestors.add(metadata);
49628
+ const leaves = [];
49629
+ for (const [key, value] of Object.entries(metadata)) {
49630
+ const childPath = [...path, key];
49631
+ if (isRecord9(value)) {
49632
+ leaves.push(...compileMetadataLeaves(value, childPath, ancestors));
49633
+ } else {
49634
+ validateMetadataValue(value, ancestors);
49635
+ leaves.push([childPath, value]);
49636
+ }
49637
+ }
49638
+ ancestors.delete(metadata);
49639
+ return leaves;
49640
+ }
49641
+ function normalizeSpanFilters(filters, spanType) {
49642
+ if (filters != null && !isRecord9(filters)) {
49643
+ throw new Error("filters must be an object");
49644
+ }
49645
+ const values = { ...filters ?? {} };
49646
+ if (spanType !== void 0) {
49647
+ if (!Array.isArray(spanType) || !spanType.every((item) => typeof item === "string")) {
49648
+ throw new Error("spanType must be an array of strings");
49649
+ }
49650
+ if (Object.hasOwn(values, "spanType")) {
49651
+ throw new Error(
49652
+ "spanType cannot be provided both directly and in filters"
49653
+ );
49654
+ }
49655
+ if (spanType.length > 0) {
49656
+ values.spanType = spanType;
49657
+ }
49658
+ }
49659
+ if (Object.keys(values).some((field) => !spanFilterFields.has(field))) {
49660
+ throw new Error("Unsupported span filter fields");
49661
+ }
49662
+ for (const field of ["spanType", "name"]) {
49663
+ if (Object.hasOwn(values, field)) {
49664
+ const items = values[field];
49665
+ if (!Array.isArray(items) || !items.every((item) => typeof item === "string")) {
49666
+ throw new Error(`filters.${field} must be an array of strings`);
49667
+ }
49668
+ }
49669
+ }
49670
+ if (Object.hasOwn(values, "hasError") && typeof values.hasError !== "boolean") {
49671
+ throw new Error("filters.hasError must be a boolean");
49672
+ }
49673
+ let compiledMetadataLeaves = [];
49674
+ if (Object.hasOwn(values, "metadata")) {
49675
+ if (!isRecord9(values.metadata)) {
49676
+ throw new Error("filters.metadata must be an object");
49677
+ }
49678
+ compiledMetadataLeaves = compileMetadataLeaves(values.metadata);
49679
+ }
49680
+ if (Object.hasOwn(values, "duration")) {
49681
+ if (!isRecord9(values.duration) || Object.keys(values.duration).some(
49682
+ (bound) => bound !== "min" && bound !== "max"
49683
+ )) {
49684
+ throw new Error("filters.duration must contain only min and/or max");
49685
+ }
49686
+ if (Object.values(values.duration).some(
49687
+ (bound) => typeof bound !== "number" || !Number.isFinite(bound)
49688
+ )) {
49689
+ throw new Error("filters.duration bounds must be finite numbers");
49690
+ }
49691
+ }
49692
+ const normalized = {};
49693
+ if (Array.isArray(values.spanType)) {
49694
+ normalized.spanType = values.spanType;
49695
+ }
49696
+ if (Array.isArray(values.name)) {
49697
+ normalized.name = values.name;
49698
+ }
49699
+ if (typeof values.hasError === "boolean") {
49700
+ normalized.hasError = values.hasError;
49701
+ }
49702
+ if (isRecord9(values.metadata)) {
49703
+ normalized.metadata = values.metadata;
49704
+ }
49705
+ if (isRecord9(values.duration)) {
49706
+ normalized.duration = {};
49707
+ if (typeof values.duration.min === "number") {
49708
+ normalized.duration.min = values.duration.min;
49709
+ }
49710
+ if (typeof values.duration.max === "number") {
49711
+ normalized.duration.max = values.duration.max;
49712
+ }
49713
+ }
49714
+ return { filters: normalized, metadataLeaves: compiledMetadataLeaves };
49715
+ }
49716
+ function metadataEqual(actual, expected) {
49717
+ if (expected === null) {
49718
+ return actual === null || actual === void 0;
49719
+ }
49720
+ if (Array.isArray(expected)) {
49721
+ return Array.isArray(actual) && actual.length === expected.length && expected.every((value, index) => metadataEqual(actual[index], value));
49722
+ }
49723
+ if (isRecord9(expected)) {
49724
+ if (!isRecord9(actual)) {
49725
+ return false;
49726
+ }
49727
+ const expectedKeys = Object.keys(expected);
49728
+ const actualKeys = Object.keys(actual);
49729
+ return actualKeys.length === expectedKeys.length && expectedKeys.every(
49730
+ (key) => Object.hasOwn(actual, key) && metadataEqual(actual[key], expected[key])
49731
+ );
49732
+ }
49733
+ return actual === expected;
49734
+ }
49735
+ function matchesSpanFilters(span, compiledFilters) {
49736
+ const { filters, metadataLeaves } = compiledFilters;
49737
+ if (filters.spanType !== void 0 && !filters.spanType.includes(span.span_attributes?.type ?? "")) {
49738
+ return false;
49739
+ }
49740
+ if (filters.name !== void 0 && !filters.name.includes(span.span_attributes?.name ?? "")) {
49741
+ return false;
49742
+ }
49743
+ if (filters.hasError !== void 0 && (span.error !== null && span.error !== void 0) !== filters.hasError) {
49744
+ return false;
49745
+ }
49746
+ for (const [path, expected] of metadataLeaves) {
49747
+ let actual = span.metadata;
49748
+ for (const key of path) {
49749
+ actual = isRecord9(actual) && Object.hasOwn(actual, key) ? actual[key] : void 0;
49750
+ }
49751
+ if (!metadataEqual(actual, expected)) {
49752
+ return false;
49753
+ }
49754
+ }
49755
+ if (filters.duration && Object.keys(filters.duration).length > 0) {
49756
+ const metrics = span.metrics;
49757
+ const start = isRecord9(metrics) ? metrics.start : void 0;
49758
+ const end = isRecord9(metrics) ? metrics.end : void 0;
49759
+ if (typeof start !== "number" || !Number.isFinite(start) || typeof end !== "number" || !Number.isFinite(end)) {
49760
+ return false;
49761
+ }
49762
+ const elapsed = end - start;
49763
+ if (filters.duration.min !== void 0 && elapsed < filters.duration.min) {
49764
+ return false;
49765
+ }
49766
+ if (filters.duration.max !== void 0 && elapsed > filters.duration.max) {
49767
+ return false;
49768
+ }
49769
+ }
49770
+ return true;
49771
+ }
49772
+ function btqlComparison(op, name, value) {
49773
+ return {
49774
+ op,
49775
+ left: { op: "ident", name },
49776
+ right: { op: "literal", value }
49777
+ };
49778
+ }
49779
+ function btqlNullCheck(op, name) {
49780
+ return { op, expr: { op: "ident", name } };
49781
+ }
49782
+ function spanFilterClauses(compiledFilters) {
49783
+ const { filters, metadataLeaves } = compiledFilters;
49784
+ const children = [];
49785
+ for (const [field, attribute] of [
49786
+ ["spanType", "type"],
49787
+ ["name", "name"]
49788
+ ]) {
49789
+ const values = filters[field];
49790
+ if (values !== void 0) {
49791
+ children.push(
49792
+ values.length > 0 ? btqlComparison("in", ["span_attributes", attribute], values) : { op: "literal", value: false }
49793
+ );
49794
+ }
49795
+ }
49796
+ if (filters.hasError !== void 0) {
49797
+ children.push(
49798
+ btqlNullCheck(filters.hasError ? "isnotnull" : "isnull", ["error"])
49799
+ );
49800
+ }
49801
+ for (const [path, value] of metadataLeaves) {
49802
+ const name = ["metadata", ...path];
49803
+ children.push(
49804
+ value === null ? btqlNullCheck("isnull", name) : btqlComparison("eq", name, value)
49805
+ );
49806
+ }
49807
+ const elapsed = {
49808
+ op: "sub",
49809
+ left: { op: "ident", name: ["metrics", "end"] },
49810
+ right: { op: "ident", name: ["metrics", "start"] }
49811
+ };
49812
+ if (filters.duration?.min !== void 0) {
49813
+ children.push({
49814
+ op: "ge",
49815
+ left: elapsed,
49816
+ right: { op: "literal", value: filters.duration.min }
49817
+ });
49818
+ }
49819
+ if (filters.duration?.max !== void 0) {
49820
+ children.push({
49821
+ op: "le",
49822
+ left: elapsed,
49823
+ right: { op: "literal", value: filters.duration.max }
49824
+ });
49825
+ }
49826
+ return children;
49827
+ }
47932
49828
  var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
47933
- constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false, brainstoreRealtime = true) {
49829
+ constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false, brainstoreRealtime = true, filters) {
49830
+ const normalizedFilters = normalizeSpanFilters(filters, spanTypeFilter);
47934
49831
  const filterExpr = _SpanFetcher.buildFilter(
47935
49832
  rootSpanId,
47936
- spanTypeFilter,
49833
+ normalizedFilters,
47937
49834
  includeScorers
47938
49835
  );
47939
49836
  super(
@@ -47954,42 +49851,22 @@ var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
47954
49851
  rootSpanId;
47955
49852
  _state;
47956
49853
  spanTypeFilter;
47957
- static buildFilter(rootSpanId, spanTypeFilter, includeScorers = false) {
49854
+ static buildFilter(rootSpanId, filters, includeScorers = false) {
49855
+ const purpose = ["span_attributes", "purpose"];
47958
49856
  const children = [
47959
- // Base filter: root_span_id = 'value'
47960
- {
47961
- op: "eq",
47962
- left: { op: "ident", name: ["root_span_id"] },
47963
- right: { op: "literal", value: rootSpanId }
47964
- }
49857
+ btqlComparison("eq", ["root_span_id"], rootSpanId)
47965
49858
  ];
47966
49859
  if (!includeScorers) {
47967
49860
  children.push({
47968
49861
  op: "or",
47969
49862
  children: [
47970
- {
47971
- op: "isnull",
47972
- expr: { op: "ident", name: ["span_attributes", "purpose"] }
47973
- },
47974
- {
47975
- op: "ne",
47976
- left: { op: "ident", name: ["span_attributes", "purpose"] },
47977
- right: { op: "literal", value: "scorer" }
47978
- }
49863
+ btqlNullCheck("isnull", purpose),
49864
+ btqlComparison("ne", purpose, "scorer")
47979
49865
  ]
47980
49866
  });
47981
49867
  }
47982
- if (spanTypeFilter && spanTypeFilter.length > 0) {
47983
- children.push({
47984
- op: "in",
47985
- left: { op: "ident", name: ["span_attributes", "type"] },
47986
- right: { op: "literal", value: spanTypeFilter }
47987
- });
47988
- }
47989
- return {
47990
- op: "and",
47991
- children
47992
- };
49868
+ children.push(...spanFilterClauses(filters));
49869
+ return { op: "and", children };
47993
49870
  }
47994
49871
  get id() {
47995
49872
  return Promise.resolve(this._objectId);
@@ -48004,67 +49881,80 @@ var CachedSpanFetcher = class {
48004
49881
  fetchFn;
48005
49882
  constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState, brainstoreRealtime = true) {
48006
49883
  if (typeof objectTypeOrFetchFn === "function") {
48007
- this.fetchFn = (spanType) => objectTypeOrFetchFn(spanType);
49884
+ this.fetchFn = async (filters) => (await objectTypeOrFetchFn(filters.filters.spanType)).filter(
49885
+ (span) => matchesSpanFilters(span, filters)
49886
+ );
48008
49887
  } else {
48009
49888
  const objectType = objectTypeOrFetchFn;
48010
- this.fetchFn = async (spanType, includeScorers) => {
49889
+ this.fetchFn = async (filters, includeScorers) => {
48011
49890
  const state = await getState();
48012
49891
  const fetcher = new SpanFetcher(
48013
49892
  objectType,
48014
49893
  objectId,
48015
49894
  rootSpanId,
48016
49895
  state,
48017
- spanType,
49896
+ void 0,
48018
49897
  includeScorers,
48019
- brainstoreRealtime
49898
+ brainstoreRealtime,
49899
+ filters.filters
48020
49900
  );
48021
- const rows = await fetcher.fetchedData();
48022
- return rows.map((row) => ({
48023
- input: row.input,
48024
- output: row.output,
48025
- expected: row.expected,
48026
- error: row.error,
48027
- scores: row.scores,
48028
- metrics: row.metrics,
48029
- metadata: row.metadata,
48030
- span_id: row.span_id,
48031
- span_parents: row.span_parents,
48032
- is_root: row.is_root,
48033
- span_attributes: row.span_attributes,
48034
- id: row.id,
48035
- _xact_id: row._xact_id,
48036
- _pagination_key: row._pagination_key,
48037
- root_span_id: row.root_span_id,
48038
- created: row.created,
48039
- tags: row.tags
48040
- }));
49901
+ let spans = (await fetcher.fetchedData()).map(
49902
+ (row) => ({ ...row })
49903
+ );
49904
+ if (filters.filters.metadata !== void 0) {
49905
+ spans = spans.filter((span) => matchesSpanFilters(span, filters));
49906
+ }
49907
+ return spans;
48041
49908
  };
48042
49909
  }
48043
49910
  }
48044
49911
  async getSpans({
48045
- spanType,
49912
+ spanType: requestedSpanType,
49913
+ filters,
48046
49914
  includeScorers = false
48047
49915
  } = {}) {
49916
+ const normalizedFilters = normalizeSpanFilters(filters, requestedSpanType);
49917
+ const spanType = normalizedFilters.filters.spanType;
49918
+ const hasAdvancedFilters = Object.keys(normalizedFilters.filters).some(
49919
+ (field) => field !== "spanType"
49920
+ );
49921
+ if (spanType?.length === 0) {
49922
+ return [];
49923
+ }
48048
49924
  if (includeScorers) {
48049
- return this.fetchFn(spanType, true);
49925
+ return this.fetchFn(normalizedFilters, true);
48050
49926
  }
48051
49927
  if (this.allFetched) {
48052
- return this.getFromCache(spanType);
49928
+ const spans = this.getFromCache(spanType);
49929
+ return hasAdvancedFilters ? spans.filter((span) => matchesSpanFilters(span, normalizedFilters)) : spans;
48053
49930
  }
48054
- if (!spanType || spanType.length === 0) {
49931
+ if (hasAdvancedFilters && spanType && spanType.every((type) => this.spanCache.has(type))) {
49932
+ return this.getFromCache(spanType).filter(
49933
+ (span) => matchesSpanFilters(span, normalizedFilters)
49934
+ );
49935
+ }
49936
+ if (hasAdvancedFilters) {
49937
+ return this.fetchFn(normalizedFilters, false);
49938
+ }
49939
+ if (!spanType) {
49940
+ this.spanCache.clear();
48055
49941
  await this.fetchSpans(void 0);
48056
- this.allFetched = true;
49942
+ if (this.spanCache.size > 0) {
49943
+ this.allFetched = true;
49944
+ }
48057
49945
  return this.getFromCache(void 0);
48058
49946
  }
48059
- const missingTypes = spanType.filter((t) => !this.spanCache.has(t));
48060
- if (missingTypes.length === 0) {
48061
- return this.getFromCache(spanType);
49947
+ const missingTypes = spanType.filter((type) => !this.spanCache.has(type));
49948
+ if (missingTypes.length > 0) {
49949
+ await this.fetchSpans(missingTypes);
48062
49950
  }
48063
- await this.fetchSpans(missingTypes);
48064
49951
  return this.getFromCache(spanType);
48065
49952
  }
48066
49953
  async fetchSpans(spanType) {
48067
- const spans = await this.fetchFn(spanType, false);
49954
+ const spans = await this.fetchFn(
49955
+ normalizeSpanFilters(spanType ? { spanType } : void 0),
49956
+ false
49957
+ );
48068
49958
  for (const span of spans) {
48069
49959
  const type = span.span_attributes?.type ?? "";
48070
49960
  const existing = this.spanCache.get(type) ?? [];
@@ -48144,34 +50034,20 @@ var LocalTrace = class {
48144
50034
  */
48145
50035
  async getSpans({
48146
50036
  spanType,
50037
+ filters,
48147
50038
  includeScorers = false
48148
50039
  } = {}) {
50040
+ const normalizedFilters = normalizeSpanFilters(filters, spanType);
48149
50041
  const cachedSpans = this.state.spanCache.getByRootSpanId(this.rootSpanId);
48150
50042
  if (cachedSpans && cachedSpans.length > 0) {
48151
- let spans = includeScorers ? cachedSpans : cachedSpans.filter(
48152
- (span) => span.span_attributes?.purpose !== "scorer"
48153
- );
48154
- if (spanType && spanType.length > 0) {
48155
- spans = spans.filter(
48156
- (span) => spanType.includes(span.span_attributes?.type ?? "")
48157
- );
48158
- }
48159
- return spans.map((span) => ({
48160
- input: span.input,
48161
- output: span.output,
48162
- expected: span.expected,
48163
- error: span.error,
48164
- scores: span.scores,
48165
- metrics: span.metrics,
48166
- metadata: span.metadata,
48167
- span_id: span.span_id,
48168
- span_parents: span.span_parents,
48169
- is_root: span.is_root,
48170
- span_attributes: span.span_attributes,
48171
- tags: span.tags
48172
- }));
48173
- }
48174
- return this.cachedFetcher.getSpans({ spanType, includeScorers });
50043
+ return cachedSpans.filter(
50044
+ (span) => (includeScorers || span.span_attributes?.purpose !== "scorer") && matchesSpanFilters({ ...span }, normalizedFilters)
50045
+ ).map((span) => ({ ...span }));
50046
+ }
50047
+ return this.cachedFetcher.getSpans({
50048
+ filters: normalizedFilters.filters,
50049
+ includeScorers
50050
+ });
48175
50051
  }
48176
50052
  /**
48177
50053
  * Get the thread (preprocessed messages) for this trace.
@@ -48591,7 +50467,7 @@ async function Eval(name, evaluator, reporterOrOpts) {
48591
50467
  data,
48592
50468
  { disabled: Boolean(options.parent || options.noSendLogs) }
48593
50469
  );
48594
- if (experiment && typeof process !== "undefined" && globalThis.BRAINTRUST_CONTEXT_MANAGER !== void 0) {
50470
+ if (experiment) {
48595
50471
  await experiment._waitForId();
48596
50472
  }
48597
50473
  if (experiment && options.onStart) {
@@ -48916,6 +50792,10 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
48916
50792
  } : void 0;
48917
50793
  const parsedDatumOrigin = ObjectReference.safeParse(datum.origin);
48918
50794
  const origin = inlineDatasetOrigin ?? (parsedDatumOrigin?.success ? parsedDatumOrigin.data : void 0);
50795
+ const upsertId = datum.upsert_id && trialIndex > 0 ? (0, import_uuid3.v5)(
50796
+ `braintrust:eval:${datum.upsert_id}:trial:${trialIndex}`,
50797
+ import_uuid3.v5.URL
50798
+ ) : datum.upsert_id;
48919
50799
  const baseEvent = {
48920
50800
  name: "eval",
48921
50801
  spanAttributes: {
@@ -48926,7 +50806,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
48926
50806
  expected: "expected" in datum ? datum.expected : void 0,
48927
50807
  tags: datum.tags,
48928
50808
  origin,
48929
- ...datum.upsert_id ? { id: datum.upsert_id } : {}
50809
+ ...upsertId ? { id: upsertId } : {}
48930
50810
  }
48931
50811
  };
48932
50812
  const callback = async (rootSpan) => {
@@ -49435,14 +51315,14 @@ var defaultReporter = {
49435
51315
  }
49436
51316
  };
49437
51317
 
49438
- // src/durable-eval.ts
51318
+ // src/workflow-eval.ts
49439
51319
  var encoder = new TextEncoder();
49440
51320
  var decoder = new TextDecoder();
49441
- var BATCH_TASK_KIND = "braintrust.durable.batch-task";
49442
- var BATCH_SCORER_KIND = "braintrust.durable.batch-scorer";
49443
- var DEFAULT_BATCH_SIZE = 1e3;
49444
- var DurableEvalMemoryStore = class {
51321
+ var WORKFLOW_TASK_KIND = "braintrust.workflow.task";
51322
+ var WORKFLOW_SCORER_KIND = "braintrust.workflow.scorer";
51323
+ var WorkflowEvalMemoryStore = class {
49445
51324
  values = /* @__PURE__ */ new Map();
51325
+ sets = /* @__PURE__ */ new Map();
49446
51326
  async read(key) {
49447
51327
  return this.values.get(key)?.slice();
49448
51328
  }
@@ -49455,8 +51335,16 @@ var DurableEvalMemoryStore = class {
49455
51335
  this.values.set(key, value.slice());
49456
51336
  return { value: value.slice(), created: true };
49457
51337
  }
51338
+ async addToSet(key, member) {
51339
+ let members = this.sets.get(key);
51340
+ if (!members) this.sets.set(key, members = /* @__PURE__ */ new Set());
51341
+ members.add(member);
51342
+ }
51343
+ async getSetSize(key) {
51344
+ return this.sets.get(key)?.size ?? 0;
51345
+ }
49458
51346
  };
49459
- var DurableEvalRedisStore = class {
51347
+ var WorkflowEvalRedisStore = class {
49460
51348
  client;
49461
51349
  keyPrefix;
49462
51350
  ttlMs;
@@ -49465,14 +51353,16 @@ var DurableEvalRedisStore = class {
49465
51353
  this.keyPrefix = options.keyPrefix ?? "braintrust-eval:";
49466
51354
  this.ttlMs = options.ttlMs ?? 1e3 * 60 * 60 * 24 * 7;
49467
51355
  if (!Number.isInteger(this.ttlMs) || this.ttlMs < 1) {
49468
- throw new Error("DurableEvalRedisStore ttlMs must be a positive integer");
51356
+ throw new Error(
51357
+ "WorkflowEvalRedisStore ttlMs must be a positive integer"
51358
+ );
49469
51359
  }
49470
51360
  }
49471
51361
  async read(key) {
49472
51362
  const value = await this.client.get(`${this.keyPrefix}${key}`);
49473
51363
  if (value == null) return void 0;
49474
51364
  if (typeof value !== "string") {
49475
- throw new Error("DurableEvalRedisStore expected GET to return a string");
51365
+ throw new Error("WorkflowEvalRedisStore expected GET to return a string");
49476
51366
  }
49477
51367
  return base64ToUint8Array(value);
49478
51368
  }
@@ -49489,7 +51379,7 @@ var DurableEvalRedisStore = class {
49489
51379
  await set.call(client, redisKey, encoded, { px: this.ttlMs });
49490
51380
  } else {
49491
51381
  throw new Error(
49492
- "DurableEvalRedisStore requires a node-redis, ioredis, or @upstash/redis client"
51382
+ "WorkflowEvalRedisStore requires a node-redis, ioredis, or @upstash/redis client"
49493
51383
  );
49494
51384
  }
49495
51385
  }
@@ -49507,49 +51397,73 @@ var DurableEvalRedisStore = class {
49507
51397
  setOptions = [{ px: this.ttlMs, nx: true, get: true }];
49508
51398
  } else {
49509
51399
  throw new Error(
49510
- "DurableEvalRedisStore getOrSet requires a node-redis, ioredis, or @upstash/redis client"
51400
+ "WorkflowEvalRedisStore getOrSet requires a node-redis, ioredis, or @upstash/redis client"
49511
51401
  );
49512
51402
  }
49513
51403
  const existing = await set.call(client, redisKey, encoded, ...setOptions);
49514
51404
  if (existing === null) return { value: value.slice(), created: true };
49515
51405
  if (typeof existing !== "string") {
49516
51406
  throw new Error(
49517
- "DurableEvalRedisStore expected atomic SET to return a string or null"
51407
+ "WorkflowEvalRedisStore expected atomic SET to return a string or null"
49518
51408
  );
49519
51409
  }
49520
51410
  return { value: base64ToUint8Array(existing), created: false };
49521
51411
  }
51412
+ async addToSet(key, member) {
51413
+ await this.evalSet(
51414
+ "redis.call('SADD', KEYS[1], ARGV[1]); redis.call('PEXPIRE', KEYS[1], ARGV[2]); return 1",
51415
+ key,
51416
+ [member, String(this.ttlMs)]
51417
+ );
51418
+ }
51419
+ async getSetSize(key) {
51420
+ return this.evalSet("return redis.call('SCARD', KEYS[1])", key, []);
51421
+ }
51422
+ async evalSet(script, key, args) {
51423
+ const client = this.client;
51424
+ const redisKey = `${this.keyPrefix}${key}`;
51425
+ const result = typeof client.defineCommand === "function" ? await client.eval(script, 1, redisKey, ...args) : typeof client.sendCommand === "function" ? await client.eval(script, { keys: [redisKey], arguments: args }) : await client.eval(script, [redisKey], args);
51426
+ if (typeof result !== "number") {
51427
+ throw new Error(
51428
+ "WorkflowEvalRedisStore expected EVAL to return a number"
51429
+ );
51430
+ }
51431
+ return result;
51432
+ }
49522
51433
  };
49523
- var BatchTask = class {
51434
+ var WorkflowTask = class {
49524
51435
  constructor(processor) {
49525
51436
  this.processor = processor;
49526
51437
  }
49527
51438
  processor;
49528
- kind = BATCH_TASK_KIND;
51439
+ kind = WORKFLOW_TASK_KIND;
49529
51440
  };
49530
- var BatchScorer = class {
51441
+ var WorkflowScorer = class {
49531
51442
  constructor(processor) {
49532
51443
  this.processor = processor;
49533
51444
  this.name = processor.name;
49534
51445
  }
49535
51446
  processor;
49536
- kind = BATCH_SCORER_KIND;
51447
+ kind = WORKFLOW_SCORER_KIND;
49537
51448
  name;
49538
51449
  };
49539
- function defineDurableEval(projectName, evaluator) {
51450
+ function defineWorkflowEval(projectName, evaluator) {
51451
+ if (evaluator.maxConcurrency !== void 0 && (!Number.isInteger(evaluator.maxConcurrency) || evaluator.maxConcurrency < 1)) {
51452
+ throw new Error("maxConcurrency must be a positive integer");
51453
+ }
49540
51454
  const definition = {
49541
51455
  projectName,
49542
51456
  evalName: evaluator.experimentName ?? projectName,
49543
51457
  evaluator
49544
51458
  };
49545
51459
  return {
49546
- start: (options = {}) => startDurableEval(definition, options),
49547
- status: (options) => getDurableEvalStatus(definition, options),
49548
- poll: (options) => pollDurableEval(definition, options),
49549
- processBatchResult: (result) => processDurableBatchResult(definition, result)
51460
+ start: (options = {}) => startWorkflowEval(definition, options),
51461
+ status: (options) => getWorkflowEvalStatus(definition, options),
51462
+ poll: (options) => pollWorkflowEval(definition, options),
51463
+ processSubmissionResult: (result) => processWorkflowSubmissionResult(definition, result)
49550
51464
  };
49551
51465
  }
49552
- async function startDurableEval(definition, options) {
51466
+ async function startWorkflowEval(definition, options) {
49553
51467
  const store = definition.evaluator.store;
49554
51468
  const runId = newId();
49555
51469
  const key = runKey(definition.projectName, definition.evalName, runId);
@@ -49569,7 +51483,7 @@ async function startDurableEval(definition, options) {
49569
51483
  update: true
49570
51484
  }
49571
51485
  );
49572
- if (!isBatchTask(definition.evaluator.task) && !(definition.evaluator.scores ?? []).some(isBatchScorer)) {
51486
+ if (!isWorkflowTask(definition.evaluator.task) && !(definition.evaluator.scores ?? []).some(isWorkflowScorer)) {
49573
51487
  const result = await runEvaluator(
49574
51488
  experiment,
49575
51489
  {
@@ -49596,67 +51510,91 @@ async function startDurableEval(definition, options) {
49596
51510
  parameters: assertJsonValue(parameters, "eval parameters"),
49597
51511
  status: "completed",
49598
51512
  summary: result.summary,
51513
+ caseCount: 0,
49599
51514
  cases: [],
49600
- batches: []
51515
+ submissions: []
49601
51516
  };
49602
51517
  await experiment?.flush();
49603
51518
  await writeRunRecord(store, key, state2);
49604
51519
  return currentStatus(definition, state2);
49605
51520
  }
51521
+ const cases = await materializeCases(definition, data, experiment);
49606
51522
  const state = {
49607
51523
  runId,
49608
51524
  experimentName,
49609
51525
  noSendLogs: options.noSendLogs ?? false,
49610
51526
  parameters: assertJsonValue(parameters, "eval parameters"),
49611
51527
  status: "running",
49612
- cases: await materializeCases(definition, data, experiment),
49613
- batches: []
51528
+ caseCount: cases.length,
51529
+ cases,
51530
+ submissions: []
49614
51531
  };
51532
+ await writeJson(
51533
+ store,
51534
+ `${key}/case-ids`,
51535
+ cases.map(({ id }) => id)
51536
+ );
49615
51537
  await writeCaseBaseRecords(store, key, state.cases);
49616
51538
  await writeRunRecord(store, key, state);
49617
- return advanceDurableEval(definition, state, store, key, experiment);
51539
+ return advanceWorkflowEval(definition, state, store, key, experiment);
49618
51540
  }
49619
- async function getDurableEvalStatus(definition, options) {
51541
+ async function getWorkflowEvalStatus(definition, options) {
49620
51542
  const store = definition.evaluator.store;
49621
- const state = await readRunState(
49622
- definition,
49623
- store,
49624
- runKey(definition.projectName, definition.evalName, options.runId)
51543
+ const key = runKey(
51544
+ definition.projectName,
51545
+ definition.evalName,
51546
+ options.runId
49625
51547
  );
49626
- if (!state) throw new Error(`Durable eval run ${options.runId} is missing`);
51548
+ const state = await readJson(store, key);
51549
+ if (!state) throw new Error(`Workflow eval run ${options.runId} is missing`);
49627
51550
  return currentStatus(definition, state);
49628
51551
  }
49629
- async function processDurableBatchResult(definition, result) {
49630
- if (!result.batchId && !result.externalId) {
49631
- throw new Error("Batch results require batchId or externalId");
51552
+ async function processWorkflowSubmissionResult(definition, result) {
51553
+ if (!result.submissionId && !result.externalId) {
51554
+ throw new Error("Submission results require submissionId or externalId");
49632
51555
  }
49633
51556
  const store = definition.evaluator.store;
49634
51557
  const key = runKey(definition.projectName, definition.evalName, result.runId);
49635
- const state = await readRunState(definition, store, key);
49636
- if (!state) throw new Error(`Durable eval run ${result.runId} is missing`);
49637
- const byBatch = result.batchId ? state.batches.find((candidate) => candidate.id === result.batchId) : void 0;
49638
- const byExternal = result.externalId ? state.batches.find(
49639
- (candidate) => candidate.externalId === result.externalId
51558
+ const run = await readJson(store, key);
51559
+ if (!run) throw new Error(`Workflow eval run ${result.runId} is missing`);
51560
+ const externalSubmissionId = result.externalId ? await readJson(
51561
+ store,
51562
+ `${key}/external/${encodedKeyPart(result.externalId)}`
51563
+ ) : void 0;
51564
+ if (result.submissionId && externalSubmissionId && result.submissionId !== externalSubmissionId) {
51565
+ throw new Error(
51566
+ "submissionId and externalId identify different submissions"
51567
+ );
51568
+ }
51569
+ const submissionId = result.submissionId ?? externalSubmissionId;
51570
+ const submission = submissionId ? await readJson(
51571
+ store,
51572
+ submissionRecordKey(key, submissionId)
49640
51573
  ) : void 0;
49641
- if (byBatch && byExternal && byBatch.id !== byExternal.id) {
49642
- throw new Error("batchId and externalId identify different batches");
49643
- }
49644
- const batch = byBatch ?? byExternal;
49645
- if (!batch) throw new Error("No submitted batch matches this result");
49646
- if (batch.status !== "complete") {
49647
- const records = await collectBatch(definition, state, batch);
49648
- batch.status = "complete";
49649
- await writeCaseRecords(store, key, records);
49650
- await writeBatchRecords(store, key, [batch]);
49651
- }
49652
- return advanceDurableEval(
51574
+ if (!submission) throw new Error("No submission matches this result");
51575
+ if (result.externalId && submission.externalId !== result.externalId) {
51576
+ throw new Error(
51577
+ "submissionId and externalId identify different submissions"
51578
+ );
51579
+ }
51580
+ if (run.status === "completed") return currentStatus(definition, run);
51581
+ const state = await readRunState(definition, store, key, [
51582
+ submission.itemId
51583
+ ]);
51584
+ if (submission.status !== "complete") {
51585
+ const record = await collectSubmission(definition, state, submission);
51586
+ await writeCaseRecords(store, key, [record]);
51587
+ submission.status = "complete";
51588
+ }
51589
+ await writeSubmissionRecords(store, key, [submission]);
51590
+ return advanceWorkflowEval(
49653
51591
  definition,
49654
- await readRunState(definition, store, key),
51592
+ await readRunState(definition, store, key, [submission.itemId]),
49655
51593
  store,
49656
51594
  key
49657
51595
  );
49658
51596
  }
49659
- async function pollDurableEval(definition, options) {
51597
+ async function pollWorkflowEval(definition, options) {
49660
51598
  const store = definition.evaluator.store;
49661
51599
  const key = runKey(
49662
51600
  definition.projectName,
@@ -49664,39 +51602,53 @@ async function pollDurableEval(definition, options) {
49664
51602
  options.runId
49665
51603
  );
49666
51604
  const state = await readRunState(definition, store, key);
49667
- if (!state) throw new Error(`Durable eval run ${options.runId} is missing`);
49668
- const batches = state.batches.filter((batch) => {
49669
- if (batch.status === "complete") return false;
49670
- return processorForStage(definition, batch.kind, batch.scorerName).completion.mode === "poll";
49671
- });
49672
- const results = await Promise.all(
49673
- batches.map(async (batch) => ({
49674
- batch,
49675
- result: await processorForStage(definition, batch.kind, batch.scorerName).completion.poll(batch.submissionData, {
49676
- runId: state.runId,
49677
- batchId: batch.id
49678
- })
49679
- }))
49680
- );
49681
- const changedCases = /* @__PURE__ */ new Map();
49682
- const changedBatches = [];
49683
- for (const { batch, result } of results) {
51605
+ if (!state) throw new Error(`Workflow eval run ${options.runId} is missing`);
51606
+ const submissions = state.submissions.filter((submission) => {
51607
+ if (submission.status === "complete") return false;
51608
+ return processorForStage(definition, submission.kind, submission.scorerName).completion.mode === "poll";
51609
+ });
51610
+ const workers = queue(async (submission) => {
51611
+ const completion = processorForStage(
51612
+ definition,
51613
+ submission.kind,
51614
+ submission.scorerName
51615
+ ).completion;
51616
+ if (completion.mode !== "poll") return;
51617
+ const result = await completion.poll(submission.submissionData, {
51618
+ runId: state.runId,
51619
+ submissionId: submission.id
51620
+ });
49684
51621
  if (result.status === "failed") throw asError(result.error);
49685
- if (result.status !== "complete") continue;
49686
- for (const record of await collectBatch(definition, state, batch)) {
49687
- changedCases.set(record.id, record);
49688
- }
49689
- batch.status = "complete";
49690
- changedBatches.push(batch);
49691
- }
49692
- if (changedBatches.length > 0) {
49693
- await writeCaseRecords(store, key, [...changedCases.values()]);
49694
- await writeBatchRecords(store, key, changedBatches);
51622
+ if (result.status === "complete") {
51623
+ const record = await collectSubmission(definition, state, submission);
51624
+ await writeCaseRecords(store, key, [record]);
51625
+ submission.status = "complete";
51626
+ await writeSubmissionRecords(store, key, [submission]);
51627
+ }
51628
+ }, definition.evaluator.maxConcurrency ?? 10);
51629
+ const results = await Promise.allSettled(
51630
+ submissions.map((submission) => workers.pushAsync(submission))
51631
+ );
51632
+ let status;
51633
+ const errors = results.flatMap(
51634
+ (result) => result.status === "rejected" ? [asError(result.reason)] : []
51635
+ );
51636
+ try {
51637
+ status = await advanceWorkflowEval(
51638
+ definition,
51639
+ await readRunState(definition, store, key),
51640
+ store,
51641
+ key
51642
+ );
51643
+ } catch (error) {
51644
+ errors.push(asError(error));
49695
51645
  }
49696
- const currentState = changedBatches.length > 0 ? await readRunState(definition, store, key) : state;
49697
- return advanceDurableEval(definition, currentState, store, key);
51646
+ if (errors.length === 1) throw errors[0];
51647
+ if (errors.length > 1)
51648
+ throw new AggregateError(errors, "Workflow submission callbacks failed");
51649
+ return status;
49698
51650
  }
49699
- async function openDurableExperiment(definition, state) {
51651
+ async function openWorkflowExperiment(definition, state) {
49700
51652
  const data = [];
49701
51653
  return await _internalInitEvaluatorExperiment(
49702
51654
  definition.projectName,
@@ -49709,45 +51661,49 @@ async function openDurableExperiment(definition, state) {
49709
51661
  }
49710
51662
  );
49711
51663
  }
49712
- async function advanceDurableEval(definition, state, store, key, existingExperiment) {
51664
+ async function advanceWorkflowEval(definition, state, store, key, existingExperiment) {
49713
51665
  if (state.status === "completed") return currentStatus(definition, state);
49714
- const experiment = existingExperiment === void 0 ? await openDurableExperiment(definition, state) : existingExperiment;
51666
+ const experiment = existingExperiment === void 0 ? await openWorkflowExperiment(definition, state) : existingExperiment;
51667
+ const caseIds = state.cases.map(({ id }) => id);
49715
51668
  await runTaskStage(definition, state, store, key, experiment);
49716
51669
  await logCompletedTasks(definition, state, store, key, experiment);
49717
- state = await readRunState(definition, store, key) ?? state;
49718
- if (state.cases.some((record) => !record.taskComplete || !record.taskLogged)) {
49719
- return currentStatus(definition, state);
49720
- }
51670
+ state = await readRunState(definition, store, key, caseIds) ?? state;
49721
51671
  await runScoreStages(definition, state, store, key, experiment);
49722
- state = await readRunState(definition, store, key) ?? state;
51672
+ state = await readRunState(definition, store, key, caseIds) ?? state;
49723
51673
  const scorerNames = resolveScorers(definition.evaluator.scores ?? []).map(
49724
51674
  ({ name }) => name
49725
51675
  );
49726
51676
  const classifierNames = (definition.evaluator.classifiers ?? []).map(
49727
51677
  classifierName
49728
51678
  );
49729
- if (state.cases.some(
49730
- (record) => scorerNames.some(
49731
- (name) => !Object.hasOwn(record.scores, name) || !Object.hasOwn(record.loggedScores, name)
49732
- ) || classifierNames.some(
49733
- (name) => !Object.hasOwn(record.loggedClassifications, name)
49734
- )
49735
- )) {
51679
+ await Promise.all(
51680
+ state.cases.map(async (record) => {
51681
+ if (record.taskComplete && record.taskLogged && scorerNames.every(
51682
+ (name) => Object.hasOwn(record.scores, name) && Object.hasOwn(record.loggedScores, name)
51683
+ ) && classifierNames.every(
51684
+ (name) => Object.hasOwn(record.loggedClassifications, name)
51685
+ )) {
51686
+ await store.addToSet(`${key}/progress/cases`, record.id);
51687
+ }
51688
+ })
51689
+ );
51690
+ if (await store.getSetSize(`${key}/progress/cases`) !== state.caseCount) {
49736
51691
  return currentStatus(definition, state);
49737
51692
  }
49738
51693
  if (!await claimAction(store, key, "finish")) {
49739
- const latest = await readRunState(definition, store, key);
51694
+ const latest = await readJson(store, key);
49740
51695
  return currentStatus(definition, latest ?? state);
49741
51696
  }
51697
+ state = await readRunState(definition, store, key);
49742
51698
  state.summary = await finishExperiment(definition, state, experiment);
49743
51699
  state.status = "completed";
49744
51700
  await writeRunRecord(store, key, state);
49745
51701
  return currentStatus(definition, state);
49746
51702
  }
49747
- function currentStatus(definition, state) {
51703
+ async function currentStatus(definition, state) {
49748
51704
  if (state.status === "completed") {
49749
51705
  if (!state.summary) {
49750
- throw new Error(`Durable eval run ${state.runId} has no saved summary`);
51706
+ throw new Error(`Workflow eval run ${state.runId} has no saved summary`);
49751
51707
  }
49752
51708
  return {
49753
51709
  status: "completed",
@@ -49756,11 +51712,20 @@ function currentStatus(definition, state) {
49756
51712
  summary: state.summary
49757
51713
  };
49758
51714
  }
51715
+ const key = runKey(definition.projectName, definition.evalName, state.runId);
51716
+ const store = definition.evaluator.store;
49759
51717
  const pending = { poll: 0, webhook: 0 };
49760
- for (const batch of state.batches) {
49761
- if (batch.status === "complete") continue;
49762
- pending[processorForStage(definition, batch.kind, batch.scorerName).completion.mode]++;
49763
- }
51718
+ await Promise.all(
51719
+ ["poll", "webhook"].map(async (mode) => {
51720
+ const completed = await store.getSetSize(
51721
+ `${key}/progress/${mode}/complete`
51722
+ );
51723
+ const submitted = await store.getSetSize(
51724
+ `${key}/progress/${mode}/submitted`
51725
+ );
51726
+ pending[mode] = submitted - completed;
51727
+ })
51728
+ );
49764
51729
  return { status: "waiting", runId: state.runId, pending };
49765
51730
  }
49766
51731
  async function startCaseRoot(definition, state, record, experiment) {
@@ -49821,7 +51786,7 @@ async function logTaskResult(definition, state, record, experiment, task) {
49821
51786
  expected: "expected" in datum ? datum.expected : void 0,
49822
51787
  metadata: {
49823
51788
  ...record.metadata,
49824
- durable_eval: {
51789
+ workflow_eval: {
49825
51790
  run_id: state.runId,
49826
51791
  case_id: record.caseId,
49827
51792
  trial_index: record.trialIndex
@@ -49852,8 +51817,8 @@ async function logCompletedTasks(definition, state, store, key, experiment) {
49852
51817
  }
49853
51818
  }
49854
51819
  async function runTaskStage(definition, state, store, key, experiment) {
49855
- if (isBatchTask(definition.evaluator.task)) {
49856
- await ensureBatches(definition, state, store, key, "task");
51820
+ if (isWorkflowTask(definition.evaluator.task)) {
51821
+ await ensureSubmissions(definition, state, store, key, "task");
49857
51822
  return;
49858
51823
  }
49859
51824
  const task = definition.evaluator.task;
@@ -49879,8 +51844,9 @@ async function runScoreStages(definition, state, store, key, experiment) {
49879
51844
  changed.clear();
49880
51845
  };
49881
51846
  for (const { name, scorer } of scorers) {
49882
- if (isBatchScorer(scorer)) {
51847
+ if (isWorkflowScorer(scorer)) {
49883
51848
  for (const record of state.cases) {
51849
+ if (!record.taskComplete || !record.taskLogged) continue;
49884
51850
  if (Object.hasOwn(record.scores, name) && !Object.hasOwn(record.loggedScores, name)) {
49885
51851
  if (!await claimAction(store, key, "score-log", record.id, name)) {
49886
51852
  continue;
@@ -49896,10 +51862,11 @@ async function runScoreStages(definition, state, store, key, experiment) {
49896
51862
  }
49897
51863
  }
49898
51864
  await persistChangedCases();
49899
- await ensureBatches(definition, state, store, key, "score", name);
51865
+ await ensureSubmissions(definition, state, store, key, "score", name);
49900
51866
  continue;
49901
51867
  }
49902
51868
  for (const record of state.cases) {
51869
+ if (!record.taskComplete || !record.taskLogged) continue;
49903
51870
  if (Object.hasOwn(record.loggedScores, name)) continue;
49904
51871
  if (!await claimAction(store, key, "score", record.id, name)) continue;
49905
51872
  await evaluateAndLogScore(
@@ -49916,6 +51883,7 @@ async function runScoreStages(definition, state, store, key, experiment) {
49916
51883
  for (const [index, classifier] of (definition.evaluator.classifiers ?? []).entries()) {
49917
51884
  const name = classifierName(classifier, index);
49918
51885
  for (const record of state.cases) {
51886
+ if (!record.taskComplete || !record.taskLogged) continue;
49919
51887
  if (Object.hasOwn(record.loggedClassifications, name)) continue;
49920
51888
  if (!await claimAction(store, key, "classification", record.id, name)) {
49921
51889
  continue;
@@ -49938,13 +51906,14 @@ function scorerArgs(record) {
49938
51906
  return {
49939
51907
  ...datum,
49940
51908
  metadata: record.metadata,
51909
+ tags: record.tags,
49941
51910
  output: record.output
49942
51911
  };
49943
51912
  }
49944
51913
  function resumeCaseRoot(definition, record, experiment) {
49945
51914
  if (!experiment) return NOOP_SPAN;
49946
51915
  if (!record.rootSpan) {
49947
- throw new Error(`Durable eval case ${record.caseId} has no root span`);
51916
+ throw new Error(`Workflow eval case ${record.caseId} has no root span`);
49948
51917
  }
49949
51918
  return _internalResumeSpan({
49950
51919
  exported: record.rootSpan,
@@ -50032,117 +52001,110 @@ async function evaluateAndLogClassification(definition, state, record, name, cla
50032
52001
  root.end();
50033
52002
  }
50034
52003
  }
50035
- async function ensureBatches(definition, state, store, key, kind, scorerName2) {
52004
+ async function ensureSubmissions(definition, state, store, key, kind, scorerName2) {
50036
52005
  const processor = processorForStage(definition, kind, scorerName2);
50037
- const plans = plannedBatches(
52006
+ const plans = plannedSubmissions(
50038
52007
  definition,
50039
52008
  state.runId,
50040
52009
  state.cases.map(({ id }) => id)
50041
52010
  );
50042
52011
  const casesById = new Map(state.cases.map((record) => [record.id, record]));
50043
- for (const plan of plans) {
50044
- if (plan.kind !== kind || plan.scorerName !== scorerName2) continue;
50045
- if (state.batches.some(({ id }) => id === plan.id)) continue;
50046
- const records = plan.itemIds.map((id) => casesById.get(id));
50047
- const ready = records.every(
50048
- (record) => kind === "task" ? !record.taskComplete : !Object.hasOwn(record.scores, scorerName2)
50049
- );
50050
- if (!ready) continue;
50051
- const batchId = plan.id;
52012
+ const existingIds = new Set(state.submissions.map(({ id }) => id));
52013
+ const workers = queue(async (plan) => {
52014
+ if (plan.kind !== kind || plan.scorerName !== scorerName2) return;
52015
+ if (existingIds.has(plan.id)) return;
52016
+ const record = casesById.get(plan.itemId);
52017
+ const ready = kind === "task" ? !record.taskComplete : record.taskComplete && record.taskLogged && !Object.hasOwn(record.scores, scorerName2);
52018
+ if (!ready) return;
52019
+ const submissionId = plan.id;
50052
52020
  const claim = await store.getOrSet(
50053
- claimRecordKey(key, "batch", batchId),
50054
- encoder.encode(batchId)
50055
- );
50056
- if (!claim.created) continue;
50057
- const context = { runId: state.runId, batchId };
50058
- const items = records.map(
50059
- (record) => kind === "task" ? taskBatchItem(record, state.parameters) : scorerBatchItem(record)
52021
+ claimRecordKey(key, "submission", submissionId),
52022
+ encoder.encode(submissionId)
50060
52023
  );
52024
+ if (!claim.created) return;
52025
+ const context = { runId: state.runId, submissionId };
52026
+ const item = kind === "task" ? taskSubmissionItem(record, state.parameters) : scorerSubmissionItem(record);
50061
52027
  const submissionData = assertJsonValue(
50062
- await processor.submit(items, context),
50063
- `submission data for batch ${batchId}`
52028
+ await processor.submit(item, context),
52029
+ `submission data for submission ${submissionId}`
50064
52030
  );
50065
52031
  const externalId = processor.completion.mode === "webhook" ? processor.completion.getExternalId(submissionData, context) : void 0;
50066
52032
  if (externalId !== void 0 && !externalId.trim()) {
50067
- throw new Error(`Batch ${batchId} produced an empty externalId`);
52033
+ throw new Error(
52034
+ `Submission ${submissionId} produced an empty externalId`
52035
+ );
50068
52036
  }
50069
- const batch = {
50070
- id: batchId,
52037
+ const submission = {
52038
+ id: submissionId,
50071
52039
  kind,
50072
52040
  scorerName: scorerName2,
50073
- itemIds: records.map((record) => record.id),
52041
+ itemId: record.id,
50074
52042
  submissionData,
50075
52043
  externalId,
50076
- status: "submitted"
50077
- };
50078
- state.batches.push(batch);
50079
- await writeBatchRecords(store, key, [batch]);
50080
- }
52044
+ status: "submitted",
52045
+ completionMode: processor.completion.mode
52046
+ };
52047
+ state.submissions.push(submission);
52048
+ await writeSubmissionRecords(store, key, [submission]);
52049
+ }, definition.evaluator.maxConcurrency ?? 10);
52050
+ const results = await Promise.allSettled(
52051
+ plans.map((plan) => workers.pushAsync(plan))
52052
+ );
52053
+ const errors = results.flatMap(
52054
+ (result) => result.status === "rejected" ? [asError(result.reason)] : []
52055
+ );
52056
+ if (errors.length === 1) throw errors[0];
52057
+ if (errors.length > 1)
52058
+ throw new AggregateError(errors, "Workflow submissions failed");
50081
52059
  }
50082
- async function collectBatch(definition, state, batch) {
50083
- const processor = processorForStage(definition, batch.kind, batch.scorerName);
50084
- const context = { runId: state.runId, batchId: batch.id };
50085
- const results = await processor.collect(batch.submissionData, context);
50086
- if (!Array.isArray(results)) {
50087
- throw new Error(`collect for batch ${batch.id} must return an array`);
52060
+ async function collectSubmission(definition, state, submission) {
52061
+ const processor = processorForStage(
52062
+ definition,
52063
+ submission.kind,
52064
+ submission.scorerName
52065
+ );
52066
+ const context = { runId: state.runId, submissionId: submission.id };
52067
+ const result = await processor.collect(submission.submissionData, context);
52068
+ if (typeof result !== "object" || result === null || Array.isArray(result)) {
52069
+ throw new Error(
52070
+ `collect for submission ${submission.id} must return a result object`
52071
+ );
50088
52072
  }
50089
- const expectedIds = new Set(batch.itemIds);
50090
- const seen = /* @__PURE__ */ new Set();
50091
- const records = [];
50092
- for (const result of results) {
50093
- const id = resultItemId(result);
50094
- if (!expectedIds.has(id)) {
50095
- throw new Error(`Batch ${batch.id} returned unknown item ${id}`);
50096
- }
50097
- if (seen.has(id)) {
50098
- throw new Error(`Batch ${batch.id} returned item ${id} more than once`);
50099
- }
50100
- seen.add(id);
50101
- const record = state.cases.find((candidate) => candidate.id === id);
50102
- records.push(record);
50103
- if (batch.kind === "task") {
50104
- record.output = assertJsonValue(
50105
- result.output,
50106
- `task output for item ${id}`
50107
- );
50108
- if ("metadata" in result && result.metadata !== void 0) {
50109
- record.metadata = assertJsonValue(
50110
- {
50111
- ...record.metadata,
50112
- ...result.metadata
50113
- },
50114
- `metadata for ${id}`
50115
- );
50116
- }
50117
- if ("tags" in result && result.tags !== void 0)
50118
- record.tags = result.tags;
50119
- record.taskComplete = true;
50120
- } else {
50121
- record.scores[batch.scorerName] = assertJsonValue(
50122
- result.score,
50123
- `score output for item ${id}`
52073
+ const record = state.cases.find(
52074
+ (candidate) => candidate.id === submission.itemId
52075
+ );
52076
+ if (submission.kind === "task") {
52077
+ record.output = assertJsonValue(
52078
+ result.output,
52079
+ `task output for item ${record.id}`
52080
+ );
52081
+ if (result.metadata !== void 0) {
52082
+ record.metadata = assertJsonValue(
52083
+ { ...record.metadata, ...result.metadata },
52084
+ `metadata for ${record.id}`
50124
52085
  );
50125
52086
  }
50126
- }
50127
- const missing = batch.itemIds.filter((id) => !seen.has(id));
50128
- if (missing.length > 0) {
50129
- throw new Error(
50130
- `Batch ${batch.id} did not return results for: ${missing.join(", ")}`
52087
+ if (result.tags !== void 0) record.tags = result.tags;
52088
+ record.taskComplete = true;
52089
+ } else {
52090
+ record.scores[submission.scorerName] = assertJsonValue(
52091
+ result.score,
52092
+ `score output for item ${record.id}`
50131
52093
  );
50132
52094
  }
50133
- return records;
52095
+ return record;
50134
52096
  }
50135
52097
  function processorForStage(definition, kind, scorerName2) {
50136
52098
  if (kind === "task") {
50137
- if (!isBatchTask(definition.evaluator.task)) {
50138
- throw new Error("Definition no longer contains the batch task");
52099
+ if (!isWorkflowTask(definition.evaluator.task)) {
52100
+ throw new Error("Definition no longer contains the submission task");
50139
52101
  }
50140
52102
  return definition.evaluator.task.processor;
50141
52103
  }
50142
52104
  const scorer = resolveScorers(definition.evaluator.scores ?? []).find(
50143
52105
  ({ name }) => name === scorerName2
50144
52106
  )?.scorer;
50145
- if (!isBatchScorer(scorer)) {
52107
+ if (!isWorkflowScorer(scorer)) {
50146
52108
  throw new Error(`Definition no longer contains scorer ${scorerName2}`);
50147
52109
  }
50148
52110
  return scorer.processor;
@@ -50164,15 +52126,15 @@ async function materializeCases(definition, data, experiment) {
50164
52126
  const caseId = datum.id ?? datum.upsert_id ?? (evaluator.caseId ? await evaluator.caseId(datum) : void 0);
50165
52127
  if (!caseId) {
50166
52128
  throw new Error(
50167
- "Every durable eval case requires id, upsert_id, or caseId"
52129
+ "Every workflow eval case requires id, upsert_id, or caseId"
50168
52130
  );
50169
52131
  }
50170
52132
  if (seen.has(caseId))
50171
- throw new Error(`Duplicate durable eval case id: ${caseId}`);
52133
+ throw new Error(`Duplicate workflow eval case id: ${caseId}`);
50172
52134
  seen.add(caseId);
50173
52135
  const trialCount = datum.trialCount ?? evaluator.trialCount ?? 1;
50174
52136
  if (!Number.isInteger(trialCount) || trialCount < 1) {
50175
- throw new Error(`Invalid trialCount for durable eval case ${caseId}`);
52137
+ throw new Error(`Invalid trialCount for workflow eval case ${caseId}`);
50176
52138
  }
50177
52139
  for (let trialIndex = 0; trialIndex < trialCount; trialIndex++) {
50178
52140
  records.push({
@@ -50196,7 +52158,7 @@ async function materializeCases(definition, data, experiment) {
50196
52158
  }
50197
52159
  return records;
50198
52160
  }
50199
- function taskBatchItem(record, parameters) {
52161
+ function taskSubmissionItem(record, parameters) {
50200
52162
  const datum = record.datum;
50201
52163
  return {
50202
52164
  id: record.id,
@@ -50208,7 +52170,7 @@ function taskBatchItem(record, parameters) {
50208
52170
  trialIndex: record.trialIndex
50209
52171
  };
50210
52172
  }
50211
- function scorerBatchItem(record) {
52173
+ function scorerSubmissionItem(record) {
50212
52174
  const datum = record.datum;
50213
52175
  return {
50214
52176
  id: record.id,
@@ -50279,12 +52241,12 @@ async function finishExperiment(definition, state, experiment) {
50279
52241
  }
50280
52242
  function resolveScorers(scorers) {
50281
52243
  return scorers.map((scorer, index) => ({
50282
- name: isBatchScorer(scorer) ? scorer.name : scorer.name || `scorer_${index}`,
52244
+ name: isWorkflowScorer(scorer) ? scorer.name : scorer.name || `scorer_${index}`,
50283
52245
  scorer
50284
52246
  }));
50285
52247
  }
50286
52248
  function runKey(projectName, evalName, runId) {
50287
- return `durable-eval/v1/runs/${contentVersion(encoder.encode(`${projectName}\0${evalName}\0${runId}`))}`;
52249
+ return `workflow-eval/v1/runs/${contentVersion(encoder.encode(`${projectName}\0${evalName}\0${runId}`))}`;
50288
52250
  }
50289
52251
  function encodedKeyPart(value) {
50290
52252
  return uint8ArrayToBase64(encoder.encode(value)).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
@@ -50293,8 +52255,8 @@ function caseRecordKey(key, caseId, kind, ...names) {
50293
52255
  const suffix = names.map(encodedKeyPart).join("/");
50294
52256
  return `${key}/cases/${encodedKeyPart(caseId)}/${kind}${suffix ? `/${suffix}` : ""}`;
50295
52257
  }
50296
- function batchRecordKey(key, batchId) {
50297
- return `${key}/batches/${encodedKeyPart(batchId)}`;
52258
+ function submissionRecordKey(key, submissionId) {
52259
+ return `${key}/submissions/${encodedKeyPart(submissionId)}`;
50298
52260
  }
50299
52261
  function claimRecordKey(key, kind, ...parts) {
50300
52262
  const identity = stableStringify([kind, parts]);
@@ -50306,33 +52268,24 @@ async function claimAction(store, key, kind, ...parts) {
50306
52268
  encoder.encode("claimed")
50307
52269
  )).created;
50308
52270
  }
50309
- function plannedBatches(definition, runId, caseIds) {
52271
+ function plannedSubmissions(definition, runId, caseIds) {
50310
52272
  const stages = [];
50311
- if (isBatchTask(definition.evaluator.task)) stages.push({ kind: "task" });
52273
+ if (isWorkflowTask(definition.evaluator.task)) stages.push({ kind: "task" });
50312
52274
  for (const { name, scorer } of resolveScorers(
50313
52275
  definition.evaluator.scores ?? []
50314
52276
  )) {
50315
- if (isBatchScorer(scorer)) {
52277
+ if (isWorkflowScorer(scorer)) {
50316
52278
  stages.push({ kind: "score", scorerName: name });
50317
52279
  }
50318
52280
  }
50319
52281
  const plans = [];
50320
52282
  for (const { kind, scorerName: scorerName2 } of stages) {
50321
- const batchSize = processorForStage(definition, kind, scorerName2).batchSize ?? DEFAULT_BATCH_SIZE;
50322
- if (!Number.isInteger(batchSize) || batchSize < 1) {
50323
- throw new Error(
50324
- `Invalid batchSize for ${scorerName2 ?? "task"}: ${batchSize}`
50325
- );
50326
- }
50327
- for (let offset = 0; offset < caseIds.length; offset += batchSize) {
50328
- const itemIds = caseIds.slice(offset, offset + batchSize);
52283
+ for (const itemId of caseIds) {
50329
52284
  plans.push({
50330
- id: deterministicId(
50331
- stableStringify([runId, kind, scorerName2, itemIds])
50332
- ),
52285
+ id: deterministicId(stableStringify([runId, kind, scorerName2, itemId])),
50333
52286
  kind,
50334
52287
  scorerName: scorerName2,
50335
- itemIds
52288
+ itemId
50336
52289
  });
50337
52290
  }
50338
52291
  }
@@ -50392,7 +52345,7 @@ async function readCaseRecord(definition, store, key, id) {
50392
52345
  }))
50393
52346
  )
50394
52347
  ]);
50395
- if (!base) throw new Error(`Durable eval case ${id} is missing`);
52348
+ if (!base) throw new Error(`Workflow eval case ${id} is missing`);
50396
52349
  const scores = /* @__PURE__ */ Object.create(null);
50397
52350
  for (const { name, value } of scoreValues) {
50398
52351
  if (value !== void 0) scores[name] = value;
@@ -50423,32 +52376,34 @@ async function readCaseRecord(definition, store, key, id) {
50423
52376
  loggedClassifications
50424
52377
  };
50425
52378
  }
50426
- async function readRunState(definition, store, key) {
52379
+ async function readRunState(definition, store, key, caseIds) {
50427
52380
  const record = await readJson(store, key);
50428
52381
  if (!record) return void 0;
50429
- const plans = plannedBatches(definition, record.runId, record.caseIds);
50430
- const [cases, batchRecords] = await Promise.all([
52382
+ const selectedIds = caseIds ?? (record.caseCount === 0 ? [] : await readJson(store, `${key}/case-ids`));
52383
+ if (!selectedIds)
52384
+ throw new Error(`Workflow eval run ${record.runId} has no case index`);
52385
+ const plans = plannedSubmissions(definition, record.runId, selectedIds);
52386
+ const [cases, submissionRecords] = await Promise.all([
50431
52387
  Promise.all(
50432
- record.caseIds.map((id) => readCaseRecord(definition, store, key, id))
52388
+ selectedIds.map((id) => readCaseRecord(definition, store, key, id))
50433
52389
  ),
50434
52390
  Promise.all(
50435
52391
  plans.map(async ({ id }) => {
50436
- return readJson(store, batchRecordKey(key, id));
52392
+ return readJson(
52393
+ store,
52394
+ submissionRecordKey(key, id)
52395
+ );
50437
52396
  })
50438
52397
  )
50439
52398
  ]);
50440
- const batches = batchRecords.filter(
52399
+ const submissions = submissionRecords.filter(
50441
52400
  (value) => value !== void 0
50442
52401
  );
50443
- const { caseIds: _caseIds, ...state } = record;
50444
- return { ...state, cases, batches };
52402
+ return { ...record, cases, submissions };
50445
52403
  }
50446
52404
  async function writeRunRecord(store, key, state) {
50447
- const { cases, batches: _batches, ...record } = state;
50448
- await writeJson(store, key, {
50449
- ...record,
50450
- caseIds: cases.map(({ id }) => id)
50451
- });
52405
+ const { cases: _cases, submissions: _submissions, ...record } = state;
52406
+ await writeJson(store, key, record);
50452
52407
  }
50453
52408
  async function writeCaseBaseRecords(store, key, records) {
50454
52409
  await Promise.all(
@@ -50520,11 +52475,25 @@ async function writeCaseRecords(store, key, records) {
50520
52475
  }
50521
52476
  await Promise.all(writes);
50522
52477
  }
50523
- async function writeBatchRecords(store, key, records) {
52478
+ async function writeSubmissionRecords(store, key, records) {
50524
52479
  await Promise.all(
50525
- records.map(
50526
- (record) => writeJson(store, batchRecordKey(key, record.id), record)
50527
- )
52480
+ records.map(async (record) => {
52481
+ if (record.externalId !== void 0) {
52482
+ const locator = await store.getOrSet(
52483
+ `${key}/external/${encodedKeyPart(record.externalId)}`,
52484
+ encoder.encode(JSON.stringify(record.id))
52485
+ );
52486
+ if (JSON.parse(decoder.decode(locator.value)) !== record.id) {
52487
+ throw new Error(`Duplicate externalId: ${record.externalId}`);
52488
+ }
52489
+ }
52490
+ const progressKey = `${key}/progress/${record.completionMode}`;
52491
+ await store.addToSet(`${progressKey}/submitted`, record.id);
52492
+ if (record.status === "complete") {
52493
+ await store.addToSet(`${progressKey}/complete`, record.id);
52494
+ }
52495
+ await writeJson(store, submissionRecordKey(key, record.id), record);
52496
+ })
50528
52497
  );
50529
52498
  }
50530
52499
  function deterministicId(value) {
@@ -50569,17 +52538,11 @@ function assertJsonValue(value, label) {
50569
52538
  throw new Error(`${label} must be JSON serializable`, { cause: error });
50570
52539
  }
50571
52540
  }
50572
- function resultItemId(value) {
50573
- if (typeof value !== "object" || value === null || !("id" in value) || typeof value.id !== "string") {
50574
- throw new Error("Batch results must contain a string id");
50575
- }
50576
- return value.id;
50577
- }
50578
- function isBatchTask(value) {
50579
- return typeof value === "object" && value !== null && "kind" in value && value.kind === BATCH_TASK_KIND;
52541
+ function isWorkflowTask(value) {
52542
+ return typeof value === "object" && value !== null && "kind" in value && value.kind === WORKFLOW_TASK_KIND;
50580
52543
  }
50581
- function isBatchScorer(value) {
50582
- return typeof value === "object" && value !== null && "kind" in value && value.kind === BATCH_SCORER_KIND;
52544
+ function isWorkflowScorer(value) {
52545
+ return typeof value === "object" && value !== null && "kind" in value && value.kind === WORKFLOW_SCORER_KIND;
50583
52546
  }
50584
52547
  function asError(error) {
50585
52548
  return error instanceof Error ? error : new Error(String(error));
@@ -51507,13 +53470,13 @@ var evaluatorDefinitionsSchema = import_v313.z.record(
51507
53470
  );
51508
53471
 
51509
53472
  // src/wrappers/elevenlabs.ts
51510
- var clients = /* @__PURE__ */ new WeakMap();
53473
+ var clients2 = /* @__PURE__ */ new WeakMap();
51511
53474
  function wrapElevenLabs(client) {
51512
53475
  if (!isObject(client) || !isObject(client.textToSpeech) || typeof client.textToSpeech.convert !== "function") {
51513
53476
  debugLogger.warn("Unsupported ElevenLabs client. Not wrapping.");
51514
53477
  return client;
51515
53478
  }
51516
- const cached = clients.get(client);
53479
+ const cached = clients2.get(client);
51517
53480
  if (cached) return cached;
51518
53481
  const sdk = client;
51519
53482
  const speech = new Proxy(sdk.textToSpeech, {
@@ -51560,8 +53523,8 @@ function wrapElevenLabs(client) {
51560
53523
  return Reflect.get(target, prop, receiver);
51561
53524
  }
51562
53525
  });
51563
- clients.set(client, proxy);
51564
- clients.set(proxy, proxy);
53526
+ clients2.set(client, proxy);
53527
+ clients2.set(proxy, proxy);
51565
53528
  return proxy;
51566
53529
  }
51567
53530