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
|
@@ -33,6 +33,8 @@ __export(index_exports, {
|
|
|
33
33
|
BasePlugin: () => BasePlugin,
|
|
34
34
|
BraintrustPlugin: () => BraintrustPlugin,
|
|
35
35
|
OpenAIAgentsTraceProcessor: () => OpenAIAgentsTraceProcessor,
|
|
36
|
+
braintrustEveHook: () => braintrustEveHook,
|
|
37
|
+
braintrustEveInstrumentation: () => braintrustEveInstrumentation,
|
|
36
38
|
braintrustFlueInstrumentation: () => braintrustFlueInstrumentation,
|
|
37
39
|
braintrustFlueObserver: () => braintrustFlueObserver,
|
|
38
40
|
configureInstrumentation: () => configureInstrumentation,
|
|
@@ -2316,19 +2318,30 @@ var CallEvent = import_v36.z.union([
|
|
|
2316
2318
|
var ChatCompletionContentPartTextWithTitle = import_v36.z.object({
|
|
2317
2319
|
text: import_v36.z.string().default(""),
|
|
2318
2320
|
type: import_v36.z.literal("text"),
|
|
2319
|
-
cache_control: import_v36.z.object({
|
|
2321
|
+
cache_control: import_v36.z.object({
|
|
2322
|
+
type: import_v36.z.literal("ephemeral"),
|
|
2323
|
+
ttl: import_v36.z.enum(["5m", "1h"]).optional()
|
|
2324
|
+
}).optional()
|
|
2320
2325
|
});
|
|
2321
2326
|
var ChatCompletionContentPartImageWithTitle = import_v36.z.object({
|
|
2322
2327
|
image_url: import_v36.z.object({
|
|
2323
2328
|
url: import_v36.z.string(),
|
|
2324
2329
|
detail: import_v36.z.union([import_v36.z.literal("auto"), import_v36.z.literal("low"), import_v36.z.literal("high")]).optional()
|
|
2325
2330
|
}),
|
|
2326
|
-
type: import_v36.z.literal("image_url")
|
|
2331
|
+
type: import_v36.z.literal("image_url"),
|
|
2332
|
+
cache_control: import_v36.z.object({
|
|
2333
|
+
type: import_v36.z.literal("ephemeral"),
|
|
2334
|
+
ttl: import_v36.z.enum(["5m", "1h"]).optional()
|
|
2335
|
+
}).optional()
|
|
2327
2336
|
});
|
|
2328
2337
|
var ChatCompletionContentPartFileFile = import_v36.z.object({ file_data: import_v36.z.string(), filename: import_v36.z.string(), file_id: import_v36.z.string() }).partial();
|
|
2329
2338
|
var ChatCompletionContentPartFileWithTitle = import_v36.z.object({
|
|
2330
2339
|
file: ChatCompletionContentPartFileFile,
|
|
2331
|
-
type: import_v36.z.literal("file")
|
|
2340
|
+
type: import_v36.z.literal("file"),
|
|
2341
|
+
cache_control: import_v36.z.object({
|
|
2342
|
+
type: import_v36.z.literal("ephemeral"),
|
|
2343
|
+
ttl: import_v36.z.enum(["5m", "1h"]).optional()
|
|
2344
|
+
}).optional()
|
|
2332
2345
|
});
|
|
2333
2346
|
var ChatCompletionContentPart = import_v36.z.union([
|
|
2334
2347
|
ChatCompletionContentPartTextWithTitle,
|
|
@@ -2338,7 +2351,10 @@ var ChatCompletionContentPart = import_v36.z.union([
|
|
|
2338
2351
|
var ChatCompletionContentPartText = import_v36.z.object({
|
|
2339
2352
|
text: import_v36.z.string().default(""),
|
|
2340
2353
|
type: import_v36.z.literal("text"),
|
|
2341
|
-
cache_control: import_v36.z.object({
|
|
2354
|
+
cache_control: import_v36.z.object({
|
|
2355
|
+
type: import_v36.z.literal("ephemeral"),
|
|
2356
|
+
ttl: import_v36.z.enum(["5m", "1h"]).optional()
|
|
2357
|
+
}).optional()
|
|
2342
2358
|
});
|
|
2343
2359
|
var ChatCompletionMessageToolCall = import_v36.z.object({
|
|
2344
2360
|
id: import_v36.z.string(),
|
|
@@ -4345,7 +4361,7 @@ var DiskCache = class {
|
|
|
4345
4361
|
}
|
|
4346
4362
|
};
|
|
4347
4363
|
|
|
4348
|
-
// src/
|
|
4364
|
+
// src/lru-cache.ts
|
|
4349
4365
|
var LRUCache = class {
|
|
4350
4366
|
cache;
|
|
4351
4367
|
maxSize;
|
|
@@ -4361,13 +4377,23 @@ var LRUCache = class {
|
|
|
4361
4377
|
* @returns The cached value if found, undefined otherwise.
|
|
4362
4378
|
*/
|
|
4363
4379
|
get(key) {
|
|
4364
|
-
const
|
|
4365
|
-
if (
|
|
4380
|
+
const entry = this.cache.get(key);
|
|
4381
|
+
if (entry === void 0) {
|
|
4366
4382
|
return void 0;
|
|
4367
4383
|
}
|
|
4368
4384
|
this.cache.delete(key);
|
|
4369
|
-
this.cache.set(key,
|
|
4370
|
-
return value;
|
|
4385
|
+
this.cache.set(key, entry);
|
|
4386
|
+
return entry.value;
|
|
4387
|
+
}
|
|
4388
|
+
/**
|
|
4389
|
+
* Checks whether a key exists and marks it as most recently used.
|
|
4390
|
+
*/
|
|
4391
|
+
has(key) {
|
|
4392
|
+
if (!this.cache.has(key)) {
|
|
4393
|
+
return false;
|
|
4394
|
+
}
|
|
4395
|
+
this.get(key);
|
|
4396
|
+
return true;
|
|
4371
4397
|
}
|
|
4372
4398
|
/**
|
|
4373
4399
|
* Stores a value in the cache.
|
|
@@ -4384,7 +4410,38 @@ var LRUCache = class {
|
|
|
4384
4410
|
const first = this.cache.keys().next().value;
|
|
4385
4411
|
this.cache.delete(first);
|
|
4386
4412
|
}
|
|
4387
|
-
this.cache.set(key, value);
|
|
4413
|
+
this.cache.set(key, { value });
|
|
4414
|
+
}
|
|
4415
|
+
/**
|
|
4416
|
+
* Removes an item from the cache.
|
|
4417
|
+
*/
|
|
4418
|
+
delete(key) {
|
|
4419
|
+
return this.cache.delete(key);
|
|
4420
|
+
}
|
|
4421
|
+
/**
|
|
4422
|
+
* Iterates over cache entries from least to most recently used.
|
|
4423
|
+
*/
|
|
4424
|
+
*entries() {
|
|
4425
|
+
for (const [key, entry] of this.cache) {
|
|
4426
|
+
yield [key, entry.value];
|
|
4427
|
+
}
|
|
4428
|
+
}
|
|
4429
|
+
/**
|
|
4430
|
+
* Iterates over cache keys from least to most recently used.
|
|
4431
|
+
*/
|
|
4432
|
+
keys() {
|
|
4433
|
+
return this.cache.keys();
|
|
4434
|
+
}
|
|
4435
|
+
/**
|
|
4436
|
+
* Iterates over cache values from least to most recently used.
|
|
4437
|
+
*/
|
|
4438
|
+
*values() {
|
|
4439
|
+
for (const entry of this.cache.values()) {
|
|
4440
|
+
yield entry.value;
|
|
4441
|
+
}
|
|
4442
|
+
}
|
|
4443
|
+
[Symbol.iterator]() {
|
|
4444
|
+
return this.entries();
|
|
4388
4445
|
}
|
|
4389
4446
|
/**
|
|
4390
4447
|
* Removes all items from the cache.
|
|
@@ -4942,6 +4999,9 @@ function applyMaskingToField(maskingFunction, data, fieldName) {
|
|
|
4942
4999
|
return `ERROR: Failed to mask field '${fieldName}' - ${errorType}`;
|
|
4943
5000
|
}
|
|
4944
5001
|
}
|
|
5002
|
+
var INITIAL_SPAN_WRITE_AS_MERGE = /* @__PURE__ */ Symbol(
|
|
5003
|
+
"braintrust.initial-span-write-as-merge"
|
|
5004
|
+
);
|
|
4945
5005
|
var BRAINTRUST_CURRENT_SPAN_STORE = /* @__PURE__ */ Symbol.for(
|
|
4946
5006
|
"braintrust.currentSpanStore"
|
|
4947
5007
|
);
|
|
@@ -5498,25 +5558,46 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
5498
5558
|
})
|
|
5499
5559
|
);
|
|
5500
5560
|
}
|
|
5501
|
-
async post(path, params, config) {
|
|
5561
|
+
async post(path, params, config, retries = 0) {
|
|
5502
5562
|
const { headers, ...rest } = config || {};
|
|
5503
5563
|
const this_fetch = this.fetch;
|
|
5504
5564
|
const this_base_url = this.base_url;
|
|
5505
5565
|
const this_headers = this.headers;
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
|
|
5566
|
+
const tries = retries + 1;
|
|
5567
|
+
for (let i = 0; i < tries; i++) {
|
|
5568
|
+
try {
|
|
5569
|
+
return await checkResponse(
|
|
5570
|
+
await this_fetch(_urljoin(this_base_url, path), {
|
|
5571
|
+
method: "POST",
|
|
5572
|
+
headers: {
|
|
5573
|
+
Accept: "application/json",
|
|
5574
|
+
"Content-Type": "application/json",
|
|
5575
|
+
...this_headers,
|
|
5576
|
+
...headers
|
|
5577
|
+
},
|
|
5578
|
+
body: typeof params === "string" ? params : params ? JSON.stringify(params) : void 0,
|
|
5579
|
+
keepalive: true,
|
|
5580
|
+
...rest
|
|
5581
|
+
})
|
|
5582
|
+
);
|
|
5583
|
+
} catch (error) {
|
|
5584
|
+
if (config?.signal?.aborted) {
|
|
5585
|
+
throw getAbortReason(config.signal);
|
|
5586
|
+
}
|
|
5587
|
+
if (i === tries - 1 || !isRetryableHTTPError(error)) {
|
|
5588
|
+
throw error;
|
|
5589
|
+
}
|
|
5590
|
+
debugLogger.debug(
|
|
5591
|
+
`Retrying API request ${path} after ${formatHTTPError(error)}`
|
|
5592
|
+
);
|
|
5593
|
+
const sleepTimeMs = HTTP_RETRY_BASE_SLEEP_TIME_S * 1e3 * 2 ** i + Math.random() * HTTP_RETRY_JITTER_MS;
|
|
5594
|
+
debugLogger.info(
|
|
5595
|
+
`Sleeping for ${sleepTimeMs}ms before retrying API request`
|
|
5596
|
+
);
|
|
5597
|
+
await waitForRetry(sleepTimeMs, config?.signal);
|
|
5598
|
+
}
|
|
5599
|
+
}
|
|
5600
|
+
throw new Error("Unexpected retry state");
|
|
5520
5601
|
}
|
|
5521
5602
|
async get_json(object_type, args = void 0, retries = 0) {
|
|
5522
5603
|
const tries = retries + 1;
|
|
@@ -5940,6 +6021,28 @@ function updateSpanImpl({
|
|
|
5940
6021
|
}));
|
|
5941
6022
|
state.bgLogger().log([record]);
|
|
5942
6023
|
}
|
|
6024
|
+
function updateSpan({
|
|
6025
|
+
exported,
|
|
6026
|
+
state,
|
|
6027
|
+
...event
|
|
6028
|
+
}) {
|
|
6029
|
+
const resolvedState = state ?? _globalState;
|
|
6030
|
+
const components = SpanComponentsV4.fromStr(exported);
|
|
6031
|
+
if (!components.data.row_id) {
|
|
6032
|
+
throw new Error("Exported span must have a row id");
|
|
6033
|
+
}
|
|
6034
|
+
updateSpanImpl({
|
|
6035
|
+
state: resolvedState,
|
|
6036
|
+
parentObjectType: components.data.object_type,
|
|
6037
|
+
parentObjectId: new LazyValue(
|
|
6038
|
+
spanComponentsToObjectIdLambda(resolvedState, components)
|
|
6039
|
+
),
|
|
6040
|
+
id: components.data.row_id,
|
|
6041
|
+
root_span_id: components.data.root_span_id,
|
|
6042
|
+
span_id: components.data.span_id,
|
|
6043
|
+
event
|
|
6044
|
+
});
|
|
6045
|
+
}
|
|
5943
6046
|
function spanComponentsToObjectIdLambda(state, components) {
|
|
5944
6047
|
if (components.data.object_id) {
|
|
5945
6048
|
const ret = components.data.object_id;
|
|
@@ -6416,6 +6519,45 @@ function now() {
|
|
|
6416
6519
|
var DEFAULT_FLUSH_BACKPRESSURE_BYTES = 10 * 1024 * 1024;
|
|
6417
6520
|
var BACKGROUND_LOGGER_BASE_SLEEP_TIME_S = 1;
|
|
6418
6521
|
var HTTP_RETRY_BASE_SLEEP_TIME_S = 1;
|
|
6522
|
+
var HTTP_RETRY_JITTER_MS = 200;
|
|
6523
|
+
var BTQL_HTTP_RETRIES = 3;
|
|
6524
|
+
var RETRYABLE_HTTP_STATUS_CODES = /* @__PURE__ */ new Set([500, 502, 503, 504]);
|
|
6525
|
+
function isRetryableHTTPError(error) {
|
|
6526
|
+
return !(error instanceof FailedHTTPResponse) || RETRYABLE_HTTP_STATUS_CODES.has(error.status);
|
|
6527
|
+
}
|
|
6528
|
+
function formatHTTPError(error) {
|
|
6529
|
+
if (error instanceof FailedHTTPResponse) {
|
|
6530
|
+
return `${error.status} ${error.text}`;
|
|
6531
|
+
}
|
|
6532
|
+
return error instanceof Error ? error.message : String(error);
|
|
6533
|
+
}
|
|
6534
|
+
function getAbortReason(signal) {
|
|
6535
|
+
return signal.reason ?? new Error("Request aborted");
|
|
6536
|
+
}
|
|
6537
|
+
async function waitForRetry(delayMs, signal) {
|
|
6538
|
+
if (!signal) {
|
|
6539
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
6540
|
+
return;
|
|
6541
|
+
}
|
|
6542
|
+
if (signal.aborted) {
|
|
6543
|
+
throw getAbortReason(signal);
|
|
6544
|
+
}
|
|
6545
|
+
await new Promise((resolve, reject) => {
|
|
6546
|
+
const onAbort = () => {
|
|
6547
|
+
clearTimeout(timeout);
|
|
6548
|
+
signal.removeEventListener("abort", onAbort);
|
|
6549
|
+
reject(getAbortReason(signal));
|
|
6550
|
+
};
|
|
6551
|
+
const timeout = setTimeout(() => {
|
|
6552
|
+
signal.removeEventListener("abort", onAbort);
|
|
6553
|
+
resolve();
|
|
6554
|
+
}, delayMs);
|
|
6555
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
6556
|
+
if (signal.aborted) {
|
|
6557
|
+
onAbort();
|
|
6558
|
+
}
|
|
6559
|
+
});
|
|
6560
|
+
}
|
|
6419
6561
|
var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
|
|
6420
6562
|
apiConn;
|
|
6421
6563
|
queue;
|
|
@@ -7367,21 +7509,27 @@ function parentSpanIdsUsable(spanId, rootSpanId) {
|
|
|
7367
7509
|
return Boolean(spanId) && Boolean(rootSpanId);
|
|
7368
7510
|
}
|
|
7369
7511
|
function logError(span, error) {
|
|
7370
|
-
let
|
|
7512
|
+
let errorMessage2 = "<error>";
|
|
7371
7513
|
let stackTrace = "";
|
|
7372
7514
|
if (error instanceof Error) {
|
|
7373
|
-
|
|
7515
|
+
errorMessage2 = error.message;
|
|
7374
7516
|
stackTrace = error.stack || "";
|
|
7375
7517
|
} else {
|
|
7376
|
-
|
|
7518
|
+
errorMessage2 = String(error);
|
|
7377
7519
|
}
|
|
7378
|
-
span.log({ error: `${
|
|
7520
|
+
span.log({ error: `${errorMessage2}
|
|
7379
7521
|
|
|
7380
7522
|
${stackTrace}` });
|
|
7381
7523
|
}
|
|
7382
7524
|
function startSpan(args) {
|
|
7383
7525
|
return startSpanAndIsLogger(args).span;
|
|
7384
7526
|
}
|
|
7527
|
+
function _internalStartSpanWithInitialMerge(args) {
|
|
7528
|
+
return startSpanAndIsLogger({
|
|
7529
|
+
...args,
|
|
7530
|
+
[INITIAL_SPAN_WRITE_AS_MERGE]: true
|
|
7531
|
+
}).span;
|
|
7532
|
+
}
|
|
7385
7533
|
async function flush(options) {
|
|
7386
7534
|
const state = options?.state ?? _globalState;
|
|
7387
7535
|
return await state.bgLogger().flush();
|
|
@@ -7710,7 +7858,8 @@ var ObjectFetcher = class {
|
|
|
7710
7858
|
version: this.pinnedVersion
|
|
7711
7859
|
} : {}
|
|
7712
7860
|
},
|
|
7713
|
-
{ headers: { "Accept-Encoding": "gzip" } }
|
|
7861
|
+
{ headers: { "Accept-Encoding": "gzip" } },
|
|
7862
|
+
BTQL_HTTP_RETRIES
|
|
7714
7863
|
);
|
|
7715
7864
|
const respJson = await resp.json();
|
|
7716
7865
|
const mutate = this.mutateRecord;
|
|
@@ -8186,7 +8335,7 @@ var SpanImpl = class _SpanImpl {
|
|
|
8186
8335
|
this._spanId = resolvedIds.spanId;
|
|
8187
8336
|
this._rootSpanId = resolvedIds.rootSpanId;
|
|
8188
8337
|
this._spanParents = resolvedIds.spanParents;
|
|
8189
|
-
this.isMerge =
|
|
8338
|
+
this.isMerge = args[INITIAL_SPAN_WRITE_AS_MERGE] === true;
|
|
8190
8339
|
this.logInternal({ event, internalData });
|
|
8191
8340
|
this.isMerge = true;
|
|
8192
8341
|
}
|
|
@@ -27100,6 +27249,446 @@ function isBraintrustHandler(handler) {
|
|
|
27100
27249
|
return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
27101
27250
|
}
|
|
27102
27251
|
|
|
27252
|
+
// src/instrumentation/plugins/langsmith-channels.ts
|
|
27253
|
+
var langSmithChannels = defineChannels("langsmith", {
|
|
27254
|
+
createRun: channel({
|
|
27255
|
+
channelName: "Client.createRun",
|
|
27256
|
+
kind: "async"
|
|
27257
|
+
}),
|
|
27258
|
+
updateRun: channel({
|
|
27259
|
+
channelName: "Client.updateRun",
|
|
27260
|
+
kind: "async"
|
|
27261
|
+
}),
|
|
27262
|
+
batchIngestRuns: channel({
|
|
27263
|
+
channelName: "Client.batchIngestRuns",
|
|
27264
|
+
kind: "async"
|
|
27265
|
+
})
|
|
27266
|
+
});
|
|
27267
|
+
|
|
27268
|
+
// src/instrumentation/plugins/langsmith-plugin.ts
|
|
27269
|
+
var MAX_COMPLETED_RUNS = 1e4;
|
|
27270
|
+
var BLOCKED_METADATA_KEYS = /* @__PURE__ */ new Set([
|
|
27271
|
+
"__proto__",
|
|
27272
|
+
"constructor",
|
|
27273
|
+
"prototype",
|
|
27274
|
+
"usage_metadata"
|
|
27275
|
+
]);
|
|
27276
|
+
var BLOCKED_METADATA_PREFIXES = ["__pregel_", "langgraph_", "lc_"];
|
|
27277
|
+
var LLM_SETTING_KEYS = [
|
|
27278
|
+
"temperature",
|
|
27279
|
+
"top_p",
|
|
27280
|
+
"max_tokens",
|
|
27281
|
+
"frequency_penalty",
|
|
27282
|
+
"presence_penalty",
|
|
27283
|
+
"stop",
|
|
27284
|
+
"response_format"
|
|
27285
|
+
];
|
|
27286
|
+
var LangSmithPlugin = class extends BasePlugin {
|
|
27287
|
+
activeRuns = /* @__PURE__ */ new Map();
|
|
27288
|
+
completedRuns = new LRUCache({
|
|
27289
|
+
max: MAX_COMPLETED_RUNS
|
|
27290
|
+
});
|
|
27291
|
+
skipLangChainRuns;
|
|
27292
|
+
constructor(options = {}) {
|
|
27293
|
+
super();
|
|
27294
|
+
this.skipLangChainRuns = options.skipLangChainRuns ?? true;
|
|
27295
|
+
}
|
|
27296
|
+
onEnable() {
|
|
27297
|
+
const createChannel = langSmithChannels.createRun.tracingChannel();
|
|
27298
|
+
const createHandlers = {
|
|
27299
|
+
start: (event) => {
|
|
27300
|
+
this.containLifecycleFailure("createRun", () => {
|
|
27301
|
+
this.processCreate(event.arguments[0]);
|
|
27302
|
+
});
|
|
27303
|
+
}
|
|
27304
|
+
};
|
|
27305
|
+
createChannel.subscribe(createHandlers);
|
|
27306
|
+
this.unsubscribers.push(() => createChannel.unsubscribe(createHandlers));
|
|
27307
|
+
const updateChannel = langSmithChannels.updateRun.tracingChannel();
|
|
27308
|
+
const updateHandlers = {
|
|
27309
|
+
start: (event) => {
|
|
27310
|
+
this.containLifecycleFailure("updateRun", () => {
|
|
27311
|
+
this.processUpdate(event.arguments[0], event.arguments[1]);
|
|
27312
|
+
});
|
|
27313
|
+
}
|
|
27314
|
+
};
|
|
27315
|
+
updateChannel.subscribe(updateHandlers);
|
|
27316
|
+
this.unsubscribers.push(() => updateChannel.unsubscribe(updateHandlers));
|
|
27317
|
+
const batchChannel = langSmithChannels.batchIngestRuns.tracingChannel();
|
|
27318
|
+
const batchHandlers = {
|
|
27319
|
+
start: (event) => {
|
|
27320
|
+
this.containLifecycleFailure("batchIngestRuns", () => {
|
|
27321
|
+
this.processBatch(event.arguments[0]);
|
|
27322
|
+
});
|
|
27323
|
+
}
|
|
27324
|
+
};
|
|
27325
|
+
batchChannel.subscribe(batchHandlers);
|
|
27326
|
+
this.unsubscribers.push(() => batchChannel.unsubscribe(batchHandlers));
|
|
27327
|
+
}
|
|
27328
|
+
onDisable() {
|
|
27329
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
27330
|
+
for (const { span } of this.activeRuns.values()) {
|
|
27331
|
+
span.end();
|
|
27332
|
+
}
|
|
27333
|
+
this.activeRuns.clear();
|
|
27334
|
+
this.completedRuns.clear();
|
|
27335
|
+
}
|
|
27336
|
+
processBatch(batch) {
|
|
27337
|
+
if (!isRecord2(batch)) {
|
|
27338
|
+
return;
|
|
27339
|
+
}
|
|
27340
|
+
const creates = ownValue(batch, "runCreates");
|
|
27341
|
+
if (Array.isArray(creates)) {
|
|
27342
|
+
const parentFirst = [...creates].sort((left, right) => {
|
|
27343
|
+
const leftId = stringValue2(ownValue(left, "id"));
|
|
27344
|
+
const rightId = stringValue2(ownValue(right, "id"));
|
|
27345
|
+
const leftParent = stringValue2(ownValue(left, "parent_run_id"));
|
|
27346
|
+
const rightParent = stringValue2(ownValue(right, "parent_run_id"));
|
|
27347
|
+
if (leftParent && leftParent === rightId) {
|
|
27348
|
+
return 1;
|
|
27349
|
+
}
|
|
27350
|
+
if (rightParent && rightParent === leftId) {
|
|
27351
|
+
return -1;
|
|
27352
|
+
}
|
|
27353
|
+
return dottedOrderDepth(left) - dottedOrderDepth(right);
|
|
27354
|
+
});
|
|
27355
|
+
for (const run of parentFirst) {
|
|
27356
|
+
this.containLifecycleFailure("batchIngestRuns create", () => {
|
|
27357
|
+
this.processCreate(run);
|
|
27358
|
+
});
|
|
27359
|
+
}
|
|
27360
|
+
}
|
|
27361
|
+
const updates = ownValue(batch, "runUpdates");
|
|
27362
|
+
if (Array.isArray(updates)) {
|
|
27363
|
+
for (const run of updates) {
|
|
27364
|
+
this.containLifecycleFailure("batchIngestRuns update", () => {
|
|
27365
|
+
this.processUpdate(stringValue2(ownValue(run, "id")) ?? "", run);
|
|
27366
|
+
});
|
|
27367
|
+
}
|
|
27368
|
+
}
|
|
27369
|
+
}
|
|
27370
|
+
processCreate(run) {
|
|
27371
|
+
const id = stringValue2(ownValue(run, "id"));
|
|
27372
|
+
if (!id || this.completedRuns.get(id)) {
|
|
27373
|
+
return;
|
|
27374
|
+
}
|
|
27375
|
+
if (this.shouldSkipLangChainRun(run)) {
|
|
27376
|
+
this.completedRuns.set(id, true);
|
|
27377
|
+
return;
|
|
27378
|
+
}
|
|
27379
|
+
const active = this.activeRuns.get(id);
|
|
27380
|
+
if (active) {
|
|
27381
|
+
const previous = active.run;
|
|
27382
|
+
active.run = mergeRuns(previous, run);
|
|
27383
|
+
this.logRun(
|
|
27384
|
+
active.span,
|
|
27385
|
+
active.run,
|
|
27386
|
+
previous,
|
|
27387
|
+
timestampSeconds(ownValue(active.run, "end_time")) !== void 0 || errorMessage(ownValue(active.run, "error")) !== void 0
|
|
27388
|
+
);
|
|
27389
|
+
this.endIfComplete(id, active, active.run);
|
|
27390
|
+
return;
|
|
27391
|
+
}
|
|
27392
|
+
const span = this.startRunSpan(id, run);
|
|
27393
|
+
const activeRun = { run, span };
|
|
27394
|
+
this.activeRuns.set(id, activeRun);
|
|
27395
|
+
this.logRun(
|
|
27396
|
+
span,
|
|
27397
|
+
run,
|
|
27398
|
+
void 0,
|
|
27399
|
+
timestampSeconds(ownValue(run, "end_time")) !== void 0 || errorMessage(ownValue(run, "error")) !== void 0
|
|
27400
|
+
);
|
|
27401
|
+
this.endIfComplete(id, activeRun, run);
|
|
27402
|
+
}
|
|
27403
|
+
processUpdate(explicitId, run) {
|
|
27404
|
+
const id = stringValue2(explicitId) ?? stringValue2(ownValue(run, "id"));
|
|
27405
|
+
if (!id || this.completedRuns.get(id)) {
|
|
27406
|
+
return;
|
|
27407
|
+
}
|
|
27408
|
+
if (this.shouldSkipLangChainRun(run)) {
|
|
27409
|
+
const active2 = this.activeRuns.get(id);
|
|
27410
|
+
active2?.span.end();
|
|
27411
|
+
this.activeRuns.delete(id);
|
|
27412
|
+
this.completedRuns.set(id, true);
|
|
27413
|
+
return;
|
|
27414
|
+
}
|
|
27415
|
+
let active = this.activeRuns.get(id);
|
|
27416
|
+
if (!active) {
|
|
27417
|
+
const span = this.startRunSpan(id, run);
|
|
27418
|
+
active = { run, span };
|
|
27419
|
+
this.activeRuns.set(id, active);
|
|
27420
|
+
}
|
|
27421
|
+
const previous = active.run;
|
|
27422
|
+
active.run = mergeRuns(previous, run);
|
|
27423
|
+
this.logRun(active.span, active.run, previous, true);
|
|
27424
|
+
this.endIfComplete(id, active, active.run);
|
|
27425
|
+
}
|
|
27426
|
+
startRunSpan(id, run) {
|
|
27427
|
+
const traceId = stringValue2(ownValue(run, "trace_id")) ?? id;
|
|
27428
|
+
const parentId = stringValue2(ownValue(run, "parent_run_id")) ?? stringValue2(ownValue(ownValue(run, "parent_run"), "id"));
|
|
27429
|
+
const startTime = timestampSeconds(ownValue(run, "start_time"));
|
|
27430
|
+
return startSpan({
|
|
27431
|
+
name: stringValue2(ownValue(run, "name")) ?? "LangSmith run",
|
|
27432
|
+
spanId: id,
|
|
27433
|
+
parentSpanIds: {
|
|
27434
|
+
parentSpanIds: parentId ? [parentId] : [],
|
|
27435
|
+
rootSpanId: traceId
|
|
27436
|
+
},
|
|
27437
|
+
spanAttributes: {
|
|
27438
|
+
type: mapRunType(ownValue(run, "run_type"))
|
|
27439
|
+
},
|
|
27440
|
+
...startTime === void 0 ? {} : { startTime },
|
|
27441
|
+
event: { id }
|
|
27442
|
+
});
|
|
27443
|
+
}
|
|
27444
|
+
logRun(span, run, previous, includeOutput) {
|
|
27445
|
+
const inputs = preferOwnValue(run, previous, "inputs");
|
|
27446
|
+
const outputs = preferOwnValue(run, previous, "outputs");
|
|
27447
|
+
const error = errorMessage(preferOwnValue(run, previous, "error"));
|
|
27448
|
+
const metadata = extractMetadata(run, previous);
|
|
27449
|
+
const tags = extractTags(preferOwnValue(run, previous, "tags"));
|
|
27450
|
+
const metrics = extractMetrics(run, previous);
|
|
27451
|
+
span.log({
|
|
27452
|
+
...inputs === void 0 ? {} : { input: sanitizeLoggedValue(inputs) },
|
|
27453
|
+
...includeOutput && outputs !== void 0 ? { output: sanitizeLoggedValue(outputs) } : {},
|
|
27454
|
+
...error === void 0 ? {} : { error },
|
|
27455
|
+
...metadata === void 0 ? {} : { metadata },
|
|
27456
|
+
...tags === void 0 ? {} : { tags },
|
|
27457
|
+
...Object.keys(metrics).length === 0 ? {} : { metrics }
|
|
27458
|
+
});
|
|
27459
|
+
}
|
|
27460
|
+
endIfComplete(id, active, run) {
|
|
27461
|
+
const endTime = timestampSeconds(ownValue(run, "end_time"));
|
|
27462
|
+
if (endTime === void 0 && errorMessage(ownValue(run, "error")) === void 0) {
|
|
27463
|
+
return;
|
|
27464
|
+
}
|
|
27465
|
+
active.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
27466
|
+
this.activeRuns.delete(id);
|
|
27467
|
+
this.completedRuns.set(id, true);
|
|
27468
|
+
}
|
|
27469
|
+
shouldSkipLangChainRun(run) {
|
|
27470
|
+
if (!this.skipLangChainRuns) {
|
|
27471
|
+
return false;
|
|
27472
|
+
}
|
|
27473
|
+
const serialized = ownValue(run, "serialized");
|
|
27474
|
+
return isRecord2(serialized) && ownValue(serialized, "lc") === 1;
|
|
27475
|
+
}
|
|
27476
|
+
containLifecycleFailure(operation, fn) {
|
|
27477
|
+
try {
|
|
27478
|
+
fn();
|
|
27479
|
+
} catch (error) {
|
|
27480
|
+
debugLogger.error(
|
|
27481
|
+
`Failed to process LangSmith ${operation} instrumentation:`,
|
|
27482
|
+
error
|
|
27483
|
+
);
|
|
27484
|
+
}
|
|
27485
|
+
}
|
|
27486
|
+
};
|
|
27487
|
+
function ownValue(value, key) {
|
|
27488
|
+
if (!isRecord2(value)) {
|
|
27489
|
+
return void 0;
|
|
27490
|
+
}
|
|
27491
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
27492
|
+
return descriptor && "value" in descriptor ? descriptor.value : void 0;
|
|
27493
|
+
}
|
|
27494
|
+
function preferOwnValue(current, previous, key) {
|
|
27495
|
+
const currentDescriptor = isRecord2(current) ? Object.getOwnPropertyDescriptor(current, key) : void 0;
|
|
27496
|
+
if (currentDescriptor && "value" in currentDescriptor) {
|
|
27497
|
+
return currentDescriptor.value;
|
|
27498
|
+
}
|
|
27499
|
+
return ownValue(previous, key);
|
|
27500
|
+
}
|
|
27501
|
+
function mergeRuns(previous, current) {
|
|
27502
|
+
const entries = /* @__PURE__ */ new Map();
|
|
27503
|
+
for (const value of [previous, current]) {
|
|
27504
|
+
if (!isRecord2(value)) {
|
|
27505
|
+
continue;
|
|
27506
|
+
}
|
|
27507
|
+
for (const [key, descriptor] of Object.entries(
|
|
27508
|
+
Object.getOwnPropertyDescriptors(value)
|
|
27509
|
+
)) {
|
|
27510
|
+
if (descriptor.enumerable && "value" in descriptor) {
|
|
27511
|
+
entries.set(key, descriptor.value);
|
|
27512
|
+
}
|
|
27513
|
+
}
|
|
27514
|
+
}
|
|
27515
|
+
return Object.fromEntries(entries);
|
|
27516
|
+
}
|
|
27517
|
+
function isRecord2(value) {
|
|
27518
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27519
|
+
}
|
|
27520
|
+
function stringValue2(value) {
|
|
27521
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
27522
|
+
}
|
|
27523
|
+
function timestampSeconds(value) {
|
|
27524
|
+
if (value instanceof Date) {
|
|
27525
|
+
const timestamp = value.getTime();
|
|
27526
|
+
return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
|
|
27527
|
+
}
|
|
27528
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
27529
|
+
return value > 1e10 ? value / 1e3 : value;
|
|
27530
|
+
}
|
|
27531
|
+
if (typeof value === "string") {
|
|
27532
|
+
const timestamp = Date.parse(value);
|
|
27533
|
+
return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
|
|
27534
|
+
}
|
|
27535
|
+
return void 0;
|
|
27536
|
+
}
|
|
27537
|
+
function dottedOrderDepth(run) {
|
|
27538
|
+
const dottedOrder = stringValue2(ownValue(run, "dotted_order"));
|
|
27539
|
+
return dottedOrder ? dottedOrder.split(".").length : Number.MAX_SAFE_INTEGER;
|
|
27540
|
+
}
|
|
27541
|
+
function mapRunType(runType) {
|
|
27542
|
+
switch (runType) {
|
|
27543
|
+
case "llm":
|
|
27544
|
+
case "embedding":
|
|
27545
|
+
return "llm" /* LLM */;
|
|
27546
|
+
case "tool":
|
|
27547
|
+
case "retriever":
|
|
27548
|
+
return "tool" /* TOOL */;
|
|
27549
|
+
default:
|
|
27550
|
+
return "task" /* TASK */;
|
|
27551
|
+
}
|
|
27552
|
+
}
|
|
27553
|
+
function extractMetadata(run, previous) {
|
|
27554
|
+
const extra = preferOwnValue(run, previous, "extra");
|
|
27555
|
+
const rawMetadata = ownValue(extra, "metadata");
|
|
27556
|
+
if (!isRecord2(rawMetadata)) {
|
|
27557
|
+
return void 0;
|
|
27558
|
+
}
|
|
27559
|
+
const metadata = {};
|
|
27560
|
+
for (const [key, descriptor] of Object.entries(
|
|
27561
|
+
Object.getOwnPropertyDescriptors(rawMetadata)
|
|
27562
|
+
)) {
|
|
27563
|
+
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}`)) {
|
|
27564
|
+
continue;
|
|
27565
|
+
}
|
|
27566
|
+
const normalizedKey = key === "ls_provider" ? "provider" : key === "ls_model_name" ? "model" : key.startsWith("ls_") ? key.slice(3) : key;
|
|
27567
|
+
const sanitized = sanitizeLoggedValue(descriptor.value);
|
|
27568
|
+
if (sanitized !== void 0) {
|
|
27569
|
+
metadata[normalizedKey] = sanitized;
|
|
27570
|
+
}
|
|
27571
|
+
}
|
|
27572
|
+
return Object.keys(metadata).length === 0 ? void 0 : metadata;
|
|
27573
|
+
}
|
|
27574
|
+
function extractTags(value) {
|
|
27575
|
+
if (!Array.isArray(value)) {
|
|
27576
|
+
return void 0;
|
|
27577
|
+
}
|
|
27578
|
+
const tags = value.filter(
|
|
27579
|
+
(tag) => typeof tag === "string" && tag.length > 0
|
|
27580
|
+
);
|
|
27581
|
+
return tags.length > 0 ? tags : void 0;
|
|
27582
|
+
}
|
|
27583
|
+
function extractMetrics(run, previous) {
|
|
27584
|
+
const outputs = preferOwnValue(run, previous, "outputs");
|
|
27585
|
+
const extra = preferOwnValue(run, previous, "extra");
|
|
27586
|
+
const metadata = ownValue(extra, "metadata");
|
|
27587
|
+
const usage = ownValue(outputs, "usage_metadata") ?? ownValue(metadata, "usage_metadata");
|
|
27588
|
+
const metrics = {};
|
|
27589
|
+
assignFirstMetric(metrics, "prompt_tokens", usage, [
|
|
27590
|
+
"input_tokens",
|
|
27591
|
+
"prompt_tokens"
|
|
27592
|
+
]);
|
|
27593
|
+
assignFirstMetric(metrics, "completion_tokens", usage, [
|
|
27594
|
+
"output_tokens",
|
|
27595
|
+
"completion_tokens"
|
|
27596
|
+
]);
|
|
27597
|
+
assignFirstMetric(metrics, "tokens", usage, ["total_tokens", "tokens"]);
|
|
27598
|
+
const inputTokenDetails = ownValue(usage, "input_token_details");
|
|
27599
|
+
assignFirstMetric(metrics, "prompt_cached_tokens", inputTokenDetails, [
|
|
27600
|
+
"cache_read",
|
|
27601
|
+
"cached_tokens"
|
|
27602
|
+
]);
|
|
27603
|
+
if (metrics.prompt_cached_tokens === void 0) {
|
|
27604
|
+
assignFirstMetric(metrics, "prompt_cached_tokens", usage, [
|
|
27605
|
+
"cache_read_input_tokens",
|
|
27606
|
+
"prompt_cached_tokens"
|
|
27607
|
+
]);
|
|
27608
|
+
}
|
|
27609
|
+
assignFirstMetric(
|
|
27610
|
+
metrics,
|
|
27611
|
+
"prompt_cache_creation_tokens",
|
|
27612
|
+
inputTokenDetails,
|
|
27613
|
+
["cache_creation"]
|
|
27614
|
+
);
|
|
27615
|
+
if (metrics.prompt_cache_creation_tokens === void 0) {
|
|
27616
|
+
assignFirstMetric(metrics, "prompt_cache_creation_tokens", usage, [
|
|
27617
|
+
"cache_creation_input_tokens",
|
|
27618
|
+
"prompt_cache_creation_tokens"
|
|
27619
|
+
]);
|
|
27620
|
+
}
|
|
27621
|
+
if (metrics.tokens === void 0 && (metrics.prompt_tokens !== void 0 || metrics.completion_tokens !== void 0)) {
|
|
27622
|
+
metrics.tokens = (metrics.prompt_tokens ?? 0) + (metrics.completion_tokens ?? 0);
|
|
27623
|
+
}
|
|
27624
|
+
const startTime = timestampSeconds(
|
|
27625
|
+
preferOwnValue(run, previous, "start_time")
|
|
27626
|
+
);
|
|
27627
|
+
const events = preferOwnValue(run, previous, "events");
|
|
27628
|
+
if (startTime !== void 0 && Array.isArray(events)) {
|
|
27629
|
+
for (const event of events) {
|
|
27630
|
+
if (ownValue(event, "name") !== "new_token") {
|
|
27631
|
+
continue;
|
|
27632
|
+
}
|
|
27633
|
+
const eventTime3 = timestampSeconds(ownValue(event, "time"));
|
|
27634
|
+
if (eventTime3 !== void 0 && eventTime3 >= startTime) {
|
|
27635
|
+
metrics.time_to_first_token = eventTime3 - startTime;
|
|
27636
|
+
}
|
|
27637
|
+
break;
|
|
27638
|
+
}
|
|
27639
|
+
}
|
|
27640
|
+
return metrics;
|
|
27641
|
+
}
|
|
27642
|
+
function assignFirstMetric(metrics, target, source, keys) {
|
|
27643
|
+
for (const key of keys) {
|
|
27644
|
+
const value = ownValue(source, key);
|
|
27645
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
27646
|
+
metrics[target] = value;
|
|
27647
|
+
return;
|
|
27648
|
+
}
|
|
27649
|
+
}
|
|
27650
|
+
}
|
|
27651
|
+
function errorMessage(value) {
|
|
27652
|
+
if (typeof value === "string") {
|
|
27653
|
+
return value;
|
|
27654
|
+
}
|
|
27655
|
+
if (value instanceof Error) {
|
|
27656
|
+
return value.message;
|
|
27657
|
+
}
|
|
27658
|
+
return void 0;
|
|
27659
|
+
}
|
|
27660
|
+
function sanitizeLoggedValue(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
|
|
27661
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
27662
|
+
return value;
|
|
27663
|
+
}
|
|
27664
|
+
if (typeof value === "number") {
|
|
27665
|
+
return Number.isFinite(value) ? value : void 0;
|
|
27666
|
+
}
|
|
27667
|
+
if (value instanceof Date) {
|
|
27668
|
+
return Number.isFinite(value.getTime()) ? value.toISOString() : void 0;
|
|
27669
|
+
}
|
|
27670
|
+
if (typeof value !== "object" || depth >= 20) {
|
|
27671
|
+
return void 0;
|
|
27672
|
+
}
|
|
27673
|
+
if (seen.has(value)) {
|
|
27674
|
+
return "[Circular]";
|
|
27675
|
+
}
|
|
27676
|
+
seen.add(value);
|
|
27677
|
+
if (Array.isArray(value)) {
|
|
27678
|
+
return value.map((item) => sanitizeLoggedValue(item, seen, depth + 1));
|
|
27679
|
+
}
|
|
27680
|
+
const entries = [];
|
|
27681
|
+
for (const [key, descriptor] of Object.entries(
|
|
27682
|
+
Object.getOwnPropertyDescriptors(value)
|
|
27683
|
+
)) {
|
|
27684
|
+
if (!descriptor.enumerable || !("value" in descriptor) || BLOCKED_METADATA_KEYS.has(key)) {
|
|
27685
|
+
continue;
|
|
27686
|
+
}
|
|
27687
|
+
entries.push([key, sanitizeLoggedValue(descriptor.value, seen, depth + 1)]);
|
|
27688
|
+
}
|
|
27689
|
+
return Object.fromEntries(entries);
|
|
27690
|
+
}
|
|
27691
|
+
|
|
27103
27692
|
// src/instrumentation/plugins/pi-coding-agent-channels.ts
|
|
27104
27693
|
var piCodingAgentChannels = defineChannels(
|
|
27105
27694
|
"@earendil-works/pi-coding-agent",
|
|
@@ -27479,11 +28068,11 @@ function patchAssistantMessageStream(stream, promptState, llmState) {
|
|
|
27479
28068
|
function recordPiAssistantMessageEvent(promptState, llmState, event) {
|
|
27480
28069
|
recordFirstTokenMetric(llmState, event);
|
|
27481
28070
|
const message = "message" in event ? event.message : void 0;
|
|
27482
|
-
const
|
|
28071
|
+
const errorMessage2 = "error" in event ? event.error : void 0;
|
|
27483
28072
|
if (event.type === "done" && isPiAssistantMessage(message)) {
|
|
27484
28073
|
finishPiLlmSpan(promptState, llmState, message);
|
|
27485
|
-
} else if (event.type === "error" && isPiAssistantMessage(
|
|
27486
|
-
finishPiLlmSpan(promptState, llmState,
|
|
28074
|
+
} else if (event.type === "error" && isPiAssistantMessage(errorMessage2)) {
|
|
28075
|
+
finishPiLlmSpan(promptState, llmState, errorMessage2);
|
|
27487
28076
|
}
|
|
27488
28077
|
}
|
|
27489
28078
|
function recordFirstTokenMetric(state, event) {
|
|
@@ -28001,6 +28590,7 @@ var strandsAgentSDKChannels = defineChannels("@strands-agents/sdk", {
|
|
|
28001
28590
|
});
|
|
28002
28591
|
|
|
28003
28592
|
// src/instrumentation/plugins/strands-agent-sdk-plugin.ts
|
|
28593
|
+
var MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES = 32;
|
|
28004
28594
|
var StrandsAgentSDKPlugin = class extends BasePlugin {
|
|
28005
28595
|
activeChildParents = /* @__PURE__ */ new WeakMap();
|
|
28006
28596
|
onEnable() {
|
|
@@ -28145,11 +28735,16 @@ function startAgentStream(event, activeChildParents) {
|
|
|
28145
28735
|
...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
|
|
28146
28736
|
};
|
|
28147
28737
|
const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
|
|
28738
|
+
const attachmentCache = createStrandsAttachmentCache();
|
|
28739
|
+
const input = processStrandsInputAttachments(
|
|
28740
|
+
event.arguments[0],
|
|
28741
|
+
attachmentCache
|
|
28742
|
+
);
|
|
28148
28743
|
const span = parentSpan ? withCurrent(
|
|
28149
28744
|
parentSpan,
|
|
28150
28745
|
() => startSpan({
|
|
28151
28746
|
event: {
|
|
28152
|
-
input
|
|
28747
|
+
input,
|
|
28153
28748
|
metadata
|
|
28154
28749
|
},
|
|
28155
28750
|
name: formatAgentSpanName(agent),
|
|
@@ -28157,7 +28752,7 @@ function startAgentStream(event, activeChildParents) {
|
|
|
28157
28752
|
})
|
|
28158
28753
|
) : startSpan({
|
|
28159
28754
|
event: {
|
|
28160
|
-
input
|
|
28755
|
+
input,
|
|
28161
28756
|
metadata
|
|
28162
28757
|
},
|
|
28163
28758
|
name: formatAgentSpanName(agent),
|
|
@@ -28165,6 +28760,7 @@ function startAgentStream(event, activeChildParents) {
|
|
|
28165
28760
|
});
|
|
28166
28761
|
return {
|
|
28167
28762
|
activeTools: /* @__PURE__ */ new Map(),
|
|
28763
|
+
attachmentCache,
|
|
28168
28764
|
finalized: false,
|
|
28169
28765
|
metadata,
|
|
28170
28766
|
span,
|
|
@@ -28180,11 +28776,12 @@ function startMultiAgentStream(event, operation, activeChildParents) {
|
|
|
28180
28776
|
...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
|
|
28181
28777
|
};
|
|
28182
28778
|
const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
|
|
28779
|
+
const input = processStrandsInputAttachments(event.arguments[0]);
|
|
28183
28780
|
const span = parentSpan ? withCurrent(
|
|
28184
28781
|
parentSpan,
|
|
28185
28782
|
() => startSpan({
|
|
28186
28783
|
event: {
|
|
28187
|
-
input
|
|
28784
|
+
input,
|
|
28188
28785
|
metadata
|
|
28189
28786
|
},
|
|
28190
28787
|
name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
|
|
@@ -28192,7 +28789,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
|
|
|
28192
28789
|
})
|
|
28193
28790
|
) : startSpan({
|
|
28194
28791
|
event: {
|
|
28195
|
-
input
|
|
28792
|
+
input,
|
|
28196
28793
|
metadata
|
|
28197
28794
|
},
|
|
28198
28795
|
name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
|
|
@@ -28301,7 +28898,10 @@ function startModelSpan(state, event) {
|
|
|
28301
28898
|
state.span,
|
|
28302
28899
|
() => startSpan({
|
|
28303
28900
|
event: {
|
|
28304
|
-
input: Array.isArray(event.agent?.messages) ?
|
|
28901
|
+
input: Array.isArray(event.agent?.messages) ? processStrandsInputAttachments(
|
|
28902
|
+
event.agent.messages,
|
|
28903
|
+
state.attachmentCache
|
|
28904
|
+
) : void 0,
|
|
28305
28905
|
metadata
|
|
28306
28906
|
},
|
|
28307
28907
|
name: formatModelSpanName(model),
|
|
@@ -28515,6 +29115,7 @@ function finalizeAgentStream(state, error, output) {
|
|
|
28515
29115
|
...output !== void 0 ? { output } : {}
|
|
28516
29116
|
});
|
|
28517
29117
|
state.span.end();
|
|
29118
|
+
state.attachmentCache.strings.clear();
|
|
28518
29119
|
}
|
|
28519
29120
|
function finalizeMultiAgentStream(state, activeChildParents, error, output) {
|
|
28520
29121
|
if (state.finalized) {
|
|
@@ -28661,8 +29262,168 @@ function extractNodeResultOutput(result) {
|
|
|
28661
29262
|
}
|
|
28662
29263
|
return result;
|
|
28663
29264
|
}
|
|
28664
|
-
|
|
28665
|
-
|
|
29265
|
+
var STRANDS_MEDIA_TYPES = {
|
|
29266
|
+
png: "image/png",
|
|
29267
|
+
jpg: "image/jpeg",
|
|
29268
|
+
jpeg: "image/jpeg",
|
|
29269
|
+
gif: "image/gif",
|
|
29270
|
+
webp: "image/webp",
|
|
29271
|
+
mkv: "video/x-matroska",
|
|
29272
|
+
mov: "video/quicktime",
|
|
29273
|
+
mp4: "video/mp4",
|
|
29274
|
+
webm: "video/webm",
|
|
29275
|
+
flv: "video/x-flv",
|
|
29276
|
+
mpeg: "video/mpeg",
|
|
29277
|
+
mpg: "video/mpeg",
|
|
29278
|
+
wmv: "video/x-ms-wmv",
|
|
29279
|
+
"3gp": "video/3gpp",
|
|
29280
|
+
pdf: "application/pdf",
|
|
29281
|
+
csv: "text/csv",
|
|
29282
|
+
doc: "application/msword",
|
|
29283
|
+
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
29284
|
+
xls: "application/vnd.ms-excel",
|
|
29285
|
+
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
29286
|
+
html: "text/html",
|
|
29287
|
+
txt: "text/plain",
|
|
29288
|
+
md: "text/markdown",
|
|
29289
|
+
json: "application/json",
|
|
29290
|
+
xml: "application/xml"
|
|
29291
|
+
};
|
|
29292
|
+
function createStrandsAttachmentCache() {
|
|
29293
|
+
return {
|
|
29294
|
+
objects: /* @__PURE__ */ new WeakMap(),
|
|
29295
|
+
strings: new LRUCache({
|
|
29296
|
+
max: MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES
|
|
29297
|
+
})
|
|
29298
|
+
};
|
|
29299
|
+
}
|
|
29300
|
+
function processStrandsInputAttachments(input, cache = createStrandsAttachmentCache()) {
|
|
29301
|
+
try {
|
|
29302
|
+
return processStrandsInputNode(input, cache);
|
|
29303
|
+
} catch (error) {
|
|
29304
|
+
logInstrumentationError5("Strands Agent SDK input attachments", error);
|
|
29305
|
+
return input;
|
|
29306
|
+
}
|
|
29307
|
+
}
|
|
29308
|
+
function processStrandsInputNode(value, cache) {
|
|
29309
|
+
if (value instanceof BaseAttachment) {
|
|
29310
|
+
return value;
|
|
29311
|
+
}
|
|
29312
|
+
if (Array.isArray(value)) {
|
|
29313
|
+
return value.map((child) => processStrandsInputNode(child, cache));
|
|
29314
|
+
}
|
|
29315
|
+
if (!isObject(value)) {
|
|
29316
|
+
return value;
|
|
29317
|
+
}
|
|
29318
|
+
const directMedia = processDirectStrandsMediaBlock(value, cache);
|
|
29319
|
+
if (directMedia !== void 0) {
|
|
29320
|
+
return directMedia;
|
|
29321
|
+
}
|
|
29322
|
+
const wrappedMedia = processWrappedStrandsMediaBlock(value, cache);
|
|
29323
|
+
if (wrappedMedia !== void 0) {
|
|
29324
|
+
return wrappedMedia;
|
|
29325
|
+
}
|
|
29326
|
+
if (value.type === "message" && Array.isArray(value.content)) {
|
|
29327
|
+
return {
|
|
29328
|
+
role: value.role,
|
|
29329
|
+
content: value.content.map(
|
|
29330
|
+
(child) => processStrandsInputNode(child, cache)
|
|
29331
|
+
),
|
|
29332
|
+
...value.metadata !== void 0 ? { metadata: value.metadata } : {}
|
|
29333
|
+
};
|
|
29334
|
+
}
|
|
29335
|
+
if (typeof value.toJSON === "function") {
|
|
29336
|
+
return processStrandsInputNode(value.toJSON(), cache);
|
|
29337
|
+
}
|
|
29338
|
+
return Object.fromEntries(
|
|
29339
|
+
Object.entries(value).map(([key, child]) => [
|
|
29340
|
+
key,
|
|
29341
|
+
processStrandsInputNode(child, cache)
|
|
29342
|
+
])
|
|
29343
|
+
);
|
|
29344
|
+
}
|
|
29345
|
+
function processDirectStrandsMediaBlock(block, cache) {
|
|
29346
|
+
if (!isStrandsMediaBlock(block)) {
|
|
29347
|
+
return void 0;
|
|
29348
|
+
}
|
|
29349
|
+
const mediaKey = block.type === "imageBlock" ? "image" : block.type === "videoBlock" ? "video" : "document";
|
|
29350
|
+
return createStrandsMediaAttachment(mediaKey, block, cache);
|
|
29351
|
+
}
|
|
29352
|
+
function isStrandsMediaBlock(block) {
|
|
29353
|
+
return (block.type === "imageBlock" || block.type === "videoBlock" || block.type === "documentBlock") && typeof block.format === "string" && isObject(block.source);
|
|
29354
|
+
}
|
|
29355
|
+
function processWrappedStrandsMediaBlock(block, cache) {
|
|
29356
|
+
for (const mediaKey of ["image", "video", "document"]) {
|
|
29357
|
+
const media = block[mediaKey];
|
|
29358
|
+
if (!Object.hasOwn(block, mediaKey) || !isObject(media)) {
|
|
29359
|
+
continue;
|
|
29360
|
+
}
|
|
29361
|
+
const processed = createStrandsMediaAttachment(mediaKey, media, cache);
|
|
29362
|
+
if (processed !== void 0) {
|
|
29363
|
+
return processed;
|
|
29364
|
+
}
|
|
29365
|
+
}
|
|
29366
|
+
return void 0;
|
|
29367
|
+
}
|
|
29368
|
+
function createStrandsMediaAttachment(mediaKey, media, cache) {
|
|
29369
|
+
const format = media.format;
|
|
29370
|
+
const source = media.source;
|
|
29371
|
+
if (typeof format !== "string" || !isObject(source) || !Object.hasOwn(source, "bytes")) {
|
|
29372
|
+
return void 0;
|
|
29373
|
+
}
|
|
29374
|
+
const contentType = STRANDS_MEDIA_TYPES[format.toLowerCase()];
|
|
29375
|
+
if (!contentType) {
|
|
29376
|
+
return void 0;
|
|
29377
|
+
}
|
|
29378
|
+
const filename = mediaKey === "document" && typeof media.name === "string" && media.name.length > 0 ? media.name : `${mediaKey}.${format.toLowerCase()}`;
|
|
29379
|
+
const attachment = getOrCreateStrandsAttachment(
|
|
29380
|
+
source.bytes,
|
|
29381
|
+
filename,
|
|
29382
|
+
contentType,
|
|
29383
|
+
cache
|
|
29384
|
+
);
|
|
29385
|
+
if (!attachment) {
|
|
29386
|
+
return void 0;
|
|
29387
|
+
}
|
|
29388
|
+
const { type: _type, ...serializedMedia } = media;
|
|
29389
|
+
const { type: _sourceType, ...serializedSource } = source;
|
|
29390
|
+
return {
|
|
29391
|
+
[mediaKey]: {
|
|
29392
|
+
...serializedMedia,
|
|
29393
|
+
source: {
|
|
29394
|
+
...serializedSource,
|
|
29395
|
+
bytes: attachment
|
|
29396
|
+
}
|
|
29397
|
+
}
|
|
29398
|
+
};
|
|
29399
|
+
}
|
|
29400
|
+
function getOrCreateStrandsAttachment(data, filename, contentType, cache) {
|
|
29401
|
+
const key = `${contentType}\0${filename}`;
|
|
29402
|
+
const attachments = typeof data === "string" ? cache.strings.get(data) : isObject(data) ? cache.objects.get(data) : void 0;
|
|
29403
|
+
const cached = attachments?.get(key);
|
|
29404
|
+
if (cached) {
|
|
29405
|
+
return cached;
|
|
29406
|
+
}
|
|
29407
|
+
const blob = convertDataToBlob(data, contentType);
|
|
29408
|
+
if (!blob) {
|
|
29409
|
+
return void 0;
|
|
29410
|
+
}
|
|
29411
|
+
const attachment = new Attachment({
|
|
29412
|
+
data: blob,
|
|
29413
|
+
filename,
|
|
29414
|
+
contentType
|
|
29415
|
+
});
|
|
29416
|
+
const updatedAttachments = attachments ?? /* @__PURE__ */ new Map();
|
|
29417
|
+
updatedAttachments.set(key, attachment);
|
|
29418
|
+
if (typeof data === "string") {
|
|
29419
|
+
cache.strings.set(data, updatedAttachments);
|
|
29420
|
+
} else if (isObject(data)) {
|
|
29421
|
+
cache.objects.set(data, updatedAttachments);
|
|
29422
|
+
}
|
|
29423
|
+
return attachment;
|
|
29424
|
+
}
|
|
29425
|
+
function normalizeContentBlocks(blocks) {
|
|
29426
|
+
const text = blocks.map((block) => typeof block.text === "string" ? block.text : void 0).filter((part) => Boolean(part)).join("");
|
|
28666
29427
|
return text.length > 0 ? text : blocks;
|
|
28667
29428
|
}
|
|
28668
29429
|
function parseUsage(usage) {
|
|
@@ -28790,6 +29551,7 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
28790
29551
|
gitHubCopilotPlugin = null;
|
|
28791
29552
|
fluePlugin = null;
|
|
28792
29553
|
langChainPlugin = null;
|
|
29554
|
+
langSmithPlugin = null;
|
|
28793
29555
|
piCodingAgentPlugin = null;
|
|
28794
29556
|
strandsAgentSDKPlugin = null;
|
|
28795
29557
|
constructor(config = {}) {
|
|
@@ -28886,6 +29648,12 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
28886
29648
|
this.langChainPlugin = new LangChainPlugin();
|
|
28887
29649
|
this.langChainPlugin.enable();
|
|
28888
29650
|
}
|
|
29651
|
+
if (integrations.langsmith !== false) {
|
|
29652
|
+
this.langSmithPlugin = new LangSmithPlugin({
|
|
29653
|
+
skipLangChainRuns: integrations.langchain !== false
|
|
29654
|
+
});
|
|
29655
|
+
this.langSmithPlugin.enable();
|
|
29656
|
+
}
|
|
28889
29657
|
}
|
|
28890
29658
|
onDisable() {
|
|
28891
29659
|
if (this.openaiPlugin) {
|
|
@@ -28976,8 +29744,1396 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
28976
29744
|
this.langChainPlugin.disable();
|
|
28977
29745
|
this.langChainPlugin = null;
|
|
28978
29746
|
}
|
|
29747
|
+
if (this.langSmithPlugin) {
|
|
29748
|
+
this.langSmithPlugin.disable();
|
|
29749
|
+
this.langSmithPlugin = null;
|
|
29750
|
+
}
|
|
29751
|
+
}
|
|
29752
|
+
};
|
|
29753
|
+
|
|
29754
|
+
// src/instrumentation/plugins/eve-plugin.ts
|
|
29755
|
+
var EVE_TRACE_STATE_KEY = "braintrust.eve.tracing";
|
|
29756
|
+
var MAX_EVE_CACHE_ENTRIES = 1e4;
|
|
29757
|
+
var MAX_STORED_LLM_INPUTS = 100;
|
|
29758
|
+
var MAX_STORED_SPAN_REFERENCES = 1e4;
|
|
29759
|
+
var MAX_STORED_STEP_STARTS = 1e4;
|
|
29760
|
+
function braintrustEveHook(options) {
|
|
29761
|
+
const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
|
|
29762
|
+
const bridge = new EveBridge(state);
|
|
29763
|
+
return {
|
|
29764
|
+
events: {
|
|
29765
|
+
"*": async (event, ctx) => {
|
|
29766
|
+
await bridge.handle(event, ctx, options.metadata);
|
|
29767
|
+
}
|
|
29768
|
+
}
|
|
29769
|
+
};
|
|
29770
|
+
}
|
|
29771
|
+
function braintrustEveInstrumentation(options) {
|
|
29772
|
+
const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
|
|
29773
|
+
return {
|
|
29774
|
+
events: {
|
|
29775
|
+
"step.started": (input) => {
|
|
29776
|
+
try {
|
|
29777
|
+
captureEveModelInput(state, input);
|
|
29778
|
+
} catch (error) {
|
|
29779
|
+
debugLogger.warn("Error in Eve LLM input capture:", error);
|
|
29780
|
+
}
|
|
29781
|
+
}
|
|
29782
|
+
},
|
|
29783
|
+
recordInputs: false,
|
|
29784
|
+
recordOutputs: false,
|
|
29785
|
+
setup: options.setup
|
|
29786
|
+
};
|
|
29787
|
+
}
|
|
29788
|
+
function isEveHandleMessageStreamEvent(event) {
|
|
29789
|
+
return isObject(event) && typeof event["type"] === "string";
|
|
29790
|
+
}
|
|
29791
|
+
var ResumedEveSpan = class {
|
|
29792
|
+
constructor(reference) {
|
|
29793
|
+
this.reference = reference;
|
|
29794
|
+
this.endTime = reference.endTime;
|
|
29795
|
+
}
|
|
29796
|
+
endTime;
|
|
29797
|
+
get rootSpanId() {
|
|
29798
|
+
return this.reference.rootSpanId;
|
|
29799
|
+
}
|
|
29800
|
+
get spanId() {
|
|
29801
|
+
return this.reference.spanId;
|
|
29802
|
+
}
|
|
29803
|
+
log(event) {
|
|
29804
|
+
const metrics = {
|
|
29805
|
+
...this.reference.startEvent?.metrics,
|
|
29806
|
+
...this.endTime === void 0 ? {} : { end: this.endTime },
|
|
29807
|
+
...event.metrics
|
|
29808
|
+
};
|
|
29809
|
+
updateSpan({
|
|
29810
|
+
exported: this.reference.exported,
|
|
29811
|
+
...this.reference.startEvent,
|
|
29812
|
+
...event,
|
|
29813
|
+
...Object.keys(metrics).length > 0 ? { metrics } : {}
|
|
29814
|
+
});
|
|
29815
|
+
}
|
|
29816
|
+
end(args) {
|
|
29817
|
+
if (this.endTime === void 0) {
|
|
29818
|
+
this.endTime = args?.endTime ?? getCurrentUnixTimestamp();
|
|
29819
|
+
this.log({ metrics: { end: this.endTime } });
|
|
29820
|
+
}
|
|
29821
|
+
return this.endTime;
|
|
28979
29822
|
}
|
|
28980
29823
|
};
|
|
29824
|
+
var EveBridge = class {
|
|
29825
|
+
constructor(state) {
|
|
29826
|
+
this.state = state;
|
|
29827
|
+
}
|
|
29828
|
+
eventQueuesBySession = /* @__PURE__ */ new Map();
|
|
29829
|
+
completedToolKeys = new LRUCache({
|
|
29830
|
+
max: MAX_EVE_CACHE_ENTRIES
|
|
29831
|
+
});
|
|
29832
|
+
toolsByCallKey = new LRUCache({
|
|
29833
|
+
max: MAX_EVE_CACHE_ENTRIES
|
|
29834
|
+
});
|
|
29835
|
+
turnsByKey = new LRUCache({
|
|
29836
|
+
max: MAX_EVE_CACHE_ENTRIES
|
|
29837
|
+
});
|
|
29838
|
+
async startEveSpan(args) {
|
|
29839
|
+
const rowId = args?.event?.id;
|
|
29840
|
+
const reference = typeof rowId === "string" && readEveTraceState(this.state).spanReferences.find(
|
|
29841
|
+
(candidate) => candidate.rowId === rowId
|
|
29842
|
+
);
|
|
29843
|
+
if (reference) {
|
|
29844
|
+
return new ResumedEveSpan(reference);
|
|
29845
|
+
}
|
|
29846
|
+
const startTime = args?.startTime ?? getCurrentUnixTimestamp();
|
|
29847
|
+
const parentSpanIds = args?.parentSpanIds;
|
|
29848
|
+
const startEvent = {
|
|
29849
|
+
created: (/* @__PURE__ */ new Date()).toISOString(),
|
|
29850
|
+
metrics: { start: startTime },
|
|
29851
|
+
span_attributes: {
|
|
29852
|
+
...args?.name ? { name: args.name } : {},
|
|
29853
|
+
...args?.type ? { type: args.type } : {},
|
|
29854
|
+
...args?.spanAttributes
|
|
29855
|
+
},
|
|
29856
|
+
span_parents: parentSpanIds ? "spanId" in parentSpanIds ? [parentSpanIds.spanId] : parentSpanIds.parentSpanIds : []
|
|
29857
|
+
};
|
|
29858
|
+
const span = withCurrent(
|
|
29859
|
+
NOOP_SPAN,
|
|
29860
|
+
() => _internalStartSpanWithInitialMerge({ ...args, startTime })
|
|
29861
|
+
);
|
|
29862
|
+
if (typeof rowId !== "string") {
|
|
29863
|
+
return span;
|
|
29864
|
+
}
|
|
29865
|
+
try {
|
|
29866
|
+
const exported = await span.export();
|
|
29867
|
+
const reference2 = {
|
|
29868
|
+
exported,
|
|
29869
|
+
rootSpanId: span.rootSpanId,
|
|
29870
|
+
rowId,
|
|
29871
|
+
spanId: span.spanId,
|
|
29872
|
+
startEvent
|
|
29873
|
+
};
|
|
29874
|
+
this.state.update((current) => {
|
|
29875
|
+
const normalized = normalizeEveTraceState(current);
|
|
29876
|
+
return normalized.spanReferences.some(
|
|
29877
|
+
(candidate) => candidate.rowId === rowId
|
|
29878
|
+
) ? normalized : {
|
|
29879
|
+
...normalized,
|
|
29880
|
+
spanReferences: [...normalized.spanReferences, reference2].slice(
|
|
29881
|
+
-MAX_STORED_SPAN_REFERENCES
|
|
29882
|
+
)
|
|
29883
|
+
};
|
|
29884
|
+
});
|
|
29885
|
+
} catch (error) {
|
|
29886
|
+
debugLogger.warn("Error exporting Eve span for resumption:", error);
|
|
29887
|
+
}
|
|
29888
|
+
return span;
|
|
29889
|
+
}
|
|
29890
|
+
async startEveChildSpan(parent, args) {
|
|
29891
|
+
return await this.startEveSpan({
|
|
29892
|
+
...args,
|
|
29893
|
+
parentSpanIds: {
|
|
29894
|
+
rootSpanId: parent.rootSpanId,
|
|
29895
|
+
spanId: parent.spanId
|
|
29896
|
+
}
|
|
29897
|
+
});
|
|
29898
|
+
}
|
|
29899
|
+
stepOrdinal(event) {
|
|
29900
|
+
let ordinal = 0;
|
|
29901
|
+
this.state.update((current) => {
|
|
29902
|
+
const state = normalizeEveTraceState(current);
|
|
29903
|
+
const previous = state.stepStarts.filter(
|
|
29904
|
+
(entry) => entry.turnId === event.data.turnId && entry.stepIndex === event.data.stepIndex
|
|
29905
|
+
).at(-1);
|
|
29906
|
+
if (previous?.open) {
|
|
29907
|
+
ordinal = previous.ordinal;
|
|
29908
|
+
return state;
|
|
29909
|
+
}
|
|
29910
|
+
ordinal = state.stepStarts.filter(
|
|
29911
|
+
(entry) => entry.turnId === event.data.turnId
|
|
29912
|
+
).length;
|
|
29913
|
+
return {
|
|
29914
|
+
...state,
|
|
29915
|
+
stepStarts: [
|
|
29916
|
+
...state.stepStarts,
|
|
29917
|
+
{
|
|
29918
|
+
open: true,
|
|
29919
|
+
ordinal,
|
|
29920
|
+
stepIndex: event.data.stepIndex,
|
|
29921
|
+
turnId: event.data.turnId
|
|
29922
|
+
}
|
|
29923
|
+
].slice(-MAX_STORED_STEP_STARTS)
|
|
29924
|
+
};
|
|
29925
|
+
});
|
|
29926
|
+
return ordinal;
|
|
29927
|
+
}
|
|
29928
|
+
markStepEnded(turnId, stepIndex) {
|
|
29929
|
+
this.state.update((current) => {
|
|
29930
|
+
const state = normalizeEveTraceState(current);
|
|
29931
|
+
let index = -1;
|
|
29932
|
+
for (let i = state.stepStarts.length - 1; i >= 0; i--) {
|
|
29933
|
+
const entry = state.stepStarts[i];
|
|
29934
|
+
if (entry?.turnId === turnId && entry.stepIndex === stepIndex) {
|
|
29935
|
+
index = i;
|
|
29936
|
+
break;
|
|
29937
|
+
}
|
|
29938
|
+
}
|
|
29939
|
+
if (index < 0 || !state.stepStarts[index]?.open) {
|
|
29940
|
+
return state;
|
|
29941
|
+
}
|
|
29942
|
+
return {
|
|
29943
|
+
...state,
|
|
29944
|
+
stepStarts: state.stepStarts.map(
|
|
29945
|
+
(entry, entryIndex) => entryIndex === index ? { ...entry, open: false } : entry
|
|
29946
|
+
)
|
|
29947
|
+
};
|
|
29948
|
+
});
|
|
29949
|
+
}
|
|
29950
|
+
async handle(event, ctx, hookMetadata) {
|
|
29951
|
+
if (!isEveHandleMessageStreamEvent(event)) {
|
|
29952
|
+
return;
|
|
29953
|
+
}
|
|
29954
|
+
const run = async () => {
|
|
29955
|
+
try {
|
|
29956
|
+
if (!await this.handleEvent(event, ctx, hookMetadata)) {
|
|
29957
|
+
return;
|
|
29958
|
+
}
|
|
29959
|
+
if (event.type === "session.failed") {
|
|
29960
|
+
const sessionId2 = event.data.sessionId || sessionIdFromContext(ctx);
|
|
29961
|
+
await this.flushInstrumentation();
|
|
29962
|
+
if (sessionId2) {
|
|
29963
|
+
this.cleanupSession(sessionId2);
|
|
29964
|
+
}
|
|
29965
|
+
} else if (event.type === "session.completed") {
|
|
29966
|
+
const sessionId2 = sessionIdFromContext(ctx);
|
|
29967
|
+
await this.flushInstrumentation();
|
|
29968
|
+
if (sessionId2) {
|
|
29969
|
+
this.cleanupSession(sessionId2);
|
|
29970
|
+
}
|
|
29971
|
+
}
|
|
29972
|
+
} catch (error) {
|
|
29973
|
+
debugLogger.warn("Error in Eve hook instrumentation:", error);
|
|
29974
|
+
}
|
|
29975
|
+
};
|
|
29976
|
+
const sessionId = event.type === "session.failed" ? event.data.sessionId || sessionIdFromContext(ctx) : sessionIdFromContext(ctx);
|
|
29977
|
+
if (!sessionId) {
|
|
29978
|
+
await run();
|
|
29979
|
+
return;
|
|
29980
|
+
}
|
|
29981
|
+
const previous = this.eventQueuesBySession.get(sessionId);
|
|
29982
|
+
const queued = previous ? previous.then(run) : run();
|
|
29983
|
+
this.eventQueuesBySession.set(sessionId, queued);
|
|
29984
|
+
try {
|
|
29985
|
+
await queued;
|
|
29986
|
+
} finally {
|
|
29987
|
+
if (this.eventQueuesBySession.get(sessionId) === queued) {
|
|
29988
|
+
this.eventQueuesBySession.delete(sessionId);
|
|
29989
|
+
}
|
|
29990
|
+
}
|
|
29991
|
+
}
|
|
29992
|
+
async handleEvent(event, ctx, hookMetadata) {
|
|
29993
|
+
switch (event.type) {
|
|
29994
|
+
case "session.started":
|
|
29995
|
+
this.handleSessionStarted(event, ctx, hookMetadata);
|
|
29996
|
+
return true;
|
|
29997
|
+
case "turn.started":
|
|
29998
|
+
await this.handleTurnStarted(event, ctx, hookMetadata);
|
|
29999
|
+
return true;
|
|
30000
|
+
case "message.received":
|
|
30001
|
+
await this.handleMessageReceived(event, ctx, hookMetadata);
|
|
30002
|
+
return true;
|
|
30003
|
+
case "step.started":
|
|
30004
|
+
await this.handleStepStarted(event, ctx, hookMetadata);
|
|
30005
|
+
return true;
|
|
30006
|
+
case "message.completed":
|
|
30007
|
+
this.handleMessageCompleted(event, ctx);
|
|
30008
|
+
return true;
|
|
30009
|
+
case "result.completed":
|
|
30010
|
+
this.handleResultCompleted(event, ctx);
|
|
30011
|
+
return true;
|
|
30012
|
+
case "actions.requested":
|
|
30013
|
+
await this.handleActionsRequested(event, ctx, hookMetadata);
|
|
30014
|
+
return true;
|
|
30015
|
+
case "action.result":
|
|
30016
|
+
await this.handleActionResult(event, ctx, hookMetadata);
|
|
30017
|
+
return true;
|
|
30018
|
+
case "subagent.called":
|
|
30019
|
+
await this.handleSubagentCalled(event, ctx, hookMetadata);
|
|
30020
|
+
return true;
|
|
30021
|
+
case "subagent.completed":
|
|
30022
|
+
await this.handleSubagentCompleted(event, ctx, hookMetadata);
|
|
30023
|
+
return true;
|
|
30024
|
+
case "step.completed":
|
|
30025
|
+
this.handleStepCompleted(event, ctx);
|
|
30026
|
+
return true;
|
|
30027
|
+
case "step.failed":
|
|
30028
|
+
this.handleStepFailed(event, ctx);
|
|
30029
|
+
return true;
|
|
30030
|
+
case "turn.completed":
|
|
30031
|
+
this.handleTurnCompleted(event, ctx);
|
|
30032
|
+
return true;
|
|
30033
|
+
case "turn.failed":
|
|
30034
|
+
this.handleTurnFailed(event, ctx);
|
|
30035
|
+
return true;
|
|
30036
|
+
case "session.failed":
|
|
30037
|
+
this.handleSessionFailed(event, ctx);
|
|
30038
|
+
return true;
|
|
30039
|
+
case "session.completed":
|
|
30040
|
+
this.handleSessionCompleted(event, ctx);
|
|
30041
|
+
return true;
|
|
30042
|
+
default:
|
|
30043
|
+
return false;
|
|
30044
|
+
}
|
|
30045
|
+
}
|
|
30046
|
+
handleSessionStarted(event, ctx, hookMetadata) {
|
|
30047
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30048
|
+
if (!sessionId) {
|
|
30049
|
+
return;
|
|
30050
|
+
}
|
|
30051
|
+
const metadata = {
|
|
30052
|
+
...hookMetadata ?? {},
|
|
30053
|
+
...modelMetadataFromRuntime(event.data.runtime)
|
|
30054
|
+
};
|
|
30055
|
+
this.state.update((current) => {
|
|
30056
|
+
const normalized = normalizeEveTraceState(current);
|
|
30057
|
+
return {
|
|
30058
|
+
...normalized,
|
|
30059
|
+
metadata: { ...normalized.metadata, ...metadata }
|
|
30060
|
+
};
|
|
30061
|
+
});
|
|
30062
|
+
for (const [key, turn] of this.turnsByKey) {
|
|
30063
|
+
if (!key.startsWith(`${sessionId}:`)) {
|
|
30064
|
+
continue;
|
|
30065
|
+
}
|
|
30066
|
+
turn.metadata = { ...turn.metadata, ...metadata };
|
|
30067
|
+
turn.span.log({ metadata: turn.metadata });
|
|
30068
|
+
for (const step of turn.stepsByIndex.values()) {
|
|
30069
|
+
step.metadata = { ...step.metadata, ...metadata };
|
|
30070
|
+
step.span.log({ metadata: step.metadata });
|
|
30071
|
+
}
|
|
30072
|
+
}
|
|
30073
|
+
}
|
|
30074
|
+
async handleTurnStarted(event, ctx, hookMetadata) {
|
|
30075
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30076
|
+
if (!sessionId) {
|
|
30077
|
+
return;
|
|
30078
|
+
}
|
|
30079
|
+
const key = turnKey2(sessionId, event.data.turnId);
|
|
30080
|
+
const metadata = {
|
|
30081
|
+
...readEveTraceState(this.state).metadata,
|
|
30082
|
+
...hookMetadata ?? {},
|
|
30083
|
+
"eve.session_id": sessionId
|
|
30084
|
+
};
|
|
30085
|
+
const existing = this.turnsByKey.get(key);
|
|
30086
|
+
if (existing) {
|
|
30087
|
+
existing.metadata = { ...existing.metadata, ...metadata };
|
|
30088
|
+
existing.span.log({ metadata: existing.metadata });
|
|
30089
|
+
return;
|
|
30090
|
+
}
|
|
30091
|
+
const span = await this.startTurnSpan(sessionId, event, ctx, metadata);
|
|
30092
|
+
span.log({ metadata });
|
|
30093
|
+
this.turnsByKey.set(key, {
|
|
30094
|
+
key,
|
|
30095
|
+
metadata,
|
|
30096
|
+
metrics: {},
|
|
30097
|
+
span,
|
|
30098
|
+
stepsByIndex: /* @__PURE__ */ new Map(),
|
|
30099
|
+
turnId: event.data.turnId
|
|
30100
|
+
});
|
|
30101
|
+
}
|
|
30102
|
+
async handleMessageReceived(event, ctx, hookMetadata) {
|
|
30103
|
+
const turn = await this.ensureTurn(event, ctx, hookMetadata);
|
|
30104
|
+
if (!turn) {
|
|
30105
|
+
return;
|
|
30106
|
+
}
|
|
30107
|
+
const input = [{ content: event.data.message, role: "user" }];
|
|
30108
|
+
turn.span.log({ input });
|
|
30109
|
+
}
|
|
30110
|
+
async handleStepStarted(event, ctx, hookMetadata) {
|
|
30111
|
+
const turn = await this.ensureTurn(event, ctx, hookMetadata);
|
|
30112
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30113
|
+
if (!turn || !sessionId) {
|
|
30114
|
+
return;
|
|
30115
|
+
}
|
|
30116
|
+
const existing = turn.stepsByIndex.get(event.data.stepIndex);
|
|
30117
|
+
if (existing) {
|
|
30118
|
+
existing.span.log({
|
|
30119
|
+
...existing.input !== void 0 ? { input: existing.input } : {},
|
|
30120
|
+
metadata: existing.metadata,
|
|
30121
|
+
metrics: existing.metrics,
|
|
30122
|
+
output: existing.output
|
|
30123
|
+
});
|
|
30124
|
+
const endTime = eventTime2(event);
|
|
30125
|
+
existing.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30126
|
+
this.markStepEnded(event.data.turnId, event.data.stepIndex);
|
|
30127
|
+
}
|
|
30128
|
+
const stepOrdinal = this.stepOrdinal(event);
|
|
30129
|
+
const metadata = { ...turn.metadata };
|
|
30130
|
+
const input = consumeCapturedEveModelInput(
|
|
30131
|
+
this.state,
|
|
30132
|
+
sessionId,
|
|
30133
|
+
event.data.turnId,
|
|
30134
|
+
event.data.stepIndex
|
|
30135
|
+
);
|
|
30136
|
+
const { rowId: eventId, spanId } = await generateEveIds(
|
|
30137
|
+
"step",
|
|
30138
|
+
sessionId,
|
|
30139
|
+
event.data.turnId,
|
|
30140
|
+
String(stepOrdinal)
|
|
30141
|
+
);
|
|
30142
|
+
const span = await this.startEveChildSpan(turn.span, {
|
|
30143
|
+
event: {
|
|
30144
|
+
id: eventId,
|
|
30145
|
+
...input !== void 0 ? { input } : {},
|
|
30146
|
+
metadata
|
|
30147
|
+
},
|
|
30148
|
+
name: "eve.step",
|
|
30149
|
+
spanAttributes: { type: "llm" /* LLM */ },
|
|
30150
|
+
spanId,
|
|
30151
|
+
startTime: eventTime2(event)
|
|
30152
|
+
});
|
|
30153
|
+
span.log({ ...input !== void 0 ? { input } : {}, metadata });
|
|
30154
|
+
turn.stepsByIndex.set(event.data.stepIndex, {
|
|
30155
|
+
...input !== void 0 ? { input } : {},
|
|
30156
|
+
metadata,
|
|
30157
|
+
metrics: {},
|
|
30158
|
+
span
|
|
30159
|
+
});
|
|
30160
|
+
}
|
|
30161
|
+
handleMessageCompleted(event, ctx) {
|
|
30162
|
+
const step = this.stepForEvent(event, ctx);
|
|
30163
|
+
if (!step) {
|
|
30164
|
+
return;
|
|
30165
|
+
}
|
|
30166
|
+
const existingMessage = Array.isArray(step.output) && isObject(step.output[0]) ? step.output[0].message : void 0;
|
|
30167
|
+
const existingToolCalls = isObject(existingMessage) ? existingMessage.tool_calls : void 0;
|
|
30168
|
+
step.output = [
|
|
30169
|
+
{
|
|
30170
|
+
finish_reason: normalizedFinishReason(event.data.finishReason),
|
|
30171
|
+
index: 0,
|
|
30172
|
+
message: {
|
|
30173
|
+
content: event.data.message,
|
|
30174
|
+
role: "assistant",
|
|
30175
|
+
...Array.isArray(existingToolCalls) ? { tool_calls: existingToolCalls } : {}
|
|
30176
|
+
}
|
|
30177
|
+
}
|
|
30178
|
+
];
|
|
30179
|
+
const turn = this.turnForEvent(event, ctx);
|
|
30180
|
+
if (turn && event.data.finishReason !== "tool-calls") {
|
|
30181
|
+
turn.output = event.data.message;
|
|
30182
|
+
}
|
|
30183
|
+
}
|
|
30184
|
+
handleResultCompleted(event, ctx) {
|
|
30185
|
+
const step = this.stepForEvent(event, ctx);
|
|
30186
|
+
if (step) {
|
|
30187
|
+
step.output = [
|
|
30188
|
+
{
|
|
30189
|
+
finish_reason: "stop",
|
|
30190
|
+
index: 0,
|
|
30191
|
+
message: {
|
|
30192
|
+
content: event.data.result,
|
|
30193
|
+
role: "assistant"
|
|
30194
|
+
}
|
|
30195
|
+
}
|
|
30196
|
+
];
|
|
30197
|
+
}
|
|
30198
|
+
const turn = this.turnForEvent(event, ctx);
|
|
30199
|
+
if (turn) {
|
|
30200
|
+
turn.output = event.data.result;
|
|
30201
|
+
}
|
|
30202
|
+
}
|
|
30203
|
+
async handleActionsRequested(event, ctx, hookMetadata) {
|
|
30204
|
+
const turn = await this.ensureTurn(event, ctx, hookMetadata);
|
|
30205
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30206
|
+
if (!turn || !sessionId) {
|
|
30207
|
+
return;
|
|
30208
|
+
}
|
|
30209
|
+
const traceActions = event.data.actions.filter(isTraceableActionRequest);
|
|
30210
|
+
if (traceActions.length === 0) {
|
|
30211
|
+
return;
|
|
30212
|
+
}
|
|
30213
|
+
for (const action of traceActions) {
|
|
30214
|
+
if (isToolCallAction(action)) {
|
|
30215
|
+
await this.startRequestedTool(event, turn, sessionId, action);
|
|
30216
|
+
} else if (isLocalSubagentCallAction(action)) {
|
|
30217
|
+
await this.startRequestedSubagent(event, turn, sessionId, action);
|
|
30218
|
+
}
|
|
30219
|
+
}
|
|
30220
|
+
const step = turn.stepsByIndex.get(event.data.stepIndex);
|
|
30221
|
+
if (!step) {
|
|
30222
|
+
return;
|
|
30223
|
+
}
|
|
30224
|
+
const toolCallsById = /* @__PURE__ */ new Map();
|
|
30225
|
+
if (Array.isArray(step.output) && isObject(step.output[0])) {
|
|
30226
|
+
const message = step.output[0]["message"];
|
|
30227
|
+
if (isObject(message) && Array.isArray(message["tool_calls"])) {
|
|
30228
|
+
for (const toolCall of message["tool_calls"]) {
|
|
30229
|
+
if (isObject(toolCall) && typeof toolCall["id"] === "string") {
|
|
30230
|
+
toolCallsById.set(toolCall["id"], toolCall);
|
|
30231
|
+
}
|
|
30232
|
+
}
|
|
30233
|
+
}
|
|
30234
|
+
}
|
|
30235
|
+
for (const action of traceActions) {
|
|
30236
|
+
const name = action.kind === "tool-call" ? action.toolName : action.subagentName ?? action.name ?? "agent";
|
|
30237
|
+
toolCallsById.set(action.callId, {
|
|
30238
|
+
function: {
|
|
30239
|
+
arguments: JSON.stringify(action.input),
|
|
30240
|
+
name
|
|
30241
|
+
},
|
|
30242
|
+
id: action.callId,
|
|
30243
|
+
type: "function"
|
|
30244
|
+
});
|
|
30245
|
+
}
|
|
30246
|
+
step.output = [
|
|
30247
|
+
{
|
|
30248
|
+
finish_reason: "tool_calls",
|
|
30249
|
+
index: 0,
|
|
30250
|
+
message: {
|
|
30251
|
+
content: null,
|
|
30252
|
+
role: "assistant",
|
|
30253
|
+
tool_calls: [...toolCallsById.values()]
|
|
30254
|
+
}
|
|
30255
|
+
}
|
|
30256
|
+
];
|
|
30257
|
+
step.span.log({ metadata: step.metadata, output: step.output });
|
|
30258
|
+
}
|
|
30259
|
+
async handleActionResult(event, ctx, hookMetadata) {
|
|
30260
|
+
if (isToolResult(event.data.result)) {
|
|
30261
|
+
await this.handleToolResult(event, ctx, event.data.result, hookMetadata);
|
|
30262
|
+
return;
|
|
30263
|
+
}
|
|
30264
|
+
if (isSubagentResult(event.data.result)) {
|
|
30265
|
+
await this.handleSubagentResult(
|
|
30266
|
+
event,
|
|
30267
|
+
ctx,
|
|
30268
|
+
event.data.result,
|
|
30269
|
+
hookMetadata
|
|
30270
|
+
);
|
|
30271
|
+
}
|
|
30272
|
+
}
|
|
30273
|
+
async handleToolResult(event, ctx, result, hookMetadata) {
|
|
30274
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30275
|
+
if (!sessionId) {
|
|
30276
|
+
return;
|
|
30277
|
+
}
|
|
30278
|
+
const key = toolKey3(sessionId, result.callId);
|
|
30279
|
+
if (this.completedToolKeys.has(key)) {
|
|
30280
|
+
return;
|
|
30281
|
+
}
|
|
30282
|
+
const tool = this.toolsByCallKey.get(key) ?? await this.startSyntheticTool(event, ctx, result, hookMetadata);
|
|
30283
|
+
if (!tool) {
|
|
30284
|
+
return;
|
|
30285
|
+
}
|
|
30286
|
+
const failed = event.data.status === "failed" || result.isError === true || event.data.error !== void 0;
|
|
30287
|
+
tool.span.log({
|
|
30288
|
+
...failed ? {
|
|
30289
|
+
error: actionResultError(event.data.error, result.output)
|
|
30290
|
+
} : {},
|
|
30291
|
+
metadata: tool.metadata,
|
|
30292
|
+
output: result.output
|
|
30293
|
+
});
|
|
30294
|
+
const endTime = eventTime2(event);
|
|
30295
|
+
tool.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30296
|
+
this.toolsByCallKey.delete(key);
|
|
30297
|
+
this.completedToolKeys.set(key, true);
|
|
30298
|
+
}
|
|
30299
|
+
async handleSubagentCalled(event, ctx, hookMetadata) {
|
|
30300
|
+
if (event.data.remote?.url) {
|
|
30301
|
+
return;
|
|
30302
|
+
}
|
|
30303
|
+
const turn = await this.ensureTurn(event, ctx, hookMetadata);
|
|
30304
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30305
|
+
if (!turn || !sessionId) {
|
|
30306
|
+
return;
|
|
30307
|
+
}
|
|
30308
|
+
const key = toolKey3(sessionId, event.data.callId);
|
|
30309
|
+
const metadata = toolMetadataFromTurn(turn);
|
|
30310
|
+
const existing = this.toolsByCallKey.get(key);
|
|
30311
|
+
if (existing) {
|
|
30312
|
+
existing.metadata = { ...existing.metadata, ...metadata };
|
|
30313
|
+
existing.span.log({ metadata: existing.metadata });
|
|
30314
|
+
return;
|
|
30315
|
+
}
|
|
30316
|
+
if (this.completedToolKeys.has(key)) {
|
|
30317
|
+
return;
|
|
30318
|
+
}
|
|
30319
|
+
const { rowId: eventId, spanId } = await generateEveIds(
|
|
30320
|
+
"subagent",
|
|
30321
|
+
sessionId,
|
|
30322
|
+
event.data.callId
|
|
30323
|
+
);
|
|
30324
|
+
const pending = this.toolsByCallKey.get(key);
|
|
30325
|
+
if (pending || this.completedToolKeys.has(key)) {
|
|
30326
|
+
if (pending) {
|
|
30327
|
+
pending.metadata = { ...pending.metadata, ...metadata };
|
|
30328
|
+
pending.span.log({ metadata: pending.metadata });
|
|
30329
|
+
}
|
|
30330
|
+
return;
|
|
30331
|
+
}
|
|
30332
|
+
const span = await this.startEveChildSpan(turn.span, {
|
|
30333
|
+
event: {
|
|
30334
|
+
id: eventId,
|
|
30335
|
+
metadata
|
|
30336
|
+
},
|
|
30337
|
+
name: event.data.toolName ?? event.data.name,
|
|
30338
|
+
spanAttributes: { type: "tool" /* TOOL */ },
|
|
30339
|
+
spanId,
|
|
30340
|
+
startTime: eventTime2(event)
|
|
30341
|
+
});
|
|
30342
|
+
span.log({ metadata });
|
|
30343
|
+
this.toolsByCallKey.set(key, {
|
|
30344
|
+
metadata,
|
|
30345
|
+
span,
|
|
30346
|
+
turnKey: turnKey2(sessionId, event.data.turnId)
|
|
30347
|
+
});
|
|
30348
|
+
}
|
|
30349
|
+
async handleSubagentCompleted(event, ctx, hookMetadata) {
|
|
30350
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30351
|
+
if (!sessionId) {
|
|
30352
|
+
return;
|
|
30353
|
+
}
|
|
30354
|
+
const key = toolKey3(sessionId, event.data.callId);
|
|
30355
|
+
if (this.completedToolKeys.has(key)) {
|
|
30356
|
+
return;
|
|
30357
|
+
}
|
|
30358
|
+
const subagent = this.toolsByCallKey.get(key) ?? await this.startSyntheticSubagent(event, ctx, hookMetadata);
|
|
30359
|
+
if (!subagent) {
|
|
30360
|
+
return;
|
|
30361
|
+
}
|
|
30362
|
+
subagent.span.log({
|
|
30363
|
+
...event.data.status === "failed" ? {
|
|
30364
|
+
error: actionResultError(event.data.error, event.data.output)
|
|
30365
|
+
} : {},
|
|
30366
|
+
metadata: subagent.metadata,
|
|
30367
|
+
...event.data.output !== void 0 ? { output: event.data.output } : {}
|
|
30368
|
+
});
|
|
30369
|
+
const endTime = eventTime2(event);
|
|
30370
|
+
const recordedEndTime = subagent.span.end(
|
|
30371
|
+
endTime === void 0 ? void 0 : { endTime }
|
|
30372
|
+
);
|
|
30373
|
+
this.state.update((current) => {
|
|
30374
|
+
const normalized = normalizeEveTraceState(current);
|
|
30375
|
+
return {
|
|
30376
|
+
...normalized,
|
|
30377
|
+
spanReferences: normalized.spanReferences.map(
|
|
30378
|
+
(reference) => reference.spanId === subagent.span.spanId ? { ...reference, endTime: recordedEndTime } : reference
|
|
30379
|
+
)
|
|
30380
|
+
};
|
|
30381
|
+
});
|
|
30382
|
+
}
|
|
30383
|
+
async handleSubagentResult(event, ctx, result, hookMetadata) {
|
|
30384
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30385
|
+
if (!sessionId) {
|
|
30386
|
+
return;
|
|
30387
|
+
}
|
|
30388
|
+
const key = toolKey3(sessionId, result.callId);
|
|
30389
|
+
if (this.completedToolKeys.has(key)) {
|
|
30390
|
+
return;
|
|
30391
|
+
}
|
|
30392
|
+
const subagent = this.toolsByCallKey.get(key) ?? await this.startSyntheticSubagentResult(
|
|
30393
|
+
event,
|
|
30394
|
+
ctx,
|
|
30395
|
+
result,
|
|
30396
|
+
hookMetadata
|
|
30397
|
+
);
|
|
30398
|
+
if (!subagent) {
|
|
30399
|
+
return;
|
|
30400
|
+
}
|
|
30401
|
+
const isError = event.data.status === "failed" || result.isError === true || event.data.error !== void 0;
|
|
30402
|
+
subagent.span.log({
|
|
30403
|
+
...isError ? {
|
|
30404
|
+
error: actionResultError(event.data.error, result.output)
|
|
30405
|
+
} : {},
|
|
30406
|
+
metadata: subagent.metadata,
|
|
30407
|
+
output: result.output
|
|
30408
|
+
});
|
|
30409
|
+
const endTime = eventTime2(event);
|
|
30410
|
+
subagent.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30411
|
+
this.toolsByCallKey.delete(key);
|
|
30412
|
+
this.completedToolKeys.set(key, true);
|
|
30413
|
+
}
|
|
30414
|
+
handleStepCompleted(event, ctx) {
|
|
30415
|
+
const step = this.stepForEvent(event, ctx);
|
|
30416
|
+
if (!step) {
|
|
30417
|
+
return;
|
|
30418
|
+
}
|
|
30419
|
+
const usage = event.data.usage;
|
|
30420
|
+
const inputTokens = typeof usage?.inputTokens === "number" && Number.isFinite(usage.inputTokens) && usage.inputTokens >= 0 ? usage.inputTokens : void 0;
|
|
30421
|
+
const outputTokens = typeof usage?.outputTokens === "number" && Number.isFinite(usage.outputTokens) && usage.outputTokens >= 0 ? usage.outputTokens : void 0;
|
|
30422
|
+
const cacheReadTokens = typeof usage?.cacheReadTokens === "number" && Number.isFinite(usage.cacheReadTokens) && usage.cacheReadTokens >= 0 ? usage.cacheReadTokens : void 0;
|
|
30423
|
+
const cacheWriteTokens = typeof usage?.cacheWriteTokens === "number" && Number.isFinite(usage.cacheWriteTokens) && usage.cacheWriteTokens >= 0 ? usage.cacheWriteTokens : void 0;
|
|
30424
|
+
const costUsd = typeof usage?.costUsd === "number" && Number.isFinite(usage.costUsd) && usage.costUsd >= 0 ? usage.costUsd : void 0;
|
|
30425
|
+
const total = inputTokens !== void 0 && outputTokens !== void 0 ? inputTokens + outputTokens : void 0;
|
|
30426
|
+
const metrics = {
|
|
30427
|
+
...inputTokens !== void 0 ? { prompt_tokens: inputTokens } : {},
|
|
30428
|
+
...outputTokens !== void 0 ? { completion_tokens: outputTokens } : {},
|
|
30429
|
+
...total !== void 0 ? { tokens: total } : {},
|
|
30430
|
+
...cacheReadTokens !== void 0 ? { prompt_cached_tokens: cacheReadTokens } : {},
|
|
30431
|
+
...cacheWriteTokens !== void 0 ? { prompt_cache_creation_tokens: cacheWriteTokens } : {},
|
|
30432
|
+
...costUsd !== void 0 ? { estimated_cost: costUsd } : {}
|
|
30433
|
+
};
|
|
30434
|
+
step.metrics = { ...step.metrics, ...metrics };
|
|
30435
|
+
if (Array.isArray(step.output) && isObject(step.output[0])) {
|
|
30436
|
+
const finishReason = step.output[0].finish_reason;
|
|
30437
|
+
if (typeof finishReason !== "string") {
|
|
30438
|
+
step.output[0].finish_reason = normalizedFinishReason(
|
|
30439
|
+
event.data.finishReason
|
|
30440
|
+
);
|
|
30441
|
+
}
|
|
30442
|
+
}
|
|
30443
|
+
step.span.log({
|
|
30444
|
+
...step.input !== void 0 ? { input: step.input } : {},
|
|
30445
|
+
metadata: step.metadata,
|
|
30446
|
+
metrics,
|
|
30447
|
+
output: step.output
|
|
30448
|
+
});
|
|
30449
|
+
const endTime = eventTime2(event);
|
|
30450
|
+
step.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30451
|
+
const turn = this.turnForEvent(event, ctx);
|
|
30452
|
+
if (turn) {
|
|
30453
|
+
for (const [key, value] of Object.entries(metrics)) {
|
|
30454
|
+
turn.metrics[key] = (turn.metrics[key] ?? 0) + value;
|
|
30455
|
+
}
|
|
30456
|
+
turn.stepsByIndex.delete(event.data.stepIndex);
|
|
30457
|
+
}
|
|
30458
|
+
this.markStepEnded(event.data.turnId, event.data.stepIndex);
|
|
30459
|
+
}
|
|
30460
|
+
handleStepFailed(event, ctx) {
|
|
30461
|
+
const step = this.stepForEvent(event, ctx);
|
|
30462
|
+
if (step) {
|
|
30463
|
+
step.span.log({
|
|
30464
|
+
error: errorFromMessage(
|
|
30465
|
+
event.data.message,
|
|
30466
|
+
event.data.code,
|
|
30467
|
+
event.data.details
|
|
30468
|
+
)
|
|
30469
|
+
});
|
|
30470
|
+
const endTime = eventTime2(event);
|
|
30471
|
+
step.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30472
|
+
}
|
|
30473
|
+
const turn = this.turnForEvent(event, ctx);
|
|
30474
|
+
turn?.stepsByIndex.delete(event.data.stepIndex);
|
|
30475
|
+
this.markStepEnded(event.data.turnId, event.data.stepIndex);
|
|
30476
|
+
}
|
|
30477
|
+
handleTurnCompleted(event, ctx) {
|
|
30478
|
+
const turn = this.turnForEvent(event, ctx);
|
|
30479
|
+
if (!turn) {
|
|
30480
|
+
return;
|
|
30481
|
+
}
|
|
30482
|
+
this.finalizeTurn(turn, {
|
|
30483
|
+
endTime: eventTime2(event)
|
|
30484
|
+
});
|
|
30485
|
+
}
|
|
30486
|
+
handleTurnFailed(event, ctx) {
|
|
30487
|
+
const turn = this.turnForEvent(event, ctx);
|
|
30488
|
+
if (!turn) {
|
|
30489
|
+
return;
|
|
30490
|
+
}
|
|
30491
|
+
this.finalizeTurn(turn, {
|
|
30492
|
+
endTime: eventTime2(event),
|
|
30493
|
+
error: errorFromMessage(
|
|
30494
|
+
event.data.message,
|
|
30495
|
+
event.data.code,
|
|
30496
|
+
event.data.details
|
|
30497
|
+
)
|
|
30498
|
+
});
|
|
30499
|
+
}
|
|
30500
|
+
handleSessionFailed(event, ctx) {
|
|
30501
|
+
const sessionId = event.data.sessionId || sessionIdFromContext(ctx);
|
|
30502
|
+
if (!sessionId) {
|
|
30503
|
+
return;
|
|
30504
|
+
}
|
|
30505
|
+
const error = errorFromMessage(
|
|
30506
|
+
event.data.message,
|
|
30507
|
+
event.data.code,
|
|
30508
|
+
event.data.details
|
|
30509
|
+
);
|
|
30510
|
+
for (const [key, turn] of this.turnsByKey) {
|
|
30511
|
+
if (!key.startsWith(`${sessionId}:`)) {
|
|
30512
|
+
continue;
|
|
30513
|
+
}
|
|
30514
|
+
this.finalizeTurn(turn, {
|
|
30515
|
+
endTime: eventTime2(event),
|
|
30516
|
+
error
|
|
30517
|
+
});
|
|
30518
|
+
}
|
|
30519
|
+
for (const [key, tool] of this.toolsByCallKey) {
|
|
30520
|
+
if (key.startsWith(`${sessionId}:`)) {
|
|
30521
|
+
const endTime = eventTime2(event);
|
|
30522
|
+
if (!tool.endedByTurn) {
|
|
30523
|
+
tool.span.log({ metadata: tool.metadata });
|
|
30524
|
+
tool.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30525
|
+
tool.endedByTurn = true;
|
|
30526
|
+
}
|
|
30527
|
+
}
|
|
30528
|
+
}
|
|
30529
|
+
}
|
|
30530
|
+
handleSessionCompleted(event, ctx) {
|
|
30531
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30532
|
+
if (!sessionId) {
|
|
30533
|
+
return;
|
|
30534
|
+
}
|
|
30535
|
+
for (const [key, turn] of this.turnsByKey) {
|
|
30536
|
+
if (!key.startsWith(`${sessionId}:`)) {
|
|
30537
|
+
continue;
|
|
30538
|
+
}
|
|
30539
|
+
this.finalizeTurn(turn, {
|
|
30540
|
+
endTime: eventTime2(event)
|
|
30541
|
+
});
|
|
30542
|
+
}
|
|
30543
|
+
for (const [key, tool] of this.toolsByCallKey) {
|
|
30544
|
+
if (key.startsWith(`${sessionId}:`) && !tool.endedByTurn) {
|
|
30545
|
+
const endTime = eventTime2(event);
|
|
30546
|
+
tool.span.log({ metadata: tool.metadata });
|
|
30547
|
+
tool.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30548
|
+
tool.endedByTurn = true;
|
|
30549
|
+
}
|
|
30550
|
+
}
|
|
30551
|
+
}
|
|
30552
|
+
async ensureTurn(event, ctx, hookMetadata) {
|
|
30553
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30554
|
+
if (!sessionId) {
|
|
30555
|
+
return void 0;
|
|
30556
|
+
}
|
|
30557
|
+
const key = turnKey2(sessionId, event.data.turnId);
|
|
30558
|
+
const existing = this.turnsByKey.get(key);
|
|
30559
|
+
if (existing) {
|
|
30560
|
+
return existing;
|
|
30561
|
+
}
|
|
30562
|
+
const metadata = {
|
|
30563
|
+
...readEveTraceState(this.state).metadata,
|
|
30564
|
+
...hookMetadata ?? {},
|
|
30565
|
+
"eve.session_id": sessionId
|
|
30566
|
+
};
|
|
30567
|
+
const span = await this.startTurnSpan(sessionId, event, ctx, metadata);
|
|
30568
|
+
span.log({ metadata });
|
|
30569
|
+
const state = {
|
|
30570
|
+
key,
|
|
30571
|
+
metadata,
|
|
30572
|
+
metrics: {},
|
|
30573
|
+
span,
|
|
30574
|
+
stepsByIndex: /* @__PURE__ */ new Map(),
|
|
30575
|
+
turnId: event.data.turnId
|
|
30576
|
+
};
|
|
30577
|
+
this.turnsByKey.set(key, state);
|
|
30578
|
+
return state;
|
|
30579
|
+
}
|
|
30580
|
+
async startRequestedTool(event, turn, sessionId, action) {
|
|
30581
|
+
const key = toolKey3(sessionId, action.callId);
|
|
30582
|
+
if (this.toolsByCallKey.has(key) || this.completedToolKeys.has(key)) {
|
|
30583
|
+
return;
|
|
30584
|
+
}
|
|
30585
|
+
const metadata = toolMetadataFromTurn(turn);
|
|
30586
|
+
const { rowId: eventId, spanId } = await generateEveIds(
|
|
30587
|
+
"tool",
|
|
30588
|
+
sessionId,
|
|
30589
|
+
event.data.turnId,
|
|
30590
|
+
action.callId
|
|
30591
|
+
);
|
|
30592
|
+
if (this.toolsByCallKey.has(key) || this.completedToolKeys.has(key)) {
|
|
30593
|
+
return;
|
|
30594
|
+
}
|
|
30595
|
+
const span = await this.startEveChildSpan(turn.span, {
|
|
30596
|
+
event: {
|
|
30597
|
+
id: eventId,
|
|
30598
|
+
input: action.input,
|
|
30599
|
+
metadata
|
|
30600
|
+
},
|
|
30601
|
+
name: action.toolName,
|
|
30602
|
+
spanAttributes: { type: "tool" /* TOOL */ },
|
|
30603
|
+
spanId,
|
|
30604
|
+
startTime: eventTime2(event)
|
|
30605
|
+
});
|
|
30606
|
+
span.log({ input: action.input, metadata });
|
|
30607
|
+
this.toolsByCallKey.set(key, {
|
|
30608
|
+
metadata,
|
|
30609
|
+
span,
|
|
30610
|
+
turnKey: turnKey2(sessionId, event.data.turnId)
|
|
30611
|
+
});
|
|
30612
|
+
}
|
|
30613
|
+
async startRequestedSubagent(event, turn, sessionId, action) {
|
|
30614
|
+
const key = toolKey3(sessionId, action.callId);
|
|
30615
|
+
if (this.toolsByCallKey.has(key) || this.completedToolKeys.has(key)) {
|
|
30616
|
+
return;
|
|
30617
|
+
}
|
|
30618
|
+
const name = action.subagentName ?? action.name ?? "agent";
|
|
30619
|
+
const metadata = toolMetadataFromTurn(turn);
|
|
30620
|
+
const { rowId: eventId, spanId } = await generateEveIds(
|
|
30621
|
+
"subagent",
|
|
30622
|
+
sessionId,
|
|
30623
|
+
action.callId
|
|
30624
|
+
);
|
|
30625
|
+
if (this.toolsByCallKey.has(key) || this.completedToolKeys.has(key)) {
|
|
30626
|
+
return;
|
|
30627
|
+
}
|
|
30628
|
+
const span = await this.startEveChildSpan(turn.span, {
|
|
30629
|
+
event: {
|
|
30630
|
+
id: eventId,
|
|
30631
|
+
input: action.input,
|
|
30632
|
+
metadata
|
|
30633
|
+
},
|
|
30634
|
+
name,
|
|
30635
|
+
spanAttributes: { type: "tool" /* TOOL */ },
|
|
30636
|
+
spanId,
|
|
30637
|
+
startTime: eventTime2(event)
|
|
30638
|
+
});
|
|
30639
|
+
span.log({ input: action.input, metadata });
|
|
30640
|
+
this.toolsByCallKey.set(key, {
|
|
30641
|
+
metadata,
|
|
30642
|
+
span,
|
|
30643
|
+
turnKey: turnKey2(sessionId, event.data.turnId)
|
|
30644
|
+
});
|
|
30645
|
+
}
|
|
30646
|
+
async startSyntheticTool(event, ctx, result, hookMetadata) {
|
|
30647
|
+
const turn = await this.ensureTurn(event, ctx, hookMetadata);
|
|
30648
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30649
|
+
if (!turn || !sessionId) {
|
|
30650
|
+
return void 0;
|
|
30651
|
+
}
|
|
30652
|
+
const metadata = toolMetadataFromTurn(turn);
|
|
30653
|
+
const { rowId: eventId, spanId } = await generateEveIds(
|
|
30654
|
+
"tool",
|
|
30655
|
+
sessionId,
|
|
30656
|
+
event.data.turnId,
|
|
30657
|
+
result.callId
|
|
30658
|
+
);
|
|
30659
|
+
const existing = this.toolsByCallKey.get(toolKey3(sessionId, result.callId));
|
|
30660
|
+
if (existing) {
|
|
30661
|
+
return existing;
|
|
30662
|
+
}
|
|
30663
|
+
const span = await this.startEveChildSpan(turn.span, {
|
|
30664
|
+
event: {
|
|
30665
|
+
id: eventId,
|
|
30666
|
+
metadata
|
|
30667
|
+
},
|
|
30668
|
+
name: result.toolName,
|
|
30669
|
+
spanAttributes: { type: "tool" /* TOOL */ },
|
|
30670
|
+
spanId,
|
|
30671
|
+
startTime: eventTime2(event)
|
|
30672
|
+
});
|
|
30673
|
+
span.log({ metadata });
|
|
30674
|
+
const state = {
|
|
30675
|
+
metadata,
|
|
30676
|
+
span,
|
|
30677
|
+
turnKey: turnKey2(sessionId, event.data.turnId)
|
|
30678
|
+
};
|
|
30679
|
+
this.toolsByCallKey.set(toolKey3(sessionId, result.callId), state);
|
|
30680
|
+
return state;
|
|
30681
|
+
}
|
|
30682
|
+
async startSyntheticSubagent(event, ctx, hookMetadata) {
|
|
30683
|
+
const turn = await this.ensureTurn(event, ctx, hookMetadata);
|
|
30684
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30685
|
+
if (!turn || !sessionId) {
|
|
30686
|
+
return void 0;
|
|
30687
|
+
}
|
|
30688
|
+
const metadata = toolMetadataFromTurn(turn);
|
|
30689
|
+
const { rowId: eventId, spanId } = await generateEveIds(
|
|
30690
|
+
"subagent",
|
|
30691
|
+
sessionId,
|
|
30692
|
+
event.data.callId
|
|
30693
|
+
);
|
|
30694
|
+
const existing = this.toolsByCallKey.get(
|
|
30695
|
+
toolKey3(sessionId, event.data.callId)
|
|
30696
|
+
);
|
|
30697
|
+
if (existing) {
|
|
30698
|
+
return existing;
|
|
30699
|
+
}
|
|
30700
|
+
const span = await this.startEveChildSpan(turn.span, {
|
|
30701
|
+
event: {
|
|
30702
|
+
id: eventId,
|
|
30703
|
+
metadata
|
|
30704
|
+
},
|
|
30705
|
+
name: event.data.subagentName,
|
|
30706
|
+
spanAttributes: { type: "tool" /* TOOL */ },
|
|
30707
|
+
spanId,
|
|
30708
|
+
startTime: eventTime2(event)
|
|
30709
|
+
});
|
|
30710
|
+
span.log({ metadata });
|
|
30711
|
+
const state = {
|
|
30712
|
+
metadata,
|
|
30713
|
+
span,
|
|
30714
|
+
turnKey: turnKey2(sessionId, event.data.turnId)
|
|
30715
|
+
};
|
|
30716
|
+
this.toolsByCallKey.set(toolKey3(sessionId, event.data.callId), state);
|
|
30717
|
+
return state;
|
|
30718
|
+
}
|
|
30719
|
+
async startSyntheticSubagentResult(event, ctx, result, hookMetadata) {
|
|
30720
|
+
const turn = await this.ensureTurn(event, ctx, hookMetadata);
|
|
30721
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30722
|
+
if (!turn || !sessionId) {
|
|
30723
|
+
return void 0;
|
|
30724
|
+
}
|
|
30725
|
+
const metadata = toolMetadataFromTurn(turn);
|
|
30726
|
+
const { rowId: eventId, spanId } = await generateEveIds(
|
|
30727
|
+
"subagent",
|
|
30728
|
+
sessionId,
|
|
30729
|
+
result.callId
|
|
30730
|
+
);
|
|
30731
|
+
const existing = this.toolsByCallKey.get(toolKey3(sessionId, result.callId));
|
|
30732
|
+
if (existing) {
|
|
30733
|
+
return existing;
|
|
30734
|
+
}
|
|
30735
|
+
const span = await this.startEveChildSpan(turn.span, {
|
|
30736
|
+
event: {
|
|
30737
|
+
id: eventId,
|
|
30738
|
+
metadata
|
|
30739
|
+
},
|
|
30740
|
+
name: result.subagentName,
|
|
30741
|
+
spanAttributes: { type: "tool" /* TOOL */ },
|
|
30742
|
+
spanId,
|
|
30743
|
+
startTime: eventTime2(event)
|
|
30744
|
+
});
|
|
30745
|
+
span.log({ metadata });
|
|
30746
|
+
const state = {
|
|
30747
|
+
metadata,
|
|
30748
|
+
span,
|
|
30749
|
+
turnKey: turnKey2(sessionId, event.data.turnId)
|
|
30750
|
+
};
|
|
30751
|
+
this.toolsByCallKey.set(toolKey3(sessionId, result.callId), state);
|
|
30752
|
+
return state;
|
|
30753
|
+
}
|
|
30754
|
+
async startTurnSpan(sessionId, event, ctx, metadata) {
|
|
30755
|
+
const session = isObject(ctx) ? ctx["session"] : void 0;
|
|
30756
|
+
const parent = isObject(session) ? session["parent"] : void 0;
|
|
30757
|
+
const parentTurn = isObject(parent) ? parent["turn"] : void 0;
|
|
30758
|
+
const parentLineage = isObject(parent) && typeof parent["callId"] === "string" && typeof parent["sessionId"] === "string" && isObject(parentTurn) && typeof parentTurn["id"] === "string" ? {
|
|
30759
|
+
callId: parent["callId"],
|
|
30760
|
+
sessionId: parent["sessionId"],
|
|
30761
|
+
turnId: parentTurn["id"]
|
|
30762
|
+
} : void 0;
|
|
30763
|
+
const [{ rowId: eventId, spanId }, rootSpanId, parentSpanId] = await Promise.all([
|
|
30764
|
+
generateEveIds("turn", sessionId, event.data.turnId),
|
|
30765
|
+
deterministicEveId(
|
|
30766
|
+
"eve:root",
|
|
30767
|
+
parentLineage?.sessionId ?? sessionId,
|
|
30768
|
+
parentLineage?.turnId ?? event.data.turnId
|
|
30769
|
+
),
|
|
30770
|
+
parentLineage ? deterministicEveId(
|
|
30771
|
+
"eve:subagent",
|
|
30772
|
+
parentLineage.sessionId,
|
|
30773
|
+
parentLineage.callId
|
|
30774
|
+
) : Promise.resolve(void 0)
|
|
30775
|
+
]);
|
|
30776
|
+
return await this.startEveSpan({
|
|
30777
|
+
event: {
|
|
30778
|
+
id: eventId,
|
|
30779
|
+
metadata
|
|
30780
|
+
},
|
|
30781
|
+
name: "eve.turn",
|
|
30782
|
+
parentSpanIds: parentSpanId ? { rootSpanId, spanId: parentSpanId } : { parentSpanIds: [], rootSpanId },
|
|
30783
|
+
spanAttributes: { type: "task" /* TASK */ },
|
|
30784
|
+
spanId,
|
|
30785
|
+
startTime: eventTime2(event)
|
|
30786
|
+
});
|
|
30787
|
+
}
|
|
30788
|
+
turnForEvent(event, ctx) {
|
|
30789
|
+
const sessionId = sessionIdFromContext(ctx);
|
|
30790
|
+
return sessionId ? this.turnsByKey.get(turnKey2(sessionId, event.data.turnId)) : void 0;
|
|
30791
|
+
}
|
|
30792
|
+
stepForEvent(event, ctx) {
|
|
30793
|
+
return this.turnForEvent(event, ctx)?.stepsByIndex.get(
|
|
30794
|
+
event.data.stepIndex
|
|
30795
|
+
);
|
|
30796
|
+
}
|
|
30797
|
+
finalizeTurn(turn, args) {
|
|
30798
|
+
const { endTime } = args;
|
|
30799
|
+
for (const step of turn.stepsByIndex.values()) {
|
|
30800
|
+
step.span.log({
|
|
30801
|
+
...step.input !== void 0 ? { input: step.input } : {},
|
|
30802
|
+
metadata: step.metadata,
|
|
30803
|
+
metrics: step.metrics,
|
|
30804
|
+
output: step.output
|
|
30805
|
+
});
|
|
30806
|
+
step.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30807
|
+
}
|
|
30808
|
+
turn.stepsByIndex.clear();
|
|
30809
|
+
for (const tool of this.toolsByCallKey.values()) {
|
|
30810
|
+
if (tool.turnKey !== turn.key) {
|
|
30811
|
+
continue;
|
|
30812
|
+
}
|
|
30813
|
+
if (tool.endedByTurn) {
|
|
30814
|
+
continue;
|
|
30815
|
+
}
|
|
30816
|
+
tool.span.log({ metadata: tool.metadata });
|
|
30817
|
+
tool.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30818
|
+
tool.endedByTurn = true;
|
|
30819
|
+
}
|
|
30820
|
+
if (args.error) {
|
|
30821
|
+
turn.span.log({ error: args.error });
|
|
30822
|
+
} else {
|
|
30823
|
+
turn.span.log({
|
|
30824
|
+
metadata: turn.metadata,
|
|
30825
|
+
metrics: turn.metrics,
|
|
30826
|
+
output: turn.output
|
|
30827
|
+
});
|
|
30828
|
+
}
|
|
30829
|
+
turn.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
30830
|
+
this.turnsByKey.delete(turn.key);
|
|
30831
|
+
this.state.update((current) => {
|
|
30832
|
+
const normalized = normalizeEveTraceState(current);
|
|
30833
|
+
return {
|
|
30834
|
+
...normalized,
|
|
30835
|
+
stepStarts: normalized.stepStarts.filter(
|
|
30836
|
+
(entry) => entry.turnId !== turn.turnId
|
|
30837
|
+
)
|
|
30838
|
+
};
|
|
30839
|
+
});
|
|
30840
|
+
}
|
|
30841
|
+
cleanupSession(sessionId) {
|
|
30842
|
+
const keyPrefix = `${sessionId}:`;
|
|
30843
|
+
for (const key of this.turnsByKey.keys()) {
|
|
30844
|
+
if (key.startsWith(keyPrefix)) {
|
|
30845
|
+
this.turnsByKey.delete(key);
|
|
30846
|
+
}
|
|
30847
|
+
}
|
|
30848
|
+
for (const key of this.toolsByCallKey.keys()) {
|
|
30849
|
+
if (key.startsWith(keyPrefix)) {
|
|
30850
|
+
this.toolsByCallKey.delete(key);
|
|
30851
|
+
}
|
|
30852
|
+
}
|
|
30853
|
+
for (const key of this.completedToolKeys.keys()) {
|
|
30854
|
+
if (key.startsWith(keyPrefix)) {
|
|
30855
|
+
this.completedToolKeys.delete(key);
|
|
30856
|
+
}
|
|
30857
|
+
}
|
|
30858
|
+
this.state.update(() => emptyEveTraceState());
|
|
30859
|
+
}
|
|
30860
|
+
async flushInstrumentation() {
|
|
30861
|
+
try {
|
|
30862
|
+
await flush();
|
|
30863
|
+
return true;
|
|
30864
|
+
} catch (error) {
|
|
30865
|
+
debugLogger.warn("Error in Eve flush instrumentation:", error);
|
|
30866
|
+
return false;
|
|
30867
|
+
}
|
|
30868
|
+
}
|
|
30869
|
+
};
|
|
30870
|
+
function emptyEveTraceState() {
|
|
30871
|
+
return {
|
|
30872
|
+
llmInputs: [],
|
|
30873
|
+
metadata: {},
|
|
30874
|
+
spanReferences: [],
|
|
30875
|
+
stepStarts: []
|
|
30876
|
+
};
|
|
30877
|
+
}
|
|
30878
|
+
function normalizeEveTraceState(state) {
|
|
30879
|
+
if (!isObject(state)) {
|
|
30880
|
+
return emptyEveTraceState();
|
|
30881
|
+
}
|
|
30882
|
+
const metadata = isObject(state["metadata"]) ? state["metadata"] : {};
|
|
30883
|
+
const spanReferences = Array.isArray(state["spanReferences"]) ? state["spanReferences"].flatMap((entry) => {
|
|
30884
|
+
if (!isObject(entry)) {
|
|
30885
|
+
return [];
|
|
30886
|
+
}
|
|
30887
|
+
const exported = entry["exported"];
|
|
30888
|
+
const endTime = entry["endTime"];
|
|
30889
|
+
const rootSpanId = entry["rootSpanId"];
|
|
30890
|
+
const rowId = entry["rowId"];
|
|
30891
|
+
const spanId = entry["spanId"];
|
|
30892
|
+
const startEvent = entry["startEvent"];
|
|
30893
|
+
const startEventCreated = isObject(startEvent) ? startEvent["created"] : void 0;
|
|
30894
|
+
const startEventMetrics = isObject(startEvent) ? startEvent["metrics"] : void 0;
|
|
30895
|
+
const startEventSpanAttributes = isObject(startEvent) ? startEvent["span_attributes"] : void 0;
|
|
30896
|
+
const startEventSpanParents = isObject(startEvent) ? startEvent["span_parents"] : void 0;
|
|
30897
|
+
const normalizedStartEvent = typeof startEventCreated === "string" && isObject(startEventMetrics) && typeof startEventMetrics["start"] === "number" && Number.isFinite(startEventMetrics["start"]) && isObject(startEventSpanAttributes) && Array.isArray(startEventSpanParents) && startEventSpanParents.every(
|
|
30898
|
+
(parent) => typeof parent === "string"
|
|
30899
|
+
) ? {
|
|
30900
|
+
created: startEventCreated,
|
|
30901
|
+
metrics: { start: startEventMetrics["start"] },
|
|
30902
|
+
span_attributes: { ...startEventSpanAttributes },
|
|
30903
|
+
span_parents: [...startEventSpanParents]
|
|
30904
|
+
} : void 0;
|
|
30905
|
+
return typeof exported === "string" && typeof rootSpanId === "string" && typeof rowId === "string" && typeof spanId === "string" ? [
|
|
30906
|
+
{
|
|
30907
|
+
...typeof endTime === "number" && Number.isFinite(endTime) ? { endTime } : {},
|
|
30908
|
+
exported,
|
|
30909
|
+
rootSpanId,
|
|
30910
|
+
rowId,
|
|
30911
|
+
spanId,
|
|
30912
|
+
...normalizedStartEvent ? { startEvent: normalizedStartEvent } : {}
|
|
30913
|
+
}
|
|
30914
|
+
] : [];
|
|
30915
|
+
}).slice(-MAX_STORED_SPAN_REFERENCES) : [];
|
|
30916
|
+
const llmInputs = Array.isArray(state["llmInputs"]) ? state["llmInputs"].flatMap((entry) => {
|
|
30917
|
+
if (!isObject(entry)) {
|
|
30918
|
+
return [];
|
|
30919
|
+
}
|
|
30920
|
+
const key = entry["key"];
|
|
30921
|
+
const input = entry["input"];
|
|
30922
|
+
return typeof key === "string" && isCapturedModelInput(input) ? [{ input, key }] : [];
|
|
30923
|
+
}).slice(-MAX_STORED_LLM_INPUTS) : [];
|
|
30924
|
+
const stepStarts = Array.isArray(state["stepStarts"]) ? state["stepStarts"].flatMap((entry) => {
|
|
30925
|
+
if (!isObject(entry)) {
|
|
30926
|
+
return [];
|
|
30927
|
+
}
|
|
30928
|
+
const ordinal = entry["ordinal"];
|
|
30929
|
+
const open = entry["open"];
|
|
30930
|
+
const stepIndex = entry["stepIndex"];
|
|
30931
|
+
const turnId = entry["turnId"];
|
|
30932
|
+
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 }] : [];
|
|
30933
|
+
}).slice(-MAX_STORED_STEP_STARTS) : [];
|
|
30934
|
+
return { llmInputs, metadata: { ...metadata }, spanReferences, stepStarts };
|
|
30935
|
+
}
|
|
30936
|
+
function readEveTraceState(state) {
|
|
30937
|
+
try {
|
|
30938
|
+
return normalizeEveTraceState(state.get());
|
|
30939
|
+
} catch {
|
|
30940
|
+
return emptyEveTraceState();
|
|
30941
|
+
}
|
|
30942
|
+
}
|
|
30943
|
+
function captureEveModelInput(state, input) {
|
|
30944
|
+
if (!isObject(input)) {
|
|
30945
|
+
return;
|
|
30946
|
+
}
|
|
30947
|
+
const session = input["session"];
|
|
30948
|
+
const turn = input["turn"];
|
|
30949
|
+
const step = input["step"];
|
|
30950
|
+
if (!isObject(session) || !isObject(turn) || !isObject(step)) {
|
|
30951
|
+
return;
|
|
30952
|
+
}
|
|
30953
|
+
const sessionId = session["id"];
|
|
30954
|
+
const turnId = turn["id"];
|
|
30955
|
+
const stepIndex = step["index"];
|
|
30956
|
+
if (typeof sessionId !== "string" || typeof turnId !== "string" || typeof stepIndex !== "number" || !Number.isInteger(stepIndex)) {
|
|
30957
|
+
return;
|
|
30958
|
+
}
|
|
30959
|
+
const captured = capturedModelInput(input["modelInput"]);
|
|
30960
|
+
if (!captured) {
|
|
30961
|
+
return;
|
|
30962
|
+
}
|
|
30963
|
+
const key = llmInputKey(sessionId, turnId, stepIndex);
|
|
30964
|
+
state.update((current) => {
|
|
30965
|
+
const normalized = normalizeEveTraceState(current);
|
|
30966
|
+
const llmInputs = [...normalized.llmInputs, { input: captured, key }];
|
|
30967
|
+
return {
|
|
30968
|
+
...normalized,
|
|
30969
|
+
llmInputs: llmInputs.slice(-MAX_STORED_LLM_INPUTS)
|
|
30970
|
+
};
|
|
30971
|
+
});
|
|
30972
|
+
}
|
|
30973
|
+
function consumeCapturedEveModelInput(state, sessionId, turnId, stepIndex) {
|
|
30974
|
+
try {
|
|
30975
|
+
const key = llmInputKey(sessionId, turnId, stepIndex);
|
|
30976
|
+
let input;
|
|
30977
|
+
state.update((current) => {
|
|
30978
|
+
const normalized = normalizeEveTraceState(current);
|
|
30979
|
+
const index = normalized.llmInputs.findIndex(
|
|
30980
|
+
(candidate) => candidate.key === key
|
|
30981
|
+
);
|
|
30982
|
+
if (index < 0) {
|
|
30983
|
+
return normalized;
|
|
30984
|
+
}
|
|
30985
|
+
input = normalized.llmInputs[index]?.input;
|
|
30986
|
+
return {
|
|
30987
|
+
...normalized,
|
|
30988
|
+
llmInputs: normalized.llmInputs.filter(
|
|
30989
|
+
(_, candidateIndex) => candidateIndex !== index
|
|
30990
|
+
)
|
|
30991
|
+
};
|
|
30992
|
+
});
|
|
30993
|
+
return input;
|
|
30994
|
+
} catch (error) {
|
|
30995
|
+
debugLogger.warn("Error in Eve LLM input consumption:", error);
|
|
30996
|
+
return void 0;
|
|
30997
|
+
}
|
|
30998
|
+
}
|
|
30999
|
+
function capturedModelInput(modelInput) {
|
|
31000
|
+
if (!isObject(modelInput)) {
|
|
31001
|
+
return void 0;
|
|
31002
|
+
}
|
|
31003
|
+
const messages = modelInput["messages"];
|
|
31004
|
+
if (!Array.isArray(messages)) {
|
|
31005
|
+
return void 0;
|
|
31006
|
+
}
|
|
31007
|
+
const instructions = modelInput["instructions"];
|
|
31008
|
+
const value = [
|
|
31009
|
+
...instructions !== void 0 ? [{ content: instructions, role: "system" }] : [],
|
|
31010
|
+
...messages
|
|
31011
|
+
];
|
|
31012
|
+
try {
|
|
31013
|
+
const cloned = JSON.parse(JSON.stringify(value));
|
|
31014
|
+
if (!Array.isArray(cloned)) {
|
|
31015
|
+
return void 0;
|
|
31016
|
+
}
|
|
31017
|
+
return cloned;
|
|
31018
|
+
} catch {
|
|
31019
|
+
return void 0;
|
|
31020
|
+
}
|
|
31021
|
+
}
|
|
31022
|
+
function isCapturedModelInput(input) {
|
|
31023
|
+
return Array.isArray(input);
|
|
31024
|
+
}
|
|
31025
|
+
function llmInputKey(sessionId, turnId, stepIndex) {
|
|
31026
|
+
return `${sessionId}\0${turnId}\0${stepIndex}`;
|
|
31027
|
+
}
|
|
31028
|
+
function modelMetadataFromRuntime(runtime) {
|
|
31029
|
+
if (!isObject(runtime)) {
|
|
31030
|
+
return {};
|
|
31031
|
+
}
|
|
31032
|
+
const modelId = runtime["modelId"];
|
|
31033
|
+
return typeof modelId === "string" && !modelId.trim().startsWith("dynamic:") ? modelMetadataFromModelId(modelId) : {};
|
|
31034
|
+
}
|
|
31035
|
+
function modelMetadataFromModelId(modelId) {
|
|
31036
|
+
const normalized = modelId.trim();
|
|
31037
|
+
if (!normalized) {
|
|
31038
|
+
return {};
|
|
31039
|
+
}
|
|
31040
|
+
const slashIndex = normalized.indexOf("/");
|
|
31041
|
+
if (slashIndex > 0 && slashIndex < normalized.length - 1) {
|
|
31042
|
+
return {
|
|
31043
|
+
model: normalized.slice(slashIndex + 1),
|
|
31044
|
+
provider: normalized.slice(0, slashIndex)
|
|
31045
|
+
};
|
|
31046
|
+
}
|
|
31047
|
+
return {
|
|
31048
|
+
model: normalized
|
|
31049
|
+
};
|
|
31050
|
+
}
|
|
31051
|
+
function sessionIdFromContext(ctx) {
|
|
31052
|
+
if (!isObject(ctx)) {
|
|
31053
|
+
return void 0;
|
|
31054
|
+
}
|
|
31055
|
+
const session = ctx["session"];
|
|
31056
|
+
if (!isObject(session)) {
|
|
31057
|
+
return void 0;
|
|
31058
|
+
}
|
|
31059
|
+
const id = session["id"];
|
|
31060
|
+
return typeof id === "string" ? id : void 0;
|
|
31061
|
+
}
|
|
31062
|
+
function toolMetadataFromTurn(turn) {
|
|
31063
|
+
const { model: _model, provider: _provider, ...metadata } = turn.metadata;
|
|
31064
|
+
return metadata;
|
|
31065
|
+
}
|
|
31066
|
+
function isToolCallAction(action) {
|
|
31067
|
+
return isObject(action) && action["kind"] === "tool-call" && typeof action["callId"] === "string" && typeof action["toolName"] === "string" && isObject(action["input"]);
|
|
31068
|
+
}
|
|
31069
|
+
function isLocalSubagentCallAction(action) {
|
|
31070
|
+
return isObject(action) && action["kind"] === "subagent-call" && typeof action["callId"] === "string" && isObject(action["input"]);
|
|
31071
|
+
}
|
|
31072
|
+
function isTraceableActionRequest(action) {
|
|
31073
|
+
return isToolCallAction(action) || isLocalSubagentCallAction(action);
|
|
31074
|
+
}
|
|
31075
|
+
function isToolResult(result) {
|
|
31076
|
+
return isObject(result) && result["kind"] === "tool-result" && typeof result["callId"] === "string" && typeof result["toolName"] === "string";
|
|
31077
|
+
}
|
|
31078
|
+
function isSubagentResult(result) {
|
|
31079
|
+
return isObject(result) && result["kind"] === "subagent-result" && typeof result["callId"] === "string" && typeof result["subagentName"] === "string";
|
|
31080
|
+
}
|
|
31081
|
+
function normalizedFinishReason(finishReason) {
|
|
31082
|
+
switch (finishReason) {
|
|
31083
|
+
case "content-filter":
|
|
31084
|
+
return "content_filter";
|
|
31085
|
+
case "tool-calls":
|
|
31086
|
+
return "tool_calls";
|
|
31087
|
+
default:
|
|
31088
|
+
return finishReason;
|
|
31089
|
+
}
|
|
31090
|
+
}
|
|
31091
|
+
function errorFromMessage(message, code, details) {
|
|
31092
|
+
const error = new Error(`${code}: ${message}`);
|
|
31093
|
+
if (details !== void 0) {
|
|
31094
|
+
error.cause = details;
|
|
31095
|
+
}
|
|
31096
|
+
return error;
|
|
31097
|
+
}
|
|
31098
|
+
function actionResultError(error, output) {
|
|
31099
|
+
if (error) {
|
|
31100
|
+
return errorFromMessage(error.message, error.code);
|
|
31101
|
+
}
|
|
31102
|
+
const result = new Error("Eve action failed");
|
|
31103
|
+
if (output !== void 0) {
|
|
31104
|
+
result.cause = output;
|
|
31105
|
+
}
|
|
31106
|
+
return result;
|
|
31107
|
+
}
|
|
31108
|
+
function eventTime2(event) {
|
|
31109
|
+
if (!event.meta?.at) {
|
|
31110
|
+
return void 0;
|
|
31111
|
+
}
|
|
31112
|
+
const timestamp = Date.parse(event.meta.at);
|
|
31113
|
+
return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
|
|
31114
|
+
}
|
|
31115
|
+
function turnKey2(sessionId, turnId) {
|
|
31116
|
+
return `${sessionId}:${turnId}`;
|
|
31117
|
+
}
|
|
31118
|
+
function toolKey3(sessionId, callId) {
|
|
31119
|
+
return `${sessionId}:${callId}`;
|
|
31120
|
+
}
|
|
31121
|
+
async function generateEveIds(kind, ...parts) {
|
|
31122
|
+
const [rowId, spanId] = await Promise.all([
|
|
31123
|
+
deterministicEveId(`eve:row:${kind}`, ...parts),
|
|
31124
|
+
deterministicEveId(`eve:${kind}`, ...parts)
|
|
31125
|
+
]);
|
|
31126
|
+
return { rowId, spanId };
|
|
31127
|
+
}
|
|
31128
|
+
async function deterministicEveId(...parts) {
|
|
31129
|
+
const data = new TextEncoder().encode(
|
|
31130
|
+
parts.map((part) => `${part.length}:${part}`).join("\0")
|
|
31131
|
+
);
|
|
31132
|
+
const digest = await globalThis.crypto.subtle.digest("SHA-256", data);
|
|
31133
|
+
const bytes = Array.from(new Uint8Array(digest, 0, 16));
|
|
31134
|
+
const hex = bytes.map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
31135
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
31136
|
+
}
|
|
28981
31137
|
|
|
28982
31138
|
// src/instrumentation/config.ts
|
|
28983
31139
|
var envIntegrationAliases = {
|
|
@@ -29040,7 +31196,8 @@ var envIntegrationAliases = {
|
|
|
29040
31196
|
langchain: "langchain",
|
|
29041
31197
|
"langchain-js": "langchain",
|
|
29042
31198
|
"@langchain": "langchain",
|
|
29043
|
-
langgraph: "langgraph"
|
|
31199
|
+
langgraph: "langgraph",
|
|
31200
|
+
langsmith: "langsmith"
|
|
29044
31201
|
};
|
|
29045
31202
|
function getDefaultInstrumentationIntegrations() {
|
|
29046
31203
|
return {
|
|
@@ -29071,6 +31228,7 @@ function getDefaultInstrumentationIntegrations() {
|
|
|
29071
31228
|
gitHubCopilot: true,
|
|
29072
31229
|
langchain: true,
|
|
29073
31230
|
langgraph: true,
|
|
31231
|
+
langsmith: true,
|
|
29074
31232
|
piCodingAgent: true,
|
|
29075
31233
|
strandsAgentSDK: true
|
|
29076
31234
|
};
|
|
@@ -29188,6 +31346,8 @@ function configureInstrumentation(config) {
|
|
|
29188
31346
|
BasePlugin,
|
|
29189
31347
|
BraintrustPlugin,
|
|
29190
31348
|
OpenAIAgentsTraceProcessor,
|
|
31349
|
+
braintrustEveHook,
|
|
31350
|
+
braintrustEveInstrumentation,
|
|
29191
31351
|
braintrustFlueInstrumentation,
|
|
29192
31352
|
braintrustFlueObserver,
|
|
29193
31353
|
configureInstrumentation,
|