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
@@ -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;
@@ -27188,6 +27249,446 @@ function isBraintrustHandler(handler) {
27188
27249
  return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
27189
27250
  }
27190
27251
 
27252
+ // src/instrumentation/plugins/langsmith-channels.ts
27253
+ var langSmithChannels = defineChannels("langsmith", {
27254
+ createRun: channel({
27255
+ channelName: "Client.createRun",
27256
+ kind: "async"
27257
+ }),
27258
+ updateRun: channel({
27259
+ channelName: "Client.updateRun",
27260
+ kind: "async"
27261
+ }),
27262
+ batchIngestRuns: channel({
27263
+ channelName: "Client.batchIngestRuns",
27264
+ kind: "async"
27265
+ })
27266
+ });
27267
+
27268
+ // src/instrumentation/plugins/langsmith-plugin.ts
27269
+ var MAX_COMPLETED_RUNS = 1e4;
27270
+ var BLOCKED_METADATA_KEYS = /* @__PURE__ */ new Set([
27271
+ "__proto__",
27272
+ "constructor",
27273
+ "prototype",
27274
+ "usage_metadata"
27275
+ ]);
27276
+ var BLOCKED_METADATA_PREFIXES = ["__pregel_", "langgraph_", "lc_"];
27277
+ var LLM_SETTING_KEYS = [
27278
+ "temperature",
27279
+ "top_p",
27280
+ "max_tokens",
27281
+ "frequency_penalty",
27282
+ "presence_penalty",
27283
+ "stop",
27284
+ "response_format"
27285
+ ];
27286
+ var LangSmithPlugin = class extends BasePlugin {
27287
+ activeRuns = /* @__PURE__ */ new Map();
27288
+ completedRuns = new LRUCache({
27289
+ max: MAX_COMPLETED_RUNS
27290
+ });
27291
+ skipLangChainRuns;
27292
+ constructor(options = {}) {
27293
+ super();
27294
+ this.skipLangChainRuns = options.skipLangChainRuns ?? true;
27295
+ }
27296
+ onEnable() {
27297
+ const createChannel = langSmithChannels.createRun.tracingChannel();
27298
+ const createHandlers = {
27299
+ start: (event) => {
27300
+ this.containLifecycleFailure("createRun", () => {
27301
+ this.processCreate(event.arguments[0]);
27302
+ });
27303
+ }
27304
+ };
27305
+ createChannel.subscribe(createHandlers);
27306
+ this.unsubscribers.push(() => createChannel.unsubscribe(createHandlers));
27307
+ const updateChannel = langSmithChannels.updateRun.tracingChannel();
27308
+ const updateHandlers = {
27309
+ start: (event) => {
27310
+ this.containLifecycleFailure("updateRun", () => {
27311
+ this.processUpdate(event.arguments[0], event.arguments[1]);
27312
+ });
27313
+ }
27314
+ };
27315
+ updateChannel.subscribe(updateHandlers);
27316
+ this.unsubscribers.push(() => updateChannel.unsubscribe(updateHandlers));
27317
+ const batchChannel = langSmithChannels.batchIngestRuns.tracingChannel();
27318
+ const batchHandlers = {
27319
+ start: (event) => {
27320
+ this.containLifecycleFailure("batchIngestRuns", () => {
27321
+ this.processBatch(event.arguments[0]);
27322
+ });
27323
+ }
27324
+ };
27325
+ batchChannel.subscribe(batchHandlers);
27326
+ this.unsubscribers.push(() => batchChannel.unsubscribe(batchHandlers));
27327
+ }
27328
+ onDisable() {
27329
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
27330
+ for (const { span } of this.activeRuns.values()) {
27331
+ span.end();
27332
+ }
27333
+ this.activeRuns.clear();
27334
+ this.completedRuns.clear();
27335
+ }
27336
+ processBatch(batch) {
27337
+ if (!isRecord2(batch)) {
27338
+ return;
27339
+ }
27340
+ const creates = ownValue(batch, "runCreates");
27341
+ if (Array.isArray(creates)) {
27342
+ const parentFirst = [...creates].sort((left, right) => {
27343
+ const leftId = stringValue2(ownValue(left, "id"));
27344
+ const rightId = stringValue2(ownValue(right, "id"));
27345
+ const leftParent = stringValue2(ownValue(left, "parent_run_id"));
27346
+ const rightParent = stringValue2(ownValue(right, "parent_run_id"));
27347
+ if (leftParent && leftParent === rightId) {
27348
+ return 1;
27349
+ }
27350
+ if (rightParent && rightParent === leftId) {
27351
+ return -1;
27352
+ }
27353
+ return dottedOrderDepth(left) - dottedOrderDepth(right);
27354
+ });
27355
+ for (const run of parentFirst) {
27356
+ this.containLifecycleFailure("batchIngestRuns create", () => {
27357
+ this.processCreate(run);
27358
+ });
27359
+ }
27360
+ }
27361
+ const updates = ownValue(batch, "runUpdates");
27362
+ if (Array.isArray(updates)) {
27363
+ for (const run of updates) {
27364
+ this.containLifecycleFailure("batchIngestRuns update", () => {
27365
+ this.processUpdate(stringValue2(ownValue(run, "id")) ?? "", run);
27366
+ });
27367
+ }
27368
+ }
27369
+ }
27370
+ processCreate(run) {
27371
+ const id = stringValue2(ownValue(run, "id"));
27372
+ if (!id || this.completedRuns.get(id)) {
27373
+ return;
27374
+ }
27375
+ if (this.shouldSkipLangChainRun(run)) {
27376
+ this.completedRuns.set(id, true);
27377
+ return;
27378
+ }
27379
+ const active = this.activeRuns.get(id);
27380
+ if (active) {
27381
+ const previous = active.run;
27382
+ active.run = mergeRuns(previous, run);
27383
+ this.logRun(
27384
+ active.span,
27385
+ active.run,
27386
+ previous,
27387
+ timestampSeconds(ownValue(active.run, "end_time")) !== void 0 || errorMessage(ownValue(active.run, "error")) !== void 0
27388
+ );
27389
+ this.endIfComplete(id, active, active.run);
27390
+ return;
27391
+ }
27392
+ const span = this.startRunSpan(id, run);
27393
+ const activeRun = { run, span };
27394
+ this.activeRuns.set(id, activeRun);
27395
+ this.logRun(
27396
+ span,
27397
+ run,
27398
+ void 0,
27399
+ timestampSeconds(ownValue(run, "end_time")) !== void 0 || errorMessage(ownValue(run, "error")) !== void 0
27400
+ );
27401
+ this.endIfComplete(id, activeRun, run);
27402
+ }
27403
+ processUpdate(explicitId, run) {
27404
+ const id = stringValue2(explicitId) ?? stringValue2(ownValue(run, "id"));
27405
+ if (!id || this.completedRuns.get(id)) {
27406
+ return;
27407
+ }
27408
+ if (this.shouldSkipLangChainRun(run)) {
27409
+ const active2 = this.activeRuns.get(id);
27410
+ active2?.span.end();
27411
+ this.activeRuns.delete(id);
27412
+ this.completedRuns.set(id, true);
27413
+ return;
27414
+ }
27415
+ let active = this.activeRuns.get(id);
27416
+ if (!active) {
27417
+ const span = this.startRunSpan(id, run);
27418
+ active = { run, span };
27419
+ this.activeRuns.set(id, active);
27420
+ }
27421
+ const previous = active.run;
27422
+ active.run = mergeRuns(previous, run);
27423
+ this.logRun(active.span, active.run, previous, true);
27424
+ this.endIfComplete(id, active, active.run);
27425
+ }
27426
+ startRunSpan(id, run) {
27427
+ const traceId = stringValue2(ownValue(run, "trace_id")) ?? id;
27428
+ const parentId = stringValue2(ownValue(run, "parent_run_id")) ?? stringValue2(ownValue(ownValue(run, "parent_run"), "id"));
27429
+ const startTime = timestampSeconds(ownValue(run, "start_time"));
27430
+ return startSpan({
27431
+ name: stringValue2(ownValue(run, "name")) ?? "LangSmith run",
27432
+ spanId: id,
27433
+ parentSpanIds: {
27434
+ parentSpanIds: parentId ? [parentId] : [],
27435
+ rootSpanId: traceId
27436
+ },
27437
+ spanAttributes: {
27438
+ type: mapRunType(ownValue(run, "run_type"))
27439
+ },
27440
+ ...startTime === void 0 ? {} : { startTime },
27441
+ event: { id }
27442
+ });
27443
+ }
27444
+ logRun(span, run, previous, includeOutput) {
27445
+ const inputs = preferOwnValue(run, previous, "inputs");
27446
+ const outputs = preferOwnValue(run, previous, "outputs");
27447
+ const error = errorMessage(preferOwnValue(run, previous, "error"));
27448
+ const metadata = extractMetadata(run, previous);
27449
+ const tags = extractTags(preferOwnValue(run, previous, "tags"));
27450
+ const metrics = extractMetrics(run, previous);
27451
+ span.log({
27452
+ ...inputs === void 0 ? {} : { input: sanitizeLoggedValue(inputs) },
27453
+ ...includeOutput && outputs !== void 0 ? { output: sanitizeLoggedValue(outputs) } : {},
27454
+ ...error === void 0 ? {} : { error },
27455
+ ...metadata === void 0 ? {} : { metadata },
27456
+ ...tags === void 0 ? {} : { tags },
27457
+ ...Object.keys(metrics).length === 0 ? {} : { metrics }
27458
+ });
27459
+ }
27460
+ endIfComplete(id, active, run) {
27461
+ const endTime = timestampSeconds(ownValue(run, "end_time"));
27462
+ if (endTime === void 0 && errorMessage(ownValue(run, "error")) === void 0) {
27463
+ return;
27464
+ }
27465
+ active.span.end(endTime === void 0 ? void 0 : { endTime });
27466
+ this.activeRuns.delete(id);
27467
+ this.completedRuns.set(id, true);
27468
+ }
27469
+ shouldSkipLangChainRun(run) {
27470
+ if (!this.skipLangChainRuns) {
27471
+ return false;
27472
+ }
27473
+ const serialized = ownValue(run, "serialized");
27474
+ return isRecord2(serialized) && ownValue(serialized, "lc") === 1;
27475
+ }
27476
+ containLifecycleFailure(operation, fn) {
27477
+ try {
27478
+ fn();
27479
+ } catch (error) {
27480
+ debugLogger.error(
27481
+ `Failed to process LangSmith ${operation} instrumentation:`,
27482
+ error
27483
+ );
27484
+ }
27485
+ }
27486
+ };
27487
+ function ownValue(value, key) {
27488
+ if (!isRecord2(value)) {
27489
+ return void 0;
27490
+ }
27491
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
27492
+ return descriptor && "value" in descriptor ? descriptor.value : void 0;
27493
+ }
27494
+ function preferOwnValue(current, previous, key) {
27495
+ const currentDescriptor = isRecord2(current) ? Object.getOwnPropertyDescriptor(current, key) : void 0;
27496
+ if (currentDescriptor && "value" in currentDescriptor) {
27497
+ return currentDescriptor.value;
27498
+ }
27499
+ return ownValue(previous, key);
27500
+ }
27501
+ function mergeRuns(previous, current) {
27502
+ const entries = /* @__PURE__ */ new Map();
27503
+ for (const value of [previous, current]) {
27504
+ if (!isRecord2(value)) {
27505
+ continue;
27506
+ }
27507
+ for (const [key, descriptor] of Object.entries(
27508
+ Object.getOwnPropertyDescriptors(value)
27509
+ )) {
27510
+ if (descriptor.enumerable && "value" in descriptor) {
27511
+ entries.set(key, descriptor.value);
27512
+ }
27513
+ }
27514
+ }
27515
+ return Object.fromEntries(entries);
27516
+ }
27517
+ function isRecord2(value) {
27518
+ return typeof value === "object" && value !== null && !Array.isArray(value);
27519
+ }
27520
+ function stringValue2(value) {
27521
+ return typeof value === "string" && value.length > 0 ? value : void 0;
27522
+ }
27523
+ function timestampSeconds(value) {
27524
+ if (value instanceof Date) {
27525
+ const timestamp = value.getTime();
27526
+ return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
27527
+ }
27528
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
27529
+ return value > 1e10 ? value / 1e3 : value;
27530
+ }
27531
+ if (typeof value === "string") {
27532
+ const timestamp = Date.parse(value);
27533
+ return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
27534
+ }
27535
+ return void 0;
27536
+ }
27537
+ function dottedOrderDepth(run) {
27538
+ const dottedOrder = stringValue2(ownValue(run, "dotted_order"));
27539
+ return dottedOrder ? dottedOrder.split(".").length : Number.MAX_SAFE_INTEGER;
27540
+ }
27541
+ function mapRunType(runType) {
27542
+ switch (runType) {
27543
+ case "llm":
27544
+ case "embedding":
27545
+ return "llm" /* LLM */;
27546
+ case "tool":
27547
+ case "retriever":
27548
+ return "tool" /* TOOL */;
27549
+ default:
27550
+ return "task" /* TASK */;
27551
+ }
27552
+ }
27553
+ function extractMetadata(run, previous) {
27554
+ const extra = preferOwnValue(run, previous, "extra");
27555
+ const rawMetadata = ownValue(extra, "metadata");
27556
+ if (!isRecord2(rawMetadata)) {
27557
+ return void 0;
27558
+ }
27559
+ const metadata = {};
27560
+ for (const [key, descriptor] of Object.entries(
27561
+ Object.getOwnPropertyDescriptors(rawMetadata)
27562
+ )) {
27563
+ if (!("value" in descriptor) || !descriptor.enumerable || BLOCKED_METADATA_KEYS.has(key) || BLOCKED_METADATA_PREFIXES.some((prefix) => key.startsWith(prefix)) || key.startsWith("ls_") && key !== "ls_provider" && key !== "ls_model_name" && !LLM_SETTING_KEYS.some((setting) => key === `ls_${setting}`)) {
27564
+ continue;
27565
+ }
27566
+ const normalizedKey = key === "ls_provider" ? "provider" : key === "ls_model_name" ? "model" : key.startsWith("ls_") ? key.slice(3) : key;
27567
+ const sanitized = sanitizeLoggedValue(descriptor.value);
27568
+ if (sanitized !== void 0) {
27569
+ metadata[normalizedKey] = sanitized;
27570
+ }
27571
+ }
27572
+ return Object.keys(metadata).length === 0 ? void 0 : metadata;
27573
+ }
27574
+ function extractTags(value) {
27575
+ if (!Array.isArray(value)) {
27576
+ return void 0;
27577
+ }
27578
+ const tags = value.filter(
27579
+ (tag) => typeof tag === "string" && tag.length > 0
27580
+ );
27581
+ return tags.length > 0 ? tags : void 0;
27582
+ }
27583
+ function extractMetrics(run, previous) {
27584
+ const outputs = preferOwnValue(run, previous, "outputs");
27585
+ const extra = preferOwnValue(run, previous, "extra");
27586
+ const metadata = ownValue(extra, "metadata");
27587
+ const usage = ownValue(outputs, "usage_metadata") ?? ownValue(metadata, "usage_metadata");
27588
+ const metrics = {};
27589
+ assignFirstMetric(metrics, "prompt_tokens", usage, [
27590
+ "input_tokens",
27591
+ "prompt_tokens"
27592
+ ]);
27593
+ assignFirstMetric(metrics, "completion_tokens", usage, [
27594
+ "output_tokens",
27595
+ "completion_tokens"
27596
+ ]);
27597
+ assignFirstMetric(metrics, "tokens", usage, ["total_tokens", "tokens"]);
27598
+ const inputTokenDetails = ownValue(usage, "input_token_details");
27599
+ assignFirstMetric(metrics, "prompt_cached_tokens", inputTokenDetails, [
27600
+ "cache_read",
27601
+ "cached_tokens"
27602
+ ]);
27603
+ if (metrics.prompt_cached_tokens === void 0) {
27604
+ assignFirstMetric(metrics, "prompt_cached_tokens", usage, [
27605
+ "cache_read_input_tokens",
27606
+ "prompt_cached_tokens"
27607
+ ]);
27608
+ }
27609
+ assignFirstMetric(
27610
+ metrics,
27611
+ "prompt_cache_creation_tokens",
27612
+ inputTokenDetails,
27613
+ ["cache_creation"]
27614
+ );
27615
+ if (metrics.prompt_cache_creation_tokens === void 0) {
27616
+ assignFirstMetric(metrics, "prompt_cache_creation_tokens", usage, [
27617
+ "cache_creation_input_tokens",
27618
+ "prompt_cache_creation_tokens"
27619
+ ]);
27620
+ }
27621
+ if (metrics.tokens === void 0 && (metrics.prompt_tokens !== void 0 || metrics.completion_tokens !== void 0)) {
27622
+ metrics.tokens = (metrics.prompt_tokens ?? 0) + (metrics.completion_tokens ?? 0);
27623
+ }
27624
+ const startTime = timestampSeconds(
27625
+ preferOwnValue(run, previous, "start_time")
27626
+ );
27627
+ const events = preferOwnValue(run, previous, "events");
27628
+ if (startTime !== void 0 && Array.isArray(events)) {
27629
+ for (const event of events) {
27630
+ if (ownValue(event, "name") !== "new_token") {
27631
+ continue;
27632
+ }
27633
+ const eventTime3 = timestampSeconds(ownValue(event, "time"));
27634
+ if (eventTime3 !== void 0 && eventTime3 >= startTime) {
27635
+ metrics.time_to_first_token = eventTime3 - startTime;
27636
+ }
27637
+ break;
27638
+ }
27639
+ }
27640
+ return metrics;
27641
+ }
27642
+ function assignFirstMetric(metrics, target, source, keys) {
27643
+ for (const key of keys) {
27644
+ const value = ownValue(source, key);
27645
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
27646
+ metrics[target] = value;
27647
+ return;
27648
+ }
27649
+ }
27650
+ }
27651
+ function errorMessage(value) {
27652
+ if (typeof value === "string") {
27653
+ return value;
27654
+ }
27655
+ if (value instanceof Error) {
27656
+ return value.message;
27657
+ }
27658
+ return void 0;
27659
+ }
27660
+ function sanitizeLoggedValue(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
27661
+ if (value === null || typeof value === "string" || typeof value === "boolean") {
27662
+ return value;
27663
+ }
27664
+ if (typeof value === "number") {
27665
+ return Number.isFinite(value) ? value : void 0;
27666
+ }
27667
+ if (value instanceof Date) {
27668
+ return Number.isFinite(value.getTime()) ? value.toISOString() : void 0;
27669
+ }
27670
+ if (typeof value !== "object" || depth >= 20) {
27671
+ return void 0;
27672
+ }
27673
+ if (seen.has(value)) {
27674
+ return "[Circular]";
27675
+ }
27676
+ seen.add(value);
27677
+ if (Array.isArray(value)) {
27678
+ return value.map((item) => sanitizeLoggedValue(item, seen, depth + 1));
27679
+ }
27680
+ const entries = [];
27681
+ for (const [key, descriptor] of Object.entries(
27682
+ Object.getOwnPropertyDescriptors(value)
27683
+ )) {
27684
+ if (!descriptor.enumerable || !("value" in descriptor) || BLOCKED_METADATA_KEYS.has(key)) {
27685
+ continue;
27686
+ }
27687
+ entries.push([key, sanitizeLoggedValue(descriptor.value, seen, depth + 1)]);
27688
+ }
27689
+ return Object.fromEntries(entries);
27690
+ }
27691
+
27191
27692
  // src/instrumentation/plugins/pi-coding-agent-channels.ts
