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/README.md +4 -0
- package/dev/dist/index.d.mts +1029 -0
- package/dev/dist/index.d.ts +1029 -0
- package/dev/dist/index.js +75 -11
- package/dev/dist/index.mjs +75 -11
- package/dist/auto-instrumentations/hook.mjs +75 -11
- package/dist/browser.d.mts +3274 -92
- package/dist/browser.d.ts +3274 -92
- package/dist/browser.js +1548 -11
- package/dist/browser.mjs +1548 -11
- package/dist/{chunk-FY7DAKA5.js → chunk-MWVVR5LR.js} +84 -12
- package/dist/{chunk-O2P765XK.mjs → chunk-ZG2O3XVF.mjs} +83 -11
- package/dist/cli.js +80 -13
- package/dist/edge-light.d.mts +1 -1
- package/dist/edge-light.d.ts +1 -1
- package/dist/edge-light.js +1548 -11
- package/dist/edge-light.mjs +1548 -11
- package/dist/index.d.mts +3274 -92
- package/dist/index.d.ts +3274 -92
- package/dist/index.js +1780 -311
- package/dist/index.mjs +1470 -1
- package/dist/instrumentation/index.d.mts +919 -1
- package/dist/instrumentation/index.d.ts +919 -1
- package/dist/instrumentation/index.js +1563 -10
- package/dist/instrumentation/index.mjs +1561 -10
- package/dist/vitest-evals-reporter.js +15 -15
- package/dist/vitest-evals-reporter.mjs +1 -1
- package/dist/workerd.d.mts +1 -1
- package/dist/workerd.d.ts +1 -1
- package/dist/workerd.js +1548 -11
- package/dist/workerd.mjs +1548 -11
- package/package.json +5 -2
|
@@ -33,6 +33,8 @@ __export(index_exports, {
|
|
|
33
33
|
BasePlugin: () => BasePlugin,
|
|
34
34
|
BraintrustPlugin: () => BraintrustPlugin,
|
|
35
35
|
OpenAIAgentsTraceProcessor: () => OpenAIAgentsTraceProcessor,
|
|
36
|
+
braintrustEveHook: () => braintrustEveHook,
|
|
37
|
+
braintrustEveInstrumentation: () => braintrustEveInstrumentation,
|
|
36
38
|
braintrustFlueInstrumentation: () => braintrustFlueInstrumentation,
|
|
37
39
|
braintrustFlueObserver: () => braintrustFlueObserver,
|
|
38
40
|
configureInstrumentation: () => configureInstrumentation,
|
|
@@ -2316,19 +2318,30 @@ var CallEvent = import_v36.z.union([
|
|
|
2316
2318
|
var ChatCompletionContentPartTextWithTitle = import_v36.z.object({
|
|
2317
2319
|
text: import_v36.z.string().default(""),
|
|
2318
2320
|
type: import_v36.z.literal("text"),
|
|
2319
|
-
cache_control: import_v36.z.object({
|
|
2321
|
+
cache_control: import_v36.z.object({
|
|
2322
|
+
type: import_v36.z.literal("ephemeral"),
|
|
2323
|
+
ttl: import_v36.z.enum(["5m", "1h"]).optional()
|
|
2324
|
+
}).optional()
|
|
2320
2325
|
});
|
|
2321
2326
|
var ChatCompletionContentPartImageWithTitle = import_v36.z.object({
|
|
2322
2327
|
image_url: import_v36.z.object({
|
|
2323
2328
|
url: import_v36.z.string(),
|
|
2324
2329
|
detail: import_v36.z.union([import_v36.z.literal("auto"), import_v36.z.literal("low"), import_v36.z.literal("high")]).optional()
|
|
2325
2330
|
}),
|
|
2326
|
-
type: import_v36.z.literal("image_url")
|
|
2331
|
+
type: import_v36.z.literal("image_url"),
|
|
2332
|
+
cache_control: import_v36.z.object({
|
|
2333
|
+
type: import_v36.z.literal("ephemeral"),
|
|
2334
|
+
ttl: import_v36.z.enum(["5m", "1h"]).optional()
|
|
2335
|
+
}).optional()
|
|
2327
2336
|
});
|
|
2328
2337
|
var ChatCompletionContentPartFileFile = import_v36.z.object({ file_data: import_v36.z.string(), filename: import_v36.z.string(), file_id: import_v36.z.string() }).partial();
|
|
2329
2338
|
var ChatCompletionContentPartFileWithTitle = import_v36.z.object({
|
|
2330
2339
|
file: ChatCompletionContentPartFileFile,
|
|
2331
|
-
type: import_v36.z.literal("file")
|
|
2340
|
+
type: import_v36.z.literal("file"),
|
|
2341
|
+
cache_control: import_v36.z.object({
|
|
2342
|
+
type: import_v36.z.literal("ephemeral"),
|
|
2343
|
+
ttl: import_v36.z.enum(["5m", "1h"]).optional()
|
|
2344
|
+
}).optional()
|
|
2332
2345
|
});
|
|
2333
2346
|
var ChatCompletionContentPart = import_v36.z.union([
|
|
2334
2347
|
ChatCompletionContentPartTextWithTitle,
|
|
@@ -2338,7 +2351,10 @@ var ChatCompletionContentPart = import_v36.z.union([
|
|
|
2338
2351
|
var ChatCompletionContentPartText = import_v36.z.object({
|
|
2339
2352
|
text: import_v36.z.string().default(""),
|
|
2340
2353
|
type: import_v36.z.literal("text"),
|
|
2341
|
-
cache_control: import_v36.z.object({
|
|
2354
|
+
cache_control: import_v36.z.object({
|
|
2355
|
+
type: import_v36.z.literal("ephemeral"),
|
|
2356
|
+
ttl: import_v36.z.enum(["5m", "1h"]).optional()
|
|
2357
|
+
}).optional()
|
|
2342
2358
|
});
|
|
2343
2359
|
var ChatCompletionMessageToolCall = import_v36.z.object({
|
|
2344
2360
|
id: import_v36.z.string(),
|
|
@@ -4361,13 +4377,23 @@ var LRUCache = class {
|
|
|
4361
4377
|
* @returns The cached value if found, undefined otherwise.
|
|
4362
4378
|
*/
|
|
4363
4379
|
get(key) {
|
|
4364
|
-
const
|
|
4365
|
-
if (
|
|
4380
|
+
const entry = this.cache.get(key);
|
|
4381
|
+
if (entry === void 0) {
|
|
4366
4382
|
return void 0;
|
|
4367
4383
|
}
|
|
4368
4384
|
this.cache.delete(key);
|
|
4369
|
-
this.cache.set(key,
|
|
4370
|
-
return value;
|
|
4385
|
+
this.cache.set(key, entry);
|
|
4386
|
+
return entry.value;
|
|
4387
|
+
}
|
|
4388
|
+
/**
|
|
4389
|
+
* Checks whether a key exists and marks it as most recently used.
|
|
4390
|
+
*/
|
|
4391
|
+
has(key) {
|
|
4392
|
+
if (!this.cache.has(key)) {
|
|
4393
|
+
return false;
|
|
4394
|
+
}
|
|
4395
|
+
this.get(key);
|
|
4396
|
+
return true;
|
|
4371
4397
|
}
|
|
4372
4398
|
/**
|
|
4373
4399
|
* Stores a value in the cache.
|
|
@@ -4384,7 +4410,38 @@ var LRUCache = class {
|
|
|
4384
4410
|
const first = this.cache.keys().next().value;
|
|
4385
4411
|
this.cache.delete(first);
|
|
4386
4412
|
}
|
|
4387
|
-
this.cache.set(key, value);
|
|
4413
|
+
this.cache.set(key, { value });
|
|
4414
|
+
}
|
|
4415
|
+
/**
|
|
4416
|
+
* Removes an item from the cache.
|
|
4417
|
+
*/
|
|
4418
|
+
delete(key) {
|
|
4419
|
+
return this.cache.delete(key);
|
|
4420
|
+
}
|
|
4421
|
+
/**
|
|
4422
|
+
* Iterates over cache entries from least to most recently used.
|
|
4423
|
+
*/
|
|
4424
|
+
*entries() {
|
|
4425
|
+
for (const [key, entry] of this.cache) {
|
|
4426
|
+
yield [key, entry.value];
|
|
4427
|
+
}
|
|
4428
|
+
}
|
|
4429
|
+
/**
|
|
4430
|
+
* Iterates over cache keys from least to most recently used.
|
|
4431
|
+
*/
|
|
4432
|
+
keys() {
|
|
4433
|
+
return this.cache.keys();
|
|
4434
|
+
}
|
|
4435
|
+
/**
|
|
4436
|
+
* Iterates over cache values from least to most recently used.
|
|
4437
|
+
*/
|
|
4438
|
+
*values() {
|
|
4439
|
+
for (const entry of this.cache.values()) {
|
|
4440
|
+
yield entry.value;
|
|
4441
|
+
}
|
|
4442
|
+
}
|
|
4443
|
+
[Symbol.iterator]() {
|
|
4444
|
+
return this.entries();
|
|
4388
4445
|
}
|
|
4389
4446
|
/**
|
|
4390
4447
|
* Removes all items from the cache.
|
|
@@ -4942,6 +4999,9 @@ function applyMaskingToField(maskingFunction, data, fieldName) {
|
|
|
4942
4999
|
return `ERROR: Failed to mask field '${fieldName}' - ${errorType}`;
|
|
4943
5000
|
}
|
|
4944
5001
|
}
|
|
5002
|
+
var INITIAL_SPAN_WRITE_AS_MERGE = /* @__PURE__ */ Symbol(
|
|
5003
|
+
"braintrust.initial-span-write-as-merge"
|
|
5004
|
+
);
|
|
4945
5005
|
var BRAINTRUST_CURRENT_SPAN_STORE = /* @__PURE__ */ Symbol.for(
|
|
4946
5006
|
"braintrust.currentSpanStore"
|
|
4947
5007
|
);
|
|
@@ -5940,6 +6000,28 @@ function updateSpanImpl({
|
|
|
5940
6000
|
}));
|
|
5941
6001
|
state.bgLogger().log([record]);
|
|
5942
6002
|
}
|
|
6003
|
+
function updateSpan({
|
|
6004
|
+
exported,
|
|
6005
|
+
state,
|
|
6006
|
+
...event
|
|
6007
|
+
}) {
|
|
6008
|
+
const resolvedState = state ?? _globalState;
|
|
6009
|
+
const components = SpanComponentsV4.fromStr(exported);
|
|
6010
|
+
if (!components.data.row_id) {
|
|
6011
|
+
throw new Error("Exported span must have a row id");
|
|
6012
|
+
}
|
|
6013
|
+
updateSpanImpl({
|
|
6014
|
+
state: resolvedState,
|
|
6015
|
+
parentObjectType: components.data.object_type,
|
|
6016
|
+
parentObjectId: new LazyValue(
|
|
6017
|
+
spanComponentsToObjectIdLambda(resolvedState, components)
|
|
6018
|
+
),
|
|
6019
|
+
id: components.data.row_id,
|
|
6020
|
+
root_span_id: components.data.root_span_id,
|
|
6021
|
+
span_id: components.data.span_id,
|
|
6022
|
+
event
|
|
6023
|
+
});
|
|
6024
|
+
}
|
|
5943
6025
|
function spanComponentsToObjectIdLambda(state, components) {
|
|
5944
6026
|
if (components.data.object_id) {
|
|
5945
6027
|
const ret = components.data.object_id;
|
|
@@ -7382,6 +7464,12 @@ ${stackTrace}` });
|
|
|
7382
7464
|
function startSpan(args) {
|
|
7383
7465
|
return startSpanAndIsLogger(args).span;
|
|
7384
7466
|
}
|
|
7467
|
+
function _internalStartSpanWithInitialMerge(args) {
|
|
7468
|
+
return startSpanAndIsLogger({
|
|
7469
|
+
...args,
|
|
7470
|
+
[INITIAL_SPAN_WRITE_AS_MERGE]: true
|
|
7471
|
+
}).span;
|
|
7472
|
+
}
|
|
7385
7473
|
async function flush(options) {
|
|
7386
7474
|
const state = options?.state ?? _globalState;
|
|
7387
7475
|
return await state.bgLogger().flush();
|
|
@@ -8186,7 +8274,7 @@ var SpanImpl = class _SpanImpl {
|
|
|
8186
8274
|
this._spanId = resolvedIds.spanId;
|
|
8187
8275
|
this._rootSpanId = resolvedIds.rootSpanId;
|
|
8188
8276
|
this._spanParents = resolvedIds.spanParents;
|
|
8189
|
-
this.isMerge =
|
|
8277
|
+
this.isMerge = args[INITIAL_SPAN_WRITE_AS_MERGE] === true;
|
|
8190
8278
|
this.logInternal({ event, internalData });
|
|
8191
8279
|
this.isMerge = true;
|
|
8192
8280
|
}
|
|
@@ -28979,6 +29067,1469 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
28979
29067
|
}
|
|
28980
29068
|
};
|
|
28981
29069
|
|
|
29070
|
+
// src/instrumentation/plugins/eve-plugin.ts
|
|
29071
|
+
var EVE_TRACE_STATE_KEY = "braintrust.eve.tracing";
|
|
29072
|
+
var MAX_EVE_CACHE_ENTRIES = 1e4;
|
|
29073
|
+
var MAX_STORED_LLM_INPUTS = 100;
|
|
29074
|
+
var MAX_STORED_SPAN_REFERENCES = 1e4;
|
|
29075
|
+
var MAX_STORED_STEP_STARTS = 1e4;
|
|
29076
|
+
function braintrustEveHook(options) {
|
|
29077
|
+
const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
|
|
29078
|
+
const bridge = new EveBridge(state);
|
|
29079
|
+
return {
|
|
29080
|
+
events: {
|
|
29081
|
+
"*": async (event, ctx) => {
|
|
29082
|
+
await bridge.handle(event, ctx, options.metadata);
|
|
29083
|
+
}
|
|
29084
|
+
}
|
|
29085
|
+
};
|
|
29086
|
+
}
|
|
29087
|
+
function braintrustEveInstrumentation(options) {
|
|
29088
|
+
const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
|
|
29089
|
+
return {
|
|
29090
|
+
events: {
|
|
29091
|
+
"step.started": (input) => {
|
|
29092
|
+
try {
|
|
29093
|
+
captureEveModelInput(state, input);
|
|
29094
|
+
} catch (error) {
|
|
29095
|
+
debugLogger.warn("Error in Eve LLM input capture:", error);
|
|
29096
|
+
}
|
|
29097
|
+
}
|
|
29098
|
+
},
|
|
29099
|
+
recordInputs: false,
|
|
29100
|
+
recordOutputs: false,
|
|
29101
|
+
setup: options.setup
|
|
29102
|
+
};
|
|
29103
|
+
}
|
|
29104
|
+
function isEveHandleMessageStreamEvent(event) {
|
|
29105
|
+
return isObject(event) && typeof event["type"] === "string";
|
|
29106
|
+
}
|
|
29107
|
+
var ResumedEveSpan = class {
|
|
29108
|
+
constructor(reference) {
|
|
29109
|
+
this.reference = reference;
|
|
29110
|
+
this.endTime = reference.endTime;
|
|
29111
|
+
}
|
|
29112
|
+
endTime;
|
|
29113
|
+
get rootSpanId() {
|
|
29114
|
+
return this.reference.rootSpanId;
|
|
29115
|
+
}
|
|
29116
|
+
get spanId() {
|
|
29117
|
+
return this.reference.spanId;
|
|
29118
|
+
}
|
|
29119
|
+
log(event) {
|
|
29120
|
+
const metrics = {
|
|
29121
|
+
...this.reference.startEvent?.metrics,
|
|
29122
|
+
...this.endTime === void 0 ? {} : { end: this.endTime },
|
|
29123
|
+
...event.metrics
|
|
29124
|
+
};
|
|
29125
|
+
updateSpan({
|
|
29126
|
+
exported: this.reference.exported,
|
|
29127
|
+
...this.reference.startEvent,
|
|
29128
|
+
...event,
|
|
29129
|
+
...Object.keys(metrics).length > 0 ? { metrics } : {}
|
|
29130
|
+
});
|
|
29131
|
+
}
|
|
29132
|
+
end(args) {
|
|
29133
|
+
if (this.endTime === void 0) {
|
|
29134
|
+
this.endTime = args?.endTime ?? getCurrentUnixTimestamp();
|
|
29135
|
+
this.log({ metrics: { end: this.endTime } });
|
|
29136
|
+
}
|
|
29137
|
+
return this.endTime;
|
|
29138
|
+
}
|
|
29139
|
+
};
|
|
29140
|
+
var EveBridge = class {
|
|
29141
|
+
constructor(state) {
|
|
29142
|
+
this.state = state;
|
|
29143
|
+
}
|
|
29144
|
+
eventQueuesBySession = /* @__PURE__ */ new Map();
|
|
29145
|
+
sessionsById = new LRUCache({
|
|
29146
|
+
max: MAX_EVE_CACHE_ENTRIES
|
|
29147
|
+
});
|
|
29148
|
+
completedToolKeys = new LRUCache({
|
|
29149
|
+
max: MAX_EVE_CACHE_ENTRIES
|
|
29150
|
+
});
|
|
29151
|
+
toolsByCallKey = new LRUCache({
|
|
29152
|
+
max: MAX_EVE_CACHE_ENTRIES
|
|
29153
|
+
});
|
|
29154
|
+
turnsByKey = new LRUCache({
|
|
29155
|
+
max: MAX_EVE_CACHE_ENTRIES
|
|
29156
|
+
});
|
|
29157
|
+
async startEveSpan(args) {
|
|
29158
|
+
const rowId = args?.event?.id;
|
|
29159
|
+
const reference = typeof rowId === "string" && readEveTraceState(this.state).spanReferences.find(
|
|
29160
|
+
(candidate) => candidate.rowId === rowId
|
|
29161
|
+
);
|
|
29162
|
+
if (reference) {
|
|
29163
|
+
return new ResumedEveSpan(reference);
|
|
29164
|
+
}
|
|
29165
|
+
const startTime = args?.startTime ?? getCurrentUnixTimestamp();
|
|
29166
|
+
const parentSpanIds = args?.parentSpanIds;
|
|
29167
|
+
const startEvent = {
|
|
29168
|
+
created: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29169
|
+
metrics: { start: startTime },
|
|
29170
|
+
span_attributes: {
|
|
29171
|
+
...args?.name ? { name: args.name } : {},
|
|
29172
|
+
...args?.type ? { type: args.type } : {},
|
|
29173
|
+
...args?.spanAttributes
|
|
29174
|
+
},
|
|
29175
|
+
span_parents: parentSpanIds ? "spanId" in parentSpanIds ? [parentSpanIds.spanId] : parentSpanIds.parentSpanIds : []
|
|
29176
|
+
};
|
|
29177
|
+
const span = withCurrent(
|
|
29178
|
+
NOOP_SPAN,
|
|
29179
|
+
() => _internalStartSpanWithInitialMerge({ ...args, startTime })
|
|
29180
|
+
);
|
|
29181
|
+
if (typeof rowId !== "string") {
|
|
29182
|
+
return span;
|
|
29183
|
+
}
|
|
29184
|
+
try {
|
|
29185
|
+
const exported = await span.export();
|
|
29186
|
+
const reference2 = {
|
|
29187
|
+
exported,
|
|
29188
|
+
rootSpanId: span.rootSpanId,
|
|
29189
|
+
rowId,
|
|
29190
|
+
spanId: span.spanId,
|
|
29191
|
+
startEvent
|
|
29192
|
+
};
|
|
29193
|
+
this.state.update((current) => {
|
|
29194
|
+
const normalized = normalizeEveTraceState(current);
|
|
29195
|
+
return normalized.spanReferences.some(
|
|
29196
|
+
(candidate) => candidate.rowId === rowId
|
|
29197
|
+
) ? normalized : {
|
|
29198
|
+
...normalized,
|
|
29199
|
+
spanReferences: [...normalized.spanReferences, reference2].slice(
|
|
29200
|
+
-MAX_STORED_SPAN_REFERENCES
|
|
29201
|
+
)
|
|
29202
|
+
};
|
|
29203
|
+
});
|
|
29204
|
+
} catch (error) {
|
|
29205
|
+
debugLogger.warn("Error exporting Eve span for resumption:", error);
|
|
29206
|
+
}
|
|
29207
|
+
return span;
|
|
29208
|
+
}
|
|
29209
|
+
async startEveChildSpan(parent, args) {
|
|
29210
|
+
return await this.startEveSpan({
|
|
29211
|
+
...args,
|
|
29212
|
+
parentSpanIds: {
|
|
29213
|
+
rootSpanId: parent.rootSpanId,
|
|
29214
|
+
spanId: parent.spanId
|
|
29215
|
+
}
|
|
29216
|
+
});
|
|
29217
|
+
}
|
|
29218
|
+
stepOrdinal(event) {
|
|
29219
|
+
let ordinal = 0;
|
|
29220
|
+
this.state.update((current) => {
|
|
29221
|
+
const state = normalizeEveTraceState(current);
|
|
29222
|
+
const previous = state.stepStarts.filter(
|
|
29223
|
+
(entry) => entry.turnId === event.data.turnId && entry.stepIndex === event.data.stepIndex
|
|
29224
|
+
).at(-1);
|
|
29225
|
+
if (previous?.open) {
|
|
29226
|
+
ordinal = previous.ordinal;
|
|
29227
|
+
return state;
|
|
29228
|
+
}
|
|
29229
|
+
ordinal = state.stepStarts.filter(
|
|
29230
|
+
(entry) => entry.turnId === event.data.turnId
|
|
29231
|
+
).length;
|
|
29232
|
+
return {
|
|
29233
|
+
...state,
|
|
29234
|
+
stepStarts: [
|
|
29235
|
+
...state.stepStarts,
|
|
29236
|
+
{
|
|
29237
|
+
open: true,
|
|
29238
|
+
ordinal,
|
|
29239
|
+
stepIndex: event.data.stepIndex,
|
|
29240
|
+
turnId: event.data.turnId
|
|
29241
|
+
}
|
|
29242
|
+
].slice(-MAX_STORED_STEP_STARTS)
|
|
29243
|
+
};
|
|
29244
|
+
});
|
|
29245
|
+
return ordinal;
|
|
29246
|
+
}
|
|
29247
|
+
markStepEnded(turnId, stepIndex) {
|
|
29248
|
+
this.state.update((current) => {
|
|
29249
|
+
const state = normalizeEveTraceState(current);
|
|
29250
|
+
let index = -1;
|
|
29251
|
+
for (let i = state.stepStarts.length - 1; i >= 0; i--) {
|
|
29252
|
+
const entry = state.stepStarts[i];
|
|
29253
|
+
if (entry?.turnId === turnId && entry.stepIndex === stepIndex) {
|
|
29254
|
+
index = i;
|
|
29255
|
+
break;
|
|
29256
|
+
}
|
|
29257
|
+
}
|
|
29258
|
+
if (index < 0 || !state.stepStarts[index]?.open) {
|
|
29259
|
+
return state;
|
|
29260
|
+
}
|
|
29261
|
+
return {
|
|
29262
|
+
...state,
|
|
29263
|
+
stepStarts: state.stepStarts.map(
|
|
29264
|
+
(entry, entryIndex) => entryIndex === index ? { ...entry, open: false } : entry
|
|
29265
|
+
)
|
|
29266
|
+
};
|
|
29267
|
+
});
|
|
29268
|
+
}
|
|
29269
|
+
async handle(event, ctx, hookMetadata) {
|
|
29270
|
+
if (!isEveHandleMessageStreamEvent(event)) {
|
|
29271
|
+
return;
|
|
29272
|
+
}
|
|
29273
|
+
const run = async () => {
|
|
29274
|
+
try {
|
|
29275
|
+
if (!await this.handleEvent(event, ctx, hookMetadata)) {
|
|
29276
|
+
return;
|
|
29277
|
+
}
|
|
29278
|
+
if (event.type === "session.failed") {
|
|
29279
|
+
const sessionId2 = event.data.sessionId || sessionIdFromContext(ctx);
|
|
29280
|
+
await this.flushInstrumentation();
|
|
29281
|
+
if (sessionId2) {
|
|
29282
|
+
this.cleanupSession(sessionId2);
|
|
29283
|
+
}
|
|
29284
|
+
} else if (event.type === "session.completed") {
|
|
29285
|
+
const sessionId2 = sessionIdFromContext(ctx);
|
|
29286
|
+
await this.flushInstrumentation();
|
|
29287
|
+
if (sessionId2) {
|
|
29288
|
+
this.cleanupSession(sessionId2);
|
|
29289
|
+
}
|
|
29290
|
+
}
|
|
29291
|
+
} catch (error) {
|
|
29292
|
+
debugLogger.warn("Error in Eve hook instrumentation:", error);
|
|
29293
|
+
}
|
|
29294
|
+
};
|
|
29295
|
+
const sessionId = event.type === "session.failed" ? event.data.sessionId || sessionIdFromContext(ctx) : sessionIdFromContext(ctx);
|
|
29296
|
+
if (!sessionId) {
|
|
29297
|
+
await run();
|
|
29298
|
+
return;
|
|
29299
|
+
}
|
|
29300
|
+
const previous = this.eventQueuesBySession.get(sessionId);
|
|
29301
|
+
const queued = previous ? previous.then(run) : run();
|
|
29302
|
+
this.eventQueuesBySession.set(sessionId, queued);
|
|
29303
|
+
try {
|
|
29304
|
+
await queued;
|
|
29305
|
+
} finally {
|
|
29306
|
+
if (this.eventQueuesBySession.get(sessionId) === queued) {
|
|
29307
|
+
this.eventQueuesBySession.delete(sessionId);
|
|
29308
|
+
}
|
|
29309
|
+
}
|
|
29310
|
+
}
|
|
29311
|
+
async handleEvent(event, ctx, hookMetadata) {
|
|
29312
|
+
switch (event.type) {
|
|
29313
|
+
case "session.started":
|
|
29314
|
+
await this.handleSessionStarted(event, ctx, hookMetadata);
|
|
29315
|
+
return true;
|
|
29316
|
+
case "turn.started":
|
|
29317
|
+
await this.handleTurnStarted(event, ctx, hookMetadata);
|
|
29318
|
+
return true;
|
|
29319
|
+
case "message.received":
|
|
29320
|
+
await this.handleMessageReceived(event, ctx, hookMetadata);
|
|
29321
|
+
return true;
|
|
29322
|
+
case "step.started":
|
|
29323
|
+
await this.handleStepStarted(event, ctx, hookMetadata);
|
|
29324
|
+
return true;
|
|
29325
|
+
case "message.completed":
|
|
29326
|
+
this.handleMessageCompleted(event, ctx);
|
|
29327
|
+
return true;
|
|
29328
|
+
case "result.completed":
|
|
29329
|
+
this.handleResultCompleted(event, ctx);
|
|
29330
|
+
return true;
|
|
29331
|
+
case "actions.requested":
|
|
29332
|
+
await this.handleActionsRequested(event, ctx, hookMetadata);
|
|
29333
|
+
return true;
|
|
29334
|
+
case "action.result":
|
|
29335
|
+
await this.handleActionResult(event, ctx, hookMetadata);
|
|
29336
|
+
return true;
|
|
29337
|
+
case "subagent.called":
|
|
29338
|
+
await this.handleSubagentCalled(event, ctx, hookMetadata);
|
|
29339
|
+
return true;
|
|
29340
|
+
case "subagent.completed":
|
|
29341
|
+
await this.handleSubagentCompleted(event, ctx, hookMetadata);
|
|
29342
|
+
return true;
|
|
29343
|
+
case "step.completed":
|
|
29344
|
+
this.handleStepCompleted(event, ctx);
|
|
29345
|
+
return true;
|
|
29346
|
+
case "step.failed":
|
|
29347
|
+
this.handleStepFailed(event, ctx);
|
|
29348
|
+
return true;
|
|
29349
|
+
case "turn.completed":
|
|
29350
|
+
await this.handleTurnCompleted(event, ctx);
|
|
29351
|
+
return true;
|
|
29352
|
+
case "turn.failed":
|
|
29353
|
+
await this.handleTurnFailed(event, ctx);
|
|
29354
|
+
return true;
|
|
29355
|
+
case "session.failed":
|
|
29356
|
+
await this.handleSessionFailed(event, ctx);
|
|
29357
|
+
return true;
|
|
29358
|
+
case "session.completed":
|
|
29359
|
+
await this.handleSessionCompleted(event, ctx);
|
|
29360
|
+
return true;
|
|
29361
|
+
default:
|
|
29362
|
+
return false;
|
|
29363
|
+
}
|
|
29364
|
+
}
|
|
29365
|
+
async handleSessionStarted(event, ctx, hookMetadata) {
|
|
29366
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
29367
|
+
if (!sessionId) {
|
|
29368
|
+
return;
|
|
29369
|
+
}
|
|
29370
|
+
const metadata = {
|
|
29371
|
+
...hookMetadata ?? {},
|
|
29372
|
+
...modelMetadataFromRuntime(event.data.runtime)
|
|
29373
|
+
};
|
|
29374
|
+
this.state.update((current) => {
|
|
29375
|
+
const normalized = normalizeEveTraceState(current);
|
|
29376
|
+
return {
|
|
29377
|
+
...normalized,
|
|
29378
|
+
metadata: { ...normalized.metadata, ...metadata }
|
|
29379
|
+
};
|
|
29380
|
+
});
|
|
29381
|
+
await this.ensureSession(sessionId, ctx, metadata, eventTime2(event));
|
|
29382
|
+
for (const [key, turn] of this.turnsByKey) {
|
|
29383
|
+
if (!key.startsWith(`${sessionId}:`)) {
|
|
29384
|
+
continue;
|
|
29385
|
+
}
|
|
29386
|
+
turn.metadata = { ...turn.metadata, ...metadata };
|
|
29387
|
+
turn.span.log({ metadata: turn.metadata });
|
|
29388
|
+
for (const step of turn.stepsByIndex.values()) {
|
|
29389
|
+
step.metadata = { ...step.metadata, ...metadata };
|
|
29390
|
+
step.span.log({ metadata: step.metadata });
|
|
29391
|
+
}
|
|
29392
|
+
}
|
|
29393
|
+
}
|
|
29394
|
+
async handleTurnStarted(event, ctx, hookMetadata) {
|
|
29395
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
29396
|
+
if (!sessionId) {
|
|
29397
|
+
return;
|
|
29398
|
+
}
|
|
29399
|
+
const session = await this.ensureSession(
|
|
29400
|
+
sessionId,
|
|
29401
|
+
ctx,
|
|
29402
|
+
hookMetadata ?? {},
|
|
29403
|
+
eventTime2(event)
|
|
29404
|
+
);
|
|
29405
|
+
const key = turnKey2(sessionId, event.data.turnId);
|
|
29406
|
+
const metadata = { ...session.metadata };
|
|
29407
|
+
const existing = this.turnsByKey.get(key);
|
|
29408
|
+
if (existing) {
|
|
29409
|
+
existing.metadata = { ...existing.metadata, ...metadata };
|
|
29410
|
+
existing.span.log({ metadata: existing.metadata });
|
|
29411
|
+
return;
|
|
29412
|
+
}
|
|
29413
|
+
const span = await this.startTurnSpan(session, event, metadata);
|
|
29414
|
+
span.log({ metadata });
|
|
29415
|
+
this.turnsByKey.set(key, {
|
|
29416
|
+
key,
|
|
29417
|
+
metadata,
|
|
29418
|
+
metrics: {},
|
|
29419
|
+
span,
|
|
29420
|
+
stepsByIndex: /* @__PURE__ */ new Map(),
|
|
29421
|
+
turnId: event.data.turnId
|
|
29422
|
+
});
|
|
29423
|
+
}
|
|
29424
|
+
async handleMessageReceived(event, ctx, hookMetadata) {
|
|
29425
|
+
const turn = await this.ensureTurn(event, ctx, hookMetadata);
|
|
29426
|
+
if (!turn) {
|
|
29427
|
+
return;
|
|
29428
|
+
}
|
|
29429
|
+
const input = [{ content: event.data.message, role: "user" }];
|
|
29430
|
+
turn.span.log({ input });
|
|
29431
|
+
}
|
|
29432
|
+
async handleStepStarted(event, ctx, hookMetadata) {
|
|
29433
|
+
const turn = await this.ensureTurn(event, ctx, hookMetadata);
|
|
29434
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
29435
|
+
if (!turn || !sessionId) {
|
|
29436
|
+
return;
|
|
29437
|
+
}
|
|
29438
|
+
const existing = turn.stepsByIndex.get(event.data.stepIndex);
|
|
29439
|
+
if (existing) {
|
|
29440
|
+
existing.span.log({
|
|
29441
|
+
...existing.input !== void 0 ? { input: existing.input } : {},
|
|
29442
|
+
metadata: existing.metadata,
|
|
29443
|
+
metrics: existing.metrics,
|
|
29444
|
+
output: existing.output
|
|
29445
|
+
});
|
|
29446
|
+
const endTime = eventTime2(event);
|
|
29447
|
+
existing.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
29448
|
+
this.markStepEnded(event.data.turnId, event.data.stepIndex);
|
|
29449
|
+
}
|
|
29450
|
+
const stepOrdinal = this.stepOrdinal(event);
|
|
29451
|
+
const metadata = {
|
|
29452
|
+
...turn.metadata,
|
|
29453
|
+
...this.sessionsById.get(sessionId)?.metadata ?? {}
|
|
29454
|
+
};
|
|
29455
|
+
const input = consumeCapturedEveModelInput(
|
|
29456
|
+
this.state,
|
|
29457
|
+
sessionId,
|
|
29458
|
+
event.data.turnId,
|
|
29459
|
+
event.data.stepIndex
|
|
29460
|
+
);
|
|
29461
|
+
const { rowId: eventId, spanId } = await generateEveIds(
|
|
29462
|
+
"step",
|
|
29463
|
+
sessionId,
|
|
29464
|
+
event.data.turnId,
|
|
29465
|
+
String(stepOrdinal)
|
|
29466
|
+
);
|
|
29467
|
+
const span = await this.startEveChildSpan(turn.span, {
|
|
29468
|
+
event: {
|
|
29469
|
+
id: eventId,
|
|
29470
|
+
...input !== void 0 ? { input } : {},
|
|
29471
|
+
metadata
|
|
29472
|
+
},
|
|
29473
|
+
name: "eve.step",
|
|
29474
|
+
spanAttributes: { type: "llm" /* LLM */ },
|
|
29475
|
+
spanId,
|
|
29476
|
+
startTime: eventTime2(event)
|
|
29477
|
+
});
|
|
29478
|
+
span.log({ ...input !== void 0 ? { input } : {}, metadata });
|
|
29479
|
+
turn.stepsByIndex.set(event.data.stepIndex, {
|
|
29480
|
+
...input !== void 0 ? { input } : {},
|
|
29481
|
+
metadata,
|
|
29482
|
+
metrics: {},
|
|
29483
|
+
span
|
|
29484
|
+
});
|
|
29485
|
+
}
|
|
29486
|
+
handleMessageCompleted(event, ctx) {
|
|
29487
|
+
const step = this.stepForEvent(event, ctx);
|
|
29488
|
+
if (!step) {
|
|
29489
|
+
return;
|
|
29490
|
+
}
|
|
29491
|
+
const existingMessage = Array.isArray(step.output) && isObject(step.output[0]) ? step.output[0].message : void 0;
|
|
29492
|
+
const existingToolCalls = isObject(existingMessage) ? existingMessage.tool_calls : void 0;
|
|
29493
|
+
step.output = [
|
|
29494
|
+
{
|
|
29495
|
+
finish_reason: normalizedFinishReason(event.data.finishReason),
|
|
29496
|
+
index: 0,
|
|
29497
|
+
message: {
|
|
29498
|
+
content: event.data.message,
|
|
29499
|
+
role: "assistant",
|
|
29500
|
+
...Array.isArray(existingToolCalls) ? { tool_calls: existingToolCalls } : {}
|
|
29501
|
+
}
|
|
29502
|
+
}
|
|
29503
|
+
];
|
|
29504
|
+
const turn = this.turnForEvent(event, ctx);
|
|
29505
|
+
if (turn && event.data.finishReason !== "tool-calls") {
|
|
29506
|
+
turn.output = event.data.message;
|
|
29507
|
+
}
|
|
29508
|
+
}
|
|
29509
|
+
handleResultCompleted(event, ctx) {
|
|
29510
|
+
const step = this.stepForEvent(event, ctx);
|
|
29511
|
+
if (step) {
|
|
29512
|
+
step.output = [
|
|
29513
|
+
{
|
|
29514
|
+
finish_reason: "stop",
|
|
29515
|
+
index: 0,
|
|
29516
|
+
message: {
|
|
29517
|
+
content: event.data.result,
|
|
29518
|
+
role: "assistant"
|
|
29519
|
+
}
|
|
29520
|
+
}
|
|
29521
|
+
];
|
|
29522
|
+
}
|
|
29523
|
+
const turn = this.turnForEvent(event, ctx);
|
|
29524
|
+
if (turn) {
|
|
29525
|
+
turn.output = event.data.result;
|
|
29526
|
+
}
|
|
29527
|
+
}
|
|
29528
|
+
async handleActionsRequested(event, ctx, hookMetadata) {
|
|
29529
|
+
const turn = await this.ensureTurn(event, ctx, hookMetadata);
|
|
29530
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
29531
|
+
if (!turn || !sessionId) {
|
|
29532
|
+
return;
|
|
29533
|
+
}
|
|
29534
|
+
const traceActions = event.data.actions.filter(isTraceableActionRequest);
|
|
29535
|
+
if (traceActions.length === 0) {
|
|
29536
|
+
return;
|
|
29537
|
+
}
|
|
29538
|
+
for (const action of traceActions) {
|
|
29539
|
+
if (isToolCallAction(action)) {
|
|
29540
|
+
await this.startRequestedTool(event, turn, sessionId, action);
|
|
29541
|
+
} else if (isLocalSubagentCallAction(action)) {
|
|
29542
|
+
await this.startRequestedSubagent(event, turn, sessionId, action);
|
|
29543
|
+
}
|
|
29544
|
+
}
|
|
29545
|
+
const step = turn.stepsByIndex.get(event.data.stepIndex);
|
|
29546
|
+
if (!step) {
|
|
29547
|
+
return;
|
|
29548
|
+
}
|
|
29549
|
+
step.output = [
|
|
29550
|
+
{
|
|
29551
|
+
finish_reason: "tool_calls",
|
|
29552
|
+
index: 0,
|
|
29553
|
+
message: {
|
|
29554
|
+
content: null,
|
|
29555
|
+
role: "assistant",
|
|
29556
|
+
tool_calls: traceActions.map((action) => {
|
|
29557
|
+
const name = action.kind === "tool-call" ? action.toolName : action.subagentName ?? action.name ?? "agent";
|
|
29558
|
+
return {
|
|
29559
|
+
function: {
|
|
29560
|
+
arguments: JSON.stringify(action.input),
|
|
29561
|
+
name
|
|
29562
|
+
},
|
|
29563
|
+
id: action.callId,
|
|
29564
|
+
type: "function"
|
|
29565
|
+
};
|
|
29566
|
+
})
|
|
29567
|
+
}
|
|
29568
|
+
}
|
|
29569
|
+
];
|
|
29570
|
+
step.span.log({ metadata: step.metadata, output: step.output });
|
|
29571
|
+
}
|
|
29572
|
+
async handleActionResult(event, ctx, hookMetadata) {
|
|
29573
|
+
if (isToolResult(event.data.result)) {
|
|
29574
|
+
await this.handleToolResult(event, ctx, event.data.result, hookMetadata);
|
|
29575
|
+
return;
|
|
29576
|
+
}
|
|
29577
|
+
if (isSubagentResult(event.data.result)) {
|
|
29578
|
+
await this.handleSubagentResult(
|
|
29579
|
+
event,
|
|
29580
|
+
ctx,
|
|
29581
|
+
event.data.result,
|
|
29582
|
+
hookMetadata
|
|
29583
|
+
);
|
|
29584
|
+
}
|
|
29585
|
+
}
|
|
29586
|
+
async handleToolResult(event, ctx, result, hookMetadata) {
|
|
29587
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
29588
|
+
if (!sessionId) {
|
|
29589
|
+
return;
|
|
29590
|
+
}
|
|
29591
|
+
const key = toolKey3(sessionId, result.callId);
|
|
29592
|
+
if (this.completedToolKeys.has(key)) {
|
|
29593
|
+
return;
|
|
29594
|
+
}
|
|
29595
|
+
const tool = this.toolsByCallKey.get(key) ?? await this.startSyntheticTool(event, ctx, result, hookMetadata);
|
|
29596
|
+
if (!tool) {
|
|
29597
|
+
return;
|
|
29598
|
+
}
|
|
29599
|
+
const failed = event.data.status === "failed" || result.isError === true || event.data.error !== void 0;
|
|
29600
|
+
tool.span.log({
|
|
29601
|
+
...failed ? {
|
|
29602
|
+
error: actionResultError(event.data.error, result.output)
|
|
29603
|
+
} : {},
|
|
29604
|
+
metadata: tool.metadata,
|
|
29605
|
+
output: result.output
|
|
29606
|
+
});
|
|
29607
|
+
const endTime = eventTime2(event);
|
|
29608
|
+
tool.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
29609
|
+
this.toolsByCallKey.delete(key);
|
|
29610
|
+
this.completedToolKeys.set(key, true);
|
|
29611
|
+
}
|
|
29612
|
+
async handleSubagentCalled(event, ctx, hookMetadata) {
|
|
29613
|
+
if (event.data.remote?.url) {
|
|
29614
|
+
return;
|
|
29615
|
+
}
|
|
29616
|
+
const turn = await this.ensureTurn(event, ctx, hookMetadata);
|
|
29617
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
29618
|
+
if (!turn || !sessionId) {
|
|
29619
|
+
return;
|
|
29620
|
+
}
|
|
29621
|
+
const key = toolKey3(sessionId, event.data.callId);
|
|
29622
|
+
const metadata = toolMetadataFromTurn(turn);
|
|
29623
|
+
const existing = this.toolsByCallKey.get(key);
|
|
29624
|
+
if (existing) {
|
|
29625
|
+
existing.metadata = { ...existing.metadata, ...metadata };
|
|
29626
|
+
existing.span.log({ metadata: existing.metadata });
|
|
29627
|
+
return;
|
|
29628
|
+
}
|
|
29629
|
+
if (this.completedToolKeys.has(key)) {
|
|
29630
|
+
return;
|
|
29631
|
+
}
|
|
29632
|
+
const { rowId: eventId, spanId } = await generateEveIds(
|
|
29633
|
+
"subagent",
|
|
29634
|
+
sessionId,
|
|
29635
|
+
event.data.callId
|
|
29636
|
+
);
|
|
29637
|
+
const pending = this.toolsByCallKey.get(key);
|
|
29638
|
+
if (pending || this.completedToolKeys.has(key)) {
|
|
29639
|
+
if (pending) {
|
|
29640
|
+
pending.metadata = { ...pending.metadata, ...metadata };
|
|
29641
|
+
pending.span.log({ metadata: pending.metadata });
|
|
29642
|
+
}
|
|
29643
|
+
return;
|
|
29644
|
+
}
|
|
29645
|
+
const span = await this.startEveChildSpan(turn.span, {
|
|
29646
|
+
event: {
|
|
29647
|
+
id: eventId,
|
|
29648
|
+
metadata
|
|
29649
|
+
},
|
|
29650
|
+
name: event.data.toolName ?? event.data.name,
|
|
29651
|
+
spanAttributes: { type: "tool" /* TOOL */ },
|
|
29652
|
+
spanId,
|
|
29653
|
+
startTime: eventTime2(event)
|
|
29654
|
+
});
|
|
29655
|
+
span.log({ metadata });
|
|
29656
|
+
this.toolsByCallKey.set(key, {
|
|
29657
|
+
metadata,
|
|
29658
|
+
span,
|
|
29659
|
+
turnKey: turnKey2(sessionId, event.data.turnId)
|
|
29660
|
+
});
|
|
29661
|
+
}
|
|
29662
|
+
async handleSubagentCompleted(event, ctx, hookMetadata) {
|
|
29663
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
29664
|
+
if (!sessionId) {
|
|
29665
|
+
return;
|
|
29666
|
+
}
|
|
29667
|
+
const key = toolKey3(sessionId, event.data.callId);
|
|
29668
|
+
if (this.completedToolKeys.has(key)) {
|
|
29669
|
+
return;
|
|
29670
|
+
}
|
|
29671
|
+
const subagent = this.toolsByCallKey.get(key) ?? await this.startSyntheticSubagent(event, ctx, hookMetadata);
|
|
29672
|
+
if (!subagent) {
|
|
29673
|
+
return;
|
|
29674
|
+
}
|
|
29675
|
+
subagent.span.log({
|
|
29676
|
+
...event.data.status === "failed" ? {
|
|
29677
|
+
error: actionResultError(event.data.error, event.data.output)
|
|
29678
|
+
} : {},
|
|
29679
|
+
metadata: subagent.metadata,
|
|
29680
|
+
...event.data.output !== void 0 ? { output: event.data.output } : {}
|
|
29681
|
+
});
|
|
29682
|
+
const endTime = eventTime2(event);
|
|
29683
|
+
const recordedEndTime = subagent.span.end(
|
|
29684
|
+
endTime === void 0 ? void 0 : { endTime }
|
|
29685
|
+
);
|
|
29686
|
+
this.state.update((current) => {
|
|
29687
|
+
const normalized = normalizeEveTraceState(current);
|
|
29688
|
+
return {
|
|
29689
|
+
...normalized,
|
|
29690
|
+
spanReferences: normalized.spanReferences.map(
|
|
29691
|
+
(reference) => reference.spanId === subagent.span.spanId ? { ...reference, endTime: recordedEndTime } : reference
|
|
29692
|
+
)
|
|
29693
|
+
};
|
|
29694
|
+
});
|
|
29695
|
+
}
|
|
29696
|
+
async handleSubagentResult(event, ctx, result, hookMetadata) {
|
|
29697
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
29698
|
+
if (!sessionId) {
|
|
29699
|
+
return;
|
|
29700
|
+
}
|
|
29701
|
+
const key = toolKey3(sessionId, result.callId);
|
|
29702
|
+
if (this.completedToolKeys.has(key)) {
|
|
29703
|
+
return;
|
|
29704
|
+
}
|
|
29705
|
+
const subagent = this.toolsByCallKey.get(key) ?? await this.startSyntheticSubagentResult(
|
|
29706
|
+
event,
|
|
29707
|
+
ctx,
|
|
29708
|
+
result,
|
|
29709
|
+
hookMetadata
|
|
29710
|
+
);
|
|
29711
|
+
if (!subagent) {
|
|
29712
|
+
return;
|
|
29713
|
+
}
|
|
29714
|
+
const isError = event.data.status === "failed" || result.isError === true || event.data.error !== void 0;
|
|
29715
|
+
subagent.span.log({
|
|
29716
|
+
...isError ? {
|
|
29717
|
+
error: actionResultError(event.data.error, result.output)
|
|
29718
|
+
} : {},
|
|
29719
|
+
metadata: subagent.metadata,
|
|
29720
|
+
output: result.output
|
|
29721
|
+
});
|
|
29722
|
+
const endTime = eventTime2(event);
|
|
29723
|
+
subagent.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
29724
|
+
this.toolsByCallKey.delete(key);
|
|
29725
|
+
this.completedToolKeys.set(key, true);
|
|
29726
|
+
}
|
|
29727
|
+
handleStepCompleted(event, ctx) {
|
|
29728
|
+
const step = this.stepForEvent(event, ctx);
|
|
29729
|
+
if (!step) {
|
|
29730
|
+
return;
|
|
29731
|
+
}
|
|
29732
|
+
const usage = event.data.usage;
|
|
29733
|
+
const inputTokens = typeof usage?.inputTokens === "number" && Number.isFinite(usage.inputTokens) && usage.inputTokens >= 0 ? usage.inputTokens : void 0;
|
|
29734
|
+
const outputTokens = typeof usage?.outputTokens === "number" && Number.isFinite(usage.outputTokens) && usage.outputTokens >= 0 ? usage.outputTokens : void 0;
|
|
29735
|
+
const cacheReadTokens = typeof usage?.cacheReadTokens === "number" && Number.isFinite(usage.cacheReadTokens) && usage.cacheReadTokens >= 0 ? usage.cacheReadTokens : void 0;
|
|
29736
|
+
const cacheWriteTokens = typeof usage?.cacheWriteTokens === "number" && Number.isFinite(usage.cacheWriteTokens) && usage.cacheWriteTokens >= 0 ? usage.cacheWriteTokens : void 0;
|
|
29737
|
+
const costUsd = typeof usage?.costUsd === "number" && Number.isFinite(usage.costUsd) && usage.costUsd >= 0 ? usage.costUsd : void 0;
|
|
29738
|
+
const total = inputTokens !== void 0 && outputTokens !== void 0 ? inputTokens + outputTokens : void 0;
|
|
29739
|
+
const metrics = {
|
|
29740
|
+
...inputTokens !== void 0 ? { prompt_tokens: inputTokens } : {},
|
|
29741
|
+
...outputTokens !== void 0 ? { completion_tokens: outputTokens } : {},
|
|
29742
|
+
...total !== void 0 ? { tokens: total } : {},
|
|
29743
|
+
...cacheReadTokens !== void 0 ? { prompt_cached_tokens: cacheReadTokens } : {},
|
|
29744
|
+
...cacheWriteTokens !== void 0 ? { prompt_cache_creation_tokens: cacheWriteTokens } : {},
|
|
29745
|
+
...costUsd !== void 0 ? { estimated_cost: costUsd } : {}
|
|
29746
|
+
};
|
|
29747
|
+
step.metrics = { ...step.metrics, ...metrics };
|
|
29748
|
+
if (Array.isArray(step.output) && isObject(step.output[0])) {
|
|
29749
|
+
const finishReason = step.output[0].finish_reason;
|
|
29750
|
+
if (typeof finishReason !== "string") {
|
|
29751
|
+
step.output[0].finish_reason = normalizedFinishReason(
|
|
29752
|
+
event.data.finishReason
|
|
29753
|
+
);
|
|
29754
|
+
}
|
|
29755
|
+
}
|
|
29756
|
+
step.span.log({
|
|
29757
|
+
...step.input !== void 0 ? { input: step.input } : {},
|
|
29758
|
+
metadata: step.metadata,
|
|
29759
|
+
metrics,
|
|
29760
|
+
output: step.output
|
|
29761
|
+
});
|
|
29762
|
+
const endTime = eventTime2(event);
|
|
29763
|
+
step.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
29764
|
+
const turn = this.turnForEvent(event, ctx);
|
|
29765
|
+
if (turn) {
|
|
29766
|
+
for (const [key, value] of Object.entries(metrics)) {
|
|
29767
|
+
turn.metrics[key] = (turn.metrics[key] ?? 0) + value;
|
|
29768
|
+
}
|
|
29769
|
+
turn.stepsByIndex.delete(event.data.stepIndex);
|
|
29770
|
+
}
|
|
29771
|
+
this.markStepEnded(event.data.turnId, event.data.stepIndex);
|
|
29772
|
+
}
|
|
29773
|
+
handleStepFailed(event, ctx) {
|
|
29774
|
+
const step = this.stepForEvent(event, ctx);
|
|
29775
|
+
if (step) {
|
|
29776
|
+
step.span.log({
|
|
29777
|
+
error: errorFromMessage(
|
|
29778
|
+
event.data.message,
|
|
29779
|
+
event.data.code,
|
|
29780
|
+
event.data.details
|
|
29781
|
+
)
|
|
29782
|
+
});
|
|
29783
|
+
const endTime = eventTime2(event);
|
|
29784
|
+
step.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
29785
|
+
}
|
|
29786
|
+
const turn = this.turnForEvent(event, ctx);
|
|
29787
|
+
turn?.stepsByIndex.delete(event.data.stepIndex);
|
|
29788
|
+
this.markStepEnded(event.data.turnId, event.data.stepIndex);
|
|
29789
|
+
}
|
|
29790
|
+
handleTurnCompleted(event, ctx) {
|
|
29791
|
+
const turn = this.turnForEvent(event, ctx);
|
|
29792
|
+
if (!turn) {
|
|
29793
|
+
return;
|
|
29794
|
+
}
|
|
29795
|
+
this.finalizeTurn(turn, {
|
|
29796
|
+
endTime: eventTime2(event)
|
|
29797
|
+
});
|
|
29798
|
+
}
|
|
29799
|
+
handleTurnFailed(event, ctx) {
|
|
29800
|
+
const turn = this.turnForEvent(event, ctx);
|
|
29801
|
+
if (!turn) {
|
|
29802
|
+
return;
|
|
29803
|
+
}
|
|
29804
|
+
this.finalizeTurn(turn, {
|
|
29805
|
+
endTime: eventTime2(event),
|
|
29806
|
+
error: errorFromMessage(
|
|
29807
|
+
event.data.message,
|
|
29808
|
+
event.data.code,
|
|
29809
|
+
event.data.details
|
|
29810
|
+
)
|
|
29811
|
+
});
|
|
29812
|
+
}
|
|
29813
|
+
async handleSessionFailed(event, ctx) {
|
|
29814
|
+
const sessionId = event.data.sessionId || sessionIdFromContext(ctx);
|
|
29815
|
+
if (!sessionId) {
|
|
29816
|
+
return;
|
|
29817
|
+
}
|
|
29818
|
+
const session = await this.ensureSession(
|
|
29819
|
+
sessionId,
|
|
29820
|
+
ctx,
|
|
29821
|
+
{},
|
|
29822
|
+
eventTime2(event)
|
|
29823
|
+
);
|
|
29824
|
+
const error = errorFromMessage(
|
|
29825
|
+
event.data.message,
|
|
29826
|
+
event.data.code,
|
|
29827
|
+
event.data.details
|
|
29828
|
+
);
|
|
29829
|
+
for (const [key, turn] of this.turnsByKey) {
|
|
29830
|
+
if (!key.startsWith(`${sessionId}:`)) {
|
|
29831
|
+
continue;
|
|
29832
|
+
}
|
|
29833
|
+
this.finalizeTurn(turn, {
|
|
29834
|
+
endTime: eventTime2(event),
|
|
29835
|
+
error
|
|
29836
|
+
});
|
|
29837
|
+
}
|
|
29838
|
+
for (const [key, tool] of this.toolsByCallKey) {
|
|
29839
|
+
if (key.startsWith(`${sessionId}:`)) {
|
|
29840
|
+
const endTime2 = eventTime2(event);
|
|
29841
|
+
if (!tool.endedByTurn) {
|
|
29842
|
+
tool.span.log({ metadata: tool.metadata });
|
|
29843
|
+
tool.span.end(endTime2 === void 0 ? void 0 : { endTime: endTime2 });
|
|
29844
|
+
tool.endedByTurn = true;
|
|
29845
|
+
}
|
|
29846
|
+
}
|
|
29847
|
+
}
|
|
29848
|
+
session.span.log({ error });
|
|
29849
|
+
const endTime = eventTime2(event);
|
|
29850
|
+
session.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
29851
|
+
}
|
|
29852
|
+
async handleSessionCompleted(event, ctx) {
|
|
29853
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
29854
|
+
if (!sessionId) {
|
|
29855
|
+
return;
|
|
29856
|
+
}
|
|
29857
|
+
const session = await this.ensureSession(
|
|
29858
|
+
sessionId,
|
|
29859
|
+
ctx,
|
|
29860
|
+
{},
|
|
29861
|
+
eventTime2(event)
|
|
29862
|
+
);
|
|
29863
|
+
for (const [key, turn] of this.turnsByKey) {
|
|
29864
|
+
if (!key.startsWith(`${sessionId}:`)) {
|
|
29865
|
+
continue;
|
|
29866
|
+
}
|
|
29867
|
+
this.finalizeTurn(turn, {
|
|
29868
|
+
endTime: eventTime2(event)
|
|
29869
|
+
});
|
|
29870
|
+
}
|
|
29871
|
+
for (const [key, tool] of this.toolsByCallKey) {
|
|
29872
|
+
if (key.startsWith(`${sessionId}:`) && !tool.endedByTurn) {
|
|
29873
|
+
const endTime2 = eventTime2(event);
|
|
29874
|
+
tool.span.log({ metadata: tool.metadata });
|
|
29875
|
+
tool.span.end(endTime2 === void 0 ? void 0 : { endTime: endTime2 });
|
|
29876
|
+
tool.endedByTurn = true;
|
|
29877
|
+
}
|
|
29878
|
+
}
|
|
29879
|
+
session.span.log({ metadata: session.metadata });
|
|
29880
|
+
const endTime = eventTime2(event);
|
|
29881
|
+
session.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
29882
|
+
}
|
|
29883
|
+
async ensureSession(sessionId, ctx, metadata, startTime) {
|
|
29884
|
+
metadata = {
|
|
29885
|
+
...readEveTraceState(this.state).metadata,
|
|
29886
|
+
...metadata
|
|
29887
|
+
};
|
|
29888
|
+
const existing = this.sessionsById.get(sessionId);
|
|
29889
|
+
if (existing) {
|
|
29890
|
+
existing.metadata = { ...existing.metadata, ...metadata };
|
|
29891
|
+
existing.span.log({ metadata: existing.metadata });
|
|
29892
|
+
return existing;
|
|
29893
|
+
}
|
|
29894
|
+
const lineage = parentLineageFromContext(ctx);
|
|
29895
|
+
const parentSubagent = lineage ? this.toolsByCallKey.get(toolKey3(lineage.sessionId, lineage.callId)) : void 0;
|
|
29896
|
+
const activeParent = currentSpan();
|
|
29897
|
+
const [
|
|
29898
|
+
{ rowId: eventId, spanId },
|
|
29899
|
+
parentSubagentSpanId,
|
|
29900
|
+
fallbackRootSpanId
|
|
29901
|
+
] = await Promise.all([
|
|
29902
|
+
generateEveIds("session", sessionId),
|
|
29903
|
+
lineage ? spanIdForSubagent(lineage.sessionId, lineage.callId) : Promise.resolve(void 0),
|
|
29904
|
+
lineage ? rootSpanIdForSession(lineage.rootSessionId) : rootSpanIdForSession(sessionId)
|
|
29905
|
+
]);
|
|
29906
|
+
const span = await this.startEveSpan({
|
|
29907
|
+
event: {
|
|
29908
|
+
id: eventId,
|
|
29909
|
+
metadata
|
|
29910
|
+
},
|
|
29911
|
+
name: "eve.session",
|
|
29912
|
+
parentSpanIds: lineage && parentSubagentSpanId ? {
|
|
29913
|
+
rootSpanId: parentSubagent?.span.rootSpanId ?? fallbackRootSpanId,
|
|
29914
|
+
spanId: parentSubagentSpanId
|
|
29915
|
+
} : !Object.is(activeParent, NOOP_SPAN) ? {
|
|
29916
|
+
rootSpanId: activeParent.rootSpanId,
|
|
29917
|
+
spanId: activeParent.spanId
|
|
29918
|
+
} : {
|
|
29919
|
+
parentSpanIds: [],
|
|
29920
|
+
rootSpanId: fallbackRootSpanId
|
|
29921
|
+
},
|
|
29922
|
+
spanAttributes: { type: "task" /* TASK */ },
|
|
29923
|
+
spanId,
|
|
29924
|
+
startTime
|
|
29925
|
+
});
|
|
29926
|
+
span.log({ metadata });
|
|
29927
|
+
const session = { metadata, sessionId, span };
|
|
29928
|
+
this.sessionsById.set(sessionId, session);
|
|
29929
|
+
return session;
|
|
29930
|
+
}
|
|
29931
|
+
async ensureTurn(event, ctx, hookMetadata) {
|
|
29932
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
29933
|
+
if (!sessionId) {
|
|
29934
|
+
return void 0;
|
|
29935
|
+
}
|
|
29936
|
+
const session = await this.ensureSession(
|
|
29937
|
+
sessionId,
|
|
29938
|
+
ctx,
|
|
29939
|
+
hookMetadata ?? {},
|
|
29940
|
+
eventTime2(event)
|
|
29941
|
+
);
|
|
29942
|
+
const key = turnKey2(sessionId, event.data.turnId);
|
|
29943
|
+
const existing = this.turnsByKey.get(key);
|
|
29944
|
+
if (existing) {
|
|
29945
|
+
return existing;
|
|
29946
|
+
}
|
|
29947
|
+
const metadata = { ...session.metadata };
|
|
29948
|
+
const span = await this.startTurnSpan(session, event, metadata);
|
|
29949
|
+
span.log({ metadata });
|
|
29950
|
+
const state = {
|
|
29951
|
+
key,
|
|
29952
|
+
metadata,
|
|
29953
|
+
metrics: {},
|
|
29954
|
+
span,
|
|
29955
|
+
stepsByIndex: /* @__PURE__ */ new Map(),
|
|
29956
|
+
turnId: event.data.turnId
|
|
29957
|
+
};
|
|
29958
|
+
this.turnsByKey.set(key, state);
|
|
29959
|
+
return state;
|
|
29960
|
+
}
|
|
29961
|
+
async startRequestedTool(event, turn, sessionId, action) {
|
|
29962
|
+
const key = toolKey3(sessionId, action.callId);
|
|
29963
|
+
if (this.toolsByCallKey.has(key) || this.completedToolKeys.has(key)) {
|
|
29964
|
+
return;
|
|
29965
|
+
}
|
|
29966
|
+
const metadata = toolMetadataFromTurn(turn);
|
|
29967
|
+
const { rowId: eventId, spanId } = await generateEveIds(
|
|
29968
|
+
"tool",
|
|
29969
|
+
sessionId,
|
|
29970
|
+
event.data.turnId,
|
|
29971
|
+
action.callId
|
|
29972
|
+
);
|
|
29973
|
+
if (this.toolsByCallKey.has(key) || this.completedToolKeys.has(key)) {
|
|
29974
|
+
return;
|
|
29975
|
+
}
|
|
29976
|
+
const span = await this.startEveChildSpan(turn.span, {
|
|
29977
|
+
event: {
|
|
29978
|
+
id: eventId,
|
|
29979
|
+
input: action.input,
|
|
29980
|
+
metadata
|
|
29981
|
+
},
|
|
29982
|
+
name: action.toolName,
|
|
29983
|
+
spanAttributes: { type: "tool" /* TOOL */ },
|
|
29984
|
+
spanId,
|
|
29985
|
+
startTime: eventTime2(event)
|
|
29986
|
+
});
|
|
29987
|
+
span.log({ input: action.input, metadata });
|
|
29988
|
+
this.toolsByCallKey.set(key, {
|
|
29989
|
+
metadata,
|
|
29990
|
+
span,
|
|
29991
|
+
turnKey: turnKey2(sessionId, event.data.turnId)
|
|
29992
|
+
});
|
|
29993
|
+
}
|
|
29994
|
+
async startRequestedSubagent(event, turn, sessionId, action) {
|
|
29995
|
+
const key = toolKey3(sessionId, action.callId);
|
|
29996
|
+
if (this.toolsByCallKey.has(key) || this.completedToolKeys.has(key)) {
|
|
29997
|
+
return;
|
|
29998
|
+
}
|
|
29999
|
+
const name = action.subagentName ?? action.name ?? "agent";
|
|
30000
|
+
const metadata = toolMetadataFromTurn(turn);
|
|
30001
|
+
const { rowId: eventId, spanId } = await generateEveIds(
|
|
30002
|
+
"subagent",
|
|
30003
|
+
sessionId,
|
|
30004
|
+
action.callId
|
|
30005
|
+
);
|
|
30006
|
+
if (this.toolsByCallKey.has(key) || this.completedToolKeys.has(key)) {
|
|
30007
|
+
return;
|
|
30008
|
+
}
|
|
30009
|
+
const span = await this.startEveChildSpan(turn.span, {
|
|
30010
|
+
event: {
|
|
30011
|
+
id: eventId,
|
|
30012
|
+
input: action.input,
|
|
30013
|
+
metadata
|
|
30014
|
+
},
|
|
30015
|
+
name,
|
|
30016
|
+
spanAttributes: { type: "tool" /* TOOL */ },
|
|
30017
|
+
spanId,
|
|
30018
|
+
startTime: eventTime2(event)
|
|
30019
|
+
});
|
|
30020
|
+
span.log({ input: action.input, metadata });
|
|
30021
|
+
this.toolsByCallKey.set(key, {
|
|
30022
|
+
metadata,
|
|
30023
|
+
span,
|
|
30024
|
+
turnKey: turnKey2(sessionId, event.data.turnId)
|
|
30025
|
+
});
|
|
30026
|
+
}
|
|
30027
|
+
async startSyntheticTool(event, ctx, result, hookMetadata) {
|
|
30028
|
+
const turn = await this.ensureTurn(event, ctx, hookMetadata);
|
|
30029
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30030
|
+
if (!turn || !sessionId) {
|
|
30031
|
+
return void 0;
|
|
30032
|
+
}
|
|
30033
|
+
const metadata = toolMetadataFromTurn(turn);
|
|
30034
|
+
const { rowId: eventId, spanId } = await generateEveIds(
|
|
30035
|
+
"tool",
|
|
30036
|
+
sessionId,
|
|
30037
|
+
event.data.turnId,
|
|
30038
|
+
result.callId
|
|
30039
|
+
);
|
|
30040
|
+
const existing = this.toolsByCallKey.get(toolKey3(sessionId, result.callId));
|
|
30041
|
+
if (existing) {
|
|
30042
|
+
return existing;
|
|
30043
|
+
}
|
|
30044
|
+
const span = await this.startEveChildSpan(turn.span, {
|
|
30045
|
+
event: {
|
|
30046
|
+
id: eventId,
|
|
30047
|
+
metadata
|
|
30048
|
+
},
|
|
30049
|
+
name: result.toolName,
|
|
30050
|
+
spanAttributes: { type: "tool" /* TOOL */ },
|
|
30051
|
+
spanId,
|
|
30052
|
+
startTime: eventTime2(event)
|
|
30053
|
+
});
|
|
30054
|
+
span.log({ metadata });
|
|
30055
|
+
const state = {
|
|
30056
|
+
metadata,
|
|
30057
|
+
span,
|
|
30058
|
+
turnKey: turnKey2(sessionId, event.data.turnId)
|
|
30059
|
+
};
|
|
30060
|
+
this.toolsByCallKey.set(toolKey3(sessionId, result.callId), state);
|
|
30061
|
+
return state;
|
|
30062
|
+
}
|
|
30063
|
+
async startSyntheticSubagent(event, ctx, hookMetadata) {
|
|
30064
|
+
const turn = await this.ensureTurn(event, ctx, hookMetadata);
|
|
30065
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30066
|
+
if (!turn || !sessionId) {
|
|
30067
|
+
return void 0;
|
|
30068
|
+
}
|
|
30069
|
+
const metadata = toolMetadataFromTurn(turn);
|
|
30070
|
+
const { rowId: eventId, spanId } = await generateEveIds(
|
|
30071
|
+
"subagent",
|
|
30072
|
+
sessionId,
|
|
30073
|
+
event.data.callId
|
|
30074
|
+
);
|
|
30075
|
+
const existing = this.toolsByCallKey.get(
|
|
30076
|
+
toolKey3(sessionId, event.data.callId)
|
|
30077
|
+
);
|
|
30078
|
+
if (existing) {
|
|
30079
|
+
return existing;
|
|
30080
|
+
}
|
|
30081
|
+
const span = await this.startEveChildSpan(turn.span, {
|
|
30082
|
+
event: {
|
|
30083
|
+
id: eventId,
|
|
30084
|
+
metadata
|
|
30085
|
+
},
|
|
30086
|
+
name: event.data.subagentName,
|
|
30087
|
+
spanAttributes: { type: "tool" /* TOOL */ },
|
|
30088
|
+
spanId,
|
|
30089
|
+
startTime: eventTime2(event)
|
|
30090
|
+
});
|
|
30091
|
+
span.log({ metadata });
|
|
30092
|
+
const state = {
|
|
30093
|
+
metadata,
|
|
30094
|
+
span,
|
|
30095
|
+
turnKey: turnKey2(sessionId, event.data.turnId)
|
|
30096
|
+
};
|
|
30097
|
+
this.toolsByCallKey.set(toolKey3(sessionId, event.data.callId), state);
|
|
30098
|
+
return state;
|
|
30099
|
+
}
|
|
30100
|
+
async startSyntheticSubagentResult(event, ctx, result, hookMetadata) {
|
|
30101
|
+
const turn = await this.ensureTurn(event, ctx, hookMetadata);
|
|
30102
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30103
|
+
if (!turn || !sessionId) {
|
|
30104
|
+
return void 0;
|
|
30105
|
+
}
|
|
30106
|
+
const metadata = toolMetadataFromTurn(turn);
|
|
30107
|
+
const { rowId: eventId, spanId } = await generateEveIds(
|
|
30108
|
+
"subagent",
|
|
30109
|
+
sessionId,
|
|
30110
|
+
result.callId
|
|
30111
|
+
);
|
|
30112
|
+
const existing = this.toolsByCallKey.get(toolKey3(sessionId, result.callId));
|
|
30113
|
+
if (existing) {
|
|
30114
|
+
return existing;
|
|
30115
|
+
}
|
|
30116
|
+
const span = await this.startEveChildSpan(turn.span, {
|
|
30117
|
+
event: {
|
|
30118
|
+
id: eventId,
|
|
30119
|
+
metadata
|
|
30120
|
+
},
|
|
30121
|
+
name: result.subagentName,
|
|
30122
|
+
spanAttributes: { type: "tool" /* TOOL */ },
|
|
30123
|
+
spanId,
|
|
30124
|
+
startTime: eventTime2(event)
|
|
30125
|
+
});
|
|
30126
|
+
span.log({ metadata });
|
|
30127
|
+
const state = {
|
|
30128
|
+
metadata,
|
|
30129
|
+
span,
|
|
30130
|
+
turnKey: turnKey2(sessionId, event.data.turnId)
|
|
30131
|
+
};
|
|
30132
|
+
this.toolsByCallKey.set(toolKey3(sessionId, result.callId), state);
|
|
30133
|
+
return state;
|
|
30134
|
+
}
|
|
30135
|
+
async startTurnSpan(session, event, metadata) {
|
|
30136
|
+
const { rowId: eventId, spanId } = await generateEveIds(
|
|
30137
|
+
"turn",
|
|
30138
|
+
session.sessionId,
|
|
30139
|
+
event.data.turnId
|
|
30140
|
+
);
|
|
30141
|
+
return await this.startEveSpan({
|
|
30142
|
+
event: {
|
|
30143
|
+
id: eventId,
|
|
30144
|
+
metadata
|
|
30145
|
+
},
|
|
30146
|
+
name: "eve.turn",
|
|
30147
|
+
parentSpanIds: {
|
|
30148
|
+
rootSpanId: session.span.rootSpanId,
|
|
30149
|
+
spanId: session.span.spanId
|
|
30150
|
+
},
|
|
30151
|
+
spanAttributes: { type: "task" /* TASK */ },
|
|
30152
|
+
spanId,
|
|
30153
|
+
startTime: eventTime2(event)
|
|
30154
|
+
});
|
|
30155
|
+
}
|
|
30156
|
+
turnForEvent(event, ctx) {
|
|
30157
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30158
|
+
return sessionId ? this.turnsByKey.get(turnKey2(sessionId, event.data.turnId)) : void 0;
|
|
30159
|
+
}
|
|
30160
|
+
stepForEvent(event, ctx) {
|
|
30161
|
+
return this.turnForEvent(event, ctx)?.stepsByIndex.get(
|
|
30162
|
+
event.data.stepIndex
|
|
30163
|
+
);
|
|
30164
|
+
}
|
|
30165
|
+
finalizeTurn(turn, args) {
|
|
30166
|
+
const { endTime } = args;
|
|
30167
|
+
for (const step of turn.stepsByIndex.values()) {
|
|
30168
|
+
step.span.log({
|
|
30169
|
+
...step.input !== void 0 ? { input: step.input } : {},
|
|
30170
|
+
metadata: step.metadata,
|
|
30171
|
+
metrics: step.metrics,
|
|
30172
|
+
output: step.output
|
|
30173
|
+
});
|
|
30174
|
+
step.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30175
|
+
}
|
|
30176
|
+
turn.stepsByIndex.clear();
|
|
30177
|
+
for (const tool of this.toolsByCallKey.values()) {
|
|
30178
|
+
if (tool.turnKey !== turn.key) {
|
|
30179
|
+
continue;
|
|
30180
|
+
}
|
|
30181
|
+
if (tool.endedByTurn) {
|
|
30182
|
+
continue;
|
|
30183
|
+
}
|
|
30184
|
+
tool.span.log({ metadata: tool.metadata });
|
|
30185
|
+
tool.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30186
|
+
tool.endedByTurn = true;
|
|
30187
|
+
}
|
|
30188
|
+
if (args.error) {
|
|
30189
|
+
turn.span.log({ error: args.error });
|
|
30190
|
+
} else {
|
|
30191
|
+
turn.span.log({
|
|
30192
|
+
metadata: turn.metadata,
|
|
30193
|
+
metrics: turn.metrics,
|
|
30194
|
+
output: turn.output
|
|
30195
|
+
});
|
|
30196
|
+
}
|
|
30197
|
+
turn.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30198
|
+
this.turnsByKey.delete(turn.key);
|
|
30199
|
+
this.state.update((current) => {
|
|
30200
|
+
const normalized = normalizeEveTraceState(current);
|
|
30201
|
+
return {
|
|
30202
|
+
...normalized,
|
|
30203
|
+
stepStarts: normalized.stepStarts.filter(
|
|
30204
|
+
(entry) => entry.turnId !== turn.turnId
|
|
30205
|
+
)
|
|
30206
|
+
};
|
|
30207
|
+
});
|
|
30208
|
+
}
|
|
30209
|
+
cleanupSession(sessionId) {
|
|
30210
|
+
const keyPrefix = `${sessionId}:`;
|
|
30211
|
+
this.sessionsById.delete(sessionId);
|
|
30212
|
+
for (const key of this.turnsByKey.keys()) {
|
|
30213
|
+
if (key.startsWith(keyPrefix)) {
|
|
30214
|
+
this.turnsByKey.delete(key);
|
|
30215
|
+
}
|
|
30216
|
+
}
|
|
30217
|
+
for (const key of this.toolsByCallKey.keys()) {
|
|
30218
|
+
if (key.startsWith(keyPrefix)) {
|
|
30219
|
+
this.toolsByCallKey.delete(key);
|
|
30220
|
+
}
|
|
30221
|
+
}
|
|
30222
|
+
for (const key of this.completedToolKeys.keys()) {
|
|
30223
|
+
if (key.startsWith(keyPrefix)) {
|
|
30224
|
+
this.completedToolKeys.delete(key);
|
|
30225
|
+
}
|
|
30226
|
+
}
|
|
30227
|
+
this.state.update(() => emptyEveTraceState());
|
|
30228
|
+
}
|
|
30229
|
+
async flushInstrumentation() {
|
|
30230
|
+
try {
|
|
30231
|
+
await flush();
|
|
30232
|
+
return true;
|
|
30233
|
+
} catch (error) {
|
|
30234
|
+
debugLogger.warn("Error in Eve flush instrumentation:", error);
|
|
30235
|
+
return false;
|
|
30236
|
+
}
|
|
30237
|
+
}
|
|
30238
|
+
};
|
|
30239
|
+
function emptyEveTraceState() {
|
|
30240
|
+
return {
|
|
30241
|
+
llmInputs: [],
|
|
30242
|
+
metadata: {},
|
|
30243
|
+
spanReferences: [],
|
|
30244
|
+
stepStarts: []
|
|
30245
|
+
};
|
|
30246
|
+
}
|
|
30247
|
+
function normalizeEveTraceState(state) {
|
|
30248
|
+
if (!isObject(state)) {
|
|
30249
|
+
return emptyEveTraceState();
|
|
30250
|
+
}
|
|
30251
|
+
const metadata = isObject(state["metadata"]) ? state["metadata"] : {};
|
|
30252
|
+
const spanReferences = Array.isArray(state["spanReferences"]) ? state["spanReferences"].flatMap((entry) => {
|
|
30253
|
+
if (!isObject(entry)) {
|
|
30254
|
+
return [];
|
|
30255
|
+
}
|
|
30256
|
+
const exported = entry["exported"];
|
|
30257
|
+
const endTime = entry["endTime"];
|
|
30258
|
+
const rootSpanId = entry["rootSpanId"];
|
|
30259
|
+
const rowId = entry["rowId"];
|
|
30260
|
+
const spanId = entry["spanId"];
|
|
30261
|
+
const startEvent = entry["startEvent"];
|
|
30262
|
+
const startEventCreated = isObject(startEvent) ? startEvent["created"] : void 0;
|
|
30263
|
+
const startEventMetrics = isObject(startEvent) ? startEvent["metrics"] : void 0;
|
|
30264
|
+
const startEventSpanAttributes = isObject(startEvent) ? startEvent["span_attributes"] : void 0;
|
|
30265
|
+
const startEventSpanParents = isObject(startEvent) ? startEvent["span_parents"] : void 0;
|
|
30266
|
+
const normalizedStartEvent = typeof startEventCreated === "string" && isObject(startEventMetrics) && typeof startEventMetrics["start"] === "number" && Number.isFinite(startEventMetrics["start"]) && isObject(startEventSpanAttributes) && Array.isArray(startEventSpanParents) && startEventSpanParents.every(
|
|
30267
|
+
(parent) => typeof parent === "string"
|
|
30268
|
+
) ? {
|
|
30269
|
+
created: startEventCreated,
|
|
30270
|
+
metrics: { start: startEventMetrics["start"] },
|
|
30271
|
+
span_attributes: { ...startEventSpanAttributes },
|
|
30272
|
+
span_parents: [...startEventSpanParents]
|
|
30273
|
+
} : void 0;
|
|
30274
|
+
return typeof exported === "string" && typeof rootSpanId === "string" && typeof rowId === "string" && typeof spanId === "string" ? [
|
|
30275
|
+
{
|
|
30276
|
+
...typeof endTime === "number" && Number.isFinite(endTime) ? { endTime } : {},
|
|
30277
|
+
exported,
|
|
30278
|
+
rootSpanId,
|
|
30279
|
+
rowId,
|
|
30280
|
+
spanId,
|
|
30281
|
+
...normalizedStartEvent ? { startEvent: normalizedStartEvent } : {}
|
|
30282
|
+
}
|
|
30283
|
+
] : [];
|
|
30284
|
+
}).slice(-MAX_STORED_SPAN_REFERENCES) : [];
|
|
30285
|
+
const llmInputs = Array.isArray(state["llmInputs"]) ? state["llmInputs"].flatMap((entry) => {
|
|
30286
|
+
if (!isObject(entry)) {
|
|
30287
|
+
return [];
|
|
30288
|
+
}
|
|
30289
|
+
const key = entry["key"];
|
|
30290
|
+
const input = entry["input"];
|
|
30291
|
+
return typeof key === "string" && isCapturedModelInput(input) ? [{ input, key }] : [];
|
|
30292
|
+
}).slice(-MAX_STORED_LLM_INPUTS) : [];
|
|
30293
|
+
const stepStarts = Array.isArray(state["stepStarts"]) ? state["stepStarts"].flatMap((entry) => {
|
|
30294
|
+
if (!isObject(entry)) {
|
|
30295
|
+
return [];
|
|
30296
|
+
}
|
|
30297
|
+
const ordinal = entry["ordinal"];
|
|
30298
|
+
const open = entry["open"];
|
|
30299
|
+
const stepIndex = entry["stepIndex"];
|
|
30300
|
+
const turnId = entry["turnId"];
|
|
30301
|
+
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 }] : [];
|
|
30302
|
+
}).slice(-MAX_STORED_STEP_STARTS) : [];
|
|
30303
|
+
return { llmInputs, metadata: { ...metadata }, spanReferences, stepStarts };
|
|
30304
|
+
}
|
|
30305
|
+
function readEveTraceState(state) {
|
|
30306
|
+
try {
|
|
30307
|
+
return normalizeEveTraceState(state.get());
|
|
30308
|
+
} catch {
|
|
30309
|
+
return emptyEveTraceState();
|
|
30310
|
+
}
|
|
30311
|
+
}
|
|
30312
|
+
function captureEveModelInput(state, input) {
|
|
30313
|
+
if (!isObject(input)) {
|
|
30314
|
+
return;
|
|
30315
|
+
}
|
|
30316
|
+
const session = input["session"];
|
|
30317
|
+
const turn = input["turn"];
|
|
30318
|
+
const step = input["step"];
|
|
30319
|
+
if (!isObject(session) || !isObject(turn) || !isObject(step)) {
|
|
30320
|
+
return;
|
|
30321
|
+
}
|
|
30322
|
+
const sessionId = session["id"];
|
|
30323
|
+
const turnId = turn["id"];
|
|
30324
|
+
const stepIndex = step["index"];
|
|
30325
|
+
if (typeof sessionId !== "string" || typeof turnId !== "string" || typeof stepIndex !== "number" || !Number.isInteger(stepIndex)) {
|
|
30326
|
+
return;
|
|
30327
|
+
}
|
|
30328
|
+
const captured = capturedModelInput(input["modelInput"]);
|
|
30329
|
+
if (!captured) {
|
|
30330
|
+
return;
|
|
30331
|
+
}
|
|
30332
|
+
const key = llmInputKey(sessionId, turnId, stepIndex);
|
|
30333
|
+
state.update((current) => {
|
|
30334
|
+
const normalized = normalizeEveTraceState(current);
|
|
30335
|
+
const llmInputs = [...normalized.llmInputs, { input: captured, key }];
|
|
30336
|
+
return {
|
|
30337
|
+
...normalized,
|
|
30338
|
+
llmInputs: llmInputs.slice(-MAX_STORED_LLM_INPUTS)
|
|
30339
|
+
};
|
|
30340
|
+
});
|
|
30341
|
+
}
|
|
30342
|
+
function consumeCapturedEveModelInput(state, sessionId, turnId, stepIndex) {
|
|
30343
|
+
try {
|
|
30344
|
+
const key = llmInputKey(sessionId, turnId, stepIndex);
|
|
30345
|
+
let input;
|
|
30346
|
+
state.update((current) => {
|
|
30347
|
+
const normalized = normalizeEveTraceState(current);
|
|
30348
|
+
const index = normalized.llmInputs.findIndex(
|
|
30349
|
+
(candidate) => candidate.key === key
|
|
30350
|
+
);
|
|
30351
|
+
if (index < 0) {
|
|
30352
|
+
return normalized;
|
|
30353
|
+
}
|
|
30354
|
+
input = normalized.llmInputs[index]?.input;
|
|
30355
|
+
return {
|
|
30356
|
+
...normalized,
|
|
30357
|
+
llmInputs: normalized.llmInputs.filter(
|
|
30358
|
+
(_, candidateIndex) => candidateIndex !== index
|
|
30359
|
+
)
|
|
30360
|
+
};
|
|
30361
|
+
});
|
|
30362
|
+
return input;
|
|
30363
|
+
} catch (error) {
|
|
30364
|
+
debugLogger.warn("Error in Eve LLM input consumption:", error);
|
|
30365
|
+
return void 0;
|
|
30366
|
+
}
|
|
30367
|
+
}
|
|
30368
|
+
function capturedModelInput(modelInput) {
|
|
30369
|
+
if (!isObject(modelInput)) {
|
|
30370
|
+
return void 0;
|
|
30371
|
+
}
|
|
30372
|
+
const messages = modelInput["messages"];
|
|
30373
|
+
if (!Array.isArray(messages)) {
|
|
30374
|
+
return void 0;
|
|
30375
|
+
}
|
|
30376
|
+
const instructions = modelInput["instructions"];
|
|
30377
|
+
const value = [
|
|
30378
|
+
...instructions !== void 0 ? [{ content: instructions, role: "system" }] : [],
|
|
30379
|
+
...messages
|
|
30380
|
+
];
|
|
30381
|
+
try {
|
|
30382
|
+
const cloned = JSON.parse(JSON.stringify(value));
|
|
30383
|
+
if (!Array.isArray(cloned)) {
|
|
30384
|
+
return void 0;
|
|
30385
|
+
}
|
|
30386
|
+
return cloned;
|
|
30387
|
+
} catch {
|
|
30388
|
+
return void 0;
|
|
30389
|
+
}
|
|
30390
|
+
}
|
|
30391
|
+
function isCapturedModelInput(input) {
|
|
30392
|
+
return Array.isArray(input);
|
|
30393
|
+
}
|
|
30394
|
+
function llmInputKey(sessionId, turnId, stepIndex) {
|
|
30395
|
+
return `${sessionId}\0${turnId}\0${stepIndex}`;
|
|
30396
|
+
}
|
|
30397
|
+
function modelMetadataFromRuntime(runtime) {
|
|
30398
|
+
if (!isObject(runtime)) {
|
|
30399
|
+
return {};
|
|
30400
|
+
}
|
|
30401
|
+
const modelId = runtime["modelId"];
|
|
30402
|
+
return typeof modelId === "string" ? modelMetadataFromModelId(modelId) : {};
|
|
30403
|
+
}
|
|
30404
|
+
function modelMetadataFromModelId(modelId) {
|
|
30405
|
+
const normalized = modelId.trim();
|
|
30406
|
+
if (!normalized) {
|
|
30407
|
+
return {};
|
|
30408
|
+
}
|
|
30409
|
+
const slashIndex = normalized.indexOf("/");
|
|
30410
|
+
if (slashIndex > 0 && slashIndex < normalized.length - 1) {
|
|
30411
|
+
return {
|
|
30412
|
+
model: normalized.slice(slashIndex + 1),
|
|
30413
|
+
provider: normalized.slice(0, slashIndex)
|
|
30414
|
+
};
|
|
30415
|
+
}
|
|
30416
|
+
return {
|
|
30417
|
+
model: normalized
|
|
30418
|
+
};
|
|
30419
|
+
}
|
|
30420
|
+
function sessionIdFromContext(ctx) {
|
|
30421
|
+
if (!isObject(ctx)) {
|
|
30422
|
+
return void 0;
|
|
30423
|
+
}
|
|
30424
|
+
const session = ctx["session"];
|
|
30425
|
+
if (!isObject(session)) {
|
|
30426
|
+
return void 0;
|
|
30427
|
+
}
|
|
30428
|
+
const id = session["id"];
|
|
30429
|
+
return typeof id === "string" ? id : void 0;
|
|
30430
|
+
}
|
|
30431
|
+
function toolMetadataFromTurn(turn) {
|
|
30432
|
+
const { model: _model, provider: _provider, ...metadata } = turn.metadata;
|
|
30433
|
+
return metadata;
|
|
30434
|
+
}
|
|
30435
|
+
function parentLineageFromContext(ctx) {
|
|
30436
|
+
if (!isObject(ctx)) {
|
|
30437
|
+
return void 0;
|
|
30438
|
+
}
|
|
30439
|
+
const session = ctx.session;
|
|
30440
|
+
if (!isObject(session)) {
|
|
30441
|
+
return void 0;
|
|
30442
|
+
}
|
|
30443
|
+
const parent = session["parent"];
|
|
30444
|
+
if (!isObject(parent)) {
|
|
30445
|
+
return void 0;
|
|
30446
|
+
}
|
|
30447
|
+
const callId = parent["callId"];
|
|
30448
|
+
const rootSessionId = parent["rootSessionId"];
|
|
30449
|
+
const sessionId = parent["sessionId"];
|
|
30450
|
+
if (typeof callId !== "string" || typeof rootSessionId !== "string" || typeof sessionId !== "string") {
|
|
30451
|
+
return void 0;
|
|
30452
|
+
}
|
|
30453
|
+
return { callId, rootSessionId, sessionId };
|
|
30454
|
+
}
|
|
30455
|
+
function isToolCallAction(action) {
|
|
30456
|
+
return isObject(action) && action["kind"] === "tool-call" && typeof action["callId"] === "string" && typeof action["toolName"] === "string" && isObject(action["input"]);
|
|
30457
|
+
}
|
|
30458
|
+
function isLocalSubagentCallAction(action) {
|
|
30459
|
+
return isObject(action) && action["kind"] === "subagent-call" && typeof action["callId"] === "string" && isObject(action["input"]);
|
|
30460
|
+
}
|
|
30461
|
+
function isTraceableActionRequest(action) {
|
|
30462
|
+
return isToolCallAction(action) || isLocalSubagentCallAction(action);
|
|
30463
|
+
}
|
|
30464
|
+
function isToolResult(result) {
|
|
30465
|
+
return isObject(result) && result["kind"] === "tool-result" && typeof result["callId"] === "string" && typeof result["toolName"] === "string";
|
|
30466
|
+
}
|
|
30467
|
+
function isSubagentResult(result) {
|
|
30468
|
+
return isObject(result) && result["kind"] === "subagent-result" && typeof result["callId"] === "string" && typeof result["subagentName"] === "string";
|
|
30469
|
+
}
|
|
30470
|
+
function normalizedFinishReason(finishReason) {
|
|
30471
|
+
switch (finishReason) {
|
|
30472
|
+
case "content-filter":
|
|
30473
|
+
return "content_filter";
|
|
30474
|
+
case "tool-calls":
|
|
30475
|
+
return "tool_calls";
|
|
30476
|
+
default:
|
|
30477
|
+
return finishReason;
|
|
30478
|
+
}
|
|
30479
|
+
}
|
|
30480
|
+
function errorFromMessage(message, code, details) {
|
|
30481
|
+
const error = new Error(`${code}: ${message}`);
|
|
30482
|
+
if (details !== void 0) {
|
|
30483
|
+
error.cause = details;
|
|
30484
|
+
}
|
|
30485
|
+
return error;
|
|
30486
|
+
}
|
|
30487
|
+
function actionResultError(error, output) {
|
|
30488
|
+
if (error) {
|
|
30489
|
+
return errorFromMessage(error.message, error.code);
|
|
30490
|
+
}
|
|
30491
|
+
const result = new Error("Eve action failed");
|
|
30492
|
+
if (output !== void 0) {
|
|
30493
|
+
result.cause = output;
|
|
30494
|
+
}
|
|
30495
|
+
return result;
|
|
30496
|
+
}
|
|
30497
|
+
function eventTime2(event) {
|
|
30498
|
+
if (!event.meta?.at) {
|
|
30499
|
+
return void 0;
|
|
30500
|
+
}
|
|
30501
|
+
const timestamp = Date.parse(event.meta.at);
|
|
30502
|
+
return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
|
|
30503
|
+
}
|
|
30504
|
+
function turnKey2(sessionId, turnId) {
|
|
30505
|
+
return `${sessionId}:${turnId}`;
|
|
30506
|
+
}
|
|
30507
|
+
function toolKey3(sessionId, callId) {
|
|
30508
|
+
return `${sessionId}:${callId}`;
|
|
30509
|
+
}
|
|
30510
|
+
async function rootSpanIdForSession(sessionId) {
|
|
30511
|
+
return deterministicEveId("eve:root", sessionId);
|
|
30512
|
+
}
|
|
30513
|
+
async function generateEveIds(kind, ...parts) {
|
|
30514
|
+
const [rowId, spanId] = await Promise.all([
|
|
30515
|
+
deterministicEveId(`eve:row:${kind}`, ...parts),
|
|
30516
|
+
deterministicEveId(`eve:${kind}`, ...parts)
|
|
30517
|
+
]);
|
|
30518
|
+
return { rowId, spanId };
|
|
30519
|
+
}
|
|
30520
|
+
async function spanIdForSubagent(sessionId, callId) {
|
|
30521
|
+
return deterministicEveId("eve:subagent", sessionId, callId);
|
|
30522
|
+
}
|
|
30523
|
+
async function deterministicEveId(...parts) {
|
|
30524
|
+
const data = new TextEncoder().encode(
|
|
30525
|
+
parts.map((part) => `${part.length}:${part}`).join("\0")
|
|
30526
|
+
);
|
|
30527
|
+
const digest = await globalThis.crypto.subtle.digest("SHA-256", data);
|
|
30528
|
+
const bytes = Array.from(new Uint8Array(digest, 0, 16));
|
|
30529
|
+
const hex = bytes.map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
30530
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
30531
|
+
}
|
|
30532
|
+
|
|
28982
30533
|
// src/instrumentation/config.ts
|
|
28983
30534
|
var envIntegrationAliases = {
|
|
28984
30535
|
openai: "openai",
|
|
@@ -29188,6 +30739,8 @@ function configureInstrumentation(config) {
|
|
|
29188
30739
|
BasePlugin,
|
|
29189
30740
|
BraintrustPlugin,
|
|
29190
30741
|
OpenAIAgentsTraceProcessor,
|
|
30742
|
+
braintrustEveHook,
|
|
30743
|
+
braintrustEveInstrumentation,
|
|
29191
30744
|
braintrustFlueInstrumentation,
|
|
29192
30745
|
braintrustFlueObserver,
|
|
29193
30746
|
configureInstrumentation,
|