braintrust 3.22.0 → 3.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +43 -0
  2. package/dev/dist/index.d.mts +1 -1
  3. package/dev/dist/index.d.ts +1 -1
  4. package/dev/dist/index.js +1354 -654
  5. package/dev/dist/index.mjs +736 -36
  6. package/dist/apply-auto-instrumentation.js +222 -186
  7. package/dist/apply-auto-instrumentation.mjs +37 -1
  8. package/dist/auto-instrumentations/bundler/esbuild.cjs +53 -1
  9. package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
  10. package/dist/auto-instrumentations/bundler/next.cjs +53 -1
  11. package/dist/auto-instrumentations/bundler/next.mjs +3 -3
  12. package/dist/auto-instrumentations/bundler/rollup.cjs +53 -1
  13. package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
  14. package/dist/auto-instrumentations/bundler/vite.cjs +53 -1
  15. package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
  16. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +53 -1
  17. package/dist/auto-instrumentations/bundler/webpack.cjs +53 -1
  18. package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
  19. package/dist/auto-instrumentations/{chunk-TKRPRPGD.mjs → chunk-EXY7QCJD.mjs} +5 -2
  20. package/dist/auto-instrumentations/{chunk-T6J4C7LX.mjs → chunk-KIMLYPRW.mjs} +1 -1
  21. package/dist/auto-instrumentations/{chunk-BRQX23KL.mjs → chunk-YXLNSAMJ.mjs} +51 -0
  22. package/dist/auto-instrumentations/hook.mjs +149 -20
  23. package/dist/auto-instrumentations/index.cjs +52 -0
  24. package/dist/auto-instrumentations/index.d.mts +3 -1
  25. package/dist/auto-instrumentations/index.d.ts +3 -1
  26. package/dist/auto-instrumentations/index.mjs +3 -1
  27. package/dist/browser.d.mts +11 -13
  28. package/dist/browser.d.ts +11 -13
  29. package/dist/browser.js +1098 -205
  30. package/dist/browser.mjs +1098 -205
  31. package/dist/{chunk-KMGUTPB7.mjs → chunk-36IPYKMG.mjs} +20 -1
  32. package/dist/{chunk-MWVVR5LR.js → chunk-B6ZQIAK3.js} +1506 -822
  33. package/dist/{chunk-BFGIH2ZJ.js → chunk-CDIKAHDZ.js} +21 -2
  34. package/dist/{chunk-ZG2O3XVF.mjs → chunk-RBXD2KYN.mjs} +719 -35
  35. package/dist/cli.js +737 -37
  36. package/dist/edge-light.d.mts +1 -1
  37. package/dist/edge-light.d.ts +1 -1
  38. package/dist/edge-light.js +1098 -205
  39. package/dist/edge-light.mjs +1098 -205
  40. package/dist/index.d.mts +11 -13
  41. package/dist/index.d.ts +11 -13
  42. package/dist/index.js +786 -593
  43. package/dist/index.mjs +346 -153
  44. package/dist/instrumentation/index.d.mts +3 -11
  45. package/dist/instrumentation/index.d.ts +3 -11
  46. package/dist/instrumentation/index.js +788 -183
  47. package/dist/instrumentation/index.mjs +788 -183
  48. package/dist/vitest-evals-reporter.js +16 -16
  49. package/dist/vitest-evals-reporter.mjs +2 -2
  50. package/dist/workerd.d.mts +1 -1
  51. package/dist/workerd.d.ts +1 -1
  52. package/dist/workerd.js +1098 -205
  53. package/dist/workerd.mjs +1098 -205
  54. package/package.json +1 -1
@@ -4361,7 +4361,7 @@ var DiskCache = class {
4361
4361
  }
4362
4362
  };
4363
4363
 
4364
- // src/prompt-cache/lru-cache.ts
4364
+ // src/lru-cache.ts
4365
4365
  var LRUCache = class {
4366
4366
  cache;
4367
4367
  maxSize;
@@ -5558,25 +5558,46 @@ var HTTPConnection = class _HTTPConnection {
5558
5558
  })
5559
5559
  );
5560
5560
  }