27192
27693
  var piCodingAgentChannels = defineChannels(
27193
27694
  "@earendil-works/pi-coding-agent",
@@ -27567,11 +28068,11 @@ function patchAssistantMessageStream(stream, promptState, llmState) {
27567
28068
  function recordPiAssistantMessageEvent(promptState, llmState, event) {
27568
28069
  recordFirstTokenMetric(llmState, event);
27569
28070
  const message = "message" in event ? event.message : void 0;
27570
- const errorMessage = "error" in event ? event.error : void 0;
28071
+ const errorMessage2 = "error" in event ? event.error : void 0;
27571
28072
  if (event.type === "done" && isPiAssistantMessage(message)) {
27572
28073
  finishPiLlmSpan(promptState, llmState, message);
27573
- } else if (event.type === "error" && isPiAssistantMessage(errorMessage)) {
27574
- finishPiLlmSpan(promptState, llmState, errorMessage);
28074
+ } else if (event.type === "error" && isPiAssistantMessage(errorMessage2)) {
28075
+ finishPiLlmSpan(promptState, llmState, errorMessage2);
27575
28076
  }
27576
28077
  }
27577
28078
  function recordFirstTokenMetric(state, event) {
@@ -28089,6 +28590,7 @@ var strandsAgentSDKChannels = defineChannels("@strands-agents/sdk", {
28089
28590
  });
28090
28591
 
28091
28592
  // src/instrumentation/plugins/strands-agent-sdk-plugin.ts
28593
+ var MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES = 32;
28092
28594
  var StrandsAgentSDKPlugin = class extends BasePlugin {
28093
28595
  activeChildParents = /* @__PURE__ */ new WeakMap();
28094
28596
  onEnable() {
@@ -28233,11 +28735,16 @@ function startAgentStream(event, activeChildParents) {
28233
28735
  ...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
28234
28736
  };
28235
28737
  const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
28738
+ const attachmentCache = createStrandsAttachmentCache();
28739
+ const input = processStrandsInputAttachments(
28740
+ event.arguments[0],
28741
+ attachmentCache
28742
+ );
28236
28743
  const span = parentSpan ? withCurrent(
28237
28744
  parentSpan,
28238
28745
  () => startSpan({
28239
28746
  event: {
28240
- input: event.arguments[0],
28747
+ input,
28241
28748
  metadata
28242
28749
  },
28243
28750
  name: formatAgentSpanName(agent),
@@ -28245,7 +28752,7 @@ function startAgentStream(event, activeChildParents) {
28245
28752
  })
28246
28753
  ) : startSpan({
28247
28754
  event: {
28248
- input: event.arguments[0],
28755
+ input,
28249
28756
  metadata
28250
28757
  },
28251
28758
  name: formatAgentSpanName(agent),
@@ -28253,6 +28760,7 @@ function startAgentStream(event, activeChildParents) {
28253
28760
  });
28254
28761
  return {
28255
28762
  activeTools: /* @__PURE__ */ new Map(),
28763
+ attachmentCache,
28256
28764
  finalized: false,
28257
28765
  metadata,
28258
28766
  span,
@@ -28268,11 +28776,12 @@ function startMultiAgentStream(event, operation, activeChildParents) {
28268
28776
  ...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
28269
28777
  };
28270
28778
  const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
28779
+ const input = processStrandsInputAttachments(event.arguments[0]);
28271
28780
  const span = parentSpan ? withCurrent(
28272
28781
  parentSpan,
28273
28782
  () => startSpan({
28274
28783
  event: {
28275
- input: event.arguments[0],
28784
+ input,
28276
28785
  metadata
28277
28786
  },
28278
28787
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -28280,7 +28789,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
28280
28789
  })
28281
28790
  ) : startSpan({
28282
28791
  event: {
28283
- input: event.arguments[0],
28792
+ input,
28284
28793
  metadata
28285
28794
  },
28286
28795
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -28389,7 +28898,10 @@ function startModelSpan(state, event) {
28389
28898
  state.span,
28390
28899
  () => startSpan({
28391
28900
  event: {
28392
- input: Array.isArray(event.agent?.messages) ? event.agent.messages : void 0,
28901
+ input: Array.isArray(event.agent?.messages) ? processStrandsInputAttachments(
28902
+ event.agent.messages,
28903
+ state.attachmentCache
28904
+ ) : void 0,
28393
28905
  metadata
28394
28906
  },
28395
28907
  name: formatModelSpanName(model),
@@ -28603,6 +29115,7 @@ function finalizeAgentStream(state, error, output) {
28603
29115
  ...output !== void 0 ? { output } : {}
28604
29116
  });
28605
29117
  state.span.end();
29118
+ state.attachmentCache.strings.clear();
28606
29119
  }
28607
29120
  function finalizeMultiAgentStream(state, activeChildParents, error, output) {
28608
29121
  if (state.finalized) {
@@ -28749,6 +29262,166 @@ function extractNodeResultOutput(result) {
28749
29262
  }
28750
29263
  return result;
28751
29264
  }
29265
+ var STRANDS_MEDIA_TYPES = {
29266
+ png: "image/png",
29267
+ jpg: "image/jpeg",
29268
+ jpeg: "image/jpeg",
29269
+ gif: "image/gif",
29270
+ webp: "image/webp",
29271
+ mkv: "video/x-matroska",
29272
+ mov: "video/quicktime",
29273
+ mp4: "video/mp4",
29274
+ webm: "video/webm",
29275
+ flv: "video/x-flv",
29276
+ mpeg: "video/mpeg",
29277
+ mpg: "video/mpeg",
29278
+ wmv: "video/x-ms-wmv",
29279
+ "3gp": "video/3gpp",
29280
+ pdf: "application/pdf",
29281
+ csv: "text/csv",
29282
+ doc: "application/msword",
29283
+ docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
29284
+ xls: "application/vnd.ms-excel",
29285
+ xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
29286
+ html: "text/html",
29287
+ txt: "text/plain",
29288
+ md: "text/markdown",
29289
+ json: "application/json",
29290
+ xml: "application/xml"
29291
+ };
29292
+ function createStrandsAttachmentCache() {
29293
+ return {
29294
+ objects: /* @__PURE__ */ new WeakMap(),
29295
+ strings: new LRUCache({
29296
+ max: MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES
29297
+ })
29298
+ };
29299
+ }
29300
+ function processStrandsInputAttachments(input, cache = createStrandsAttachmentCache()) {
29301
+ try {
29302
+ return processStrandsInputNode(input, cache);
29303
+ } catch (error) {
29304
+ logInstrumentationError5("Strands Agent SDK input attachments", error);
29305
+ return input;
29306
+ }
29307
+ }
29308
+ function processStrandsInputNode(value, cache) {
29309
+ if (value instanceof BaseAttachment) {
29310
+ return value;
29311
+ }
29312
+ if (Array.isArray(value)) {
29313
+ return value.map((child) => processStrandsInputNode(child, cache));
29314
+ }
29315
+ if (!isObject(value)) {
29316
+ return value;
29317
+ }
29318
+ const directMedia = processDirectStrandsMediaBlock(value, cache);
29319
+ if (directMedia !== void 0) {
29320
+ return directMedia;
29321
+ }
29322
+ const wrappedMedia = processWrappedStrandsMediaBlock(value, cache);
29323
+ if (wrappedMedia !== void 0) {
29324
+ return wrappedMedia;
29325
+ }
29326
+ if (value.type === "message" && Array.isArray(value.content)) {
29327
+ return {
29328
+ role: value.role,
29329
+ content: value.content.map(
29330
+ (child) => processStrandsInputNode(child, cache)
29331
+ ),
29332
+ ...value.metadata !== void 0 ? { metadata: value.metadata } : {}
29333
+ };
29334
+ }
29335
+ if (typeof value.toJSON === "function") {
29336
+ return processStrandsInputNode(value.toJSON(), cache);
29337
+ }
29338
+ return Object.fromEntries(
29339
+ Object.entries(value).map(([key, child]) => [
29340
+ key,
29341
+ processStrandsInputNode(child, cache)
29342
+ ])
29343
+ );
29344
+ }
29345
+ function processDirectStrandsMediaBlock(block, cache) {
29346
+ if (!isStrandsMediaBlock(block)) {
29347
+ return void 0;
29348
+ }
29349
+ const mediaKey = block.type === "imageBlock" ? "image" : block.type === "videoBlock" ? "video" : "document";
29350
+ return createStrandsMediaAttachment(mediaKey, block, cache);
29351
+ }
29352
+ function isStrandsMediaBlock(block) {
29353
+ return (block.type === "imageBlock" || block.type === "videoBlock" || block.type === "documentBlock") && typeof block.format === "string" && isObject(block.source);
29354
+ }
29355
+ function processWrappedStrandsMediaBlock(block, cache) {
29356
+ for (const mediaKey of ["image", "video", "document"]) {
29357
+ const media = block[mediaKey];
29358
+ if (!Object.hasOwn(block, mediaKey) || !isObject(media)) {
29359
+ continue;
29360
+ }
29361
+ const processed = createStrandsMediaAttachment(mediaKey, media, cache);
29362
+ if (processed !== void 0) {
29363
+ return processed;
29364
+ }
29365
+ }
29366
+ return void 0;
29367
+ }
29368
+ function createStrandsMediaAttachment(mediaKey, media, cache) {
29369
+ const format = media.format;
29370
+ const source = media.source;
29371
+ if (typeof format !== "string" || !isObject(source) || !Object.hasOwn(source, "bytes")) {
29372
+ return void 0;
29373
+ }
29374
+ const contentType = STRANDS_MEDIA_TYPES[format.toLowerCase()];
29375
+ if (!contentType) {
29376
+ return void 0;
29377
+ }
29378
+ const filename = mediaKey === "document" && typeof media.name === "string" && media.name.length > 0 ? media.name : `${mediaKey}.${format.toLowerCase()}`;
29379
+ const attachment = getOrCreateStrandsAttachment(
29380
+ source.bytes,
29381
+ filename,
29382
+ contentType,
29383
+ cache
29384
+ );
29385
+ if (!attachment) {
29386
+ return void 0;
29387
+ }
29388
+ const { type: _type, ...serializedMedia } = media;
29389
+ const { type: _sourceType, ...serializedSource } = source;
29390
+ return {
29391
+ [mediaKey]: {
29392
+ ...serializedMedia,
29393
+ source: {
29394
+ ...serializedSource,
29395
+ bytes: attachment
29396
+ }
29397
+ }
29398
+ };
29399
+ }
29400
+ function getOrCreateStrandsAttachment(data, filename, contentType, cache) {
29401
+ const key = `${contentType}\0${filename}`;
29402
+ const attachments = typeof data === "string" ? cache.strings.get(data) : isObject(data) ? cache.objects.get(data) : void 0;
29403
+ const cached = attachments?.get(key);
29404
+ if (cached) {
29405
+ return cached;
29406
+ }
29407
+ const blob = convertDataToBlob(data, contentType);
29408
+ if (!blob) {
29409
+ return void 0;
29410
+ }
29411
+ const attachment = new Attachment({
29412
+ data: blob,
29413
+ filename,
29414
+ contentType
29415
+ });
29416
+ const updatedAttachments = attachments ?? /* @__PURE__ */ new Map();
29417
+ updatedAttachments.set(key, attachment);
29418
+ if (typeof data === "string") {
29419
+ cache.strings.set(data, updatedAttachments);
29420
+ } else if (isObject(data)) {
29421
+ cache.objects.set(data, updatedAttachments);
29422
+ }
29423
+ return attachment;
29424
+ }
28752
29425
  function normalizeContentBlocks(blocks) {
28753
29426
  const text = blocks.map((block) => typeof block.text === "string" ? block.text : void 0).filter((part) => Boolean(part)).join("");
28754
29427
  return text.length > 0 ? text : blocks;
@@ -28878,6 +29551,7 @@ var BraintrustPlugin = class extends BasePlugin {
28878
29551
  gitHubCopilotPlugin = null;
28879
29552
  fluePlugin = null;
28880
29553
  langChainPlugin = null;
29554
+ langSmithPlugin = null;
28881
29555
  piCodingAgentPlugin = null;
28882
29556
  strandsAgentSDKPlugin = null;
28883
29557
  constructor(config = {}) {
@@ -28974,6 +29648,12 @@ var BraintrustPlugin = class extends BasePlugin {
28974
29648
  this.langChainPlugin = new LangChainPlugin();
28975
29649
  this.langChainPlugin.enable();
28976
29650
  }
29651
+ if (integrations.langsmith !== false) {
29652
+ this.langSmithPlugin = new LangSmithPlugin({
29653
+ skipLangChainRuns: integrations.langchain !== false
29654
+ });
29655
+ this.langSmithPlugin.enable();
29656
+ }
28977
29657
  }
28978
29658
  onDisable() {
28979
29659
  if (this.openaiPlugin) {
@@ -29064,6 +29744,10 @@ var BraintrustPlugin = class extends BasePlugin {
29064
29744
  this.langChainPlugin.disable();
29065
29745
  this.langChainPlugin = null;
29066
29746
  }
29747
+ if (this.langSmithPlugin) {
29748
+ this.langSmithPlugin.disable();
29749
+ this.langSmithPlugin = null;
29750
+ }
29067
29751
  }
29068
29752
  };
29069
29753
 
@@ -29142,9 +29826,6 @@ var EveBridge = class {
29142
29826
  this.state = state;
29143
29827
  }
29144
29828
  eventQueuesBySession = /* @__PURE__ */ new Map();
29145
- sessionsById = new LRUCache({
29146
- max: MAX_EVE_CACHE_ENTRIES
29147
- });
29148
29829
  completedToolKeys = new LRUCache({
29149
29830
  max: MAX_EVE_CACHE_ENTRIES
29150
29831
  });
@@ -29311,7 +29992,7 @@ var EveBridge = class {
29311
29992
  async handleEvent(event, ctx, hookMetadata) {
29312
29993
  switch (event.type) {
29313
29994
  case "session.started":
29314
- await this.handleSessionStarted(event, ctx, hookMetadata);
29995
+ this.handleSessionStarted(event, ctx, hookMetadata);
29315
29996
  return true;
29316
29997
  case "turn.started":
29317
29998
  await this.handleTurnStarted(event, ctx, hookMetadata);
@@ -29347,22 +30028,22 @@ var EveBridge = class {
29347
30028
  this.handleStepFailed(event, ctx);
29348
30029
  return true;
29349
30030
  case "turn.completed":
29350
- await this.handleTurnCompleted(event, ctx);
30031
+ this.handleTurnCompleted(event, ctx);
29351
30032
  return true;
29352
30033
  case "turn.failed":
29353
- await this.handleTurnFailed(event, ctx);
30034
+ this.handleTurnFailed(event, ctx);
29354
30035
  return true;
29355
30036
  case "session.failed":
29356
- await this.handleSessionFailed(event, ctx);
30037
+ this.handleSessionFailed(event, ctx);
29357
30038
  return true;
29358
30039
  case "session.completed":
29359
- await this.handleSessionCompleted(event, ctx);
30040
+ this.handleSessionCompleted(event, ctx);
29360
30041
  return true;
29361
30042
  default:
29362
30043
  return false;
29363
30044
  }
29364
30045
  }
29365
- async handleSessionStarted(event, ctx, hookMetadata) {
30046
+ handleSessionStarted(event, ctx, hookMetadata) {
29366
30047
  const sessionId = sessionIdFromContext(ctx);
29367
30048
  if (!sessionId) {
29368
30049
  return;
@@ -29378,7 +30059,6 @@ var EveBridge = class {
29378
30059
  metadata: { ...normalized.metadata, ...metadata }
29379
30060
  };
29380
30061
  });
29381
- await this.ensureSession(sessionId, ctx, metadata, eventTime2(event));
29382
30062
  for (const [key, turn] of this.turnsByKey) {
29383
30063
  if (!key.startsWith(`${sessionId}:`)) {
29384
30064
  continue;
@@ -29396,21 +30076,19 @@ var EveBridge = class {
29396
30076
  if (!sessionId) {
29397
30077
  return;
29398
30078
  }
29399
- const session = await this.ensureSession(
29400
- sessionId,
29401
- ctx,
29402
- hookMetadata ?? {},
29403
- eventTime2(event)
29404
- );
29405
30079
  const key = turnKey2(sessionId, event.data.turnId);
29406
- const metadata = { ...session.metadata };
30080
+ const metadata = {
30081
+ ...readEveTraceState(this.state).metadata,
30082
+ ...hookMetadata ?? {},
30083
+ "eve.session_id": sessionId
30084
+ };
29407
30085
  const existing = this.turnsByKey.get(key);
29408
30086
  if (existing) {
29409
30087
  existing.metadata = { ...existing.metadata, ...metadata };
29410
30088
  existing.span.log({ metadata: existing.metadata });
29411
30089
  return;
29412
30090
  }
29413
- const span = await this.startTurnSpan(session, event, metadata);
30091
+ const span = await this.startTurnSpan(sessionId, event, ctx, metadata);
29414
30092
  span.log({ metadata });
29415
30093
  this.turnsByKey.set(key, {
29416
30094
  key,
@@ -29448,10 +30126,7 @@ var EveBridge = class {
29448
30126
  this.markStepEnded(event.data.turnId, event.data.stepIndex);
29449
30127
  }
29450
30128
  const stepOrdinal = this.stepOrdinal(event);
29451
- const metadata = {
29452
- ...turn.metadata,
29453
- ...this.sessionsById.get(sessionId)?.metadata ?? {}
29454
- };
30129
+ const metadata = { ...turn.metadata };
29455
30130
  const input = consumeCapturedEveModelInput(
29456
30131
  this.state,
29457
30132
  sessionId,
@@ -29546,6 +30221,28 @@ var EveBridge = class {
29546
30221
  if (!step) {
29547
30222
  return;
29548
30223
  }
30224
+ const toolCallsById = /* @__PURE__ */ new Map();
30225
+ if (Array.isArray(step.output) && isObject(step.output[0])) {
30226
+ const message = step.output[0]["message"];
30227
+ if (isObject(message) && Array.isArray(message["tool_calls"])) {
30228
+ for (const toolCall of message["tool_calls"]) {
30229
+ if (isObject(toolCall) && typeof toolCall["id"] === "string") {
30230
+ toolCallsById.set(toolCall["id"], toolCall);
30231
+ }
30232
+ }
30233
+ }
30234
+ }
30235
+ for (const action of traceActions) {
30236
+ const name = action.kind === "tool-call" ? action.toolName : action.subagentName ?? action.name ?? "agent";
30237
+ toolCallsById.set(action.callId, {
30238
+ function: {
30239
+ arguments: JSON.stringify(action.input),
30240
+ name
30241
+ },
30242
+ id: action.callId,
30243
+ type: "function"
30244
+ });
30245
+ }
29549
30246
  step.output = [
29550
30247
  {
29551
30248
  finish_reason: "tool_calls",
@@ -29553,17 +30250,7 @@ var EveBridge = class {
29553
30250
  message: {
29554
30251
  content: null,
29555
30252
  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
- })
30253
+ tool_calls: [...toolCallsById.values()]
29567
30254
  }
29568
30255
  }
29569
30256
  ];
@@ -29810,17 +30497,11 @@ var EveBridge = class {
29810
30497
  )
29811
30498
  });
29812
30499
  }
29813
- async handleSessionFailed(event, ctx) {
30500
+ handleSessionFailed(event, ctx) {
29814
30501
  const sessionId = event.data.sessionId || sessionIdFromContext(ctx);
29815
30502
  if (!sessionId) {
29816
30503
  return;
29817
30504
  }
29818
- const session = await this.ensureSession(
29819
- sessionId,
29820
- ctx,
29821
- {},
29822
- eventTime2(event)
29823
- );
29824
30505
  const error = errorFromMessage(
29825
30506
  event.data.message,
29826
30507
  event.data.code,
@@ -29837,29 +30518,20 @@ var EveBridge = class {
29837
30518
  }
29838
30519
  for (const [key, tool] of this.toolsByCallKey) {
29839
30520
  if (key.startsWith(`${sessionId}:`)) {
29840
- const endTime2 = eventTime2(event);
30521
+ const endTime = eventTime2(event);
29841
30522
  if (!tool.endedByTurn) {
29842
30523
  tool.span.log({ metadata: tool.metadata });
29843
- tool.span.end(endTime2 === void 0 ? void 0 : { endTime: endTime2 });
30524
+ tool.span.end(endTime === void 0 ? void 0 : { endTime });
29844
30525
  tool.endedByTurn = true;
29845
30526
  }
29846
30527
  }
29847
30528
  }
29848
- session.span.log({ error });
29849
- const endTime = eventTime2(event);
29850
- session.span.end(endTime === void 0 ? void 0 : { endTime });
29851
30529
  }
29852
- async handleSessionCompleted(event, ctx) {
30530
+ handleSessionCompleted(event, ctx) {
29853
30531
  const sessionId = sessionIdFromContext(ctx);
29854
30532
  if (!sessionId) {
29855
30533
  return;
29856
30534
  }
29857
- const session = await this.ensureSession(
29858
- sessionId,
29859
- ctx,
29860
- {},
29861
- eventTime2(event)
29862
- );
29863
30535
  for (const [key, turn] of this.turnsByKey) {
29864
30536
  if (!key.startsWith(`${sessionId}:`)) {
29865
30537
  continue;
@@ -29870,82 +30542,29 @@ var EveBridge = class {
29870
30542
  }
29871
30543
  for (const [key, tool] of this.toolsByCallKey) {
29872
30544
  if (key.startsWith(`${sessionId}:`) && !tool.endedByTurn) {
29873
- const endTime2 = eventTime2(event);
30545
+ const endTime = eventTime2(event);
29874
30546
  tool.span.log({ metadata: tool.metadata });
29875
- tool.span.end(endTime2 === void 0 ? void 0 : { endTime: endTime2 });
30547
+ tool.span.end(endTime === void 0 ? void 0 : { endTime });
29876
30548
  tool.endedByTurn = true;
29877
30549
  }
29878
30550
  }
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
30551
  }
29931
30552
  async ensureTurn(event, ctx, hookMetadata) {
29932
30553
  const sessionId = sessionIdFromContext(ctx);
29933
30554
  if (!sessionId) {
29934
30555
  return void 0;
29935
30556
  }
29936
- const session = await this.ensureSession(
29937
- sessionId,
29938
- ctx,
29939
- hookMetadata ?? {},
29940
- eventTime2(event)
29941
- );
29942
30557
  const key = turnKey2(sessionId, event.data.turnId);
29943
30558
  const existing = this.turnsByKey.get(key);
29944
30559
  if (existing) {
29945
30560
  return existing;
29946
30561
  }
29947
- const metadata = { ...session.metadata };
29948
- const span = await this.startTurnSpan(session, event, metadata);
30562
+ const metadata = {
30563
+ ...readEveTraceState(this.state).metadata,
30564
+ ...hookMetadata ?? {},
30565
+ "eve.session_id": sessionId
30566
+ };
30567
+ const span = await this.startTurnSpan(sessionId, event, ctx, metadata);
29949
30568
  span.log({ metadata });
29950
30569
  const state = {
29951
30570
  key,
@@ -30132,22 +30751,35 @@ var EveBridge = class {
30132
30751
  this.toolsByCallKey.set(toolKey3(sessionId, result.callId), state);
30133
30752
  return state;
30134
30753
  }
30135
- async startTurnSpan(session, event, metadata) {
30136
- const { rowId: eventId, spanId } = await generateEveIds(
30137
- "turn",
30138
- session.sessionId,
30139
- event.data.turnId
30140
- );
30754
+ async startTurnSpan(sessionId, event, ctx, metadata) {
30755
+ const session = isObject(ctx) ? ctx["session"] : void 0;
30756
+ const parent = isObject(session) ? session["parent"] : void 0;
30757
+ const parentTurn = isObject(parent) ? parent["turn"] : void 0;
30758
+ const parentLineage = isObject(parent) && typeof parent["callId"] === "string" && typeof parent["sessionId"] === "string" && isObject(parentTurn) && typeof parentTurn["id"] === "string" ? {
30759
+ callId: parent["callId"],
30760
+ sessionId: parent["sessionId"],
30761
+ turnId: parentTurn["id"]
30762
+ } : void 0;
30763
+ const [{ rowId: eventId, spanId }, rootSpanId, parentSpanId] = await Promise.all([
30764
+ generateEveIds("turn", sessionId, event.data.turnId),
30765
+ deterministicEveId(
30766
+ "eve:root",
30767
+ parentLineage?.sessionId ?? sessionId,
30768
+ parentLineage?.turnId ?? event.data.turnId
30769
+ ),
30770
+ parentLineage ? deterministicEveId(
30771
+ "eve:subagent",
30772
+ parentLineage.sessionId,
30773
+ parentLineage.callId
30774
+ ) : Promise.resolve(void 0)
30775
+ ]);
30141
30776
  return await this.startEveSpan({
30142
30777
  event: {
30143
30778
  id: eventId,
30144
30779
  metadata
30145
30780
  },
30146
30781
  name: "eve.turn",
30147
- parentSpanIds: {
30148
- rootSpanId: session.span.rootSpanId,
30149
- spanId: session.span.spanId
30150
- },
30782
+ parentSpanIds: parentSpanId ? { rootSpanId, spanId: parentSpanId } : { parentSpanIds: [], rootSpanId },
30151
30783
  spanAttributes: { type: "task" /* TASK */ },
30152
30784
  spanId,
30153
30785
  startTime: eventTime2(event)
@@ -30208,7 +30840,6 @@ var EveBridge = class {
30208
30840
  }
30209
30841
  cleanupSession(sessionId) {
30210
30842
  const keyPrefix = `${sessionId}:`;
30211
- this.sessionsById.delete(sessionId);
30212
30843
  for (const key of this.turnsByKey.keys()) {
30213
30844
  if (key.startsWith(keyPrefix)) {
30214
30845
  this.turnsByKey.delete(key);
@@ -30399,7 +31030,7 @@ function modelMetadataFromRuntime(runtime) {
30399
31030
  return {};
30400
31031
  }
30401
31032
  const modelId = runtime["modelId"];
30402
- return typeof modelId === "string" ? modelMetadataFromModelId(modelId) : {};
31033
+ return typeof modelId === "string" && !modelId.trim().startsWith("dynamic:") ? modelMetadataFromModelId(modelId) : {};
30403
31034
  }
30404
31035
  function modelMetadataFromModelId(modelId) {
30405
31036
  const normalized = modelId.trim();
@@ -30432,26 +31063,6 @@ function toolMetadataFromTurn(turn) {
30432
31063
  const { model: _model, provider: _provider, ...metadata } = turn.metadata;
30433
31064
  return metadata;
30434
31065
  }
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
31066
  function isToolCallAction(action) {
30456
31067
  return isObject(action) && action["kind"] === "tool-call" && typeof action["callId"] === "string" && typeof action["toolName"] === "string" && isObject(action["input"]);
30457
31068
  }
@@ -30507,9 +31118,6 @@ function turnKey2(sessionId, turnId) {
30507
31118
  function toolKey3(sessionId, callId) {
30508
31119
  return `${sessionId}:${callId}`;
30509
31120
  }
30510
- async function rootSpanIdForSession(sessionId) {
30511
- return deterministicEveId("eve:root", sessionId);
30512
- }
30513
31121
  async function generateEveIds(kind, ...parts) {
30514
31122
  const [rowId, spanId] = await Promise.all([
30515
31123
  deterministicEveId(`eve:row:${kind}`, ...parts),
@@ -30517,9 +31125,6 @@ async function generateEveIds(kind, ...parts) {
30517
31125
  ]);
30518
31126
  return { rowId, spanId };
30519
31127
  }
30520
- async function spanIdForSubagent(sessionId, callId) {
30521
- return deterministicEveId("eve:subagent", sessionId, callId);
30522
- }
30523
31128
  async function deterministicEveId(...parts) {
30524
31129
  const data = new TextEncoder().encode(
30525
31130
  parts.map((part) => `${part.length}:${part}`).join("\0")
@@ -30591,7 +31196,8 @@ var envIntegrationAliases = {
30591
31196
  langchain: "langchain",
30592
31197
  "langchain-js": "langchain",
30593
31198
  "@langchain": "langchain",
30594
- langgraph: "langgraph"
31199
+ langgraph: "langgraph",
31200
+ langsmith: "langsmith"
30595
31201
  };
30596
31202
  function getDefaultInstrumentationIntegrations() {
30597
31203
  return {
@@ -30622,6 +31228,7 @@ function getDefaultInstrumentationIntegrations() {
30622
31228
  gitHubCopilot: true,
30623
31229
  langchain: true,
30624
31230
  langgraph: true,
31231
+ langsmith: true,
30625
31232
  piCodingAgent: true,
30626
31233
  strandsAgentSDK: true
30627
31234
  };