braintrust 3.21.0 → 3.23.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 +47 -0
- package/dev/dist/index.d.mts +1030 -1
- package/dev/dist/index.d.ts +1030 -1
- package/dev/dist/index.js +1429 -663
- package/dev/dist/index.mjs +811 -45
- package/dist/apply-auto-instrumentation.js +222 -186
- package/dist/apply-auto-instrumentation.mjs +37 -1
- package/dist/auto-instrumentations/bundler/esbuild.cjs +53 -1
- package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
- package/dist/auto-instrumentations/bundler/next.cjs +53 -1
- package/dist/auto-instrumentations/bundler/next.mjs +3 -3
- package/dist/auto-instrumentations/bundler/rollup.cjs +53 -1
- package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
- package/dist/auto-instrumentations/bundler/vite.cjs +53 -1
- package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
- package/dist/auto-instrumentations/bundler/webpack-loader.cjs +53 -1
- package/dist/auto-instrumentations/bundler/webpack.cjs +53 -1
- package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
- package/dist/auto-instrumentations/{chunk-TKRPRPGD.mjs → chunk-EXY7QCJD.mjs} +5 -2
- package/dist/auto-instrumentations/{chunk-T6J4C7LX.mjs → chunk-KIMLYPRW.mjs} +1 -1
- package/dist/auto-instrumentations/{chunk-BRQX23KL.mjs → chunk-YXLNSAMJ.mjs} +51 -0
- package/dist/auto-instrumentations/hook.mjs +224 -31
- package/dist/auto-instrumentations/index.cjs +52 -0
- package/dist/auto-instrumentations/index.d.mts +3 -1
- package/dist/auto-instrumentations/index.d.ts +3 -1
- package/dist/auto-instrumentations/index.mjs +3 -1
- package/dist/browser.d.mts +3273 -93
- package/dist/browser.d.ts +3273 -93
- package/dist/browser.js +2495 -63
- package/dist/browser.mjs +2495 -63
- package/dist/{chunk-KMGUTPB7.mjs → chunk-36IPYKMG.mjs} +20 -1
- package/dist/{chunk-BFGIH2ZJ.js → chunk-CDIKAHDZ.js} +21 -2
- package/dist/{chunk-FY7DAKA5.js → chunk-FZWPFCVE.js} +1590 -832
- package/dist/{chunk-O2P765XK.mjs → chunk-IXL4PMY4.mjs} +802 -44
- package/dist/cli.js +816 -47
- package/dist/edge-light.d.mts +1 -1
- package/dist/edge-light.d.ts +1 -1
- package/dist/edge-light.js +2495 -63
- package/dist/edge-light.mjs +2495 -63
- package/dist/index.d.mts +3273 -93
- package/dist/index.d.ts +3273 -93
- package/dist/index.js +2078 -416
- package/dist/index.mjs +1664 -2
- package/dist/instrumentation/index.d.mts +912 -2
- package/dist/instrumentation/index.d.ts +912 -2
- package/dist/instrumentation/index.js +2202 -42
- package/dist/instrumentation/index.mjs +2200 -42
- package/dist/vitest-evals-reporter.js +16 -16
- package/dist/vitest-evals-reporter.mjs +2 -2
- package/dist/workerd.d.mts +1 -1
- package/dist/workerd.d.ts +1 -1
- package/dist/workerd.js +2495 -63
- package/dist/workerd.mjs +2495 -63
- package/package.json +5 -2
|
@@ -2272,19 +2272,30 @@ var CallEvent = z6.union([
|
|
|
2272
2272
|
var ChatCompletionContentPartTextWithTitle = z6.object({
|
|
2273
2273
|
text: z6.string().default(""),
|
|
2274
2274
|
type: z6.literal("text"),
|
|
2275
|
-
cache_control: z6.object({
|
|
2275
|
+
cache_control: z6.object({
|
|
2276
|
+
type: z6.literal("ephemeral"),
|
|
2277
|
+
ttl: z6.enum(["5m", "1h"]).optional()
|
|
2278
|
+
}).optional()
|
|
2276
2279
|
});
|
|
2277
2280
|
var ChatCompletionContentPartImageWithTitle = z6.object({
|
|
2278
2281
|
image_url: z6.object({
|
|
2279
2282
|
url: z6.string(),
|
|
2280
2283
|
detail: z6.union([z6.literal("auto"), z6.literal("low"), z6.literal("high")]).optional()
|
|
2281
2284
|
}),
|
|
2282
|
-
type: z6.literal("image_url")
|
|
2285
|
+
type: z6.literal("image_url"),
|
|
2286
|
+
cache_control: z6.object({
|
|
2287
|
+
type: z6.literal("ephemeral"),
|
|
2288
|
+
ttl: z6.enum(["5m", "1h"]).optional()
|
|
2289
|
+
}).optional()
|
|
2283
2290
|
});
|
|
2284
2291
|
var ChatCompletionContentPartFileFile = z6.object({ file_data: z6.string(), filename: z6.string(), file_id: z6.string() }).partial();
|
|
2285
2292
|
var ChatCompletionContentPartFileWithTitle = z6.object({
|
|
2286
2293
|
file: ChatCompletionContentPartFileFile,
|
|
2287
|
-
type: z6.literal("file")
|
|
2294
|
+
type: z6.literal("file"),
|
|
2295
|
+
cache_control: z6.object({
|
|
2296
|
+
type: z6.literal("ephemeral"),
|
|
2297
|
+
ttl: z6.enum(["5m", "1h"]).optional()
|
|
2298
|
+
}).optional()
|
|
2288
2299
|
});
|
|
2289
2300
|
var ChatCompletionContentPart = z6.union([
|
|
2290
2301
|
ChatCompletionContentPartTextWithTitle,
|
|
@@ -2294,7 +2305,10 @@ var ChatCompletionContentPart = z6.union([
|
|
|
2294
2305
|
var ChatCompletionContentPartText = z6.object({
|
|
2295
2306
|
text: z6.string().default(""),
|
|
2296
2307
|
type: z6.literal("text"),
|
|
2297
|
-
cache_control: z6.object({
|
|
2308
|
+
cache_control: z6.object({
|
|
2309
|
+
type: z6.literal("ephemeral"),
|
|
2310
|
+
ttl: z6.enum(["5m", "1h"]).optional()
|
|
2311
|
+
}).optional()
|
|
2298
2312
|
});
|
|
2299
2313
|
var ChatCompletionMessageToolCall = z6.object({
|
|
2300
2314
|
id: z6.string(),
|
|
@@ -4303,7 +4317,7 @@ var DiskCache = class {
|
|
|
4303
4317
|
}
|
|
4304
4318
|
};
|
|
4305
4319
|
|
|
4306
|
-
// src/
|
|
4320
|
+
// src/lru-cache.ts
|
|
4307
4321
|
var LRUCache = class {
|
|
4308
4322
|
cache;
|
|
4309
4323
|
maxSize;
|
|
@@ -4319,13 +4333,23 @@ var LRUCache = class {
|
|
|
4319
4333
|
* @returns The cached value if found, undefined otherwise.
|
|
4320
4334
|
*/
|
|
4321
4335
|
get(key) {
|
|
4322
|
-
const
|
|
4323
|
-
if (
|
|
4336
|
+
const entry = this.cache.get(key);
|
|
4337
|
+
if (entry === void 0) {
|
|
4324
4338
|
return void 0;
|
|
4325
4339
|
}
|
|
4326
4340
|
this.cache.delete(key);
|
|
4327
|
-
this.cache.set(key,
|
|
4328
|
-
return value;
|
|
4341
|
+
this.cache.set(key, entry);
|
|
4342
|
+
return entry.value;
|
|
4343
|
+
}
|
|
4344
|
+
/**
|
|
4345
|
+
* Checks whether a key exists and marks it as most recently used.
|
|
4346
|
+
*/
|
|
4347
|
+
has(key) {
|
|
4348
|
+
if (!this.cache.has(key)) {
|
|
4349
|
+
return false;
|
|
4350
|
+
}
|
|
4351
|
+
this.get(key);
|
|
4352
|
+
return true;
|
|
4329
4353
|
}
|
|
4330
4354
|
/**
|
|
4331
4355
|
* Stores a value in the cache.
|
|
@@ -4342,7 +4366,38 @@ var LRUCache = class {
|
|
|
4342
4366
|
const first = this.cache.keys().next().value;
|
|
4343
4367
|
this.cache.delete(first);
|
|
4344
4368
|
}
|
|
4345
|
-
this.cache.set(key, value);
|
|
4369
|
+
this.cache.set(key, { value });
|
|
4370
|
+
}
|
|
4371
|
+
/**
|
|
4372
|
+
* Removes an item from the cache.
|
|
4373
|
+
*/
|
|
4374
|
+
delete(key) {
|
|
4375
|
+
return this.cache.delete(key);
|
|
4376
|
+
}
|
|
4377
|
+
/**
|
|
4378
|
+
* Iterates over cache entries from least to most recently used.
|
|
4379
|
+
*/
|
|
4380
|
+
*entries() {
|
|
4381
|
+
for (const [key, entry] of this.cache) {
|
|
4382
|
+
yield [key, entry.value];
|
|
4383
|
+
}
|
|
4384
|
+
}
|
|
4385
|
+
/**
|
|
4386
|
+
* Iterates over cache keys from least to most recently used.
|
|
4387
|
+
*/
|
|
4388
|
+
keys() {
|
|
4389
|
+
return this.cache.keys();
|
|
4390
|
+
}
|
|
4391
|
+
/**
|
|
4392
|
+
* Iterates over cache values from least to most recently used.
|
|
4393
|
+
*/
|
|
4394
|
+
*values() {
|
|
4395
|
+
for (const entry of this.cache.values()) {
|
|
4396
|
+
yield entry.value;
|
|
4397
|
+
}
|
|
4398
|
+
}
|
|
4399
|
+
[Symbol.iterator]() {
|
|
4400
|
+
return this.entries();
|
|
4346
4401
|
}
|
|
4347
4402
|
/**
|
|
4348
4403
|
* Removes all items from the cache.
|
|
@@ -4900,6 +4955,9 @@ function applyMaskingToField(maskingFunction, data, fieldName) {
|
|
|
4900
4955
|
return `ERROR: Failed to mask field '${fieldName}' - ${errorType}`;
|
|
4901
4956
|
}
|
|
4902
4957
|
}
|
|
4958
|
+
var INITIAL_SPAN_WRITE_AS_MERGE = /* @__PURE__ */ Symbol(
|
|
4959
|
+
"braintrust.initial-span-write-as-merge"
|
|
4960
|
+
);
|
|
4903
4961
|
var BRAINTRUST_CURRENT_SPAN_STORE = /* @__PURE__ */ Symbol.for(
|
|
4904
4962
|
"braintrust.currentSpanStore"
|
|
4905
4963
|
);
|
|
@@ -5456,25 +5514,46 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
5456
5514
|
})
|
|
5457
5515
|
);
|
|
5458
5516
|
}
|
|
5459
|
-
async post(path, params, config) {
|
|
5517
|
+
async post(path, params, config, retries = 0) {
|
|
5460
5518
|
const { headers, ...rest } = config || {};
|
|
5461
5519
|
const this_fetch = this.fetch;
|
|
5462
5520
|
const this_base_url = this.base_url;
|
|
5463
5521
|
const this_headers = this.headers;
|
|
5464
|
-
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
|
|
5474
|
-
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
|
|
5522
|
+
const tries = retries + 1;
|
|
5523
|
+
for (let i = 0; i < tries; i++) {
|
|
5524
|
+
try {
|
|
5525
|
+
return await checkResponse(
|
|
5526
|
+
await this_fetch(_urljoin(this_base_url, path), {
|
|
5527
|
+
method: "POST",
|
|
5528
|
+
headers: {
|
|
5529
|
+
Accept: "application/json",
|
|
5530
|
+
"Content-Type": "application/json",
|
|
5531
|
+
...this_headers,
|
|
5532
|
+
...headers
|
|
5533
|
+
},
|
|
5534
|
+
body: typeof params === "string" ? params : params ? JSON.stringify(params) : void 0,
|
|
5535
|
+
keepalive: true,
|
|
5536
|
+
...rest
|
|
5537
|
+
})
|
|
5538
|
+
);
|
|
5539
|
+
} catch (error) {
|
|
5540
|
+
if (config?.signal?.aborted) {
|
|
5541
|
+
throw getAbortReason(config.signal);
|
|
5542
|
+
}
|
|
5543
|
+
if (i === tries - 1 || !isRetryableHTTPError(error)) {
|
|
5544
|
+
throw error;
|
|
5545
|
+
}
|
|
5546
|
+
debugLogger.debug(
|
|
5547
|
+
`Retrying API request ${path} after ${formatHTTPError(error)}`
|
|
5548
|
+
);
|
|
5549
|
+
const sleepTimeMs = HTTP_RETRY_BASE_SLEEP_TIME_S * 1e3 * 2 ** i + Math.random() * HTTP_RETRY_JITTER_MS;
|
|
5550
|
+
debugLogger.info(
|
|
5551
|
+
`Sleeping for ${sleepTimeMs}ms before retrying API request`
|
|
5552
|
+
);
|
|
5553
|
+
await waitForRetry(sleepTimeMs, config?.signal);
|
|
5554
|
+
}
|
|
5555
|
+
}
|
|
5556
|
+
throw new Error("Unexpected retry state");
|
|
5478
5557
|
}
|
|
5479
5558
|
async get_json(object_type, args = void 0, retries = 0) {
|
|
5480
5559
|
const tries = retries + 1;
|
|
@@ -5898,6 +5977,28 @@ function updateSpanImpl({
|
|
|
5898
5977
|
}));
|
|
5899
5978
|
state.bgLogger().log([record]);
|
|
5900
5979
|
}
|
|
5980
|
+
function updateSpan({
|
|
5981
|
+
exported,
|
|
5982
|
+
state,
|
|
5983
|
+
...event
|
|
5984
|
+
}) {
|
|
5985
|
+
const resolvedState = state ?? _globalState;
|
|
5986
|
+
const components = SpanComponentsV4.fromStr(exported);
|
|
5987
|
+
if (!components.data.row_id) {
|
|
5988
|
+
throw new Error("Exported span must have a row id");
|
|
5989
|
+
}
|
|
5990
|
+
updateSpanImpl({
|
|
5991
|
+
state: resolvedState,
|
|
5992
|
+
parentObjectType: components.data.object_type,
|
|
5993
|
+
parentObjectId: new LazyValue(
|
|
5994
|
+
spanComponentsToObjectIdLambda(resolvedState, components)
|
|
5995
|
+
),
|
|
5996
|
+
id: components.data.row_id,
|
|
5997
|
+
root_span_id: components.data.root_span_id,
|
|
5998
|
+
span_id: components.data.span_id,
|
|
5999
|
+
event
|
|
6000
|
+
});
|
|
6001
|
+
}
|
|
5901
6002
|
function spanComponentsToObjectIdLambda(state, components) {
|
|
5902
6003
|
if (components.data.object_id) {
|
|
5903
6004
|
const ret = components.data.object_id;
|
|
@@ -6374,6 +6475,45 @@ function now() {
|
|
|
6374
6475
|
var DEFAULT_FLUSH_BACKPRESSURE_BYTES = 10 * 1024 * 1024;
|
|
6375
6476
|
var BACKGROUND_LOGGER_BASE_SLEEP_TIME_S = 1;
|
|
6376
6477
|
var HTTP_RETRY_BASE_SLEEP_TIME_S = 1;
|
|
6478
|
+
var HTTP_RETRY_JITTER_MS = 200;
|
|
6479
|
+
var BTQL_HTTP_RETRIES = 3;
|
|
6480
|
+
var RETRYABLE_HTTP_STATUS_CODES = /* @__PURE__ */ new Set([500, 502, 503, 504]);
|
|
6481
|
+
function isRetryableHTTPError(error) {
|
|
6482
|
+
return !(error instanceof FailedHTTPResponse) || RETRYABLE_HTTP_STATUS_CODES.has(error.status);
|
|
6483
|
+
}
|
|
6484
|
+
function formatHTTPError(error) {
|
|
6485
|
+
if (error instanceof FailedHTTPResponse) {
|
|
6486
|
+
return `${error.status} ${error.text}`;
|
|
6487
|
+
}
|
|
6488
|
+
return error instanceof Error ? error.message : String(error);
|
|
6489
|
+
}
|
|
6490
|
+
function getAbortReason(signal) {
|
|
6491
|
+
return signal.reason ?? new Error("Request aborted");
|
|
6492
|
+
}
|
|
6493
|
+
async function waitForRetry(delayMs, signal) {
|
|
6494
|
+
if (!signal) {
|
|
6495
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
6496
|
+
return;
|
|
6497
|
+
}
|
|
6498
|
+
if (signal.aborted) {
|
|
6499
|
+
throw getAbortReason(signal);
|
|
6500
|
+
}
|
|
6501
|
+
await new Promise((resolve, reject) => {
|
|
6502
|
+
const onAbort = () => {
|
|
6503
|
+
clearTimeout(timeout);
|
|
6504
|
+
signal.removeEventListener("abort", onAbort);
|
|
6505
|
+
reject(getAbortReason(signal));
|
|
6506
|
+
};
|
|
6507
|
+
const timeout = setTimeout(() => {
|
|
6508
|
+
signal.removeEventListener("abort", onAbort);
|
|
6509
|
+
resolve();
|
|
6510
|
+
}, delayMs);
|
|
6511
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
6512
|
+
if (signal.aborted) {
|
|
6513
|
+
onAbort();
|
|
6514
|
+
}
|
|
6515
|
+
});
|
|
6516
|
+
}
|
|
6377
6517
|
var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
|
|
6378
6518
|
apiConn;
|
|
6379
6519
|
queue;
|
|
@@ -7325,21 +7465,27 @@ function parentSpanIdsUsable(spanId, rootSpanId) {
|
|
|
7325
7465
|
return Boolean(spanId) && Boolean(rootSpanId);
|
|
7326
7466
|
}
|
|
7327
7467
|
function logError(span, error) {
|
|
7328
|
-
let
|
|
7468
|
+
let errorMessage2 = "<error>";
|
|
7329
7469
|
let stackTrace = "";
|
|
7330
7470
|
if (error instanceof Error) {
|
|
7331
|
-
|
|
7471
|
+
errorMessage2 = error.message;
|
|
7332
7472
|
stackTrace = error.stack || "";
|
|
7333
7473
|
} else {
|
|
7334
|
-
|
|
7474
|
+
errorMessage2 = String(error);
|
|
7335
7475
|
}
|
|
7336
|
-
span.log({ error: `${
|
|
7476
|
+
span.log({ error: `${errorMessage2}
|
|
7337
7477
|
|
|
7338
7478
|
${stackTrace}` });
|
|
7339
7479
|
}
|
|
7340
7480
|
function startSpan(args) {
|
|
7341
7481
|
return startSpanAndIsLogger(args).span;
|
|
7342
7482
|
}
|
|
7483
|
+
function _internalStartSpanWithInitialMerge(args) {
|
|
7484
|
+
return startSpanAndIsLogger({
|
|
7485
|
+
...args,
|
|
7486
|
+
[INITIAL_SPAN_WRITE_AS_MERGE]: true
|
|
7487
|
+
}).span;
|
|
7488
|
+
}
|
|
7343
7489
|
async function flush(options) {
|
|
7344
7490
|
const state = options?.state ?? _globalState;
|
|
7345
7491
|
return await state.bgLogger().flush();
|
|
@@ -7668,7 +7814,8 @@ var ObjectFetcher = class {
|
|
|
7668
7814
|
version: this.pinnedVersion
|
|
7669
7815
|
} : {}
|
|
7670
7816
|
},
|
|
7671
|
-
{ headers: { "Accept-Encoding": "gzip" } }
|
|
7817
|
+
{ headers: { "Accept-Encoding": "gzip" } },
|
|
7818
|
+
BTQL_HTTP_RETRIES
|
|
7672
7819
|
);
|
|
7673
7820
|
const respJson = await resp.json();
|
|
7674
7821
|
const mutate = this.mutateRecord;
|
|
@@ -8144,7 +8291,7 @@ var SpanImpl = class _SpanImpl {
|
|
|
8144
8291
|
this._spanId = resolvedIds.spanId;
|
|
8145
8292
|
this._rootSpanId = resolvedIds.rootSpanId;
|
|
8146
8293
|
this._spanParents = resolvedIds.spanParents;
|
|
8147
|
-
this.isMerge =
|
|
8294
|
+
this.isMerge = args[INITIAL_SPAN_WRITE_AS_MERGE] === true;
|
|
8148
8295
|
this.logInternal({ event, internalData });
|
|
8149
8296
|
this.isMerge = true;
|
|
8150
8297
|
}
|
|
@@ -27058,6 +27205,446 @@ function isBraintrustHandler(handler) {
|
|
|
27058
27205
|
return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
27059
27206
|
}
|
|
27060
27207
|
|
|
27208
|
+
// src/instrumentation/plugins/langsmith-channels.ts
|
|
27209
|
+
var langSmithChannels = defineChannels("langsmith", {
|
|
27210
|
+
createRun: channel({
|
|
27211
|
+
channelName: "Client.createRun",
|
|
27212
|
+
kind: "async"
|
|
27213
|
+
}),
|
|
27214
|
+
updateRun: channel({
|
|
27215
|
+
channelName: "Client.updateRun",
|
|
27216
|
+
kind: "async"
|
|
27217
|
+
}),
|
|
27218
|
+
batchIngestRuns: channel({
|
|
27219
|
+
channelName: "Client.batchIngestRuns",
|
|
27220
|
+
kind: "async"
|
|
27221
|
+
})
|
|
27222
|
+
});
|
|
27223
|
+
|
|
27224
|
+
// src/instrumentation/plugins/langsmith-plugin.ts
|
|
27225
|
+
var MAX_COMPLETED_RUNS = 1e4;
|
|
27226
|
+
var BLOCKED_METADATA_KEYS = /* @__PURE__ */ new Set([
|
|
27227
|
+
"__proto__",
|
|
27228
|
+
"constructor",
|
|
27229
|
+
"prototype",
|
|
27230
|
+
"usage_metadata"
|
|
27231
|
+
]);
|
|
27232
|
+
var BLOCKED_METADATA_PREFIXES = ["__pregel_", "langgraph_", "lc_"];
|
|
27233
|
+
var LLM_SETTING_KEYS = [
|
|
27234
|
+
"temperature",
|
|
27235
|
+
"top_p",
|
|
27236
|
+
"max_tokens",
|
|
27237
|
+
"frequency_penalty",
|
|
27238
|
+
"presence_penalty",
|
|
27239
|
+
"stop",
|
|
27240
|
+
"response_format"
|
|
27241
|
+
];
|
|
27242
|
+
var LangSmithPlugin = class extends BasePlugin {
|
|
27243
|
+
activeRuns = /* @__PURE__ */ new Map();
|
|
27244
|
+
completedRuns = new LRUCache({
|
|
27245
|
+
max: MAX_COMPLETED_RUNS
|
|
27246
|
+
});
|
|
27247
|
+
skipLangChainRuns;
|
|
27248
|
+
constructor(options = {}) {
|
|
27249
|
+
super();
|
|
27250
|
+
this.skipLangChainRuns = options.skipLangChainRuns ?? true;
|
|
27251
|
+
}
|
|
27252
|
+
onEnable() {
|
|
27253
|
+
const createChannel = langSmithChannels.createRun.tracingChannel();
|
|
27254
|
+
const createHandlers = {
|
|
27255
|
+
start: (event) => {
|
|
27256
|
+
this.containLifecycleFailure("createRun", () => {
|
|
27257
|
+
this.processCreate(event.arguments[0]);
|
|
27258
|
+
});
|
|
27259
|
+
}
|
|
27260
|
+
};
|
|
27261
|
+
createChannel.subscribe(createHandlers);
|
|
27262
|
+
this.unsubscribers.push(() => createChannel.unsubscribe(createHandlers));
|
|
27263
|
+
const updateChannel = langSmithChannels.updateRun.tracingChannel();
|
|
27264
|
+
const updateHandlers = {
|
|
27265
|
+
start: (event) => {
|
|
27266
|
+
this.containLifecycleFailure("updateRun", () => {
|
|
27267
|
+
this.processUpdate(event.arguments[0], event.arguments[1]);
|
|
27268
|
+
});
|
|
27269
|
+
}
|
|
27270
|
+
};
|
|
27271
|
+
updateChannel.subscribe(updateHandlers);
|
|
27272
|
+
this.unsubscribers.push(() => updateChannel.unsubscribe(updateHandlers));
|
|
27273
|
+
const batchChannel = langSmithChannels.batchIngestRuns.tracingChannel();
|
|
27274
|
+
const batchHandlers = {
|
|
27275
|
+
start: (event) => {
|
|
27276
|
+
this.containLifecycleFailure("batchIngestRuns", () => {
|
|
27277
|
+
this.processBatch(event.arguments[0]);
|
|
27278
|
+
});
|
|
27279
|
+
}
|
|
27280
|
+
};
|
|
27281
|
+
batchChannel.subscribe(batchHandlers);
|
|
27282
|
+
this.unsubscribers.push(() => batchChannel.unsubscribe(batchHandlers));
|
|
27283
|
+
}
|
|
27284
|
+
onDisable() {
|
|
27285
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
27286
|
+
for (const { span } of this.activeRuns.values()) {
|
|
27287
|
+
span.end();
|
|
27288
|
+
}
|
|
27289
|
+
this.activeRuns.clear();
|
|
27290
|
+
this.completedRuns.clear();
|
|
27291
|
+
}
|
|
27292
|
+
processBatch(batch) {
|
|
27293
|
+
if (!isRecord2(batch)) {
|
|
27294
|
+
return;
|
|
27295
|
+
}
|
|
27296
|
+
const creates = ownValue(batch, "runCreates");
|
|
27297
|
+
if (Array.isArray(creates)) {
|
|
27298
|
+
const parentFirst = [...creates].sort((left, right) => {
|
|
27299
|
+
const leftId = stringValue2(ownValue(left, "id"));
|
|
27300
|
+
const rightId = stringValue2(ownValue(right, "id"));
|
|
27301
|
+
const leftParent = stringValue2(ownValue(left, "parent_run_id"));
|
|
27302
|
+
const rightParent = stringValue2(ownValue(right, "parent_run_id"));
|
|
27303
|
+
if (leftParent && leftParent === rightId) {
|
|
27304
|
+
return 1;
|
|
27305
|
+
}
|
|
27306
|
+
if (rightParent && rightParent === leftId) {
|
|
27307
|
+
return -1;
|
|
27308
|
+
}
|
|
27309
|
+
return dottedOrderDepth(left) - dottedOrderDepth(right);
|
|
27310
|
+
});
|
|
27311
|
+
for (const run of parentFirst) {
|
|
27312
|
+
this.containLifecycleFailure("batchIngestRuns create", () => {
|
|
27313
|
+
this.processCreate(run);
|
|
27314
|
+
});
|
|
27315
|
+
}
|
|
27316
|
+
}
|
|
27317
|
+
const updates = ownValue(batch, "runUpdates");
|
|
27318
|
+
if (Array.isArray(updates)) {
|
|
27319
|
+
for (const run of updates) {
|
|
27320
|
+
this.containLifecycleFailure("batchIngestRuns update", () => {
|
|
27321
|
+
this.processUpdate(stringValue2(ownValue(run, "id")) ?? "", run);
|
|
27322
|
+
});
|
|
27323
|
+
}
|
|
27324
|
+
}
|
|
27325
|
+
}
|
|
27326
|
+
processCreate(run) {
|
|
27327
|
+
const id = stringValue2(ownValue(run, "id"));
|
|
27328
|
+
if (!id || this.completedRuns.get(id)) {
|
|
27329
|
+
return;
|
|
27330
|
+
}
|
|
27331
|
+
if (this.shouldSkipLangChainRun(run)) {
|
|
27332
|
+
this.completedRuns.set(id, true);
|
|
27333
|
+
return;
|
|
27334
|
+
}
|
|
27335
|
+
const active = this.activeRuns.get(id);
|
|
27336
|
+
if (active) {
|
|
27337
|
+
const previous = active.run;
|
|
27338
|
+
active.run = mergeRuns(previous, run);
|
|
27339
|
+
this.logRun(
|
|
27340
|
+
active.span,
|
|
27341
|
+
active.run,
|
|
27342
|
+
previous,
|
|
27343
|
+
timestampSeconds(ownValue(active.run, "end_time")) !== void 0 || errorMessage(ownValue(active.run, "error")) !== void 0
|
|
27344
|
+
);
|
|
27345
|
+
this.endIfComplete(id, active, active.run);
|
|
27346
|
+
return;
|
|
27347
|
+
}
|
|
27348
|
+
const span = this.startRunSpan(id, run);
|
|
27349
|
+
const activeRun = { run, span };
|
|
27350
|
+
this.activeRuns.set(id, activeRun);
|
|
27351
|
+
this.logRun(
|
|
27352
|
+
span,
|
|
27353
|
+
run,
|
|
27354
|
+
void 0,
|
|
27355
|
+
timestampSeconds(ownValue(run, "end_time")) !== void 0 || errorMessage(ownValue(run, "error")) !== void 0
|
|
27356
|
+
);
|
|
27357
|
+
this.endIfComplete(id, activeRun, run);
|
|
27358
|
+
}
|
|
27359
|
+
processUpdate(explicitId, run) {
|
|
27360
|
+
const id = stringValue2(explicitId) ?? stringValue2(ownValue(run, "id"));
|
|
27361
|
+
if (!id || this.completedRuns.get(id)) {
|
|
27362
|
+
return;
|
|
27363
|
+
}
|
|
27364
|
+
if (this.shouldSkipLangChainRun(run)) {
|
|
27365
|
+
const active2 = this.activeRuns.get(id);
|
|
27366
|
+
active2?.span.end();
|
|
27367
|
+
this.activeRuns.delete(id);
|
|
27368
|
+
this.completedRuns.set(id, true);
|
|
27369
|
+
return;
|
|
27370
|
+
}
|
|
27371
|
+
let active = this.activeRuns.get(id);
|
|
27372
|
+
if (!active) {
|
|
27373
|
+
const span = this.startRunSpan(id, run);
|
|
27374
|
+
active = { run, span };
|
|
27375
|
+
this.activeRuns.set(id, active);
|
|
27376
|
+
}
|
|
27377
|
+
const previous = active.run;
|
|
27378
|
+
active.run = mergeRuns(previous, run);
|
|
27379
|
+
this.logRun(active.span, active.run, previous, true);
|
|
27380
|
+
this.endIfComplete(id, active, active.run);
|
|
27381
|
+
}
|
|
27382
|
+
startRunSpan(id, run) {
|
|
27383
|
+
const traceId = stringValue2(ownValue(run, "trace_id")) ?? id;
|
|
27384
|
+
const parentId = stringValue2(ownValue(run, "parent_run_id")) ?? stringValue2(ownValue(ownValue(run, "parent_run"), "id"));
|
|
27385
|
+
const startTime = timestampSeconds(ownValue(run, "start_time"));
|
|
27386
|
+
return startSpan({
|
|
27387
|
+
name: stringValue2(ownValue(run, "name")) ?? "LangSmith run",
|
|
27388
|
+
spanId: id,
|
|
27389
|
+
parentSpanIds: {
|
|
27390
|
+
parentSpanIds: parentId ? [parentId] : [],
|
|
27391
|
+
rootSpanId: traceId
|
|
27392
|
+
},
|
|
27393
|
+
spanAttributes: {
|
|
27394
|
+
type: mapRunType(ownValue(run, "run_type"))
|
|
27395
|
+
},
|
|
27396
|
+
...startTime === void 0 ? {} : { startTime },
|
|
27397
|
+
event: { id }
|
|
27398
|
+
});
|
|
27399
|
+
}
|
|
27400
|
+
logRun(span, run, previous, includeOutput) {
|
|
27401
|
+
const inputs = preferOwnValue(run, previous, "inputs");
|
|
27402
|
+
const outputs = preferOwnValue(run, previous, "outputs");
|
|
27403
|
+
const error = errorMessage(preferOwnValue(run, previous, "error"));
|
|
27404
|
+
const metadata = extractMetadata(run, previous);
|
|
27405
|
+
const tags = extractTags(preferOwnValue(run, previous, "tags"));
|
|
27406
|
+
const metrics = extractMetrics(run, previous);
|
|
27407
|
+
span.log({
|
|
27408
|
+
...inputs === void 0 ? {} : { input: sanitizeLoggedValue(inputs) },
|
|
27409
|
+
...includeOutput && outputs !== void 0 ? { output: sanitizeLoggedValue(outputs) } : {},
|
|
27410
|
+
...error === void 0 ? {} : { error },
|
|
27411
|
+
...metadata === void 0 ? {} : { metadata },
|
|
27412
|
+
...tags === void 0 ? {} : { tags },
|
|
27413
|
+
...Object.keys(metrics).length === 0 ? {} : { metrics }
|
|
27414
|
+
});
|
|
27415
|
+
}
|
|
27416
|
+
endIfComplete(id, active, run) {
|
|
27417
|
+
const endTime = timestampSeconds(ownValue(run, "end_time"));
|
|
27418
|
+
if (endTime === void 0 && errorMessage(ownValue(run, "error")) === void 0) {
|
|
27419
|
+
return;
|
|
27420
|
+
}
|
|
27421
|
+
active.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
27422
|
+
this.activeRuns.delete(id);
|
|
27423
|
+
this.completedRuns.set(id, true);
|
|
27424
|
+
}
|
|
27425
|
+
shouldSkipLangChainRun(run) {
|
|
27426
|
+
if (!this.skipLangChainRuns) {
|
|
27427
|
+
return false;
|
|
27428
|
+
}
|
|
27429
|
+
const serialized = ownValue(run, "serialized");
|
|
27430
|
+
return isRecord2(serialized) && ownValue(serialized, "lc") === 1;
|
|
27431
|
+
}
|
|
27432
|
+
containLifecycleFailure(operation, fn) {
|
|
27433
|
+
try {
|
|
27434
|
+
fn();
|
|
27435
|
+
} catch (error) {
|
|
27436
|
+
debugLogger.error(
|
|
27437
|
+
`Failed to process LangSmith ${operation} instrumentation:`,
|
|
27438
|
+
error
|
|
27439
|
+
);
|
|
27440
|
+
}
|
|
27441
|
+
}
|
|
27442
|
+
};
|
|
27443
|
+
function ownValue(value, key) {
|
|
27444
|
+
if (!isRecord2(value)) {
|
|
27445
|
+
return void 0;
|
|
27446
|
+
}
|
|
27447
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
27448
|
+
return descriptor && "value" in descriptor ? descriptor.value : void 0;
|
|
27449
|
+
}
|
|
27450
|
+
function preferOwnValue(current, previous, key) {
|
|
27451
|
+
const currentDescriptor = isRecord2(current) ? Object.getOwnPropertyDescriptor(current, key) : void 0;
|
|
27452
|
+
if (currentDescriptor && "value" in currentDescriptor) {
|
|
27453
|
+
return currentDescriptor.value;
|
|
27454
|
+
}
|
|
27455
|
+
return ownValue(previous, key);
|
|
27456
|
+
}
|
|
27457
|
+
function mergeRuns(previous, current) {
|
|
27458
|
+
const entries = /* @__PURE__ */ new Map();
|
|
27459
|
+
for (const value of [previous, current]) {
|
|
27460
|
+
if (!isRecord2(value)) {
|
|
27461
|
+
continue;
|
|
27462
|
+
}
|
|
27463
|
+
for (const [key, descriptor] of Object.entries(
|
|
27464
|
+
Object.getOwnPropertyDescriptors(value)
|
|
27465
|
+
)) {
|
|
27466
|
+
if (descriptor.enumerable && "value" in descriptor) {
|
|
27467
|
+
entries.set(key, descriptor.value);
|
|
27468
|
+
}
|
|
27469
|
+
}
|
|
27470
|
+
}
|
|
27471
|
+
return Object.fromEntries(entries);
|
|
27472
|
+
}
|
|
27473
|
+
function isRecord2(value) {
|
|
27474
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27475
|
+
}
|
|
27476
|
+
function stringValue2(value) {
|
|
27477
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
27478
|
+
}
|
|
27479
|
+
function timestampSeconds(value) {
|
|
27480
|
+
if (value instanceof Date) {
|
|
27481
|
+
const timestamp = value.getTime();
|
|
27482
|
+
return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
|
|
27483
|
+
}
|
|
27484
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
27485
|
+
return value > 1e10 ? value / 1e3 : value;
|
|
27486
|
+
}
|
|
27487
|
+
if (typeof value === "string") {
|
|
27488
|
+
const timestamp = Date.parse(value);
|
|
27489
|
+
return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
|
|
27490
|
+
}
|
|
27491
|
+
return void 0;
|
|
27492
|
+
}
|
|
27493
|
+
function dottedOrderDepth(run) {
|
|
27494
|
+
const dottedOrder = stringValue2(ownValue(run, "dotted_order"));
|
|
27495
|
+
return dottedOrder ? dottedOrder.split(".").length : Number.MAX_SAFE_INTEGER;
|
|
27496
|
+
}
|
|
27497
|
+
function mapRunType(runType) {
|
|
27498
|
+
switch (runType) {
|
|
27499
|
+
case "llm":
|
|
27500
|
+
case "embedding":
|
|
27501
|
+
return "llm" /* LLM */;
|
|
27502
|
+
case "tool":
|
|
27503
|
+
case "retriever":
|
|
27504
|
+
return "tool" /* TOOL */;
|
|
27505
|
+
default:
|
|
27506
|
+
return "task" /* TASK */;
|
|
27507
|
+
}
|
|
27508
|
+
}
|
|
27509
|
+
function extractMetadata(run, previous) {
|
|
27510
|
+
const extra = preferOwnValue(run, previous, "extra");
|
|
27511
|
+
const rawMetadata = ownValue(extra, "metadata");
|
|
27512
|
+
if (!isRecord2(rawMetadata)) {
|
|
27513
|
+
return void 0;
|
|
27514
|
+
}
|
|
27515
|
+
const metadata = {};
|
|
27516
|
+
for (const [key, descriptor] of Object.entries(
|
|
27517
|
+
Object.getOwnPropertyDescriptors(rawMetadata)
|
|
27518
|
+
)) {
|
|
27519
|
+
if (!("value" in descriptor) || !descriptor.enumerable || BLOCKED_METADATA_KEYS.has(key) || BLOCKED_METADATA_PREFIXES.some((prefix) => key.startsWith(prefix)) || key.startsWith("ls_") && key !== "ls_provider" && key !== "ls_model_name" && !LLM_SETTING_KEYS.some((setting) => key === `ls_${setting}`)) {
|
|
27520
|
+
continue;
|
|
27521
|
+
}
|
|
27522
|
+
const normalizedKey = key === "ls_provider" ? "provider" : key === "ls_model_name" ? "model" : key.startsWith("ls_") ? key.slice(3) : key;
|
|
27523
|
+
const sanitized = sanitizeLoggedValue(descriptor.value);
|
|
27524
|
+
if (sanitized !== void 0) {
|
|
27525
|
+
metadata[normalizedKey] = sanitized;
|
|
27526
|
+
}
|
|
27527
|
+
}
|
|
27528
|
+
return Object.keys(metadata).length === 0 ? void 0 : metadata;
|
|
27529
|
+
}
|
|
27530
|
+
function extractTags(value) {
|
|
27531
|
+
if (!Array.isArray(value)) {
|
|
27532
|
+
return void 0;
|
|
27533
|
+
}
|
|
27534
|
+
const tags = value.filter(
|
|
27535
|
+
(tag) => typeof tag === "string" && tag.length > 0
|
|
27536
|
+
);
|
|
27537
|
+
return tags.length > 0 ? tags : void 0;
|
|
27538
|
+
}
|
|
27539
|
+
function extractMetrics(run, previous) {
|
|
27540
|
+
const outputs = preferOwnValue(run, previous, "outputs");
|
|
27541
|
+
const extra = preferOwnValue(run, previous, "extra");
|
|
27542
|
+
const metadata = ownValue(extra, "metadata");
|
|
27543
|
+
const usage = ownValue(outputs, "usage_metadata") ?? ownValue(metadata, "usage_metadata");
|
|
27544
|
+
const metrics = {};
|
|
27545
|
+
assignFirstMetric(metrics, "prompt_tokens", usage, [
|
|
27546
|
+
"input_tokens",
|
|
27547
|
+
"prompt_tokens"
|
|
27548
|
+
]);
|
|
27549
|
+
assignFirstMetric(metrics, "completion_tokens", usage, [
|
|
27550
|
+
"output_tokens",
|
|
27551
|
+
"completion_tokens"
|
|
27552
|
+
]);
|
|
27553
|
+
assignFirstMetric(metrics, "tokens", usage, ["total_tokens", "tokens"]);
|
|
27554
|
+
const inputTokenDetails = ownValue(usage, "input_token_details");
|
|
27555
|
+
assignFirstMetric(metrics, "prompt_cached_tokens", inputTokenDetails, [
|
|
27556
|
+
"cache_read",
|
|
27557
|
+
"cached_tokens"
|
|
27558
|
+
]);
|
|
27559
|
+
if (metrics.prompt_cached_tokens === void 0) {
|
|
27560
|
+
assignFirstMetric(metrics, "prompt_cached_tokens", usage, [
|
|
27561
|
+
"cache_read_input_tokens",
|
|
27562
|
+
"prompt_cached_tokens"
|
|
27563
|
+
]);
|
|
27564
|
+
}
|
|
27565
|
+
assignFirstMetric(
|
|
27566
|
+
metrics,
|
|
27567
|
+
"prompt_cache_creation_tokens",
|
|
27568
|
+
inputTokenDetails,
|
|
27569
|
+
["cache_creation"]
|
|
27570
|
+
);
|
|
27571
|
+
if (metrics.prompt_cache_creation_tokens === void 0) {
|
|
27572
|
+
assignFirstMetric(metrics, "prompt_cache_creation_tokens", usage, [
|
|
27573
|
+
"cache_creation_input_tokens",
|
|
27574
|
+
"prompt_cache_creation_tokens"
|
|
27575
|
+
]);
|
|
27576
|
+
}
|
|
27577
|
+
if (metrics.tokens === void 0 && (metrics.prompt_tokens !== void 0 || metrics.completion_tokens !== void 0)) {
|
|
27578
|
+
metrics.tokens = (metrics.prompt_tokens ?? 0) + (metrics.completion_tokens ?? 0);
|
|
27579
|
+
}
|
|
27580
|
+
const startTime = timestampSeconds(
|
|
27581
|
+
preferOwnValue(run, previous, "start_time")
|
|
27582
|
+
);
|
|
27583
|
+
const events = preferOwnValue(run, previous, "events");
|
|
27584
|
+
if (startTime !== void 0 && Array.isArray(events)) {
|
|
27585
|
+
for (const event of events) {
|
|
27586
|
+
if (ownValue(event, "name") !== "new_token") {
|
|
27587
|
+
continue;
|
|
27588
|
+
}
|
|
27589
|
+
const eventTime3 = timestampSeconds(ownValue(event, "time"));
|
|
27590
|
+
if (eventTime3 !== void 0 && eventTime3 >= startTime) {
|
|
27591
|
+
metrics.time_to_first_token = eventTime3 - startTime;
|
|
27592
|
+
}
|
|
27593
|
+
break;
|
|
27594
|
+
}
|
|
27595
|
+
}
|
|
27596
|
+
return metrics;
|
|
27597
|
+
}
|
|
27598
|
+
function assignFirstMetric(metrics, target, source, keys) {
|
|
27599
|
+
for (const key of keys) {
|
|
27600
|
+
const value = ownValue(source, key);
|
|
27601
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
27602
|
+
metrics[target] = value;
|
|
27603
|
+
return;
|
|
27604
|
+
}
|
|
27605
|
+
}
|
|
27606
|
+
}
|
|
27607
|
+
function errorMessage(value) {
|
|
27608
|
+
if (typeof value === "string") {
|
|
27609
|
+
return value;
|
|
27610
|
+
}
|
|
27611
|
+
if (value instanceof Error) {
|
|
27612
|
+
return value.message;
|
|
27613
|
+
}
|
|
27614
|
+
return void 0;
|
|
27615
|
+
}
|
|
27616
|
+
function sanitizeLoggedValue(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
|
|
27617
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
27618
|
+
return value;
|
|
27619
|
+
}
|
|
27620
|
+
if (typeof value === "number") {
|
|
27621
|
+
return Number.isFinite(value) ? value : void 0;
|
|
27622
|
+
}
|
|
27623
|
+
if (value instanceof Date) {
|
|
27624
|
+
return Number.isFinite(value.getTime()) ? value.toISOString() : void 0;
|
|
27625
|
+
}
|
|
27626
|
+
if (typeof value !== "object" || depth >= 20) {
|
|
27627
|
+
return void 0;
|
|
27628
|
+
}
|
|
27629
|
+
if (seen.has(value)) {
|
|
27630
|
+
return "[Circular]";
|
|
27631
|
+
}
|
|
27632
|
+
seen.add(value);
|
|
27633
|
+
if (Array.isArray(value)) {
|
|
27634
|
+
return value.map((item) => sanitizeLoggedValue(item, seen, depth + 1));
|
|
27635
|
+
}
|
|
27636
|
+
const entries = [];
|
|
27637
|
+
for (const [key, descriptor] of Object.entries(
|
|
27638
|
+
Object.getOwnPropertyDescriptors(value)
|
|
27639
|
+
)) {
|
|
27640
|
+
if (!descriptor.enumerable || !("value" in descriptor) || BLOCKED_METADATA_KEYS.has(key)) {
|
|
27641
|
+
continue;
|
|
27642
|
+
}
|
|
27643
|
+
entries.push([key, sanitizeLoggedValue(descriptor.value, seen, depth + 1)]);
|
|
27644
|
+
}
|
|
27645
|
+
return Object.fromEntries(entries);
|
|
27646
|
+
}
|
|
27647
|
+
|
|
27061
27648
|
// src/instrumentation/plugins/pi-coding-agent-channels.ts
|
|
27062
27649
|
var piCodingAgentChannels = defineChannels(
|
|
27063
27650
|
"@earendil-works/pi-coding-agent",
|
|
@@ -27437,11 +28024,11 @@ function patchAssistantMessageStream(stream, promptState, llmState) {
|
|
|
27437
28024
|
function recordPiAssistantMessageEvent(promptState, llmState, event) {
|
|
27438
28025
|
recordFirstTokenMetric(llmState, event);
|
|
27439
28026
|
const message = "message" in event ? event.message : void 0;
|
|
27440
|
-
const
|
|
28027
|
+
const errorMessage2 = "error" in event ? event.error : void 0;
|
|
27441
28028
|
if (event.type === "done" && isPiAssistantMessage(message)) {
|
|
27442
28029
|
finishPiLlmSpan(promptState, llmState, message);
|
|
27443
|
-
} else if (event.type === "error" && isPiAssistantMessage(
|
|
27444
|
-
finishPiLlmSpan(promptState, llmState,
|
|
28030
|
+
} else if (event.type === "error" && isPiAssistantMessage(errorMessage2)) {
|
|
28031
|
+
finishPiLlmSpan(promptState, llmState, errorMessage2);
|
|
27445
28032
|
}
|
|
27446
28033
|
}
|
|
27447
28034
|
function recordFirstTokenMetric(state, event) {
|
|
@@ -27959,6 +28546,7 @@ var strandsAgentSDKChannels = defineChannels("@strands-agents/sdk", {
|
|
|
27959
28546
|
});
|
|
27960
28547
|
|
|
27961
28548
|
// src/instrumentation/plugins/strands-agent-sdk-plugin.ts
|
|
28549
|
+
var MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES = 32;
|
|
27962
28550
|
var StrandsAgentSDKPlugin = class extends BasePlugin {
|
|
27963
28551
|
activeChildParents = /* @__PURE__ */ new WeakMap();
|
|
27964
28552
|
onEnable() {
|
|
@@ -28103,11 +28691,16 @@ function startAgentStream(event, activeChildParents) {
|
|
|
28103
28691
|
...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
|
|
28104
28692
|
};
|
|
28105
28693
|
const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
|
|
28694
|
+
const attachmentCache = createStrandsAttachmentCache();
|
|
28695
|
+
const input = processStrandsInputAttachments(
|
|
28696
|
+
event.arguments[0],
|
|
28697
|
+
attachmentCache
|
|
28698
|
+
);
|
|
28106
28699
|
const span = parentSpan ? withCurrent(
|
|
28107
28700
|
parentSpan,
|
|
28108
28701
|
() => startSpan({
|
|
28109
28702
|
event: {
|
|
28110
|
-
input
|
|
28703
|
+
input,
|
|
28111
28704
|
metadata
|
|
28112
28705
|
},
|
|
28113
28706
|
name: formatAgentSpanName(agent),
|
|
@@ -28115,7 +28708,7 @@ function startAgentStream(event, activeChildParents) {
|
|
|
28115
28708
|
})
|
|
28116
28709
|
) : startSpan({
|
|
28117
28710
|
event: {
|
|
28118
|
-
input
|
|
28711
|
+
input,
|
|
28119
28712
|
metadata
|
|
28120
28713
|
},
|
|
28121
28714
|
name: formatAgentSpanName(agent),
|
|
@@ -28123,6 +28716,7 @@ function startAgentStream(event, activeChildParents) {
|
|
|
28123
28716
|
});
|
|
28124
28717
|
return {
|
|
28125
28718
|
activeTools: /* @__PURE__ */ new Map(),
|
|
28719
|
+
attachmentCache,
|
|
28126
28720
|
finalized: false,
|
|
28127
28721
|
metadata,
|
|
28128
28722
|
span,
|
|
@@ -28138,11 +28732,12 @@ function startMultiAgentStream(event, operation, activeChildParents) {
|
|
|
28138
28732
|
...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
|
|
28139
28733
|
};
|
|
28140
28734
|
const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
|
|
28735
|
+
const input = processStrandsInputAttachments(event.arguments[0]);
|
|
28141
28736
|
const span = parentSpan ? withCurrent(
|
|
28142
28737
|
parentSpan,
|
|
28143
28738
|
() => startSpan({
|
|
28144
28739
|
event: {
|
|
28145
|
-
input
|
|
28740
|
+
input,
|
|
28146
28741
|
metadata
|
|
28147
28742
|
},
|
|
28148
28743
|
name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
|
|
@@ -28150,7 +28745,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
|
|
|
28150
28745
|
})
|
|
28151
28746
|
) : startSpan({
|
|
28152
28747
|
event: {
|
|
28153
|
-
input
|
|
28748
|
+
input,
|
|
28154
28749
|
metadata
|
|
28155
28750
|
},
|
|
28156
28751
|
name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
|
|
@@ -28259,7 +28854,10 @@ function startModelSpan(state, event) {
|
|
|
28259
28854
|
state.span,
|
|
28260
28855
|
() => startSpan({
|
|
28261
28856
|
event: {
|
|
28262
|
-
input: Array.isArray(event.agent?.messages) ?
|
|
28857
|
+
input: Array.isArray(event.agent?.messages) ? processStrandsInputAttachments(
|
|
28858
|
+
event.agent.messages,
|
|
28859
|
+
state.attachmentCache
|
|
28860
|
+
) : void 0,
|
|
28263
28861
|
metadata
|
|
28264
28862
|
},
|
|
28265
28863
|
name: formatModelSpanName(model),
|
|
@@ -28473,6 +29071,7 @@ function finalizeAgentStream(state, error, output) {
|
|
|
28473
29071
|
...output !== void 0 ? { output } : {}
|
|
28474
29072
|
});
|
|
28475
29073
|
state.span.end();
|
|
29074
|
+
state.attachmentCache.strings.clear();
|
|
28476
29075
|
}
|
|
28477
29076
|
function finalizeMultiAgentStream(state, activeChildParents, error, output) {
|
|
28478
29077
|
if (state.finalized) {
|
|
@@ -28619,8 +29218,168 @@ function extractNodeResultOutput(result) {
|
|
|
28619
29218
|
}
|
|
28620
29219
|
return result;
|
|
28621
29220
|
}
|
|
28622
|
-
|
|
28623
|
-
|
|
29221
|
+
var STRANDS_MEDIA_TYPES = {
|
|
29222
|
+
png: "image/png",
|
|
29223
|
+
jpg: "image/jpeg",
|
|
29224
|
+
jpeg: "image/jpeg",
|
|
29225
|
+
gif: "image/gif",
|
|
29226
|
+
webp: "image/webp",
|
|
29227
|
+
mkv: "video/x-matroska",
|
|
29228
|
+
mov: "video/quicktime",
|
|
29229
|
+
mp4: "video/mp4",
|
|
29230
|
+
webm: "video/webm",
|
|
29231
|
+
flv: "video/x-flv",
|
|
29232
|
+
mpeg: "video/mpeg",
|
|
29233
|
+
mpg: "video/mpeg",
|
|
29234
|
+
wmv: "video/x-ms-wmv",
|
|
29235
|
+
"3gp": "video/3gpp",
|
|
29236
|
+
pdf: "application/pdf",
|
|
29237
|
+
csv: "text/csv",
|
|
29238
|
+
doc: "application/msword",
|
|
29239
|
+
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
29240
|
+
xls: "application/vnd.ms-excel",
|
|
29241
|
+
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
29242
|
+
html: "text/html",
|
|
29243
|
+
txt: "text/plain",
|
|
29244
|
+
md: "text/markdown",
|
|
29245
|
+
json: "application/json",
|
|
29246
|
+
xml: "application/xml"
|
|
29247
|
+
};
|
|
29248
|
+
function createStrandsAttachmentCache() {
|
|
29249
|
+
return {
|
|
29250
|
+
objects: /* @__PURE__ */ new WeakMap(),
|
|
29251
|
+
strings: new LRUCache({
|
|
29252
|
+
max: MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES
|
|
29253
|
+
})
|
|
29254
|
+
};
|
|
29255
|
+
}
|
|
29256
|
+
function processStrandsInputAttachments(input, cache = createStrandsAttachmentCache()) {
|
|
29257
|
+
try {
|
|
29258
|
+
return processStrandsInputNode(input, cache);
|
|
29259
|
+
} catch (error) {
|
|
29260
|
+
logInstrumentationError5("Strands Agent SDK input attachments", error);
|
|
29261
|
+
return input;
|
|
29262
|
+
}
|
|
29263
|
+
}
|
|
29264
|
+
function processStrandsInputNode(value, cache) {
|
|
29265
|
+
if (value instanceof BaseAttachment) {
|
|
29266
|
+
return value;
|
|
29267
|
+
}
|
|
29268
|
+
if (Array.isArray(value)) {
|
|
29269
|
+
return value.map((child) => processStrandsInputNode(child, cache));
|
|
29270
|
+
}
|
|
29271
|
+
if (!isObject(value)) {
|
|
29272
|
+
return value;
|
|
29273
|
+
}
|
|
29274
|
+
const directMedia = processDirectStrandsMediaBlock(value, cache);
|
|
29275
|
+
if (directMedia !== void 0) {
|
|
29276
|
+
return directMedia;
|
|
29277
|
+
}
|
|
29278
|
+
const wrappedMedia = processWrappedStrandsMediaBlock(value, cache);
|
|
29279
|
+
if (wrappedMedia !== void 0) {
|
|
29280
|
+
return wrappedMedia;
|
|
29281
|
+
}
|
|
29282
|
+
if (value.type === "message" && Array.isArray(value.content)) {
|
|
29283
|
+
return {
|
|
29284
|
+
role: value.role,
|
|
29285
|
+
content: value.content.map(
|
|
29286
|
+
(child) => processStrandsInputNode(child, cache)
|
|
29287
|
+
),
|
|
29288
|
+
...value.metadata !== void 0 ? { metadata: value.metadata } : {}
|
|
29289
|
+
};
|
|
29290
|
+
}
|
|
29291
|
+
if (typeof value.toJSON === "function") {
|
|
29292
|
+
return processStrandsInputNode(value.toJSON(), cache);
|
|
29293
|
+
}
|
|
29294
|
+
return Object.fromEntries(
|
|
29295
|
+
Object.entries(value).map(([key, child]) => [
|
|
29296
|
+
key,
|
|
29297
|
+
processStrandsInputNode(child, cache)
|
|
29298
|
+
])
|
|
29299
|
+
);
|
|
29300
|
+
}
|
|
29301
|
+
function processDirectStrandsMediaBlock(block, cache) {
|
|
29302
|
+
if (!isStrandsMediaBlock(block)) {
|
|
29303
|
+
return void 0;
|
|
29304
|
+
}
|
|
29305
|
+
const mediaKey = block.type === "imageBlock" ? "image" : block.type === "videoBlock" ? "video" : "document";
|
|
29306
|
+
return createStrandsMediaAttachment(mediaKey, block, cache);
|
|
29307
|
+
}
|
|
29308
|
+
function isStrandsMediaBlock(block) {
|
|
29309
|
+
return (block.type === "imageBlock" || block.type === "videoBlock" || block.type === "documentBlock") && typeof block.format === "string" && isObject(block.source);
|
|
29310
|
+
}
|
|
29311
|
+
function processWrappedStrandsMediaBlock(block, cache) {
|
|
29312
|
+
for (const mediaKey of ["image", "video", "document"]) {
|
|
29313
|
+
const media = block[mediaKey];
|
|
29314
|
+
if (!Object.hasOwn(block, mediaKey) || !isObject(media)) {
|
|
29315
|
+
continue;
|
|
29316
|
+
}
|
|
29317
|
+
const processed = createStrandsMediaAttachment(mediaKey, media, cache);
|
|
29318
|
+
if (processed !== void 0) {
|
|
29319
|
+
return processed;
|
|
29320
|
+
}
|
|
29321
|
+
}
|
|
29322
|
+
return void 0;
|
|
29323
|
+
}
|
|
29324
|
+
function createStrandsMediaAttachment(mediaKey, media, cache) {
|
|
29325
|
+
const format = media.format;
|
|
29326
|
+
const source = media.source;
|
|
29327
|
+
if (typeof format !== "string" || !isObject(source) || !Object.hasOwn(source, "bytes")) {
|
|
29328
|
+
return void 0;
|
|
29329
|
+
}
|
|
29330
|
+
const contentType = STRANDS_MEDIA_TYPES[format.toLowerCase()];
|
|
29331
|
+
if (!contentType) {
|
|
29332
|
+
return void 0;
|
|
29333
|
+
}
|
|
29334
|
+
const filename = mediaKey === "document" && typeof media.name === "string" && media.name.length > 0 ? media.name : `${mediaKey}.${format.toLowerCase()}`;
|
|
29335
|
+
const attachment = getOrCreateStrandsAttachment(
|
|
29336
|
+
source.bytes,
|
|
29337
|
+
filename,
|
|
29338
|
+
contentType,
|
|
29339
|
+
cache
|
|
29340
|
+
);
|
|
29341
|
+
if (!attachment) {
|
|
29342
|
+
return void 0;
|
|
29343
|
+
}
|
|
29344
|
+
const { type: _type, ...serializedMedia } = media;
|
|
29345
|
+
const { type: _sourceType, ...serializedSource } = source;
|
|
29346
|
+
return {
|
|
29347
|
+
[mediaKey]: {
|
|
29348
|
+
...serializedMedia,
|
|
29349
|
+
source: {
|
|
29350
|
+
...serializedSource,
|
|
29351
|
+
bytes: attachment
|
|
29352
|
+
}
|
|
29353
|
+
}
|
|
29354
|
+
};
|
|
29355
|
+
}
|
|
29356
|
+
function getOrCreateStrandsAttachment(data, filename, contentType, cache) {
|
|
29357
|
+
const key = `${contentType}\0${filename}`;
|
|
29358
|
+
const attachments = typeof data === "string" ? cache.strings.get(data) : isObject(data) ? cache.objects.get(data) : void 0;
|
|
29359
|
+
const cached = attachments?.get(key);
|
|
29360
|
+
if (cached) {
|
|
29361
|
+
return cached;
|
|
29362
|
+
}
|
|
29363
|
+
const blob = convertDataToBlob(data, contentType);
|
|
29364
|
+
if (!blob) {
|
|
29365
|
+
return void 0;
|
|
29366
|
+
}
|
|
29367
|
+
const attachment = new Attachment({
|
|
29368
|
+
data: blob,
|
|
29369
|
+
filename,
|
|
29370
|
+
contentType
|
|
29371
|
+
});
|
|
29372
|
+
const updatedAttachments = attachments ?? /* @__PURE__ */ new Map();
|
|
29373
|
+
updatedAttachments.set(key, attachment);
|
|
29374
|
+
if (typeof data === "string") {
|
|
29375
|
+
cache.strings.set(data, updatedAttachments);
|
|
29376
|
+
} else if (isObject(data)) {
|
|
29377
|
+
cache.objects.set(data, updatedAttachments);
|
|
29378
|
+
}
|
|
29379
|
+
return attachment;
|
|
29380
|
+
}
|
|
29381
|
+
function normalizeContentBlocks(blocks) {
|
|
29382
|
+
const text = blocks.map((block) => typeof block.text === "string" ? block.text : void 0).filter((part) => Boolean(part)).join("");
|
|
28624
29383
|
return text.length > 0 ? text : blocks;
|
|
28625
29384
|
}
|
|
28626
29385
|
function parseUsage(usage) {
|
|
@@ -28748,6 +29507,7 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
28748
29507
|
gitHubCopilotPlugin = null;
|
|
28749
29508
|
fluePlugin = null;
|
|
28750
29509
|
langChainPlugin = null;
|
|
29510
|
+
langSmithPlugin = null;
|
|
28751
29511
|
piCodingAgentPlugin = null;
|
|
28752
29512
|
strandsAgentSDKPlugin = null;
|
|
28753
29513
|
constructor(config = {}) {
|
|
@@ -28844,6 +29604,12 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
28844
29604
|
this.langChainPlugin = new LangChainPlugin();
|
|
28845
29605
|
this.langChainPlugin.enable();
|
|
28846
29606
|
}
|
|
29607
|
+
if (integrations.langsmith !== false) {
|
|
29608
|
+
this.langSmithPlugin = new LangSmithPlugin({
|
|
29609
|
+
skipLangChainRuns: integrations.langchain !== false
|
|
29610
|
+
});
|
|
29611
|
+
this.langSmithPlugin.enable();
|
|
29612
|
+
}
|
|
28847
29613
|
}
|
|
28848
29614
|
onDisable() {
|
|
28849
29615
|
if (this.openaiPlugin) {
|
|
@@ -28934,8 +29700,1396 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
28934
29700
|
this.langChainPlugin.disable();
|
|
28935
29701
|
this.langChainPlugin = null;
|
|
28936
29702
|
}
|
|
29703
|
+
if (this.langSmithPlugin) {
|
|
29704
|
+
this.langSmithPlugin.disable();
|
|
29705
|
+
this.langSmithPlugin = null;
|
|
29706
|
+
}
|
|
29707
|
+
}
|
|
29708
|
+
};
|
|
29709
|
+
|
|
29710
|
+
// src/instrumentation/plugins/eve-plugin.ts
|
|
29711
|
+
var EVE_TRACE_STATE_KEY = "braintrust.eve.tracing";
|
|
29712
|
+
var MAX_EVE_CACHE_ENTRIES = 1e4;
|
|
29713
|
+
var MAX_STORED_LLM_INPUTS = 100;
|
|
29714
|
+
var MAX_STORED_SPAN_REFERENCES = 1e4;
|
|
29715
|
+
var MAX_STORED_STEP_STARTS = 1e4;
|
|
29716
|
+
function braintrustEveHook(options) {
|
|
29717
|
+
const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
|
|
29718
|
+
const bridge = new EveBridge(state);
|
|
29719
|
+
return {
|
|
29720
|
+
events: {
|
|
29721
|
+
"*": async (event, ctx) => {
|
|
29722
|
+
await bridge.handle(event, ctx, options.metadata);
|
|
29723
|
+
}
|
|
29724
|
+
}
|
|
29725
|
+
};
|
|
29726
|
+
}
|
|
29727
|
+
function braintrustEveInstrumentation(options) {
|
|
29728
|
+
const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
|
|
29729
|
+
return {
|
|
29730
|
+
events: {
|
|
29731
|
+
"step.started": (input) => {
|
|
29732
|
+
try {
|
|
29733
|
+
captureEveModelInput(state, input);
|
|
29734
|
+
} catch (error) {
|
|
29735
|
+
debugLogger.warn("Error in Eve LLM input capture:", error);
|
|
29736
|
+
}
|
|
29737
|
+
}
|
|
29738
|
+
},
|
|
29739
|
+
recordInputs: false,
|
|
29740
|
+
recordOutputs: false,
|
|
29741
|
+
setup: options.setup
|
|
29742
|
+
};
|
|
29743
|
+
}
|
|
29744
|
+
function isEveHandleMessageStreamEvent(event) {
|
|
29745
|
+
return isObject(event) && typeof event["type"] === "string";
|
|
29746
|
+
}
|
|
29747
|
+
var ResumedEveSpan = class {
|
|
29748
|
+
constructor(reference) {
|
|
29749
|
+
this.reference = reference;
|
|
29750
|
+
this.endTime = reference.endTime;
|
|
29751
|
+
}
|
|
29752
|
+
endTime;
|
|
29753
|
+
get rootSpanId() {
|
|
29754
|
+
return this.reference.rootSpanId;
|
|
29755
|
+
}
|
|
29756
|
+
get spanId() {
|
|
29757
|
+
return this.reference.spanId;
|
|
29758
|
+
}
|
|
29759
|
+
log(event) {
|
|
29760
|
+
const metrics = {
|
|
29761
|
+
...this.reference.startEvent?.metrics,
|
|
29762
|
+
...this.endTime === void 0 ? {} : { end: this.endTime },
|
|
29763
|
+
...event.metrics
|
|
29764
|
+
};
|
|
29765
|
+
updateSpan({
|
|
29766
|
+
exported: this.reference.exported,
|
|
29767
|
+
...this.reference.startEvent,
|
|
29768
|
+
...event,
|
|
29769
|
+
...Object.keys(metrics).length > 0 ? { metrics } : {}
|
|
29770
|
+
});
|
|
29771
|
+
}
|
|
29772
|
+
end(args) {
|
|
29773
|
+
if (this.endTime === void 0) {
|
|
29774
|
+
this.endTime = args?.endTime ?? getCurrentUnixTimestamp();
|
|
29775
|
+
this.log({ metrics: { end: this.endTime } });
|
|
29776
|
+
}
|
|
29777
|
+
return this.endTime;
|
|
28937
29778
|
}
|
|
28938
29779
|
};
|
|
29780
|
+
var EveBridge = class {
|
|
29781
|
+
constructor(state) {
|
|
29782
|
+
this.state = state;
|
|
29783
|
+
}
|
|
29784
|
+
eventQueuesBySession = /* @__PURE__ */ new Map();
|
|
29785
|
+
completedToolKeys = new LRUCache({
|
|
29786
|
+
max: MAX_EVE_CACHE_ENTRIES
|
|
29787
|
+
});
|
|
29788
|
+
toolsByCallKey = new LRUCache({
|
|
29789
|
+
max: MAX_EVE_CACHE_ENTRIES
|
|
29790
|
+
});
|
|
29791
|
+
turnsByKey = new LRUCache({
|
|
29792
|
+
max: MAX_EVE_CACHE_ENTRIES
|
|
29793
|
+
});
|
|
29794
|
+
async startEveSpan(args) {
|
|
29795
|
+
const rowId = args?.event?.id;
|
|
29796
|
+
const reference = typeof rowId === "string" && readEveTraceState(this.state).spanReferences.find(
|
|
29797
|
+
(candidate) => candidate.rowId === rowId
|
|
29798
|
+
);
|
|
29799
|
+
if (reference) {
|
|
29800
|
+
return new ResumedEveSpan(reference);
|
|
29801
|
+
}
|
|
29802
|
+
const startTime = args?.startTime ?? getCurrentUnixTimestamp();
|
|
29803
|
+
const parentSpanIds = args?.parentSpanIds;
|
|
29804
|
+
const startEvent = {
|
|
29805
|
+
created: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29806
|
+
metrics: { start: startTime },
|
|
29807
|
+
span_attributes: {
|
|
29808
|
+
...args?.name ? { name: args.name } : {},
|
|
29809
|
+
...args?.type ? { type: args.type } : {},
|
|
29810
|
+
...args?.spanAttributes
|
|
29811
|
+
},
|
|
29812
|
+
span_parents: parentSpanIds ? "spanId" in parentSpanIds ? [parentSpanIds.spanId] : parentSpanIds.parentSpanIds : []
|
|
29813
|
+
};
|
|
29814
|
+
const span = withCurrent(
|
|
29815
|
+
NOOP_SPAN,
|
|
29816
|
+
() => _internalStartSpanWithInitialMerge({ ...args, startTime })
|
|
29817
|
+
);
|
|
29818
|
+
if (typeof rowId !== "string") {
|
|
29819
|
+
return span;
|
|
29820
|
+
}
|
|
29821
|
+
try {
|
|
29822
|
+
const exported = await span.export();
|
|
29823
|
+
const reference2 = {
|
|
29824
|
+
exported,
|
|
29825
|
+
rootSpanId: span.rootSpanId,
|
|
29826
|
+
rowId,
|
|
29827
|
+
spanId: span.spanId,
|
|
29828
|
+
startEvent
|
|
29829
|
+
};
|
|
29830
|
+
this.state.update((current) => {
|
|
29831
|
+
const normalized = normalizeEveTraceState(current);
|
|
29832
|
+
return normalized.spanReferences.some(
|
|
29833
|
+
(candidate) => candidate.rowId === rowId
|
|
29834
|
+
) ? normalized : {
|
|
29835
|
+
...normalized,
|
|
29836
|
+
spanReferences: [...normalized.spanReferences, reference2].slice(
|
|
29837
|
+
-MAX_STORED_SPAN_REFERENCES
|
|
29838
|
+
)
|
|
29839
|
+
};
|
|
29840
|
+
});
|
|
29841
|
+
} catch (error) {
|
|
29842
|
+
debugLogger.warn("Error exporting Eve span for resumption:", error);
|
|
29843
|
+
}
|
|
29844
|
+
return span;
|
|
29845
|
+
}
|
|
29846
|
+
async startEveChildSpan(parent, args) {
|
|
29847
|
+
return await this.startEveSpan({
|
|
29848
|
+
...args,
|
|
29849
|
+
parentSpanIds: {
|
|
29850
|
+
rootSpanId: parent.rootSpanId,
|
|
29851
|
+
spanId: parent.spanId
|
|
29852
|
+
}
|
|
29853
|
+
});
|
|
29854
|
+
}
|
|
29855
|
+
stepOrdinal(event) {
|
|
29856
|
+
let ordinal = 0;
|
|
29857
|
+
this.state.update((current) => {
|
|
29858
|
+
const state = normalizeEveTraceState(current);
|
|
29859
|
+
const previous = state.stepStarts.filter(
|
|
29860
|
+
(entry) => entry.turnId === event.data.turnId && entry.stepIndex === event.data.stepIndex
|
|
29861
|
+
).at(-1);
|
|
29862
|
+
if (previous?.open) {
|
|
29863
|
+
ordinal = previous.ordinal;
|
|
29864
|
+
return state;
|
|
29865
|
+
}
|
|
29866
|
+
ordinal = state.stepStarts.filter(
|
|
29867
|
+
(entry) => entry.turnId === event.data.turnId
|
|
29868
|
+
).length;
|
|
29869
|
+
return {
|
|
29870
|
+
...state,
|
|
29871
|
+
stepStarts: [
|
|
29872
|
+
...state.stepStarts,
|
|
29873
|
+
{
|
|
29874
|
+
open: true,
|
|
29875
|
+
ordinal,
|
|
29876
|
+
stepIndex: event.data.stepIndex,
|
|
29877
|
+
turnId: event.data.turnId
|
|
29878
|
+
}
|
|
29879
|
+
].slice(-MAX_STORED_STEP_STARTS)
|
|
29880
|
+
};
|
|
29881
|
+
});
|
|
29882
|
+
return ordinal;
|
|
29883
|
+
}
|
|
29884
|
+
markStepEnded(turnId, stepIndex) {
|
|
29885
|
+
this.state.update((current) => {
|
|
29886
|
+
const state = normalizeEveTraceState(current);
|
|
29887
|
+
let index = -1;
|
|
29888
|
+
for (let i = state.stepStarts.length - 1; i >= 0; i--) {
|
|
29889
|
+
const entry = state.stepStarts[i];
|
|
29890
|
+
if (entry?.turnId === turnId && entry.stepIndex === stepIndex) {
|
|
29891
|
+
index = i;
|
|
29892
|
+
break;
|
|
29893
|
+
}
|
|
29894
|
+
}
|
|
29895
|
+
if (index < 0 || !state.stepStarts[index]?.open) {
|
|
29896
|
+
return state;
|
|
29897
|
+
}
|
|
29898
|
+
return {
|
|
29899
|
+
...state,
|
|
29900
|
+
stepStarts: state.stepStarts.map(
|
|
29901
|
+
(entry, entryIndex) => entryIndex === index ? { ...entry, open: false } : entry
|
|
29902
|
+
)
|
|
29903
|
+
};
|
|
29904
|
+
});
|
|
29905
|
+
}
|
|
29906
|
+
async handle(event, ctx, hookMetadata) {
|
|
29907
|
+
if (!isEveHandleMessageStreamEvent(event)) {
|
|
29908
|
+
return;
|
|
29909
|
+
}
|
|
29910
|
+
const run = async () => {
|
|
29911
|
+
try {
|
|
29912
|
+
if (!await this.handleEvent(event, ctx, hookMetadata)) {
|
|
29913
|
+
return;
|
|
29914
|
+
}
|
|
29915
|
+
if (event.type === "session.failed") {
|
|
29916
|
+
const sessionId2 = event.data.sessionId || sessionIdFromContext(ctx);
|
|
29917
|
+
await this.flushInstrumentation();
|
|
29918
|
+
if (sessionId2) {
|
|
29919
|
+
this.cleanupSession(sessionId2);
|
|
29920
|
+
}
|
|
29921
|
+
} else if (event.type === "session.completed") {
|
|
29922
|
+
const sessionId2 = sessionIdFromContext(ctx);
|
|
29923
|
+
await this.flushInstrumentation();
|
|
29924
|
+
if (sessionId2) {
|
|
29925
|
+
this.cleanupSession(sessionId2);
|
|
29926
|
+
}
|
|
29927
|
+
}
|
|
29928
|
+
} catch (error) {
|
|
29929
|
+
debugLogger.warn("Error in Eve hook instrumentation:", error);
|
|
29930
|
+
}
|
|
29931
|
+
};
|
|
29932
|
+
const sessionId = event.type === "session.failed" ? event.data.sessionId || sessionIdFromContext(ctx) : sessionIdFromContext(ctx);
|
|
29933
|
+
if (!sessionId) {
|
|
29934
|
+
await run();
|
|
29935
|
+
return;
|
|
29936
|
+
}
|
|
29937
|
+
const previous = this.eventQueuesBySession.get(sessionId);
|
|
29938
|
+
const queued = previous ? previous.then(run) : run();
|
|
29939
|
+
this.eventQueuesBySession.set(sessionId, queued);
|
|
29940
|
+
try {
|
|
29941
|
+
await queued;
|
|
29942
|
+
} finally {
|
|
29943
|
+
if (this.eventQueuesBySession.get(sessionId) === queued) {
|
|
29944
|
+
this.eventQueuesBySession.delete(sessionId);
|
|
29945
|
+
}
|
|
29946
|
+
}
|
|
29947
|
+
}
|
|
29948
|
+
async handleEvent(event, ctx, hookMetadata) {
|
|
29949
|
+
switch (event.type) {
|
|
29950
|
+
case "session.started":
|
|
29951
|
+
this.handleSessionStarted(event, ctx, hookMetadata);
|
|
29952
|
+
return true;
|
|
29953
|
+
case "turn.started":
|
|
29954
|
+
await this.handleTurnStarted(event, ctx, hookMetadata);
|
|
29955
|
+
return true;
|
|
29956
|
+
case "message.received":
|
|
29957
|
+
await this.handleMessageReceived(event, ctx, hookMetadata);
|
|
29958
|
+
return true;
|
|
29959
|
+
case "step.started":
|
|
29960
|
+
await this.handleStepStarted(event, ctx, hookMetadata);
|
|
29961
|
+
return true;
|
|
29962
|
+
case "message.completed":
|
|
29963
|
+
this.handleMessageCompleted(event, ctx);
|
|
29964
|
+
return true;
|
|
29965
|
+
case "result.completed":
|
|
29966
|
+
this.handleResultCompleted(event, ctx);
|
|
29967
|
+
return true;
|
|
29968
|
+
case "actions.requested":
|
|
29969
|
+
await this.handleActionsRequested(event, ctx, hookMetadata);
|
|
29970
|
+
return true;
|
|
29971
|
+
case "action.result":
|
|
29972
|
+
await this.handleActionResult(event, ctx, hookMetadata);
|
|
29973
|
+
return true;
|
|
29974
|
+
case "subagent.called":
|
|
29975
|
+
await this.handleSubagentCalled(event, ctx, hookMetadata);
|
|
29976
|
+
return true;
|
|
29977
|
+
case "subagent.completed":
|
|
29978
|
+
await this.handleSubagentCompleted(event, ctx, hookMetadata);
|
|
29979
|
+
return true;
|
|
29980
|
+
case "step.completed":
|
|
29981
|
+
this.handleStepCompleted(event, ctx);
|
|
29982
|
+
return true;
|
|
29983
|
+
case "step.failed":
|
|
29984
|
+
this.handleStepFailed(event, ctx);
|
|
29985
|
+
return true;
|
|
29986
|
+
case "turn.completed":
|
|
29987
|
+
this.handleTurnCompleted(event, ctx);
|
|
29988
|
+
return true;
|
|
29989
|
+
case "turn.failed":
|
|
29990
|
+
this.handleTurnFailed(event, ctx);
|
|
29991
|
+
return true;
|
|
29992
|
+
case "session.failed":
|
|
29993
|
+
this.handleSessionFailed(event, ctx);
|
|
29994
|
+
return true;
|
|
29995
|
+
case "session.completed":
|
|
29996
|
+
this.handleSessionCompleted(event, ctx);
|
|
29997
|
+
return true;
|
|
29998
|
+
default:
|
|
29999
|
+
return false;
|
|
30000
|
+
}
|
|
30001
|
+
}
|
|
30002
|
+
handleSessionStarted(event, ctx, hookMetadata) {
|
|
30003
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30004
|
+
if (!sessionId) {
|
|
30005
|
+
return;
|
|
30006
|
+
}
|
|
30007
|
+
const metadata = {
|
|
30008
|
+
...hookMetadata ?? {},
|
|
30009
|
+
...modelMetadataFromRuntime(event.data.runtime)
|
|
30010
|
+
};
|
|
30011
|
+
this.state.update((current) => {
|
|
30012
|
+
const normalized = normalizeEveTraceState(current);
|
|
30013
|
+
return {
|
|
30014
|
+
...normalized,
|
|
30015
|
+
metadata: { ...normalized.metadata, ...metadata }
|
|
30016
|
+
};
|
|
30017
|
+
});
|
|
30018
|
+
for (const [key, turn] of this.turnsByKey) {
|
|
30019
|
+
if (!key.startsWith(`${sessionId}:`)) {
|
|
30020
|
+
continue;
|
|
30021
|
+
}
|
|
30022
|
+
turn.metadata = { ...turn.metadata, ...metadata };
|
|
30023
|
+
turn.span.log({ metadata: turn.metadata });
|
|
30024
|
+
for (const step of turn.stepsByIndex.values()) {
|
|
30025
|
+
step.metadata = { ...step.metadata, ...metadata };
|
|
30026
|
+
step.span.log({ metadata: step.metadata });
|
|
30027
|
+
}
|
|
30028
|
+
}
|
|
30029
|
+
}
|
|
30030
|
+
async handleTurnStarted(event, ctx, hookMetadata) {
|
|
30031
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30032
|
+
if (!sessionId) {
|
|
30033
|
+
return;
|
|
30034
|
+
}
|
|
30035
|
+
const key = turnKey2(sessionId, event.data.turnId);
|
|
30036
|
+
const metadata = {
|
|
30037
|
+
...readEveTraceState(this.state).metadata,
|
|
30038
|
+
...hookMetadata ?? {},
|
|
30039
|
+
"eve.session_id": sessionId
|
|
30040
|
+
};
|
|
30041
|
+
const existing = this.turnsByKey.get(key);
|
|
30042
|
+
if (existing) {
|
|
30043
|
+
existing.metadata = { ...existing.metadata, ...metadata };
|
|
30044
|
+
existing.span.log({ metadata: existing.metadata });
|
|
30045
|
+
return;
|
|
30046
|
+
}
|
|
30047
|
+
const span = await this.startTurnSpan(sessionId, event, ctx, metadata);
|
|
30048
|
+
span.log({ metadata });
|
|
30049
|
+
this.turnsByKey.set(key, {
|
|
30050
|
+
key,
|
|
30051
|
+
metadata,
|
|
30052
|
+
metrics: {},
|
|
30053
|
+
span,
|
|
30054
|
+
stepsByIndex: /* @__PURE__ */ new Map(),
|
|
30055
|
+
turnId: event.data.turnId
|
|
30056
|
+
});
|
|
30057
|
+
}
|
|
30058
|
+
async handleMessageReceived(event, ctx, hookMetadata) {
|
|
30059
|
+
const turn = await this.ensureTurn(event, ctx, hookMetadata);
|
|
30060
|
+
if (!turn) {
|
|
30061
|
+
return;
|
|
30062
|
+
}
|
|
30063
|
+
const input = [{ content: event.data.message, role: "user" }];
|
|
30064
|
+
turn.span.log({ input });
|
|
30065
|
+
}
|
|
30066
|
+
async handleStepStarted(event, ctx, hookMetadata) {
|
|
30067
|
+
const turn = await this.ensureTurn(event, ctx, hookMetadata);
|
|
30068
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30069
|
+
if (!turn || !sessionId) {
|
|
30070
|
+
return;
|
|
30071
|
+
}
|
|
30072
|
+
const existing = turn.stepsByIndex.get(event.data.stepIndex);
|
|
30073
|
+
if (existing) {
|
|
30074
|
+
existing.span.log({
|
|
30075
|
+
...existing.input !== void 0 ? { input: existing.input } : {},
|
|
30076
|
+
metadata: existing.metadata,
|
|
30077
|
+
metrics: existing.metrics,
|
|
30078
|
+
output: existing.output
|
|
30079
|
+
});
|
|
30080
|
+
const endTime = eventTime2(event);
|
|
30081
|
+
existing.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30082
|
+
this.markStepEnded(event.data.turnId, event.data.stepIndex);
|
|
30083
|
+
}
|
|
30084
|
+
const stepOrdinal = this.stepOrdinal(event);
|
|
30085
|
+
const metadata = { ...turn.metadata };
|
|
30086
|
+
const input = consumeCapturedEveModelInput(
|
|
30087
|
+
this.state,
|
|
30088
|
+
sessionId,
|
|
30089
|
+
event.data.turnId,
|
|
30090
|
+
event.data.stepIndex
|
|
30091
|
+
);
|
|
30092
|
+
const { rowId: eventId, spanId } = await generateEveIds(
|
|
30093
|
+
"step",
|
|
30094
|
+
sessionId,
|
|
30095
|
+
event.data.turnId,
|
|
30096
|
+
String(stepOrdinal)
|
|
30097
|
+
);
|
|
30098
|
+
const span = await this.startEveChildSpan(turn.span, {
|
|
30099
|
+
event: {
|
|
30100
|
+
id: eventId,
|
|
30101
|
+
...input !== void 0 ? { input } : {},
|
|
30102
|
+
metadata
|
|
30103
|
+
},
|
|
30104
|
+
name: "eve.step",
|
|
30105
|
+
spanAttributes: { type: "llm" /* LLM */ },
|
|
30106
|
+
spanId,
|
|
30107
|
+
startTime: eventTime2(event)
|
|
30108
|
+
});
|
|
30109
|
+
span.log({ ...input !== void 0 ? { input } : {}, metadata });
|
|
30110
|
+
turn.stepsByIndex.set(event.data.stepIndex, {
|
|
30111
|
+
...input !== void 0 ? { input } : {},
|
|
30112
|
+
metadata,
|
|
30113
|
+
metrics: {},
|
|
30114
|
+
span
|
|
30115
|
+
});
|
|
30116
|
+
}
|
|
30117
|
+
handleMessageCompleted(event, ctx) {
|
|
30118
|
+
const step = this.stepForEvent(event, ctx);
|
|
30119
|
+
if (!step) {
|
|
30120
|
+
return;
|
|
30121
|
+
}
|
|
30122
|
+
const existingMessage = Array.isArray(step.output) && isObject(step.output[0]) ? step.output[0].message : void 0;
|
|
30123
|
+
const existingToolCalls = isObject(existingMessage) ? existingMessage.tool_calls : void 0;
|
|
30124
|
+
step.output = [
|
|
30125
|
+
{
|
|
30126
|
+
finish_reason: normalizedFinishReason(event.data.finishReason),
|
|
30127
|
+
index: 0,
|
|
30128
|
+
message: {
|
|
30129
|
+
content: event.data.message,
|
|
30130
|
+
role: "assistant",
|
|
30131
|
+
...Array.isArray(existingToolCalls) ? { tool_calls: existingToolCalls } : {}
|
|
30132
|
+
}
|
|
30133
|
+
}
|
|
30134
|
+
];
|
|
30135
|
+
const turn = this.turnForEvent(event, ctx);
|
|
30136
|
+
if (turn && event.data.finishReason !== "tool-calls") {
|
|
30137
|
+
turn.output = event.data.message;
|
|
30138
|
+
}
|
|
30139
|
+
}
|
|
30140
|
+
handleResultCompleted(event, ctx) {
|
|
30141
|
+
const step = this.stepForEvent(event, ctx);
|
|
30142
|
+
if (step) {
|
|
30143
|
+
step.output = [
|
|
30144
|
+
{
|
|
30145
|
+
finish_reason: "stop",
|
|
30146
|
+
index: 0,
|
|
30147
|
+
message: {
|
|
30148
|
+
content: event.data.result,
|
|
30149
|
+
role: "assistant"
|
|
30150
|
+
}
|
|
30151
|
+
}
|
|
30152
|
+
];
|
|
30153
|
+
}
|
|
30154
|
+
const turn = this.turnForEvent(event, ctx);
|
|
30155
|
+
if (turn) {
|
|
30156
|
+
turn.output = event.data.result;
|
|
30157
|
+
}
|
|
30158
|
+
}
|
|
30159
|
+
async handleActionsRequested(event, ctx, hookMetadata) {
|
|
30160
|
+
const turn = await this.ensureTurn(event, ctx, hookMetadata);
|
|
30161
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30162
|
+
if (!turn || !sessionId) {
|
|
30163
|
+
return;
|
|
30164
|
+
}
|
|
30165
|
+
const traceActions = event.data.actions.filter(isTraceableActionRequest);
|
|
30166
|
+
if (traceActions.length === 0) {
|
|
30167
|
+
return;
|
|
30168
|
+
}
|
|
30169
|
+
for (const action of traceActions) {
|
|
30170
|
+
if (isToolCallAction(action)) {
|
|
30171
|
+
await this.startRequestedTool(event, turn, sessionId, action);
|
|
30172
|
+
} else if (isLocalSubagentCallAction(action)) {
|
|
30173
|
+
await this.startRequestedSubagent(event, turn, sessionId, action);
|
|
30174
|
+
}
|
|
30175
|
+
}
|
|
30176
|
+
const step = turn.stepsByIndex.get(event.data.stepIndex);
|
|
30177
|
+
if (!step) {
|
|
30178
|
+
return;
|
|
30179
|
+
}
|
|
30180
|
+
const toolCallsById = /* @__PURE__ */ new Map();
|
|
30181
|
+
if (Array.isArray(step.output) && isObject(step.output[0])) {
|
|
30182
|
+
const message = step.output[0]["message"];
|
|
30183
|
+
if (isObject(message) && Array.isArray(message["tool_calls"])) {
|
|
30184
|
+
for (const toolCall of message["tool_calls"]) {
|
|
30185
|
+
if (isObject(toolCall) && typeof toolCall["id"] === "string") {
|
|
30186
|
+
toolCallsById.set(toolCall["id"], toolCall);
|
|
30187
|
+
}
|
|
30188
|
+
}
|
|
30189
|
+
}
|
|
30190
|
+
}
|
|
30191
|
+
for (const action of traceActions) {
|
|
30192
|
+
const name = action.kind === "tool-call" ? action.toolName : action.subagentName ?? action.name ?? "agent";
|
|
30193
|
+
toolCallsById.set(action.callId, {
|
|
30194
|
+
function: {
|
|
30195
|
+
arguments: JSON.stringify(action.input),
|
|
30196
|
+
name
|
|
30197
|
+
},
|
|
30198
|
+
id: action.callId,
|
|
30199
|
+
type: "function"
|
|
30200
|
+
});
|
|
30201
|
+
}
|
|
30202
|
+
step.output = [
|
|
30203
|
+
{
|
|
30204
|
+
finish_reason: "tool_calls",
|
|
30205
|
+
index: 0,
|
|
30206
|
+
message: {
|
|
30207
|
+
content: null,
|
|
30208
|
+
role: "assistant",
|
|
30209
|
+
tool_calls: [...toolCallsById.values()]
|
|
30210
|
+
}
|
|
30211
|
+
}
|
|
30212
|
+
];
|
|
30213
|
+
step.span.log({ metadata: step.metadata, output: step.output });
|
|
30214
|
+
}
|
|
30215
|
+
async handleActionResult(event, ctx, hookMetadata) {
|
|
30216
|
+
if (isToolResult(event.data.result)) {
|
|
30217
|
+
await this.handleToolResult(event, ctx, event.data.result, hookMetadata);
|
|
30218
|
+
return;
|
|
30219
|
+
}
|
|
30220
|
+
if (isSubagentResult(event.data.result)) {
|
|
30221
|
+
await this.handleSubagentResult(
|
|
30222
|
+
event,
|
|
30223
|
+
ctx,
|
|
30224
|
+
event.data.result,
|
|
30225
|
+
hookMetadata
|
|
30226
|
+
);
|
|
30227
|
+
}
|
|
30228
|
+
}
|
|
30229
|
+
async handleToolResult(event, ctx, result, hookMetadata) {
|
|
30230
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30231
|
+
if (!sessionId) {
|
|
30232
|
+
return;
|
|
30233
|
+
}
|
|
30234
|
+
const key = toolKey3(sessionId, result.callId);
|
|
30235
|
+
if (this.completedToolKeys.has(key)) {
|
|
30236
|
+
return;
|
|
30237
|
+
}
|
|
30238
|
+
const tool = this.toolsByCallKey.get(key) ?? await this.startSyntheticTool(event, ctx, result, hookMetadata);
|
|
30239
|
+
if (!tool) {
|
|
30240
|
+
return;
|
|
30241
|
+
}
|
|
30242
|
+
const failed = event.data.status === "failed" || result.isError === true || event.data.error !== void 0;
|
|
30243
|
+
tool.span.log({
|
|
30244
|
+
...failed ? {
|
|
30245
|
+
error: actionResultError(event.data.error, result.output)
|
|
30246
|
+
} : {},
|
|
30247
|
+
metadata: tool.metadata,
|
|
30248
|
+
output: result.output
|
|
30249
|
+
});
|
|
30250
|
+
const endTime = eventTime2(event);
|
|
30251
|
+
tool.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30252
|
+
this.toolsByCallKey.delete(key);
|
|
30253
|
+
this.completedToolKeys.set(key, true);
|
|
30254
|
+
}
|
|
30255
|
+
async handleSubagentCalled(event, ctx, hookMetadata) {
|
|
30256
|
+
if (event.data.remote?.url) {
|
|
30257
|
+
return;
|
|
30258
|
+
}
|
|
30259
|
+
const turn = await this.ensureTurn(event, ctx, hookMetadata);
|
|
30260
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30261
|
+
if (!turn || !sessionId) {
|
|
30262
|
+
return;
|
|
30263
|
+
}
|
|
30264
|
+
const key = toolKey3(sessionId, event.data.callId);
|
|
30265
|
+
const metadata = toolMetadataFromTurn(turn);
|
|
30266
|
+
const existing = this.toolsByCallKey.get(key);
|
|
30267
|
+
if (existing) {
|
|
30268
|
+
existing.metadata = { ...existing.metadata, ...metadata };
|
|
30269
|
+
existing.span.log({ metadata: existing.metadata });
|
|
30270
|
+
return;
|
|
30271
|
+
}
|
|
30272
|
+
if (this.completedToolKeys.has(key)) {
|
|
30273
|
+
return;
|
|
30274
|
+
}
|
|
30275
|
+
const { rowId: eventId, spanId } = await generateEveIds(
|
|
30276
|
+
"subagent",
|
|
30277
|
+
sessionId,
|
|
30278
|
+
event.data.callId
|
|
30279
|
+
);
|
|
30280
|
+
const pending = this.toolsByCallKey.get(key);
|
|
30281
|
+
if (pending || this.completedToolKeys.has(key)) {
|
|
30282
|
+
if (pending) {
|
|
30283
|
+
pending.metadata = { ...pending.metadata, ...metadata };
|
|
30284
|
+
pending.span.log({ metadata: pending.metadata });
|
|
30285
|
+
}
|
|
30286
|
+
return;
|
|
30287
|
+
}
|
|
30288
|
+
const span = await this.startEveChildSpan(turn.span, {
|
|
30289
|
+
event: {
|
|
30290
|
+
id: eventId,
|
|
30291
|
+
metadata
|
|
30292
|
+
},
|
|
30293
|
+
name: event.data.toolName ?? event.data.name,
|
|
30294
|
+
spanAttributes: { type: "tool" /* TOOL */ },
|
|
30295
|
+
spanId,
|
|
30296
|
+
startTime: eventTime2(event)
|
|
30297
|
+
});
|
|
30298
|
+
span.log({ metadata });
|
|
30299
|
+
this.toolsByCallKey.set(key, {
|
|
30300
|
+
metadata,
|
|
30301
|
+
span,
|
|
30302
|
+
turnKey: turnKey2(sessionId, event.data.turnId)
|
|
30303
|
+
});
|
|
30304
|
+
}
|
|
30305
|
+
async handleSubagentCompleted(event, ctx, hookMetadata) {
|
|
30306
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30307
|
+
if (!sessionId) {
|
|
30308
|
+
return;
|
|
30309
|
+
}
|
|
30310
|
+
const key = toolKey3(sessionId, event.data.callId);
|
|
30311
|
+
if (this.completedToolKeys.has(key)) {
|
|
30312
|
+
return;
|
|
30313
|
+
}
|
|
30314
|
+
const subagent = this.toolsByCallKey.get(key) ?? await this.startSyntheticSubagent(event, ctx, hookMetadata);
|
|
30315
|
+
if (!subagent) {
|
|
30316
|
+
return;
|
|
30317
|
+
}
|
|
30318
|
+
subagent.span.log({
|
|
30319
|
+
...event.data.status === "failed" ? {
|
|
30320
|
+
error: actionResultError(event.data.error, event.data.output)
|
|
30321
|
+
} : {},
|
|
30322
|
+
metadata: subagent.metadata,
|
|
30323
|
+
...event.data.output !== void 0 ? { output: event.data.output } : {}
|
|
30324
|
+
});
|
|
30325
|
+
const endTime = eventTime2(event);
|
|
30326
|
+
const recordedEndTime = subagent.span.end(
|
|
30327
|
+
endTime === void 0 ? void 0 : { endTime }
|
|
30328
|
+
);
|
|
30329
|
+
this.state.update((current) => {
|
|
30330
|
+
const normalized = normalizeEveTraceState(current);
|
|
30331
|
+
return {
|
|
30332
|
+
...normalized,
|
|
30333
|
+
spanReferences: normalized.spanReferences.map(
|
|
30334
|
+
(reference) => reference.spanId === subagent.span.spanId ? { ...reference, endTime: recordedEndTime } : reference
|
|
30335
|
+
)
|
|
30336
|
+
};
|
|
30337
|
+
});
|
|
30338
|
+
}
|
|
30339
|
+
async handleSubagentResult(event, ctx, result, hookMetadata) {
|
|
30340
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30341
|
+
if (!sessionId) {
|
|
30342
|
+
return;
|
|
30343
|
+
}
|
|
30344
|
+
const key = toolKey3(sessionId, result.callId);
|
|
30345
|
+
if (this.completedToolKeys.has(key)) {
|
|
30346
|
+
return;
|
|
30347
|
+
}
|
|
30348
|
+
const subagent = this.toolsByCallKey.get(key) ?? await this.startSyntheticSubagentResult(
|
|
30349
|
+
event,
|
|
30350
|
+
ctx,
|
|
30351
|
+
result,
|
|
30352
|
+
hookMetadata
|
|
30353
|
+
);
|
|
30354
|
+
if (!subagent) {
|
|
30355
|
+
return;
|
|
30356
|
+
}
|
|
30357
|
+
const isError = event.data.status === "failed" || result.isError === true || event.data.error !== void 0;
|
|
30358
|
+
subagent.span.log({
|
|
30359
|
+
...isError ? {
|
|
30360
|
+
error: actionResultError(event.data.error, result.output)
|
|
30361
|
+
} : {},
|
|
30362
|
+
metadata: subagent.metadata,
|
|
30363
|
+
output: result.output
|
|
30364
|
+
});
|
|
30365
|
+
const endTime = eventTime2(event);
|
|
30366
|
+
subagent.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30367
|
+
this.toolsByCallKey.delete(key);
|
|
30368
|
+
this.completedToolKeys.set(key, true);
|
|
30369
|
+
}
|
|
30370
|
+
handleStepCompleted(event, ctx) {
|
|
30371
|
+
const step = this.stepForEvent(event, ctx);
|
|
30372
|
+
if (!step) {
|
|
30373
|
+
return;
|
|
30374
|
+
}
|
|
30375
|
+
const usage = event.data.usage;
|
|
30376
|
+
const inputTokens = typeof usage?.inputTokens === "number" && Number.isFinite(usage.inputTokens) && usage.inputTokens >= 0 ? usage.inputTokens : void 0;
|
|
30377
|
+
const outputTokens = typeof usage?.outputTokens === "number" && Number.isFinite(usage.outputTokens) && usage.outputTokens >= 0 ? usage.outputTokens : void 0;
|
|
30378
|
+
const cacheReadTokens = typeof usage?.cacheReadTokens === "number" && Number.isFinite(usage.cacheReadTokens) && usage.cacheReadTokens >= 0 ? usage.cacheReadTokens : void 0;
|
|
30379
|
+
const cacheWriteTokens = typeof usage?.cacheWriteTokens === "number" && Number.isFinite(usage.cacheWriteTokens) && usage.cacheWriteTokens >= 0 ? usage.cacheWriteTokens : void 0;
|
|
30380
|
+
const costUsd = typeof usage?.costUsd === "number" && Number.isFinite(usage.costUsd) && usage.costUsd >= 0 ? usage.costUsd : void 0;
|
|
30381
|
+
const total = inputTokens !== void 0 && outputTokens !== void 0 ? inputTokens + outputTokens : void 0;
|
|
30382
|
+
const metrics = {
|
|
30383
|
+
...inputTokens !== void 0 ? { prompt_tokens: inputTokens } : {},
|
|
30384
|
+
...outputTokens !== void 0 ? { completion_tokens: outputTokens } : {},
|
|
30385
|
+
...total !== void 0 ? { tokens: total } : {},
|
|
30386
|
+
...cacheReadTokens !== void 0 ? { prompt_cached_tokens: cacheReadTokens } : {},
|
|
30387
|
+
...cacheWriteTokens !== void 0 ? { prompt_cache_creation_tokens: cacheWriteTokens } : {},
|
|
30388
|
+
...costUsd !== void 0 ? { estimated_cost: costUsd } : {}
|
|
30389
|
+
};
|
|
30390
|
+
step.metrics = { ...step.metrics, ...metrics };
|
|
30391
|
+
if (Array.isArray(step.output) && isObject(step.output[0])) {
|
|
30392
|
+
const finishReason = step.output[0].finish_reason;
|
|
30393
|
+
if (typeof finishReason !== "string") {
|
|
30394
|
+
step.output[0].finish_reason = normalizedFinishReason(
|
|
30395
|
+
event.data.finishReason
|
|
30396
|
+
);
|
|
30397
|
+
}
|
|
30398
|
+
}
|
|
30399
|
+
step.span.log({
|
|
30400
|
+
...step.input !== void 0 ? { input: step.input } : {},
|
|
30401
|
+
metadata: step.metadata,
|
|
30402
|
+
metrics,
|
|
30403
|
+
output: step.output
|
|
30404
|
+
});
|
|
30405
|
+
const endTime = eventTime2(event);
|
|
30406
|
+
step.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30407
|
+
const turn = this.turnForEvent(event, ctx);
|
|
30408
|
+
if (turn) {
|
|
30409
|
+
for (const [key, value] of Object.entries(metrics)) {
|
|
30410
|
+
turn.metrics[key] = (turn.metrics[key] ?? 0) + value;
|
|
30411
|
+
}
|
|
30412
|
+
turn.stepsByIndex.delete(event.data.stepIndex);
|
|
30413
|
+
}
|
|
30414
|
+
this.markStepEnded(event.data.turnId, event.data.stepIndex);
|
|
30415
|
+
}
|
|
30416
|
+
handleStepFailed(event, ctx) {
|
|
30417
|
+
const step = this.stepForEvent(event, ctx);
|
|
30418
|
+
if (step) {
|
|
30419
|
+
step.span.log({
|
|
30420
|
+
error: errorFromMessage(
|
|
30421
|
+
event.data.message,
|
|
30422
|
+
event.data.code,
|
|
30423
|
+
event.data.details
|
|
30424
|
+
)
|
|
30425
|
+
});
|
|
30426
|
+
const endTime = eventTime2(event);
|
|
30427
|
+
step.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30428
|
+
}
|
|
30429
|
+
const turn = this.turnForEvent(event, ctx);
|
|
30430
|
+
turn?.stepsByIndex.delete(event.data.stepIndex);
|
|
30431
|
+
this.markStepEnded(event.data.turnId, event.data.stepIndex);
|
|
30432
|
+
}
|
|
30433
|
+
handleTurnCompleted(event, ctx) {
|
|
30434
|
+
const turn = this.turnForEvent(event, ctx);
|
|
30435
|
+
if (!turn) {
|
|
30436
|
+
return;
|
|
30437
|
+
}
|
|
30438
|
+
this.finalizeTurn(turn, {
|
|
30439
|
+
endTime: eventTime2(event)
|
|
30440
|
+
});
|
|
30441
|
+
}
|
|
30442
|
+
handleTurnFailed(event, ctx) {
|
|
30443
|
+
const turn = this.turnForEvent(event, ctx);
|
|
30444
|
+
if (!turn) {
|
|
30445
|
+
return;
|
|
30446
|
+
}
|
|
30447
|
+
this.finalizeTurn(turn, {
|
|
30448
|
+
endTime: eventTime2(event),
|
|
30449
|
+
error: errorFromMessage(
|
|
30450
|
+
event.data.message,
|
|
30451
|
+
event.data.code,
|
|
30452
|
+
event.data.details
|
|
30453
|
+
)
|
|
30454
|
+
});
|
|
30455
|
+
}
|
|
30456
|
+
handleSessionFailed(event, ctx) {
|
|
30457
|
+
const sessionId = event.data.sessionId || sessionIdFromContext(ctx);
|
|
30458
|
+
if (!sessionId) {
|
|
30459
|
+
return;
|
|
30460
|
+
}
|
|
30461
|
+
const error = errorFromMessage(
|
|
30462
|
+
event.data.message,
|
|
30463
|
+
event.data.code,
|
|
30464
|
+
event.data.details
|
|
30465
|
+
);
|
|
30466
|
+
for (const [key, turn] of this.turnsByKey) {
|
|
30467
|
+
if (!key.startsWith(`${sessionId}:`)) {
|
|
30468
|
+
continue;
|
|
30469
|
+
}
|
|
30470
|
+
this.finalizeTurn(turn, {
|
|
30471
|
+
endTime: eventTime2(event),
|
|
30472
|
+
error
|
|
30473
|
+
});
|
|
30474
|
+
}
|
|
30475
|
+
for (const [key, tool] of this.toolsByCallKey) {
|
|
30476
|
+
if (key.startsWith(`${sessionId}:`)) {
|
|
30477
|
+
const endTime = eventTime2(event);
|
|
30478
|
+
if (!tool.endedByTurn) {
|
|
30479
|
+
tool.span.log({ metadata: tool.metadata });
|
|
30480
|
+
tool.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30481
|
+
tool.endedByTurn = true;
|
|
30482
|
+
}
|
|
30483
|
+
}
|
|
30484
|
+
}
|
|
30485
|
+
}
|
|
30486
|
+
handleSessionCompleted(event, ctx) {
|
|
30487
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30488
|
+
if (!sessionId) {
|
|
30489
|
+
return;
|
|
30490
|
+
}
|
|
30491
|
+
for (const [key, turn] of this.turnsByKey) {
|
|
30492
|
+
if (!key.startsWith(`${sessionId}:`)) {
|
|
30493
|
+
continue;
|
|
30494
|
+
}
|
|
30495
|
+
this.finalizeTurn(turn, {
|
|
30496
|
+
endTime: eventTime2(event)
|
|
30497
|
+
});
|
|
30498
|
+
}
|
|
30499
|
+
for (const [key, tool] of this.toolsByCallKey) {
|
|
30500
|
+
if (key.startsWith(`${sessionId}:`) && !tool.endedByTurn) {
|
|
30501
|
+
const endTime = eventTime2(event);
|
|
30502
|
+
tool.span.log({ metadata: tool.metadata });
|
|
30503
|
+
tool.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30504
|
+
tool.endedByTurn = true;
|
|
30505
|
+
}
|
|
30506
|
+
}
|
|
30507
|
+
}
|
|
30508
|
+
async ensureTurn(event, ctx, hookMetadata) {
|
|
30509
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30510
|
+
if (!sessionId) {
|
|
30511
|
+
return void 0;
|
|
30512
|
+
}
|
|
30513
|
+
const key = turnKey2(sessionId, event.data.turnId);
|
|
30514
|
+
const existing = this.turnsByKey.get(key);
|
|
30515
|
+
if (existing) {
|
|
30516
|
+
return existing;
|
|
30517
|
+
}
|
|
30518
|
+
const metadata = {
|
|
30519
|
+
...readEveTraceState(this.state).metadata,
|
|
30520
|
+
...hookMetadata ?? {},
|
|
30521
|
+
"eve.session_id": sessionId
|
|
30522
|
+
};
|
|
30523
|
+
const span = await this.startTurnSpan(sessionId, event, ctx, metadata);
|
|
30524
|
+
span.log({ metadata });
|
|
30525
|
+
const state = {
|
|
30526
|
+
key,
|
|
30527
|
+
metadata,
|
|
30528
|
+
metrics: {},
|
|
30529
|
+
span,
|
|
30530
|
+
stepsByIndex: /* @__PURE__ */ new Map(),
|
|
30531
|
+
turnId: event.data.turnId
|
|
30532
|
+
};
|
|
30533
|
+
this.turnsByKey.set(key, state);
|
|
30534
|
+
return state;
|
|
30535
|
+
}
|
|
30536
|
+
async startRequestedTool(event, turn, sessionId, action) {
|
|
30537
|
+
const key = toolKey3(sessionId, action.callId);
|
|
30538
|
+
if (this.toolsByCallKey.has(key) || this.completedToolKeys.has(key)) {
|
|
30539
|
+
return;
|
|
30540
|
+
}
|
|
30541
|
+
const metadata = toolMetadataFromTurn(turn);
|
|
30542
|
+
const { rowId: eventId, spanId } = await generateEveIds(
|
|
30543
|
+
"tool",
|
|
30544
|
+
sessionId,
|
|
30545
|
+
event.data.turnId,
|
|
30546
|
+
action.callId
|
|
30547
|
+
);
|
|
30548
|
+
if (this.toolsByCallKey.has(key) || this.completedToolKeys.has(key)) {
|
|
30549
|
+
return;
|
|
30550
|
+
}
|
|
30551
|
+
const span = await this.startEveChildSpan(turn.span, {
|
|
30552
|
+
event: {
|
|
30553
|
+
id: eventId,
|
|
30554
|
+
input: action.input,
|
|
30555
|
+
metadata
|
|
30556
|
+
},
|
|
30557
|
+
name: action.toolName,
|
|
30558
|
+
spanAttributes: { type: "tool" /* TOOL */ },
|
|
30559
|
+
spanId,
|
|
30560
|
+
startTime: eventTime2(event)
|
|
30561
|
+
});
|
|
30562
|
+
span.log({ input: action.input, metadata });
|
|
30563
|
+
this.toolsByCallKey.set(key, {
|
|
30564
|
+
metadata,
|
|
30565
|
+
span,
|
|
30566
|
+
turnKey: turnKey2(sessionId, event.data.turnId)
|
|
30567
|
+
});
|
|
30568
|
+
}
|
|
30569
|
+
async startRequestedSubagent(event, turn, sessionId, action) {
|
|
30570
|
+
const key = toolKey3(sessionId, action.callId);
|
|
30571
|
+
if (this.toolsByCallKey.has(key) || this.completedToolKeys.has(key)) {
|
|
30572
|
+
return;
|
|
30573
|
+
}
|
|
30574
|
+
const name = action.subagentName ?? action.name ?? "agent";
|
|
30575
|
+
const metadata = toolMetadataFromTurn(turn);
|
|
30576
|
+
const { rowId: eventId, spanId } = await generateEveIds(
|
|
30577
|
+
"subagent",
|
|
30578
|
+
sessionId,
|
|
30579
|
+
action.callId
|
|
30580
|
+
);
|
|
30581
|
+
if (this.toolsByCallKey.has(key) || this.completedToolKeys.has(key)) {
|
|
30582
|
+
return;
|
|
30583
|
+
}
|
|
30584
|
+
const span = await this.startEveChildSpan(turn.span, {
|
|
30585
|
+
event: {
|
|
30586
|
+
id: eventId,
|
|
30587
|
+
input: action.input,
|
|
30588
|
+
metadata
|
|
30589
|
+
},
|
|
30590
|
+
name,
|
|
30591
|
+
spanAttributes: { type: "tool" /* TOOL */ },
|
|
30592
|
+
spanId,
|
|
30593
|
+
startTime: eventTime2(event)
|
|
30594
|
+
});
|
|
30595
|
+
span.log({ input: action.input, metadata });
|
|
30596
|
+
this.toolsByCallKey.set(key, {
|
|
30597
|
+
metadata,
|
|
30598
|
+
span,
|
|
30599
|
+
turnKey: turnKey2(sessionId, event.data.turnId)
|
|
30600
|
+
});
|
|
30601
|
+
}
|
|
30602
|
+
async startSyntheticTool(event, ctx, result, hookMetadata) {
|
|
30603
|
+
const turn = await this.ensureTurn(event, ctx, hookMetadata);
|
|
30604
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30605
|
+
if (!turn || !sessionId) {
|
|
30606
|
+
return void 0;
|
|
30607
|
+
}
|
|
30608
|
+
const metadata = toolMetadataFromTurn(turn);
|
|
30609
|
+
const { rowId: eventId, spanId } = await generateEveIds(
|
|
30610
|
+
"tool",
|
|
30611
|
+
sessionId,
|
|
30612
|
+
event.data.turnId,
|
|
30613
|
+
result.callId
|
|
30614
|
+
);
|
|
30615
|
+
const existing = this.toolsByCallKey.get(toolKey3(sessionId, result.callId));
|
|
30616
|
+
if (existing) {
|
|
30617
|
+
return existing;
|
|
30618
|
+
}
|
|
30619
|
+
const span = await this.startEveChildSpan(turn.span, {
|
|
30620
|
+
event: {
|
|
30621
|
+
id: eventId,
|
|
30622
|
+
metadata
|
|
30623
|
+
},
|
|
30624
|
+
name: result.toolName,
|
|
30625
|
+
spanAttributes: { type: "tool" /* TOOL */ },
|
|
30626
|
+
spanId,
|
|
30627
|
+
startTime: eventTime2(event)
|
|
30628
|
+
});
|
|
30629
|
+
span.log({ metadata });
|
|
30630
|
+
const state = {
|
|
30631
|
+
metadata,
|
|
30632
|
+
span,
|
|
30633
|
+
turnKey: turnKey2(sessionId, event.data.turnId)
|
|
30634
|
+
};
|
|
30635
|
+
this.toolsByCallKey.set(toolKey3(sessionId, result.callId), state);
|
|
30636
|
+
return state;
|
|
30637
|
+
}
|
|
30638
|
+
async startSyntheticSubagent(event, ctx, hookMetadata) {
|
|
30639
|
+
const turn = await this.ensureTurn(event, ctx, hookMetadata);
|
|
30640
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30641
|
+
if (!turn || !sessionId) {
|
|
30642
|
+
return void 0;
|
|
30643
|
+
}
|
|
30644
|
+
const metadata = toolMetadataFromTurn(turn);
|
|
30645
|
+
const { rowId: eventId, spanId } = await generateEveIds(
|
|
30646
|
+
"subagent",
|
|
30647
|
+
sessionId,
|
|
30648
|
+
event.data.callId
|
|
30649
|
+
);
|
|
30650
|
+
const existing = this.toolsByCallKey.get(
|
|
30651
|
+
toolKey3(sessionId, event.data.callId)
|
|
30652
|
+
);
|
|
30653
|
+
if (existing) {
|
|
30654
|
+
return existing;
|
|
30655
|
+
}
|
|
30656
|
+
const span = await this.startEveChildSpan(turn.span, {
|
|
30657
|
+
event: {
|
|
30658
|
+
id: eventId,
|
|
30659
|
+
metadata
|
|
30660
|
+
},
|
|
30661
|
+
name: event.data.subagentName,
|
|
30662
|
+
spanAttributes: { type: "tool" /* TOOL */ },
|
|
30663
|
+
spanId,
|
|
30664
|
+
startTime: eventTime2(event)
|
|
30665
|
+
});
|
|
30666
|
+
span.log({ metadata });
|
|
30667
|
+
const state = {
|
|
30668
|
+
metadata,
|
|
30669
|
+
span,
|
|
30670
|
+
turnKey: turnKey2(sessionId, event.data.turnId)
|
|
30671
|
+
};
|
|
30672
|
+
this.toolsByCallKey.set(toolKey3(sessionId, event.data.callId), state);
|
|
30673
|
+
return state;
|
|
30674
|
+
}
|
|
30675
|
+
async startSyntheticSubagentResult(event, ctx, result, hookMetadata) {
|
|
30676
|
+
const turn = await this.ensureTurn(event, ctx, hookMetadata);
|
|
30677
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30678
|
+
if (!turn || !sessionId) {
|
|
30679
|
+
return void 0;
|
|
30680
|
+
}
|
|
30681
|
+
const metadata = toolMetadataFromTurn(turn);
|
|
30682
|
+
const { rowId: eventId, spanId } = await generateEveIds(
|
|
30683
|
+
"subagent",
|
|
30684
|
+
sessionId,
|
|
30685
|
+
result.callId
|
|
30686
|
+
);
|
|
30687
|
+
const existing = this.toolsByCallKey.get(toolKey3(sessionId, result.callId));
|
|
30688
|
+
if (existing) {
|
|
30689
|
+
return existing;
|
|
30690
|
+
}
|
|
30691
|
+
const span = await this.startEveChildSpan(turn.span, {
|
|
30692
|
+
event: {
|
|
30693
|
+
id: eventId,
|
|
30694
|
+
metadata
|
|
30695
|
+
},
|
|
30696
|
+
name: result.subagentName,
|
|
30697
|
+
spanAttributes: { type: "tool" /* TOOL */ },
|
|
30698
|
+
spanId,
|
|
30699
|
+
startTime: eventTime2(event)
|
|
30700
|
+
});
|
|
30701
|
+
span.log({ metadata });
|
|
30702
|
+
const state = {
|
|
30703
|
+
metadata,
|
|
30704
|
+
span,
|
|
30705
|
+
turnKey: turnKey2(sessionId, event.data.turnId)
|
|
30706
|
+
};
|
|
30707
|
+
this.toolsByCallKey.set(toolKey3(sessionId, result.callId), state);
|
|
30708
|
+
return state;
|
|
30709
|
+
}
|
|
30710
|
+
async startTurnSpan(sessionId, event, ctx, metadata) {
|
|
30711
|
+
const session = isObject(ctx) ? ctx["session"] : void 0;
|
|
30712
|
+
const parent = isObject(session) ? session["parent"] : void 0;
|
|
30713
|
+
const parentTurn = isObject(parent) ? parent["turn"] : void 0;
|
|
30714
|
+
const parentLineage = isObject(parent) && typeof parent["callId"] === "string" && typeof parent["sessionId"] === "string" && isObject(parentTurn) && typeof parentTurn["id"] === "string" ? {
|
|
30715
|
+
callId: parent["callId"],
|
|
30716
|
+
sessionId: parent["sessionId"],
|
|
30717
|
+
turnId: parentTurn["id"]
|
|
30718
|
+
} : void 0;
|
|
30719
|
+
const [{ rowId: eventId, spanId }, rootSpanId, parentSpanId] = await Promise.all([
|
|
30720
|
+
generateEveIds("turn", sessionId, event.data.turnId),
|
|
30721
|
+
deterministicEveId(
|
|
30722
|
+
"eve:root",
|
|
30723
|
+
parentLineage?.sessionId ?? sessionId,
|
|
30724
|
+
parentLineage?.turnId ?? event.data.turnId
|
|
30725
|
+
),
|
|
30726
|
+
parentLineage ? deterministicEveId(
|
|
30727
|
+
"eve:subagent",
|
|
30728
|
+
parentLineage.sessionId,
|
|
30729
|
+
parentLineage.callId
|
|
30730
|
+
) : Promise.resolve(void 0)
|
|
30731
|
+
]);
|
|
30732
|
+
return await this.startEveSpan({
|
|
30733
|
+
event: {
|
|
30734
|
+
id: eventId,
|
|
30735
|
+
metadata
|
|
30736
|
+
},
|
|
30737
|
+
name: "eve.turn",
|
|
30738
|
+
parentSpanIds: parentSpanId ? { rootSpanId, spanId: parentSpanId } : { parentSpanIds: [], rootSpanId },
|
|
30739
|
+
spanAttributes: { type: "task" /* TASK */ },
|
|
30740
|
+
spanId,
|
|
30741
|
+
startTime: eventTime2(event)
|
|
30742
|
+
});
|
|
30743
|
+
}
|
|
30744
|
+
turnForEvent(event, ctx) {
|
|
30745
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30746
|
+
return sessionId ? this.turnsByKey.get(turnKey2(sessionId, event.data.turnId)) : void 0;
|
|
30747
|
+
}
|
|
30748
|
+
stepForEvent(event, ctx) {
|
|
30749
|
+
return this.turnForEvent(event, ctx)?.stepsByIndex.get(
|
|
30750
|
+
event.data.stepIndex
|
|
30751
|
+
);
|
|
30752
|
+
}
|
|
30753
|
+
finalizeTurn(turn, args) {
|
|
30754
|
+
const { endTime } = args;
|
|
30755
|
+
for (const step of turn.stepsByIndex.values()) {
|
|
30756
|
+
step.span.log({
|
|
30757
|
+
...step.input !== void 0 ? { input: step.input } : {},
|
|
30758
|
+
metadata: step.metadata,
|
|
30759
|
+
metrics: step.metrics,
|
|
30760
|
+
output: step.output
|
|
30761
|
+
});
|
|
30762
|
+
step.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30763
|
+
}
|
|
30764
|
+
turn.stepsByIndex.clear();
|
|
30765
|
+
for (const tool of this.toolsByCallKey.values()) {
|
|
30766
|
+
if (tool.turnKey !== turn.key) {
|
|
30767
|
+
continue;
|
|
30768
|
+
}
|
|
30769
|
+
if (tool.endedByTurn) {
|
|
30770
|
+
continue;
|
|
30771
|
+
}
|
|
30772
|
+
tool.span.log({ metadata: tool.metadata });
|
|
30773
|
+
tool.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30774
|
+
tool.endedByTurn = true;
|
|
30775
|
+
}
|
|
30776
|
+
if (args.error) {
|
|
30777
|
+
turn.span.log({ error: args.error });
|
|
30778
|
+
} else {
|
|
30779
|
+
turn.span.log({
|
|
30780
|
+
metadata: turn.metadata,
|
|
30781
|
+
metrics: turn.metrics,
|
|
30782
|
+
output: turn.output
|
|
30783
|
+
});
|
|
30784
|
+
}
|
|
30785
|
+
turn.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30786
|
+
this.turnsByKey.delete(turn.key);
|
|
30787
|
+
this.state.update((current) => {
|
|
30788
|
+
const normalized = normalizeEveTraceState(current);
|
|
30789
|
+
return {
|
|
30790
|
+
...normalized,
|
|
30791
|
+
stepStarts: normalized.stepStarts.filter(
|
|
30792
|
+
(entry) => entry.turnId !== turn.turnId
|
|
30793
|
+
)
|
|
30794
|
+
};
|
|
30795
|
+
});
|
|
30796
|
+
}
|
|
30797
|
+
cleanupSession(sessionId) {
|
|
30798
|
+
const keyPrefix = `${sessionId}:`;
|
|
30799
|
+
for (const key of this.turnsByKey.keys()) {
|
|
30800
|
+
if (key.startsWith(keyPrefix)) {
|
|
30801
|
+
this.turnsByKey.delete(key);
|
|
30802
|
+
}
|
|
30803
|
+
}
|
|
30804
|
+
for (const key of this.toolsByCallKey.keys()) {
|
|
30805
|
+
if (key.startsWith(keyPrefix)) {
|
|
30806
|
+
this.toolsByCallKey.delete(key);
|
|
30807
|
+
}
|
|
30808
|
+
}
|
|
30809
|
+
for (const key of this.completedToolKeys.keys()) {
|
|
30810
|
+
if (key.startsWith(keyPrefix)) {
|
|
30811
|
+
this.completedToolKeys.delete(key);
|
|
30812
|
+
}
|
|
30813
|
+
}
|
|
30814
|
+
this.state.update(() => emptyEveTraceState());
|
|
30815
|
+
}
|
|
30816
|
+
async flushInstrumentation() {
|
|
30817
|
+
try {
|
|
30818
|
+
await flush();
|
|
30819
|
+
return true;
|
|
30820
|
+
} catch (error) {
|
|
30821
|
+
debugLogger.warn("Error in Eve flush instrumentation:", error);
|
|
30822
|
+
return false;
|
|
30823
|
+
}
|
|
30824
|
+
}
|
|
30825
|
+
};
|
|
30826
|
+
function emptyEveTraceState() {
|
|
30827
|
+
return {
|
|
30828
|
+
llmInputs: [],
|
|
30829
|
+
metadata: {},
|
|
30830
|
+
spanReferences: [],
|
|
30831
|
+
stepStarts: []
|
|
30832
|
+
};
|
|
30833
|
+
}
|
|
30834
|
+
function normalizeEveTraceState(state) {
|
|
30835
|
+
if (!isObject(state)) {
|
|
30836
|
+
return emptyEveTraceState();
|
|
30837
|
+
}
|
|
30838
|
+
const metadata = isObject(state["metadata"]) ? state["metadata"] : {};
|
|
30839
|
+
const spanReferences = Array.isArray(state["spanReferences"]) ? state["spanReferences"].flatMap((entry) => {
|
|
30840
|
+
if (!isObject(entry)) {
|
|
30841
|
+
return [];
|
|
30842
|
+
}
|
|
30843
|
+
const exported = entry["exported"];
|
|
30844
|
+
const endTime = entry["endTime"];
|
|
30845
|
+
const rootSpanId = entry["rootSpanId"];
|
|
30846
|
+
const rowId = entry["rowId"];
|
|
30847
|
+
const spanId = entry["spanId"];
|
|
30848
|
+
const startEvent = entry["startEvent"];
|
|
30849
|
+
const startEventCreated = isObject(startEvent) ? startEvent["created"] : void 0;
|
|
30850
|
+
const startEventMetrics = isObject(startEvent) ? startEvent["metrics"] : void 0;
|
|
30851
|
+
const startEventSpanAttributes = isObject(startEvent) ? startEvent["span_attributes"] : void 0;
|
|
30852
|
+
const startEventSpanParents = isObject(startEvent) ? startEvent["span_parents"] : void 0;
|
|
30853
|
+
const normalizedStartEvent = typeof startEventCreated === "string" && isObject(startEventMetrics) && typeof startEventMetrics["start"] === "number" && Number.isFinite(startEventMetrics["start"]) && isObject(startEventSpanAttributes) && Array.isArray(startEventSpanParents) && startEventSpanParents.every(
|
|
30854
|
+
(parent) => typeof parent === "string"
|
|
30855
|
+
) ? {
|
|
30856
|
+
created: startEventCreated,
|
|
30857
|
+
metrics: { start: startEventMetrics["start"] },
|
|
30858
|
+
span_attributes: { ...startEventSpanAttributes },
|
|
30859
|
+
span_parents: [...startEventSpanParents]
|
|
30860
|
+
} : void 0;
|
|
30861
|
+
return typeof exported === "string" && typeof rootSpanId === "string" && typeof rowId === "string" && typeof spanId === "string" ? [
|
|
30862
|
+
{
|
|
30863
|
+
...typeof endTime === "number" && Number.isFinite(endTime) ? { endTime } : {},
|
|
30864
|
+
exported,
|
|
30865
|
+
rootSpanId,
|
|
30866
|
+
rowId,
|
|
30867
|
+
spanId,
|
|
30868
|
+
...normalizedStartEvent ? { startEvent: normalizedStartEvent } : {}
|
|
30869
|
+
}
|
|
30870
|
+
] : [];
|
|
30871
|
+
}).slice(-MAX_STORED_SPAN_REFERENCES) : [];
|
|
30872
|
+
const llmInputs = Array.isArray(state["llmInputs"]) ? state["llmInputs"].flatMap((entry) => {
|
|
30873
|
+
if (!isObject(entry)) {
|
|
30874
|
+
return [];
|
|
30875
|
+
}
|
|
30876
|
+
const key = entry["key"];
|
|
30877
|
+
const input = entry["input"];
|
|
30878
|
+
return typeof key === "string" && isCapturedModelInput(input) ? [{ input, key }] : [];
|
|
30879
|
+
}).slice(-MAX_STORED_LLM_INPUTS) : [];
|
|
30880
|
+
const stepStarts = Array.isArray(state["stepStarts"]) ? state["stepStarts"].flatMap((entry) => {
|
|
30881
|
+
if (!isObject(entry)) {
|
|
30882
|
+
return [];
|
|
30883
|
+
}
|
|
30884
|
+
const ordinal = entry["ordinal"];
|
|
30885
|
+
const open = entry["open"];
|
|
30886
|
+
const stepIndex = entry["stepIndex"];
|
|
30887
|
+
const turnId = entry["turnId"];
|
|
30888
|
+
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 }] : [];
|
|
30889
|
+
}).slice(-MAX_STORED_STEP_STARTS) : [];
|
|
30890
|
+
return { llmInputs, metadata: { ...metadata }, spanReferences, stepStarts };
|
|
30891
|
+
}
|
|
30892
|
+
function readEveTraceState(state) {
|
|
30893
|
+
try {
|
|
30894
|
+
return normalizeEveTraceState(state.get());
|
|
30895
|
+
} catch {
|
|
30896
|
+
return emptyEveTraceState();
|
|
30897
|
+
}
|
|
30898
|
+
}
|
|
30899
|
+
function captureEveModelInput(state, input) {
|
|
30900
|
+
if (!isObject(input)) {
|
|
30901
|
+
return;
|
|
30902
|
+
}
|
|
30903
|
+
const session = input["session"];
|
|
30904
|
+
const turn = input["turn"];
|
|
30905
|
+
const step = input["step"];
|
|
30906
|
+
if (!isObject(session) || !isObject(turn) || !isObject(step)) {
|
|
30907
|
+
return;
|
|
30908
|
+
}
|
|
30909
|
+
const sessionId = session["id"];
|
|
30910
|
+
const turnId = turn["id"];
|
|
30911
|
+
const stepIndex = step["index"];
|
|
30912
|
+
if (typeof sessionId !== "string" || typeof turnId !== "string" || typeof stepIndex !== "number" || !Number.isInteger(stepIndex)) {
|
|
30913
|
+
return;
|
|
30914
|
+
}
|
|
30915
|
+
const captured = capturedModelInput(input["modelInput"]);
|
|
30916
|
+
if (!captured) {
|
|
30917
|
+
return;
|
|
30918
|
+
}
|
|
30919
|
+
const key = llmInputKey(sessionId, turnId, stepIndex);
|
|
30920
|
+
state.update((current) => {
|
|
30921
|
+
const normalized = normalizeEveTraceState(current);
|
|
30922
|
+
const llmInputs = [...normalized.llmInputs, { input: captured, key }];
|
|
30923
|
+
return {
|
|
30924
|
+
...normalized,
|
|
30925
|
+
llmInputs: llmInputs.slice(-MAX_STORED_LLM_INPUTS)
|
|
30926
|
+
};
|
|
30927
|
+
});
|
|
30928
|
+
}
|
|
30929
|
+
function consumeCapturedEveModelInput(state, sessionId, turnId, stepIndex) {
|
|
30930
|
+
try {
|
|
30931
|
+
const key = llmInputKey(sessionId, turnId, stepIndex);
|
|
30932
|
+
let input;
|
|
30933
|
+
state.update((current) => {
|
|
30934
|
+
const normalized = normalizeEveTraceState(current);
|
|
30935
|
+
const index = normalized.llmInputs.findIndex(
|
|
30936
|
+
(candidate) => candidate.key === key
|
|
30937
|
+
);
|
|
30938
|
+
if (index < 0) {
|
|
30939
|
+
return normalized;
|
|
30940
|
+
}
|
|
30941
|
+
input = normalized.llmInputs[index]?.input;
|
|
30942
|
+
return {
|
|
30943
|
+
...normalized,
|
|
30944
|
+
llmInputs: normalized.llmInputs.filter(
|
|
30945
|
+
(_, candidateIndex) => candidateIndex !== index
|
|
30946
|
+
)
|
|
30947
|
+
};
|
|
30948
|
+
});
|
|
30949
|
+
return input;
|
|
30950
|
+
} catch (error) {
|
|
30951
|
+
debugLogger.warn("Error in Eve LLM input consumption:", error);
|
|
30952
|
+
return void 0;
|
|
30953
|
+
}
|
|
30954
|
+
}
|
|
30955
|
+
function capturedModelInput(modelInput) {
|
|
30956
|
+
if (!isObject(modelInput)) {
|
|
30957
|
+
return void 0;
|
|
30958
|
+
}
|
|
30959
|
+
const messages = modelInput["messages"];
|
|
30960
|
+
if (!Array.isArray(messages)) {
|
|
30961
|
+
return void 0;
|
|
30962
|
+
}
|
|
30963
|
+
const instructions = modelInput["instructions"];
|
|
30964
|
+
const value = [
|
|
30965
|
+
...instructions !== void 0 ? [{ content: instructions, role: "system" }] : [],
|
|
30966
|
+
...messages
|
|
30967
|
+
];
|
|
30968
|
+
try {
|
|
30969
|
+
const cloned = JSON.parse(JSON.stringify(value));
|
|
30970
|
+
if (!Array.isArray(cloned)) {
|
|
30971
|
+
return void 0;
|
|
30972
|
+
}
|
|
30973
|
+
return cloned;
|
|
30974
|
+
} catch {
|
|
30975
|
+
return void 0;
|
|
30976
|
+
}
|
|
30977
|
+
}
|
|
30978
|
+
function isCapturedModelInput(input) {
|
|
30979
|
+
return Array.isArray(input);
|
|
30980
|
+
}
|
|
30981
|
+
function llmInputKey(sessionId, turnId, stepIndex) {
|
|
30982
|
+
return `${sessionId}\0${turnId}\0${stepIndex}`;
|
|
30983
|
+
}
|
|
30984
|
+
function modelMetadataFromRuntime(runtime) {
|
|
30985
|
+
if (!isObject(runtime)) {
|
|
30986
|
+
return {};
|
|
30987
|
+
}
|
|
30988
|
+
const modelId = runtime["modelId"];
|
|
30989
|
+
return typeof modelId === "string" && !modelId.trim().startsWith("dynamic:") ? modelMetadataFromModelId(modelId) : {};
|
|
30990
|
+
}
|
|
30991
|
+
function modelMetadataFromModelId(modelId) {
|
|
30992
|
+
const normalized = modelId.trim();
|
|
30993
|
+
if (!normalized) {
|
|
30994
|
+
return {};
|
|
30995
|
+
}
|
|
30996
|
+
const slashIndex = normalized.indexOf("/");
|
|
30997
|
+
if (slashIndex > 0 && slashIndex < normalized.length - 1) {
|
|
30998
|
+
return {
|
|
30999
|
+
model: normalized.slice(slashIndex + 1),
|
|
31000
|
+
provider: normalized.slice(0, slashIndex)
|
|
31001
|
+
};
|
|
31002
|
+
}
|
|
31003
|
+
return {
|
|
31004
|
+
model: normalized
|
|
31005
|
+
};
|
|
31006
|
+
}
|
|
31007
|
+
function sessionIdFromContext(ctx) {
|
|
31008
|
+
if (!isObject(ctx)) {
|
|
31009
|
+
return void 0;
|
|
31010
|
+
}
|
|
31011
|
+
const session = ctx["session"];
|
|
31012
|
+
if (!isObject(session)) {
|
|
31013
|
+
return void 0;
|
|
31014
|
+
}
|
|
31015
|
+
const id = session["id"];
|
|
31016
|
+
return typeof id === "string" ? id : void 0;
|
|
31017
|
+
}
|
|
31018
|
+
function toolMetadataFromTurn(turn) {
|
|
31019
|
+
const { model: _model, provider: _provider, ...metadata } = turn.metadata;
|
|
31020
|
+
return metadata;
|
|
31021
|
+
}
|
|
31022
|
+
function isToolCallAction(action) {
|
|
31023
|
+
return isObject(action) && action["kind"] === "tool-call" && typeof action["callId"] === "string" && typeof action["toolName"] === "string" && isObject(action["input"]);
|
|
31024
|
+
}
|
|
31025
|
+
function isLocalSubagentCallAction(action) {
|
|
31026
|
+
return isObject(action) && action["kind"] === "subagent-call" && typeof action["callId"] === "string" && isObject(action["input"]);
|
|
31027
|
+
}
|
|
31028
|
+
function isTraceableActionRequest(action) {
|
|
31029
|
+
return isToolCallAction(action) || isLocalSubagentCallAction(action);
|
|
31030
|
+
}
|
|
31031
|
+
function isToolResult(result) {
|
|
31032
|
+
return isObject(result) && result["kind"] === "tool-result" && typeof result["callId"] === "string" && typeof result["toolName"] === "string";
|
|
31033
|
+
}
|
|
31034
|
+
function isSubagentResult(result) {
|
|
31035
|
+
return isObject(result) && result["kind"] === "subagent-result" && typeof result["callId"] === "string" && typeof result["subagentName"] === "string";
|
|
31036
|
+
}
|
|
31037
|
+
function normalizedFinishReason(finishReason) {
|
|
31038
|
+
switch (finishReason) {
|
|
31039
|
+
case "content-filter":
|
|
31040
|
+
return "content_filter";
|
|
31041
|
+
case "tool-calls":
|
|
31042
|
+
return "tool_calls";
|
|
31043
|
+
default:
|
|
31044
|
+
return finishReason;
|
|
31045
|
+
}
|
|
31046
|
+
}
|
|
31047
|
+
function errorFromMessage(message, code, details) {
|
|
31048
|
+
const error = new Error(`${code}: ${message}`);
|
|
31049
|
+
if (details !== void 0) {
|
|
31050
|
+
error.cause = details;
|
|
31051
|
+
}
|
|
31052
|
+
return error;
|
|
31053
|
+
}
|
|
31054
|
+
function actionResultError(error, output) {
|
|
31055
|
+
if (error) {
|
|
31056
|
+
return errorFromMessage(error.message, error.code);
|
|
31057
|
+
}
|
|
31058
|
+
const result = new Error("Eve action failed");
|
|
31059
|
+
if (output !== void 0) {
|
|
31060
|
+
result.cause = output;
|
|
31061
|
+
}
|
|
31062
|
+
return result;
|
|
31063
|
+
}
|
|
31064
|
+
function eventTime2(event) {
|
|
31065
|
+
if (!event.meta?.at) {
|
|
31066
|
+
return void 0;
|
|
31067
|
+
}
|
|
31068
|
+
const timestamp = Date.parse(event.meta.at);
|
|
31069
|
+
return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
|
|
31070
|
+
}
|
|
31071
|
+
function turnKey2(sessionId, turnId) {
|
|
31072
|
+
return `${sessionId}:${turnId}`;
|
|
31073
|
+
}
|
|
31074
|
+
function toolKey3(sessionId, callId) {
|
|
31075
|
+
return `${sessionId}:${callId}`;
|
|
31076
|
+
}
|
|
31077
|
+
async function generateEveIds(kind, ...parts) {
|
|
31078
|
+
const [rowId, spanId] = await Promise.all([
|
|
31079
|
+
deterministicEveId(`eve:row:${kind}`, ...parts),
|
|
31080
|
+
deterministicEveId(`eve:${kind}`, ...parts)
|
|
31081
|
+
]);
|
|
31082
|
+
return { rowId, spanId };
|
|
31083
|
+
}
|
|
31084
|
+
async function deterministicEveId(...parts) {
|
|
31085
|
+
const data = new TextEncoder().encode(
|
|
31086
|
+
parts.map((part) => `${part.length}:${part}`).join("\0")
|
|
31087
|
+
);
|
|
31088
|
+
const digest = await globalThis.crypto.subtle.digest("SHA-256", data);
|
|
31089
|
+
const bytes = Array.from(new Uint8Array(digest, 0, 16));
|
|
31090
|
+
const hex = bytes.map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
31091
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
31092
|
+
}
|
|
28939
31093
|
|
|
28940
31094
|
// src/instrumentation/config.ts
|
|
28941
31095
|
var envIntegrationAliases = {
|
|
@@ -28998,7 +31152,8 @@ var envIntegrationAliases = {
|
|
|
28998
31152
|
langchain: "langchain",
|
|
28999
31153
|
"langchain-js": "langchain",
|
|
29000
31154
|
"@langchain": "langchain",
|
|
29001
|
-
langgraph: "langgraph"
|
|
31155
|
+
langgraph: "langgraph",
|
|
31156
|
+
langsmith: "langsmith"
|
|
29002
31157
|
};
|
|
29003
31158
|
function getDefaultInstrumentationIntegrations() {
|
|
29004
31159
|
return {
|
|
@@ -29029,6 +31184,7 @@ function getDefaultInstrumentationIntegrations() {
|
|
|
29029
31184
|
gitHubCopilot: true,
|
|
29030
31185
|
langchain: true,
|
|
29031
31186
|
langgraph: true,
|
|
31187
|
+
langsmith: true,
|
|
29032
31188
|
piCodingAgent: true,
|
|
29033
31189
|
strandsAgentSDK: true
|
|
29034
31190
|
};
|
|
@@ -29145,6 +31301,8 @@ export {
|
|
|
29145
31301
|
BasePlugin,
|
|
29146
31302
|
BraintrustPlugin,
|
|
29147
31303
|
OpenAIAgentsTraceProcessor,
|
|
31304
|
+
braintrustEveHook,
|
|
31305
|
+
braintrustEveInstrumentation,
|
|
29148
31306
|
braintrustFlueInstrumentation,
|
|
29149
31307
|
braintrustFlueObserver,
|
|
29150
31308
|
configureInstrumentation,
|