5561
- async post(path, params, config) {
5561
+ async post(path, params, config, retries = 0) {
5562
5562
  const { headers, ...rest } = config || {};
5563
5563
  const this_fetch = this.fetch;
5564
5564
  const this_base_url = this.base_url;
5565
5565
  const this_headers = this.headers;
5566
- return await checkResponse(
5567
- await this_fetch(_urljoin(this_base_url, path), {
5568
- method: "POST",
5569
- headers: {
5570
- Accept: "application/json",
5571
- "Content-Type": "application/json",
5572
- ...this_headers,
5573
- ...headers
5574
- },
5575
- body: typeof params === "string" ? params : params ? JSON.stringify(params) : void 0,
5576
- keepalive: true,
5577
- ...rest
5578
- })
5579
- );
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");
5580
5601
  }
5581
5602
  async get_json(object_type, args = void 0, retries = 0) {
5582
5603
  const tries = retries + 1;
@@ -6498,6 +6519,45 @@ function now() {
6498
6519
  var DEFAULT_FLUSH_BACKPRESSURE_BYTES = 10 * 1024 * 1024;
6499
6520
  var BACKGROUND_LOGGER_BASE_SLEEP_TIME_S = 1;
6500
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
+ }
6501
6561
  var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
6502
6562
  apiConn;
6503
6563
  queue;
@@ -7449,15 +7509,15 @@ function parentSpanIdsUsable(spanId, rootSpanId) {
7449
7509
  return Boolean(spanId) && Boolean(rootSpanId);
7450
7510
  }
7451
7511
  function logError(span, error) {
7452
- let errorMessage = "<error>";
7512
+ let errorMessage2 = "<error>";
7453
7513
  let stackTrace = "";
7454
7514
  if (error instanceof Error) {
7455
- errorMessage = error.message;
7515
+ errorMessage2 = error.message;
7456
7516
  stackTrace = error.stack || "";
7457
7517
  } else {
7458
- errorMessage = String(error);
7518
+ errorMessage2 = String(error);
7459
7519
  }
7460
- span.log({ error: `${errorMessage}
7520
+ span.log({ error: `${errorMessage2}
7461
7521
 
7462
7522
  ${stackTrace}` });
7463
7523
  }
@@ -7798,7 +7858,8 @@ var ObjectFetcher = class {
7798
7858
  version: this.pinnedVersion
7799
7859
  } : {}
7800
7860
  },
7801
- { headers: { "Accept-Encoding": "gzip" } }
7861
+ { headers: { "Accept-Encoding": "gzip" } },
7862
+ BTQL_HTTP_RETRIES
7802
7863
  );
7803
7864
  const respJson = await resp.json();
7804
7865
  const mutate = this.mutateRecord;
@@ -15989,8 +16050,6 @@ function filterSerializableOptions(options) {
15989
16050
  "additionalDirectories",
15990
16051
  "permissionMode",
15991
16052
  "debug",
15992
- "apiKey",
15993
- "apiKeySource",
15994
16053
  "agentName",
15995
16054
  "instructions"
15996
16055
  ];
@@ -27188,6 +27247,446 @@ function isBraintrustHandler(handler) {
27188
27247
  return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
27189
27248
  }
27190
27249
 
27250
+ // src/instrumentation/plugins/langsmith-channels.ts
27251
+ var langSmithChannels = defineChannels("langsmith", {
27252
+ createRun: channel({
27253
+ channelName: "Client.createRun",
27254
+ kind: "async"
27255
+ }),
27256
+ updateRun: channel({
27257
+ channelName: "Client.updateRun",
27258
+ kind: "async"
27259
+ }),
27260
+ batchIngestRuns: channel({
27261
+ channelName: "Client.batchIngestRuns",
27262
+ kind: "async"
27263
+ })
27264
+ });
27265
+
27266
+ // src/instrumentation/plugins/langsmith-plugin.ts
27267
+ var MAX_COMPLETED_RUNS = 1e4;
27268
+ var BLOCKED_METADATA_KEYS = /* @__PURE__ */ new Set([
27269
+ "__proto__",
27270
+ "constructor",
27271
+ "prototype",
27272
+ "usage_metadata"
27273
+ ]);
27274
+ var BLOCKED_METADATA_PREFIXES = ["__pregel_", "langgraph_", "lc_"];
27275
+ var LLM_SETTING_KEYS = [
27276
+ "temperature",
27277
+ "top_p",
27278
+ "max_tokens",
27279
+ "frequency_penalty",
27280
+ "presence_penalty",
27281
+ "stop",
27282
+ "response_format"
27283
+ ];
27284
+ var LangSmithPlugin = class extends BasePlugin {
27285
+ activeRuns = /* @__PURE__ */ new Map();
27286
+ completedRuns = new LRUCache({
27287
+ max: MAX_COMPLETED_RUNS
27288
+ });
27289
+ skipLangChainRuns;
27290
+ constructor(options = {}) {
27291
+ super();
27292
+ this.skipLangChainRuns = options.skipLangChainRuns ?? true;
27293
+ }
27294
+ onEnable() {
27295
+ const createChannel = langSmithChannels.createRun.tracingChannel();
27296
+ const createHandlers = {
27297
+ start: (event) => {
27298
+ this.containLifecycleFailure("createRun", () => {
27299
+ this.processCreate(event.arguments[0]);
27300
+ });
27301
+ }
27302
+ };
27303
+ createChannel.subscribe(createHandlers);
27304
+ this.unsubscribers.push(() => createChannel.unsubscribe(createHandlers));
27305
+ const updateChannel = langSmithChannels.updateRun.tracingChannel();
27306
+ const updateHandlers = {
27307
+ start: (event) => {
27308
+ this.containLifecycleFailure("updateRun", () => {
27309
+ this.processUpdate(event.arguments[0], event.arguments[1]);
27310
+ });
27311
+ }
27312
+ };
27313
+ updateChannel.subscribe(updateHandlers);
27314
+ this.unsubscribers.push(() => updateChannel.unsubscribe(updateHandlers));
27315
+ const batchChannel = langSmithChannels.batchIngestRuns.tracingChannel();
27316
+ const batchHandlers = {
27317
+ start: (event) => {
27318
+ this.containLifecycleFailure("batchIngestRuns", () => {
27319
+ this.processBatch(event.arguments[0]);
27320
+ });
27321
+ }
27322
+ };
27323
+ batchChannel.subscribe(batchHandlers);
27324
+ this.unsubscribers.push(() => batchChannel.unsubscribe(batchHandlers));
27325
+ }
27326
+ onDisable() {
27327
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
27328
+ for (const { span } of this.activeRuns.values()) {
27329
+ span.end();
27330
+ }
27331
+ this.activeRuns.clear();
27332
+ this.completedRuns.clear();
27333
+ }
27334
+ processBatch(batch) {
27335
+ if (!isRecord2(batch)) {
27336
+ return;
27337
+ }
27338
+ const creates = ownValue(batch, "runCreates");
27339
+ if (Array.isArray(creates)) {
27340
+ const parentFirst = [...creates].sort((left, right) => {
27341
+ const leftId = stringValue2(ownValue(left, "id"));
27342
+ const rightId = stringValue2(ownValue(right, "id"));
27343
+ const leftParent = stringValue2(ownValue(left, "parent_run_id"));
27344
+ const rightParent = stringValue2(ownValue(right, "parent_run_id"));
27345
+ if (leftParent && leftParent === rightId) {
27346
+ return 1;
27347
+ }
27348
+ if (rightParent && rightParent === leftId) {
27349
+ return -1;
27350
+ }
27351
+ return dottedOrderDepth(left) - dottedOrderDepth(right);
27352
+ });
27353
+ for (const run of parentFirst) {
27354
+ this.containLifecycleFailure("batchIngestRuns create", () => {
27355
+ this.processCreate(run);
27356
+ });
27357
+ }
27358
+ }
27359
+ const updates = ownValue(batch, "runUpdates");
27360
+ if (Array.isArray(updates)) {
27361
+ for (const run of updates) {
27362
+ this.containLifecycleFailure("batchIngestRuns update", () => {
27363
+ this.processUpdate(stringValue2(ownValue(run, "id")) ?? "", run);
27364
+ });
27365
+ }
27366
+ }
27367
+ }
27368
+ processCreate(run) {
27369
+ const id = stringValue2(ownValue(run, "id"));
27370
+ if (!id || this.completedRuns.get(id)) {
27371
+ return;
27372
+ }
27373
+ if (this.shouldSkipLangChainRun(run)) {
27374
+ this.completedRuns.set(id, true);
27375
+ return;
27376
+ }
27377
+ const active = this.activeRuns.get(id);
27378
+ if (active) {
27379
+ const previous = active.run;
27380
+ active.run = mergeRuns(previous, run);
27381
+ this.logRun(
27382
+ active.span,
27383
+ active.run,
27384
+ previous,
27385
+ timestampSeconds(ownValue(active.run, "end_time")) !== void 0 || errorMessage(ownValue(active.run, "error")) !== void 0
27386
+ );
27387
+ this.endIfComplete(id, active, active.run);
27388
+ return;
27389
+ }
27390
+ const span = this.startRunSpan(id, run);
27391
+ const activeRun = { run, span };
27392
+ this.activeRuns.set(id, activeRun);
27393
+ this.logRun(
27394
+ span,
27395
+ run,
27396
+ void 0,
27397
+ timestampSeconds(ownValue(run, "end_time")) !== void 0 || errorMessage(ownValue(run, "error")) !== void 0
27398
+ );
27399
+ this.endIfComplete(id, activeRun, run);
27400
+ }
27401
+ processUpdate(explicitId, run) {
27402
+ const id = stringValue2(explicitId) ?? stringValue2(ownValue(run, "id"));
27403
+ if (!id || this.completedRuns.get(id)) {
27404
+ return;
27405
+ }
27406
+ if (this.shouldSkipLangChainRun(run)) {
27407
+ const active2 = this.activeRuns.get(id);
27408
+ active2?.span.end();
27409
+ this.activeRuns.delete(id);
27410
+ this.completedRuns.set(id, true);
27411
+ return;
27412
+ }
27413
+ let active = this.activeRuns.get(id);
27414
+ if (!active) {
27415
+ const span = this.startRunSpan(id, run);
27416
+ active = { run, span };
27417
+ this.activeRuns.set(id, active);
27418
+ }
27419
+ const previous = active.run;
27420
+ active.run = mergeRuns(previous, run);
27421
+ this.logRun(active.span, active.run, previous, true);
27422
+ this.endIfComplete(id, active, active.run);
27423
+ }
27424
+ startRunSpan(id, run) {
27425
+ const traceId = stringValue2(ownValue(run, "trace_id")) ?? id;
27426
+ const parentId = stringValue2(ownValue(run, "parent_run_id")) ?? stringValue2(ownValue(ownValue(run, "parent_run"), "id"));
27427
+ const startTime = timestampSeconds(ownValue(run, "start_time"));
27428
+ return startSpan({
27429
+ name: stringValue2(ownValue(run, "name")) ?? "LangSmith run",
27430
+ spanId: id,
27431
+ parentSpanIds: {
27432
+ parentSpanIds: parentId ? [parentId] : [],
27433
+ rootSpanId: traceId
27434
+ },
27435
+ spanAttributes: {
27436
+ type: mapRunType(ownValue(run, "run_type"))
27437
+ },
27438
+ ...startTime === void 0 ? {} : { startTime },
27439
+ event: { id }
27440
+ });
27441
+ }
27442
+ logRun(span, run, previous, includeOutput) {
27443
+ const inputs = preferOwnValue(run, previous, "inputs");
27444
+ const outputs = preferOwnValue(run, previous, "outputs");
27445
+ const error = errorMessage(preferOwnValue(run, previous, "error"));
27446
+ const metadata = extractMetadata(run, previous);
27447
+ const tags = extractTags(preferOwnValue(run, previous, "tags"));
27448
+ const metrics = extractMetrics(run, previous);
27449
+ span.log({
27450
+ ...inputs === void 0 ? {} : { input: sanitizeLoggedValue(inputs) },
27451
+ ...includeOutput && outputs !== void 0 ? { output: sanitizeLoggedValue(outputs) } : {},
27452
+ ...error === void 0 ? {} : { error },
27453
+ ...metadata === void 0 ? {} : { metadata },
27454
+ ...tags === void 0 ? {} : { tags },
27455
+ ...Object.keys(metrics).length === 0 ? {} : { metrics }
27456
+ });
27457
+ }
27458
+ endIfComplete(id, active, run) {
27459
+ const endTime = timestampSeconds(ownValue(run, "end_time"));
27460
+ if (endTime === void 0 && errorMessage(ownValue(run, "error")) === void 0) {
27461
+ return;
27462
+ }
27463
+ active.span.end(endTime === void 0 ? void 0 : { endTime });
27464
+ this.activeRuns.delete(id);
27465
+ this.completedRuns.set(id, true);
27466
+ }
27467
+ shouldSkipLangChainRun(run) {
27468
+ if (!this.skipLangChainRuns) {
27469
+ return false;
27470
+ }
27471
+ const serialized = ownValue(run, "serialized");
27472
+ return isRecord2(serialized) && ownValue(serialized, "lc") === 1;
27473
+ }
27474
+ containLifecycleFailure(operation, fn) {
27475
+ try {
27476
+ fn();
27477
+ } catch (error) {
27478
+ debugLogger.error(
27479
+ `Failed to process LangSmith ${operation} instrumentation:`,
27480
+ error
27481
+ );
27482
+ }
27483
+ }
27484
+ };
27485
+ function ownValue(value, key) {
27486
+ if (!isRecord2(value)) {
27487
+ return void 0;
27488
+ }
27489
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
27490
+ return descriptor && "value" in descriptor ? descriptor.value : void 0;
27491
+ }
27492
+ function preferOwnValue(current, previous, key) {
27493
+ const currentDescriptor = isRecord2(current) ? Object.getOwnPropertyDescriptor(current, key) : void 0;
27494
+ if (currentDescriptor && "value" in currentDescriptor) {
27495
+ return currentDescriptor.value;
27496
+ }
27497
+ return ownValue(previous, key);
27498
+ }
27499
+ function mergeRuns(previous, current) {
27500
+ const entries = /* @__PURE__ */ new Map();
27501
+ for (const value of [previous, current]) {
27502
+ if (!isRecord2(value)) {
27503
+ continue;
27504
+ }
27505
+ for (const [key, descriptor] of Object.entries(
27506
+ Object.getOwnPropertyDescriptors(value)
27507
+ )) {
27508
+ if (descriptor.enumerable && "value" in descriptor) {
27509
+ entries.set(key, descriptor.value);
27510
+ }
27511
+ }
27512
+ }
27513
+ return Object.fromEntries(entries);
27514
+ }
27515
+ function isRecord2(value) {
27516
+ return typeof value === "object" && value !== null && !Array.isArray(value);
27517
+ }
27518
+ function stringValue2(value) {
27519
+ return typeof value === "string" && value.length > 0 ? value : void 0;
27520
+ }
27521
+ function timestampSeconds(value) {
27522
+ if (value instanceof Date) {
27523
+ const timestamp = value.getTime();
27524
+ return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
27525
+ }
27526
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
27527
+ return value > 1e10 ? value / 1e3 : value;
27528
+ }
27529
+ if (typeof value === "string") {
27530
+ const timestamp = Date.parse(value);
27531
+ return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
27532
+ }
27533
+ return void 0;
27534
+ }
27535
+ function dottedOrderDepth(run) {
27536
+ const dottedOrder = stringValue2(ownValue(run, "dotted_order"));
27537
+ return dottedOrder ? dottedOrder.split(".").length : Number.MAX_SAFE_INTEGER;
27538
+ }
27539
+ function mapRunType(runType) {
27540
+ switch (runType) {
27541
+ case "llm":
27542
+ case "embedding":
27543
+ return "llm" /* LLM */;
27544
+ case "tool":
27545
+ case "retriever":
27546
+ return "tool" /* TOOL */;
27547
+ default:
27548
+ return "task" /* TASK */;
27549
+ }
27550
+ }
27551
+ function extractMetadata(run, previous) {
27552
+ const extra = preferOwnValue(run, previous, "extra");
27553
+ const rawMetadata = ownValue(extra, "metadata");
27554
+ if (!isRecord2(rawMetadata)) {
27555
+ return void 0;
27556
+ }
27557
+ const metadata = {};
27558
+ for (const [key, descriptor] of Object.entries(
27559
+ Object.getOwnPropertyDescriptors(rawMetadata)
27560
+ )) {
27561
+ 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}`)) {
27562
+ continue;
27563
+ }
27564
+ const normalizedKey = key === "ls_provider" ? "provider" : key === "ls_model_name" ? "model" : key.startsWith("ls_") ? key.slice(3) : key;
27565
+ const sanitized = sanitizeLoggedValue(descriptor.value);
27566
+ if (sanitized !== void 0) {
27567
+ metadata[normalizedKey] = sanitized;
27568
+ }
27569
+ }
27570
+ return Object.keys(metadata).length === 0 ? void 0 : metadata;
27571
+ }
27572
+ function extractTags(value) {
27573
+ if (!Array.isArray(value)) {
27574
+ return void 0;
27575
+ }
27576
+ const tags = value.filter(
27577
+ (tag) => typeof tag === "string" && tag.length > 0
27578
+ );
27579
+ return tags.length > 0 ? tags : void 0;
27580
+ }
27581
+ function extractMetrics(run, previous) {
27582
+ const outputs = preferOwnValue(run, previous, "outputs");
27583
+ const extra = preferOwnValue(run, previous, "extra");
27584
+ const metadata = ownValue(extra, "metadata");
27585
+ const usage = ownValue(outputs, "usage_metadata") ?? ownValue(metadata, "usage_metadata");
27586
+ const metrics = {};
27587
+ assignFirstMetric(metrics, "prompt_tokens", usage, [
27588
+ "input_tokens",
27589
+ "prompt_tokens"
27590
+ ]);
27591
+ assignFirstMetric(metrics, "completion_tokens", usage, [
27592
+ "output_tokens",
27593
+ "completion_tokens"
27594
+ ]);
27595
+ assignFirstMetric(metrics, "tokens", usage, ["total_tokens", "tokens"]);
27596
+ const inputTokenDetails = ownValue(usage, "input_token_details");
27597
+ assignFirstMetric(metrics, "prompt_cached_tokens", inputTokenDetails, [
27598
+ "cache_read",
27599
+ "cached_tokens"
27600
+ ]);
27601
+ if (metrics.prompt_cached_tokens === void 0) {
27602
+ assignFirstMetric(metrics, "prompt_cached_tokens", usage, [
27603
+ "cache_read_input_tokens",
27604
+ "prompt_cached_tokens"
27605
+ ]);
27606
+ }
27607
+ assignFirstMetric(
27608
+ metrics,
27609
+ "prompt_cache_creation_tokens",
27610
+ inputTokenDetails,
27611
+ ["cache_creation"]
27612
+ );
27613
+ if (metrics.prompt_cache_creation_tokens === void 0) {
27614
+ assignFirstMetric(metrics, "prompt_cache_creation_tokens", usage, [
27615
+ "cache_creation_input_tokens",
27616
+ "prompt_cache_creation_tokens"
27617
+ ]);
27618
+ }
27619
+ if (metrics.tokens === void 0 && (metrics.prompt_tokens !== void 0 || metrics.completion_tokens !== void 0)) {
27620
+ metrics.tokens = (metrics.prompt_tokens ?? 0) + (metrics.completion_tokens ?? 0);
27621
+ }
27622
+ const startTime = timestampSeconds(
27623
+ preferOwnValue(run, previous, "start_time")
27624
+ );
27625
+ const events = preferOwnValue(run, previous, "events");
27626
+ if (startTime !== void 0 && Array.isArray(events)) {
27627
+ for (const event of events) {
27628
+ if (ownValue(event, "name") !== "new_token") {
27629
+ continue;
27630
+ }
27631
+ const eventTime3 = timestampSeconds(ownValue(event, "time"));
27632
+ if (eventTime3 !== void 0 && eventTime3 >= startTime) {
27633
+ metrics.time_to_first_token = eventTime3 - startTime;
27634
+ }
27635
+ break;
27636
+ }
27637
+ }
27638
+ return metrics;
27639
+ }
27640
+ function assignFirstMetric(metrics, target, source, keys) {
27641
+ for (const key of keys) {
27642
+ const value = ownValue(source, key);
27643
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
27644
+ metrics[target] = value;
27645
+ return;
27646
+ }
27647
+ }
27648
+ }
27649
+ function errorMessage(value) {
27650
+ if (typeof value === "string") {
27651
+ return value;
27652
+ }
27653
+ if (value instanceof Error) {
27654
+ return value.message;
27655
+ }
27656
+ return void 0;
27657
+ }
27658
+ function sanitizeLoggedValue(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
27659
+ if (value === null || typeof value === "string" || typeof value === "boolean") {
27660
+ return value;
27661
+ }
27662
+ if (typeof value === "number") {
27663
+ return Number.isFinite(value) ? value : void 0;
27664
+ }
27665
+ if (value instanceof Date) {
27666
+ return Number.isFinite(value.getTime()) ? value.toISOString() : void 0;
27667
+ }
27668
+ if (typeof value !== "object" || depth >= 20) {
27669
+ return void 0;
27670
+ }
27671
+ if (seen.has(value)) {
27672
+ return "[Circular]";
27673
+ }
27674
+ seen.add(value);
27675
+ if (Array.isArray(value)) {
27676
+ return value.map((item) => sanitizeLoggedValue(item, seen, depth + 1));
27677
+ }
27678
+ const entries = [];
27679
+ for (const [key, descriptor] of Object.entries(
27680
+ Object.getOwnPropertyDescriptors(value)
27681
+ )) {
27682
+ if (!descriptor.enumerable || !("value" in descriptor) || BLOCKED_METADATA_KEYS.has(key)) {
27683
+ continue;
27684
+ }
27685
+ entries.push([key, sanitizeLoggedValue(descriptor.value, seen, depth + 1)]);
27686
+ }
27687
+ return Object.fromEntries(entries);
27688
+ }
27689
+
27191
27690
  // src/instrumentation/plugins/pi-coding-agent-channels.ts
