braintrust 3.21.0 → 3.22.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.
package/dist/index.mjs CHANGED
@@ -27,6 +27,7 @@ import {
27
27
  JSONAttachment,
28
28
  LEGACY_CACHED_HEADER,
29
29
  LOGS3_OVERFLOW_REFERENCE_TYPE,
30
+ LRUCache,
30
31
  LazyValue,
31
32
  Logger,
32
33
  LoginInvalidOrgError,
@@ -55,6 +56,7 @@ import {
55
56
  _exportsForTestingOnly,
56
57
  _internalGetGlobalState,
57
58
  _internalSetInitialState,
59
+ _internalStartSpanWithInitialMerge,
58
60
  addAzureBlobHeaders,
59
61
  braintrustAISDKTelemetry,
60
62
  braintrustFlueInstrumentation,
@@ -137,7 +139,7 @@ import {
137
139
  wrapMastraAgent,
138
140
  wrapTraced,
139
141
  zodToJsonSchema
140
- } from "./chunk-O2P765XK.mjs";
142
+ } from "./chunk-ZG2O3XVF.mjs";
141
143
  import {
142
144
  __export,
143
145
  aiSDKChannels,
@@ -228,6 +230,8 @@ __export(exports_exports, {
228
230
  addAzureBlobHeaders: () => addAzureBlobHeaders,
229
231
  agentAssertionScorer: () => agentAssertionScorer,
230
232
  braintrustAISDKTelemetry: () => braintrustAISDKTelemetry,
233
+ braintrustEveHook: () => braintrustEveHook,
234
+ braintrustEveInstrumentation: () => braintrustEveInstrumentation,
231
235
  braintrustFlueInstrumentation: () => braintrustFlueInstrumentation,
232
236
  braintrustFlueObserver: () => braintrustFlueObserver,
233
237
  braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
@@ -1728,6 +1732,1469 @@ function BraintrustMiddleware(config = {}) {
1728
1732
  };
1729
1733
  }
1730
1734
 
1735
+ // src/instrumentation/plugins/eve-plugin.ts
1736
+ var EVE_TRACE_STATE_KEY = "braintrust.eve.tracing";
1737
+ var MAX_EVE_CACHE_ENTRIES = 1e4;
1738
+ var MAX_STORED_LLM_INPUTS = 100;
1739
+ var MAX_STORED_SPAN_REFERENCES = 1e4;
1740
+ var MAX_STORED_STEP_STARTS = 1e4;
1741
+ function braintrustEveHook(options) {
1742
+ const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
1743
+ const bridge = new EveBridge(state);
1744
+ return {
1745
+ events: {
1746
+ "*": async (event, ctx) => {
1747
+ await bridge.handle(event, ctx, options.metadata);
1748
+ }
1749
+ }
1750
+ };
1751
+ }
1752
+ function braintrustEveInstrumentation(options) {
1753
+ const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
1754
+ return {
1755
+ events: {
1756
+ "step.started": (input) => {
1757
+ try {
1758
+ captureEveModelInput(state, input);
1759
+ } catch (error) {
1760
+ debugLogger.warn("Error in Eve LLM input capture:", error);
1761
+ }
1762
+ }
1763
+ },
1764
+ recordInputs: false,
1765
+ recordOutputs: false,
1766
+ setup: options.setup
1767
+ };
1768
+ }
1769
+ function isEveHandleMessageStreamEvent(event) {
1770
+ return isObject(event) && typeof event["type"] === "string";
1771
+ }
1772
+ var ResumedEveSpan = class {
1773
+ constructor(reference) {
1774
+ this.reference = reference;
1775
+ this.endTime = reference.endTime;
1776
+ }
1777
+ endTime;
1778
+ get rootSpanId() {
1779
+ return this.reference.rootSpanId;
1780
+ }
1781
+ get spanId() {
1782
+ return this.reference.spanId;
1783
+ }
1784
+ log(event) {
1785
+ const metrics = {
1786
+ ...this.reference.startEvent?.metrics,
1787
+ ...this.endTime === void 0 ? {} : { end: this.endTime },
1788
+ ...event.metrics
1789
+ };
1790
+ updateSpan({
1791
+ exported: this.reference.exported,
1792
+ ...this.reference.startEvent,
1793
+ ...event,
1794
+ ...Object.keys(metrics).length > 0 ? { metrics } : {}
1795
+ });
1796
+ }
1797
+ end(args) {
1798
+ if (this.endTime === void 0) {
1799
+ this.endTime = args?.endTime ?? getCurrentUnixTimestamp();
1800
+ this.log({ metrics: { end: this.endTime } });
1801
+ }
1802
+ return this.endTime;
1803
+ }
1804
+ };
1805
+ var EveBridge = class {
1806
+ constructor(state) {
1807
+ this.state = state;
1808
+ }
1809
+ eventQueuesBySession = /* @__PURE__ */ new Map();
1810
+ sessionsById = new LRUCache({
1811
+ max: MAX_EVE_CACHE_ENTRIES
1812
+ });
1813
+ completedToolKeys = new LRUCache({
1814
+ max: MAX_EVE_CACHE_ENTRIES
1815
+ });
1816
+ toolsByCallKey = new LRUCache({
1817
+ max: MAX_EVE_CACHE_ENTRIES
1818
+ });
1819
+ turnsByKey = new LRUCache({
1820
+ max: MAX_EVE_CACHE_ENTRIES
1821
+ });
1822
+ async startEveSpan(args) {
1823
+ const rowId = args?.event?.id;
1824
+ const reference = typeof rowId === "string" && readEveTraceState(this.state).spanReferences.find(
1825
+ (candidate) => candidate.rowId === rowId
1826
+ );
1827
+ if (reference) {
1828
+ return new ResumedEveSpan(reference);
1829
+ }
1830
+ const startTime = args?.startTime ?? getCurrentUnixTimestamp();
1831
+ const parentSpanIds = args?.parentSpanIds;
1832
+ const startEvent = {
1833
+ created: (/* @__PURE__ */ new Date()).toISOString(),
1834
+ metrics: { start: startTime },
1835
+ span_attributes: {
1836
+ ...args?.name ? { name: args.name } : {},
1837
+ ...args?.type ? { type: args.type } : {},
1838
+ ...args?.spanAttributes
1839
+ },
1840
+ span_parents: parentSpanIds ? "spanId" in parentSpanIds ? [parentSpanIds.spanId] : parentSpanIds.parentSpanIds : []
1841
+ };
1842
+ const span = withCurrent(
1843
+ NOOP_SPAN,
1844
+ () => _internalStartSpanWithInitialMerge({ ...args, startTime })
1845
+ );
1846
+ if (typeof rowId !== "string") {
1847
+ return span;
1848
+ }
1849
+ try {
1850
+ const exported = await span.export();
1851
+ const reference2 = {
1852
+ exported,
1853
+ rootSpanId: span.rootSpanId,
1854
+ rowId,
1855
+ spanId: span.spanId,
1856
+ startEvent
1857
+ };
1858
+ this.state.update((current) => {
1859
+ const normalized = normalizeEveTraceState(current);
1860
+ return normalized.spanReferences.some(
1861
+ (candidate) => candidate.rowId === rowId
1862
+ ) ? normalized : {
1863
+ ...normalized,
1864
+ spanReferences: [...normalized.spanReferences, reference2].slice(
1865
+ -MAX_STORED_SPAN_REFERENCES
1866
+ )
1867
+ };
1868
+ });
1869
+ } catch (error) {
1870
+ debugLogger.warn("Error exporting Eve span for resumption:", error);
1871
+ }
1872
+ return span;
1873
+ }
1874
+ async startEveChildSpan(parent, args) {
1875
+ return await this.startEveSpan({
1876
+ ...args,
1877
+ parentSpanIds: {
1878
+ rootSpanId: parent.rootSpanId,
1879
+ spanId: parent.spanId
1880
+ }
1881
+ });
1882
+ }
1883
+ stepOrdinal(event) {
1884
+ let ordinal = 0;
1885
+ this.state.update((current) => {
1886
+ const state = normalizeEveTraceState(current);
1887
+ const previous = state.stepStarts.filter(
1888
+ (entry) => entry.turnId === event.data.turnId && entry.stepIndex === event.data.stepIndex
1889
+ ).at(-1);
1890
+ if (previous?.open) {
1891
+ ordinal = previous.ordinal;
1892
+ return state;
1893
+ }
1894
+ ordinal = state.stepStarts.filter(
1895
+ (entry) => entry.turnId === event.data.turnId
1896
+ ).length;
1897
+ return {
1898
+ ...state,
1899
+ stepStarts: [
1900
+ ...state.stepStarts,
1901
+ {
1902
+ open: true,
1903
+ ordinal,
1904
+ stepIndex: event.data.stepIndex,
1905
+ turnId: event.data.turnId
1906
+ }
1907
+ ].slice(-MAX_STORED_STEP_STARTS)
1908
+ };
1909
+ });
1910
+ return ordinal;
1911
+ }
1912
+ markStepEnded(turnId, stepIndex) {
1913
+ this.state.update((current) => {
1914
+ const state = normalizeEveTraceState(current);
1915
+ let index = -1;
1916
+ for (let i = state.stepStarts.length - 1; i >= 0; i--) {
1917
+ const entry = state.stepStarts[i];
1918
+ if (entry?.turnId === turnId && entry.stepIndex === stepIndex) {
1919
+ index = i;
1920
+ break;
1921
+ }
1922
+ }
1923
+ if (index < 0 || !state.stepStarts[index]?.open) {
1924
+ return state;
1925
+ }
1926
+ return {
1927
+ ...state,
1928
+ stepStarts: state.stepStarts.map(
1929
+ (entry, entryIndex) => entryIndex === index ? { ...entry, open: false } : entry
1930
+ )
1931
+ };
1932
+ });
1933
+ }
1934
+ async handle(event, ctx, hookMetadata) {
1935
+ if (!isEveHandleMessageStreamEvent(event)) {
1936
+ return;
1937
+ }
1938
+ const run = async () => {
1939
+ try {
1940
+ if (!await this.handleEvent(event, ctx, hookMetadata)) {
1941
+ return;
1942
+ }
1943
+ if (event.type === "session.failed") {
1944
+ const sessionId2 = event.data.sessionId || sessionIdFromContext(ctx);
1945
+ await this.flushInstrumentation();
1946
+ if (sessionId2) {
1947
+ this.cleanupSession(sessionId2);
1948
+ }
1949
+ } else if (event.type === "session.completed") {
1950
+ const sessionId2 = sessionIdFromContext(ctx);
1951
+ await this.flushInstrumentation();
1952
+ if (sessionId2) {
1953
+ this.cleanupSession(sessionId2);
1954
+ }
1955
+ }
1956
+ } catch (error) {
1957
+ debugLogger.warn("Error in Eve hook instrumentation:", error);
1958
+ }
1959
+ };
1960
+ const sessionId = event.type === "session.failed" ? event.data.sessionId || sessionIdFromContext(ctx) : sessionIdFromContext(ctx);
1961
+ if (!sessionId) {
1962
+ await run();
1963
+ return;
1964
+ }
1965
+ const previous = this.eventQueuesBySession.get(sessionId);
1966
+ const queued = previous ? previous.then(run) : run();
1967
+ this.eventQueuesBySession.set(sessionId, queued);
1968
+ try {
1969
+ await queued;
1970
+ } finally {
1971
+ if (this.eventQueuesBySession.get(sessionId) === queued) {
1972
+ this.eventQueuesBySession.delete(sessionId);
1973
+ }
1974
+ }
1975
+ }
1976
+ async handleEvent(event, ctx, hookMetadata) {
1977
+ switch (event.type) {
1978
+ case "session.started":
1979
+ await this.handleSessionStarted(event, ctx, hookMetadata);
1980
+ return true;
1981
+ case "turn.started":
1982
+ await this.handleTurnStarted(event, ctx, hookMetadata);
1983
+ return true;
1984
+ case "message.received":
1985
+ await this.handleMessageReceived(event, ctx, hookMetadata);
1986
+ return true;
1987
+ case "step.started":
1988
+ await this.handleStepStarted(event, ctx, hookMetadata);
1989
+ return true;
1990
+ case "message.completed":
1991
+ this.handleMessageCompleted(event, ctx);
1992
+ return true;
1993
+ case "result.completed":
1994
+ this.handleResultCompleted(event, ctx);
1995
+ return true;
1996
+ case "actions.requested":
1997
+ await this.handleActionsRequested(event, ctx, hookMetadata);
1998
+ return true;
1999
+ case "action.result":
2000
+ await this.handleActionResult(event, ctx, hookMetadata);
2001
+ return true;
2002
+ case "subagent.called":
2003
+ await this.handleSubagentCalled(event, ctx, hookMetadata);
2004
+ return true;
2005
+ case "subagent.completed":
2006
+ await this.handleSubagentCompleted(event, ctx, hookMetadata);
2007
+ return true;
2008
+ case "step.completed":
2009
+ this.handleStepCompleted(event, ctx);
2010
+ return true;
2011
+ case "step.failed":
2012
+ this.handleStepFailed(event, ctx);
2013
+ return true;
2014
+ case "turn.completed":
2015
+ await this.handleTurnCompleted(event, ctx);
2016
+ return true;
2017
+ case "turn.failed":
2018
+ await this.handleTurnFailed(event, ctx);
2019
+ return true;
2020
+ case "session.failed":
2021
+ await this.handleSessionFailed(event, ctx);
2022
+ return true;
2023
+ case "session.completed":
2024
+ await this.handleSessionCompleted(event, ctx);
2025
+ return true;
2026
+ default:
2027
+ return false;
2028
+ }
2029
+ }
2030
+ async handleSessionStarted(event, ctx, hookMetadata) {
2031
+ const sessionId = sessionIdFromContext(ctx);
2032
+ if (!sessionId) {
2033
+ return;
2034
+ }
2035
+ const metadata = {
2036
+ ...hookMetadata ?? {},
2037
+ ...modelMetadataFromRuntime(event.data.runtime)
2038
+ };
2039
+ this.state.update((current) => {
2040
+ const normalized = normalizeEveTraceState(current);
2041
+ return {
2042
+ ...normalized,
2043
+ metadata: { ...normalized.metadata, ...metadata }
2044
+ };
2045
+ });
2046
+ await this.ensureSession(sessionId, ctx, metadata, eventTime(event));
2047
+ for (const [key, turn] of this.turnsByKey) {
2048
+ if (!key.startsWith(`${sessionId}:`)) {
2049
+ continue;
2050
+ }
2051
+ turn.metadata = { ...turn.metadata, ...metadata };
2052
+ turn.span.log({ metadata: turn.metadata });
2053
+ for (const step of turn.stepsByIndex.values()) {
2054
+ step.metadata = { ...step.metadata, ...metadata };
2055
+ step.span.log({ metadata: step.metadata });
2056
+ }
2057
+ }
2058
+ }
2059
+ async handleTurnStarted(event, ctx, hookMetadata) {
2060
+ const sessionId = sessionIdFromContext(ctx);
2061
+ if (!sessionId) {
2062
+ return;
2063
+ }
2064
+ const session = await this.ensureSession(
2065
+ sessionId,
2066
+ ctx,
2067
+ hookMetadata ?? {},
2068
+ eventTime(event)
2069
+ );
2070
+ const key = turnKey(sessionId, event.data.turnId);
2071
+ const metadata = { ...session.metadata };
2072
+ const existing = this.turnsByKey.get(key);
2073
+ if (existing) {
2074
+ existing.metadata = { ...existing.metadata, ...metadata };
2075
+ existing.span.log({ metadata: existing.metadata });
2076
+ return;
2077
+ }
2078
+ const span = await this.startTurnSpan(session, event, metadata);
2079
+ span.log({ metadata });
2080
+ this.turnsByKey.set(key, {
2081
+ key,
2082
+ metadata,
2083
+ metrics: {},
2084
+ span,
2085
+ stepsByIndex: /* @__PURE__ */ new Map(),
2086
+ turnId: event.data.turnId
2087
+ });
2088
+ }
2089
+ async handleMessageReceived(event, ctx, hookMetadata) {
2090
+ const turn = await this.ensureTurn(event, ctx, hookMetadata);
2091
+ if (!turn) {
2092
+ return;
2093
+ }
2094
+ const input = [{ content: event.data.message, role: "user" }];
2095
+ turn.span.log({ input });
2096
+ }
2097
+ async handleStepStarted(event, ctx, hookMetadata) {
2098
+ const turn = await this.ensureTurn(event, ctx, hookMetadata);
2099
+ const sessionId = sessionIdFromContext(ctx);
2100
+ if (!turn || !sessionId) {
2101
+ return;
2102
+ }
2103
+ const existing = turn.stepsByIndex.get(event.data.stepIndex);
2104
+ if (existing) {
2105
+ existing.span.log({
2106
+ ...existing.input !== void 0 ? { input: existing.input } : {},
2107
+ metadata: existing.metadata,
2108
+ metrics: existing.metrics,
2109
+ output: existing.output
2110
+ });
2111
+ const endTime = eventTime(event);
2112
+ existing.span.end(endTime === void 0 ? void 0 : { endTime });
2113
+ this.markStepEnded(event.data.turnId, event.data.stepIndex);
2114
+ }
2115
+ const stepOrdinal = this.stepOrdinal(event);
2116
+ const metadata = {
2117
+ ...turn.metadata,
2118
+ ...this.sessionsById.get(sessionId)?.metadata ?? {}
2119
+ };
2120
+ const input = consumeCapturedEveModelInput(
2121
+ this.state,
2122
+ sessionId,
2123
+ event.data.turnId,
2124
+ event.data.stepIndex
2125
+ );
2126
+ const { rowId: eventId, spanId } = await generateEveIds(
2127
+ "step",
2128
+ sessionId,
2129
+ event.data.turnId,
2130
+ String(stepOrdinal)
2131
+ );
2132
+ const span = await this.startEveChildSpan(turn.span, {
2133
+ event: {
2134
+ id: eventId,
2135
+ ...input !== void 0 ? { input } : {},
2136
+ metadata
2137
+ },
2138
+ name: "eve.step",
2139
+ spanAttributes: { type: "llm" /* LLM */ },
2140
+ spanId,
2141
+ startTime: eventTime(event)
2142
+ });
2143
+ span.log({ ...input !== void 0 ? { input } : {}, metadata });
2144
+ turn.stepsByIndex.set(event.data.stepIndex, {
2145
+ ...input !== void 0 ? { input } : {},
2146
+ metadata,
2147
+ metrics: {},
2148
+ span
2149
+ });
2150
+ }
2151
+ handleMessageCompleted(event, ctx) {
2152
+ const step = this.stepForEvent(event, ctx);
2153
+ if (!step) {
2154
+ return;
2155
+ }
2156
+ const existingMessage = Array.isArray(step.output) && isObject(step.output[0]) ? step.output[0].message : void 0;
2157
+ const existingToolCalls = isObject(existingMessage) ? existingMessage.tool_calls : void 0;
2158
+ step.output = [
2159
+ {
2160
+ finish_reason: normalizedFinishReason(event.data.finishReason),
2161
+ index: 0,
2162
+ message: {
2163
+ content: event.data.message,
2164
+ role: "assistant",
2165
+ ...Array.isArray(existingToolCalls) ? { tool_calls: existingToolCalls } : {}
2166
+ }
2167
+ }
2168
+ ];
2169
+ const turn = this.turnForEvent(event, ctx);
2170
+ if (turn && event.data.finishReason !== "tool-calls") {
2171
+ turn.output = event.data.message;
2172
+ }
2173
+ }
2174
+ handleResultCompleted(event, ctx) {
2175
+ const step = this.stepForEvent(event, ctx);
2176
+ if (step) {
2177
+ step.output = [
2178
+ {
2179
+ finish_reason: "stop",
2180
+ index: 0,
2181
+ message: {
2182
+ content: event.data.result,
2183
+ role: "assistant"
2184
+ }
2185
+ }
2186
+ ];
2187
+ }
2188
+ const turn = this.turnForEvent(event, ctx);
2189
+ if (turn) {
2190
+ turn.output = event.data.result;
2191
+ }
2192
+ }
2193
+ async handleActionsRequested(event, ctx, hookMetadata) {
2194
+ const turn = await this.ensureTurn(event, ctx, hookMetadata);
2195
+ const sessionId = sessionIdFromContext(ctx);
2196
+ if (!turn || !sessionId) {
2197
+ return;
2198
+ }
2199
+ const traceActions = event.data.actions.filter(isTraceableActionRequest);
2200
+ if (traceActions.length === 0) {
2201
+ return;
2202
+ }
2203
+ for (const action of traceActions) {
2204
+ if (isToolCallAction(action)) {
2205
+ await this.startRequestedTool(event, turn, sessionId, action);
2206
+ } else if (isLocalSubagentCallAction(action)) {
2207
+ await this.startRequestedSubagent(event, turn, sessionId, action);
2208
+ }
2209
+ }
2210
+ const step = turn.stepsByIndex.get(event.data.stepIndex);
2211
+ if (!step) {
2212
+ return;
2213
+ }
2214
+ step.output = [
2215
+ {
2216
+ finish_reason: "tool_calls",
2217
+ index: 0,
2218
+ message: {
2219
+ content: null,
2220
+ role: "assistant",
2221
+ tool_calls: traceActions.map((action) => {
2222
+ const name = action.kind === "tool-call" ? action.toolName : action.subagentName ?? action.name ?? "agent";
2223
+ return {
2224
+ function: {
2225
+ arguments: JSON.stringify(action.input),
2226
+ name
2227
+ },
2228
+ id: action.callId,
2229
+ type: "function"
2230
+ };
2231
+ })
2232
+ }
2233
+ }
2234
+ ];
2235
+ step.span.log({ metadata: step.metadata, output: step.output });
2236
+ }
2237
+ async handleActionResult(event, ctx, hookMetadata) {
2238
+ if (isToolResult(event.data.result)) {
2239
+ await this.handleToolResult(event, ctx, event.data.result, hookMetadata);
2240
+ return;
2241
+ }
2242
+ if (isSubagentResult(event.data.result)) {
2243
+ await this.handleSubagentResult(
2244
+ event,
2245
+ ctx,
2246
+ event.data.result,
2247
+ hookMetadata
2248
+ );
2249
+ }
2250
+ }
2251
+ async handleToolResult(event, ctx, result, hookMetadata) {
2252
+ const sessionId = sessionIdFromContext(ctx);
2253
+ if (!sessionId) {
2254
+ return;
2255
+ }
2256
+ const key = toolKey(sessionId, result.callId);
2257
+ if (this.completedToolKeys.has(key)) {
2258
+ return;
2259
+ }
2260
+ const tool = this.toolsByCallKey.get(key) ?? await this.startSyntheticTool(event, ctx, result, hookMetadata);
2261
+ if (!tool) {
2262
+ return;
2263
+ }
2264
+ const failed = event.data.status === "failed" || result.isError === true || event.data.error !== void 0;
2265
+ tool.span.log({
2266
+ ...failed ? {
2267
+ error: actionResultError(event.data.error, result.output)
2268
+ } : {},
2269
+ metadata: tool.metadata,
2270
+ output: result.output
2271
+ });
2272
+ const endTime = eventTime(event);
2273
+ tool.span.end(endTime === void 0 ? void 0 : { endTime });
2274
+ this.toolsByCallKey.delete(key);
2275
+ this.completedToolKeys.set(key, true);
2276
+ }
2277
+ async handleSubagentCalled(event, ctx, hookMetadata) {
2278
+ if (event.data.remote?.url) {
2279
+ return;
2280
+ }
2281
+ const turn = await this.ensureTurn(event, ctx, hookMetadata);
2282
+ const sessionId = sessionIdFromContext(ctx);
2283
+ if (!turn || !sessionId) {
2284
+ return;
2285
+ }
2286
+ const key = toolKey(sessionId, event.data.callId);
2287
+ const metadata = toolMetadataFromTurn(turn);
2288
+ const existing = this.toolsByCallKey.get(key);
2289
+ if (existing) {
2290
+ existing.metadata = { ...existing.metadata, ...metadata };
2291
+ existing.span.log({ metadata: existing.metadata });
2292
+ return;
2293
+ }
2294
+ if (this.completedToolKeys.has(key)) {
2295
+ return;
2296
+ }
2297
+ const { rowId: eventId, spanId } = await generateEveIds(
2298
+ "subagent",
2299
+ sessionId,
2300
+ event.data.callId
2301
+ );
2302
+ const pending = this.toolsByCallKey.get(key);
2303
+ if (pending || this.completedToolKeys.has(key)) {
2304
+ if (pending) {
2305
+ pending.metadata = { ...pending.metadata, ...metadata };
2306
+ pending.span.log({ metadata: pending.metadata });
2307
+ }
2308
+ return;
2309
+ }
2310
+ const span = await this.startEveChildSpan(turn.span, {
2311
+ event: {
2312
+ id: eventId,
2313
+ metadata
2314
+ },
2315
+ name: event.data.toolName ?? event.data.name,
2316
+ spanAttributes: { type: "tool" /* TOOL */ },
2317
+ spanId,
2318
+ startTime: eventTime(event)
2319
+ });
2320
+ span.log({ metadata });
2321
+ this.toolsByCallKey.set(key, {
2322
+ metadata,
2323
+ span,
2324
+ turnKey: turnKey(sessionId, event.data.turnId)
2325
+ });
2326
+ }
2327
+ async handleSubagentCompleted(event, ctx, hookMetadata) {
2328
+ const sessionId = sessionIdFromContext(ctx);
2329
+ if (!sessionId) {
2330
+ return;
2331
+ }
2332
+ const key = toolKey(sessionId, event.data.callId);
2333
+ if (this.completedToolKeys.has(key)) {
2334
+ return;
2335
+ }
2336
+ const subagent = this.toolsByCallKey.get(key) ?? await this.startSyntheticSubagent(event, ctx, hookMetadata);
2337
+ if (!subagent) {
2338
+ return;
2339
+ }
2340
+ subagent.span.log({
2341
+ ...event.data.status === "failed" ? {
2342
+ error: actionResultError(event.data.error, event.data.output)
2343
+ } : {},
2344
+ metadata: subagent.metadata,
2345
+ ...event.data.output !== void 0 ? { output: event.data.output } : {}
2346
+ });
2347
+ const endTime = eventTime(event);
2348
+ const recordedEndTime = subagent.span.end(
2349
+ endTime === void 0 ? void 0 : { endTime }
2350
+ );
2351
+ this.state.update((current) => {
2352
+ const normalized = normalizeEveTraceState(current);
2353
+ return {
2354
+ ...normalized,
2355
+ spanReferences: normalized.spanReferences.map(
2356
+ (reference) => reference.spanId === subagent.span.spanId ? { ...reference, endTime: recordedEndTime } : reference
2357
+ )
2358
+ };
2359
+ });
2360
+ }
2361
+ async handleSubagentResult(event, ctx, result, hookMetadata) {
2362
+ const sessionId = sessionIdFromContext(ctx);
2363
+ if (!sessionId) {
2364
+ return;
2365
+ }
2366
+ const key = toolKey(sessionId, result.callId);
2367
+ if (this.completedToolKeys.has(key)) {
2368
+ return;
2369
+ }
2370
+ const subagent = this.toolsByCallKey.get(key) ?? await this.startSyntheticSubagentResult(
2371
+ event,
2372
+ ctx,
2373
+ result,
2374
+ hookMetadata
2375
+ );
2376
+ if (!subagent) {
2377
+ return;
2378
+ }
2379
+ const isError = event.data.status === "failed" || result.isError === true || event.data.error !== void 0;
2380
+ subagent.span.log({
2381
+ ...isError ? {
2382
+ error: actionResultError(event.data.error, result.output)
2383
+ } : {},
2384
+ metadata: subagent.metadata,
2385
+ output: result.output
2386
+ });
2387
+ const endTime = eventTime(event);
2388
+ subagent.span.end(endTime === void 0 ? void 0 : { endTime });
2389
+ this.toolsByCallKey.delete(key);
2390
+ this.completedToolKeys.set(key, true);
2391
+ }
2392
+ handleStepCompleted(event, ctx) {
2393
+ const step = this.stepForEvent(event, ctx);
2394
+ if (!step) {
2395
+ return;
2396
+ }
2397
+ const usage = event.data.usage;
2398
+ const inputTokens = typeof usage?.inputTokens === "number" && Number.isFinite(usage.inputTokens) && usage.inputTokens >= 0 ? usage.inputTokens : void 0;
2399
+ const outputTokens = typeof usage?.outputTokens === "number" && Number.isFinite(usage.outputTokens) && usage.outputTokens >= 0 ? usage.outputTokens : void 0;
2400
+ const cacheReadTokens = typeof usage?.cacheReadTokens === "number" && Number.isFinite(usage.cacheReadTokens) && usage.cacheReadTokens >= 0 ? usage.cacheReadTokens : void 0;
2401
+ const cacheWriteTokens = typeof usage?.cacheWriteTokens === "number" && Number.isFinite(usage.cacheWriteTokens) && usage.cacheWriteTokens >= 0 ? usage.cacheWriteTokens : void 0;
2402
+ const costUsd = typeof usage?.costUsd === "number" && Number.isFinite(usage.costUsd) && usage.costUsd >= 0 ? usage.costUsd : void 0;
2403
+ const total = inputTokens !== void 0 && outputTokens !== void 0 ? inputTokens + outputTokens : void 0;
2404
+ const metrics = {
2405
+ ...inputTokens !== void 0 ? { prompt_tokens: inputTokens } : {},
2406
+ ...outputTokens !== void 0 ? { completion_tokens: outputTokens } : {},
2407
+ ...total !== void 0 ? { tokens: total } : {},
2408
+ ...cacheReadTokens !== void 0 ? { prompt_cached_tokens: cacheReadTokens } : {},
2409
+ ...cacheWriteTokens !== void 0 ? { prompt_cache_creation_tokens: cacheWriteTokens } : {},
2410
+ ...costUsd !== void 0 ? { estimated_cost: costUsd } : {}
2411
+ };
2412
+ step.metrics = { ...step.metrics, ...metrics };
2413
+ if (Array.isArray(step.output) && isObject(step.output[0])) {
2414
+ const finishReason = step.output[0].finish_reason;
2415
+ if (typeof finishReason !== "string") {
2416
+ step.output[0].finish_reason = normalizedFinishReason(
2417
+ event.data.finishReason
2418
+ );
2419
+ }
2420
+ }
2421
+ step.span.log({
2422
+ ...step.input !== void 0 ? { input: step.input } : {},
2423
+ metadata: step.metadata,
2424
+ metrics,
2425
+ output: step.output
2426
+ });
2427
+ const endTime = eventTime(event);
2428
+ step.span.end(endTime === void 0 ? void 0 : { endTime });
2429
+ const turn = this.turnForEvent(event, ctx);
2430
+ if (turn) {
2431
+ for (const [key, value] of Object.entries(metrics)) {
2432
+ turn.metrics[key] = (turn.metrics[key] ?? 0) + value;
2433
+ }
2434
+ turn.stepsByIndex.delete(event.data.stepIndex);
2435
+ }
2436
+ this.markStepEnded(event.data.turnId, event.data.stepIndex);
2437
+ }
2438
+ handleStepFailed(event, ctx) {
2439
+ const step = this.stepForEvent(event, ctx);
2440
+ if (step) {
2441
+ step.span.log({
2442
+ error: errorFromMessage(
2443
+ event.data.message,
2444
+ event.data.code,
2445
+ event.data.details
2446
+ )
2447
+ });
2448
+ const endTime = eventTime(event);
2449
+ step.span.end(endTime === void 0 ? void 0 : { endTime });
2450
+ }
2451
+ const turn = this.turnForEvent(event, ctx);
2452
+ turn?.stepsByIndex.delete(event.data.stepIndex);
2453
+ this.markStepEnded(event.data.turnId, event.data.stepIndex);
2454
+ }
2455
+ handleTurnCompleted(event, ctx) {
2456
+ const turn = this.turnForEvent(event, ctx);
2457
+ if (!turn) {
2458
+ return;
2459
+ }
2460
+ this.finalizeTurn(turn, {
2461
+ endTime: eventTime(event)
2462
+ });
2463
+ }
2464
+ handleTurnFailed(event, ctx) {
2465
+ const turn = this.turnForEvent(event, ctx);
2466
+ if (!turn) {
2467
+ return;
2468
+ }
2469
+ this.finalizeTurn(turn, {
2470
+ endTime: eventTime(event),
2471
+ error: errorFromMessage(
2472
+ event.data.message,
2473
+ event.data.code,
2474
+ event.data.details
2475
+ )
2476
+ });
2477
+ }
2478
+ async handleSessionFailed(event, ctx) {
2479
+ const sessionId = event.data.sessionId || sessionIdFromContext(ctx);
2480
+ if (!sessionId) {
2481
+ return;
2482
+ }
2483
+ const session = await this.ensureSession(
2484
+ sessionId,
2485
+ ctx,
2486
+ {},
2487
+ eventTime(event)
2488
+ );
2489
+ const error = errorFromMessage(
2490
+ event.data.message,
2491
+ event.data.code,
2492
+ event.data.details
2493
+ );
2494
+ for (const [key, turn] of this.turnsByKey) {
2495
+ if (!key.startsWith(`${sessionId}:`)) {
2496
+ continue;
2497
+ }
2498
+ this.finalizeTurn(turn, {
2499
+ endTime: eventTime(event),
2500
+ error
2501
+ });
2502
+ }
2503
+ for (const [key, tool] of this.toolsByCallKey) {
2504
+ if (key.startsWith(`${sessionId}:`)) {
2505
+ const endTime2 = eventTime(event);
2506
+ if (!tool.endedByTurn) {
2507
+ tool.span.log({ metadata: tool.metadata });
2508
+ tool.span.end(endTime2 === void 0 ? void 0 : { endTime: endTime2 });
2509
+ tool.endedByTurn = true;
2510
+ }
2511
+ }
2512
+ }
2513
+ session.span.log({ error });
2514
+ const endTime = eventTime(event);
2515
+ session.span.end(endTime === void 0 ? void 0 : { endTime });
2516
+ }
2517
+ async handleSessionCompleted(event, ctx) {
2518
+ const sessionId = sessionIdFromContext(ctx);
2519
+ if (!sessionId) {
2520
+ return;
2521
+ }
2522
+ const session = await this.ensureSession(
2523
+ sessionId,
2524
+ ctx,
2525
+ {},
2526
+ eventTime(event)
2527
+ );
2528
+ for (const [key, turn] of this.turnsByKey) {
2529
+ if (!key.startsWith(`${sessionId}:`)) {
2530
+ continue;
2531
+ }
2532
+ this.finalizeTurn(turn, {
2533
+ endTime: eventTime(event)
2534
+ });
2535
+ }
2536
+ for (const [key, tool] of this.toolsByCallKey) {
2537
+ if (key.startsWith(`${sessionId}:`) && !tool.endedByTurn) {
2538
+ const endTime2 = eventTime(event);
2539
+ tool.span.log({ metadata: tool.metadata });
2540
+ tool.span.end(endTime2 === void 0 ? void 0 : { endTime: endTime2 });
2541
+ tool.endedByTurn = true;
2542
+ }
2543
+ }
2544
+ session.span.log({ metadata: session.metadata });
2545
+ const endTime = eventTime(event);
2546
+ session.span.end(endTime === void 0 ? void 0 : { endTime });
2547
+ }
2548
+ async ensureSession(sessionId, ctx, metadata, startTime) {
2549
+ metadata = {
2550
+ ...readEveTraceState(this.state).metadata,
2551
+ ...metadata
2552
+ };
2553
+ const existing = this.sessionsById.get(sessionId);
2554
+ if (existing) {
2555
+ existing.metadata = { ...existing.metadata, ...metadata };
2556
+ existing.span.log({ metadata: existing.metadata });
2557
+ return existing;
2558
+ }
2559
+ const lineage = parentLineageFromContext(ctx);
2560
+ const parentSubagent = lineage ? this.toolsByCallKey.get(toolKey(lineage.sessionId, lineage.callId)) : void 0;
2561
+ const activeParent = currentSpan();
2562
+ const [
2563
+ { rowId: eventId, spanId },
2564
+ parentSubagentSpanId,
2565
+ fallbackRootSpanId
2566
+ ] = await Promise.all([
2567
+ generateEveIds("session", sessionId),
2568
+ lineage ? spanIdForSubagent(lineage.sessionId, lineage.callId) : Promise.resolve(void 0),
2569
+ lineage ? rootSpanIdForSession(lineage.rootSessionId) : rootSpanIdForSession(sessionId)
2570
+ ]);
2571
+ const span = await this.startEveSpan({
2572
+ event: {
2573
+ id: eventId,
2574
+ metadata
2575
+ },
2576
+ name: "eve.session",
2577
+ parentSpanIds: lineage && parentSubagentSpanId ? {
2578
+ rootSpanId: parentSubagent?.span.rootSpanId ?? fallbackRootSpanId,
2579
+ spanId: parentSubagentSpanId
2580
+ } : !Object.is(activeParent, NOOP_SPAN) ? {
2581
+ rootSpanId: activeParent.rootSpanId,
2582
+ spanId: activeParent.spanId
2583
+ } : {
2584
+ parentSpanIds: [],
2585
+ rootSpanId: fallbackRootSpanId
2586
+ },
2587
+ spanAttributes: { type: "task" /* TASK */ },
2588
+ spanId,
2589
+ startTime
2590
+ });
2591
+ span.log({ metadata });
2592
+ const session = { metadata, sessionId, span };
2593
+ this.sessionsById.set(sessionId, session);
2594
+ return session;
2595
+ }
2596
+ async ensureTurn(event, ctx, hookMetadata) {
2597
+ const sessionId = sessionIdFromContext(ctx);
2598
+ if (!sessionId) {
2599
+ return void 0;
2600
+ }
2601
+ const session = await this.ensureSession(
2602
+ sessionId,
2603
+ ctx,
2604
+ hookMetadata ?? {},
2605
+ eventTime(event)
2606
+ );
2607
+ const key = turnKey(sessionId, event.data.turnId);
2608
+ const existing = this.turnsByKey.get(key);
2609
+ if (existing) {
2610
+ return existing;
2611
+ }
2612
+ const metadata = { ...session.metadata };
2613
+ const span = await this.startTurnSpan(session, event, metadata);
2614
+ span.log({ metadata });
2615
+ const state = {
2616
+ key,
2617
+ metadata,
2618
+ metrics: {},
2619
+ span,
2620
+ stepsByIndex: /* @__PURE__ */ new Map(),
2621
+ turnId: event.data.turnId
2622
+ };
2623
+ this.turnsByKey.set(key, state);
2624
+ return state;
2625
+ }
2626
+ async startRequestedTool(event, turn, sessionId, action) {
2627
+ const key = toolKey(sessionId, action.callId);
2628
+ if (this.toolsByCallKey.has(key) || this.completedToolKeys.has(key)) {
2629
+ return;
2630
+ }
2631
+ const metadata = toolMetadataFromTurn(turn);
2632
+ const { rowId: eventId, spanId } = await generateEveIds(
2633
+ "tool",
2634
+ sessionId,
2635
+ event.data.turnId,
2636
+ action.callId
2637
+ );
2638
+ if (this.toolsByCallKey.has(key) || this.completedToolKeys.has(key)) {
2639
+ return;
2640
+ }
2641
+ const span = await this.startEveChildSpan(turn.span, {
2642
+ event: {
2643
+ id: eventId,
2644
+ input: action.input,
2645
+ metadata
2646
+ },
2647
+ name: action.toolName,
2648
+ spanAttributes: { type: "tool" /* TOOL */ },
2649
+ spanId,
2650
+ startTime: eventTime(event)
2651
+ });
2652
+ span.log({ input: action.input, metadata });
2653
+ this.toolsByCallKey.set(key, {
2654
+ metadata,
2655
+ span,
2656
+ turnKey: turnKey(sessionId, event.data.turnId)
2657
+ });
2658
+ }
2659
+ async startRequestedSubagent(event, turn, sessionId, action) {
2660
+ const key = toolKey(sessionId, action.callId);
2661
+ if (this.toolsByCallKey.has(key) || this.completedToolKeys.has(key)) {
2662
+ return;
2663
+ }
2664
+ const name = action.subagentName ?? action.name ?? "agent";
2665
+ const metadata = toolMetadataFromTurn(turn);
2666
+ const { rowId: eventId, spanId } = await generateEveIds(
2667
+ "subagent",
2668
+ sessionId,
2669
+ action.callId
2670
+ );
2671
+ if (this.toolsByCallKey.has(key) || this.completedToolKeys.has(key)) {
2672
+ return;
2673
+ }
2674
+ const span = await this.startEveChildSpan(turn.span, {
2675
+ event: {
2676
+ id: eventId,
2677
+ input: action.input,
2678
+ metadata
2679
+ },
2680
+ name,
2681
+ spanAttributes: { type: "tool" /* TOOL */ },
2682
+ spanId,
2683
+ startTime: eventTime(event)
2684
+ });
2685
+ span.log({ input: action.input, metadata });
2686
+ this.toolsByCallKey.set(key, {
2687
+ metadata,
2688
+ span,
2689
+ turnKey: turnKey(sessionId, event.data.turnId)
2690
+ });
2691
+ }
2692
+ async startSyntheticTool(event, ctx, result, hookMetadata) {
2693
+ const turn = await this.ensureTurn(event, ctx, hookMetadata);
2694
+ const sessionId = sessionIdFromContext(ctx);
2695
+ if (!turn || !sessionId) {
2696
+ return void 0;
2697
+ }
2698
+ const metadata = toolMetadataFromTurn(turn);
2699
+ const { rowId: eventId, spanId } = await generateEveIds(
2700
+ "tool",
2701
+ sessionId,
2702
+ event.data.turnId,
2703
+ result.callId
2704
+ );
2705
+ const existing = this.toolsByCallKey.get(toolKey(sessionId, result.callId));
2706
+ if (existing) {
2707
+ return existing;
2708
+ }
2709
+ const span = await this.startEveChildSpan(turn.span, {
2710
+ event: {
2711
+ id: eventId,
2712
+ metadata
2713
+ },
2714
+ name: result.toolName,
2715
+ spanAttributes: { type: "tool" /* TOOL */ },
2716
+ spanId,
2717
+ startTime: eventTime(event)
2718
+ });
2719
+ span.log({ metadata });
2720
+ const state = {
2721
+ metadata,
2722
+ span,
2723
+ turnKey: turnKey(sessionId, event.data.turnId)
2724
+ };
2725
+ this.toolsByCallKey.set(toolKey(sessionId, result.callId), state);
2726
+ return state;
2727
+ }
2728
+ async startSyntheticSubagent(event, ctx, hookMetadata) {
2729
+ const turn = await this.ensureTurn(event, ctx, hookMetadata);
2730
+ const sessionId = sessionIdFromContext(ctx);
2731
+ if (!turn || !sessionId) {
2732
+ return void 0;
2733
+ }
2734
+ const metadata = toolMetadataFromTurn(turn);
2735
+ const { rowId: eventId, spanId } = await generateEveIds(
2736
+ "subagent",
2737
+ sessionId,
2738
+ event.data.callId
2739
+ );
2740
+ const existing = this.toolsByCallKey.get(
2741
+ toolKey(sessionId, event.data.callId)
2742
+ );
2743
+ if (existing) {
2744
+ return existing;
2745
+ }
2746
+ const span = await this.startEveChildSpan(turn.span, {
2747
+ event: {
2748
+ id: eventId,
2749
+ metadata
2750
+ },
2751
+ name: event.data.subagentName,
2752
+ spanAttributes: { type: "tool" /* TOOL */ },
2753
+ spanId,
2754
+ startTime: eventTime(event)
2755
+ });
2756
+ span.log({ metadata });
2757
+ const state = {
2758
+ metadata,
2759
+ span,
2760
+ turnKey: turnKey(sessionId, event.data.turnId)
2761
+ };
2762
+ this.toolsByCallKey.set(toolKey(sessionId, event.data.callId), state);
2763
+ return state;
2764
+ }
2765
+ async startSyntheticSubagentResult(event, ctx, result, hookMetadata) {
2766
+ const turn = await this.ensureTurn(event, ctx, hookMetadata);
2767
+ const sessionId = sessionIdFromContext(ctx);
2768
+ if (!turn || !sessionId) {
2769
+ return void 0;
2770
+ }
2771
+ const metadata = toolMetadataFromTurn(turn);
2772
+ const { rowId: eventId, spanId } = await generateEveIds(
2773
+ "subagent",
2774
+ sessionId,
2775
+ result.callId
2776
+ );
2777
+ const existing = this.toolsByCallKey.get(toolKey(sessionId, result.callId));
2778
+ if (existing) {
2779
+ return existing;
2780
+ }
2781
+ const span = await this.startEveChildSpan(turn.span, {
2782
+ event: {
2783
+ id: eventId,
2784
+ metadata
2785
+ },
2786
+ name: result.subagentName,
2787
+ spanAttributes: { type: "tool" /* TOOL */ },
2788
+ spanId,
2789
+ startTime: eventTime(event)
2790
+ });
2791
+ span.log({ metadata });
2792
+ const state = {
2793
+ metadata,
2794
+ span,
2795
+ turnKey: turnKey(sessionId, event.data.turnId)
2796
+ };
2797
+ this.toolsByCallKey.set(toolKey(sessionId, result.callId), state);
2798
+ return state;
2799
+ }
2800
+ async startTurnSpan(session, event, metadata) {
2801
+ const { rowId: eventId, spanId } = await generateEveIds(
2802
+ "turn",
2803
+ session.sessionId,
2804
+ event.data.turnId
2805
+ );
2806
+ return await this.startEveSpan({
2807
+ event: {
2808
+ id: eventId,
2809
+ metadata
2810
+ },
2811
+ name: "eve.turn",
2812
+ parentSpanIds: {
2813
+ rootSpanId: session.span.rootSpanId,
2814
+ spanId: session.span.spanId
2815
+ },
2816
+ spanAttributes: { type: "task" /* TASK */ },
2817
+ spanId,
2818
+ startTime: eventTime(event)
2819
+ });
2820
+ }
2821
+ turnForEvent(event, ctx) {
2822
+ const sessionId = sessionIdFromContext(ctx);
2823
+ return sessionId ? this.turnsByKey.get(turnKey(sessionId, event.data.turnId)) : void 0;
2824
+ }
2825
+ stepForEvent(event, ctx) {
2826
+ return this.turnForEvent(event, ctx)?.stepsByIndex.get(
2827
+ event.data.stepIndex
2828
+ );
2829
+ }
2830
+ finalizeTurn(turn, args) {
2831
+ const { endTime } = args;
2832
+ for (const step of turn.stepsByIndex.values()) {
2833
+ step.span.log({
2834
+ ...step.input !== void 0 ? { input: step.input } : {},
2835
+ metadata: step.metadata,
2836
+ metrics: step.metrics,
2837
+ output: step.output
2838
+ });
2839
+ step.span.end(endTime === void 0 ? void 0 : { endTime });
2840
+ }
2841
+ turn.stepsByIndex.clear();
2842
+ for (const tool of this.toolsByCallKey.values()) {
2843
+ if (tool.turnKey !== turn.key) {
2844
+ continue;
2845
+ }
2846
+ if (tool.endedByTurn) {
2847
+ continue;
2848
+ }
2849
+ tool.span.log({ metadata: tool.metadata });
2850
+ tool.span.end(endTime === void 0 ? void 0 : { endTime });
2851
+ tool.endedByTurn = true;
2852
+ }
2853
+ if (args.error) {
2854
+ turn.span.log({ error: args.error });
2855
+ } else {
2856
+ turn.span.log({
2857
+ metadata: turn.metadata,
2858
+ metrics: turn.metrics,
2859
+ output: turn.output
2860
+ });
2861
+ }
2862
+ turn.span.end(endTime === void 0 ? void 0 : { endTime });
2863
+ this.turnsByKey.delete(turn.key);
2864
+ this.state.update((current) => {
2865
+ const normalized = normalizeEveTraceState(current);
2866
+ return {
2867
+ ...normalized,
2868
+ stepStarts: normalized.stepStarts.filter(
2869
+ (entry) => entry.turnId !== turn.turnId
2870
+ )
2871
+ };
2872
+ });
2873
+ }
2874
+ cleanupSession(sessionId) {
2875
+ const keyPrefix = `${sessionId}:`;
2876
+ this.sessionsById.delete(sessionId);
2877
+ for (const key of this.turnsByKey.keys()) {
2878
+ if (key.startsWith(keyPrefix)) {
2879
+ this.turnsByKey.delete(key);
2880
+ }
2881
+ }
2882
+ for (const key of this.toolsByCallKey.keys()) {
2883
+ if (key.startsWith(keyPrefix)) {
2884
+ this.toolsByCallKey.delete(key);
2885
+ }
2886
+ }
2887
+ for (const key of this.completedToolKeys.keys()) {
2888
+ if (key.startsWith(keyPrefix)) {
2889
+ this.completedToolKeys.delete(key);
2890
+ }
2891
+ }
2892
+ this.state.update(() => emptyEveTraceState());
2893
+ }
2894
+ async flushInstrumentation() {
2895
+ try {
2896
+ await flush();
2897
+ return true;
2898
+ } catch (error) {
2899
+ debugLogger.warn("Error in Eve flush instrumentation:", error);
2900
+ return false;
2901
+ }
2902
+ }
2903
+ };
2904
+ function emptyEveTraceState() {
2905
+ return {
2906
+ llmInputs: [],
2907
+ metadata: {},
2908
+ spanReferences: [],
2909
+ stepStarts: []
2910
+ };
2911
+ }
2912
+ function normalizeEveTraceState(state) {
2913
+ if (!isObject(state)) {
2914
+ return emptyEveTraceState();
2915
+ }
2916
+ const metadata = isObject(state["metadata"]) ? state["metadata"] : {};
2917
+ const spanReferences = Array.isArray(state["spanReferences"]) ? state["spanReferences"].flatMap((entry) => {
2918
+ if (!isObject(entry)) {
2919
+ return [];
2920
+ }
2921
+ const exported = entry["exported"];
2922
+ const endTime = entry["endTime"];
2923
+ const rootSpanId = entry["rootSpanId"];
2924
+ const rowId = entry["rowId"];
2925
+ const spanId = entry["spanId"];
2926
+ const startEvent = entry["startEvent"];
2927
+ const startEventCreated = isObject(startEvent) ? startEvent["created"] : void 0;
2928
+ const startEventMetrics = isObject(startEvent) ? startEvent["metrics"] : void 0;
2929
+ const startEventSpanAttributes = isObject(startEvent) ? startEvent["span_attributes"] : void 0;
2930
+ const startEventSpanParents = isObject(startEvent) ? startEvent["span_parents"] : void 0;
2931
+ const normalizedStartEvent = typeof startEventCreated === "string" && isObject(startEventMetrics) && typeof startEventMetrics["start"] === "number" && Number.isFinite(startEventMetrics["start"]) && isObject(startEventSpanAttributes) && Array.isArray(startEventSpanParents) && startEventSpanParents.every(
2932
+ (parent) => typeof parent === "string"
2933
+ ) ? {
2934
+ created: startEventCreated,
2935
+ metrics: { start: startEventMetrics["start"] },
2936
+ span_attributes: { ...startEventSpanAttributes },
2937
+ span_parents: [...startEventSpanParents]
2938
+ } : void 0;
2939
+ return typeof exported === "string" && typeof rootSpanId === "string" && typeof rowId === "string" && typeof spanId === "string" ? [
2940
+ {
2941
+ ...typeof endTime === "number" && Number.isFinite(endTime) ? { endTime } : {},
2942
+ exported,
2943
+ rootSpanId,
2944
+ rowId,
2945
+ spanId,
2946
+ ...normalizedStartEvent ? { startEvent: normalizedStartEvent } : {}
2947
+ }
2948
+ ] : [];
2949
+ }).slice(-MAX_STORED_SPAN_REFERENCES) : [];
2950
+ const llmInputs = Array.isArray(state["llmInputs"]) ? state["llmInputs"].flatMap((entry) => {
2951
+ if (!isObject(entry)) {
2952
+ return [];
2953
+ }
2954
+ const key = entry["key"];
2955
+ const input = entry["input"];
2956
+ return typeof key === "string" && isCapturedModelInput(input) ? [{ input, key }] : [];
2957
+ }).slice(-MAX_STORED_LLM_INPUTS) : [];
2958
+ const stepStarts = Array.isArray(state["stepStarts"]) ? state["stepStarts"].flatMap((entry) => {
2959
+ if (!isObject(entry)) {
2960
+ return [];
2961
+ }
2962
+ const ordinal = entry["ordinal"];
2963
+ const open = entry["open"];
2964
+ const stepIndex = entry["stepIndex"];
2965
+ const turnId = entry["turnId"];
2966
+ return typeof ordinal === "number" && Number.isInteger(ordinal) && ordinal >= 0 && typeof open === "boolean" && typeof stepIndex === "number" && Number.isInteger(stepIndex) && typeof turnId === "string" ? [{ open, ordinal, stepIndex, turnId }] : [];
2967
+ }).slice(-MAX_STORED_STEP_STARTS) : [];
2968
+ return { llmInputs, metadata: { ...metadata }, spanReferences, stepStarts };
2969
+ }
2970
+ function readEveTraceState(state) {
2971
+ try {
2972
+ return normalizeEveTraceState(state.get());
2973
+ } catch {
2974
+ return emptyEveTraceState();
2975
+ }
2976
+ }
2977
+ function captureEveModelInput(state, input) {
2978
+ if (!isObject(input)) {
2979
+ return;
2980
+ }
2981
+ const session = input["session"];
2982
+ const turn = input["turn"];
2983
+ const step = input["step"];
2984
+ if (!isObject(session) || !isObject(turn) || !isObject(step)) {
2985
+ return;
2986
+ }
2987
+ const sessionId = session["id"];
2988
+ const turnId = turn["id"];
2989
+ const stepIndex = step["index"];
2990
+ if (typeof sessionId !== "string" || typeof turnId !== "string" || typeof stepIndex !== "number" || !Number.isInteger(stepIndex)) {
2991
+ return;
2992
+ }
2993
+ const captured = capturedModelInput(input["modelInput"]);
2994
+ if (!captured) {
2995
+ return;
2996
+ }
2997
+ const key = llmInputKey(sessionId, turnId, stepIndex);
2998
+ state.update((current) => {
2999
+ const normalized = normalizeEveTraceState(current);
3000
+ const llmInputs = [...normalized.llmInputs, { input: captured, key }];
3001
+ return {
3002
+ ...normalized,
3003
+ llmInputs: llmInputs.slice(-MAX_STORED_LLM_INPUTS)
3004
+ };
3005
+ });
3006
+ }
3007
+ function consumeCapturedEveModelInput(state, sessionId, turnId, stepIndex) {
3008
+ try {
3009
+ const key = llmInputKey(sessionId, turnId, stepIndex);
3010
+ let input;
3011
+ state.update((current) => {
3012
+ const normalized = normalizeEveTraceState(current);
3013
+ const index = normalized.llmInputs.findIndex(
3014
+ (candidate) => candidate.key === key
3015
+ );
3016
+ if (index < 0) {
3017
+ return normalized;
3018
+ }
3019
+ input = normalized.llmInputs[index]?.input;
3020
+ return {
3021
+ ...normalized,
3022
+ llmInputs: normalized.llmInputs.filter(
3023
+ (_, candidateIndex) => candidateIndex !== index
3024
+ )
3025
+ };
3026
+ });
3027
+ return input;
3028
+ } catch (error) {
3029
+ debugLogger.warn("Error in Eve LLM input consumption:", error);
3030
+ return void 0;
3031
+ }
3032
+ }
3033
+ function capturedModelInput(modelInput) {
3034
+ if (!isObject(modelInput)) {
3035
+ return void 0;
3036
+ }
3037
+ const messages = modelInput["messages"];
3038
+ if (!Array.isArray(messages)) {
3039
+ return void 0;
3040
+ }
3041
+ const instructions = modelInput["instructions"];
3042
+ const value = [
3043
+ ...instructions !== void 0 ? [{ content: instructions, role: "system" }] : [],
3044
+ ...messages
3045
+ ];
3046
+ try {
3047
+ const cloned = JSON.parse(JSON.stringify(value));
3048
+ if (!Array.isArray(cloned)) {
3049
+ return void 0;
3050
+ }
3051
+ return cloned;
3052
+ } catch {
3053
+ return void 0;
3054
+ }
3055
+ }
3056
+ function isCapturedModelInput(input) {
3057
+ return Array.isArray(input);
3058
+ }
3059
+ function llmInputKey(sessionId, turnId, stepIndex) {
3060
+ return `${sessionId}\0${turnId}\0${stepIndex}`;
3061
+ }
3062
+ function modelMetadataFromRuntime(runtime) {
3063
+ if (!isObject(runtime)) {
3064
+ return {};
3065
+ }
3066
+ const modelId = runtime["modelId"];
3067
+ return typeof modelId === "string" ? modelMetadataFromModelId(modelId) : {};
3068
+ }
3069
+ function modelMetadataFromModelId(modelId) {
3070
+ const normalized = modelId.trim();
3071
+ if (!normalized) {
3072
+ return {};
3073
+ }
3074
+ const slashIndex = normalized.indexOf("/");
3075
+ if (slashIndex > 0 && slashIndex < normalized.length - 1) {
3076
+ return {
3077
+ model: normalized.slice(slashIndex + 1),
3078
+ provider: normalized.slice(0, slashIndex)
3079
+ };
3080
+ }
3081
+ return {
3082
+ model: normalized
3083
+ };
3084
+ }
3085
+ function sessionIdFromContext(ctx) {
3086
+ if (!isObject(ctx)) {
3087
+ return void 0;
3088
+ }
3089
+ const session = ctx["session"];
3090
+ if (!isObject(session)) {
3091
+ return void 0;
3092
+ }
3093
+ const id = session["id"];
3094
+ return typeof id === "string" ? id : void 0;
3095
+ }
3096
+ function toolMetadataFromTurn(turn) {
3097
+ const { model: _model, provider: _provider, ...metadata } = turn.metadata;
3098
+ return metadata;
3099
+ }
3100
+ function parentLineageFromContext(ctx) {
3101
+ if (!isObject(ctx)) {
3102
+ return void 0;
3103
+ }
3104
+ const session = ctx.session;
3105
+ if (!isObject(session)) {
3106
+ return void 0;
3107
+ }
3108
+ const parent = session["parent"];
3109
+ if (!isObject(parent)) {
3110
+ return void 0;
3111
+ }
3112
+ const callId = parent["callId"];
3113
+ const rootSessionId = parent["rootSessionId"];
3114
+ const sessionId = parent["sessionId"];
3115
+ if (typeof callId !== "string" || typeof rootSessionId !== "string" || typeof sessionId !== "string") {
3116
+ return void 0;
3117
+ }
3118
+ return { callId, rootSessionId, sessionId };
3119
+ }
3120
+ function isToolCallAction(action) {
3121
+ return isObject(action) && action["kind"] === "tool-call" && typeof action["callId"] === "string" && typeof action["toolName"] === "string" && isObject(action["input"]);
3122
+ }
3123
+ function isLocalSubagentCallAction(action) {
3124
+ return isObject(action) && action["kind"] === "subagent-call" && typeof action["callId"] === "string" && isObject(action["input"]);
3125
+ }
3126
+ function isTraceableActionRequest(action) {
3127
+ return isToolCallAction(action) || isLocalSubagentCallAction(action);
3128
+ }
3129
+ function isToolResult(result) {
3130
+ return isObject(result) && result["kind"] === "tool-result" && typeof result["callId"] === "string" && typeof result["toolName"] === "string";
3131
+ }
3132
+ function isSubagentResult(result) {
3133
+ return isObject(result) && result["kind"] === "subagent-result" && typeof result["callId"] === "string" && typeof result["subagentName"] === "string";
3134
+ }
3135
+ function normalizedFinishReason(finishReason) {
3136
+ switch (finishReason) {
3137
+ case "content-filter":
3138
+ return "content_filter";
3139
+ case "tool-calls":
3140
+ return "tool_calls";
3141
+ default:
3142
+ return finishReason;
3143
+ }
3144
+ }
3145
+ function errorFromMessage(message, code, details) {
3146
+ const error = new Error(`${code}: ${message}`);
3147
+ if (details !== void 0) {
3148
+ error.cause = details;
3149
+ }
3150
+ return error;
3151
+ }
3152
+ function actionResultError(error, output) {
3153
+ if (error) {
3154
+ return errorFromMessage(error.message, error.code);
3155
+ }
3156
+ const result = new Error("Eve action failed");
3157
+ if (output !== void 0) {
3158
+ result.cause = output;
3159
+ }
3160
+ return result;
3161
+ }
3162
+ function eventTime(event) {
3163
+ if (!event.meta?.at) {
3164
+ return void 0;
3165
+ }
3166
+ const timestamp = Date.parse(event.meta.at);
3167
+ return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
3168
+ }
3169
+ function turnKey(sessionId, turnId) {
3170
+ return `${sessionId}:${turnId}`;
3171
+ }
3172
+ function toolKey(sessionId, callId) {
3173
+ return `${sessionId}:${callId}`;
3174
+ }
3175
+ async function rootSpanIdForSession(sessionId) {
3176
+ return deterministicEveId("eve:root", sessionId);
3177
+ }
3178
+ async function generateEveIds(kind, ...parts) {
3179
+ const [rowId, spanId] = await Promise.all([
3180
+ deterministicEveId(`eve:row:${kind}`, ...parts),
3181
+ deterministicEveId(`eve:${kind}`, ...parts)
3182
+ ]);
3183
+ return { rowId, spanId };
3184
+ }
3185
+ async function spanIdForSubagent(sessionId, callId) {
3186
+ return deterministicEveId("eve:subagent", sessionId, callId);
3187
+ }
3188
+ async function deterministicEveId(...parts) {
3189
+ const data = new TextEncoder().encode(
3190
+ parts.map((part) => `${part.length}:${part}`).join("\0")
3191
+ );
3192
+ const digest = await globalThis.crypto.subtle.digest("SHA-256", data);
3193
+ const bytes = Array.from(new Uint8Array(digest, 0, 16));
3194
+ const hex = bytes.map((byte) => byte.toString(16).padStart(2, "0")).join("");
3195
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
3196
+ }
3197
+
1731
3198
  // src/typed-instrumentation-helpers.ts
1732
3199
  var TypedApplyProxy = Proxy;
1733
3200
 
@@ -8058,6 +9525,8 @@ export {
8058
9525
  addAzureBlobHeaders,
8059
9526
  agentAssertionScorer,
8060
9527
  braintrustAISDKTelemetry,
9528
+ braintrustEveHook,
9529
+ braintrustEveInstrumentation,
8061
9530
  braintrustFlueInstrumentation,
8062
9531
  braintrustFlueObserver,
8063
9532
  braintrustStreamChunkSchema,