braintrust 3.22.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.
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 -652
  5. package/dev/dist/index.mjs +736 -34
  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 -203
  30. package/dist/browser.mjs +1098 -203
  31. package/dist/{chunk-KMGUTPB7.mjs → chunk-36IPYKMG.mjs} +20 -1
  32. package/dist/{chunk-BFGIH2ZJ.js → chunk-CDIKAHDZ.js} +21 -2
  33. package/dist/{chunk-MWVVR5LR.js → chunk-FZWPFCVE.js} +1506 -820
  34. package/dist/{chunk-ZG2O3XVF.mjs → chunk-IXL4PMY4.mjs} +719 -33
  35. package/dist/cli.js +737 -35
  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 -203
  39. package/dist/edge-light.mjs +1098 -203
  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 -181
  47. package/dist/instrumentation/index.mjs +788 -181
  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 -203
  53. package/dist/workerd.mjs +1098 -203
  54. package/package.json +1 -1
@@ -4317,7 +4317,7 @@ var DiskCache = class {
4317
4317
  }
4318
4318
  };
4319
4319
 
4320
- // src/prompt-cache/lru-cache.ts
4320
+ // src/lru-cache.ts
4321
4321
  var LRUCache = class {
4322
4322
  cache;
4323
4323
  maxSize;
@@ -5514,25 +5514,46 @@ var HTTPConnection = class _HTTPConnection {
5514
5514
  })
5515
5515
  );
5516
5516
  }