27192
27691
  var piCodingAgentChannels = defineChannels(
27193
27692
  "@earendil-works/pi-coding-agent",
@@ -27567,11 +28066,11 @@ function patchAssistantMessageStream(stream, promptState, llmState) {
27567
28066
  function recordPiAssistantMessageEvent(promptState, llmState, event) {
27568
28067
  recordFirstTokenMetric(llmState, event);
27569
28068
  const message = "message" in event ? event.message : void 0;
27570
- const errorMessage = "error" in event ? event.error : void 0;
28069
+ const errorMessage2 = "error" in event ? event.error : void 0;
27571
28070
  if (event.type === "done" && isPiAssistantMessage(message)) {
27572
28071
  finishPiLlmSpan(promptState, llmState, message);
27573
- } else if (event.type === "error" && isPiAssistantMessage(errorMessage)) {
27574
- finishPiLlmSpan(promptState, llmState, errorMessage);
28072
+ } else if (event.type === "error" && isPiAssistantMessage(errorMessage2)) {
28073
+ finishPiLlmSpan(promptState, llmState, errorMessage2);
27575
28074
  }
27576
28075
  }
27577
28076
  function recordFirstTokenMetric(state, event) {
@@ -28089,6 +28588,7 @@ var strandsAgentSDKChannels = defineChannels("@strands-agents/sdk", {
28089
28588
  });
28090
28589
 
28091
28590
  // src/instrumentation/plugins/strands-agent-sdk-plugin.ts
28591
+ var MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES = 32;
28092
28592
  var StrandsAgentSDKPlugin = class extends BasePlugin {
28093
28593
  activeChildParents = /* @__PURE__ */ new WeakMap();
28094
28594
  onEnable() {
@@ -28233,11 +28733,16 @@ function startAgentStream(event, activeChildParents) {
28233
28733
  ...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
28234
28734
  };
28235
28735
  const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
28736
+ const attachmentCache = createStrandsAttachmentCache();
28737
+ const input = processStrandsInputAttachments(
28738
+ event.arguments[0],
28739
+ attachmentCache
28740
+ );
28236
28741
  const span = parentSpan ? withCurrent(
28237
28742
  parentSpan,
28238
28743
  () => startSpan({
28239
28744
  event: {
28240
- input: event.arguments[0],
28745
+ input,
28241
28746
  metadata
28242
28747
  },
28243
28748
  name: formatAgentSpanName(agent),
@@ -28245,7 +28750,7 @@ function startAgentStream(event, activeChildParents) {
28245
28750
  })
28246
28751
  ) : startSpan({
28247
28752
  event: {
28248
- input: event.arguments[0],
28753
+ input,
28249
28754
  metadata
28250
28755
  },
28251
28756
  name: formatAgentSpanName(agent),
@@ -28253,6 +28758,7 @@ function startAgentStream(event, activeChildParents) {
28253
28758
  });
28254
28759
  return {
28255
28760
  activeTools: /* @__PURE__ */ new Map(),
28761
+ attachmentCache,
28256
28762
  finalized: false,
28257
28763
  metadata,
28258
28764
  span,
@@ -28268,11 +28774,12 @@ function startMultiAgentStream(event, operation, activeChildParents) {
28268
28774
  ...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
28269
28775
  };
28270
28776
  const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
28777
+ const input = processStrandsInputAttachments(event.arguments[0]);
28271
28778
  const span = parentSpan ? withCurrent(
28272
28779
  parentSpan,
28273
28780
  () => startSpan({
28274
28781
  event: {
28275
- input: event.arguments[0],
28782
+ input,
28276
28783
  metadata
28277
28784
  },
28278
28785
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -28280,7 +28787,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
28280
28787
  })
28281
28788
  ) : startSpan({
28282
28789
  event: {
28283
- input: event.arguments[0],
28790
+ input,
28284
28791
  metadata
28285
28792
  },
28286
28793
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -28389,7 +28896,10 @@ function startModelSpan(state, event) {
28389
28896
  state.span,
28390
28897
  () => startSpan({
28391
28898
  event: {
28392
- input: Array.isArray(event.agent?.messages) ? event.agent.messages : void 0,
28899
+ input: Array.isArray(event.agent?.messages) ? processStrandsInputAttachments(
28900
+ event.agent.messages,
28901
+ state.attachmentCache
28902
+ ) : void 0,
28393
28903
  metadata
28394
28904
  },
28395
28905
  name: formatModelSpanName(model),
@@ -28603,6 +29113,7 @@ function finalizeAgentStream(state, error, output) {
28603
29113
  ...output !== void 0 ? { output } : {}
28604
29114
  });
28605
29115
  state.span.end();
29116
+ state.attachmentCache.strings.clear();
28606
29117
  }
28607
29118
  function finalizeMultiAgentStream(state, activeChildParents, error, output) {
28608
29119
  if (state.finalized) {
@@ -28749,6 +29260,166 @@ function extractNodeResultOutput(result) {
28749
29260
  }
28750
29261
  return result;
28751
29262
  }
29263
+ var STRANDS_MEDIA_TYPES = {
29264
+ png: "image/png",
29265
+ jpg: "image/jpeg",
29266
+ jpeg: "image/jpeg",
29267
+ gif: "image/gif",
29268
+ webp: "image/webp",
29269
+ mkv: "video/x-matroska",
29270
+ mov: "video/quicktime",
29271
+ mp4: "video/mp4",
29272
+ webm: "video/webm",
29273
+ flv: "video/x-flv",
29274
+ mpeg: "video/mpeg",
29275
+ mpg: "video/mpeg",
29276
+ wmv: "video/x-ms-wmv",
29277
+ "3gp": "video/3gpp",
29278
+ pdf: "application/pdf",
29279
+ csv: "text/csv",
29280
+ doc: "application/msword",
29281
+ docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
29282
+ xls: "application/vnd.ms-excel",
29283
+ xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
29284
+ html: "text/html",
29285
+ txt: "text/plain",
29286
+ md: "text/markdown",
29287
+ json: "application/json",
29288
+ xml: "application/xml"
29289
+ };
29290
+ function createStrandsAttachmentCache() {
29291
+ return {
29292
+ objects: /* @__PURE__ */ new WeakMap(),
29293
+ strings: new LRUCache({
29294
+ max: MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES
29295
+ })
29296
+ };
29297
+ }
29298
+ function processStrandsInputAttachments(input, cache = createStrandsAttachmentCache()) {
29299
+ try {
29300
+ return processStrandsInputNode(input, cache);
29301
+ } catch (error) {
29302
+ logInstrumentationError5("Strands Agent SDK input attachments", error);
29303
+ return input;
29304
+ }
29305
+ }
29306
+ function processStrandsInputNode(value, cache) {
29307
+ if (value instanceof BaseAttachment) {
29308
+ return value;
29309
+ }
29310
+ if (Array.isArray(value)) {
29311
+ return value.map((child) => processStrandsInputNode(child, cache));
29312
+ }
29313
+ if (!isObject(value)) {
29314
+ return value;
29315
+ }
29316
+ const directMedia = processDirectStrandsMediaBlock(value, cache);
29317
+ if (directMedia !== void 0) {
29318
+ return directMedia;
29319
+ }
29320
+ const wrappedMedia = processWrappedStrandsMediaBlock(value, cache);
29321
+ if (wrappedMedia !== void 0) {
29322
+ return wrappedMedia;
29323
+ }
29324
+ if (value.type === "message" && Array.isArray(value.content)) {
29325
+ return {
29326
+ role: value.role,
29327
+ content: value.content.map(
29328
+ (child) => processStrandsInputNode(child, cache)
29329
+ ),
29330
+ ...value.metadata !== void 0 ? { metadata: value.metadata } : {}
29331
+ };
29332
+ }
29333
+ if (typeof value.toJSON === "function") {
29334
+ return processStrandsInputNode(value.toJSON(), cache);
29335
+ }
29336
+ return Object.fromEntries(
29337
+ Object.entries(value).map(([key, child]) => [
29338
+ key,
29339
+ processStrandsInputNode(child, cache)
29340
+ ])
29341
+ );
29342
+ }
29343
+ function processDirectStrandsMediaBlock(block, cache) {
29344
+ if (!isStrandsMediaBlock(block)) {
29345
+ return void 0;
29346
+ }
29347
+ const mediaKey = block.type === "imageBlock" ? "image" : block.type === "videoBlock" ? "video" : "document";
29348
+ return createStrandsMediaAttachment(mediaKey, block, cache);
29349
+ }
29350
+ function isStrandsMediaBlock(block) {
29351
+ return (block.type === "imageBlock" || block.type === "videoBlock" || block.type === "documentBlock") && typeof block.format === "string" && isObject(block.source);
29352
+ }
29353
+ function processWrappedStrandsMediaBlock(block, cache) {
29354
+ for (const mediaKey of ["image", "video", "document"]) {
29355
+ const media = block[mediaKey];
29356
+ if (!Object.hasOwn(block, mediaKey) || !isObject(media)) {
29357
+ continue;
29358
+ }
29359
+ const processed = createStrandsMediaAttachment(mediaKey, media, cache);
29360
+ if (processed !== void 0) {
29361
+ return processed;
29362
+ }
29363
+ }
29364
+ return void 0;
29365
+ }
29366
+ function createStrandsMediaAttachment(mediaKey, media, cache) {
29367
+ const format = media.format;
29368
+ const source = media.source;
29369
+ if (typeof format !== "string" || !isObject(source) || !Object.hasOwn(source, "bytes")) {
29370
+ return void 0;
29371
+ }
29372
+ const contentType = STRANDS_MEDIA_TYPES[format.toLowerCase()];
29373
+ if (!contentType) {
29374
+ return void 0;
29375
+ }
29376
+ const filename = mediaKey === "document" && typeof media.name === "string" && media.name.length > 0 ? media.name : `${mediaKey}.${format.toLowerCase()}`;
29377
+ const attachment = getOrCreateStrandsAttachment(
29378
+ source.bytes,
29379
+ filename,
29380
+ contentType,
29381
+ cache
29382
+ );
29383
+ if (!attachment) {
29384
+ return void 0;
29385
+ }
29386
+ const { type: _type, ...serializedMedia } = media;
29387
+ const { type: _sourceType, ...serializedSource } = source;
29388
+ return {
29389
+ [mediaKey]: {
29390
+ ...serializedMedia,
29391
+ source: {
29392
+ ...serializedSource,
29393
+ bytes: attachment
29394
+ }
29395
+ }
29396
+ };
29397
+ }
29398
+ function getOrCreateStrandsAttachment(data, filename, contentType, cache) {
29399
+ const key = `${contentType}\0${filename}`;
29400
+ const attachments = typeof data === "string" ? cache.strings.get(data) : isObject(data) ? cache.objects.get(data) : void 0;
29401
+ const cached = attachments?.get(key);
29402
+ if (cached) {
29403
+ return cached;
29404
+ }
29405
+ const blob = convertDataToBlob(data, contentType);
29406
+ if (!blob) {
29407
+ return void 0;
29408
+ }
29409
+ const attachment = new Attachment({
29410
+ data: blob,
29411
+ filename,
29412
+ contentType
29413
+ });
29414
+ const updatedAttachments = attachments ?? /* @__PURE__ */ new Map();
29415
+ updatedAttachments.set(key, attachment);
29416
+ if (typeof data === "string") {
29417
+ cache.strings.set(data, updatedAttachments);
29418
+ } else if (isObject(data)) {
29419
+ cache.objects.set(data, updatedAttachments);
29420
+ }
29421
+ return attachment;
29422
+ }
28752
29423
  function normalizeContentBlocks(blocks) {
28753
29424
  const text = blocks.map((block) => typeof block.text === "string" ? block.text : void 0).filter((part) => Boolean(part)).join("");
28754
29425
  return text.length > 0 ? text : blocks;
@@ -28878,6 +29549,7 @@ var BraintrustPlugin = class extends BasePlugin {
28878
29549
  gitHubCopilotPlugin = null;
28879
29550
  fluePlugin = null;
28880
29551
  langChainPlugin = null;
29552
+ langSmithPlugin = null;
28881
29553
  piCodingAgentPlugin = null;
28882
29554
  strandsAgentSDKPlugin = null;
28883
29555
  constructor(config = {}) {
@@ -28974,6 +29646,12 @@ var BraintrustPlugin = class extends BasePlugin {
28974
29646
  this.langChainPlugin = new LangChainPlugin();
28975
29647
  this.langChainPlugin.enable();
28976
29648
  }
29649
+ if (integrations.langsmith !== false) {
29650
+ this.langSmithPlugin = new LangSmithPlugin({
29651
+ skipLangChainRuns: integrations.langchain !== false
29652
+ });
29653
+ this.langSmithPlugin.enable();
29654
+ }
28977
29655
  }
28978
29656
  onDisable() {
28979
29657
  if (this.openaiPlugin) {
@@ -29064,6 +29742,10 @@ var BraintrustPlugin = class extends BasePlugin {
29064
29742
  this.langChainPlugin.disable();
29065
29743
  this.langChainPlugin = null;
29066
29744
  }
29745
+ if (this.langSmithPlugin) {
29746
+ this.langSmithPlugin.disable();
29747
+ this.langSmithPlugin = null;
29748
+ }
29067
29749
  }
29068
29750
  };
29069
29751
 
@@ -29142,9 +29824,6 @@ var EveBridge = class {
29142
29824
  this.state = state;
29143
29825
  }
29144
29826
  eventQueuesBySession = /* @__PURE__ */ new Map();
29145
- sessionsById = new LRUCache({
29146
- max: MAX_EVE_CACHE_ENTRIES
29147
- });
29148
29827
  completedToolKeys = new LRUCache({
29149
29828
  max: MAX_EVE_CACHE_ENTRIES
29150
29829
  });
@@ -29311,7 +29990,7 @@ var EveBridge = class {
29311
29990
  async handleEvent(event, ctx, hookMetadata) {
29312
29991
  switch (event.type) {
29313
29992
  case "session.started":
29314
- await this.handleSessionStarted(event, ctx, hookMetadata);
29993
+ this.handleSessionStarted(event, ctx, hookMetadata);
29315
29994
  return true;
29316
29995
  case "turn.started":
29317
29996
  await this.handleTurnStarted(event, ctx, hookMetadata);
@@ -29347,22 +30026,22 @@ var EveBridge = class {
29347
30026
  this.handleStepFailed(event, ctx);
29348
30027
  return true;
29349
30028
  case "turn.completed":
29350
- await this.handleTurnCompleted(event, ctx);
30029
+ this.handleTurnCompleted(event, ctx);
29351
30030
  return true;
29352
30031
  case "turn.failed":
29353
- await this.handleTurnFailed(event, ctx);
30032
+ this.handleTurnFailed(event, ctx);
29354
30033
  return true;
29355
30034
  case "session.failed":
29356
- await this.handleSessionFailed(event, ctx);
30035
+ this.handleSessionFailed(event, ctx);
29357
30036
  return true;
29358
30037
  case "session.completed":
29359
- await this.handleSessionCompleted(event, ctx);
30038
+ this.handleSessionCompleted(event, ctx);
29360
30039
  return true;
29361
30040
  default:
29362
30041
  return false;
29363
30042
  }
29364
30043
  }
29365
- async handleSessionStarted(event, ctx, hookMetadata) {
30044
+ handleSessionStarted(event, ctx, hookMetadata) {
29366
30045
  const sessionId = sessionIdFromContext(ctx);
29367
30046
  if (!sessionId) {
29368
30047
  return;
@@ -29378,7 +30057,6 @@ var EveBridge = class {
29378
30057
  metadata: { ...normalized.metadata, ...metadata }
29379
30058
  };
29380
30059
  });
29381
- await this.ensureSession(sessionId, ctx, metadata, eventTime2(event));
29382
30060
  for (const [key, turn] of this.turnsByKey) {
29383
30061
  if (!key.startsWith(`${sessionId}:`)) {
29384
30062
  continue;
@@ -29396,21 +30074,19 @@ var EveBridge = class {
29396
30074
  if (!sessionId) {
29397
30075
  return;
29398
30076
  }
29399
- const session = await this.ensureSession(
29400
- sessionId,
29401
- ctx,
29402
- hookMetadata ?? {},
29403
- eventTime2(event)
29404
- );
29405
30077
  const key = turnKey2(sessionId, event.data.turnId);
29406
- const metadata = { ...session.metadata };
30078
+ const metadata = {
30079
+ ...readEveTraceState(this.state).metadata,
30080
+ ...hookMetadata ?? {},
30081
+ "eve.session_id": sessionId
30082
+ };
29407
30083
  const existing = this.turnsByKey.get(key);
29408
30084
  if (existing) {
29409
30085
  existing.metadata = { ...existing.metadata, ...metadata };
29410
30086
  existing.span.log({ metadata: existing.metadata });
29411
30087
  return;
29412
30088
  }
29413
- const span = await this.startTurnSpan(session, event, metadata);
30089
+ const span = await this.startTurnSpan(sessionId, event, ctx, metadata);
29414
30090
  span.log({ metadata });
29415
30091
  this.turnsByKey.set(key, {
29416
30092
  key,
@@ -29448,10 +30124,7 @@ var EveBridge = class {
29448
30124
  this.markStepEnded(event.data.turnId, event.data.stepIndex);
29449
30125
  }
29450
30126
  const stepOrdinal = this.stepOrdinal(event);
29451
- const metadata = {
29452
- ...turn.metadata,
29453
- ...this.sessionsById.get(sessionId)?.metadata ?? {}
29454
- };
30127
+ const metadata = { ...turn.metadata };
29455
30128
  const input = consumeCapturedEveModelInput(
29456
30129
  this.state,
29457
30130
  sessionId,
@@ -29546,6 +30219,28 @@ var EveBridge = class {
29546
30219
  if (!step) {
29547
30220
  return;
29548
30221
  }
30222
+ const toolCallsById = /* @__PURE__ */ new Map();
30223
+ if (Array.isArray(step.output) && isObject(step.output[0])) {
30224
+ const message = step.output[0]["message"];
30225
+ if (isObject(message) && Array.isArray(message["tool_calls"])) {
30226
+ for (const toolCall of message["tool_calls"]) {
30227
+ if (isObject(toolCall) && typeof toolCall["id"] === "string") {
30228
+ toolCallsById.set(toolCall["id"], toolCall);
30229
+ }
30230
+ }
30231
+ }
30232
+ }
30233
+ for (const action of traceActions) {
30234
+ const name = action.kind === "tool-call" ? action.toolName : action.subagentName ?? action.name ?? "agent";
30235
+ toolCallsById.set(action.callId, {
30236
+ function: {
30237
+ arguments: JSON.stringify(action.input),
30238
+ name
30239
+ },
30240
+ id: action.callId,
30241
+ type: "function"
30242
+ });
30243
+ }
29549
30244
  step.output = [
29550
30245
  {
29551
30246
  finish_reason: "tool_calls",
@@ -29553,17 +30248,7 @@ var EveBridge = class {
29553
30248
  message: {
29554
30249
  content: null,
29555
30250
  role: "assistant",
29556
- tool_calls: traceActions.map((action) => {
29557
- const name = action.kind === "tool-call" ? action.toolName : action.subagentName ?? action.name ?? "agent";
29558
- return {
29559
- function: {
29560
- arguments: JSON.stringify(action.input),
29561
- name
29562
- },
29563
- id: action.callId,
29564
- type: "function"
29565
- };
29566
- })
30251
+ tool_calls: [...toolCallsById.values()]
29567
30252
  }
29568
30253
  }
29569
30254
  ];
@@ -29810,17 +30495,11 @@ var EveBridge = class {
29810
30495
  )
29811
30496
  });
29812
30497
  }
29813
- async handleSessionFailed(event, ctx) {
30498
+ handleSessionFailed(event, ctx) {
29814
30499
  const sessionId = event.data.sessionId || sessionIdFromContext(ctx);
29815
30500
  if (!sessionId) {
29816
30501
  return;
29817
30502
  }
29818
- const session = await this.ensureSession(
29819
- sessionId,
29820
- ctx,
29821
- {},
29822
- eventTime2(event)
29823
- );
29824
30503
  const error = errorFromMessage(
29825
30504
  event.data.message,
29826
30505
  event.data.code,
@@ -29837,29 +30516,20 @@ var EveBridge = class {
29837
30516
  }
29838
30517
  for (const [key, tool] of this.toolsByCallKey) {
29839
30518
  if (key.startsWith(`${sessionId}:`)) {
29840
- const endTime2 = eventTime2(event);
30519
+ const endTime = eventTime2(event);
29841
30520
  if (!tool.endedByTurn) {
29842
30521
  tool.span.log({ metadata: tool.metadata });
29843
- tool.span.end(endTime2 === void 0 ? void 0 : { endTime: endTime2 });
30522
+ tool.span.end(endTime === void 0 ? void 0 : { endTime });
29844
30523
  tool.endedByTurn = true;
29845
30524
  }
29846
30525
  }
29847
30526
  }
29848
- session.span.log({ error });
29849
- const endTime = eventTime2(event);
29850
- session.span.end(endTime === void 0 ? void 0 : { endTime });
29851
30527
  }
29852
- async handleSessionCompleted(event, ctx) {
30528
+ handleSessionCompleted(event, ctx) {
29853
30529
  const sessionId = sessionIdFromContext(ctx);
29854
30530
  if (!sessionId) {
29855
30531
  return;
29856
30532
  }
29857
- const session = await this.ensureSession(
29858
- sessionId,
29859
- ctx,
29860
- {},
29861
- eventTime2(event)
29862
- );
29863
30533
  for (const [key, turn] of this.turnsByKey) {
29864
30534
  if (!key.startsWith(`${sessionId}:`)) {
29865
30535
  continue;
@@ -29870,82 +30540,29 @@ var EveBridge = class {
29870
30540
  }
29871
30541
  for (const [key, tool] of this.toolsByCallKey) {
29872
30542
  if (key.startsWith(`${sessionId}:`) && !tool.endedByTurn) {
29873
- const endTime2 = eventTime2(event);
30543
+ const endTime = eventTime2(event);
29874
30544
  tool.span.log({ metadata: tool.metadata });
29875
- tool.span.end(endTime2 === void 0 ? void 0 : { endTime: endTime2 });
30545
+ tool.span.end(endTime === void 0 ? void 0 : { endTime });
29876
30546
  tool.endedByTurn = true;
29877
30547
  }
29878
30548
  }
29879
- session.span.log({ metadata: session.metadata });
29880
- const endTime = eventTime2(event);
29881
- session.span.end(endTime === void 0 ? void 0 : { endTime });
29882
- }
29883
- async ensureSession(sessionId, ctx, metadata, startTime) {
29884
- metadata = {
29885
- ...readEveTraceState(this.state).metadata,
29886
- ...metadata
29887
- };
29888
- const existing = this.sessionsById.get(sessionId);
29889
- if (existing) {
29890
- existing.metadata = { ...existing.metadata, ...metadata };
29891
- existing.span.log({ metadata: existing.metadata });
29892
- return existing;
29893
- }
29894
- const lineage = parentLineageFromContext(ctx);
29895
- const parentSubagent = lineage ? this.toolsByCallKey.get(toolKey3(lineage.sessionId, lineage.callId)) : void 0;
29896
- const activeParent = currentSpan();
29897
- const [
29898
- { rowId: eventId, spanId },
29899
- parentSubagentSpanId,
29900
- fallbackRootSpanId
29901
- ] = await Promise.all([
29902
- generateEveIds("session", sessionId),
29903
- lineage ? spanIdForSubagent(lineage.sessionId, lineage.callId) : Promise.resolve(void 0),
29904
- lineage ? rootSpanIdForSession(lineage.rootSessionId) : rootSpanIdForSession(sessionId)
29905
- ]);
29906
- const span = await this.startEveSpan({
29907
- event: {
29908
- id: eventId,
29909
- metadata
29910
- },
29911
- name: "eve.session",
29912
- parentSpanIds: lineage && parentSubagentSpanId ? {
29913
- rootSpanId: parentSubagent?.span.rootSpanId ?? fallbackRootSpanId,
29914
- spanId: parentSubagentSpanId
29915
- } : !Object.is(activeParent, NOOP_SPAN) ? {
29916
- rootSpanId: activeParent.rootSpanId,
29917
- spanId: activeParent.spanId
29918
- } : {
29919
- parentSpanIds: [],
29920
- rootSpanId: fallbackRootSpanId
29921
- },
29922
- spanAttributes: { type: "task" /* TASK */ },
29923
- spanId,
29924
- startTime
29925
- });
29926
- span.log({ metadata });
29927
- const session = { metadata, sessionId, span };
29928
- this.sessionsById.set(sessionId, session);
29929
- return session;
29930
30549
  }
29931
30550
  async ensureTurn(event, ctx, hookMetadata) {
29932
30551
  const sessionId = sessionIdFromContext(ctx);
29933
30552
  if (!sessionId) {
29934
30553
  return void 0;
29935
30554
  }
29936
- const session = await this.ensureSession(
29937
- sessionId,
29938
- ctx,
29939
- hookMetadata ?? {},
29940
- eventTime2(event)
29941
- );
29942
30555
  const key = turnKey2(sessionId, event.data.turnId);
29943
30556
  const existing = this.turnsByKey.get(key);
29944
30557
  if (existing) {
29945
30558
  return existing;
29946
30559
  }
29947
- const metadata = { ...session.metadata };
29948
- const span = await this.startTurnSpan(session, event, metadata);
30560
+ const metadata = {
30561
+ ...readEveTraceState(this.state).metadata,
30562
+ ...hookMetadata ?? {},
30563
+ "eve.session_id": sessionId
30564
+ };
30565
+ const span = await this.startTurnSpan(sessionId, event, ctx, metadata);
29949
30566
  span.log({ metadata });
29950
30567
  const state = {
29951
30568
  key,
@@ -30132,22 +30749,35 @@ var EveBridge = class {
30132
30749
  this.toolsByCallKey.set(toolKey3(sessionId, result.callId), state);
30133
30750
  return state;
30134
30751
  }
30135
- async startTurnSpan(session, event, metadata) {
30136
- const { rowId: eventId, spanId } = await generateEveIds(
30137
- "turn",
30138
- session.sessionId,
30139
- event.data.turnId
30140
- );
30752
+ async startTurnSpan(sessionId, event, ctx, metadata) {
30753
+ const session = isObject(ctx) ? ctx["session"] : void 0;
30754
+ const parent = isObject(session) ? session["parent"] : void 0;
30755
+ const parentTurn = isObject(parent) ? parent["turn"] : void 0;
30756
+ const parentLineage = isObject(parent) && typeof parent["callId"] === "string" && typeof parent["sessionId"] === "string" && isObject(parentTurn) && typeof parentTurn["id"] === "string" ? {
30757
+ callId: parent["callId"],
30758
+ sessionId: parent["sessionId"],
30759
+ turnId: parentTurn["id"]
30760
+ } : void 0;
30761
+ const [{ rowId: eventId, spanId }, rootSpanId, parentSpanId] = await Promise.all([
30762
+ generateEveIds("turn", sessionId, event.data.turnId),
30763
+ deterministicEveId(
30764
+ "eve:root",
30765
+ parentLineage?.sessionId ?? sessionId,
30766
+ parentLineage?.turnId ?? event.data.turnId
30767
+ ),
30768
+ parentLineage ? deterministicEveId(
30769
+ "eve:subagent",
30770
+ parentLineage.sessionId,
30771
+ parentLineage.callId
30772
+ ) : Promise.resolve(void 0)
30773
+ ]);
30141
30774
  return await this.startEveSpan({
30142
30775
  event: {
30143
30776
  id: eventId,
30144
30777
  metadata
30145
30778
  },
30146
30779
  name: "eve.turn",
30147
- parentSpanIds: {
30148
- rootSpanId: session.span.rootSpanId,
30149
- spanId: session.span.spanId
30150
- },
30780
+ parentSpanIds: parentSpanId ? { rootSpanId, spanId: parentSpanId } : { parentSpanIds: [], rootSpanId },
30151
30781
  spanAttributes: { type: "task" /* TASK */ },
30152
30782
  spanId,
30153
30783
  startTime: eventTime2(event)
@@ -30208,7 +30838,6 @@ var EveBridge = class {
30208
30838
  }
30209
30839
  cleanupSession(sessionId) {
30210
30840
  const keyPrefix = `${sessionId}:`;
30211
- this.sessionsById.delete(sessionId);
30212
30841
  for (const key of this.turnsByKey.keys()) {
30213
30842
  if (key.startsWith(keyPrefix)) {
30214
30843
  this.turnsByKey.delete(key);
@@ -30399,7 +31028,7 @@ function modelMetadataFromRuntime(runtime) {
30399
31028
  return {};
30400
31029
  }
30401
31030
  const modelId = runtime["modelId"];
30402
- return typeof modelId === "string" ? modelMetadataFromModelId(modelId) : {};
31031
+ return typeof modelId === "string" && !modelId.trim().startsWith("dynamic:") ? modelMetadataFromModelId(modelId) : {};
30403
31032
  }
30404
31033
  function modelMetadataFromModelId(modelId) {
30405
31034
  const normalized = modelId.trim();
@@ -30432,26 +31061,6 @@ function toolMetadataFromTurn(turn) {
30432
31061
  const { model: _model, provider: _provider, ...metadata } = turn.metadata;
30433
31062
  return metadata;
30434
31063
  }
30435
- function parentLineageFromContext(ctx) {
30436
- if (!isObject(ctx)) {
30437
- return void 0;
30438
- }
30439
- const session = ctx.session;
30440
- if (!isObject(session)) {
30441
- return void 0;
30442
- }
30443
- const parent = session["parent"];
30444
- if (!isObject(parent)) {
30445
- return void 0;
30446
- }
30447
- const callId = parent["callId"];
30448
- const rootSessionId = parent["rootSessionId"];
30449
- const sessionId = parent["sessionId"];
30450
- if (typeof callId !== "string" || typeof rootSessionId !== "string" || typeof sessionId !== "string") {
30451
- return void 0;
30452
- }
30453
- return { callId, rootSessionId, sessionId };
30454
- }
30455
31064
  function isToolCallAction(action) {
30456
31065
  return isObject(action) && action["kind"] === "tool-call" && typeof action["callId"] === "string" && typeof action["toolName"] === "string" && isObject(action["input"]);
30457
31066
  }
@@ -30507,9 +31116,6 @@ function turnKey2(sessionId, turnId) {
30507
31116
  function toolKey3(sessionId, callId) {
30508
31117
  return `${sessionId}:${callId}`;
30509
31118
  }
30510
- async function rootSpanIdForSession(sessionId) {
30511
- return deterministicEveId("eve:root", sessionId);
30512
- }
30513
31119
  async function generateEveIds(kind, ...parts) {
30514
31120
  const [rowId, spanId] = await Promise.all([
30515
31121
  deterministicEveId(`eve:row:${kind}`, ...parts),
@@ -30517,9 +31123,6 @@ async function generateEveIds(kind, ...parts) {
30517
31123
  ]);
30518
31124
  return { rowId, spanId };
30519
31125
  }
30520
- async function spanIdForSubagent(sessionId, callId) {
30521
- return deterministicEveId("eve:subagent", sessionId, callId);
30522
- }
30523
31126
  async function deterministicEveId(...parts) {
30524
31127
  const data = new TextEncoder().encode(
30525
31128
  parts.map((part) => `${part.length}:${part}`).join("\0")
@@ -30591,7 +31194,8 @@ var envIntegrationAliases = {
30591
31194
  langchain: "langchain",
30592
31195
  "langchain-js": "langchain",
30593
31196
  "@langchain": "langchain",
30594
- langgraph: "langgraph"
31197
+ langgraph: "langgraph",
31198
+ langsmith: "langsmith"
30595
31199
  };
30596
31200
  function getDefaultInstrumentationIntegrations() {
30597
31201
  return {
@@ -30622,6 +31226,7 @@ function getDefaultInstrumentationIntegrations() {
30622
31226
  gitHubCopilot: true,
30623
31227
  langchain: true,
30624
31228
  langgraph: true,
31229
+ langsmith: true,
30625
31230
  piCodingAgent: true,
30626
31231
  strandsAgentSDK: true
30627
31232
  };