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
package/dist/browser.js CHANGED
@@ -38,8 +38,6 @@ __export(browser_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(browser_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(browser_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(browser_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(browser_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(browser_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) {
@@ -13708,6 +13751,18 @@ function defineChannels(pkg, channels, options) {
13708
13751
  var openAIChannels = defineChannels(
13709
13752
  "openai",
13710
13753
  {
13754
+ agentsTraceStart: channel({
13755
+ channelName: "agents.trace.start",
13756
+ kind: "async"
13757
+ }),
13758
+ agentsTraceCapture: channel({
13759
+ channelName: "agents.trace.capture",
13760
+ kind: "async"
13761
+ }),
13762
+ agentsTraceFail: channel({
13763
+ channelName: "agents.trace.fail",
13764
+ kind: "async"
13765
+ }),
13711
13766
  filesCreateTraced: channel({
13712
13767
  channelName: "files.create-traced",
13713
13768
  kind: "async"
@@ -14076,6 +14131,23 @@ function getCachedMetricFromHeaders(headers) {
14076
14131
  return parseCachedHeader(headers.get(LEGACY_CACHED_HEADER));
14077
14132
  }
14078
14133
 
14134
+ // src/instrumentation/plugins/openai-manual-instrumentation-utils.ts
14135
+ async function deterministicDigest(namespace, ...parts) {
14136
+ const encoded = new TextEncoder().encode(
14137
+ [namespace, ...parts].map((part) => `${part.length}:${part}`).join("\0")
14138
+ );
14139
+ return new Uint8Array(
14140
+ await globalThis.crypto.subtle.digest("SHA-256", encoded)
14141
+ );
14142
+ }
14143
+ function digestHex(bytes, length) {
14144
+ return Array.from(bytes.slice(0, length)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
14145
+ }
14146
+ function digestUuid(bytes) {
14147
+ const hex = digestHex(bytes, 16);
14148
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
14149
+ }
14150
+
14079
14151
  // src/instrumentation/plugins/openai-batch-instrumentation.ts
14080
14152
  var SUPPORTED_ENDPOINTS = /* @__PURE__ */ new Set(["/v1/chat/completions", "/v1/responses"]);
14081
14153
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
@@ -14116,21 +14188,6 @@ async function exportParent(parent) {
14116
14188
  }
14117
14189
  return void 0;
14118
14190
  }
14119
- async function deterministicDigest(namespace, ...parts) {
14120
- const encoded = new TextEncoder().encode(
14121
- [namespace, ...parts].map((part) => `${part.length}:${part}`).join("\0")
14122
- );
14123
- return new Uint8Array(
14124
- await globalThis.crypto.subtle.digest("SHA-256", encoded)
14125
- );
14126
- }
14127
- function digestHex(bytes, length) {
14128
- return Array.from(bytes.slice(0, length)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
14129
- }
14130
- function digestUuid(bytes) {
14131
- const hex = digestHex(bytes, 16);
14132
- return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
14133
- }
14134
14191
  async function batchSpanIds(inputFileId) {
14135
14192
  const [row, span, root] = await Promise.all([
14136
14193
  deterministicDigest("openai:batch:row", inputFileId),
@@ -14621,6 +14678,628 @@ var interceptOpenAIBatchTraceComplete = (target, thisArg, args) => Promise.resol
14621
14678
  return result;
14622
14679
  });
14623
14680
 
14681
+ // src/instrumentation/plugins/openai-agents-api-instrumentation.ts
14682
+ var TERMINAL_TURN_EVENTS = /* @__PURE__ */ new Set([
14683
+ "agent.session.turn.completed",
14684
+ "agent.session.turn.failed",
14685
+ "agent.session.turn.cancelled"
14686
+ ]);
14687
+ var TURN_LIFECYCLE_EVENTS = /* @__PURE__ */ new Set([
14688
+ "agent.session.turn.created",
14689
+ "agent.session.turn.in_progress",
14690
+ ...TERMINAL_TURN_EVENTS
14691
+ ]);
14692
+ var SESSION_EVENTS = /* @__PURE__ */ new Set([
14693
+ "agent.session.created",
14694
+ "agent.session.failed",
14695
+ "agent.session.idle",
14696
+ "agent.session.in_progress",
14697
+ "agent.session.requires_action"
14698
+ ]);
14699
+ var SUBAGENT_EVENTS = /* @__PURE__ */ new Set([
14700
+ "agent.session.subagent.active",
14701
+ "agent.session.subagent.closed",
14702
+ "agent.session.subagent.created"
14703
+ ]);
14704
+ function read2(value, key) {
14705
+ if (!isObject(value)) {
14706
+ return void 0;
14707
+ }
14708
+ try {
14709
+ return Reflect.get(value, key);
14710
+ } catch {
14711
+ return void 0;
14712
+ }
14713
+ }
14714
+ function stringValue(value) {
14715
+ return typeof value === "string" && value.length > 0 ? value : void 0;
14716
+ }
14717
+ function recordValue(record, key) {
14718
+ return Object.hasOwn(record, key) ? record[key] : void 0;
14719
+ }
14720
+ function setRecordValue(record, key, value) {
14721
+ Object.defineProperty(record, key, {
14722
+ configurable: true,
14723
+ enumerable: true,
14724
+ value,
14725
+ writable: true
14726
+ });
14727
+ }
14728
+ function loggedError(value, fallback2) {
14729
+ if (value instanceof Error) {
14730
+ return value;
14731
+ }
14732
+ const message = stringValue(read2(value, "message"));
14733
+ return new Error(message ?? (typeof value === "string" ? value : fallback2));
14734
+ }
14735
+ function logInstrumentationError(context, error) {
14736
+ debugLogger.debug(`OpenAI Agents API instrumentation ${context}:`, error);
14737
+ }
14738
+ async function childSpanIds2(rootKey, kind, providerId) {
14739
+ const [row, span] = await Promise.all([
14740
+ deterministicDigest("openai:agents:row", rootKey, kind, providerId),
14741
+ deterministicDigest("openai:agents:span", rootKey, kind, providerId)
14742
+ ]);
14743
+ return { rowId: digestUuid(row), spanId: digestHex(span, 8) };
14744
+ }
14745
+ function traceMetadata(args) {
14746
+ const metadata = {};
14747
+ const suppliedMetadata = read2(args, "metadata");
14748
+ if (isObject(suppliedMetadata)) {
14749
+ try {
14750
+ for (const key of Object.keys(suppliedMetadata)) {
14751
+ metadata[key] = read2(suppliedMetadata, key);
14752
+ }
14753
+ } catch (error) {
14754
+ logInstrumentationError("could not read supplied metadata", error);
14755
+ }
14756
+ }
14757
+ const agent = read2(args, "agent");
14758
+ const agentId = stringValue(read2(agent, "id")) ?? stringValue(read2(args, "agent_id"));
14759
+ const agentName = stringValue(read2(agent, "name"));
14760
+ const model = stringValue(read2(agent, "model"));
14761
+ return {
14762
+ ...metadata,
14763
+ api: "agents",
14764
+ ...agentId ? { agent_id: agentId } : {},
14765
+ ...agentName ? { agent_name: agentName } : {},
14766
+ ...model ? { model } : {},
14767
+ provider: "openai"
14768
+ };
14769
+ }
14770
+ function copyState(state) {
14771
+ return {
14772
+ ...state,
14773
+ callItems: { ...state.callItems },
14774
+ eventIds: [...state.eventIds],
14775
+ openTools: { ...state.openTools },
14776
+ subagents: { ...state.subagents },
14777
+ turnSubagents: { ...state.turnSubagents }
14778
+ };
14779
+ }
14780
+ function startRootSpan(state) {
14781
+ const root = SpanComponentsV4.fromStr(state.root);
14782
+ const parent = SpanComponentsV4.fromStr(state.rootParent);
14783
+ const rowId = stringValue(root.data.row_id);
14784
+ const rootSpanId = stringValue(root.data.root_span_id);
14785
+ const spanId = stringValue(root.data.span_id);
14786
+ if (!rowId || !rootSpanId || !spanId) {
14787
+ throw new Error("OpenAI Agents trace root is invalid");
14788
+ }
14789
+ const hasParentSpan = Boolean(
14790
+ parent.data.row_id && parent.data.span_id && parent.data.root_span_id
14791
+ );
14792
+ return withCurrent(
14793
+ NOOP_SPAN,
14794
+ () => _internalStartSpanWithInitialMergeAndParentSpanIds(
14795
+ withSpanInstrumentationName(
14796
+ {
14797
+ name: "openai.agents.turn",
14798
+ type: "task" /* TASK */,
14799
+ parent: state.rootParent,
14800
+ ...!hasParentSpan ? {
14801
+ parentSpanIds: {
14802
+ parentSpanIds: [],
14803
+ rootSpanId
14804
+ }
14805
+ } : {},
14806
+ spanId,
14807
+ startTime: state.startTime,
14808
+ event: { id: rowId }
14809
+ },
14810
+ INSTRUMENTATION_NAMES.OPENAI
14811
+ )
14812
+ )
14813
+ );
14814
+ }
14815
+ async function startSubagentSpan(state, subagentId, input, metadata, visiting = /* @__PURE__ */ new Set()) {
14816
+ const subagent = recordValue(state.subagents, subagentId);
14817
+ let parent = state.root;
14818
+ if (subagent?.parentAgentId && subagent.parentAgentId !== subagentId && recordValue(state.subagents, subagent.parentAgentId) && !visiting.has(subagent.parentAgentId)) {
14819
+ visiting.add(subagentId);
14820
+ parent = await (await startSubagentSpan(
14821
+ state,
14822
+ subagent.parentAgentId,
14823
+ void 0,
14824
+ void 0,
14825
+ visiting
14826
+ )).export();
14827
+ }
14828
+ const ids = await childSpanIds2(state.rootKey, "subagent", subagentId);
14829
+ return withCurrent(
14830
+ NOOP_SPAN,
14831
+ () => _internalStartSpanWithInitialMerge(
14832
+ withSpanInstrumentationName(
14833
+ {
14834
+ name: "openai.agents.subagent",
14835
+ type: "task" /* TASK */,
14836
+ parent,
14837
+ spanId: ids.spanId,
14838
+ startTime: subagent?.openedAt,
14839
+ event: {
14840
+ id: ids.rowId,
14841
+ ...input !== void 0 ? { input } : {},
14842
+ metadata: {
14843
+ ...metadata,
14844
+ agent_id: subagentId,
14845
+ ...subagent?.parentAgentId ? { parent_agent_id: subagent.parentAgentId } : {},
14846
+ provider: "openai"
14847
+ }
14848
+ }
14849
+ },
14850
+ INSTRUMENTATION_NAMES.OPENAI
14851
+ )
14852
+ )
14853
+ );
14854
+ }
14855
+ async function parentForTurn(state, turnId) {
14856
+ const subagentId = turnId ? recordValue(state.turnSubagents, turnId) : void 0;
14857
+ if (!subagentId) {
14858
+ return state.root;
14859
+ }
14860
+ return await (await startSubagentSpan(state, subagentId)).export();
14861
+ }
14862
+ async function startToolSpan(state, tool, input) {
14863
+ const ids = await childSpanIds2(state.rootKey, "tool", tool.itemId);
14864
+ return withCurrent(
14865
+ NOOP_SPAN,
14866
+ async () => _internalStartSpanWithInitialMerge(
14867
+ withSpanInstrumentationName(
14868
+ {
14869
+ name: tool.name,
14870
+ type: "tool" /* TOOL */,
14871
+ parent: await parentForTurn(state, tool.turnId),
14872
+ spanId: ids.spanId,
14873
+ startTime: tool.startTime,
14874
+ event: {
14875
+ id: ids.rowId,
14876
+ ...input !== void 0 ? { input } : {},
14877
+ metadata: {
14878
+ item_id: tool.itemId,
14879
+ provider: "openai",
14880
+ tool_type: tool.toolType,
14881
+ ...tool.turnId ? { turn_id: tool.turnId } : {}
14882
+ }
14883
+ }
14884
+ },
14885
+ INSTRUMENTATION_NAMES.OPENAI
14886
+ )
14887
+ )
14888
+ );
14889
+ }
14890
+ function toolFromItem(item, observedAt) {
14891
+ const itemId = stringValue(read2(item, "id"));
14892
+ const toolType = stringValue(read2(item, "type"));
14893
+ if (!itemId || !toolType) {
14894
+ return void 0;
14895
+ }
14896
+ const turnId = stringValue(read2(item, "turn_id"));
14897
+ switch (toolType) {
14898
+ case "function_call":
14899
+ return {
14900
+ input: read2(item, "arguments"),
14901
+ tool: {
14902
+ itemId,
14903
+ name: stringValue(read2(item, "name")) ?? "Function call",
14904
+ startTime: observedAt,
14905
+ toolType,
14906
+ ...turnId ? { turnId } : {}
14907
+ }
14908
+ };
14909
+ case "mcp_call": {
14910
+ const name = stringValue(read2(item, "name")) ?? "MCP call";
14911
+ const server = stringValue(read2(item, "server_label"));
14912
+ return {
14913
+ input: read2(item, "arguments"),
14914
+ tool: {
14915
+ itemId,
14916
+ name: server ? `${server}.${name}` : name,
14917
+ startTime: observedAt,
14918
+ toolType,
14919
+ ...turnId ? { turnId } : {}
14920
+ }
14921
+ };
14922
+ }
14923
+ case "web_search_call":
14924
+ return {
14925
+ input: read2(item, "action"),
14926
+ tool: {
14927
+ itemId,
14928
+ name: "Web search",
14929
+ startTime: observedAt,
14930
+ toolType,
14931
+ ...turnId ? { turnId } : {}
14932
+ }
14933
+ };
14934
+ case "command_execution":
14935
+ return {
14936
+ input: {
14937
+ command: read2(item, "command"),
14938
+ cwd: read2(item, "cwd")
14939
+ },
14940
+ tool: {
14941
+ itemId,
14942
+ name: "Command execution",
14943
+ startTime: observedAt,
14944
+ toolType,
14945
+ ...turnId ? { turnId } : {}
14946
+ }
14947
+ };
14948
+ default:
14949
+ return void 0;
14950
+ }
14951
+ }
14952
+ function textFromContent(content) {
14953
+ if (!Array.isArray(content)) {
14954
+ return void 0;
14955
+ }
14956
+ const text = [];
14957
+ for (const part of content) {
14958
+ const partText = read2(part, "text");
14959
+ if (read2(part, "type") === "output_text" && typeof partText === "string") {
14960
+ text.push(partText);
14961
+ }
14962
+ }
14963
+ return text.length > 0 ? text.join("") : void 0;
14964
+ }
14965
+ function toolOutput(item, toolType) {
14966
+ switch (toolType) {
14967
+ case "function_call":
14968
+ return read2(item, "output");
14969
+ case "mcp_call":
14970
+ return read2(item, "output");
14971
+ case "web_search_call":
14972
+ return read2(item, "action");
14973
+ case "command_execution":
14974
+ return read2(item, "output");
14975
+ default:
14976
+ return void 0;
14977
+ }
14978
+ }
14979
+ function toolFailed(item, toolType) {
14980
+ const status = read2(item, "status");
14981
+ const explicitError = read2(item, "error");
14982
+ if (explicitError !== void 0 && explicitError !== null) {
14983
+ return loggedError(explicitError, `OpenAI ${toolType} failed`);
14984
+ }
14985
+ if (status === "failed" || status === "incomplete") {
14986
+ return new Error(`OpenAI ${toolType} ${status}`);
14987
+ }
14988
+ if (toolType === "command_execution" && typeof read2(item, "exit_code") === "number" && read2(item, "exit_code") !== 0) {
14989
+ return new Error(
14990
+ `OpenAI command exited with code ${read2(item, "exit_code")}`
14991
+ );
14992
+ }
14993
+ return void 0;
14994
+ }
14995
+ async function completeTool(state, tool, item, endTime) {
14996
+ const span = await startToolSpan(state, tool);
14997
+ const output = toolOutput(item, tool.toolType);
14998
+ const error = toolFailed(item, tool.toolType);
14999
+ span.log({
15000
+ ...output !== void 0 ? { output } : {},
15001
+ ...error ? { error } : {},
15002
+ metadata: {
15003
+ status: read2(item, "status"),
15004
+ ...tool.toolType === "command_execution" ? { exit_code: read2(item, "exit_code") } : {}
15005
+ }
15006
+ });
15007
+ span.end({ endTime });
15008
+ Reflect.deleteProperty(state.openTools, tool.itemId);
15009
+ }
15010
+ async function captureMessage(state, item) {
15011
+ if (read2(item, "type") !== "message" || read2(item, "role") !== "assistant" || read2(item, "phase") !== "final_answer") {
15012
+ return;
15013
+ }
15014
+ const output = textFromContent(read2(item, "content"));
15015
+ if (output === void 0) {
15016
+ return;
15017
+ }
15018
+ const turnId = stringValue(read2(item, "turn_id"));
15019
+ const subagentId = turnId ? recordValue(state.turnSubagents, turnId) : void 0;
15020
+ if (subagentId) {
15021
+ (await startSubagentSpan(state, subagentId)).log({ output });
15022
+ } else {
15023
+ startRootSpan(state).log({ output });
15024
+ }
15025
+ }
15026
+ async function captureItem(state, item, isDone, observedAt) {
15027
+ await captureMessage(state, item);
15028
+ const itemType = stringValue(read2(item, "type"));
15029
+ if (itemType === "function_call_output") {
15030
+ const callId = stringValue(read2(item, "call_id"));
15031
+ const itemId = callId ? recordValue(state.callItems, callId) : void 0;
15032
+ const tool2 = itemId ? recordValue(state.openTools, itemId) : void 0;
15033
+ if (tool2) {
15034
+ await completeTool(state, tool2, item, observedAt);
15035
+ }
15036
+ return;
15037
+ }
15038
+ const descriptor = toolFromItem(item, observedAt);
15039
+ if (!descriptor) {
15040
+ return;
15041
+ }
15042
+ const existing = recordValue(state.openTools, descriptor.tool.itemId);
15043
+ const tool = existing ?? descriptor.tool;
15044
+ setRecordValue(state.openTools, tool.itemId, tool);
15045
+ if (itemType === "function_call") {
15046
+ const callId = stringValue(read2(item, "call_id"));
15047
+ if (callId) {
15048
+ setRecordValue(state.callItems, callId, tool.itemId);
15049
+ }
15050
+ }
15051
+ await startToolSpan(state, tool, descriptor.input);
15052
+ const status = read2(item, "status");
15053
+ const terminalFunctionCall = itemType === "function_call" && (status === "failed" || status === "incomplete");
15054
+ if (itemType !== "function_call" && (isDone || status !== "in_progress") || terminalFunctionCall) {
15055
+ await completeTool(state, tool, item, observedAt);
15056
+ }
15057
+ }
15058
+ function updateSessionMetadata(state, session) {
15059
+ const sessionId = stringValue(read2(session, "id"));
15060
+ const agent = read2(session, "agent");
15061
+ startRootSpan(state).log({
15062
+ metadata: {
15063
+ ...sessionId ? { session_id: sessionId } : {},
15064
+ ...stringValue(read2(agent, "id")) ? { agent_id: read2(agent, "id") } : {},
15065
+ ...stringValue(read2(agent, "name")) ? { agent_name: read2(agent, "name") } : {},
15066
+ ...stringValue(read2(agent, "model")) ? { model: read2(agent, "model") } : {}
15067
+ }
15068
+ });
15069
+ }
15070
+ async function captureSubagent(state, eventType, subagent, observedAt) {
15071
+ const subagentId = stringValue(read2(subagent, "id"));
15072
+ if (!subagentId) {
15073
+ return;
15074
+ }
15075
+ const existing = recordValue(state.subagents, subagentId);
15076
+ const observedOpenedAt = read2(subagent, "opened_at");
15077
+ const openedAt = typeof observedOpenedAt === "number" && Number.isFinite(observedOpenedAt) && observedOpenedAt >= 0 ? observedOpenedAt : existing?.openedAt ?? observedAt;
15078
+ const observedClosedAt = read2(subagent, "closed_at");
15079
+ const closedAt = typeof observedClosedAt === "number" && Number.isFinite(observedClosedAt) && observedClosedAt >= 0 ? observedClosedAt : existing?.closedAt;
15080
+ const parentAgentId = stringValue(read2(subagent, "parent_agent_id")) ?? existing?.parentAgentId;
15081
+ setRecordValue(state.subagents, subagentId, {
15082
+ ...closedAt !== void 0 ? { closedAt } : {},
15083
+ openedAt,
15084
+ ...parentAgentId ? { parentAgentId } : {}
15085
+ });
15086
+ const span = await startSubagentSpan(
15087
+ state,
15088
+ subagentId,
15089
+ read2(subagent, "instructions"),
15090
+ {
15091
+ ...stringValue(read2(subagent, "name")) ? { agent_name: read2(subagent, "name") } : {},
15092
+ status: read2(subagent, "status")
15093
+ }
15094
+ );
15095
+ if (eventType === "agent.session.subagent.closed") {
15096
+ span.end({ endTime: closedAt ?? observedAt });
15097
+ }
15098
+ }
15099
+ async function closeTrace(state, endTime, error, usage) {
15100
+ if (state.ended) {
15101
+ return;
15102
+ }
15103
+ for (const tool of Object.values(state.openTools)) {
15104
+ const span = await startToolSpan(state, tool);
15105
+ span.log({
15106
+ error: error ?? new Error("OpenAI Agents turn ended before tool completion")
15107
+ });
15108
+ span.end({ endTime });
15109
+ }
15110
+ state.openTools = {};
15111
+ for (const subagentId of Object.keys(state.subagents)) {
15112
+ const subagent = state.subagents[subagentId];
15113
+ const span = await startSubagentSpan(state, subagentId);
15114
+ span.end({ endTime: subagent.closedAt ?? endTime });
15115
+ }
15116
+ const root = startRootSpan(state);
15117
+ root.log({
15118
+ ...error ? { error } : {},
15119
+ metrics: parseMetricsFromUsage(usage)
15120
+ });
15121
+ root.end({ endTime });
15122
+ state.ended = true;
15123
+ }
15124
+ async function captureTurnLifecycle(state, event, eventType, observedAt) {
15125
+ const turn = read2(event, "turn");
15126
+ const turnId = stringValue(read2(event, "turn_id")) ?? stringValue(read2(turn, "id"));
15127
+ const subagentId = stringValue(read2(turn, "subagent_id"));
15128
+ if (turnId && subagentId) {
15129
+ setRecordValue(state.turnSubagents, turnId, subagentId);
15130
+ if (!recordValue(state.subagents, subagentId)) {
15131
+ const createdAt = read2(turn, "created_at");
15132
+ setRecordValue(state.subagents, subagentId, {
15133
+ openedAt: typeof createdAt === "number" && Number.isFinite(createdAt) && createdAt >= 0 ? createdAt : observedAt
15134
+ });
15135
+ }
15136
+ await startSubagentSpan(state, subagentId);
15137
+ }
15138
+ const sessionId = stringValue(read2(event, "session_id"));
15139
+ if (sessionId) {
15140
+ startRootSpan(state).log({ metadata: { session_id: sessionId } });
15141
+ }
15142
+ if (!TERMINAL_TURN_EVENTS.has(eventType) || subagentId) {
15143
+ if (subagentId && eventType === "agent.session.turn.failed") {
15144
+ (await startSubagentSpan(state, subagentId)).log({
15145
+ error: loggedError(read2(turn, "error"), "OpenAI subagent turn failed")
15146
+ });
15147
+ }
15148
+ return;
15149
+ }
15150
+ const completedAt = read2(turn, "completed_at");
15151
+ const endTime = typeof completedAt === "number" && Number.isFinite(completedAt) && completedAt >= 0 ? completedAt : observedAt;
15152
+ const usage = read2(event, "usage") ?? read2(turn, "usage");
15153
+ const error = eventType === "agent.session.turn.completed" ? void 0 : loggedError(
15154
+ read2(turn, "error"),
15155
+ eventType === "agent.session.turn.cancelled" ? "OpenAI Agents turn cancelled" : "OpenAI Agents turn failed"
15156
+ );
15157
+ await closeTrace(state, endTime, error, usage);
15158
+ }
15159
+ async function captureEvent(state, event) {
15160
+ if (state.ended) {
15161
+ return state;
15162
+ }
15163
+ const eventType = stringValue(read2(event, "type"));
15164
+ const eventId = stringValue(read2(event, "event_id"));
15165
+ if (!eventType || eventId && state.eventIds.includes(eventId)) {
15166
+ return state;
15167
+ }
15168
+ const next = copyState(state);
15169
+ const observedAt = getCurrentUnixTimestamp();
15170
+ let handled = false;
15171
+ if (SESSION_EVENTS.has(eventType)) {
15172
+ const session = read2(event, "session");
15173
+ if (session) {
15174
+ updateSessionMetadata(next, session);
15175
+ }
15176
+ handled = true;
15177
+ }
15178
+ if (eventType === "agent.session.turn.item.added") {
15179
+ await captureItem(next, read2(event, "item"), false, observedAt);
15180
+ handled = true;
15181
+ } else if (eventType === "agent.session.turn.item.done") {
15182
+ await captureItem(next, read2(event, "item"), true, observedAt);
15183
+ handled = true;
15184
+ } else if (TURN_LIFECYCLE_EVENTS.has(eventType)) {
15185
+ await captureTurnLifecycle(next, event, eventType, observedAt);
15186
+ handled = true;
15187
+ } else if (SUBAGENT_EVENTS.has(eventType)) {
15188
+ await captureSubagent(next, eventType, read2(event, "subagent"), observedAt);
15189
+ handled = true;
15190
+ } else if (eventType === "agent.session.turn.output_text.delta" && next.firstTokenAt === void 0 && stringValue(read2(event, "delta"))) {
15191
+ next.firstTokenAt = observedAt;
15192
+ startRootSpan(next).log({
15193
+ metrics: { time_to_first_token: observedAt - next.startTime }
15194
+ });
15195
+ handled = true;
15196
+ } else if (eventType === "agent.session.failed") {
15197
+ const session = read2(event, "session");
15198
+ const lastActiveAt = read2(session, "last_active_at");
15199
+ const endTime = typeof lastActiveAt === "number" && Number.isFinite(lastActiveAt) && lastActiveAt >= 0 ? lastActiveAt : observedAt;
15200
+ await closeTrace(
15201
+ next,
15202
+ endTime,
15203
+ loggedError(read2(session, "error"), "OpenAI Agents session failed"),
15204
+ read2(session, "usage")
15205
+ );
15206
+ handled = true;
15207
+ } else if (eventType === "error") {
15208
+ await closeTrace(
15209
+ next,
15210
+ observedAt,
15211
+ loggedError(read2(event, "error"), "OpenAI Agents session failed")
15212
+ );
15213
+ handled = true;
15214
+ }
15215
+ if (!handled) {
15216
+ return state;
15217
+ }
15218
+ if (eventId) {
15219
+ next.eventIds.push(eventId);
15220
+ }
15221
+ return next;
15222
+ }
15223
+ var interceptOpenAIAgentsTraceStart = async (target, thisArg, args) => {
15224
+ const fallback2 = await Reflect.apply(target, thisArg, args);
15225
+ try {
15226
+ const state = args[0].state;
15227
+ const parent = state.rootParent;
15228
+ const traceArgs = args[0].args;
15229
+ const parentComponents = SpanComponentsV4.fromStr(parent);
15230
+ const hasParentSpan = Boolean(
15231
+ parentComponents.data.row_id && parentComponents.data.span_id && parentComponents.data.root_span_id
15232
+ );
15233
+ const rootComponents = SpanComponentsV4.fromStr(state.root);
15234
+ const rowId = stringValue(rootComponents.data.row_id);
15235
+ const rootSpanId = stringValue(rootComponents.data.root_span_id);
15236
+ const spanId = stringValue(rootComponents.data.span_id);
15237
+ if (!rowId || !rootSpanId || !spanId) {
15238
+ throw new Error("OpenAI Agents trace root is invalid");
15239
+ }
15240
+ withCurrent(
15241
+ NOOP_SPAN,
15242
+ () => _internalStartSpanWithInitialMergeAndParentSpanIds(
15243
+ withSpanInstrumentationName(
15244
+ {
15245
+ name: "openai.agents.turn",
15246
+ type: "task" /* TASK */,
15247
+ parent,
15248
+ ...!hasParentSpan ? {
15249
+ parentSpanIds: {
15250
+ parentSpanIds: [],
15251
+ rootSpanId
15252
+ }
15253
+ } : {},
15254
+ spanId,
15255
+ startTime: state.startTime,
15256
+ event: {
15257
+ id: rowId,
15258
+ input: read2(traceArgs, "input"),
15259
+ metadata: traceMetadata(traceArgs)
15260
+ }
15261
+ },
15262
+ INSTRUMENTATION_NAMES.OPENAI
15263
+ )
15264
+ )
15265
+ );
15266
+ return state;
15267
+ } catch (error) {
15268
+ logInstrumentationError("could not start trace", error);
15269
+ return fallback2;
15270
+ }
15271
+ };
15272
+ var interceptOpenAIAgentsTraceCapture = async (target, thisArg, args) => {
15273
+ const fallback2 = await Reflect.apply(target, thisArg, args);
15274
+ if (!args[0].state) {
15275
+ return fallback2;
15276
+ }
15277
+ try {
15278
+ return await captureEvent(args[0].state, args[0].event);
15279
+ } catch (error) {
15280
+ logInstrumentationError("could not capture event", error);
15281
+ return fallback2;
15282
+ }
15283
+ };
15284
+ var interceptOpenAIAgentsTraceFail = async (target, thisArg, args) => {
15285
+ const fallback2 = await Reflect.apply(target, thisArg, args);
15286
+ if (!args[0].state) {
15287
+ return fallback2;
15288
+ }
15289
+ try {
15290
+ const next = copyState(args[0].state);
15291
+ await closeTrace(
15292
+ next,
15293
+ getCurrentUnixTimestamp(),
15294
+ loggedError(args[0].error, "OpenAI Agents request failed")
15295
+ );
15296
+ return next;
15297
+ } catch (error) {
15298
+ logInstrumentationError("could not fail trace", error);
15299
+ return fallback2;
15300
+ }
15301
+ };
15302
+
14624
15303
  // src/instrumentation/plugins/openai-plugin.ts
14625
15304
  var OpenAIPlugin = class extends BasePlugin {
14626
15305
  constructor() {
@@ -14628,6 +15307,13 @@ var OpenAIPlugin = class extends BasePlugin {
14628
15307
  }
14629
15308
  onEnable() {
14630
15309
  this.unsubscribers.push(
15310
+ openAIChannels.agentsTraceStart.intercept(
15311
+ interceptOpenAIAgentsTraceStart
15312
+ ),
15313
+ openAIChannels.agentsTraceCapture.intercept(
15314
+ interceptOpenAIAgentsTraceCapture
15315
+ ),
15316
+ openAIChannels.agentsTraceFail.intercept(interceptOpenAIAgentsTraceFail),
14631
15317
  openAIChannels.filesCreateTraced.intercept(
14632
15318
  interceptOpenAIFilesCreateTraced
14633
15319
  ),
@@ -15188,7 +15874,7 @@ async function* patchCodexEventStream(events, state) {
15188
15874
  try {
15189
15875
  await handleCodexEvent(state, event);
15190
15876
  } catch (error) {
15191
- logInstrumentationError("OpenAI Codex stream event", error);
15877
+ logInstrumentationError2("OpenAI Codex stream event", error);
15192
15878
  }
15193
15879
  yield event;
15194
15880
  }
@@ -15688,10 +16374,10 @@ function safeLog(span, event) {
15688
16374
  try {
15689
16375
  span.log(event);
15690
16376
  } catch (error) {
15691
- logInstrumentationError("OpenAI Codex span log", error);
16377
+ logInstrumentationError2("OpenAI Codex span log", error);
15692
16378
  }
15693
16379
  }
15694
- function logInstrumentationError(context, error) {
16380
+ function logInstrumentationError2(context, error) {
15695
16381
  debugLogger.error(`Error processing ${context}:`, error);
15696
16382
  }
15697
16383
 
@@ -17086,27 +17772,8 @@ function continuationParentFromCreateSessionParams(params) {
17086
17772
  }
17087
17773
  return context.parent;
17088
17774
  }
17089
- function exportSpanSynchronously(span) {
17090
- const parentInfo = span.getParentInfo();
17091
- if (!parentInfo) {
17092
- return void 0;
17093
- }
17094
- const objectId = parentInfo.objectId.getSync().value;
17095
- if (!objectId && !parentInfo.computeObjectMetadataArgs) {
17096
- return void 0;
17097
- }
17098
- return new SpanComponentsV4({
17099
- object_type: parentInfo.objectType,
17100
- ...objectId ? { object_id: objectId } : {
17101
- compute_object_metadata_args: parentInfo.computeObjectMetadataArgs ?? {}
17102
- },
17103
- row_id: span.id,
17104
- root_span_id: span.rootSpanId,
17105
- span_id: span.spanId
17106
- }).toStr();
17107
- }
17108
17775
  function exportedParent(parent) {
17109
- return typeof parent === "string" ? parent : exportSpanSynchronously(parent);
17776
+ return typeof parent === "string" ? parent : _internalExportParentSynchronously(parent);
17110
17777
  }
17111
17778
  function addSerializedContext(args) {
17112
17779
  if (!isObject(args.continuation) || args.sessionId === void 0) {
@@ -17863,16 +18530,16 @@ function braintrustAISDKTelemetry() {
17863
18530
  if (!toolCallId || !state) {
17864
18531
  return;
17865
18532
  }
17866
- const toolOutput = event.toolOutput;
18533
+ const toolOutput2 = event.toolOutput;
17867
18534
  const workflowToolError = event.success === false && "error" in event ? event.error : void 0;
17868
- if (toolOutput?.type === "tool-error" || workflowToolError !== void 0) {
17869
- const error = toolOutput?.error ?? workflowToolError;
18535
+ if (toolOutput2?.type === "tool-error" || workflowToolError !== void 0) {
18536
+ const error = toolOutput2?.error ?? workflowToolError;
17870
18537
  state.span.log({
17871
18538
  error: error instanceof Error ? error.message : String(error),
17872
18539
  metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
17873
18540
  });
17874
18541
  } else {
17875
- const output = toolOutput && "output" in toolOutput ? toolOutput.output : event.output;
18542
+ const output = toolOutput2 && "output" in toolOutput2 ? toolOutput2.output : event.output;
17876
18543
  state.span.log({
17877
18544
  ...shouldRecordOutputs(event) ? { output } : {},
17878
18545
  metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
@@ -20331,9 +20998,9 @@ function patchAISDKStreamingResult(args) {
20331
20998
  }
20332
20999
  finalize({ metrics, output });
20333
21000
  } catch (error) {
20334
- const loggedError = toLoggedError(error);
21001
+ const loggedError2 = toLoggedError(error);
20335
21002
  try {
20336
- span.log({ error: loggedError });
21003
+ span.log({ error: loggedError2 });
20337
21004
  } catch (loggingError) {
20338
21005
  debugLogger.error(
20339
21006
  "Error logging AI SDK streaming failure:",
@@ -20341,7 +21008,7 @@ function patchAISDKStreamingResult(args) {
20341
21008
  );
20342
21009
  }
20343
21010
  finalize({
20344
- error: error instanceof Error ? error : new Error(String(loggedError))
21011
+ error: error instanceof Error ? error : new Error(String(loggedError2))
20345
21012
  });
20346
21013
  }
20347
21014
  };
@@ -20454,9 +21121,9 @@ function patchAISDKStreamingResult(args) {
20454
21121
  }
20455
21122
  controller.enqueue(value);
20456
21123
  } catch (error) {
20457
- const loggedError = toLoggedError(error);
21124
+ const loggedError2 = toLoggedError(error);
20458
21125
  try {
20459
- span.log({ error: loggedError });
21126
+ span.log({ error: loggedError2 });
20460
21127
  } catch (loggingError) {
20461
21128
  debugLogger.error(
20462
21129
  "Error logging AI SDK base stream failure:",
@@ -20464,7 +21131,7 @@ function patchAISDKStreamingResult(args) {
20464
21131
  );
20465
21132
  }
20466
21133
  finalize({
20467
- error: error instanceof Error ? error : new Error(String(loggedError))
21134
+ error: error instanceof Error ? error : new Error(String(loggedError2))
20468
21135
  });
20469
21136
  controller.error(error);
20470
21137
  }
@@ -23358,7 +24025,7 @@ function wrapSendOptionsCallbacks(options, state) {
23358
24025
  try {
23359
24026
  await handleInteractionUpdate(state, args.update);
23360
24027
  } catch (error) {
23361
- logInstrumentationError2("Cursor SDK onDelta", error);
24028
+ logInstrumentationError3("Cursor SDK onDelta", error);
23362
24029
  }
23363
24030
  if (originalOnDelta) {
23364
24031
  return originalOnDelta(args);
@@ -23368,7 +24035,7 @@ function wrapSendOptionsCallbacks(options, state) {
23368
24035
  try {
23369
24036
  handleStepUpdate(state, args.step);
23370
24037
  } catch (error) {
23371
- logInstrumentationError2("Cursor SDK onStep", error);
24038
+ logInstrumentationError3("Cursor SDK onStep", error);
23372
24039
  }
23373
24040
  if (originalOnStep) {
23374
24041
  return originalOnStep(args);
@@ -23450,7 +24117,7 @@ async function* patchCursorStream(stream, state) {
23450
24117
  try {
23451
24118
  await handleStreamMessage2(state, message);
23452
24119
  } catch (error) {
23453
- logInstrumentationError2("Cursor SDK stream", error);
24120
+ logInstrumentationError3("Cursor SDK stream", error);
23454
24121
  }
23455
24122
  yield message;
23456
24123
  }
@@ -23514,7 +24181,7 @@ async function handleToolUpdate(state, update) {
23514
24181
  if (!state.activeToolSpans.has(callId)) {
23515
24182
  state.activeToolSpans.set(
23516
24183
  callId,
23517
- await startToolSpan(state, {
24184
+ await startToolSpan2(state, {
23518
24185
  args,
23519
24186
  callId,
23520
24187
  name,
@@ -23525,7 +24192,7 @@ async function handleToolUpdate(state, update) {
23525
24192
  }
23526
24193
  return;
23527
24194
  }
23528
- const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan(state, {
24195
+ const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan2(state, {
23529
24196
  args,
23530
24197
  callId,
23531
24198
  name,
@@ -23562,7 +24229,7 @@ async function handleStreamMessage2(state, message) {
23562
24229
  } else if (block?.type === "tool_use" && block.id) {
23563
24230
  state.activeToolSpans.set(
23564
24231
  block.id,
23565
- await startToolSpan(state, {
24232
+ await startToolSpan2(state, {
23566
24233
  args: block.input,
23567
24234
  callId: block.id,
23568
24235
  name: block.name,
@@ -23597,7 +24264,7 @@ async function handleToolMessage(state, message) {
23597
24264
  if (!state.activeToolSpans.has(callId)) {
23598
24265
  state.activeToolSpans.set(
23599
24266
  callId,
23600
- await startToolSpan(state, {
24267
+ await startToolSpan2(state, {
23601
24268
  args: message.args,
23602
24269
  callId,
23603
24270
  name: message.name,
@@ -23608,7 +24275,7 @@ async function handleToolMessage(state, message) {
23608
24275
  }
23609
24276
  return;
23610
24277
  }
23611
- const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan(state, {
24278
+ const toolState = state.activeToolSpans.get(callId) ?? await startToolSpan2(state, {
23612
24279
  args: message.args,
23613
24280
  callId,
23614
24281
  name: message.name,
@@ -23635,7 +24302,7 @@ async function handleConversation(state, turns) {
23635
24302
  const command = turn.turn?.shellCommand?.command;
23636
24303
  if (command) {
23637
24304
  const callId = `shell:${state.activeToolSpans.size}:${command}`;
23638
- const toolState = await startToolSpan(state, {
24305
+ const toolState = await startToolSpan2(state, {
23639
24306
  args: turn.turn?.shellCommand,
23640
24307
  callId,
23641
24308
  name: "shell",
@@ -23659,7 +24326,7 @@ async function handleConversationStep(state, step) {
23659
24326
  }
23660
24327
  const toolCall = step.message;
23661
24328
  const callId = typeof toolCall?.callId === "string" ? toolCall.callId : `conversation-tool:${state.activeToolSpans.size}`;
23662
- const toolState = await startToolSpan(state, {
24329
+ const toolState = await startToolSpan2(state, {
23663
24330
  args: extractToolArgs(toolCall),
23664
24331
  callId,
23665
24332
  name: extractToolName(toolCall),
@@ -23690,7 +24357,7 @@ function handleStepUpdate(state, step) {
23690
24357
  state.stepText.push(step.message.text);
23691
24358
  }
23692
24359
  }
23693
- async function startToolSpan(state, args) {
24360
+ async function startToolSpan2(state, args) {
23694
24361
  const name = args.name || "unknown";
23695
24362
  const metadata = {
23696
24363
  "cursor_sdk.tool.status": args.status,
@@ -23977,10 +24644,10 @@ function safeLog2(span, event) {
23977
24644
  try {
23978
24645
  span.log(event);
23979
24646
  } catch (error) {
23980
- logInstrumentationError2("Cursor SDK span log", error);
24647
+ logInstrumentationError3("Cursor SDK span log", error);
23981
24648
  }
23982
24649
  }
23983
- function logInstrumentationError2(context, error) {
24650
+ function logInstrumentationError3(context, error) {
23984
24651
  debugLogger.error(`Error processing ${context}:`, error);
23985
24652
  }
23986
24653
  function cleanMetrics2(metrics) {
@@ -24818,6 +25485,10 @@ var googleGenAIChannels = defineChannels(
24818
25485
  channelName: "models.embedContent",
24819
25486
  kind: "async"
24820
25487
  }),
25488
+ httpResponseJson: channel({
25489
+ channelName: "httpResponse.json",
25490
+ kind: "async"
25491
+ }),
24821
25492
  interactionsCreate: channel({
24822
25493
  channelName: "interactions.create",
24823
25494
  kind: "async"
@@ -24966,13 +25637,45 @@ var GoogleGenAIPlugin = class extends BasePlugin {
24966
25637
  subscribeToEmbedContentChannel() {
24967
25638
  const tracingChannel = googleGenAIChannels.embedContent.tracingChannel();
24968
25639
  const states = /* @__PURE__ */ new WeakMap();
25640
+ const embeddingSpans = /* @__PURE__ */ new WeakSet();
25641
+ this.unsubscribers.push(
25642
+ googleGenAIChannels.httpResponseJson.intercept(
25643
+ (target, thisArg, args) => {
25644
+ const span = currentSpan();
25645
+ const result = Reflect.apply(target, thisArg, args);
25646
+ if (embeddingSpans.has(span)) {
25647
+ void Promise.resolve(result).then(
25648
+ (response) => {
25649
+ try {
25650
+ const metrics = cleanMetrics3(
25651
+ extractEmbedContentMetrics(response)
25652
+ );
25653
+ if (embeddingSpans.has(span) && Object.keys(metrics).length > 0) {
25654
+ span.log({ metrics });
25655
+ }
25656
+ } catch (error) {
25657
+ debugLogger.error(
25658
+ "Error reading Google GenAI embedding usage:",
25659
+ error
25660
+ );
25661
+ }
25662
+ },
25663
+ () => {
25664
+ }
25665
+ // The embedding channel handles the original rejection.
25666
+ );
25667
+ }
25668
+ return result;
25669
+ }
25670
+ )
25671
+ );
24969
25672
  const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
24970
25673
  tracingChannel,
24971
25674
  states,
24972
25675
  (event) => {
24973
25676
  const params = event.arguments[0];
24974
25677
  const input = serializeEmbedContentInput(params);
24975
- const metadata = extractEmbedContentMetadata(params);
25678
+ const metadata = { provider: "google", model: params.model };
24976
25679
  const span = startSpan(
24977
25680
  withSpanInstrumentationName(
24978
25681
  {
@@ -24985,6 +25688,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
24985
25688
  INSTRUMENTATION_NAMES.GOOGLE_GENAI
24986
25689
  )
24987
25690
  );
25691
+ embeddingSpans.add(span);
24988
25692
  return {
24989
25693
  span,
24990
25694
  startTime: getCurrentUnixTimestamp()
@@ -24996,7 +25700,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
24996
25700
  ensureSpanState(states, event, () => {
24997
25701
  const params = event.arguments[0];
24998
25702
  const input = serializeEmbedContentInput(params);
24999
- const metadata = extractEmbedContentMetadata(params);
25703
+ const metadata = { provider: "google", model: params.model };
25000
25704
  const span = startSpan(
25001
25705
  withSpanInstrumentationName(
25002
25706
  {
@@ -25009,6 +25713,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
25009
25713
  INSTRUMENTATION_NAMES.GOOGLE_GENAI
25010
25714
  )
25011
25715
  );
25716
+ embeddingSpans.add(span);
25012
25717
  return {
25013
25718
  span,
25014
25719
  startTime: getCurrentUnixTimestamp()
@@ -25021,20 +25726,28 @@ var GoogleGenAIPlugin = class extends BasePlugin {
25021
25726
  return;
25022
25727
  }
25023
25728
  try {
25024
- const output = summarizeEmbedContentOutput(event.result);
25025
25729
  spanState.span.log({
25026
- ...output ? { output } : {},
25730
+ output: summarizeEmbedContentOutput(event.result),
25027
25731
  metrics: cleanMetrics3(
25028
25732
  extractEmbedContentMetrics(event.result, spanState.startTime)
25029
25733
  )
25030
25734
  });
25031
25735
  } finally {
25736
+ embeddingSpans.delete(spanState.span);
25032
25737
  spanState.span.end();
25033
25738
  states.delete(event);
25034
25739
  }
25035
25740
  },
25036
25741
  error: (event) => {
25037
- logErrorAndEndSpan(states, event);
25742
+ const spanState = states.get(event);
25743
+ if (!spanState) return;
25744
+ try {
25745
+ spanState.span.log({ error: event.error, output: { count: 0 } });
25746
+ } finally {
25747
+ embeddingSpans.delete(spanState.span);
25748
+ spanState.span.end();
25749
+ states.delete(event);
25750
+ }
25038
25751
  }
25039
25752
  };
25040
25753
  tracingChannel.subscribe(handlers);
@@ -25269,15 +25982,53 @@ function serializeGenerateContentInput(params) {
25269
25982
  return input;
25270
25983
  }
25271
25984
  function serializeEmbedContentInput(params) {
25985
+ let contents = Array.isArray(params.contents) ? params.contents : [params.contents];
25986
+ if (params.model.includes("gemini-embedding-2") && contents.length > 0 && contents.every(
25987
+ (content) => typeof content === "string" || !Array.isArray(content) && !("parts" in content)
25988
+ )) {
25989
+ contents = [contents];
25990
+ }
25272
25991
  const input = {
25273
- model: params.model,
25274
- contents: serializeContentCollection(params.contents)
25992
+ inputs: contents.map((content) => {
25993
+ const parts = typeof content === "string" ? [content] : Array.isArray(content) ? content : "parts" in content ? content.parts : [content];
25994
+ const normalized = parts.flatMap((part) => {
25995
+ if (typeof part === "string") return [{ type: "text", text: part }];
25996
+ if (part.text !== void 0) return [{ type: "text", text: part.text }];
25997
+ const media = part.inlineData ?? part.fileData;
25998
+ if (!media) return [];
25999
+ const data = "data" in media ? `data:${media.mimeType};base64,${typeof media.data === "string" ? media.data : uint8ArrayToBase64(media.data)}` : media.fileUri;
26000
+ return media.mimeType?.startsWith("image/") ? [{ type: "image_url", image_url: { url: data } }] : [
26001
+ {
26002
+ type: "file",
26003
+ file: {
26004
+ file_data: data,
26005
+ ..."displayName" in media && media.displayName ? { filename: media.displayName } : {}
26006
+ }
26007
+ }
26008
+ ];
26009
+ });
26010
+ return {
26011
+ content: normalized.length === 1 && normalized[0].type === "text" ? normalized[0].text : normalized
26012
+ };
26013
+ }),
26014
+ ...params.config?.outputDimensionality !== void 0 ? { output_dimensions: params.config.outputDimensionality } : {}
25275
26015
  };
25276
- const config = params.config ? tryToDict(params.config) : null;
25277
- if (config) {
25278
- input.config = config;
26016
+ try {
26017
+ const processed = processInputAttachments(input);
26018
+ const hasInlineMedia = processed.inputs.some(
26019
+ ({ content }) => Array.isArray(content) && content.some((part) => {
26020
+ const data = part.type === "image_url" ? part.image_url.url : part.type === "file" ? part.file.file_data : void 0;
26021
+ return typeof data === "string" && data.startsWith("data:");
26022
+ })
26023
+ );
26024
+ return hasInlineMedia ? input : processed;
26025
+ } catch (error) {
26026
+ debugLogger.error(
26027
+ "Error processing Google GenAI embedding attachments:",
26028
+ error
26029
+ );
26030
+ return input;
25279
26031
  }
25280
- return input;
25281
26032
  }
25282
26033
  function serializeInteractionInput(params) {
25283
26034
  const input = {
@@ -25465,19 +26216,6 @@ function extractGenerateContentMetadata(params) {
25465
26216
  }
25466
26217
  return metadata;
25467
26218
  }
25468
- function extractEmbedContentMetadata(params) {
25469
- const metadata = {};
25470
- if (params.model) {
25471
- metadata.model = params.model;
25472
- }
25473
- const config = params.config ? tryToDict(params.config) : null;
25474
- if (config) {
25475
- Object.keys(config).forEach((key) => {
25476
- metadata[key] = config[key];
25477
- });
25478
- }
25479
- return metadata;
25480
- }
25481
26219
  function extractGenerateContentMetrics(response, startTime) {
25482
26220
  const metrics = {};
25483
26221
  if (startTime !== void 0) {
@@ -25497,15 +26235,23 @@ function extractEmbedContentMetrics(response, startTime) {
25497
26235
  const end = getCurrentUnixTimestamp();
25498
26236
  metrics.start = startTime;
25499
26237
  metrics.end = end;
25500
- metrics.duration = end - startTime;
25501
- }
25502
- if (response?.usageMetadata) {
25503
- populateUsageMetrics(metrics, response.usageMetadata);
25504
26238
  }
25505
26239
  const embeddingTokenCount = extractEmbedPromptTokenCount(response);
25506
26240
  if (embeddingTokenCount !== void 0) {
25507
26241
  metrics.prompt_tokens = embeddingTokenCount;
25508
- metrics.tokens = embeddingTokenCount;
26242
+ }
26243
+ const totalTokens = response?.usageMetadata?.totalTokenCount ?? embeddingTokenCount;
26244
+ if (totalTokens !== void 0) {
26245
+ metrics.tokens = totalTokens;
26246
+ }
26247
+ const audioTokens = (response?.usageMetadata?.promptTokenDetails ?? response?.usageMetadata?.promptTokensDetails)?.filter(
26248
+ (detail) => detail.modality === "AUDIO" && detail.tokenCount !== void 0
26249
+ );
26250
+ if (audioTokens?.length) {
26251
+ metrics.prompt_audio_tokens = audioTokens.reduce(
26252
+ (sum, detail) => sum + (detail.tokenCount ?? 0),
26253
+ 0
26254
+ );
25509
26255
  }
25510
26256
  return metrics;
25511
26257
  }
@@ -25544,41 +26290,25 @@ function extractEmbedPromptTokenCount(response) {
25544
26290
  if (typeof usagePromptTokens === "number" && Number.isFinite(usagePromptTokens)) {
25545
26291
  return usagePromptTokens;
25546
26292
  }
25547
- const usageTotalTokens = response.usageMetadata?.totalTokenCount;
25548
- if (typeof usageTotalTokens === "number" && Number.isFinite(usageTotalTokens)) {
25549
- return usageTotalTokens;
25550
- }
25551
26293
  const embeddings = Array.isArray(response.embeddings) ? response.embeddings : response.embedding ? [response.embedding] : [];
25552
26294
  if (embeddings.length === 0) {
25553
26295
  return void 0;
25554
26296
  }
25555
26297
  let total = 0;
25556
- let sawAny = false;
25557
26298
  for (const embedding of embeddings) {
25558
26299
  const embeddingStats = tryToDict(tryToDict(embedding)?.statistics);
25559
26300
  const tokenCount2 = embeddingStats?.tokenCount;
25560
26301
  if (typeof tokenCount2 === "number" && Number.isFinite(tokenCount2)) {
25561
26302
  total += tokenCount2;
25562
- sawAny = true;
26303
+ } else {
26304
+ return void 0;
25563
26305
  }
25564
26306
  }
25565
- return sawAny ? total : void 0;
26307
+ return total;
25566
26308
  }
25567
26309
  function summarizeEmbedContentOutput(response) {
25568
- if (!response) {
25569
- return void 0;
25570
- }
25571
- const embeddings = Array.isArray(response.embeddings) ? response.embeddings : response.embedding ? [response.embedding] : [];
25572
- if (embeddings.length === 0) {
25573
- return void 0;
25574
- }
25575
- const firstValues = embeddings[0]?.values;
25576
- if (!Array.isArray(firstValues)) {
25577
- return void 0;
25578
- }
25579
26310
  return {
25580
- embedding_count: embeddings.length,
25581
- embedding_length: firstValues.length
26311
+ count: Array.isArray(response?.embeddings) ? response.embeddings.length : response?.embedding ? 1 : 0
25582
26312
  };
25583
26313
  }
25584
26314
  function populateUsageMetrics(metrics, usage) {
@@ -29205,6 +29935,379 @@ function aggregateMistralStreamChunks(chunks) {
29205
29935
  };
29206
29936
  }
29207
29937
 
29938
+ // src/instrumentation/plugins/langgraph-sdk-channels.ts
29939
+ var langGraphSDKChannels = defineChannels(
29940
+ "@langchain/langgraph-sdk",
29941
+ {
29942
+ wait: channel({
29943
+ channelName: "runs.wait",
29944
+ kind: "async"
29945
+ }),
29946
+ stream: channel({
29947
+ channelName: "runs.stream",
29948
+ kind: "sync-stream"
29949
+ })
29950
+ },
29951
+ { instrumentationName: INSTRUMENTATION_NAMES.LANGGRAPH_SDK }
29952
+ );
29953
+
29954
+ // src/instrumentation/plugins/langgraph-sdk-plugin.ts
29955
+ var LangGraphSDKPlugin = class extends BasePlugin {
29956
+ onEnable() {
29957
+ this.unsubscribers.push(
29958
+ langGraphSDKChannels.wait.intercept(
29959
+ (target, self, args) => instrumentRun("wait", args, () => Reflect.apply(target, self, args))
29960
+ ),
29961
+ langGraphSDKChannels.stream.intercept(
29962
+ (target, self, args) => instrumentRun("stream", args, () => Reflect.apply(target, self, args))
29963
+ )
29964
+ );
29965
+ }
29966
+ onDisable() {
29967
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
29968
+ }
29969
+ };
29970
+ function normalizeMessage(value) {
29971
+ if (!isObject(value)) return value;
29972
+ 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);
29973
+ if (typeof role !== "string") return value;
29974
+ const message = {
29975
+ role,
29976
+ content: value.content ?? ""
29977
+ };
29978
+ for (const key of ["name", "tool_call_id", "refusal"]) {
29979
+ if (value[key] !== void 0) message[key] = value[key];
29980
+ }
29981
+ const additional = isObject(value.additional_kwargs) ? value.additional_kwargs : {};
29982
+ const toolCalls2 = Array.isArray(value.tool_calls) && value.tool_calls.length ? value.tool_calls : additional.tool_calls;
29983
+ if (Array.isArray(toolCalls2) && toolCalls2.length > 0) {
29984
+ message.tool_calls = toolCalls2.map((call) => {
29985
+ if (!isObject(call)) return call;
29986
+ if (isObject(call.function)) return call;
29987
+ return {
29988
+ id: call.id,
29989
+ type: "function",
29990
+ function: {
29991
+ name: call.name,
29992
+ arguments: typeof call.args === "string" ? call.args : JSON.stringify(call.args ?? {})
29993
+ }
29994
+ };
29995
+ });
29996
+ }
29997
+ if (Array.isArray(value.invalid_tool_calls) && value.invalid_tool_calls.length > 0)
29998
+ message.invalid_tool_calls = value.invalid_tool_calls;
29999
+ if (message.refusal === void 0 && additional.refusal !== void 0)
30000
+ message.refusal = additional.refusal;
30001
+ return message;
30002
+ }
30003
+ function normalizeRunError(value) {
30004
+ let name;
30005
+ let message;
30006
+ if (value instanceof Error) {
30007
+ name = value.name;
30008
+ message = value.message;
30009
+ } else if (isObject(value) && typeof value.error === "string" && typeof value.message === "string") {
30010
+ name = value.error;
30011
+ message = value.message;
30012
+ } else {
30013
+ return value;
30014
+ }
30015
+ for (let depth = 0; depth < 3; depth++) {
30016
+ try {
30017
+ const nested = JSON.parse(
30018
+ message.startsWith(`${name}: `) ? message.slice(name.length + 2) : message
30019
+ );
30020
+ if (!isObject(nested) || typeof nested.error !== "string" || typeof nested.message !== "string")
30021
+ break;
30022
+ name = nested.error;
30023
+ message = nested.message;
30024
+ } catch {
30025
+ break;
30026
+ }
30027
+ }
30028
+ if (value instanceof Error && name === value.name && message === value.message)
30029
+ return value;
30030
+ return Object.assign(new Error(message), { name });
30031
+ }
30032
+ function normalizeState(value) {
30033
+ if (!isObject(value)) return value;
30034
+ return Object.fromEntries(
30035
+ Object.entries(value).map(([key, field]) => {
30036
+ if (key === "messages" && Array.isArray(field))
30037
+ return [key, field.map(normalizeMessage)];
30038
+ if (key === "__error__") {
30039
+ const error = normalizeRunError(field);
30040
+ if (error instanceof Error)
30041
+ return [key, { error: error.name, message: error.message }];
30042
+ }
30043
+ return [key, field];
30044
+ })
30045
+ );
30046
+ }
30047
+ function normalizeRunOutput(value, input) {
30048
+ if (!isObject(value)) return value;
30049
+ if (Array.isArray(value.messages)) {
30050
+ if (value.__interrupt__ !== void 0 || value.__error__ !== void 0)
30051
+ return void 0;
30052
+ const inputMessages = isObject(input) && Array.isArray(input.messages) ? input.messages : [];
30053
+ let inputPrefixLength = 0;
30054
+ while (inputPrefixLength < inputMessages.length) {
30055
+ const previous = inputMessages[inputPrefixLength];
30056
+ const message = value.messages[inputPrefixLength];
30057
+ 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)))
30058
+ break;
30059
+ inputPrefixLength++;
30060
+ }
30061
+ for (let index = value.messages.length - 1; index >= inputPrefixLength; index--) {
30062
+ const message = value.messages[index];
30063
+ const normalized = normalizeMessage(message);
30064
+ if (!isObject(normalized)) continue;
30065
+ if (normalized.role === "user") return void 0;
30066
+ if (normalized.role !== "assistant") continue;
30067
+ if (inputMessages.some((previous) => {
30068
+ if (!isObject(previous) || !isObject(message)) return false;
30069
+ return previous.id !== void 0 && previous.id === message.id && JSON.stringify(normalizeMessage(previous)) === JSON.stringify(normalized);
30070
+ }))
30071
+ continue;
30072
+ return normalized;
30073
+ }
30074
+ return void 0;
30075
+ }
30076
+ const result = Object.fromEntries(
30077
+ Object.entries(value).filter(
30078
+ ([key]) => key !== "__interrupt__" && key !== "__error__"
30079
+ )
30080
+ );
30081
+ return !Object.keys(result).length && (value.__interrupt__ !== void 0 || value.__error__ !== void 0) ? void 0 : result;
30082
+ }
30083
+ function instrumentRun(operation, [threadId, assistantId, options], invoke2) {
30084
+ if (isAutoInstrumentationSuppressed()) return invoke2();
30085
+ const start = getCurrentUnixTimestamp();
30086
+ let span;
30087
+ try {
30088
+ const metadata = {
30089
+ "langgraph.thread_id": threadId,
30090
+ "langgraph.assistant_id": assistantId
30091
+ };
30092
+ for (const key of [
30093
+ "streamMode",
30094
+ "streamSubgraphs",
30095
+ "interruptBefore",
30096
+ "interruptAfter",
30097
+ "multitaskStrategy",
30098
+ "durability"
30099
+ ]) {
30100
+ if (options?.[key] !== void 0) metadata[key] = options[key];
30101
+ }
30102
+ span = startSpan(
30103
+ withSpanInstrumentationName(
30104
+ {
30105
+ name: `langgraph.runs.${operation}`,
30106
+ spanAttributes: { type: "task" /* TASK */ },
30107
+ event: {
30108
+ input: options?.command === void 0 ? normalizeState(options?.input) : {
30109
+ input: normalizeState(options.input),
30110
+ command: options.command
30111
+ },
30112
+ metadata
30113
+ }
30114
+ },
30115
+ INSTRUMENTATION_NAMES.LANGGRAPH_SDK
30116
+ )
30117
+ );
30118
+ } catch (error) {
30119
+ debugLogger.error("Error starting LangGraph SDK span:", error);
30120
+ return invoke2();
30121
+ }
30122
+ let ended = false;
30123
+ let output;
30124
+ let streamError;
30125
+ let firstToken;
30126
+ const updates = [];
30127
+ const usageByMessage = /* @__PURE__ */ new Map();
30128
+ const captureUsage = (id, usage) => {
30129
+ if (!isObject(usage)) return;
30130
+ const metrics = {};
30131
+ for (const [source, destination] of [
30132
+ ["input_tokens", "prompt_tokens"],
30133
+ ["output_tokens", "completion_tokens"],
30134
+ ["total_tokens", "tokens"]
30135
+ ]) {
30136
+ const value = usage[source];
30137
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0)
30138
+ metrics[destination] = value;
30139
+ }
30140
+ if (metrics.tokens === void 0 && metrics.prompt_tokens !== void 0 && metrics.completion_tokens !== void 0)
30141
+ metrics.tokens = metrics.prompt_tokens + metrics.completion_tokens;
30142
+ usageByMessage.set(id, { ...usageByMessage.get(id), ...metrics });
30143
+ };
30144
+ const messages = /* @__PURE__ */ new Map();
30145
+ const messageSnapshots = /* @__PURE__ */ new Map();
30146
+ const finish = (error) => {
30147
+ if (ended) return;
30148
+ ended = true;
30149
+ try {
30150
+ const metrics = {};
30151
+ for (const usage of usageByMessage.values()) {
30152
+ for (const [key, value] of Object.entries(usage))
30153
+ metrics[key] = (metrics[key] ?? 0) + value;
30154
+ }
30155
+ if (firstToken !== void 0)
30156
+ metrics.time_to_first_token = firstToken - start;
30157
+ const finalMessages = [
30158
+ ...new Map([...messages, ...messageSnapshots]).values()
30159
+ ];
30160
+ let loggedOutput = normalizeRunOutput(output, options?.input);
30161
+ if (loggedOutput === void 0 && finalMessages.length)
30162
+ loggedOutput = normalizeRunOutput(
30163
+ { messages: finalMessages },
30164
+ void 0
30165
+ );
30166
+ if (output === void 0 && !finalMessages.length && updates.length) {
30167
+ const results = updates.map((update) => normalizeRunOutput(update, options?.input)).filter((update) => update !== void 0);
30168
+ if (results.length) loggedOutput = { updates: results };
30169
+ }
30170
+ const interrupted = [output, ...updates].find(
30171
+ (state) => isObject(state) && state.__interrupt__ !== void 0
30172
+ );
30173
+ span.log({
30174
+ ...loggedOutput !== void 0 ? { output: loggedOutput } : {},
30175
+ ...isObject(interrupted) ? { metadata: { "langgraph.interrupts": interrupted.__interrupt__ } } : {},
30176
+ ...error !== void 0 || streamError !== void 0 ? { error: normalizeRunError(error ?? streamError) } : {},
30177
+ metrics
30178
+ });
30179
+ } catch (error2) {
30180
+ debugLogger.error("Error logging LangGraph SDK span:", error2);
30181
+ }
30182
+ try {
30183
+ span.end();
30184
+ } catch (error2) {
30185
+ debugLogger.error("Error ending LangGraph SDK span:", error2);
30186
+ }
30187
+ };
30188
+ const observeMessages = (value, streaming) => {
30189
+ if (!isObject(value) || !Array.isArray(value.messages)) return;
30190
+ const inputMessages = isObject(options?.input) && Array.isArray(options.input.messages) ? options.input.messages : [];
30191
+ for (const message of value.messages) {
30192
+ if (!isObject(message) || message.type !== "ai" && message.role !== "assistant")
30193
+ continue;
30194
+ if (message.id !== void 0 && inputMessages.some(
30195
+ (input) => isObject(input) && input.id === message.id
30196
+ ))
30197
+ continue;
30198
+ captureUsage(
30199
+ typeof message.id === "string" ? message.id : "message",
30200
+ message.usage_metadata
30201
+ );
30202
+ if (streaming && (typeof message.content === "string" ? message.content.length > 0 : Array.isArray(message.content) && message.content.some(
30203
+ (part) => isObject(part) && typeof part.text === "string" && part.text.length > 0
30204
+ )))
30205
+ firstToken ??= getCurrentUnixTimestamp();
30206
+ }
30207
+ };
30208
+ const onChunk = ({ event, data }) => {
30209
+ if (ended) return;
30210
+ if (event === "metadata" && isObject(data)) {
30211
+ if (typeof data.run_id === "string")
30212
+ span.log({ metadata: { "langgraph.run_id": data.run_id } });
30213
+ } else if (event === "error") {
30214
+ streamError = normalizeRunError(data);
30215
+ } else if (event === "values") {
30216
+ output = data;
30217
+ observeMessages(data, true);
30218
+ } else if (event === "updates") {
30219
+ if (isObject(data)) {
30220
+ const stateUpdates = [];
30221
+ for (const [node, update] of Object.entries(data)) {
30222
+ observeMessages(update, true);
30223
+ if (isObject(update) && Array.isArray(update.messages)) {
30224
+ for (const message of update.messages) {
30225
+ if (isObject(message))
30226
+ messageSnapshots.set(
30227
+ typeof message.id === "string" ? message.id : `update-${messageSnapshots.size}`,
30228
+ message
30229
+ );
30230
+ }
30231
+ const state = Object.fromEntries(
30232
+ Object.entries(update).filter(([key]) => key !== "messages")
30233
+ );
30234
+ if (Object.keys(state).length) stateUpdates.push([node, state]);
30235
+ } else {
30236
+ stateUpdates.push([node, update]);
30237
+ }
30238
+ }
30239
+ if (stateUpdates.length) updates.push(Object.fromEntries(stateUpdates));
30240
+ } else {
30241
+ updates.push(data);
30242
+ }
30243
+ } else if ((event === "messages" || event === "messages/partial" || event === "messages/complete") && Array.isArray(data)) {
30244
+ const parts = event === "messages" ? [data[0]] : data;
30245
+ for (const part of parts) {
30246
+ if (!isObject(part)) continue;
30247
+ const id = typeof part.id === "string" ? part.id : "message";
30248
+ captureUsage(id, part.usage_metadata);
30249
+ const previous = messages.get(id);
30250
+ messages.set(
30251
+ id,
30252
+ event === "messages" && previous && typeof part.content === "string" && typeof previous.content === "string" ? { ...part, content: previous.content + part.content } : part
30253
+ );
30254
+ if (typeof part.content === "string" && part.content.length > 0)
30255
+ firstToken ??= getCurrentUnixTimestamp();
30256
+ }
30257
+ }
30258
+ };
30259
+ let result;
30260
+ try {
30261
+ result = withCurrent(
30262
+ span,
30263
+ () => runWithAutoInstrumentationSuppressed(invoke2)
30264
+ );
30265
+ } catch (error) {
30266
+ finish(error);
30267
+ throw error;
30268
+ }
30269
+ if (operation === "stream") {
30270
+ try {
30271
+ patchStreamIfNeeded(result, {
30272
+ shouldCollect: (chunk) => {
30273
+ try {
30274
+ onChunk(chunk);
30275
+ } catch (error) {
30276
+ debugLogger.error(
30277
+ "Error processing LangGraph stream event:",
30278
+ error
30279
+ );
30280
+ }
30281
+ return false;
30282
+ },
30283
+ aroundNext: (next) => withCurrent(span, () => runWithAutoInstrumentationSuppressed(next)),
30284
+ onComplete: () => finish(),
30285
+ onCancel: () => finish(),
30286
+ onError: (error) => finish(error)
30287
+ });
30288
+ } catch (error) {
30289
+ debugLogger.error("Error observing LangGraph stream:", error);
30290
+ finish();
30291
+ }
30292
+ } else {
30293
+ void Promise.resolve(result).then(
30294
+ (value) => {
30295
+ try {
30296
+ output = value;
30297
+ observeMessages(value, false);
30298
+ if (isObject(value) && isObject(value.__error__))
30299
+ streamError = normalizeRunError(value.__error__);
30300
+ finish();
30301
+ } catch (error) {
30302
+ finish(error);
30303
+ }
30304
+ },
30305
+ (error) => finish(error)
30306
+ );
30307
+ }
30308
+ return result;
30309
+ }
30310
+
29208
30311
  // src/instrumentation/plugins/ollama-channels.ts
29209
30312
  var ollamaChannels = defineChannels(
29210
30313
  "ollama",
@@ -29414,7 +30517,7 @@ function normalizeTextAndImages(content, images) {
29414
30517
  ...unrecognizedImages.length > 0 ? { unrecognizedImages } : {}
29415
30518
  };
29416
30519
  }
29417
- function normalizeMessage(message, toolCallId, syntheticToolCallIdOffset = 0) {
30520
+ function normalizeMessage2(message, toolCallId, syntheticToolCallIdOffset = 0) {
29418
30521
  if (typeof message.role !== "string") {
29419
30522
  return void 0;
29420
30523
  }
@@ -29460,7 +30563,7 @@ function normalizeMessages(messages) {
29460
30563
  toolCallId = pendingToolCallIds.get(toolName)?.shift();
29461
30564
  }
29462
30565
  }
29463
- const normalized = normalizeMessage(
30566
+ const normalized = normalizeMessage2(
29464
30567
  ollamaMessage,
29465
30568
  toolCallId,
29466
30569
  syntheticToolCallIdOffset
@@ -29579,7 +30682,7 @@ function extractOllamaChatOutput(result, syntheticToolCallIdOffset = 0) {
29579
30682
  if (!isObject(result) || !isObject(result.message)) {
29580
30683
  return void 0;
29581
30684
  }
29582
- const message = normalizeMessage(
30685
+ const message = normalizeMessage2(
29583
30686
  result.message,
29584
30687
  void 0,
29585
30688
  syntheticToolCallIdOffset
@@ -32299,14 +33402,14 @@ function extractActionSpanMetadata(args) {
32299
33402
  const options = extractRunInNewSpanOptions(args);
32300
33403
  const labels = isObject(options?.labels) ? options.labels : void 0;
32301
33404
  const metadata = isObject(options?.metadata) ? options.metadata : void 0;
32302
- const actionType = stringValue(labels?.["genkit:metadata:subtype"]);
32303
- const name = stringValue(metadata?.name);
33405
+ const actionType = stringValue2(labels?.["genkit:metadata:subtype"]);
33406
+ const name = stringValue2(metadata?.name);
32304
33407
  if (!actionType || !name) {
32305
33408
  return void 0;
32306
33409
  }
32307
33410
  return {
32308
33411
  actionType,
32309
- key: stringValue(labels?.["genkit:key"]),
33412
+ key: stringValue2(labels?.["genkit:key"]),
32310
33413
  name
32311
33414
  };
32312
33415
  }
@@ -32416,7 +33519,7 @@ function pickNumberMetrics(values) {
32416
33519
  })
32417
33520
  );
32418
33521
  }
32419
- function stringValue(value) {
33522
+ function stringValue2(value) {
32420
33523
  return typeof value === "string" ? value : void 0;
32421
33524
  }
32422
33525
 
@@ -33101,7 +34204,7 @@ function subscribeToFlueContext(value, state) {
33101
34204
  try {
33102
34205
  unsubscribe?.();
33103
34206
  } catch (error) {
33104
- logInstrumentationError3("Flue context unsubscribe", error);
34207
+ logInstrumentationError4("Flue context unsubscribe", error);
33105
34208
  }
33106
34209
  };
33107
34210
  try {
@@ -33117,7 +34220,7 @@ function subscribeToFlueContext(value, state) {
33117
34220
  });
33118
34221
  state.contexts.add(value);
33119
34222
  } catch (error) {
33120
- logInstrumentationError3("Flue context subscription", error);
34223
+ logInstrumentationError4("Flue context subscription", error);
33121
34224
  }
33122
34225
  }
33123
34226
  function isAutoContextTerminalEvent(event, ctx) {
@@ -33173,7 +34276,7 @@ var FlueObserveBridge = class {
33173
34276
  try {
33174
34277
  this.handleEvent(event, flueContextFromUnknown(ctx));
33175
34278
  } catch (error) {
33176
- logInstrumentationError3("Flue observe", error);
34279
+ logInstrumentationError4("Flue observe", error);
33177
34280
  }
33178
34281
  }
33179
34282
  reset() {
@@ -33190,7 +34293,7 @@ var FlueObserveBridge = class {
33190
34293
  try {
33191
34294
  span = this.spanForExecutionOperation(operation, executionContext);
33192
34295
  } catch (error) {
33193
- logInstrumentationError3("Flue execution interceptor", error);
34296
+ logInstrumentationError4("Flue execution interceptor", error);
33194
34297
  }
33195
34298
  return span ? runWithCurrentSpanStore(span, next) : next();
33196
34299
  }
@@ -33396,7 +34499,7 @@ var FlueObserveBridge = class {
33396
34499
  this.runsById.delete(event.runId);
33397
34500
  }
33398
34501
  void flush().catch((error) => {
33399
- logInstrumentationError3("Flue flush", error);
34502
+ logInstrumentationError4("Flue flush", error);
33400
34503
  });
33401
34504
  }
33402
34505
  handleOperationStart(event) {
@@ -34171,17 +35274,17 @@ function safeLog3(span, event) {
34171
35274
  try {
34172
35275
  span.log(event);
34173
35276
  } catch (error) {
34174
- logInstrumentationError3("Flue span log", error);
35277
+ logInstrumentationError4("Flue span log", error);
34175
35278
  }
34176
35279
  }
34177
35280
  function safeEnd(span, endTime) {
34178
35281
  try {
34179
35282
  span.end(endTime === void 0 ? void 0 : { endTime });
34180
35283
  } catch (error) {
34181
- logInstrumentationError3("Flue span end", error);
35284
+ logInstrumentationError4("Flue span end", error);
34182
35285
  }
34183
35286
  }
34184
- function logInstrumentationError3(label, error) {
35287
+ function logInstrumentationError4(label, error) {
34185
35288
  debugLogger.debug(`Error in ${label} instrumentation:`, error);
34186
35289
  }
34187
35290
 
@@ -34749,10 +35852,10 @@ var LangSmithPlugin = class extends BasePlugin {
34749
35852
  const creates = ownValue(batch, "runCreates");
34750
35853
  if (Array.isArray(creates)) {
34751
35854
  const parentFirst = [...creates].sort((left, right) => {
34752
- const leftId = stringValue2(ownValue(left, "id"));
34753
- const rightId = stringValue2(ownValue(right, "id"));
34754
- const leftParent = stringValue2(ownValue(left, "parent_run_id"));
34755
- const rightParent = stringValue2(ownValue(right, "parent_run_id"));
35855
+ const leftId = stringValue3(ownValue(left, "id"));
35856
+ const rightId = stringValue3(ownValue(right, "id"));
35857
+ const leftParent = stringValue3(ownValue(left, "parent_run_id"));
35858
+ const rightParent = stringValue3(ownValue(right, "parent_run_id"));
34756
35859
  if (leftParent && leftParent === rightId) {
34757
35860
  return 1;
34758
35861
  }
@@ -34771,13 +35874,13 @@ var LangSmithPlugin = class extends BasePlugin {
34771
35874
  if (Array.isArray(updates)) {
34772
35875
  for (const run of updates) {
34773
35876
  this.containLifecycleFailure("batchIngestRuns update", () => {
34774
- this.processUpdate(stringValue2(ownValue(run, "id")) ?? "", run);
35877
+ this.processUpdate(stringValue3(ownValue(run, "id")) ?? "", run);
34775
35878
  });
34776
35879
  }
34777
35880
  }
34778
35881
  }
34779
35882
  processCreate(run) {
34780
- const id = stringValue2(ownValue(run, "id"));
35883
+ const id = stringValue3(ownValue(run, "id"));
34781
35884
  if (!id || this.completedRuns.get(id)) {
34782
35885
  return;
34783
35886
  }
@@ -34810,7 +35913,7 @@ var LangSmithPlugin = class extends BasePlugin {
34810
35913
  this.endIfComplete(id, activeRun, run);
34811
35914
  }
34812
35915
  processUpdate(explicitId, run) {
34813
- const id = stringValue2(explicitId) ?? stringValue2(ownValue(run, "id"));
35916
+ const id = stringValue3(explicitId) ?? stringValue3(ownValue(run, "id"));
34814
35917
  if (!id || this.completedRuns.get(id)) {
34815
35918
  return;
34816
35919
  }
@@ -34833,13 +35936,13 @@ var LangSmithPlugin = class extends BasePlugin {
34833
35936
  this.endIfComplete(id, active, active.run);
34834
35937
  }
34835
35938
  startRunSpan(id, run) {
34836
- const traceId = stringValue2(ownValue(run, "trace_id")) ?? id;
34837
- const parentId = stringValue2(ownValue(run, "parent_run_id")) ?? stringValue2(ownValue(ownValue(run, "parent_run"), "id"));
35939
+ const traceId = stringValue3(ownValue(run, "trace_id")) ?? id;
35940
+ const parentId = stringValue3(ownValue(run, "parent_run_id")) ?? stringValue3(ownValue(ownValue(run, "parent_run"), "id"));
34838
35941
  const startTime = timestampSeconds(ownValue(run, "start_time"));
34839
35942
  return startSpan(
34840
35943
  withSpanInstrumentationName(
34841
35944
  {
34842
- name: stringValue2(ownValue(run, "name")) ?? "LangSmith run",
35945
+ name: stringValue3(ownValue(run, "name")) ?? "LangSmith run",
34843
35946
  spanId: id,
34844
35947
  parentSpanIds: {
34845
35948
  parentSpanIds: parentId ? [parentId] : [],
@@ -34931,7 +36034,7 @@ function mergeRuns(previous, current) {
34931
36034
  function isRecord2(value) {
34932
36035
  return typeof value === "object" && value !== null && !Array.isArray(value);
34933
36036
  }
34934
- function stringValue2(value) {
36037
+ function stringValue3(value) {
34935
36038
  return typeof value === "string" && value.length > 0 ? value : void 0;
34936
36039
  }
34937
36040
  function timestampSeconds(value) {
@@ -34949,7 +36052,7 @@ function timestampSeconds(value) {
34949
36052
  return void 0;
34950
36053
  }
34951
36054
  function dottedOrderDepth(run) {
34952
- const dottedOrder = stringValue2(ownValue(run, "dotted_order"));
36055
+ const dottedOrder = stringValue3(ownValue(run, "dotted_order"));
34953
36056
  return dottedOrder ? dottedOrder.split(".").length : Number.MAX_SAFE_INTEGER;
34954
36057
  }
34955
36058
  function mapRunType(runType) {
@@ -35154,7 +36257,7 @@ var PiCodingAgentPlugin = class extends BasePlugin {
35154
36257
  }
35155
36258
  );
35156
36259
  } catch (error) {
35157
- logInstrumentationError4("Pi Coding Agent prompt start", error);
36260
+ logInstrumentationError5("Pi Coding Agent prompt start", error);
35158
36261
  }
35159
36262
  if (!state) {
35160
36263
  return runWithAutoInstrumentationSuppressed(invokeTarget);
@@ -35287,12 +36390,12 @@ function installPiAgentInstrumentation(agent) {
35287
36390
  () => handlePiAgentEvent(state, event)
35288
36391
  );
35289
36392
  } catch (error) {
35290
- logInstrumentationError4("Pi Coding Agent event", error);
36393
+ logInstrumentationError5("Pi Coding Agent event", error);
35291
36394
  }
35292
36395
  });
35293
36396
  piAgentEventSubscriptions.add(agent);
35294
36397
  } catch (error) {
35295
- logInstrumentationError4("Pi Coding Agent event subscription", error);
36398
+ logInstrumentationError5("Pi Coding Agent event subscription", error);
35296
36399
  }
35297
36400
  }
35298
36401
  function makeInstrumentedStreamFunction(agent, originalStreamFunction, property) {
@@ -35342,7 +36445,7 @@ function wrapPiToolExecutors(tools) {
35342
36445
  });
35343
36446
  tool.execute = wrappedExecute;
35344
36447
  } catch (error) {
35345
- logInstrumentationError4("Pi Coding Agent tool wrapping", error);
36448
+ logInstrumentationError5("Pi Coding Agent tool wrapping", error);
35346
36449
  }
35347
36450
  }
35348
36451
  }
@@ -35421,7 +36524,7 @@ function patchAssistantMessageStream(stream, promptState, llmState) {
35421
36524
  try {
35422
36525
  await iterator.return();
35423
36526
  } catch (cleanupError) {
35424
- logInstrumentationError4(
36527
+ logInstrumentationError5(
35425
36528
  "Pi Coding Agent stream cleanup",
35426
36529
  cleanupError
35427
36530
  );
@@ -35586,7 +36689,7 @@ function finishPiPromptRun(state, error) {
35586
36689
  try {
35587
36690
  state.span.end();
35588
36691
  } catch (endError) {
35589
- logInstrumentationError4("Pi Coding Agent prompt end", endError);
36692
+ logInstrumentationError5("Pi Coding Agent prompt end", endError);
35590
36693
  }
35591
36694
  }
35592
36695
  }
@@ -35918,10 +37021,10 @@ function safeLog4(span, event) {
35918
37021
  try {
35919
37022
  span.log(event);
35920
37023
  } catch (error) {
35921
- logInstrumentationError4("Pi Coding Agent span log", error);
37024
+ logInstrumentationError5("Pi Coding Agent span log", error);
35922
37025
  }
35923
37026
  }
35924
- function logInstrumentationError4(context, error) {
37027
+ function logInstrumentationError5(context, error) {
35925
37028
  debugLogger.debug(`${context}:`, error);
35926
37029
  }
35927
37030
 
@@ -36159,7 +37262,7 @@ function handleAgentStreamEvent(state, event) {
36159
37262
  finalizeModelSpan(state, event);
36160
37263
  break;
36161
37264
  case "beforeToolCallEvent":
36162
- startToolSpan2(state, event);
37265
+ startToolSpan3(state, event);
36163
37266
  break;
36164
37267
  case "afterToolCallEvent":
36165
37268
  finalizeToolSpan(state, event);
@@ -36184,7 +37287,7 @@ function handleAgentStreamEvent(state, event) {
36184
37287
  break;
36185
37288
  }
36186
37289
  } catch (error) {
36187
- logInstrumentationError5("Strands Agent SDK event", error);
37290
+ logInstrumentationError6("Strands Agent SDK event", error);
36188
37291
  }
36189
37292
  }
36190
37293
  function handleMultiAgentStreamEvent(state, event, activeChildParents) {
@@ -36220,7 +37323,7 @@ function handleMultiAgentStreamEvent(state, event, activeChildParents) {
36220
37323
  break;
36221
37324
  }
36222
37325
  } catch (error) {
36223
- logInstrumentationError5("Strands Agent SDK multi-agent event", error);
37326
+ logInstrumentationError6("Strands Agent SDK multi-agent event", error);
36224
37327
  }
36225
37328
  }
36226
37329
  function buildModelSpanInput(event, attachmentCache) {
@@ -36299,7 +37402,7 @@ function finalizeModelSpan(state, event) {
36299
37402
  });
36300
37403
  modelState.span.end();
36301
37404
  }
36302
- function startToolSpan2(state, event) {
37405
+ function startToolSpan3(state, event) {
36303
37406
  const toolUse = event.toolUse;
36304
37407
  const key = toolKey2(toolUse);
36305
37408
  if (state.activeTools.has(key)) {
@@ -36579,7 +37682,7 @@ function getModelConfig(model) {
36579
37682
  try {
36580
37683
  return model.getConfig();
36581
37684
  } catch (error) {
36582
- logInstrumentationError5("Strands Agent SDK model config", error);
37685
+ logInstrumentationError6("Strands Agent SDK model config", error);
36583
37686
  return void 0;
36584
37687
  }
36585
37688
  }
@@ -36662,7 +37765,7 @@ function processStrandsInputAttachments(input, cache = createStrandsAttachmentCa
36662
37765
  try {
36663
37766
  return processStrandsInputNode(input, cache);
36664
37767
  } catch (error) {
36665
- logInstrumentationError5("Strands Agent SDK input attachments", error);
37768
+ logInstrumentationError6("Strands Agent SDK input attachments", error);
36666
37769
  return input;
36667
37770
  }
36668
37771
  }
@@ -36882,10 +37985,10 @@ function safeLog5(span, event) {
36882
37985
  try {
36883
37986
  span.log(event);
36884
37987
  } catch (error) {
36885
- logInstrumentationError5("Strands Agent SDK span log", error);
37988
+ logInstrumentationError6("Strands Agent SDK span log", error);
36886
37989
  }
36887
37990
  }
36888
- function logInstrumentationError5(context, error) {
37991
+ function logInstrumentationError6(context, error) {
36889
37992
  debugLogger.debug(`${context}:`, error);
36890
37993
  }
36891
37994
 
@@ -37288,10 +38391,10 @@ function observeAudioStream(value, observe, complete, cancel, span) {
37288
38391
  const getReader = value.getReader;
37289
38392
  value.getReader = function(...args) {
37290
38393
  const reader = Reflect.apply(getReader, this, args);
37291
- const read3 = reader.read;
38394
+ const read4 = reader.read;
37292
38395
  reader.read = function(...readArgs) {
37293
38396
  return Promise.resolve(
37294
- withCurrent(span, () => Reflect.apply(read3, this, readArgs))
38397
+ withCurrent(span, () => Reflect.apply(read4, this, readArgs))
37295
38398
  ).then(
37296
38399
  (result) => {
37297
38400
  if (result.value) safeObserve(result.value);
@@ -37808,14 +38911,14 @@ var CloudflareAIChatPlugin = class extends BasePlugin {
37808
38911
  const result = event.arguments[0];
37809
38912
  state = agent ? this.findResponseState(
37810
38913
  agent,
37811
- stringValue3(ownValue2(result, "requestId"))
38914
+ stringValue4(ownValue2(result, "requestId"))
37812
38915
  ) : void 0;
37813
38916
  if (!state) {
37814
38917
  return;
37815
38918
  }
37816
38919
  state.responseObserved = true;
37817
38920
  const output = serializeMessage(ownValue2(result, "message"));
37818
- const status = stringValue3(ownValue2(result, "status"));
38921
+ const status = stringValue4(ownValue2(result, "status"));
37819
38922
  const error = ownValue2(result, "error");
37820
38923
  const input = ownValue2(result, "continuation") === true ? state.input : serializeMessages(readProperty(agent, "messages"))?.filter(
37821
38924
  (message) => typeof output?.id !== "string" || message.id !== output.id
@@ -37862,7 +38965,7 @@ var CloudflareAIChatPlugin = class extends BasePlugin {
37862
38965
  }
37863
38966
  try {
37864
38967
  const agent = asObject(event.self);
37865
- const requestId = stringValue3(event.arguments[0]);
38968
+ const requestId = stringValue4(event.arguments[0]);
37866
38969
  const key = requestId ?? /* @__PURE__ */ Symbol("cloudflare-ai-chat-turn");
37867
38970
  const activeForAgent = agent ? this.getActiveTurns(agent) : void 0;
37868
38971
  const existing = activeForAgent?.get(key);
@@ -38031,7 +39134,7 @@ function ownValue2(value, key) {
38031
39134
  const descriptor = Object.getOwnPropertyDescriptor(object, key);
38032
39135
  return descriptor && "value" in descriptor ? descriptor.value : void 0;
38033
39136
  }
38034
- function stringValue3(value) {
39137
+ function stringValue4(value) {
38035
39138
  return typeof value === "string" ? value : void 0;
38036
39139
  }
38037
39140
  function serializeMessages(value) {
@@ -38149,7 +39252,7 @@ var CloudflareAgentsPlugin = class extends BasePlugin {
38149
39252
  );
38150
39253
  spans.set(event, span);
38151
39254
  } catch (error) {
38152
- logInstrumentationError6("start", error);
39255
+ logInstrumentationError7("start", error);
38153
39256
  }
38154
39257
  },
38155
39258
  asyncEnd: (event) => {
@@ -38169,7 +39272,7 @@ var CloudflareAgentsPlugin = class extends BasePlugin {
38169
39272
  }
38170
39273
  }
38171
39274
  } catch (error) {
38172
- logInstrumentationError6("completion", error);
39275
+ logInstrumentationError7("completion", error);
38173
39276
  } finally {
38174
39277
  safelyEndSpan(span);
38175
39278
  }
@@ -38183,7 +39286,7 @@ var CloudflareAgentsPlugin = class extends BasePlugin {
38183
39286
  try {
38184
39287
  span.log({ error: event.error });
38185
39288
  } catch (error) {
38186
- logInstrumentationError6("rejection", error);
39289
+ logInstrumentationError7("rejection", error);
38187
39290
  } finally {
38188
39291
  safelyEndSpan(span);
38189
39292
  }
@@ -38213,10 +39316,10 @@ function safelyEndSpan(span) {
38213
39316
  try {
38214
39317
  span.end();
38215
39318
  } catch (error) {
38216
- logInstrumentationError6("span end", error);
39319
+ logInstrumentationError7("span end", error);
38217
39320
  }
38218
39321
  }
38219
- function logInstrumentationError6(operation, error) {
39322
+ function logInstrumentationError7(operation, error) {
38220
39323
  debugLogger.error(
38221
39324
  `Failed to process Cloudflare Agents ${operation} instrumentation:`,
38222
39325
  error
@@ -38241,6 +39344,7 @@ var BraintrustPlugin = class extends BasePlugin {
38241
39344
  openRouterPlugin = null;
38242
39345
  openRouterAgentPlugin = null;
38243
39346
  mistralPlugin = null;
39347
+ langGraphSDKPlugin = null;
38244
39348
  ollamaPlugin = null;
38245
39349
  googleADKPlugin = null;
38246
39350
  coherePlugin = null;
@@ -38321,6 +39425,10 @@ var BraintrustPlugin = class extends BasePlugin {
38321
39425
  this.mistralPlugin = new MistralPlugin();
38322
39426
  this.mistralPlugin.enable();
38323
39427
  }
39428
+ if (integrations.langgraphSDK !== false) {
39429
+ this.langGraphSDKPlugin = new LangGraphSDKPlugin();
39430
+ this.langGraphSDKPlugin.enable();
39431
+ }
38324
39432
  if (integrations.ollama !== false) {
38325
39433
  this.ollamaPlugin = new OllamaPlugin();
38326
39434
  this.ollamaPlugin.enable();
@@ -38449,6 +39557,10 @@ var BraintrustPlugin = class extends BasePlugin {
38449
39557
  this.mistralPlugin.disable();
38450
39558
  this.mistralPlugin = null;
38451
39559
  }
39560
+ if (this.langGraphSDKPlugin) {
39561
+ this.langGraphSDKPlugin.disable();
39562
+ this.langGraphSDKPlugin = null;
39563
+ }
38452
39564
  if (this.ollamaPlugin) {
38453
39565
  this.ollamaPlugin.disable();
38454
39566
  this.ollamaPlugin = null;
@@ -38590,6 +39702,9 @@ var envIntegrationAliases = {
38590
39702
  "langchain-js": "langchain",
38591
39703
  "@langchain": "langchain",
38592
39704
  langgraph: "langgraph",
39705
+ langgraphsdk: "langgraphSDK",
39706
+ "langgraph-sdk": "langgraphSDK",
39707
+ "@langchain/langgraph-sdk": "langgraphSDK",
38593
39708
  langsmith: "langsmith",
38594
39709
  voyage: "voyageai",
38595
39710
  "voyage-ai": "voyageai",
@@ -38630,6 +39745,7 @@ function getDefaultInstrumentationIntegrations() {
38630
39745
  gitHubCopilot: true,
38631
39746
  langchain: true,
38632
39747
  langgraph: true,
39748
+ langgraphSDK: true,
38633
39749
  langsmith: true,
38634
39750
  voyageai: true,
38635
39751
  elevenlabs: true,
@@ -38798,8 +39914,6 @@ __export(exports_exports, {
38798
39914
  BRAINTRUST_PARENT_KEY: () => BRAINTRUST_PARENT_KEY,
38799
39915
  BaseAttachment: () => BaseAttachment,
38800
39916
  BaseExperiment: () => BaseExperiment,
38801
- BatchScorer: () => BatchScorer,
38802
- BatchTask: () => BatchTask,
38803
39917
  BraintrustLangChainCallbackHandler: () => BraintrustLangChainCallbackHandler,
38804
39918
  BraintrustMiddleware: () => BraintrustMiddleware,
38805
39919
  BraintrustObservabilityExporter: () => BraintrustObservabilityExporter,
@@ -38813,8 +39927,6 @@ __export(exports_exports, {
38813
39927
  DEFAULT_MAX_REQUEST_SIZE: () => DEFAULT_MAX_REQUEST_SIZE,
38814
39928
  Dataset: () => Dataset2,
38815
39929
  DatasetPipeline: () => DatasetPipeline,
38816
- DurableEvalMemoryStore: () => DurableEvalMemoryStore,
38817
- DurableEvalRedisStore: () => DurableEvalRedisStore,
38818
39930
  ERR_PERMALINK: () => ERR_PERMALINK,
38819
39931
  Eval: () => Eval,
38820
39932
  EvalResultWithSummary: () => EvalResultWithSummary,
@@ -38849,6 +39961,10 @@ __export(exports_exports, {
38849
39961
  TestBackgroundLogger: () => TestBackgroundLogger,
38850
39962
  ToolBuilder: () => ToolBuilder,
38851
39963
  UUIDGenerator: () => UUIDGenerator,
39964
+ WorkflowEvalMemoryStore: () => WorkflowEvalMemoryStore,
39965
+ WorkflowEvalRedisStore: () => WorkflowEvalRedisStore,
39966
+ WorkflowScorer: () => WorkflowScorer,
39967
+ WorkflowTask: () => WorkflowTask,
38852
39968
  X_CACHED_HEADER: () => X_CACHED_HEADER,
38853
39969
  _exportsForTestingOnly: () => _exportsForTestingOnly,
38854
39970
  _internalGetGlobalState: () => _internalGetGlobalState,
@@ -38873,12 +39989,13 @@ __export(exports_exports, {
38873
39989
  currentSpan: () => currentSpan,
38874
39990
  deepCopyEvent: () => deepCopyEvent,
38875
39991
  defaultErrorScoreHandler: () => defaultErrorScoreHandler,
38876
- defineDurableEval: () => defineDurableEval,
39992
+ defineWorkflowEval: () => defineWorkflowEval,
38877
39993
  deserializePlainStringAsJSON: () => deserializePlainStringAsJSON,
38878
39994
  devNullWritableStream: () => devNullWritableStream,
38879
39995
  evaluatorDefinitionSchema: () => evaluatorDefinitionSchema,
38880
39996
  evaluatorDefinitionsSchema: () => evaluatorDefinitionsSchema,
38881
39997
  extractTraceContextFromHeaders: () => extractTraceContextFromHeaders,
39998
+ failOpenAIAgentsTrace: () => failOpenAIAgentsTrace,
38882
39999
  flush: () => flush,
38883
40000
  getContextManager: () => getContextManager,
38884
40001
  getIdGenerator: () => getIdGenerator,
@@ -38925,12 +40042,14 @@ __export(exports_exports, {
38925
40042
  setFetch: () => setFetch,
38926
40043
  setMaskingFunction: () => setMaskingFunction,
38927
40044
  spanComponentsToObjectId: () => spanComponentsToObjectId,
40045
+ startOpenAIAgentsTrace: () => startOpenAIAgentsTrace,
38928
40046
  startSpan: () => startSpan,
38929
40047
  summarize: () => summarize,
38930
40048
  templateRegistry: () => templateRegistry,
38931
40049
  toolFunctionDefinitionSchema: () => ToolFunctionDefinition,
38932
40050
  traceable: () => traceable,
38933
40051
  traced: () => traced,
40052
+ updateOpenAIAgentsTrace: () => updateOpenAIAgentsTrace,
38934
40053
  updateSpan: () => updateSpan,
38935
40054
  uploadLogs3OverflowPayload: () => uploadLogs3OverflowPayload,
38936
40055
  utf8ByteLength: () => utf8ByteLength2,
@@ -38959,6 +40078,7 @@ __export(exports_exports, {
38959
40078
  wrapGroq: () => wrapGroq,
38960
40079
  wrapHuggingFace: () => wrapHuggingFace,
38961
40080
  wrapHuggingFaceTransformers: () => wrapHuggingFaceTransformers,
40081
+ wrapLangGraphSDK: () => wrapLangGraphSDK,
38962
40082
  wrapLangSmithClient: () => wrapLangSmithClient,
38963
40083
  wrapLangSmithRunTrees: () => wrapLangSmithRunTrees,
38964
40084
  wrapLangSmithTraceable: () => wrapLangSmithTraceable,
@@ -39158,7 +40278,7 @@ function createLazyAPIPromise(ensureExecuted, ensureResponse, getAPIPromise) {
39158
40278
  }
39159
40279
 
39160
40280
  // src/openai-batch.ts
39161
- function read2(value, key) {
40281
+ function read3(value, key) {
39162
40282
  if (value === null || typeof value !== "object" && typeof value !== "function") {
39163
40283
  return void 0;
39164
40284
  }
@@ -39169,7 +40289,7 @@ function read2(value, key) {
39169
40289
  }
39170
40290
  }
39171
40291
  function isAsyncIterable5(value) {
39172
- return typeof read2(value, Symbol.asyncIterator) === "function";
40292
+ return typeof read3(value, Symbol.asyncIterator) === "function";
39173
40293
  }
39174
40294
  function teeAsyncIterable(source) {
39175
40295
  const iterator = source[Symbol.asyncIterator]();
@@ -39212,7 +40332,7 @@ function teeAsyncIterable(source) {
39212
40332
  }
39213
40333
  }
39214
40334
  };
39215
- const path = read2(source, "path");
40335
+ const path = read3(source, "path");
39216
40336
  if (typeof path === "string") {
39217
40337
  Object.defineProperty(upload, "path", { value: path });
39218
40338
  }
@@ -39233,8 +40353,8 @@ function teeUpload(upload) {
39233
40353
  function openaiFilesCreateTraced(files) {
39234
40354
  return (params, options) => {
39235
40355
  const parent = getSpanParentObject();
39236
- const purpose = read2(params, "purpose");
39237
- const file = read2(params, "file");
40356
+ const purpose = read3(params, "purpose");
40357
+ const file = read3(params, "file");
39238
40358
  if (purpose !== "batch") {
39239
40359
  return files.create(params, options);
39240
40360
  }
@@ -39325,6 +40445,143 @@ async function completeOpenAIBatchTrace(args) {
39325
40445
  );
39326
40446
  }
39327
40447
 
40448
+ // src/openai-agents-api.ts
40449
+ function isRecord3(value) {
40450
+ return typeof value === "object" && value !== null && !Array.isArray(value);
40451
+ }
40452
+ function validateStartArgs(value) {
40453
+ if (!isRecord3(value)) {
40454
+ throw new TypeError(
40455
+ "startOpenAIAgentsTrace expected an OpenAI Agents parameters object"
40456
+ );
40457
+ }
40458
+ const agent = value.agent;
40459
+ if (agent !== void 0 && agent !== null && !isRecord3(agent)) {
40460
+ throw new TypeError(
40461
+ "startOpenAIAgentsTrace expected agent to be an object or null"
40462
+ );
40463
+ }
40464
+ 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")) {
40465
+ throw new TypeError(
40466
+ "startOpenAIAgentsTrace received invalid agent identity fields"
40467
+ );
40468
+ }
40469
+ if (value.agent_id !== void 0 && typeof value.agent_id !== "string") {
40470
+ throw new TypeError(
40471
+ "startOpenAIAgentsTrace expected agent_id to be a string"
40472
+ );
40473
+ }
40474
+ if (value.metadata !== void 0 && value.metadata !== null && !isRecord3(value.metadata)) {
40475
+ throw new TypeError(
40476
+ "startOpenAIAgentsTrace expected metadata to be an object or null"
40477
+ );
40478
+ }
40479
+ return value;
40480
+ }
40481
+ function validateEvent(event) {
40482
+ if (!isRecord3(event) || typeof event.type !== "string" || event.type.length === 0) {
40483
+ throw new TypeError(
40484
+ "updateOpenAIAgentsTrace expected an OpenAI Agents event object"
40485
+ );
40486
+ }
40487
+ return event;
40488
+ }
40489
+ function createTraceState() {
40490
+ const parent = _internalExportParentSynchronously(getSpanParentObject());
40491
+ if (!parent) {
40492
+ return null;
40493
+ }
40494
+ const parentComponents = SpanComponentsV4.fromStr(parent);
40495
+ const rowId = newId();
40496
+ const useLegacyIds = resolveUseLegacyUuidIds();
40497
+ const spanId = useLegacyIds ? newId() : newId().replaceAll("-", "").slice(0, 16);
40498
+ const rootSpanId = useLegacyIds ? spanId : newId().replaceAll("-", "");
40499
+ const root = new SpanComponentsV4({
40500
+ object_type: parentComponents.data.object_type,
40501
+ ...parentComponents.data.object_id ? { object_id: parentComponents.data.object_id } : {
40502
+ compute_object_metadata_args: parentComponents.data.compute_object_metadata_args ?? {}
40503
+ },
40504
+ propagated_event: parentComponents.data.propagated_event,
40505
+ root_span_id: rootSpanId,
40506
+ row_id: rowId,
40507
+ span_id: spanId
40508
+ }).toStr();
40509
+ return {
40510
+ callItems: {},
40511
+ ended: false,
40512
+ eventIds: [],
40513
+ openTools: {},
40514
+ root,
40515
+ rootKey: spanId,
40516
+ rootParent: parent,
40517
+ startTime: getCurrentUnixTimestamp(),
40518
+ subagents: {},
40519
+ turnSubagents: {},
40520
+ version: 1
40521
+ };
40522
+ }
40523
+ function startOpenAIAgentsTrace(args) {
40524
+ const validatedArgs = validateStartArgs(args);
40525
+ const state = createTraceState();
40526
+ if (!state) {
40527
+ return null;
40528
+ }
40529
+ try {
40530
+ void openAIChannels.agentsTraceStart.invoke(
40531
+ async () => state,
40532
+ void 0,
40533
+ [{ args: validatedArgs, state }],
40534
+ {}
40535
+ ).catch((error) => {
40536
+ debugLogger.debug(
40537
+ "OpenAI Agents API instrumentation could not start:",
40538
+ error
40539
+ );
40540
+ });
40541
+ } catch (error) {
40542
+ debugLogger.debug(
40543
+ "OpenAI Agents API instrumentation could not start:",
40544
+ error
40545
+ );
40546
+ }
40547
+ return state;
40548
+ }
40549
+ async function updateOpenAIAgentsTrace(token, event) {
40550
+ const state = token;
40551
+ const validatedEvent = validateEvent(event);
40552
+ try {
40553
+ return await openAIChannels.agentsTraceCapture.invoke(
40554
+ async () => state,
40555
+ void 0,
40556
+ [{ state, event: validatedEvent }],
40557
+ {}
40558
+ );
40559
+ } catch (error) {
40560
+ debugLogger.debug(
40561
+ "OpenAI Agents API instrumentation could not update:",
40562
+ error
40563
+ );
40564
+ return token;
40565
+ }
40566
+ }
40567
+ async function failOpenAIAgentsTrace(token, error) {
40568
+ const state = token;
40569
+ try {
40570
+ return await openAIChannels.agentsTraceFail.invoke(
40571
+ async () => state,
40572
+ void 0,
40573
+ [{ state, error }],
40574
+ {}
40575
+ );
40576
+ } catch (instrumentationError) {
40577
+ debugLogger.debug(
40578
+ "OpenAI Agents API instrumentation could not record failure:",
40579
+ instrumentationError
40580
+ );
40581
+ return token;
40582
+ }
40583
+ }
40584
+
39328
40585
  // src/functions/invoke.ts
39329
40586
  async function invoke(args) {
39330
40587
  const {
@@ -40774,7 +42031,31 @@ var MAX_STORED_LLM_INPUTS = 100;
40774
42031
  var MAX_STORED_REASONING_BLOCKS = 100;
40775
42032
  var MAX_STORED_SPAN_REFERENCES = 1e4;
40776
42033
  var MAX_STORED_STEP_STARTS = 1e4;
42034
+ var EVE_HANDLED_EVENT_TYPES = /* @__PURE__ */ new Set([
42035
+ "action.result",
42036
+ "actions.requested",
42037
+ "message.completed",
42038
+ "message.received",
42039
+ "reasoning.completed",
42040
+ "result.completed",
42041
+ "session.completed",
42042
+ "session.failed",
42043
+ "session.started",
42044
+ "step.completed",
42045
+ "step.failed",
42046
+ "step.started",
42047
+ "subagent.called",
42048
+ "subagent.completed",
42049
+ "turn.completed",
42050
+ "turn.failed",
42051
+ "turn.started"
42052
+ ]);
40777
42053
  function braintrustEveHook(options) {
42054
+ if (!options || typeof options.defineState !== "function") {
42055
+ throw new TypeError(
42056
+ "braintrustEveHook requires Eve's defineState function"
42057
+ );
42058
+ }
40778
42059
  const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
40779
42060
  const bridge = new EveBridge(state);
40780
42061
  return {
@@ -40786,15 +42067,27 @@ function braintrustEveHook(options) {
40786
42067
  };
40787
42068
  }
40788
42069
  function createLegacyEveInstrumentation(options) {
42070
+ if (!options || typeof options.defineState !== "function") {
42071
+ throw new TypeError(
42072
+ "braintrustEveInstrumentation requires Eve's defineState function"
42073
+ );
42074
+ }
40789
42075
  const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
40790
42076
  return {
40791
42077
  events: {
40792
42078
  "step.started": (input) => {
40793
42079
  try {
42080
+ if (!isEveInstrumentationStepStartedEventInput(input)) {
42081
+ debugLogger.warn(
42082
+ "Ignoring malformed Eve instrumentation step.started event"
42083
+ );
42084
+ return void 0;
42085
+ }
40794
42086
  captureEveModelInput(state, input);
40795
42087
  } catch (error) {
40796
42088
  debugLogger.warn("Error in Eve LLM input capture:", error);
40797
42089
  }
42090
+ return void 0;
40798
42091
  }
40799
42092
  },
40800
42093
  recordInputs: false,
@@ -40803,7 +42096,77 @@ function createLegacyEveInstrumentation(options) {
40803
42096
  };
40804
42097
  }
40805
42098
  function isEveHandleMessageStreamEvent(event) {
40806
- return isObject(event) && typeof event["type"] === "string";
42099
+ if (!isObject(event) || typeof event["type"] !== "string") {
42100
+ return false;
42101
+ }
42102
+ const type = event["type"];
42103
+ if (type === "session.completed") {
42104
+ return true;
42105
+ }
42106
+ if (!isObject(event["data"])) {
42107
+ return false;
42108
+ }
42109
+ const data = event["data"];
42110
+ if (type === "session.started") {
42111
+ return true;
42112
+ }
42113
+ if (type === "session.failed") {
42114
+ return typeof data["sessionId"] === "string" && typeof data["code"] === "string" && typeof data["message"] === "string";
42115
+ }
42116
+ if (type === "session.waiting") {
42117
+ return data["wait"] === "next-user-message";
42118
+ }
42119
+ if (typeof data["turnId"] !== "string" || typeof data["sequence"] !== "number" || !Number.isFinite(data["sequence"])) {
42120
+ return false;
42121
+ }
42122
+ if (type === "turn.started" || type === "turn.completed" || type === "subagent.called" || type === "subagent.completed") {
42123
+ if (type === "subagent.called") {
42124
+ return typeof data["callId"] === "string" && typeof data["childSessionId"] === "string" && typeof data["name"] === "string";
42125
+ }
42126
+ if (type === "subagent.completed") {
42127
+ return typeof data["callId"] === "string" && typeof data["subagentName"] === "string";
42128
+ }
42129
+ return true;
42130
+ }
42131
+ if (type === "turn.failed") {
42132
+ return typeof data["code"] === "string" && typeof data["message"] === "string";
42133
+ }
42134
+ if (type === "message.received") {
42135
+ return typeof data["message"] === "string";
42136
+ }
42137
+ if (typeof data["stepIndex"] !== "number" || !Number.isFinite(data["stepIndex"]) || data["stepIndex"] < 0) {
42138
+ return false;
42139
+ }
42140
+ switch (type) {
42141
+ case "step.started":
42142
+ return true;
42143
+ case "message.completed":
42144
+ return typeof data["finishReason"] === "string" && (typeof data["message"] === "string" || data["message"] === null);
42145
+ case "reasoning.completed":
42146
+ return typeof data["reasoning"] === "string";
42147
+ case "result.completed":
42148
+ return true;
42149
+ case "step.completed":
42150
+ return typeof data["finishReason"] === "string";
42151
+ case "step.failed":
42152
+ return typeof data["code"] === "string" && typeof data["message"] === "string";
42153
+ case "actions.requested":
42154
+ return Array.isArray(data["actions"]);
42155
+ case "action.result":
42156
+ return isObject(data["result"]) && (data["status"] === "completed" || data["status"] === "failed" || data["status"] === "rejected");
42157
+ default:
42158
+ return false;
42159
+ }
42160
+ }
42161
+ function isEveInstrumentationStepStartedEventInput(input) {
42162
+ if (!isObject(input)) {
42163
+ return false;
42164
+ }
42165
+ const modelInput = input["modelInput"];
42166
+ const session = input["session"];
42167
+ const step = input["step"];
42168
+ const turn = input["turn"];
42169
+ 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"]);
40807
42170
  }
40808
42171
  var ResumedEveSpan = class {
40809
42172
  constructor(reference) {
@@ -40972,7 +42335,17 @@ var EveBridge = class {
40972
42335
  });
40973
42336
  }
40974
42337
  async handle(event, ctx, hookMetadata) {
42338
+ try {
42339
+ await this.handleUnchecked(event, ctx, hookMetadata);
42340
+ } catch (error) {
42341
+ debugLogger.warn("Error in Eve hook instrumentation:", error);
42342
+ }
42343
+ }
42344
+ async handleUnchecked(event, ctx, hookMetadata) {
40975
42345
  if (!isEveHandleMessageStreamEvent(event)) {
42346
+ if (isObject(event) && typeof event["type"] === "string" && EVE_HANDLED_EVENT_TYPES.has(event["type"])) {
42347
+ debugLogger.warn(`Ignoring malformed Eve hook ${event["type"]} event`);
42348
+ }
40976
42349
  return;
40977
42350
  }
40978
42351
  const run = async () => {
@@ -41298,9 +42671,14 @@ var EveBridge = class {
41298
42671
  }
41299
42672
  for (const action of traceActions) {
41300
42673
  const name = action.kind === "tool-call" ? action.toolName : action.subagentName ?? action.name ?? "agent";
42674
+ let args = "null";
42675
+ try {
42676
+ args = JSON.stringify(action.input) ?? "null";
42677
+ } catch {
42678
+ }
41301
42679
  toolCallsById.set(action.callId, {
41302
42680
  function: {
41303
- arguments: JSON.stringify(action.input),
42681
+ arguments: args,
41304
42682
  name
41305
42683
  },
41306
42684
  id: action.callId,
@@ -42169,17 +43547,33 @@ function consumeCapturedEveModelInput(state, sessionId, turnId, stepIndex) {
42169
43547
  }
42170
43548
  }
42171
43549
  function capturedModelInput(modelInput) {
42172
- const { instructions, messages } = modelInput;
42173
- const value = [];
42174
- if (typeof instructions === "string") {
42175
- value.push({ content: instructions, role: "system" });
42176
- } else if (Array.isArray(instructions)) {
42177
- value.push(...instructions.map(capturedEveModelMessage));
42178
- } else if (instructions) {
42179
- value.push(capturedEveModelMessage(instructions));
42180
- }
42181
- value.push(...messages.map(capturedEveModelMessage));
42182
43550
  try {
43551
+ if (!isObject(modelInput) || !Array.isArray(modelInput["messages"])) {
43552
+ return void 0;
43553
+ }
43554
+ const value = [];
43555
+ const instructions = modelInput["instructions"];
43556
+ if (typeof instructions === "string") {
43557
+ value.push({ content: instructions, role: "system" });
43558
+ } else if (Array.isArray(instructions)) {
43559
+ for (const instruction of instructions) {
43560
+ const captured = capturedEveModelMessage(instruction);
43561
+ if (captured?.role === "system") {
43562
+ value.push(captured);
43563
+ }
43564
+ }
43565
+ } else {
43566
+ const captured = capturedEveModelMessage(instructions);
43567
+ if (captured?.role === "system") {
43568
+ value.push(captured);
43569
+ }
43570
+ }
43571
+ for (const message of modelInput["messages"]) {
43572
+ const captured = capturedEveModelMessage(message);
43573
+ if (captured) {
43574
+ value.push(captured);
43575
+ }
43576
+ }
42183
43577
  const cloned = JSON.parse(JSON.stringify(value));
42184
43578
  if (!Array.isArray(cloned)) {
42185
43579
  return void 0;
@@ -42190,116 +43584,202 @@ function capturedModelInput(modelInput) {
42190
43584
  }
42191
43585
  }
42192
43586
  function capturedEveModelMessage(message) {
42193
- const { content, role } = message;
43587
+ if (!isObject(message)) {
43588
+ return void 0;
43589
+ }
43590
+ const role = message["role"];
43591
+ if (role !== "system" && role !== "user" && role !== "assistant" && role !== "tool") {
43592
+ return void 0;
43593
+ }
43594
+ const content = message["content"];
42194
43595
  if (typeof content === "string") {
42195
43596
  return { content, role };
42196
43597
  }
42197
- return { content: content.map(capturedEveModelContentPart), role };
43598
+ if (!Array.isArray(content)) {
43599
+ return void 0;
43600
+ }
43601
+ const capturedContent = [];
43602
+ for (const part of content) {
43603
+ const captured = capturedEveModelContentPart(part);
43604
+ if (captured) {
43605
+ capturedContent.push(captured);
43606
+ }
43607
+ }
43608
+ return { content: capturedContent, role };
42198
43609
  }
42199
43610
  function capturedEveModelContentPart(part) {
42200
- switch (part.type) {
43611
+ if (!isObject(part) || typeof part["type"] !== "string") {
43612
+ return void 0;
43613
+ }
43614
+ switch (part["type"]) {
42201
43615
  case "text":
42202
- case "reasoning":
42203
- return { text: part.text, type: part.type };
43616
+ case "reasoning": {
43617
+ const text = part["text"];
43618
+ return typeof text === "string" ? { text, type: part["type"] } : void 0;
43619
+ }
42204
43620
  case "image":
43621
+ if (!Object.hasOwn(part, "image")) {
43622
+ return void 0;
43623
+ }
42205
43624
  return {
42206
- image: part.image,
42207
- ...part.mediaType !== void 0 ? { mediaType: part.mediaType } : {},
43625
+ image: part["image"],
43626
+ ...typeof part["mediaType"] === "string" ? { mediaType: part["mediaType"] } : {},
42208
43627
  type: "image"
42209
43628
  };
42210
43629
  case "file":
42211
- case "reasoning-file":
43630
+ case "reasoning-file": {
43631
+ if (!Object.hasOwn(part, "data") || typeof part["mediaType"] !== "string") {
43632
+ return void 0;
43633
+ }
42212
43634
  return {
42213
- data: part.data,
42214
- ...part.type === "file" && part.filename !== void 0 ? { filename: part.filename } : {},
42215
- mediaType: part.mediaType,
42216
- type: part.type
43635
+ data: part["data"],
43636
+ ...part["type"] === "file" && typeof part["filename"] === "string" ? { filename: part["filename"] } : {},
43637
+ mediaType: part["mediaType"],
43638
+ type: part["type"]
42217
43639
  };
43640
+ }
42218
43641
  case "custom":
42219
43642
  return {
42220
- ..."kind" in part ? { kind: part.kind } : {},
43643
+ ...typeof part["kind"] === "string" ? { kind: part["kind"] } : {},
42221
43644
  type: "custom"
42222
43645
  };
42223
- case "tool-call":
43646
+ case "tool-call": {
43647
+ if (typeof part["toolCallId"] !== "string" || typeof part["toolName"] !== "string") {
43648
+ return void 0;
43649
+ }
42224
43650
  return {
42225
- input: part.input,
42226
- ...part.providerExecuted !== void 0 ? { providerExecuted: part.providerExecuted } : {},
42227
- toolCallId: part.toolCallId,
42228
- toolName: part.toolName,
43651
+ input: part["input"],
43652
+ ...typeof part["providerExecuted"] === "boolean" ? { providerExecuted: part["providerExecuted"] } : {},
43653
+ toolCallId: part["toolCallId"],
43654
+ toolName: part["toolName"],
42229
43655
  type: "tool-call"
42230
43656
  };
43657
+ }
42231
43658
  case "tool-result": {
42232
- const output = part.output;
43659
+ const output = part["output"];
43660
+ if (typeof part["toolCallId"] !== "string" || typeof part["toolName"] !== "string" || !isObject(output) || typeof output["type"] !== "string") {
43661
+ return void 0;
43662
+ }
42233
43663
  let capturedOutput;
42234
- switch (output.type) {
43664
+ switch (output["type"]) {
42235
43665
  case "text":
42236
- case "error-text":
42237
- capturedOutput = { type: output.type, value: output.value };
43666
+ case "error-text": {
43667
+ if (typeof output["value"] !== "string") {
43668
+ return void 0;
43669
+ }
43670
+ capturedOutput = {
43671
+ type: output["type"],
43672
+ value: output["value"]
43673
+ };
42238
43674
  break;
43675
+ }
42239
43676
  case "json":
42240
43677
  case "error-json":
42241
- capturedOutput = { type: output.type, value: output.value };
43678
+ capturedOutput = {
43679
+ type: output["type"],
43680
+ value: output["value"]
43681
+ };
42242
43682
  break;
42243
43683
  case "execution-denied":
42244
43684
  capturedOutput = {
42245
- ...output.reason !== void 0 ? { reason: output.reason } : {},
43685
+ ...typeof output["reason"] === "string" ? { reason: output["reason"] } : {},
42246
43686
  type: "execution-denied"
42247
43687
  };
42248
43688
  break;
42249
- case "content":
43689
+ case "content": {
43690
+ if (!Array.isArray(output["value"])) {
43691
+ return void 0;
43692
+ }
43693
+ const value = [];
43694
+ for (const outputPart of output["value"]) {
43695
+ const captured = capturedEveModelContentPart(outputPart);
43696
+ if (captured) {
43697
+ value.push(captured);
43698
+ }
43699
+ }
42250
43700
  capturedOutput = {
42251
43701
  type: "content",
42252
- value: output.value.map(capturedEveModelContentPart)
43702
+ value
42253
43703
  };
42254
43704
  break;
43705
+ }
43706
+ default:
43707
+ return void 0;
42255
43708
  }
42256
43709
  return {
42257
43710
  output: capturedOutput,
42258
- toolCallId: part.toolCallId,
42259
- toolName: part.toolName,
43711
+ toolCallId: part["toolCallId"],
43712
+ toolName: part["toolName"],
42260
43713
  type: "tool-result"
42261
43714
  };
42262
43715
  }
42263
- case "tool-approval-request":
43716
+ case "tool-approval-request": {
43717
+ if (typeof part["approvalId"] !== "string" || typeof part["toolCallId"] !== "string") {
43718
+ return void 0;
43719
+ }
42264
43720
  return {
42265
- approvalId: part.approvalId,
42266
- ...part.isAutomatic !== void 0 ? { isAutomatic: part.isAutomatic } : {},
42267
- ...part.signature !== void 0 ? { signature: part.signature } : {},
42268
- toolCallId: part.toolCallId,
43721
+ approvalId: part["approvalId"],
43722
+ ...typeof part["isAutomatic"] === "boolean" ? { isAutomatic: part["isAutomatic"] } : {},
43723
+ ...typeof part["signature"] === "string" ? { signature: part["signature"] } : {},
43724
+ toolCallId: part["toolCallId"],
42269
43725
  type: "tool-approval-request"
42270
43726
  };
42271
- case "tool-approval-response":
43727
+ }
43728
+ case "tool-approval-response": {
43729
+ if (typeof part["approvalId"] !== "string" || typeof part["approved"] !== "boolean") {
43730
+ return void 0;
43731
+ }
42272
43732
  return {
42273
- approvalId: part.approvalId,
42274
- approved: part.approved,
42275
- ...part.providerExecuted !== void 0 ? { providerExecuted: part.providerExecuted } : {},
42276
- ...part.reason !== void 0 ? { reason: part.reason } : {},
43733
+ approvalId: part["approvalId"],
43734
+ approved: part["approved"],
43735
+ ...typeof part["providerExecuted"] === "boolean" ? { providerExecuted: part["providerExecuted"] } : {},
43736
+ ...typeof part["reason"] === "string" ? { reason: part["reason"] } : {},
42277
43737
  type: "tool-approval-response"
42278
43738
  };
43739
+ }
42279
43740
  case "file-data":
42280
- case "image-data":
43741
+ case "image-data": {
43742
+ if (typeof part["data"] !== "string" || typeof part["mediaType"] !== "string") {
43743
+ return void 0;
43744
+ }
42281
43745
  return {
42282
- data: part.data,
42283
- ...part.type === "file-data" && part.filename !== void 0 ? { filename: part.filename } : {},
42284
- mediaType: part.mediaType,
42285
- type: part.type
43746
+ data: part["data"],
43747
+ ...part["type"] === "file-data" && typeof part["filename"] === "string" ? { filename: part["filename"] } : {},
43748
+ mediaType: part["mediaType"],
43749
+ type: part["type"]
42286
43750
  };
43751
+ }
42287
43752
  case "file-url":
42288
- case "image-url":
43753
+ case "image-url": {
43754
+ if (typeof part["url"] !== "string") {
43755
+ return void 0;
43756
+ }
42289
43757
  return {
42290
- ...part.type === "file-url" && part.mediaType !== void 0 ? { mediaType: part.mediaType } : {},
42291
- type: part.type,
42292
- url: part.url
43758
+ ...part["type"] === "file-url" && typeof part["mediaType"] === "string" ? { mediaType: part["mediaType"] } : {},
43759
+ type: part["type"],
43760
+ url: part["url"]
42293
43761
  };
43762
+ }
42294
43763
  case "file-id":
42295
- case "image-file-id":
42296
- return { fileId: part.fileId, type: part.type };
43764
+ case "image-file-id": {
43765
+ const fileId = part["fileId"];
43766
+ if (typeof fileId !== "string" && !isObject(fileId)) {
43767
+ return void 0;
43768
+ }
43769
+ return { fileId, type: part["type"] };
43770
+ }
42297
43771
  case "file-reference":
42298
- case "image-file-reference":
43772
+ case "image-file-reference": {
43773
+ if (!isObject(part["providerReference"])) {
43774
+ return void 0;
43775
+ }
42299
43776
  return {
42300
- providerReference: part.providerReference,
42301
- type: part.type
43777
+ providerReference: part["providerReference"],
43778
+ type: part["type"]
42302
43779
  };
43780
+ }
43781
+ default:
43782
+ return void 0;
42303
43783
  }
42304
43784
  }
42305
43785
  function isCapturedModelInput(input) {
@@ -42435,18 +43915,54 @@ function createEveInstrumentationProvider(options = {}) {
42435
43915
  recordOutputs: true
42436
43916
  }),
42437
43917
  events: {
42438
- "action.completed": (event, context) => bridge.handleActionTerminal(event, context),
42439
- "action.failed": (event, context) => bridge.handleActionTerminal(event, context),
42440
- "action.started": (event, context) => bridge.handleActionStarted(event, context),
42441
- "model.call.completed": (event, context) => bridge.handleModelTerminal(event, context),
42442
- "model.call.failed": (event, context) => bridge.handleModelTerminal(event, context),
42443
- "model.call.started": (event, context) => bridge.handleModelStarted(event, context),
42444
- "step.attempt.completed": (event) => bridge.handleStepAttemptTerminal(event),
42445
- "step.attempt.failed": (event) => bridge.handleStepAttemptTerminal(event),
42446
- "turn.cancelled": (event, context) => bridge.handleTurnTerminal(event, context),
42447
- "turn.completed": (event, context) => bridge.handleTurnTerminal(event, context),
42448
- "turn.failed": (event, context) => bridge.handleTurnTerminal(event, context),
42449
- "turn.started": (event, context) => bridge.handleTurnStarted(event, context)
43918
+ "action.completed": providerHandler(
43919
+ "action.completed",
43920
+ bridge.handleActionTerminal.bind(bridge)
43921
+ ),
43922
+ "action.failed": providerHandler(
43923
+ "action.failed",
43924
+ bridge.handleActionTerminal.bind(bridge)
43925
+ ),
43926
+ "action.started": providerHandler(
43927
+ "action.started",
43928
+ bridge.handleActionStarted.bind(bridge)
43929
+ ),
43930
+ "model.call.completed": providerHandler(
43931
+ "model.call.completed",
43932
+ bridge.handleModelTerminal.bind(bridge)
43933
+ ),
43934
+ "model.call.failed": providerHandler(
43935
+ "model.call.failed",
43936
+ bridge.handleModelTerminal.bind(bridge)
43937
+ ),
43938
+ "model.call.started": providerHandler(
43939
+ "model.call.started",
43940
+ bridge.handleModelStarted.bind(bridge)
43941
+ ),
43942
+ "step.attempt.completed": providerHandler(
43943
+ "step.attempt.completed",
43944
+ (event) => bridge.handleStepAttemptTerminal(event)
43945
+ ),
43946
+ "step.attempt.failed": providerHandler(
43947
+ "step.attempt.failed",
43948
+ (event) => bridge.handleStepAttemptTerminal(event)
43949
+ ),
43950
+ "turn.cancelled": providerHandler(
43951
+ "turn.cancelled",
43952
+ bridge.handleTurnTerminal.bind(bridge)
43953
+ ),
43954
+ "turn.completed": providerHandler(
43955
+ "turn.completed",
43956
+ bridge.handleTurnTerminal.bind(bridge)
43957
+ ),
43958
+ "turn.failed": providerHandler(
43959
+ "turn.failed",
43960
+ bridge.handleTurnTerminal.bind(bridge)
43961
+ ),
43962
+ "turn.started": providerHandler(
43963
+ "turn.started",
43964
+ bridge.handleTurnStarted.bind(bridge)
43965
+ )
42450
43966
  },
42451
43967
  flush,
42452
43968
  setup: options.setup
@@ -42802,17 +44318,20 @@ function modelOutput(event) {
42802
44318
  const reasoning = [];
42803
44319
  const toolCalls2 = [];
42804
44320
  for (const part of content) {
42805
- if (part.type === "text") {
42806
- text += part.text;
42807
- } else if (part.type === "reasoning" && part.text.trim().length > 0) {
42808
- reasoning.push({ content: part.text });
42809
- } else if (part.type === "tool-call") {
44321
+ if (!isObject(part)) {
44322
+ continue;
44323
+ }
44324
+ if (part["type"] === "text" && typeof part["text"] === "string") {
44325
+ text += part["text"];
44326
+ } else if (part["type"] === "reasoning" && typeof part["text"] === "string" && part["text"].trim().length > 0) {
44327
+ reasoning.push({ content: part["text"] });
44328
+ } else if (part["type"] === "tool-call" && typeof part["toolName"] === "string" && typeof part["callId"] === "string") {
42810
44329
  toolCalls2.push({
42811
44330
  function: {
42812
- arguments: safeJsonStringify(part.input),
42813
- name: part.toolName
44331
+ arguments: safeJsonStringify(part["input"]),
44332
+ name: part["toolName"]
42814
44333
  },
42815
- id: part.callId,
44334
+ id: part["callId"],
42816
44335
  type: "function"
42817
44336
  });
42818
44337
  }
@@ -42831,13 +44350,13 @@ function modelOutput(event) {
42831
44350
  ];
42832
44351
  }
42833
44352
  function usageMetrics(usage) {
42834
- const promptTokens = nonNegativeNumber(usage.inputTokens);
42835
- const completionTokens = nonNegativeNumber(usage.outputTokens);
44353
+ const promptTokens = nonNegativeNumber(usage?.inputTokens);
44354
+ const completionTokens = nonNegativeNumber(usage?.outputTokens);
42836
44355
  const cachedTokens = nonNegativeNumber(
42837
- usage.inputTokenDetails?.cacheReadTokens
44356
+ usage?.inputTokenDetails?.cacheReadTokens
42838
44357
  );
42839
44358
  const cacheCreationTokens = nonNegativeNumber(
42840
- usage.inputTokenDetails?.cacheWriteTokens
44359
+ usage?.inputTokenDetails?.cacheWriteTokens
42841
44360
  );
42842
44361
  return {
42843
44362
  ...promptTokens !== void 0 ? { prompt_tokens: promptTokens } : {},
@@ -42874,10 +44393,76 @@ function turnIdempotencyKey(sessionId, turnId) {
42874
44393
  function actionIdempotencyKey(sessionId, turnId, callId) {
42875
44394
  return `action:${sessionId}:${turnId}:${callId}`;
42876
44395
  }
44396
+ function providerHandler(type, handler) {
44397
+ return async (event, context) => {
44398
+ try {
44399
+ if (!isEveProviderEvent(event, type) || !isEveProviderContext(context)) {
44400
+ debugLogger.warn(`Ignoring malformed Eve provider ${type} event`);
44401
+ return;
44402
+ }
44403
+ await handler(event, context);
44404
+ } catch (error) {
44405
+ debugLogger.warn(`Error in Eve provider ${type}:`, error);
44406
+ }
44407
+ };
44408
+ }
44409
+ function isEveProviderEvent(event, type) {
44410
+ if (!isObject(event) || event["type"] !== type || typeof event["idempotencyKey"] !== "string" || event["idempotencyKey"].length === 0) {
44411
+ return false;
44412
+ }
44413
+ if (type === "turn.started") {
44414
+ const parentLineage = event["parentLineage"];
44415
+ 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));
44416
+ }
44417
+ if (type === "turn.cancelled" || type === "turn.completed" || type === "turn.failed") {
44418
+ return typeof event["sessionId"] === "string" && typeof event["turnId"] === "string";
44419
+ }
44420
+ if (!isEveProviderScope(event["scope"])) {
44421
+ return false;
44422
+ }
44423
+ if (type === "model.call.started") {
44424
+ const model = event["model"];
44425
+ return isObject(model) && typeof model["modelId"] === "string" && typeof model["provider"] === "string";
44426
+ }
44427
+ if (type === "model.call.completed") {
44428
+ return typeof event["finishReason"] === "string" && isObject(event["usage"]) && (event["content"] === void 0 || Array.isArray(event["content"]));
44429
+ }
44430
+ if (type === "model.call.failed") {
44431
+ return true;
44432
+ }
44433
+ if (type === "action.started") {
44434
+ 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");
44435
+ }
44436
+ if (type === "action.completed") {
44437
+ const output = event["output"];
44438
+ return event["outcome"] === "completed" && isObject(output) && (output["type"] === "result" || output["type"] === "error");
44439
+ }
44440
+ if (type === "action.failed") {
44441
+ return event["outcome"] === "abandoned" || event["outcome"] === "cancelled" || event["outcome"] === "failed" || event["outcome"] === "rejected";
44442
+ }
44443
+ return type === "step.attempt.completed" || type === "step.attempt.failed";
44444
+ }
44445
+ function isEveProviderContext(value) {
44446
+ if (!isObject(value) || !isObject(value["state"])) {
44447
+ return false;
44448
+ }
44449
+ return typeof value["state"]["get"] === "function" && typeof value["state"]["set"] === "function";
44450
+ }
44451
+ function isEveProviderScope(value) {
44452
+ 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");
44453
+ }
44454
+ function isEveProviderParentLineage(value) {
44455
+ return isObject(value) && typeof value["callId"] === "string" && typeof value["sessionId"] === "string" && typeof value["turnId"] === "string";
44456
+ }
42877
44457
 
42878
44458
  // src/instrumentation/plugins/eve-instrumentation.ts
42879
44459
  var EVE_INSTRUMENTATION_PROVIDER = /* @__PURE__ */ Symbol.for("eve.instrumentation.provider");
42880
44460
  function braintrustEveInstrumentation(options) {
44461
+ if (!options || typeof options !== "object") {
44462
+ throw new TypeError(
44463
+ "braintrustEveInstrumentation requires an options object"
44464
+ );
44465
+ }
42881
44466
  const definition = "defineState" in options ? createLegacyEveInstrumentation(options) : createEveInstrumentationProvider(options);
42882
44467
  const declaration = {
42883
44468
  ...definition,
@@ -44114,6 +45699,7 @@ function wrapClient(client) {
44114
45699
  }
44115
45700
 
44116
45701
  // src/wrappers/google-genai.ts
45702
+ var patchedHttpResponses = /* @__PURE__ */ new WeakSet();
44117
45703
  function wrapGoogleGenAI(googleGenAI) {
44118
45704
  if (!googleGenAI || typeof googleGenAI !== "object") {
44119
45705
  console.warn("Invalid Google GenAI module. Not wrapping.");
@@ -44125,6 +45711,21 @@ function wrapGoogleGenAI(googleGenAI) {
44125
45711
  );
44126
45712
  return googleGenAI;
44127
45713
  }
45714
+ const httpResponse = googleGenAI.HttpResponse;
45715
+ if (typeof httpResponse === "function" && isObject(httpResponse.prototype) && typeof httpResponse.prototype.json === "function" && !patchedHttpResponses.has(httpResponse.prototype)) {
45716
+ const prototype = httpResponse.prototype;
45717
+ const originalJson = prototype.json;
45718
+ if (Reflect.set(prototype, "json", function() {
45719
+ return googleGenAIChannels.httpResponseJson.invoke(
45720
+ originalJson,
45721
+ this,
45722
+ [],
45723
+ {}
45724
+ );
45725
+ })) {
45726
+ patchedHttpResponses.add(prototype);
45727
+ }
45728
+ }
44128
45729
  return new Proxy(googleGenAI, {
44129
45730
  get(target, prop, receiver) {
44130
45731
  if (prop === "GoogleGenAI") {
@@ -44375,17 +45976,17 @@ function wrapGenkit(genkit) {
44375
45976
  console.warn("Unsupported Genkit object. Not wrapping.");
44376
45977
  return genkit;
44377
45978
  }
44378
- function isRecord3(value) {
45979
+ function isRecord4(value) {
44379
45980
  return typeof value === "object" && value !== null;
44380
45981
  }
44381
45982
  function isPropertyBag(value) {
44382
- return isRecord3(value) || typeof value === "function";
45983
+ return isRecord4(value) || typeof value === "function";
44383
45984
  }
44384
45985
  function hasFunction(value, methodName) {
44385
45986
  return isPropertyBag(value) && methodName in value && typeof value[methodName] === "function";
44386
45987
  }
44387
45988
  function isGenkitInstance(value) {
44388
- return isRecord3(value) && (hasFunction(value, "generate") || hasFunction(value, "generateStream") || hasFunction(value, "defineFlow") || hasFunction(value, "defineTool"));
45989
+ return isRecord4(value) && (hasFunction(value, "generate") || hasFunction(value, "generateStream") || hasFunction(value, "defineFlow") || hasFunction(value, "defineTool"));
44389
45990
  }
44390
45991
  function isGenkitModule(value) {
44391
45992
  return hasFunction(value, "genkit");
@@ -44439,7 +46040,7 @@ function patchGenkitRegistry(instance) {
44439
46040
  patchGenkitRegistryConstructor(registry2);
44440
46041
  }
44441
46042
  function patchGenkitRegistryLookup(registry2) {
44442
- if (!isRecord3(registry2) || hasRegistryPatchedFlag(registry2) || !hasFunction(registry2, "lookupAction")) {
46043
+ if (!isRecord4(registry2) || hasRegistryPatchedFlag(registry2) || !hasFunction(registry2, "lookupAction")) {
44443
46044
  return;
44444
46045
  }
44445
46046
  const originalLookupAction = registry2.lookupAction;
@@ -44465,7 +46066,7 @@ function patchGenkitRegistryLookup(registry2) {
44465
46066
  }
44466
46067
  }
44467
46068
  function patchGenkitRegistryConstructor(registry2) {
44468
- if (!isRecord3(registry2)) {
46069
+ if (!isRecord4(registry2)) {
44469
46070
  return;
44470
46071
  }
44471
46072
  const constructor = registry2.constructor;
@@ -44481,7 +46082,7 @@ function patchGenkitRegistryConstructor(registry2) {
44481
46082
  configurable: true,
44482
46083
  value: (...args) => {
44483
46084
  const childRegistry = originalWithParent.apply(constructor, args);
44484
- if (args.some((arg) => isRecord3(arg) && hasRegistryPatchedFlag(arg))) {
46085
+ if (args.some((arg) => isRecord4(arg) && hasRegistryPatchedFlag(arg))) {
44485
46086
  patchGenkitRegistryLookup(childRegistry);
44486
46087
  patchGenkitRegistryConstructor(childRegistry);
44487
46088
  }
@@ -44580,7 +46181,7 @@ function hasRegistryConstructorPatchedFlag(value) {
44580
46181
  );
44581
46182
  }
44582
46183
  function isPromiseLike2(value) {
44583
- return isRecord3(value) && "then" in value && typeof value.then === "function";
46184
+ return isRecord4(value) && "then" in value && typeof value.then === "function";
44584
46185
  }
44585
46186
 
44586
46187
  // src/wrappers/huggingface.ts
@@ -45057,14 +46658,14 @@ function wrapMistral(mistral) {
45057
46658
  console.warn("Unsupported Mistral library. Not wrapping.");
45058
46659
  return mistral;
45059
46660
  }
45060
- function isRecord4(value) {
46661
+ function isRecord5(value) {
45061
46662
  return typeof value === "object" && value !== null;
45062
46663
  }
45063
46664
  function hasFunction3(value, methodName) {
45064
- return isRecord4(value) && methodName in value && typeof value[methodName] === "function";
46665
+ return isRecord5(value) && methodName in value && typeof value[methodName] === "function";
45065
46666
  }
45066
46667
  function isSupportedMistralClient(value) {
45067
- if (!isRecord4(value)) {
46668
+ if (!isRecord5(value)) {
45068
46669
  return false;
45069
46670
  }
45070
46671
  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);
@@ -45239,6 +46840,42 @@ function wrapAgentsStream(stream) {
45239
46840
  });
45240
46841
  }
45241
46842
 
46843
+ // src/wrappers/langgraph-sdk.ts
46844
+ var clients = /* @__PURE__ */ new WeakMap();
46845
+ function wrapLangGraphSDK(client) {
46846
+ const runsClient = isObject(client) ? client.runs : void 0;
46847
+ if (!isObject(client) || !isObject(runsClient) || !["wait", "stream"].every((key) => typeof runsClient[key] === "function")) {
46848
+ debugLogger.warn("Unsupported LangGraph SDK client. Not wrapping.");
46849
+ return client;
46850
+ }
46851
+ const sdk = client;
46852
+ const cached = clients.get(sdk);
46853
+ if (cached) return cached;
46854
+ const runs = new Proxy(sdk.runs, {
46855
+ get(target, key) {
46856
+ switch (key) {
46857
+ case "wait":
46858
+ return (...args) => langGraphSDKChannels.wait.invoke(target.wait, target, args, {});
46859
+ case "stream":
46860
+ return (...args) => langGraphSDKChannels.stream.invoke(target.stream, target, args, {});
46861
+ default:
46862
+ const value = Reflect.get(target, key, target);
46863
+ return typeof value === "function" ? value.bind(target) : value;
46864
+ }
46865
+ }
46866
+ });
46867
+ const wrapped = new Proxy(sdk, {
46868
+ get(target, key) {
46869
+ if (key === "runs") return runs;
46870
+ const value = Reflect.get(target, key, target);
46871
+ return typeof value === "function" ? value.bind(target) : value;
46872
+ }
46873
+ });
46874
+ clients.set(sdk, wrapped);
46875
+ clients.set(wrapped, wrapped);
46876
+ return wrapped;
46877
+ }
46878
+
45242
46879
  // src/wrappers/ollama.ts
45243
46880
  function wrapOllama(ollama) {
45244
46881
  if (isSupportedOllamaClient(ollama)) {
@@ -45325,14 +46962,14 @@ function wrapCohere(cohere) {
45325
46962
  return cohere;
45326
46963
  }
45327
46964
  var cohereProxyCache = /* @__PURE__ */ new WeakMap();
45328
- function isRecord5(value) {
46965
+ function isRecord6(value) {
45329
46966
  return typeof value === "object" && value !== null;
45330
46967
  }
45331
46968
  function hasFunction4(value, methodName) {
45332
- return isRecord5(value) && methodName in value && typeof value[methodName] === "function";
46969
+ return isRecord6(value) && methodName in value && typeof value[methodName] === "function";
45333
46970
  }
45334
46971
  function isSupportedCohereClient(value) {
45335
- if (!isRecord5(value)) {
46972
+ if (!isRecord6(value)) {
45336
46973
  return false;
45337
46974
  }
45338
46975
  return hasFunction4(value, "chat") || hasFunction4(value, "chatStream") || hasFunction4(value, "embed") || hasFunction4(value, "rerank");
@@ -45470,20 +47107,20 @@ function wrapGroq(groq) {
45470
47107
  console.warn("Unsupported Groq library. Not wrapping.");
45471
47108
  return groq;
45472
47109
  }
45473
- function isRecord6(value) {
47110
+ function isRecord7(value) {
45474
47111
  return typeof value === "object" && value !== null;
45475
47112
  }
45476
47113
  function hasFunction6(value, methodName) {
45477
- return isRecord6(value) && methodName in value && typeof value[methodName] === "function";
47114
+ return isRecord7(value) && methodName in value && typeof value[methodName] === "function";
45478
47115
  }
45479
47116
  function hasChat2(value) {
45480
- return isRecord6(value) && isRecord6(value.completions) && hasFunction6(value.completions, "create");
47117
+ return isRecord7(value) && isRecord7(value.completions) && hasFunction6(value.completions, "create");
45481
47118
  }
45482
47119
  function hasEmbeddings2(value) {
45483
47120
  return hasFunction6(value, "create");
45484
47121
  }
45485
47122
  function isSupportedGroqClient(value) {
45486
- return isRecord6(value) && (value.chat !== void 0 && hasChat2(value.chat) || value.embeddings !== void 0 && hasEmbeddings2(value.embeddings));
47123
+ return isRecord7(value) && (value.chat !== void 0 && hasChat2(value.chat) || value.embeddings !== void 0 && hasEmbeddings2(value.embeddings));
45487
47124
  }
45488
47125
  function groqProxy(groq) {
45489
47126
  const privateMethodWorkaroundCache = /* @__PURE__ */ new WeakMap();
@@ -45566,11 +47203,11 @@ var BEDROCK_RUNTIME_OPERATION_METHODS = /* @__PURE__ */ new Set([
45566
47203
  "invokeModelWithBidirectionalStream",
45567
47204
  "invokeModelWithResponseStream"
45568
47205
  ]);
45569
- function isRecord7(value) {
47206
+ function isRecord8(value) {
45570
47207
  return typeof value === "object" && value !== null;
45571
47208
  }
45572
47209
  function isSupportedBedrockRuntimeClient(value) {
45573
- return isRecord7(value) && typeof value.send === "function";
47210
+ return isRecord8(value) && typeof value.send === "function";
45574
47211
  }
45575
47212
  function bedrockRuntimeProxy(client) {
45576
47213
  const cached = bedrockRuntimeProxyCache.get(client);
@@ -47896,12 +49533,272 @@ function waterfall(tasks, callback) {
47896
49533
  }
47897
49534
  var waterfall$1 = awaitify(waterfall);
47898
49535
 
49536
+ // src/framework.ts
49537
+ var import_uuid3 = require("uuid");
49538
+
47899
49539
  // src/trace.ts
49540
+ var spanFilterFields = /* @__PURE__ */ new Set([
49541
+ "spanType",
49542
+ "name",
49543
+ "hasError",
49544
+ "metadata",
49545
+ "duration"
49546
+ ]);
49547
+ function isRecord9(value) {
49548
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
49549
+ return false;
49550
+ }
49551
+ const prototype = Object.getPrototypeOf(value);
49552
+ return prototype === Object.prototype || prototype === null;
49553
+ }
49554
+ function validateMetadataValue(value, ancestors) {
49555
+ if (value === null || typeof value === "string" || typeof value === "boolean") {
49556
+ return;
49557
+ }
49558
+ if (typeof value === "number") {
49559
+ if (Number.isFinite(value)) {
49560
+ return;
49561
+ }
49562
+ throw new Error("filters.metadata numbers must be finite");
49563
+ }
49564
+ if (typeof value !== "object" || value === null) {
49565
+ throw new Error("filters.metadata values must be JSON-serializable");
49566
+ }
49567
+ if (!Array.isArray(value) && !isRecord9(value)) {
49568
+ throw new Error("filters.metadata values must be JSON-serializable");
49569
+ }
49570
+ if (ancestors.has(value)) {
49571
+ throw new Error("filters.metadata must not contain cycles");
49572
+ }
49573
+ ancestors.add(value);
49574
+ if (Array.isArray(value)) {
49575
+ for (let index = 0; index < value.length; index++) {
49576
+ validateMetadataValue(value[index], ancestors);
49577
+ }
49578
+ } else {
49579
+ if (Object.getOwnPropertySymbols(value).length > 0) {
49580
+ throw new Error("filters.metadata keys must be strings");
49581
+ }
49582
+ for (const nested of Object.values(value)) {
49583
+ validateMetadataValue(nested, ancestors);
49584
+ }
49585
+ }
49586
+ ancestors.delete(value);
49587
+ }
49588
+ function compileMetadataLeaves(metadata, path = [], ancestors = /* @__PURE__ */ new WeakSet()) {
49589
+ if (Object.getOwnPropertySymbols(metadata).length > 0) {
49590
+ throw new Error("filters.metadata keys must be strings");
49591
+ }
49592
+ if (ancestors.has(metadata)) {
49593
+ throw new Error("filters.metadata must not contain cycles");
49594
+ }
49595
+ ancestors.add(metadata);
49596
+ const leaves = [];
49597
+ for (const [key, value] of Object.entries(metadata)) {
49598
+ const childPath = [...path, key];
49599
+ if (isRecord9(value)) {
49600
+ leaves.push(...compileMetadataLeaves(value, childPath, ancestors));
49601
+ } else {
49602
+ validateMetadataValue(value, ancestors);
49603
+ leaves.push([childPath, value]);
49604
+ }
49605
+ }
49606
+ ancestors.delete(metadata);
49607
+ return leaves;
49608
+ }
49609
+ function normalizeSpanFilters(filters, spanType) {
49610
+ if (filters != null && !isRecord9(filters)) {
49611
+ throw new Error("filters must be an object");
49612
+ }
49613
+ const values = { ...filters ?? {} };
49614
+ if (spanType !== void 0) {
49615
+ if (!Array.isArray(spanType) || !spanType.every((item) => typeof item === "string")) {
49616
+ throw new Error("spanType must be an array of strings");
49617
+ }
49618
+ if (Object.hasOwn(values, "spanType")) {
49619
+ throw new Error(
49620
+ "spanType cannot be provided both directly and in filters"
49621
+ );
49622
+ }
49623
+ if (spanType.length > 0) {
49624
+ values.spanType = spanType;
49625
+ }
49626
+ }
49627
+ if (Object.keys(values).some((field) => !spanFilterFields.has(field))) {
49628
+ throw new Error("Unsupported span filter fields");
49629
+ }
49630
+ for (const field of ["spanType", "name"]) {
49631
+ if (Object.hasOwn(values, field)) {
49632
+ const items = values[field];
49633
+ if (!Array.isArray(items) || !items.every((item) => typeof item === "string")) {
49634
+ throw new Error(`filters.${field} must be an array of strings`);
49635
+ }
49636
+ }
49637
+ }
49638
+ if (Object.hasOwn(values, "hasError") && typeof values.hasError !== "boolean") {
49639
+ throw new Error("filters.hasError must be a boolean");
49640
+ }
49641
+ let compiledMetadataLeaves = [];
49642
+ if (Object.hasOwn(values, "metadata")) {
49643
+ if (!isRecord9(values.metadata)) {
49644
+ throw new Error("filters.metadata must be an object");
49645
+ }
49646
+ compiledMetadataLeaves = compileMetadataLeaves(values.metadata);
49647
+ }
49648
+ if (Object.hasOwn(values, "duration")) {
49649
+ if (!isRecord9(values.duration) || Object.keys(values.duration).some(
49650
+ (bound) => bound !== "min" && bound !== "max"
49651
+ )) {
49652
+ throw new Error("filters.duration must contain only min and/or max");
49653
+ }
49654
+ if (Object.values(values.duration).some(
49655
+ (bound) => typeof bound !== "number" || !Number.isFinite(bound)
49656
+ )) {
49657
+ throw new Error("filters.duration bounds must be finite numbers");
49658
+ }
49659
+ }
49660
+ const normalized = {};
49661
+ if (Array.isArray(values.spanType)) {
49662
+ normalized.spanType = values.spanType;
49663
+ }
49664
+ if (Array.isArray(values.name)) {
49665
+ normalized.name = values.name;
49666
+ }
49667
+ if (typeof values.hasError === "boolean") {
49668
+ normalized.hasError = values.hasError;
49669
+ }
49670
+ if (isRecord9(values.metadata)) {
49671
+ normalized.metadata = values.metadata;
49672
+ }
49673
+ if (isRecord9(values.duration)) {
49674
+ normalized.duration = {};
49675
+ if (typeof values.duration.min === "number") {
49676
+ normalized.duration.min = values.duration.min;
49677
+ }
49678
+ if (typeof values.duration.max === "number") {
49679
+ normalized.duration.max = values.duration.max;
49680
+ }
49681
+ }
49682
+ return { filters: normalized, metadataLeaves: compiledMetadataLeaves };
49683
+ }
49684
+ function metadataEqual(actual, expected) {
49685
+ if (expected === null) {
49686
+ return actual === null || actual === void 0;
49687
+ }
49688
+ if (Array.isArray(expected)) {
49689
+ return Array.isArray(actual) && actual.length === expected.length && expected.every((value, index) => metadataEqual(actual[index], value));
49690
+ }
49691
+ if (isRecord9(expected)) {
49692
+ if (!isRecord9(actual)) {
49693
+ return false;
49694
+ }
49695
+ const expectedKeys = Object.keys(expected);
49696
+ const actualKeys = Object.keys(actual);
49697
+ return actualKeys.length === expectedKeys.length && expectedKeys.every(
49698
+ (key) => Object.hasOwn(actual, key) && metadataEqual(actual[key], expected[key])
49699
+ );
49700
+ }
49701
+ return actual === expected;
49702
+ }
49703
+ function matchesSpanFilters(span, compiledFilters) {
49704
+ const { filters, metadataLeaves } = compiledFilters;
49705
+ if (filters.spanType !== void 0 && !filters.spanType.includes(span.span_attributes?.type ?? "")) {
49706
+ return false;
49707
+ }
49708
+ if (filters.name !== void 0 && !filters.name.includes(span.span_attributes?.name ?? "")) {
49709
+ return false;
49710
+ }
49711
+ if (filters.hasError !== void 0 && (span.error !== null && span.error !== void 0) !== filters.hasError) {
49712
+ return false;
49713
+ }
49714
+ for (const [path, expected] of metadataLeaves) {
49715
+ let actual = span.metadata;
49716
+ for (const key of path) {
49717
+ actual = isRecord9(actual) && Object.hasOwn(actual, key) ? actual[key] : void 0;
49718
+ }
49719
+ if (!metadataEqual(actual, expected)) {
49720
+ return false;
49721
+ }
49722
+ }
49723
+ if (filters.duration && Object.keys(filters.duration).length > 0) {
49724
+ const metrics = span.metrics;
49725
+ const start = isRecord9(metrics) ? metrics.start : void 0;
49726
+ const end = isRecord9(metrics) ? metrics.end : void 0;
49727
+ if (typeof start !== "number" || !Number.isFinite(start) || typeof end !== "number" || !Number.isFinite(end)) {
49728
+ return false;
49729
+ }
49730
+ const elapsed = end - start;
49731
+ if (filters.duration.min !== void 0 && elapsed < filters.duration.min) {
49732
+ return false;
49733
+ }
49734
+ if (filters.duration.max !== void 0 && elapsed > filters.duration.max) {
49735
+ return false;
49736
+ }
49737
+ }
49738
+ return true;
49739
+ }
49740
+ function btqlComparison(op, name, value) {
49741
+ return {
49742
+ op,
49743
+ left: { op: "ident", name },
49744
+ right: { op: "literal", value }
49745
+ };
49746
+ }
49747
+ function btqlNullCheck(op, name) {
49748
+ return { op, expr: { op: "ident", name } };
49749
+ }
49750
+ function spanFilterClauses(compiledFilters) {
49751
+ const { filters, metadataLeaves } = compiledFilters;
49752
+ const children = [];
49753
+ for (const [field, attribute] of [
49754
+ ["spanType", "type"],
49755
+ ["name", "name"]
49756
+ ]) {
49757
+ const values = filters[field];
49758
+ if (values !== void 0) {
49759
+ children.push(
49760
+ values.length > 0 ? btqlComparison("in", ["span_attributes", attribute], values) : { op: "literal", value: false }
49761
+ );
49762
+ }
49763
+ }
49764
+ if (filters.hasError !== void 0) {
49765
+ children.push(
49766
+ btqlNullCheck(filters.hasError ? "isnotnull" : "isnull", ["error"])
49767
+ );
49768
+ }
49769
+ for (const [path, value] of metadataLeaves) {
49770
+ const name = ["metadata", ...path];
49771
+ children.push(
49772
+ value === null ? btqlNullCheck("isnull", name) : btqlComparison("eq", name, value)
49773
+ );
49774
+ }
49775
+ const elapsed = {
49776
+ op: "sub",
49777
+ left: { op: "ident", name: ["metrics", "end"] },
49778
+ right: { op: "ident", name: ["metrics", "start"] }
49779
+ };
49780
+ if (filters.duration?.min !== void 0) {
49781
+ children.push({
49782
+ op: "ge",
49783
+ left: elapsed,
49784
+ right: { op: "literal", value: filters.duration.min }
49785
+ });
49786
+ }
49787
+ if (filters.duration?.max !== void 0) {
49788
+ children.push({
49789
+ op: "le",
49790
+ left: elapsed,
49791
+ right: { op: "literal", value: filters.duration.max }
49792
+ });
49793
+ }
49794
+ return children;
49795
+ }
47900
49796
  var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
47901
- constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false, brainstoreRealtime = true) {
49797
+ constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false, brainstoreRealtime = true, filters) {
49798
+ const normalizedFilters = normalizeSpanFilters(filters, spanTypeFilter);
47902
49799
  const filterExpr = _SpanFetcher.buildFilter(
47903
49800
  rootSpanId,
47904
- spanTypeFilter,
49801
+ normalizedFilters,
47905
49802
  includeScorers
47906
49803
  );
47907
49804
  super(
@@ -47922,42 +49819,22 @@ var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
47922
49819
  rootSpanId;
47923
49820
  _state;
47924
49821
  spanTypeFilter;
47925
- static buildFilter(rootSpanId, spanTypeFilter, includeScorers = false) {
49822
+ static buildFilter(rootSpanId, filters, includeScorers = false) {
49823
+ const purpose = ["span_attributes", "purpose"];
47926
49824
  const children = [
47927
- // Base filter: root_span_id = 'value'
47928
- {
47929
- op: "eq",
47930
- left: { op: "ident", name: ["root_span_id"] },
47931
- right: { op: "literal", value: rootSpanId }
47932
- }
49825
+ btqlComparison("eq", ["root_span_id"], rootSpanId)
47933
49826
  ];
47934
49827
  if (!includeScorers) {
47935
49828
  children.push({
47936
49829
  op: "or",
47937
49830
  children: [
47938
- {
47939
- op: "isnull",
47940
- expr: { op: "ident", name: ["span_attributes", "purpose"] }
47941
- },
47942
- {
47943
- op: "ne",
47944
- left: { op: "ident", name: ["span_attributes", "purpose"] },
47945
- right: { op: "literal", value: "scorer" }
47946
- }
49831
+ btqlNullCheck("isnull", purpose),
49832
+ btqlComparison("ne", purpose, "scorer")
47947
49833
  ]
47948
49834
  });
47949
49835
  }
47950
- if (spanTypeFilter && spanTypeFilter.length > 0) {
47951
- children.push({
47952
- op: "in",
47953
- left: { op: "ident", name: ["span_attributes", "type"] },
47954
- right: { op: "literal", value: spanTypeFilter }
47955
- });
47956
- }
47957
- return {
47958
- op: "and",
47959
- children
47960
- };
49836
+ children.push(...spanFilterClauses(filters));
49837
+ return { op: "and", children };
47961
49838
  }
47962
49839
  get id() {
47963
49840
  return Promise.resolve(this._objectId);
@@ -47972,67 +49849,80 @@ var CachedSpanFetcher = class {
47972
49849
  fetchFn;
47973
49850
  constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState, brainstoreRealtime = true) {
47974
49851
  if (typeof objectTypeOrFetchFn === "function") {
47975
- this.fetchFn = (spanType) => objectTypeOrFetchFn(spanType);
49852
+ this.fetchFn = async (filters) => (await objectTypeOrFetchFn(filters.filters.spanType)).filter(
49853
+ (span) => matchesSpanFilters(span, filters)
49854
+ );
47976
49855
  } else {
47977
49856
  const objectType = objectTypeOrFetchFn;
47978
- this.fetchFn = async (spanType, includeScorers) => {
49857
+ this.fetchFn = async (filters, includeScorers) => {
47979
49858
  const state = await getState();
47980
49859
  const fetcher = new SpanFetcher(
47981
49860
  objectType,
47982
49861
  objectId,
47983
49862
  rootSpanId,
47984
49863
  state,
47985
- spanType,
49864
+ void 0,
47986
49865
  includeScorers,
47987
- brainstoreRealtime
49866
+ brainstoreRealtime,
49867
+ filters.filters
47988
49868
  );
47989
- const rows = await fetcher.fetchedData();
47990
- return rows.map((row) => ({
47991
- input: row.input,
47992
- output: row.output,
47993
- expected: row.expected,
47994
- error: row.error,
47995
- scores: row.scores,
47996
- metrics: row.metrics,
47997
- metadata: row.metadata,
47998
- span_id: row.span_id,
47999
- span_parents: row.span_parents,
48000
- is_root: row.is_root,
48001
- span_attributes: row.span_attributes,
48002
- id: row.id,
48003
- _xact_id: row._xact_id,
48004
- _pagination_key: row._pagination_key,
48005
- root_span_id: row.root_span_id,
48006
- created: row.created,
48007
- tags: row.tags
48008
- }));
49869
+ let spans = (await fetcher.fetchedData()).map(
49870
+ (row) => ({ ...row })
49871
+ );
49872
+ if (filters.filters.metadata !== void 0) {
49873
+ spans = spans.filter((span) => matchesSpanFilters(span, filters));
49874
+ }
49875
+ return spans;
48009
49876
  };
48010
49877
  }
48011
49878
  }
48012
49879
  async getSpans({
48013
- spanType,
49880
+ spanType: requestedSpanType,
49881
+ filters,
48014
49882
  includeScorers = false
48015
49883
  } = {}) {
49884
+ const normalizedFilters = normalizeSpanFilters(filters, requestedSpanType);
49885
+ const spanType = normalizedFilters.filters.spanType;
49886
+ const hasAdvancedFilters = Object.keys(normalizedFilters.filters).some(
49887
+ (field) => field !== "spanType"
49888
+ );
49889
+ if (spanType?.length === 0) {
49890
+ return [];
49891
+ }
48016
49892
  if (includeScorers) {
48017
- return this.fetchFn(spanType, true);
49893
+ return this.fetchFn(normalizedFilters, true);
48018
49894
  }
48019
49895
  if (this.allFetched) {
48020
- return this.getFromCache(spanType);
49896
+ const spans = this.getFromCache(spanType);
49897
+ return hasAdvancedFilters ? spans.filter((span) => matchesSpanFilters(span, normalizedFilters)) : spans;
48021
49898
  }
48022
- if (!spanType || spanType.length === 0) {
49899
+ if (hasAdvancedFilters && spanType && spanType.every((type) => this.spanCache.has(type))) {
49900
+ return this.getFromCache(spanType).filter(
49901
+ (span) => matchesSpanFilters(span, normalizedFilters)
49902
+ );
49903
+ }
49904
+ if (hasAdvancedFilters) {
49905
+ return this.fetchFn(normalizedFilters, false);
49906
+ }
49907
+ if (!spanType) {
49908
+ this.spanCache.clear();
48023
49909
  await this.fetchSpans(void 0);
48024
- this.allFetched = true;
49910
+ if (this.spanCache.size > 0) {
49911
+ this.allFetched = true;
49912
+ }
48025
49913
  return this.getFromCache(void 0);
48026
49914
  }
48027
- const missingTypes = spanType.filter((t) => !this.spanCache.has(t));
48028
- if (missingTypes.length === 0) {
48029
- return this.getFromCache(spanType);
49915
+ const missingTypes = spanType.filter((type) => !this.spanCache.has(type));
49916
+ if (missingTypes.length > 0) {
49917
+ await this.fetchSpans(missingTypes);
48030
49918
  }
48031
- await this.fetchSpans(missingTypes);
48032
49919
  return this.getFromCache(spanType);
48033
49920
  }
48034
49921
  async fetchSpans(spanType) {
48035
- const spans = await this.fetchFn(spanType, false);
49922
+ const spans = await this.fetchFn(
49923
+ normalizeSpanFilters(spanType ? { spanType } : void 0),
49924
+ false
49925
+ );
48036
49926
  for (const span of spans) {
48037
49927
  const type = span.span_attributes?.type ?? "";
48038
49928
  const existing = this.spanCache.get(type) ?? [];
@@ -48112,34 +50002,20 @@ var LocalTrace = class {
48112
50002
  */
48113
50003
  async getSpans({
48114
50004
  spanType,
50005
+ filters,
48115
50006
  includeScorers = false
48116
50007
  } = {}) {
50008
+ const normalizedFilters = normalizeSpanFilters(filters, spanType);
48117
50009
  const cachedSpans = this.state.spanCache.getByRootSpanId(this.rootSpanId);
48118
50010
  if (cachedSpans && cachedSpans.length > 0) {
48119
- let spans = includeScorers ? cachedSpans : cachedSpans.filter(
48120
- (span) => span.span_attributes?.purpose !== "scorer"
48121
- );
48122
- if (spanType && spanType.length > 0) {
48123
- spans = spans.filter(
48124
- (span) => spanType.includes(span.span_attributes?.type ?? "")
48125
- );
48126
- }
48127
- return spans.map((span) => ({
48128
- input: span.input,
48129
- output: span.output,
48130
- expected: span.expected,
48131
- error: span.error,
48132
- scores: span.scores,
48133
- metrics: span.metrics,
48134
- metadata: span.metadata,
48135
- span_id: span.span_id,
48136
- span_parents: span.span_parents,
48137
- is_root: span.is_root,
48138
- span_attributes: span.span_attributes,
48139
- tags: span.tags
48140
- }));
48141
- }
48142
- return this.cachedFetcher.getSpans({ spanType, includeScorers });
50011
+ return cachedSpans.filter(
50012
+ (span) => (includeScorers || span.span_attributes?.purpose !== "scorer") && matchesSpanFilters({ ...span }, normalizedFilters)
50013
+ ).map((span) => ({ ...span }));
50014
+ }
50015
+ return this.cachedFetcher.getSpans({
50016
+ filters: normalizedFilters.filters,
50017
+ includeScorers
50018
+ });
48143
50019
  }
48144
50020
  /**
48145
50021
  * Get the thread (preprocessed messages) for this trace.
@@ -48559,7 +50435,7 @@ async function Eval(name, evaluator, reporterOrOpts) {
48559
50435
  data,
48560
50436
  { disabled: Boolean(options.parent || options.noSendLogs) }
48561
50437
  );
48562
- if (experiment && typeof process !== "undefined" && globalThis.BRAINTRUST_CONTEXT_MANAGER !== void 0) {
50438
+ if (experiment) {
48563
50439
  await experiment._waitForId();
48564
50440
  }
48565
50441
  if (experiment && options.onStart) {
@@ -48884,6 +50760,10 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
48884
50760
  } : void 0;
48885
50761
  const parsedDatumOrigin = ObjectReference.safeParse(datum.origin);
48886
50762
  const origin = inlineDatasetOrigin ?? (parsedDatumOrigin?.success ? parsedDatumOrigin.data : void 0);
50763
+ const upsertId = datum.upsert_id && trialIndex > 0 ? (0, import_uuid3.v5)(
50764
+ `braintrust:eval:${datum.upsert_id}:trial:${trialIndex}`,
50765
+ import_uuid3.v5.URL
50766
+ ) : datum.upsert_id;
48887
50767
  const baseEvent = {
48888
50768
  name: "eval",
48889
50769
  spanAttributes: {
@@ -48894,7 +50774,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
48894
50774
  expected: "expected" in datum ? datum.expected : void 0,
48895
50775
  tags: datum.tags,
48896
50776
  origin,
48897
- ...datum.upsert_id ? { id: datum.upsert_id } : {}
50777
+ ...upsertId ? { id: upsertId } : {}
48898
50778
  }
48899
50779
  };
48900
50780
  const callback = async (rootSpan) => {
@@ -49403,14 +51283,14 @@ var defaultReporter = {
49403
51283
  }
49404
51284
  };
49405
51285
 
49406
- // src/durable-eval.ts
51286
+ // src/workflow-eval.ts
49407
51287
  var encoder = new TextEncoder();
49408
51288
  var decoder = new TextDecoder();
49409
- var BATCH_TASK_KIND = "braintrust.durable.batch-task";
49410
- var BATCH_SCORER_KIND = "braintrust.durable.batch-scorer";
49411
- var DEFAULT_BATCH_SIZE = 1e3;
49412
- var DurableEvalMemoryStore = class {
51289
+ var WORKFLOW_TASK_KIND = "braintrust.workflow.task";
51290
+ var WORKFLOW_SCORER_KIND = "braintrust.workflow.scorer";
51291
+ var WorkflowEvalMemoryStore = class {
49413
51292
  values = /* @__PURE__ */ new Map();
51293
+ sets = /* @__PURE__ */ new Map();
49414
51294
  async read(key) {
49415
51295
  return this.values.get(key)?.slice();
49416
51296
  }
@@ -49423,8 +51303,16 @@ var DurableEvalMemoryStore = class {
49423
51303
  this.values.set(key, value.slice());
49424
51304
  return { value: value.slice(), created: true };
49425
51305
  }
51306
+ async addToSet(key, member) {
51307
+ let members = this.sets.get(key);
51308
+ if (!members) this.sets.set(key, members = /* @__PURE__ */ new Set());
51309
+ members.add(member);
51310
+ }
51311
+ async getSetSize(key) {
51312
+ return this.sets.get(key)?.size ?? 0;
51313
+ }
49426
51314
  };
49427
- var DurableEvalRedisStore = class {
51315
+ var WorkflowEvalRedisStore = class {
49428
51316
  client;
49429
51317
  keyPrefix;
49430
51318
  ttlMs;
@@ -49433,14 +51321,16 @@ var DurableEvalRedisStore = class {
49433
51321
  this.keyPrefix = options.keyPrefix ?? "braintrust-eval:";
49434
51322
  this.ttlMs = options.ttlMs ?? 1e3 * 60 * 60 * 24 * 7;
49435
51323
  if (!Number.isInteger(this.ttlMs) || this.ttlMs < 1) {
49436
- throw new Error("DurableEvalRedisStore ttlMs must be a positive integer");
51324
+ throw new Error(
51325
+ "WorkflowEvalRedisStore ttlMs must be a positive integer"
51326
+ );
49437
51327
  }
49438
51328
  }
49439
51329
  async read(key) {
49440
51330
  const value = await this.client.get(`${this.keyPrefix}${key}`);
49441
51331
  if (value == null) return void 0;
49442
51332
  if (typeof value !== "string") {
49443
- throw new Error("DurableEvalRedisStore expected GET to return a string");
51333
+ throw new Error("WorkflowEvalRedisStore expected GET to return a string");
49444
51334
  }
49445
51335
  return base64ToUint8Array(value);
49446
51336
  }
@@ -49457,7 +51347,7 @@ var DurableEvalRedisStore = class {
49457
51347
  await set.call(client, redisKey, encoded, { px: this.ttlMs });
49458
51348
  } else {
49459
51349
  throw new Error(
49460
- "DurableEvalRedisStore requires a node-redis, ioredis, or @upstash/redis client"
51350
+ "WorkflowEvalRedisStore requires a node-redis, ioredis, or @upstash/redis client"
49461
51351
  );
49462
51352
  }
49463
51353
  }
@@ -49475,49 +51365,73 @@ var DurableEvalRedisStore = class {
49475
51365
  setOptions = [{ px: this.ttlMs, nx: true, get: true }];
49476
51366
  } else {
49477
51367
  throw new Error(
49478
- "DurableEvalRedisStore getOrSet requires a node-redis, ioredis, or @upstash/redis client"
51368
+ "WorkflowEvalRedisStore getOrSet requires a node-redis, ioredis, or @upstash/redis client"
49479
51369
  );
49480
51370
  }
49481
51371
  const existing = await set.call(client, redisKey, encoded, ...setOptions);
49482
51372
  if (existing === null) return { value: value.slice(), created: true };
49483
51373
  if (typeof existing !== "string") {
49484
51374
  throw new Error(
49485
- "DurableEvalRedisStore expected atomic SET to return a string or null"
51375
+ "WorkflowEvalRedisStore expected atomic SET to return a string or null"
49486
51376
  );
49487
51377
  }
49488
51378
  return { value: base64ToUint8Array(existing), created: false };
49489
51379
  }
51380
+ async addToSet(key, member) {
51381
+ await this.evalSet(
51382
+ "redis.call('SADD', KEYS[1], ARGV[1]); redis.call('PEXPIRE', KEYS[1], ARGV[2]); return 1",
51383
+ key,
51384
+ [member, String(this.ttlMs)]
51385
+ );
51386
+ }
51387
+ async getSetSize(key) {
51388
+ return this.evalSet("return redis.call('SCARD', KEYS[1])", key, []);
51389
+ }
51390
+ async evalSet(script, key, args) {
51391
+ const client = this.client;
51392
+ const redisKey = `${this.keyPrefix}${key}`;
51393
+ 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);
51394
+ if (typeof result !== "number") {
51395
+ throw new Error(
51396
+ "WorkflowEvalRedisStore expected EVAL to return a number"
51397
+ );
51398
+ }
51399
+ return result;
51400
+ }
49490
51401
  };
49491
- var BatchTask = class {
51402
+ var WorkflowTask = class {
49492
51403
  constructor(processor) {
49493
51404
  this.processor = processor;
49494
51405
  }
49495
51406
  processor;
49496
- kind = BATCH_TASK_KIND;
51407
+ kind = WORKFLOW_TASK_KIND;
49497
51408
  };
49498
- var BatchScorer = class {
51409
+ var WorkflowScorer = class {
49499
51410
  constructor(processor) {
49500
51411
  this.processor = processor;
49501
51412
  this.name = processor.name;
49502
51413
  }
49503
51414
  processor;
49504
- kind = BATCH_SCORER_KIND;
51415
+ kind = WORKFLOW_SCORER_KIND;
49505
51416
  name;
49506
51417
  };
49507
- function defineDurableEval(projectName, evaluator) {
51418
+ function defineWorkflowEval(projectName, evaluator) {
51419
+ if (evaluator.maxConcurrency !== void 0 && (!Number.isInteger(evaluator.maxConcurrency) || evaluator.maxConcurrency < 1)) {
51420
+ throw new Error("maxConcurrency must be a positive integer");
51421
+ }
49508
51422
  const definition = {
49509
51423
  projectName,
49510
51424
  evalName: evaluator.experimentName ?? projectName,
49511
51425
  evaluator
49512
51426
  };
49513
51427
  return {
49514
- start: (options = {}) => startDurableEval(definition, options),
49515
- status: (options) => getDurableEvalStatus(definition, options),
49516
- poll: (options) => pollDurableEval(definition, options),
49517
- processBatchResult: (result) => processDurableBatchResult(definition, result)
51428
+ start: (options = {}) => startWorkflowEval(definition, options),
51429
+ status: (options) => getWorkflowEvalStatus(definition, options),
51430
+ poll: (options) => pollWorkflowEval(definition, options),
51431
+ processSubmissionResult: (result) => processWorkflowSubmissionResult(definition, result)
49518
51432
  };
49519
51433
  }
49520
- async function startDurableEval(definition, options) {
51434
+ async function startWorkflowEval(definition, options) {
49521
51435
  const store = definition.evaluator.store;
49522
51436
  const runId = newId();
49523
51437
  const key = runKey(definition.projectName, definition.evalName, runId);
@@ -49537,7 +51451,7 @@ async function startDurableEval(definition, options) {
49537
51451
  update: true
49538
51452
  }
49539
51453
  );
49540
- if (!isBatchTask(definition.evaluator.task) && !(definition.evaluator.scores ?? []).some(isBatchScorer)) {
51454
+ if (!isWorkflowTask(definition.evaluator.task) && !(definition.evaluator.scores ?? []).some(isWorkflowScorer)) {
49541
51455
  const result = await runEvaluator(
49542
51456
  experiment,
49543
51457
  {
@@ -49564,67 +51478,91 @@ async function startDurableEval(definition, options) {
49564
51478
  parameters: assertJsonValue(parameters, "eval parameters"),
49565
51479
  status: "completed",
49566
51480
  summary: result.summary,
51481
+ caseCount: 0,
49567
51482
  cases: [],
49568
- batches: []
51483
+ submissions: []
49569
51484
  };
49570
51485
  await experiment?.flush();
49571
51486
  await writeRunRecord(store, key, state2);
49572
51487
  return currentStatus(definition, state2);
49573
51488
  }
51489
+ const cases = await materializeCases(definition, data, experiment);
49574
51490
  const state = {
49575
51491
  runId,
49576
51492
  experimentName,
49577
51493
  noSendLogs: options.noSendLogs ?? false,
49578
51494
  parameters: assertJsonValue(parameters, "eval parameters"),
49579
51495
  status: "running",
49580
- cases: await materializeCases(definition, data, experiment),
49581
- batches: []
51496
+ caseCount: cases.length,
51497
+ cases,
51498
+ submissions: []
49582
51499
  };
51500
+ await writeJson(
51501
+ store,
51502
+ `${key}/case-ids`,
51503
+ cases.map(({ id }) => id)
51504
+ );
49583
51505
  await writeCaseBaseRecords(store, key, state.cases);
49584
51506
  await writeRunRecord(store, key, state);
49585
- return advanceDurableEval(definition, state, store, key, experiment);
51507
+ return advanceWorkflowEval(definition, state, store, key, experiment);
49586
51508
  }
49587
- async function getDurableEvalStatus(definition, options) {
51509
+ async function getWorkflowEvalStatus(definition, options) {
49588
51510
  const store = definition.evaluator.store;
49589
- const state = await readRunState(
49590
- definition,
49591
- store,
49592
- runKey(definition.projectName, definition.evalName, options.runId)
51511
+ const key = runKey(
51512
+ definition.projectName,
51513
+ definition.evalName,
51514
+ options.runId
49593
51515
  );
49594
- if (!state) throw new Error(`Durable eval run ${options.runId} is missing`);
51516
+ const state = await readJson(store, key);
51517
+ if (!state) throw new Error(`Workflow eval run ${options.runId} is missing`);
49595
51518
  return currentStatus(definition, state);
49596
51519
  }
49597
- async function processDurableBatchResult(definition, result) {
49598
- if (!result.batchId && !result.externalId) {
49599
- throw new Error("Batch results require batchId or externalId");
51520
+ async function processWorkflowSubmissionResult(definition, result) {
51521
+ if (!result.submissionId && !result.externalId) {
51522
+ throw new Error("Submission results require submissionId or externalId");
49600
51523
  }
49601
51524
  const store = definition.evaluator.store;
49602
51525
  const key = runKey(definition.projectName, definition.evalName, result.runId);
49603
- const state = await readRunState(definition, store, key);
49604
- if (!state) throw new Error(`Durable eval run ${result.runId} is missing`);
49605
- const byBatch = result.batchId ? state.batches.find((candidate) => candidate.id === result.batchId) : void 0;
49606
- const byExternal = result.externalId ? state.batches.find(
49607
- (candidate) => candidate.externalId === result.externalId
51526
+ const run = await readJson(store, key);
51527
+ if (!run) throw new Error(`Workflow eval run ${result.runId} is missing`);
51528
+ const externalSubmissionId = result.externalId ? await readJson(
51529
+ store,
51530
+ `${key}/external/${encodedKeyPart(result.externalId)}`
51531
+ ) : void 0;
51532
+ if (result.submissionId && externalSubmissionId && result.submissionId !== externalSubmissionId) {
51533
+ throw new Error(
51534
+ "submissionId and externalId identify different submissions"
51535
+ );
51536
+ }
51537
+ const submissionId = result.submissionId ?? externalSubmissionId;
51538
+ const submission = submissionId ? await readJson(
51539
+ store,
51540
+ submissionRecordKey(key, submissionId)
49608
51541
  ) : void 0;
49609
- if (byBatch && byExternal && byBatch.id !== byExternal.id) {
49610
- throw new Error("batchId and externalId identify different batches");
49611
- }
49612
- const batch = byBatch ?? byExternal;
49613
- if (!batch) throw new Error("No submitted batch matches this result");
49614
- if (batch.status !== "complete") {
49615
- const records = await collectBatch(definition, state, batch);
49616
- batch.status = "complete";
49617
- await writeCaseRecords(store, key, records);
49618
- await writeBatchRecords(store, key, [batch]);
49619
- }
49620
- return advanceDurableEval(
51542
+ if (!submission) throw new Error("No submission matches this result");
51543
+ if (result.externalId && submission.externalId !== result.externalId) {
51544
+ throw new Error(
51545
+ "submissionId and externalId identify different submissions"
51546
+ );
51547
+ }
51548
+ if (run.status === "completed") return currentStatus(definition, run);
51549
+ const state = await readRunState(definition, store, key, [
51550
+ submission.itemId
51551
+ ]);
51552
+ if (submission.status !== "complete") {
51553
+ const record = await collectSubmission(definition, state, submission);
51554
+ await writeCaseRecords(store, key, [record]);
51555
+ submission.status = "complete";
51556
+ }
51557
+ await writeSubmissionRecords(store, key, [submission]);
51558
+ return advanceWorkflowEval(
49621
51559
  definition,
49622
- await readRunState(definition, store, key),
51560
+ await readRunState(definition, store, key, [submission.itemId]),
49623
51561
  store,
49624
51562
  key
49625
51563
  );
49626
51564
  }
49627
- async function pollDurableEval(definition, options) {
51565
+ async function pollWorkflowEval(definition, options) {
49628
51566
  const store = definition.evaluator.store;
49629
51567
  const key = runKey(
49630
51568
  definition.projectName,
@@ -49632,39 +51570,53 @@ async function pollDurableEval(definition, options) {
49632
51570
  options.runId
49633
51571
  );
49634
51572
  const state = await readRunState(definition, store, key);
49635
- if (!state) throw new Error(`Durable eval run ${options.runId} is missing`);
49636
- const batches = state.batches.filter((batch) => {
49637
- if (batch.status === "complete") return false;
49638
- return processorForStage(definition, batch.kind, batch.scorerName).completion.mode === "poll";
49639
- });
49640
- const results = await Promise.all(
49641
- batches.map(async (batch) => ({
49642
- batch,
49643
- result: await processorForStage(definition, batch.kind, batch.scorerName).completion.poll(batch.submissionData, {
49644
- runId: state.runId,
49645
- batchId: batch.id
49646
- })
49647
- }))
49648
- );
49649
- const changedCases = /* @__PURE__ */ new Map();
49650
- const changedBatches = [];
49651
- for (const { batch, result } of results) {
51573
+ if (!state) throw new Error(`Workflow eval run ${options.runId} is missing`);
51574
+ const submissions = state.submissions.filter((submission) => {
51575
+ if (submission.status === "complete") return false;
51576
+ return processorForStage(definition, submission.kind, submission.scorerName).completion.mode === "poll";
51577
+ });
51578
+ const workers = queue(async (submission) => {
51579
+ const completion = processorForStage(
51580
+ definition,
51581
+ submission.kind,
51582
+ submission.scorerName
51583
+ ).completion;
51584
+ if (completion.mode !== "poll") return;
51585
+ const result = await completion.poll(submission.submissionData, {
51586
+ runId: state.runId,
51587
+ submissionId: submission.id
51588
+ });
49652
51589
  if (result.status === "failed") throw asError(result.error);
49653
- if (result.status !== "complete") continue;
49654
- for (const record of await collectBatch(definition, state, batch)) {
49655
- changedCases.set(record.id, record);
49656
- }
49657
- batch.status = "complete";
49658
- changedBatches.push(batch);
49659
- }
49660
- if (changedBatches.length > 0) {
49661
- await writeCaseRecords(store, key, [...changedCases.values()]);
49662
- await writeBatchRecords(store, key, changedBatches);
51590
+ if (result.status === "complete") {
51591
+ const record = await collectSubmission(definition, state, submission);
51592
+ await writeCaseRecords(store, key, [record]);
51593
+ submission.status = "complete";
51594
+ await writeSubmissionRecords(store, key, [submission]);
51595
+ }
51596
+ }, definition.evaluator.maxConcurrency ?? 10);
51597
+ const results = await Promise.allSettled(
51598
+ submissions.map((submission) => workers.pushAsync(submission))
51599
+ );
51600
+ let status;
51601
+ const errors = results.flatMap(
51602
+ (result) => result.status === "rejected" ? [asError(result.reason)] : []
51603
+ );
51604
+ try {
51605
+ status = await advanceWorkflowEval(
51606
+ definition,
51607
+ await readRunState(definition, store, key),
51608
+ store,
51609
+ key
51610
+ );
51611
+ } catch (error) {
51612
+ errors.push(asError(error));
49663
51613
  }
49664
- const currentState = changedBatches.length > 0 ? await readRunState(definition, store, key) : state;
49665
- return advanceDurableEval(definition, currentState, store, key);
51614
+ if (errors.length === 1) throw errors[0];
51615
+ if (errors.length > 1)
51616
+ throw new AggregateError(errors, "Workflow submission callbacks failed");
51617
+ return status;
49666
51618
  }
49667
- async function openDurableExperiment(definition, state) {
51619
+ async function openWorkflowExperiment(definition, state) {
49668
51620
  const data = [];
49669
51621
  return await _internalInitEvaluatorExperiment(
49670
51622
  definition.projectName,
@@ -49677,45 +51629,49 @@ async function openDurableExperiment(definition, state) {
49677
51629
  }
49678
51630
  );
49679
51631
  }
49680
- async function advanceDurableEval(definition, state, store, key, existingExperiment) {
51632
+ async function advanceWorkflowEval(definition, state, store, key, existingExperiment) {
49681
51633
  if (state.status === "completed") return currentStatus(definition, state);
49682
- const experiment = existingExperiment === void 0 ? await openDurableExperiment(definition, state) : existingExperiment;
51634
+ const experiment = existingExperiment === void 0 ? await openWorkflowExperiment(definition, state) : existingExperiment;
51635
+ const caseIds = state.cases.map(({ id }) => id);
49683
51636
  await runTaskStage(definition, state, store, key, experiment);
49684
51637
  await logCompletedTasks(definition, state, store, key, experiment);
49685
- state = await readRunState(definition, store, key) ?? state;
49686
- if (state.cases.some((record) => !record.taskComplete || !record.taskLogged)) {
49687
- return currentStatus(definition, state);
49688
- }
51638
+ state = await readRunState(definition, store, key, caseIds) ?? state;
49689
51639
  await runScoreStages(definition, state, store, key, experiment);
49690
- state = await readRunState(definition, store, key) ?? state;
51640
+ state = await readRunState(definition, store, key, caseIds) ?? state;
49691
51641
  const scorerNames = resolveScorers(definition.evaluator.scores ?? []).map(
49692
51642
  ({ name }) => name
49693
51643
  );
49694
51644
  const classifierNames = (definition.evaluator.classifiers ?? []).map(
49695
51645
  classifierName
49696
51646
  );
49697
- if (state.cases.some(
49698
- (record) => scorerNames.some(
49699
- (name) => !Object.hasOwn(record.scores, name) || !Object.hasOwn(record.loggedScores, name)
49700
- ) || classifierNames.some(
49701
- (name) => !Object.hasOwn(record.loggedClassifications, name)
49702
- )
49703
- )) {
51647
+ await Promise.all(
51648
+ state.cases.map(async (record) => {
51649
+ if (record.taskComplete && record.taskLogged && scorerNames.every(
51650
+ (name) => Object.hasOwn(record.scores, name) && Object.hasOwn(record.loggedScores, name)
51651
+ ) && classifierNames.every(
51652
+ (name) => Object.hasOwn(record.loggedClassifications, name)
51653
+ )) {
51654
+ await store.addToSet(`${key}/progress/cases`, record.id);
51655
+ }
51656
+ })
51657
+ );
51658
+ if (await store.getSetSize(`${key}/progress/cases`) !== state.caseCount) {
49704
51659
  return currentStatus(definition, state);
49705
51660
  }
49706
51661
  if (!await claimAction(store, key, "finish")) {
49707
- const latest = await readRunState(definition, store, key);
51662
+ const latest = await readJson(store, key);
49708
51663
  return currentStatus(definition, latest ?? state);
49709
51664
  }
51665
+ state = await readRunState(definition, store, key);
49710
51666
  state.summary = await finishExperiment(definition, state, experiment);
49711
51667
  state.status = "completed";
49712
51668
  await writeRunRecord(store, key, state);
49713
51669
  return currentStatus(definition, state);
49714
51670
  }
49715
- function currentStatus(definition, state) {
51671
+ async function currentStatus(definition, state) {
49716
51672
  if (state.status === "completed") {
49717
51673
  if (!state.summary) {
49718
- throw new Error(`Durable eval run ${state.runId} has no saved summary`);
51674
+ throw new Error(`Workflow eval run ${state.runId} has no saved summary`);
49719
51675
  }
49720
51676
  return {
49721
51677
  status: "completed",
@@ -49724,11 +51680,20 @@ function currentStatus(definition, state) {
49724
51680
  summary: state.summary
49725
51681
  };
49726
51682
  }
51683
+ const key = runKey(definition.projectName, definition.evalName, state.runId);
51684
+ const store = definition.evaluator.store;
49727
51685
  const pending = { poll: 0, webhook: 0 };
49728
- for (const batch of state.batches) {
49729
- if (batch.status === "complete") continue;
49730
- pending[processorForStage(definition, batch.kind, batch.scorerName).completion.mode]++;
49731
- }
51686
+ await Promise.all(
51687
+ ["poll", "webhook"].map(async (mode) => {
51688
+ const completed = await store.getSetSize(
51689
+ `${key}/progress/${mode}/complete`
51690
+ );
51691
+ const submitted = await store.getSetSize(
51692
+ `${key}/progress/${mode}/submitted`
51693
+ );
51694
+ pending[mode] = submitted - completed;
51695
+ })
51696
+ );
49732
51697
  return { status: "waiting", runId: state.runId, pending };
49733
51698
  }
49734
51699
  async function startCaseRoot(definition, state, record, experiment) {
@@ -49789,7 +51754,7 @@ async function logTaskResult(definition, state, record, experiment, task) {
49789
51754
  expected: "expected" in datum ? datum.expected : void 0,
49790
51755
  metadata: {
49791
51756
  ...record.metadata,
49792
- durable_eval: {
51757
+ workflow_eval: {
49793
51758
  run_id: state.runId,
49794
51759
  case_id: record.caseId,
49795
51760
  trial_index: record.trialIndex
@@ -49820,8 +51785,8 @@ async function logCompletedTasks(definition, state, store, key, experiment) {
49820
51785
  }
49821
51786
  }
49822
51787
  async function runTaskStage(definition, state, store, key, experiment) {
49823
- if (isBatchTask(definition.evaluator.task)) {
49824
- await ensureBatches(definition, state, store, key, "task");
51788
+ if (isWorkflowTask(definition.evaluator.task)) {
51789
+ await ensureSubmissions(definition, state, store, key, "task");
49825
51790
  return;
49826
51791
  }
49827
51792
  const task = definition.evaluator.task;
@@ -49847,8 +51812,9 @@ async function runScoreStages(definition, state, store, key, experiment) {
49847
51812
  changed.clear();
49848
51813
  };
49849
51814
  for (const { name, scorer } of scorers) {
49850
- if (isBatchScorer(scorer)) {
51815
+ if (isWorkflowScorer(scorer)) {
49851
51816
  for (const record of state.cases) {
51817
+ if (!record.taskComplete || !record.taskLogged) continue;
49852
51818
  if (Object.hasOwn(record.scores, name) && !Object.hasOwn(record.loggedScores, name)) {
49853
51819
  if (!await claimAction(store, key, "score-log", record.id, name)) {
49854
51820
  continue;
@@ -49864,10 +51830,11 @@ async function runScoreStages(definition, state, store, key, experiment) {
49864
51830
  }
49865
51831
  }
49866
51832
  await persistChangedCases();
49867
- await ensureBatches(definition, state, store, key, "score", name);
51833
+ await ensureSubmissions(definition, state, store, key, "score", name);
49868
51834
  continue;
49869
51835
  }
49870
51836
  for (const record of state.cases) {
51837
+ if (!record.taskComplete || !record.taskLogged) continue;
49871
51838
  if (Object.hasOwn(record.loggedScores, name)) continue;
49872
51839
  if (!await claimAction(store, key, "score", record.id, name)) continue;
49873
51840
  await evaluateAndLogScore(
@@ -49884,6 +51851,7 @@ async function runScoreStages(definition, state, store, key, experiment) {
49884
51851
  for (const [index, classifier] of (definition.evaluator.classifiers ?? []).entries()) {
49885
51852
  const name = classifierName(classifier, index);
49886
51853
  for (const record of state.cases) {
51854
+ if (!record.taskComplete || !record.taskLogged) continue;
49887
51855
  if (Object.hasOwn(record.loggedClassifications, name)) continue;
49888
51856
  if (!await claimAction(store, key, "classification", record.id, name)) {
49889
51857
  continue;
@@ -49906,13 +51874,14 @@ function scorerArgs(record) {
49906
51874
  return {
49907
51875
  ...datum,
49908
51876
  metadata: record.metadata,
51877
+ tags: record.tags,
49909
51878
  output: record.output
49910
51879
  };
49911
51880
  }
49912
51881
  function resumeCaseRoot(definition, record, experiment) {
49913
51882
  if (!experiment) return NOOP_SPAN;
49914
51883
  if (!record.rootSpan) {
49915
- throw new Error(`Durable eval case ${record.caseId} has no root span`);
51884
+ throw new Error(`Workflow eval case ${record.caseId} has no root span`);
49916
51885
  }
49917
51886
  return _internalResumeSpan({
49918
51887
  exported: record.rootSpan,
@@ -50000,117 +51969,110 @@ async function evaluateAndLogClassification(definition, state, record, name, cla
50000
51969
  root.end();
50001
51970
  }
50002
51971
  }
50003
- async function ensureBatches(definition, state, store, key, kind, scorerName2) {
51972
+ async function ensureSubmissions(definition, state, store, key, kind, scorerName2) {
50004
51973
  const processor = processorForStage(definition, kind, scorerName2);
50005
- const plans = plannedBatches(
51974
+ const plans = plannedSubmissions(
50006
51975
  definition,
50007
51976
  state.runId,
50008
51977
  state.cases.map(({ id }) => id)
50009
51978
  );
50010
51979
  const casesById = new Map(state.cases.map((record) => [record.id, record]));
50011
- for (const plan of plans) {
50012
- if (plan.kind !== kind || plan.scorerName !== scorerName2) continue;
50013
- if (state.batches.some(({ id }) => id === plan.id)) continue;
50014
- const records = plan.itemIds.map((id) => casesById.get(id));
50015
- const ready = records.every(
50016
- (record) => kind === "task" ? !record.taskComplete : !Object.hasOwn(record.scores, scorerName2)
50017
- );
50018
- if (!ready) continue;
50019
- const batchId = plan.id;
51980
+ const existingIds = new Set(state.submissions.map(({ id }) => id));
51981
+ const workers = queue(async (plan) => {
51982
+ if (plan.kind !== kind || plan.scorerName !== scorerName2) return;
51983
+ if (existingIds.has(plan.id)) return;
51984
+ const record = casesById.get(plan.itemId);
51985
+ const ready = kind === "task" ? !record.taskComplete : record.taskComplete && record.taskLogged && !Object.hasOwn(record.scores, scorerName2);
51986
+ if (!ready) return;
51987
+ const submissionId = plan.id;
50020
51988
  const claim = await store.getOrSet(
50021
- claimRecordKey(key, "batch", batchId),
50022
- encoder.encode(batchId)
50023
- );
50024
- if (!claim.created) continue;
50025
- const context = { runId: state.runId, batchId };
50026
- const items = records.map(
50027
- (record) => kind === "task" ? taskBatchItem(record, state.parameters) : scorerBatchItem(record)
51989
+ claimRecordKey(key, "submission", submissionId),
51990
+ encoder.encode(submissionId)
50028
51991
  );
51992
+ if (!claim.created) return;
51993
+ const context = { runId: state.runId, submissionId };
51994
+ const item = kind === "task" ? taskSubmissionItem(record, state.parameters) : scorerSubmissionItem(record);
50029
51995
  const submissionData = assertJsonValue(
50030
- await processor.submit(items, context),
50031
- `submission data for batch ${batchId}`
51996
+ await processor.submit(item, context),
51997
+ `submission data for submission ${submissionId}`
50032
51998
  );
50033
51999
  const externalId = processor.completion.mode === "webhook" ? processor.completion.getExternalId(submissionData, context) : void 0;
50034
52000
  if (externalId !== void 0 && !externalId.trim()) {
50035
- throw new Error(`Batch ${batchId} produced an empty externalId`);
52001
+ throw new Error(
52002
+ `Submission ${submissionId} produced an empty externalId`
52003
+ );
50036
52004
  }
50037
- const batch = {
50038
- id: batchId,
52005
+ const submission = {
52006
+ id: submissionId,
50039
52007
  kind,
50040
52008
  scorerName: scorerName2,
50041
- itemIds: records.map((record) => record.id),
52009
+ itemId: record.id,
50042
52010
  submissionData,
50043
52011
  externalId,
50044
- status: "submitted"
50045
- };
50046
- state.batches.push(batch);
50047
- await writeBatchRecords(store, key, [batch]);
50048
- }
52012
+ status: "submitted",
52013
+ completionMode: processor.completion.mode
52014
+ };
52015
+ state.submissions.push(submission);
52016
+ await writeSubmissionRecords(store, key, [submission]);
52017
+ }, definition.evaluator.maxConcurrency ?? 10);
52018
+ const results = await Promise.allSettled(
52019
+ plans.map((plan) => workers.pushAsync(plan))
52020
+ );
52021
+ const errors = results.flatMap(
52022
+ (result) => result.status === "rejected" ? [asError(result.reason)] : []
52023
+ );
52024
+ if (errors.length === 1) throw errors[0];
52025
+ if (errors.length > 1)
52026
+ throw new AggregateError(errors, "Workflow submissions failed");
50049
52027
  }
50050
- async function collectBatch(definition, state, batch) {
50051
- const processor = processorForStage(definition, batch.kind, batch.scorerName);
50052
- const context = { runId: state.runId, batchId: batch.id };
50053
- const results = await processor.collect(batch.submissionData, context);
50054
- if (!Array.isArray(results)) {
50055
- throw new Error(`collect for batch ${batch.id} must return an array`);
52028
+ async function collectSubmission(definition, state, submission) {
52029
+ const processor = processorForStage(
52030
+ definition,
52031
+ submission.kind,
52032
+ submission.scorerName
52033
+ );
52034
+ const context = { runId: state.runId, submissionId: submission.id };
52035
+ const result = await processor.collect(submission.submissionData, context);
52036
+ if (typeof result !== "object" || result === null || Array.isArray(result)) {
52037
+ throw new Error(
52038
+ `collect for submission ${submission.id} must return a result object`
52039
+ );
50056
52040
  }
50057
- const expectedIds = new Set(batch.itemIds);
50058
- const seen = /* @__PURE__ */ new Set();
50059
- const records = [];
50060
- for (const result of results) {
50061
- const id = resultItemId(result);
50062
- if (!expectedIds.has(id)) {
50063
- throw new Error(`Batch ${batch.id} returned unknown item ${id}`);
50064
- }
50065
- if (seen.has(id)) {
50066
- throw new Error(`Batch ${batch.id} returned item ${id} more than once`);
50067
- }
50068
- seen.add(id);
50069
- const record = state.cases.find((candidate) => candidate.id === id);
50070
- records.push(record);
50071
- if (batch.kind === "task") {
50072
- record.output = assertJsonValue(
50073
- result.output,
50074
- `task output for item ${id}`
50075
- );
50076
- if ("metadata" in result && result.metadata !== void 0) {
50077
- record.metadata = assertJsonValue(
50078
- {
50079
- ...record.metadata,
50080
- ...result.metadata
50081
- },
50082
- `metadata for ${id}`
50083
- );
50084
- }
50085
- if ("tags" in result && result.tags !== void 0)
50086
- record.tags = result.tags;
50087
- record.taskComplete = true;
50088
- } else {
50089
- record.scores[batch.scorerName] = assertJsonValue(
50090
- result.score,
50091
- `score output for item ${id}`
52041
+ const record = state.cases.find(
52042
+ (candidate) => candidate.id === submission.itemId
52043
+ );
52044
+ if (submission.kind === "task") {
52045
+ record.output = assertJsonValue(
52046
+ result.output,
52047
+ `task output for item ${record.id}`
52048
+ );
52049
+ if (result.metadata !== void 0) {
52050
+ record.metadata = assertJsonValue(
52051
+ { ...record.metadata, ...result.metadata },
52052
+ `metadata for ${record.id}`
50092
52053
  );
50093
52054
  }
50094
- }
50095
- const missing = batch.itemIds.filter((id) => !seen.has(id));
50096
- if (missing.length > 0) {
50097
- throw new Error(
50098
- `Batch ${batch.id} did not return results for: ${missing.join(", ")}`
52055
+ if (result.tags !== void 0) record.tags = result.tags;
52056
+ record.taskComplete = true;
52057
+ } else {
52058
+ record.scores[submission.scorerName] = assertJsonValue(
52059
+ result.score,
52060
+ `score output for item ${record.id}`
50099
52061
  );
50100
52062
  }
50101
- return records;
52063
+ return record;
50102
52064
  }
50103
52065
  function processorForStage(definition, kind, scorerName2) {
50104
52066
  if (kind === "task") {
50105
- if (!isBatchTask(definition.evaluator.task)) {
50106
- throw new Error("Definition no longer contains the batch task");
52067
+ if (!isWorkflowTask(definition.evaluator.task)) {
52068
+ throw new Error("Definition no longer contains the submission task");
50107
52069
  }
50108
52070
  return definition.evaluator.task.processor;
50109
52071
  }
50110
52072
  const scorer = resolveScorers(definition.evaluator.scores ?? []).find(
50111
52073
  ({ name }) => name === scorerName2
50112
52074
  )?.scorer;
50113
- if (!isBatchScorer(scorer)) {
52075
+ if (!isWorkflowScorer(scorer)) {
50114
52076
  throw new Error(`Definition no longer contains scorer ${scorerName2}`);
50115
52077
  }
50116
52078
  return scorer.processor;
@@ -50132,15 +52094,15 @@ async function materializeCases(definition, data, experiment) {
50132
52094
  const caseId = datum.id ?? datum.upsert_id ?? (evaluator.caseId ? await evaluator.caseId(datum) : void 0);
50133
52095
  if (!caseId) {
50134
52096
  throw new Error(
50135
- "Every durable eval case requires id, upsert_id, or caseId"
52097
+ "Every workflow eval case requires id, upsert_id, or caseId"
50136
52098
  );
50137
52099
  }
50138
52100
  if (seen.has(caseId))
50139
- throw new Error(`Duplicate durable eval case id: ${caseId}`);
52101
+ throw new Error(`Duplicate workflow eval case id: ${caseId}`);
50140
52102
  seen.add(caseId);
50141
52103
  const trialCount = datum.trialCount ?? evaluator.trialCount ?? 1;
50142
52104
  if (!Number.isInteger(trialCount) || trialCount < 1) {
50143
- throw new Error(`Invalid trialCount for durable eval case ${caseId}`);
52105
+ throw new Error(`Invalid trialCount for workflow eval case ${caseId}`);
50144
52106
  }
50145
52107
  for (let trialIndex = 0; trialIndex < trialCount; trialIndex++) {
50146
52108
  records.push({
@@ -50164,7 +52126,7 @@ async function materializeCases(definition, data, experiment) {
50164
52126
  }
50165
52127
  return records;
50166
52128
  }
50167
- function taskBatchItem(record, parameters) {
52129
+ function taskSubmissionItem(record, parameters) {
50168
52130
  const datum = record.datum;
50169
52131
  return {
50170
52132
  id: record.id,
@@ -50176,7 +52138,7 @@ function taskBatchItem(record, parameters) {
50176
52138
  trialIndex: record.trialIndex
50177
52139
  };
50178
52140
  }
50179
- function scorerBatchItem(record) {
52141
+ function scorerSubmissionItem(record) {
50180
52142
  const datum = record.datum;
50181
52143
  return {
50182
52144
  id: record.id,
@@ -50247,12 +52209,12 @@ async function finishExperiment(definition, state, experiment) {
50247
52209
  }
50248
52210
  function resolveScorers(scorers) {
50249
52211
  return scorers.map((scorer, index) => ({
50250
- name: isBatchScorer(scorer) ? scorer.name : scorer.name || `scorer_${index}`,
52212
+ name: isWorkflowScorer(scorer) ? scorer.name : scorer.name || `scorer_${index}`,
50251
52213
  scorer
50252
52214
  }));
50253
52215
  }
50254
52216
  function runKey(projectName, evalName, runId) {
50255
- return `durable-eval/v1/runs/${contentVersion(encoder.encode(`${projectName}\0${evalName}\0${runId}`))}`;
52217
+ return `workflow-eval/v1/runs/${contentVersion(encoder.encode(`${projectName}\0${evalName}\0${runId}`))}`;
50256
52218
  }
50257
52219
  function encodedKeyPart(value) {
50258
52220
  return uint8ArrayToBase64(encoder.encode(value)).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
@@ -50261,8 +52223,8 @@ function caseRecordKey(key, caseId, kind, ...names) {
50261
52223
  const suffix = names.map(encodedKeyPart).join("/");
50262
52224
  return `${key}/cases/${encodedKeyPart(caseId)}/${kind}${suffix ? `/${suffix}` : ""}`;
50263
52225
  }
50264
- function batchRecordKey(key, batchId) {
50265
- return `${key}/batches/${encodedKeyPart(batchId)}`;
52226
+ function submissionRecordKey(key, submissionId) {
52227
+ return `${key}/submissions/${encodedKeyPart(submissionId)}`;
50266
52228
  }
50267
52229
  function claimRecordKey(key, kind, ...parts) {
50268
52230
  const identity = stableStringify([kind, parts]);
@@ -50274,33 +52236,24 @@ async function claimAction(store, key, kind, ...parts) {
50274
52236
  encoder.encode("claimed")
50275
52237
  )).created;
50276
52238
  }
50277
- function plannedBatches(definition, runId, caseIds) {
52239
+ function plannedSubmissions(definition, runId, caseIds) {
50278
52240
  const stages = [];
50279
- if (isBatchTask(definition.evaluator.task)) stages.push({ kind: "task" });
52241
+ if (isWorkflowTask(definition.evaluator.task)) stages.push({ kind: "task" });
50280
52242
  for (const { name, scorer } of resolveScorers(
50281
52243
  definition.evaluator.scores ?? []
50282
52244
  )) {
50283
- if (isBatchScorer(scorer)) {
52245
+ if (isWorkflowScorer(scorer)) {
50284
52246
  stages.push({ kind: "score", scorerName: name });
50285
52247
  }
50286
52248
  }
50287
52249
  const plans = [];
50288
52250
  for (const { kind, scorerName: scorerName2 } of stages) {
50289
- const batchSize = processorForStage(definition, kind, scorerName2).batchSize ?? DEFAULT_BATCH_SIZE;
50290
- if (!Number.isInteger(batchSize) || batchSize < 1) {
50291
- throw new Error(
50292
- `Invalid batchSize for ${scorerName2 ?? "task"}: ${batchSize}`
50293
- );
50294
- }
50295
- for (let offset = 0; offset < caseIds.length; offset += batchSize) {
50296
- const itemIds = caseIds.slice(offset, offset + batchSize);
52251
+ for (const itemId of caseIds) {
50297
52252
  plans.push({
50298
- id: deterministicId(
50299
- stableStringify([runId, kind, scorerName2, itemIds])
50300
- ),
52253
+ id: deterministicId(stableStringify([runId, kind, scorerName2, itemId])),
50301
52254
  kind,
50302
52255
  scorerName: scorerName2,
50303
- itemIds
52256
+ itemId
50304
52257
  });
50305
52258
  }
50306
52259
  }
@@ -50360,7 +52313,7 @@ async function readCaseRecord(definition, store, key, id) {
50360
52313
  }))
50361
52314
  )
50362
52315
  ]);
50363
- if (!base) throw new Error(`Durable eval case ${id} is missing`);
52316
+ if (!base) throw new Error(`Workflow eval case ${id} is missing`);
50364
52317
  const scores = /* @__PURE__ */ Object.create(null);
50365
52318
  for (const { name, value } of scoreValues) {
50366
52319
  if (value !== void 0) scores[name] = value;
@@ -50391,32 +52344,34 @@ async function readCaseRecord(definition, store, key, id) {
50391
52344
  loggedClassifications
50392
52345
  };
50393
52346
  }
50394
- async function readRunState(definition, store, key) {
52347
+ async function readRunState(definition, store, key, caseIds) {
50395
52348
  const record = await readJson(store, key);
50396
52349
  if (!record) return void 0;
50397
- const plans = plannedBatches(definition, record.runId, record.caseIds);
50398
- const [cases, batchRecords] = await Promise.all([
52350
+ const selectedIds = caseIds ?? (record.caseCount === 0 ? [] : await readJson(store, `${key}/case-ids`));
52351
+ if (!selectedIds)
52352
+ throw new Error(`Workflow eval run ${record.runId} has no case index`);
52353
+ const plans = plannedSubmissions(definition, record.runId, selectedIds);
52354
+ const [cases, submissionRecords] = await Promise.all([
50399
52355
  Promise.all(
50400
- record.caseIds.map((id) => readCaseRecord(definition, store, key, id))
52356
+ selectedIds.map((id) => readCaseRecord(definition, store, key, id))
50401
52357
  ),
50402
52358
  Promise.all(
50403
52359
  plans.map(async ({ id }) => {
50404
- return readJson(store, batchRecordKey(key, id));
52360
+ return readJson(
52361
+ store,
52362
+ submissionRecordKey(key, id)
52363
+ );
50405
52364
  })
50406
52365
  )
50407
52366
  ]);
50408
- const batches = batchRecords.filter(
52367
+ const submissions = submissionRecords.filter(
50409
52368
  (value) => value !== void 0
50410
52369
  );
50411
- const { caseIds: _caseIds, ...state } = record;
50412
- return { ...state, cases, batches };
52370
+ return { ...record, cases, submissions };
50413
52371
  }
50414
52372
  async function writeRunRecord(store, key, state) {
50415
- const { cases, batches: _batches, ...record } = state;
50416
- await writeJson(store, key, {
50417
- ...record,
50418
- caseIds: cases.map(({ id }) => id)
50419
- });
52373
+ const { cases: _cases, submissions: _submissions, ...record } = state;
52374
+ await writeJson(store, key, record);
50420
52375
  }
50421
52376
  async function writeCaseBaseRecords(store, key, records) {
50422
52377
  await Promise.all(
@@ -50488,11 +52443,25 @@ async function writeCaseRecords(store, key, records) {
50488
52443
  }
50489
52444
  await Promise.all(writes);
50490
52445
  }
50491
- async function writeBatchRecords(store, key, records) {
52446
+ async function writeSubmissionRecords(store, key, records) {
50492
52447
  await Promise.all(
50493
- records.map(
50494
- (record) => writeJson(store, batchRecordKey(key, record.id), record)
50495
- )
52448
+ records.map(async (record) => {
52449
+ if (record.externalId !== void 0) {
52450
+ const locator = await store.getOrSet(
52451
+ `${key}/external/${encodedKeyPart(record.externalId)}`,
52452
+ encoder.encode(JSON.stringify(record.id))
52453
+ );
52454
+ if (JSON.parse(decoder.decode(locator.value)) !== record.id) {
52455
+ throw new Error(`Duplicate externalId: ${record.externalId}`);
52456
+ }
52457
+ }
52458
+ const progressKey = `${key}/progress/${record.completionMode}`;
52459
+ await store.addToSet(`${progressKey}/submitted`, record.id);
52460
+ if (record.status === "complete") {
52461
+ await store.addToSet(`${progressKey}/complete`, record.id);
52462
+ }
52463
+ await writeJson(store, submissionRecordKey(key, record.id), record);
52464
+ })
50496
52465
  );
50497
52466
  }
50498
52467
  function deterministicId(value) {
@@ -50537,17 +52506,11 @@ function assertJsonValue(value, label) {
50537
52506
  throw new Error(`${label} must be JSON serializable`, { cause: error });
50538
52507
  }
50539
52508
  }
50540
- function resultItemId(value) {
50541
- if (typeof value !== "object" || value === null || !("id" in value) || typeof value.id !== "string") {
50542
- throw new Error("Batch results must contain a string id");
50543
- }
50544
- return value.id;
50545
- }
50546
- function isBatchTask(value) {
50547
- return typeof value === "object" && value !== null && "kind" in value && value.kind === BATCH_TASK_KIND;
52509
+ function isWorkflowTask(value) {
52510
+ return typeof value === "object" && value !== null && "kind" in value && value.kind === WORKFLOW_TASK_KIND;
50548
52511
  }
50549
- function isBatchScorer(value) {
50550
- return typeof value === "object" && value !== null && "kind" in value && value.kind === BATCH_SCORER_KIND;
52512
+ function isWorkflowScorer(value) {
52513
+ return typeof value === "object" && value !== null && "kind" in value && value.kind === WORKFLOW_SCORER_KIND;
50551
52514
  }
50552
52515
  function asError(error) {
50553
52516
  return error instanceof Error ? error : new Error(String(error));
@@ -51475,13 +53438,13 @@ var evaluatorDefinitionsSchema = import_v313.z.record(
51475
53438
  );
51476
53439
 
51477
53440
  // src/wrappers/elevenlabs.ts
51478
- var clients = /* @__PURE__ */ new WeakMap();
53441
+ var clients2 = /* @__PURE__ */ new WeakMap();
51479
53442
  function wrapElevenLabs(client) {
51480
53443
  if (!isObject(client) || !isObject(client.textToSpeech) || typeof client.textToSpeech.convert !== "function") {
51481
53444
  debugLogger.warn("Unsupported ElevenLabs client. Not wrapping.");
51482
53445
  return client;
51483
53446
  }
51484
- const cached = clients.get(client);
53447
+ const cached = clients2.get(client);
51485
53448
  if (cached) return cached;
51486
53449
  const sdk = client;
51487
53450
  const speech = new Proxy(sdk.textToSpeech, {
@@ -51528,8 +53491,8 @@ function wrapElevenLabs(client) {
51528
53491
  return Reflect.get(target, prop, receiver);
51529
53492
  }
51530
53493
  });
51531
- clients.set(client, proxy);
51532
- clients.set(proxy, proxy);
53494
+ clients2.set(client, proxy);
53495
+ clients2.set(proxy, proxy);
51533
53496
  return proxy;
51534
53497
  }
51535
53498