5517
- async post(path, params, config) {
5517
+ async post(path, params, config, retries = 0) {
5518
5518
  const { headers, ...rest } = config || {};
5519
5519
  const this_fetch = this.fetch;
5520
5520
  const this_base_url = this.base_url;
5521
5521
  const this_headers = this.headers;
5522
- return await checkResponse(
5523
- await this_fetch(_urljoin(this_base_url, path), {
5524
- method: "POST",
5525
- headers: {
5526
- Accept: "application/json",
5527
- "Content-Type": "application/json",
5528
- ...this_headers,
5529
- ...headers
5530
- },
5531
- body: typeof params === "string" ? params : params ? JSON.stringify(params) : void 0,
5532
- keepalive: true,
5533
- ...rest
5534
- })
5535
- );
5522
+ const tries = retries + 1;
5523
+ for (let i = 0; i < tries; i++) {
5524
+ try {
5525
+ return await checkResponse(
5526
+ await this_fetch(_urljoin(this_base_url, path), {
5527
+ method: "POST",
5528
+ headers: {
5529
+ Accept: "application/json",
5530
+ "Content-Type": "application/json",
5531
+ ...this_headers,
5532
+ ...headers
5533
+ },
5534
+ body: typeof params === "string" ? params : params ? JSON.stringify(params) : void 0,
5535
+ keepalive: true,
5536
+ ...rest
5537
+ })
5538
+ );
5539
+ } catch (error) {
5540
+ if (config?.signal?.aborted) {
5541
+ throw getAbortReason(config.signal);
5542
+ }
5543
+ if (i === tries - 1 || !isRetryableHTTPError(error)) {
5544
+ throw error;
5545
+ }
5546
+ debugLogger.debug(
5547
+ `Retrying API request ${path} after ${formatHTTPError(error)}`
5548
+ );
5549
+ const sleepTimeMs = HTTP_RETRY_BASE_SLEEP_TIME_S * 1e3 * 2 ** i + Math.random() * HTTP_RETRY_JITTER_MS;
5550
+ debugLogger.info(
5551
+ `Sleeping for ${sleepTimeMs}ms before retrying API request`
5552
+ );
5553
+ await waitForRetry(sleepTimeMs, config?.signal);
5554
+ }
5555
+ }
5556
+ throw new Error("Unexpected retry state");
5536
5557
  }
5537
5558
  async get_json(object_type, args = void 0, retries = 0) {
5538
5559
  const tries = retries + 1;
@@ -6454,6 +6475,45 @@ function now() {
6454
6475
  var DEFAULT_FLUSH_BACKPRESSURE_BYTES = 10 * 1024 * 1024;
6455
6476
  var BACKGROUND_LOGGER_BASE_SLEEP_TIME_S = 1;
6456
6477
  var HTTP_RETRY_BASE_SLEEP_TIME_S = 1;
6478
+ var HTTP_RETRY_JITTER_MS = 200;
6479
+ var BTQL_HTTP_RETRIES = 3;
6480
+ var RETRYABLE_HTTP_STATUS_CODES = /* @__PURE__ */ new Set([500, 502, 503, 504]);
6481
+ function isRetryableHTTPError(error) {
6482
+ return !(error instanceof FailedHTTPResponse) || RETRYABLE_HTTP_STATUS_CODES.has(error.status);
6483
+ }
6484
+ function formatHTTPError(error) {
6485
+ if (error instanceof FailedHTTPResponse) {
6486
+ return `${error.status} ${error.text}`;
6487
+ }
6488
+ return error instanceof Error ? error.message : String(error);
6489
+ }
6490
+ function getAbortReason(signal) {
6491
+ return signal.reason ?? new Error("Request aborted");
6492
+ }
6493
+ async function waitForRetry(delayMs, signal) {
6494
+ if (!signal) {
6495
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
6496
+ return;
6497
+ }
6498
+ if (signal.aborted) {
6499
+ throw getAbortReason(signal);
6500
+ }
6501
+ await new Promise((resolve, reject) => {
6502
+ const onAbort = () => {
6503
+ clearTimeout(timeout);
6504
+ signal.removeEventListener("abort", onAbort);
6505
+ reject(getAbortReason(signal));
6506
+ };
6507
+ const timeout = setTimeout(() => {
6508
+ signal.removeEventListener("abort", onAbort);
6509
+ resolve();
6510
+ }, delayMs);
6511
+ signal.addEventListener("abort", onAbort, { once: true });
6512
+ if (signal.aborted) {
6513
+ onAbort();
6514
+ }
6515
+ });
6516
+ }
6457
6517
  var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
6458
6518
  apiConn;
6459
6519
  queue;
@@ -7405,15 +7465,15 @@ function parentSpanIdsUsable(spanId, rootSpanId) {
7405
7465
  return Boolean(spanId) && Boolean(rootSpanId);
7406
7466
  }
7407
7467
  function logError(span, error) {
7408
- let errorMessage = "<error>";
7468
+ let errorMessage2 = "<error>";
7409
7469
  let stackTrace = "";
7410
7470
  if (error instanceof Error) {
7411
- errorMessage = error.message;
7471
+ errorMessage2 = error.message;
7412
7472
  stackTrace = error.stack || "";
7413
7473
  } else {
7414
- errorMessage = String(error);
7474
+ errorMessage2 = String(error);
7415
7475
  }
7416
- span.log({ error: `${errorMessage}
7476
+ span.log({ error: `${errorMessage2}
7417
7477
 
7418
7478
  ${stackTrace}` });
7419
7479
  }
@@ -7754,7 +7814,8 @@ var ObjectFetcher = class {
7754
7814
  version: this.pinnedVersion
7755
7815
  } : {}
7756
7816
  },
7757
- { headers: { "Accept-Encoding": "gzip" } }
7817
+ { headers: { "Accept-Encoding": "gzip" } },
7818
+ BTQL_HTTP_RETRIES
7758
7819
  );
7759
7820
  const respJson = await resp.json();
7760
7821
  const mutate = this.mutateRecord;
@@ -27144,6 +27205,446 @@ function isBraintrustHandler(handler) {
27144
27205
  return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
27145
27206
  }
27146
27207
 
27208
+ // src/instrumentation/plugins/langsmith-channels.ts
27209
+ var langSmithChannels = defineChannels("langsmith", {
27210
+ createRun: channel({
27211
+ channelName: "Client.createRun",
27212
+ kind: "async"
27213
+ }),
27214
+ updateRun: channel({
27215
+ channelName: "Client.updateRun",
27216
+ kind: "async"
27217
+ }),
27218
+ batchIngestRuns: channel({
27219
+ channelName: "Client.batchIngestRuns",
27220
+ kind: "async"
27221
+ })
27222
+ });
27223
+
27224
+ // src/instrumentation/plugins/langsmith-plugin.ts
27225
+ var MAX_COMPLETED_RUNS = 1e4;
27226
+ var BLOCKED_METADATA_KEYS = /* @__PURE__ */ new Set([
27227
+ "__proto__",
27228
+ "constructor",
27229
+ "prototype",
27230
+ "usage_metadata"
27231
+ ]);
27232
+ var BLOCKED_METADATA_PREFIXES = ["__pregel_", "langgraph_", "lc_"];
27233
+ var LLM_SETTING_KEYS = [
27234
+ "temperature",
27235
+ "top_p",
27236
+ "max_tokens",
27237
+ "frequency_penalty",
27238
+ "presence_penalty",
27239
+ "stop",
27240
+ "response_format"
27241
+ ];
27242
+ var LangSmithPlugin = class extends BasePlugin {
27243
+ activeRuns = /* @__PURE__ */ new Map();
27244
+ completedRuns = new LRUCache({
27245
+ max: MAX_COMPLETED_RUNS
27246
+ });
27247
+ skipLangChainRuns;
27248
+ constructor(options = {}) {
27249
+ super();
27250
+ this.skipLangChainRuns = options.skipLangChainRuns ?? true;
27251
+ }
27252
+ onEnable() {
27253
+ const createChannel = langSmithChannels.createRun.tracingChannel();
27254
+ const createHandlers = {
27255
+ start: (event) => {
27256
+ this.containLifecycleFailure("createRun", () => {
27257
+ this.processCreate(event.arguments[0]);
27258
+ });
27259
+ }
27260
+ };
27261
+ createChannel.subscribe(createHandlers);
27262
+ this.unsubscribers.push(() => createChannel.unsubscribe(createHandlers));
27263
+ const updateChannel = langSmithChannels.updateRun.tracingChannel();
27264
+ const updateHandlers = {
27265
+ start: (event) => {
27266
+ this.containLifecycleFailure("updateRun", () => {
27267
+ this.processUpdate(event.arguments[0], event.arguments[1]);
27268
+ });
27269
+ }
27270
+ };
27271
+ updateChannel.subscribe(updateHandlers);
27272
+ this.unsubscribers.push(() => updateChannel.unsubscribe(updateHandlers));
27273
+ const batchChannel = langSmithChannels.batchIngestRuns.tracingChannel();
27274
+ const batchHandlers = {
27275
+ start: (event) => {
27276
+ this.containLifecycleFailure("batchIngestRuns", () => {
27277
+ this.processBatch(event.arguments[0]);
27278
+ });
27279
+ }
27280
+ };
27281
+ batchChannel.subscribe(batchHandlers);
27282
+ this.unsubscribers.push(() => batchChannel.unsubscribe(batchHandlers));
27283
+ }
27284
+ onDisable() {
27285
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
27286
+ for (const { span } of this.activeRuns.values()) {
27287
+ span.end();
27288
+ }
27289
+ this.activeRuns.clear();
27290
+ this.completedRuns.clear();
27291
+ }
27292
+ processBatch(batch) {
27293
+ if (!isRecord2(batch)) {
27294
+ return;
27295
+ }
27296
+ const creates = ownValue(batch, "runCreates");
27297
+ if (Array.isArray(creates)) {
27298
+ const parentFirst = [...creates].sort((left, right) => {
27299
+ const leftId = stringValue2(ownValue(left, "id"));
27300
+ const rightId = stringValue2(ownValue(right, "id"));
27301
+ const leftParent = stringValue2(ownValue(left, "parent_run_id"));
27302
+ const rightParent = stringValue2(ownValue(right, "parent_run_id"));
27303
+ if (leftParent && leftParent === rightId) {
27304
+ return 1;
27305
+ }
27306
+ if (rightParent && rightParent === leftId) {
27307
+ return -1;
27308
+ }
27309
+ return dottedOrderDepth(left) - dottedOrderDepth(right);
27310
+ });
27311
+ for (const run of parentFirst) {
27312
+ this.containLifecycleFailure("batchIngestRuns create", () => {
27313
+ this.processCreate(run);
27314
+ });
27315
+ }
27316
+ }
27317
+ const updates = ownValue(batch, "runUpdates");
27318
+ if (Array.isArray(updates)) {
27319
+ for (const run of updates) {
27320
+ this.containLifecycleFailure("batchIngestRuns update", () => {
27321
+ this.processUpdate(stringValue2(ownValue(run, "id")) ?? "", run);
27322
+ });
27323
+ }
27324
+ }
27325
+ }
27326
+ processCreate(run) {
27327
+ const id = stringValue2(ownValue(run, "id"));
27328
+ if (!id || this.completedRuns.get(id)) {
27329
+ return;
27330
+ }
27331
+ if (this.shouldSkipLangChainRun(run)) {
27332
+ this.completedRuns.set(id, true);
27333
+ return;
27334
+ }
27335
+ const active = this.activeRuns.get(id);
27336
+ if (active) {
27337
+ const previous = active.run;
27338
+ active.run = mergeRuns(previous, run);
27339
+ this.logRun(
27340
+ active.span,
27341
+ active.run,
27342
+ previous,
27343
+ timestampSeconds(ownValue(active.run, "end_time")) !== void 0 || errorMessage(ownValue(active.run, "error")) !== void 0
27344
+ );
27345
+ this.endIfComplete(id, active, active.run);
27346
+ return;
27347
+ }
27348
+ const span = this.startRunSpan(id, run);
27349
+ const activeRun = { run, span };
27350
+ this.activeRuns.set(id, activeRun);
27351
+ this.logRun(
27352
+ span,
27353
+ run,
27354
+ void 0,
27355
+ timestampSeconds(ownValue(run, "end_time")) !== void 0 || errorMessage(ownValue(run, "error")) !== void 0
27356
+ );
27357
+ this.endIfComplete(id, activeRun, run);
27358
+ }
27359
+ processUpdate(explicitId, run) {
27360
+ const id = stringValue2(explicitId) ?? stringValue2(ownValue(run, "id"));
27361
+ if (!id || this.completedRuns.get(id)) {
27362
+ return;
27363
+ }
27364
+ if (this.shouldSkipLangChainRun(run)) {
27365
+ const active2 = this.activeRuns.get(id);
27366
+ active2?.span.end();
27367
+ this.activeRuns.delete(id);
27368
+ this.completedRuns.set(id, true);
27369
+ return;
27370
+ }
27371
+ let active = this.activeRuns.get(id);
27372
+ if (!active) {
27373
+ const span = this.startRunSpan(id, run);
27374
+ active = { run, span };
27375
+ this.activeRuns.set(id, active);
27376
+ }
27377
+ const previous = active.run;
27378
+ active.run = mergeRuns(previous, run);
27379
+ this.logRun(active.span, active.run, previous, true);
27380
+ this.endIfComplete(id, active, active.run);
27381
+ }
27382
+ startRunSpan(id, run) {
27383
+ const traceId = stringValue2(ownValue(run, "trace_id")) ?? id;
27384
+ const parentId = stringValue2(ownValue(run, "parent_run_id")) ?? stringValue2(ownValue(ownValue(run, "parent_run"), "id"));
27385
+ const startTime = timestampSeconds(ownValue(run, "start_time"));
27386
+ return startSpan({
27387
+ name: stringValue2(ownValue(run, "name")) ?? "LangSmith run",
27388
+ spanId: id,
27389
+ parentSpanIds: {
27390
+ parentSpanIds: parentId ? [parentId] : [],
27391
+ rootSpanId: traceId
27392
+ },
27393
+ spanAttributes: {
27394
+ type: mapRunType(ownValue(run, "run_type"))
27395
+ },
27396
+ ...startTime === void 0 ? {} : { startTime },
27397
+ event: { id }
27398
+ });
27399
+ }
27400
+ logRun(span, run, previous, includeOutput) {
27401
+ const inputs = preferOwnValue(run, previous, "inputs");
27402
+ const outputs = preferOwnValue(run, previous, "outputs");
27403
+ const error = errorMessage(preferOwnValue(run, previous, "error"));
27404
+ const metadata = extractMetadata(run, previous);
27405
+ const tags = extractTags(preferOwnValue(run, previous, "tags"));
27406
+ const metrics = extractMetrics(run, previous);
27407
+ span.log({
27408
+ ...inputs === void 0 ? {} : { input: sanitizeLoggedValue(inputs) },
27409
+ ...includeOutput && outputs !== void 0 ? { output: sanitizeLoggedValue(outputs) } : {},
27410
+ ...error === void 0 ? {} : { error },
27411
+ ...metadata === void 0 ? {} : { metadata },
27412
+ ...tags === void 0 ? {} : { tags },
27413
+ ...Object.keys(metrics).length === 0 ? {} : { metrics }
27414
+ });
27415
+ }
27416
+ endIfComplete(id, active, run) {
27417
+ const endTime = timestampSeconds(ownValue(run, "end_time"));
27418
+ if (endTime === void 0 && errorMessage(ownValue(run, "error")) === void 0) {
27419
+ return;
27420
+ }
27421
+ active.span.end(endTime === void 0 ? void 0 : { endTime });
27422
+ this.activeRuns.delete(id);
27423
+ this.completedRuns.set(id, true);
27424
+ }
27425
+ shouldSkipLangChainRun(run) {
27426
+ if (!this.skipLangChainRuns) {
27427
+ return false;
27428
+ }
27429
+ const serialized = ownValue(run, "serialized");
27430
+ return isRecord2(serialized) && ownValue(serialized, "lc") === 1;
27431
+ }
27432
+ containLifecycleFailure(operation, fn) {
27433
+ try {
27434
+ fn();
27435
+ } catch (error) {
27436
+ debugLogger.error(
27437
+ `Failed to process LangSmith ${operation} instrumentation:`,
27438
+ error
27439
+ );
27440
+ }
27441
+ }
27442
+ };
27443
+ function ownValue(value, key) {
27444
+ if (!isRecord2(value)) {
27445
+ return void 0;
27446
+ }
27447
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
27448
+ return descriptor && "value" in descriptor ? descriptor.value : void 0;
27449
+ }
27450
+ function preferOwnValue(current, previous, key) {
27451
+ const currentDescriptor = isRecord2(current) ? Object.getOwnPropertyDescriptor(current, key) : void 0;
27452
+ if (currentDescriptor && "value" in currentDescriptor) {
27453
+ return currentDescriptor.value;
27454
+ }
27455
+ return ownValue(previous, key);
27456
+ }
27457
+ function mergeRuns(previous, current) {
27458
+ const entries = /* @__PURE__ */ new Map();
27459
+ for (const value of [previous, current]) {
27460
+ if (!isRecord2(value)) {
27461
+ continue;
27462
+ }
27463
+ for (const [key, descriptor] of Object.entries(
27464
+ Object.getOwnPropertyDescriptors(value)
27465
+ )) {
27466
+ if (descriptor.enumerable && "value" in descriptor) {
27467
+ entries.set(key, descriptor.value);
27468
+ }
27469
+ }
27470
+ }
27471
+ return Object.fromEntries(entries);
27472
+ }
27473
+ function isRecord2(value) {
27474
+ return typeof value === "object" && value !== null && !Array.isArray(value);
27475
+ }
27476
+ function stringValue2(value) {
27477
+ return typeof value === "string" && value.length > 0 ? value : void 0;
27478
+ }
27479
+ function timestampSeconds(value) {
27480
+ if (value instanceof Date) {
27481
+ const timestamp = value.getTime();
27482
+ return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
27483
+ }
27484
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
27485
+ return value > 1e10 ? value / 1e3 : value;
27486
+ }
27487
+ if (typeof value === "string") {
27488
+ const timestamp = Date.parse(value);
27489
+ return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
27490
+ }
27491
+ return void 0;
27492
+ }
27493
+ function dottedOrderDepth(run) {
27494
+ const dottedOrder = stringValue2(ownValue(run, "dotted_order"));
27495
+ return dottedOrder ? dottedOrder.split(".").length : Number.MAX_SAFE_INTEGER;
27496
+ }
27497
+ function mapRunType(runType) {
27498
+ switch (runType) {
27499
+ case "llm":
27500
+ case "embedding":
27501
+ return "llm" /* LLM */;
27502
+ case "tool":
27503
+ case "retriever":
27504
+ return "tool" /* TOOL */;
27505
+ default:
27506
+ return "task" /* TASK */;
27507
+ }
27508
+ }
27509
+ function extractMetadata(run, previous) {
27510
+ const extra = preferOwnValue(run, previous, "extra");
27511
+ const rawMetadata = ownValue(extra, "metadata");
27512
+ if (!isRecord2(rawMetadata)) {
27513
+ return void 0;
27514
+ }
27515
+ const metadata = {};
27516
+ for (const [key, descriptor] of Object.entries(
27517
+ Object.getOwnPropertyDescriptors(rawMetadata)
27518
+ )) {
27519
+ if (!("value" in descriptor) || !descriptor.enumerable || BLOCKED_METADATA_KEYS.has(key) || BLOCKED_METADATA_PREFIXES.some((prefix) => key.startsWith(prefix)) || key.startsWith("ls_") && key !== "ls_provider" && key !== "ls_model_name" && !LLM_SETTING_KEYS.some((setting) => key === `ls_${setting}`)) {
27520
+ continue;
27521
+ }
27522
+ const normalizedKey = key === "ls_provider" ? "provider" : key === "ls_model_name" ? "model" : key.startsWith("ls_") ? key.slice(3) : key;
27523
+ const sanitized = sanitizeLoggedValue(descriptor.value);
27524
+ if (sanitized !== void 0) {
27525
+ metadata[normalizedKey] = sanitized;
27526
+ }
27527
+ }
27528
+ return Object.keys(metadata).length === 0 ? void 0 : metadata;
27529
+ }
27530
+ function extractTags(value) {
27531
+ if (!Array.isArray(value)) {
27532
+ return void 0;
27533
+ }
27534
+ const tags = value.filter(
27535
+ (tag) => typeof tag === "string" && tag.length > 0
27536
+ );
27537
+ return tags.length > 0 ? tags : void 0;
27538
+ }
27539
+ function extractMetrics(run, previous) {
27540
+ const outputs = preferOwnValue(run, previous, "outputs");
27541
+ const extra = preferOwnValue(run, previous, "extra");
27542
+ const metadata = ownValue(extra, "metadata");
27543
+ const usage = ownValue(outputs, "usage_metadata") ?? ownValue(metadata, "usage_metadata");
27544
+ const metrics = {};
27545
+ assignFirstMetric(metrics, "prompt_tokens", usage, [
27546
+ "input_tokens",
27547
+ "prompt_tokens"
27548
+ ]);
27549
+ assignFirstMetric(metrics, "completion_tokens", usage, [
27550
+ "output_tokens",
27551
+ "completion_tokens"
27552
+ ]);
27553
+ assignFirstMetric(metrics, "tokens", usage, ["total_tokens", "tokens"]);
27554
+ const inputTokenDetails = ownValue(usage, "input_token_details");
27555
+ assignFirstMetric(metrics, "prompt_cached_tokens", inputTokenDetails, [
27556
+ "cache_read",
27557
+ "cached_tokens"
27558
+ ]);
27559
+ if (metrics.prompt_cached_tokens === void 0) {
27560
+ assignFirstMetric(metrics, "prompt_cached_tokens", usage, [
27561
+ "cache_read_input_tokens",
27562
+ "prompt_cached_tokens"
27563
+ ]);
27564
+ }
27565
+ assignFirstMetric(
27566
+ metrics,
27567
+ "prompt_cache_creation_tokens",
27568
+ inputTokenDetails,
27569
+ ["cache_creation"]
27570
+ );
27571
+ if (metrics.prompt_cache_creation_tokens === void 0) {
27572
+ assignFirstMetric(metrics, "prompt_cache_creation_tokens", usage, [
27573
+ "cache_creation_input_tokens",
27574
+ "prompt_cache_creation_tokens"
27575
+ ]);
27576
+ }
27577
+ if (metrics.tokens === void 0 && (metrics.prompt_tokens !== void 0 || metrics.completion_tokens !== void 0)) {
27578
+ metrics.tokens = (metrics.prompt_tokens ?? 0) + (metrics.completion_tokens ?? 0);
27579
+ }
27580
+ const startTime = timestampSeconds(
27581
+ preferOwnValue(run, previous, "start_time")
27582
+ );
27583
+ const events = preferOwnValue(run, previous, "events");
27584
+ if (startTime !== void 0 && Array.isArray(events)) {
27585
+ for (const event of events) {
27586
+ if (ownValue(event, "name") !== "new_token") {
27587
+ continue;
27588
+ }
27589
+ const eventTime3 = timestampSeconds(ownValue(event, "time"));
27590
+ if (eventTime3 !== void 0 && eventTime3 >= startTime) {
27591
+ metrics.time_to_first_token = eventTime3 - startTime;
27592
+ }
27593
+ break;
27594
+ }
27595
+ }
27596
+ return metrics;
27597
+ }
27598
+ function assignFirstMetric(metrics, target, source, keys) {
27599
+ for (const key of keys) {
27600
+ const value = ownValue(source, key);
27601
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
27602
+ metrics[target] = value;
27603
+ return;
27604
+ }
27605
+ }
27606
+ }
27607
+ function errorMessage(value) {
27608
+ if (typeof value === "string") {
27609
+ return value;
27610
+ }
27611
+ if (value instanceof Error) {
27612
+ return value.message;
27613
+ }
27614
+ return void 0;
27615
+ }
27616
+ function sanitizeLoggedValue(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
27617
+ if (value === null || typeof value === "string" || typeof value === "boolean") {
27618
+ return value;
27619
+ }
27620
+ if (typeof value === "number") {
27621
+ return Number.isFinite(value) ? value : void 0;
27622
+ }
27623
+ if (value instanceof Date) {
27624
+ return Number.isFinite(value.getTime()) ? value.toISOString() : void 0;
27625
+ }
27626
+ if (typeof value !== "object" || depth >= 20) {
27627
+ return void 0;
27628
+ }
27629
+ if (seen.has(value)) {
27630
+ return "[Circular]";
27631
+ }
27632
+ seen.add(value);
27633
+ if (Array.isArray(value)) {
27634
+ return value.map((item) => sanitizeLoggedValue(item, seen, depth + 1));
27635
+ }
27636
+ const entries = [];
27637
+ for (const [key, descriptor] of Object.entries(
27638
+ Object.getOwnPropertyDescriptors(value)
27639
+ )) {
27640
+ if (!descriptor.enumerable || !("value" in descriptor) || BLOCKED_METADATA_KEYS.has(key)) {
27641
+ continue;
27642
+ }
27643
+ entries.push([key, sanitizeLoggedValue(descriptor.value, seen, depth + 1)]);
27644
+ }
27645
+ return Object.fromEntries(entries);
27646
+ }
27647
+
27147
27648
  // src/instrumentation/plugins/pi-coding-agent-channels.ts
27148
27649
  var piCodingAgentChannels = defineChannels(
27149
27650
  "@earendil-works/pi-coding-agent",
@@ -27523,11 +28024,11 @@ function patchAssistantMessageStream(stream, promptState, llmState) {
27523
28024
  function recordPiAssistantMessageEvent(promptState, llmState, event) {
27524
28025
  recordFirstTokenMetric(llmState, event);
27525
28026
  const message = "message" in event ? event.message : void 0;
27526
- const errorMessage = "error" in event ? event.error : void 0;
28027
+ const errorMessage2 = "error" in event ? event.error : void 0;
27527
28028
  if (event.type === "done" && isPiAssistantMessage(message)) {
27528
28029
  finishPiLlmSpan(promptState, llmState, message);
27529
- } else if (event.type === "error" && isPiAssistantMessage(errorMessage)) {
27530
- finishPiLlmSpan(promptState, llmState, errorMessage);
28030
+ } else if (event.type === "error" && isPiAssistantMessage(errorMessage2)) {
28031
+ finishPiLlmSpan(promptState, llmState, errorMessage2);
27531
28032
  }
27532
28033
  }
27533
28034
  function recordFirstTokenMetric(state, event) {
@@ -28045,6 +28546,7 @@ var strandsAgentSDKChannels = defineChannels("@strands-agents/sdk", {
28045
28546
  });
28046
28547
 
28047
28548
  // src/instrumentation/plugins/strands-agent-sdk-plugin.ts
28549
+ var MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES = 32;
28048
28550
  var StrandsAgentSDKPlugin = class extends BasePlugin {
28049
28551
  activeChildParents = /* @__PURE__ */ new WeakMap();
28050
28552
  onEnable() {
@@ -28189,11 +28691,16 @@ function startAgentStream(event, activeChildParents) {
28189
28691
  ...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
28190
28692
  };
28191
28693
  const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
28694
+ const attachmentCache = createStrandsAttachmentCache();
28695
+ const input = processStrandsInputAttachments(
28696
+ event.arguments[0],
28697
+ attachmentCache
28698
+ );
28192
28699
  const span = parentSpan ? withCurrent(
28193
28700
  parentSpan,
28194
28701
  () => startSpan({
28195
28702
  event: {
28196
- input: event.arguments[0],
28703
+ input,
28197
28704
  metadata
28198
28705
  },
28199
28706
  name: formatAgentSpanName(agent),
@@ -28201,7 +28708,7 @@ function startAgentStream(event, activeChildParents) {
28201
28708
  })
28202
28709
  ) : startSpan({
28203
28710
  event: {
28204
- input: event.arguments[0],
28711
+ input,
28205
28712
  metadata
28206
28713
  },
28207
28714
  name: formatAgentSpanName(agent),
@@ -28209,6 +28716,7 @@ function startAgentStream(event, activeChildParents) {
28209
28716
  });
28210
28717
  return {
28211
28718
  activeTools: /* @__PURE__ */ new Map(),
28719
+ attachmentCache,
28212
28720
  finalized: false,
28213
28721
  metadata,
28214
28722
  span,
@@ -28224,11 +28732,12 @@ function startMultiAgentStream(event, operation, activeChildParents) {
28224
28732
  ...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
28225
28733
  };
28226
28734
  const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
28735
+ const input = processStrandsInputAttachments(event.arguments[0]);
28227
28736
  const span = parentSpan ? withCurrent(
28228
28737
  parentSpan,
28229
28738
  () => startSpan({
28230
28739
  event: {
28231
- input: event.arguments[0],
28740
+ input,
28232
28741
  metadata
28233
28742
  },
28234
28743
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -28236,7 +28745,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
28236
28745
  })
28237
28746
  ) : startSpan({
28238
28747
  event: {
28239
- input: event.arguments[0],
28748
+ input,
28240
28749
  metadata
28241
28750
  },
28242
28751
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -28345,7 +28854,10 @@ function startModelSpan(state, event) {
28345
28854
  state.span,
28346
28855
  () => startSpan({
28347
28856
  event: {
28348
- input: Array.isArray(event.agent?.messages) ? event.agent.messages : void 0,
28857
+ input: Array.isArray(event.agent?.messages) ? processStrandsInputAttachments(
28858
+ event.agent.messages,
28859
+ state.attachmentCache
28860
+ ) : void 0,
28349
28861
  metadata
28350
28862
  },
28351
28863
  name: formatModelSpanName(model),
@@ -28559,6 +29071,7 @@ function finalizeAgentStream(state, error, output) {
28559
29071
  ...output !== void 0 ? { output } : {}
28560
29072
  });
28561
29073
  state.span.end();
29074
+ state.attachmentCache.strings.clear();
28562
29075
  }
28563
29076
  function finalizeMultiAgentStream(state, activeChildParents, error, output) {
28564
29077
  if (state.finalized) {
@@ -28705,6 +29218,166 @@ function extractNodeResultOutput(result) {
28705
29218
  }
28706
29219
  return result;
28707
29220
  }
29221
+ var STRANDS_MEDIA_TYPES = {
29222
+ png: "image/png",
29223
+ jpg: "image/jpeg",
29224
+ jpeg: "image/jpeg",
29225
+ gif: "image/gif",
29226
+ webp: "image/webp",
29227
+ mkv: "video/x-matroska",
29228
+ mov: "video/quicktime",
29229
+ mp4: "video/mp4",
29230
+ webm: "video/webm",
29231
+ flv: "video/x-flv",
29232
+ mpeg: "video/mpeg",
29233
+ mpg: "video/mpeg",
29234
+ wmv: "video/x-ms-wmv",
29235
+ "3gp": "video/3gpp",
29236
+ pdf: "application/pdf",
29237
+ csv: "text/csv",
29238
+ doc: "application/msword",
29239
+ docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
29240
+ xls: "application/vnd.ms-excel",
29241
+ xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
29242
+ html: "text/html",
29243
+ txt: "text/plain",
29244
+ md: "text/markdown",
29245
+ json: "application/json",
29246
+ xml: "application/xml"
29247
+ };
29248
+ function createStrandsAttachmentCache() {
29249
+ return {
29250
+ objects: /* @__PURE__ */ new WeakMap(),
29251
+ strings: new LRUCache({
29252
+ max: MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES
29253
+ })
29254
+ };
29255
+ }
29256
+ function processStrandsInputAttachments(input, cache = createStrandsAttachmentCache()) {
29257
+ try {
29258
+ return processStrandsInputNode(input, cache);
29259
+ } catch (error) {
29260
+ logInstrumentationError5("Strands Agent SDK input attachments", error);
29261
+ return input;
29262
+ }
29263
+ }
29264
+ function processStrandsInputNode(value, cache) {
29265
+ if (value instanceof BaseAttachment) {
29266
+ return value;
29267
+ }
29268
+ if (Array.isArray(value)) {
29269
+ return value.map((child) => processStrandsInputNode(child, cache));
29270
+ }
29271
+ if (!isObject(value)) {
29272
+ return value;
29273
+ }
29274
+ const directMedia = processDirectStrandsMediaBlock(value, cache);
29275
+ if (directMedia !== void 0) {
29276
+ return directMedia;
29277
+ }
29278
+ const wrappedMedia = processWrappedStrandsMediaBlock(value, cache);
29279
+ if (wrappedMedia !== void 0) {
29280
+ return wrappedMedia;
29281
+ }
29282
+ if (value.type === "message" && Array.isArray(value.content)) {
29283
+ return {
29284
+ role: value.role,
29285
+ content: value.content.map(
29286
+ (child) => processStrandsInputNode(child, cache)
29287
+ ),
29288
+ ...value.metadata !== void 0 ? { metadata: value.metadata } : {}
29289
+ };
29290
+ }
29291
+ if (typeof value.toJSON === "function") {
29292
+ return processStrandsInputNode(value.toJSON(), cache);
29293
+ }
29294
+ return Object.fromEntries(
29295
+ Object.entries(value).map(([key, child]) => [
29296
+ key,
29297
+ processStrandsInputNode(child, cache)
29298
+ ])
29299
+ );
29300
+ }
29301
+ function processDirectStrandsMediaBlock(block, cache) {
29302
+ if (!isStrandsMediaBlock(block)) {
29303
+ return void 0;
29304
+ }
29305
+ const mediaKey = block.type === "imageBlock" ? "image" : block.type === "videoBlock" ? "video" : "document";
29306
+ return createStrandsMediaAttachment(mediaKey, block, cache);
29307
+ }
29308
+ function isStrandsMediaBlock(block) {
29309
+ return (block.type === "imageBlock" || block.type === "videoBlock" || block.type === "documentBlock") && typeof block.format === "string" && isObject(block.source);
29310
+ }
29311
+ function processWrappedStrandsMediaBlock(block, cache) {
29312
+ for (const mediaKey of ["image", "video", "document"]) {
29313
+ const media = block[mediaKey];
29314
+ if (!Object.hasOwn(block, mediaKey) || !isObject(media)) {
29315
+ continue;
29316
+ }
29317
+ const processed = createStrandsMediaAttachment(mediaKey, media, cache);
29318
+ if (processed !== void 0) {
29319
+ return processed;
29320
+ }
29321
+ }
29322
+ return void 0;
29323
+ }
29324
+ function createStrandsMediaAttachment(mediaKey, media, cache) {
29325
+ const format = media.format;
29326
+ const source = media.source;
29327
+ if (typeof format !== "string" || !isObject(source) || !Object.hasOwn(source, "bytes")) {
29328
+ return void 0;
29329
+ }
29330
+ const contentType = STRANDS_MEDIA_TYPES[format.toLowerCase()];
29331
+ if (!contentType) {
29332
+ return void 0;
29333
+ }
29334
+ const filename = mediaKey === "document" && typeof media.name === "string" && media.name.length > 0 ? media.name : `${mediaKey}.${format.toLowerCase()}`;
29335
+ const attachment = getOrCreateStrandsAttachment(
29336
+ source.bytes,
29337
+ filename,
29338
+ contentType,
29339
+ cache
29340
+ );
29341
+ if (!attachment) {
29342
+ return void 0;
29343
+ }
29344
+ const { type: _type, ...serializedMedia } = media;
29345
+ const { type: _sourceType, ...serializedSource } = source;
29346
+ return {
29347
+ [mediaKey]: {
29348
+ ...serializedMedia,
29349
+ source: {
29350
+ ...serializedSource,
29351
+ bytes: attachment
29352
+ }
29353
+ }
29354
+ };
29355
+ }
29356
+ function getOrCreateStrandsAttachment(data, filename, contentType, cache) {
29357
+ const key = `${contentType}\0${filename}`;
29358
+ const attachments = typeof data === "string" ? cache.strings.get(data) : isObject(data) ? cache.objects.get(data) : void 0;
29359
+ const cached = attachments?.get(key);
29360
+ if (cached) {
29361
+ return cached;
29362
+ }
29363
+ const blob = convertDataToBlob(data, contentType);
29364
+ if (!blob) {
29365
+ return void 0;
29366
+ }
29367
+ const attachment = new Attachment({
29368
+ data: blob,
29369
+ filename,
29370
+ contentType
29371
+ });
29372
+ const updatedAttachments = attachments ?? /* @__PURE__ */ new Map();
29373
+ updatedAttachments.set(key, attachment);
29374
+ if (typeof data === "string") {
29375
+ cache.strings.set(data, updatedAttachments);
29376
+ } else if (isObject(data)) {
29377
+ cache.objects.set(data, updatedAttachments);
29378
+ }
29379
+ return attachment;
29380
+ }
28708
29381
  function normalizeContentBlocks(blocks) {
28709
29382
  const text = blocks.map((block) => typeof block.text === "string" ? block.text : void 0).filter((part) => Boolean(part)).join("");
28710
29383
  return text.length > 0 ? text : blocks;
@@ -28834,6 +29507,7 @@ var BraintrustPlugin = class extends BasePlugin {
28834
29507
  gitHubCopilotPlugin = null;
28835
29508
  fluePlugin = null;
28836
29509
  langChainPlugin = null;
29510
+ langSmithPlugin = null;
28837
29511
  piCodingAgentPlugin = null;
28838
29512
  strandsAgentSDKPlugin = null;
28839
29513
  constructor(config = {}) {
@@ -28930,6 +29604,12 @@ var BraintrustPlugin = class extends BasePlugin {
28930
29604
  this.langChainPlugin = new LangChainPlugin();
28931
29605
  this.langChainPlugin.enable();
28932
29606
  }
29607
+ if (integrations.langsmith !== false) {
29608
+ this.langSmithPlugin = new LangSmithPlugin({
29609
+ skipLangChainRuns: integrations.langchain !== false
29610
+ });
29611
+ this.langSmithPlugin.enable();
29612
+ }
28933
29613
  }
28934
29614
  onDisable() {
28935
29615
  if (this.openaiPlugin) {
@@ -29020,6 +29700,10 @@ var BraintrustPlugin = class extends BasePlugin {
29020
29700
  this.langChainPlugin.disable();
29021
29701
  this.langChainPlugin = null;
29022
29702
  }
29703
+ if (this.langSmithPlugin) {
29704
+ this.langSmithPlugin.disable();
29705
+ this.langSmithPlugin = null;
29706
+ }
29023
29707
  }
29024
29708
  };
29025
29709
 
@@ -29098,9 +29782,6 @@ var EveBridge = class {
29098
29782
  this.state = state;
29099
29783
  }
29100
29784
  eventQueuesBySession = /* @__PURE__ */ new Map();
29101
- sessionsById = new LRUCache({
29102
- max: MAX_EVE_CACHE_ENTRIES
29103
- });
29104
29785
  completedToolKeys = new LRUCache({
29105
29786
  max: MAX_EVE_CACHE_ENTRIES
29106
29787
  });
@@ -29267,7 +29948,7 @@ var EveBridge = class {
29267
29948
  async handleEvent(event, ctx, hookMetadata) {
29268
29949
  switch (event.type) {
29269
29950
  case "session.started":
29270
- await this.handleSessionStarted(event, ctx, hookMetadata);
29951
+ this.handleSessionStarted(event, ctx, hookMetadata);
29271
29952
  return true;
29272
29953
  case "turn.started":
29273
29954
  await this.handleTurnStarted(event, ctx, hookMetadata);
@@ -29303,22 +29984,22 @@ var EveBridge = class {
29303
29984
  this.handleStepFailed(event, ctx);
29304
29985
  return true;
29305
29986
  case "turn.completed":
29306
- await this.handleTurnCompleted(event, ctx);
29987
+ this.handleTurnCompleted(event, ctx);
29307
29988
  return true;
29308
29989
  case "turn.failed":
29309
- await this.handleTurnFailed(event, ctx);
29990
+ this.handleTurnFailed(event, ctx);
29310
29991
  return true;
29311
29992
  case "session.failed":
29312
- await this.handleSessionFailed(event, ctx);
29993
+ this.handleSessionFailed(event, ctx);
29313
29994
  return true;
29314
29995
  case "session.completed":
29315
- await this.handleSessionCompleted(event, ctx);
29996
+ this.handleSessionCompleted(event, ctx);
29316
29997
  return true;
29317
29998
  default:
29318
29999
  return false;
29319
30000
  }
29320
30001
  }
29321
- async handleSessionStarted(event, ctx, hookMetadata) {
30002
+ handleSessionStarted(event, ctx, hookMetadata) {
29322
30003
  const sessionId = sessionIdFromContext(ctx);
29323
30004
  if (!sessionId) {
29324
30005
  return;
@@ -29334,7 +30015,6 @@ var EveBridge = class {
29334
30015
  metadata: { ...normalized.metadata, ...metadata }
29335
30016
  };
29336
30017
  });
29337
- await this.ensureSession(sessionId, ctx, metadata, eventTime2(event));
29338
30018
  for (const [key, turn] of this.turnsByKey) {
29339
30019
  if (!key.startsWith(`${sessionId}:`)) {
29340
30020
  continue;
@@ -29352,21 +30032,19 @@ var EveBridge = class {
29352
30032
  if (!sessionId) {
29353
30033
  return;
29354
30034
  }
29355
- const session = await this.ensureSession(
29356
- sessionId,
29357
- ctx,
29358
- hookMetadata ?? {},
29359
- eventTime2(event)
29360
- );
29361
30035
  const key = turnKey2(sessionId, event.data.turnId);
29362
- const metadata = { ...session.metadata };
30036
+ const metadata = {
30037
+ ...readEveTraceState(this.state).metadata,
30038
+ ...hookMetadata ?? {},
30039
+ "eve.session_id": sessionId
30040
+ };
29363
30041
  const existing = this.turnsByKey.get(key);
29364
30042
  if (existing) {
29365
30043
  existing.metadata = { ...existing.metadata, ...metadata };
29366
30044
  existing.span.log({ metadata: existing.metadata });
29367
30045
  return;
29368
30046
  }
29369
- const span = await this.startTurnSpan(session, event, metadata);
30047
+ const span = await this.startTurnSpan(sessionId, event, ctx, metadata);
29370
30048
  span.log({ metadata });
29371
30049
  this.turnsByKey.set(key, {
29372
30050
  key,
@@ -29404,10 +30082,7 @@ var EveBridge = class {
29404
30082
  this.markStepEnded(event.data.turnId, event.data.stepIndex);
29405
30083
  }
29406
30084
  const stepOrdinal = this.stepOrdinal(event);
29407
- const metadata = {
29408
- ...turn.metadata,
29409
- ...this.sessionsById.get(sessionId)?.metadata ?? {}
29410
- };
30085
+ const metadata = { ...turn.metadata };
29411
30086
  const input = consumeCapturedEveModelInput(
29412
30087
  this.state,
29413
30088
  sessionId,
@@ -29502,6 +30177,28 @@ var EveBridge = class {
29502
30177
  if (!step) {
29503
30178
  return;
29504
30179
  }
30180
+ const toolCallsById = /* @__PURE__ */ new Map();
30181
+ if (Array.isArray(step.output) && isObject(step.output[0])) {
30182
+ const message = step.output[0]["message"];
30183
+ if (isObject(message) && Array.isArray(message["tool_calls"])) {
30184
+ for (const toolCall of message["tool_calls"]) {
30185
+ if (isObject(toolCall) && typeof toolCall["id"] === "string") {
30186
+ toolCallsById.set(toolCall["id"], toolCall);
30187
+ }
30188
+ }
30189
+ }
30190
+ }
30191
+ for (const action of traceActions) {
30192
+ const name = action.kind === "tool-call" ? action.toolName : action.subagentName ?? action.name ?? "agent";
30193
+ toolCallsById.set(action.callId, {
30194
+ function: {
30195
+ arguments: JSON.stringify(action.input),
30196
+ name
30197
+ },
30198
+ id: action.callId,
30199
+ type: "function"
30200
+ });
30201
+ }
29505
30202
  step.output = [
29506
30203
  {
29507
30204
  finish_reason: "tool_calls",
@@ -29509,17 +30206,7 @@ var EveBridge = class {
29509
30206
  message: {
29510
30207
  content: null,
29511
30208
  role: "assistant",
29512
- tool_calls: traceActions.map((action) => {
29513
- const name = action.kind === "tool-call" ? action.toolName : action.subagentName ?? action.name ?? "agent";
29514
- return {
29515
- function: {
29516
- arguments: JSON.stringify(action.input),
29517
- name
29518
- },
29519
- id: action.callId,
29520
- type: "function"
29521
- };
29522
- })
30209
+ tool_calls: [...toolCallsById.values()]
29523
30210
  }
29524
30211
  }
29525
30212
  ];
@@ -29766,17 +30453,11 @@ var EveBridge = class {
29766
30453
  )
29767
30454
  });
29768
30455
  }
29769
- async handleSessionFailed(event, ctx) {
30456
+ handleSessionFailed(event, ctx) {
29770
30457
  const sessionId = event.data.sessionId || sessionIdFromContext(ctx);
29771
30458
  if (!sessionId) {
29772
30459
  return;
29773
30460
  }
29774
- const session = await this.ensureSession(
29775
- sessionId,
29776
- ctx,
29777
- {},
29778
- eventTime2(event)
29779
- );
29780
30461
  const error = errorFromMessage(
29781
30462
  event.data.message,
29782
30463
  event.data.code,
@@ -29793,29 +30474,20 @@ var EveBridge = class {
29793
30474
  }
29794
30475
  for (const [key, tool] of this.toolsByCallKey) {
29795
30476
  if (key.startsWith(`${sessionId}:`)) {
29796
- const endTime2 = eventTime2(event);
30477
+ const endTime = eventTime2(event);
29797
30478
  if (!tool.endedByTurn) {
29798
30479
  tool.span.log({ metadata: tool.metadata });
29799
- tool.span.end(endTime2 === void 0 ? void 0 : { endTime: endTime2 });
30480
+ tool.span.end(endTime === void 0 ? void 0 : { endTime });
29800
30481
  tool.endedByTurn = true;
29801
30482
  }
29802
30483
  }
29803
30484
  }
29804
- session.span.log({ error });
29805
- const endTime = eventTime2(event);
29806
- session.span.end(endTime === void 0 ? void 0 : { endTime });
29807
30485
  }
29808
- async handleSessionCompleted(event, ctx) {
30486
+ handleSessionCompleted(event, ctx) {
29809
30487
  const sessionId = sessionIdFromContext(ctx);
29810
30488
  if (!sessionId) {
29811
30489
  return;
29812
30490
  }
29813
- const session = await this.ensureSession(
29814
- sessionId,
29815
- ctx,
29816
- {},
29817
- eventTime2(event)
29818
- );
29819
30491
  for (const [key, turn] of this.turnsByKey) {
29820
30492
  if (!key.startsWith(`${sessionId}:`)) {
29821
30493
  continue;
@@ -29826,82 +30498,29 @@ var EveBridge = class {
29826
30498
  }
29827
30499
  for (const [key, tool] of this.toolsByCallKey) {
29828
30500
  if (key.startsWith(`${sessionId}:`) && !tool.endedByTurn) {
29829
- const endTime2 = eventTime2(event);
30501
+ const endTime = eventTime2(event);
29830
30502
  tool.span.log({ metadata: tool.metadata });
29831
- tool.span.end(endTime2 === void 0 ? void 0 : { endTime: endTime2 });
30503
+ tool.span.end(endTime === void 0 ? void 0 : { endTime });
29832
30504
  tool.endedByTurn = true;
29833
30505
  }
29834
30506
  }
29835
- session.span.log({ metadata: session.metadata });
29836
- const endTime = eventTime2(event);
29837
- session.span.end(endTime === void 0 ? void 0 : { endTime });
29838
- }
29839
- async ensureSession(sessionId, ctx, metadata, startTime) {
29840
- metadata = {
29841
- ...readEveTraceState(this.state).metadata,
29842
- ...metadata
29843
- };
29844
- const existing = this.sessionsById.get(sessionId);
29845
- if (existing) {
29846
- existing.metadata = { ...existing.metadata, ...metadata };
29847
- existing.span.log({ metadata: existing.metadata });
29848
- return existing;
29849
- }
29850
- const lineage = parentLineageFromContext(ctx);
29851
- const parentSubagent = lineage ? this.toolsByCallKey.get(toolKey3(lineage.sessionId, lineage.callId)) : void 0;
29852
- const activeParent = currentSpan();
29853
- const [
29854
- { rowId: eventId, spanId },
29855
- parentSubagentSpanId,
29856
- fallbackRootSpanId
29857
- ] = await Promise.all([
29858
- generateEveIds("session", sessionId),
29859
- lineage ? spanIdForSubagent(lineage.sessionId, lineage.callId) : Promise.resolve(void 0),
29860
- lineage ? rootSpanIdForSession(lineage.rootSessionId) : rootSpanIdForSession(sessionId)
29861
- ]);
29862
- const span = await this.startEveSpan({
29863
- event: {
29864
- id: eventId,
29865
- metadata
29866
- },
29867
- name: "eve.session",
29868
- parentSpanIds: lineage && parentSubagentSpanId ? {
29869
- rootSpanId: parentSubagent?.span.rootSpanId ?? fallbackRootSpanId,
29870
- spanId: parentSubagentSpanId
29871
- } : !Object.is(activeParent, NOOP_SPAN) ? {
29872
- rootSpanId: activeParent.rootSpanId,
29873
- spanId: activeParent.spanId
29874
- } : {
29875
- parentSpanIds: [],
29876
- rootSpanId: fallbackRootSpanId
29877
- },
29878
- spanAttributes: { type: "task" /* TASK */ },
29879
- spanId,
29880
- startTime
29881
- });
29882
- span.log({ metadata });
29883
- const session = { metadata, sessionId, span };
29884
- this.sessionsById.set(sessionId, session);
29885
- return session;
29886
30507
  }
29887
30508
  async ensureTurn(event, ctx, hookMetadata) {
29888
30509
  const sessionId = sessionIdFromContext(ctx);
29889
30510
  if (!sessionId) {
29890
30511
  return void 0;
29891
30512
  }
29892
- const session = await this.ensureSession(
29893
- sessionId,
29894
- ctx,
29895
- hookMetadata ?? {},
29896
- eventTime2(event)
29897
- );
29898
30513
  const key = turnKey2(sessionId, event.data.turnId);
29899
30514
  const existing = this.turnsByKey.get(key);
29900
30515
  if (existing) {
29901
30516
  return existing;
29902
30517
  }
29903
- const metadata = { ...session.metadata };
29904
- const span = await this.startTurnSpan(session, event, metadata);
30518
+ const metadata = {
30519
+ ...readEveTraceState(this.state).metadata,
30520
+ ...hookMetadata ?? {},
30521
+ "eve.session_id": sessionId
30522
+ };
30523
+ const span = await this.startTurnSpan(sessionId, event, ctx, metadata);
29905
30524
  span.log({ metadata });
29906
30525
  const state = {
29907
30526
  key,
@@ -30088,22 +30707,35 @@ var EveBridge = class {
30088
30707
  this.toolsByCallKey.set(toolKey3(sessionId, result.callId), state);
30089
30708
  return state;
30090
30709
  }
30091
- async startTurnSpan(session, event, metadata) {
30092
- const { rowId: eventId, spanId } = await generateEveIds(
30093
- "turn",
30094
- session.sessionId,
30095
- event.data.turnId
30096
- );
30710
+ async startTurnSpan(sessionId, event, ctx, metadata) {
30711
+ const session = isObject(ctx) ? ctx["session"] : void 0;
30712
+ const parent = isObject(session) ? session["parent"] : void 0;
30713
+ const parentTurn = isObject(parent) ? parent["turn"] : void 0;
30714
+ const parentLineage = isObject(parent) && typeof parent["callId"] === "string" && typeof parent["sessionId"] === "string" && isObject(parentTurn) && typeof parentTurn["id"] === "string" ? {
30715
+ callId: parent["callId"],
30716
+ sessionId: parent["sessionId"],
30717
+ turnId: parentTurn["id"]
30718
+ } : void 0;
30719
+ const [{ rowId: eventId, spanId }, rootSpanId, parentSpanId] = await Promise.all([
30720
+ generateEveIds("turn", sessionId, event.data.turnId),
30721
+ deterministicEveId(
30722
+ "eve:root",
30723
+ parentLineage?.sessionId ?? sessionId,
30724
+ parentLineage?.turnId ?? event.data.turnId
30725
+ ),
30726
+ parentLineage ? deterministicEveId(
30727
+ "eve:subagent",
30728
+ parentLineage.sessionId,
30729
+ parentLineage.callId
30730
+ ) : Promise.resolve(void 0)
30731
+ ]);
30097
30732
  return await this.startEveSpan({
30098
30733
  event: {
30099
30734
  id: eventId,
30100
30735
  metadata
30101
30736
  },
30102
30737
  name: "eve.turn",
30103
- parentSpanIds: {
30104
- rootSpanId: session.span.rootSpanId,
30105
- spanId: session.span.spanId
30106
- },
30738
+ parentSpanIds: parentSpanId ? { rootSpanId, spanId: parentSpanId } : { parentSpanIds: [], rootSpanId },
30107
30739
  spanAttributes: { type: "task" /* TASK */ },
30108
30740
  spanId,
30109
30741
  startTime: eventTime2(event)
@@ -30164,7 +30796,6 @@ var EveBridge = class {
30164
30796
  }
30165
30797
  cleanupSession(sessionId) {
30166
30798
  const keyPrefix = `${sessionId}:`;
30167
- this.sessionsById.delete(sessionId);
30168
30799
  for (const key of this.turnsByKey.keys()) {
30169
30800
  if (key.startsWith(keyPrefix)) {
30170
30801
  this.turnsByKey.delete(key);
@@ -30355,7 +30986,7 @@ function modelMetadataFromRuntime(runtime) {
30355
30986
  return {};
30356
30987
  }
30357
30988
  const modelId = runtime["modelId"];
30358
- return typeof modelId === "string" ? modelMetadataFromModelId(modelId) : {};
30989
+ return typeof modelId === "string" && !modelId.trim().startsWith("dynamic:") ? modelMetadataFromModelId(modelId) : {};
30359
30990
  }
30360
30991
  function modelMetadataFromModelId(modelId) {
30361
30992
  const normalized = modelId.trim();
@@ -30388,26 +31019,6 @@ function toolMetadataFromTurn(turn) {
30388
31019
  const { model: _model, provider: _provider, ...metadata } = turn.metadata;
30389
31020
  return metadata;
30390
31021
  }
30391
- function parentLineageFromContext(ctx) {
30392
- if (!isObject(ctx)) {
30393
- return void 0;
30394
- }
30395
- const session = ctx.session;
30396
- if (!isObject(session)) {
30397
- return void 0;
30398
- }
30399
- const parent = session["parent"];
30400
- if (!isObject(parent)) {
30401
- return void 0;
30402
- }
30403
- const callId = parent["callId"];
30404
- const rootSessionId = parent["rootSessionId"];
30405
- const sessionId = parent["sessionId"];
30406
- if (typeof callId !== "string" || typeof rootSessionId !== "string" || typeof sessionId !== "string") {
30407
- return void 0;
30408
- }
30409
- return { callId, rootSessionId, sessionId };
30410
- }
30411
31022
  function isToolCallAction(action) {
30412
31023
  return isObject(action) && action["kind"] === "tool-call" && typeof action["callId"] === "string" && typeof action["toolName"] === "string" && isObject(action["input"]);
30413
31024
  }
@@ -30463,9 +31074,6 @@ function turnKey2(sessionId, turnId) {
30463
31074
  function toolKey3(sessionId, callId) {
30464
31075
  return `${sessionId}:${callId}`;
30465
31076
  }
30466
- async function rootSpanIdForSession(sessionId) {
30467
- return deterministicEveId("eve:root", sessionId);
30468
- }
30469
31077
  async function generateEveIds(kind, ...parts) {
30470
31078
  const [rowId, spanId] = await Promise.all([
30471
31079
  deterministicEveId(`eve:row:${kind}`, ...parts),
@@ -30473,9 +31081,6 @@ async function generateEveIds(kind, ...parts) {
30473
31081
  ]);
30474
31082
  return { rowId, spanId };
30475
31083
  }
30476
- async function spanIdForSubagent(sessionId, callId) {
30477
- return deterministicEveId("eve:subagent", sessionId, callId);
30478
- }
30479
31084
  async function deterministicEveId(...parts) {
30480
31085
  const data = new TextEncoder().encode(
30481
31086
  parts.map((part) => `${part.length}:${part}`).join("\0")
@@ -30547,7 +31152,8 @@ var envIntegrationAliases = {
30547
31152
  langchain: "langchain",
30548
31153
  "langchain-js": "langchain",
30549
31154
  "@langchain": "langchain",
30550
- langgraph: "langgraph"
31155
+ langgraph: "langgraph",
31156
+ langsmith: "langsmith"
30551
31157
  };
30552
31158
  function getDefaultInstrumentationIntegrations() {
30553
31159
  return {
@@ -30578,6 +31184,7 @@ function getDefaultInstrumentationIntegrations() {
30578
31184
  gitHubCopilot: true,
30579
31185
  langchain: true,
30580
31186
  langgraph: true,
31187
+ langsmith: true,
30581
31188
  piCodingAgent: true,
30582
31189
  strandsAgentSDK: true
30583
31190
  };