braintrust 3.22.0 → 3.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +43 -0
  2. package/dev/dist/index.d.mts +1 -1
  3. package/dev/dist/index.d.ts +1 -1
  4. package/dev/dist/index.js +1354 -654
  5. package/dev/dist/index.mjs +736 -36
  6. package/dist/apply-auto-instrumentation.js +222 -186
  7. package/dist/apply-auto-instrumentation.mjs +37 -1
  8. package/dist/auto-instrumentations/bundler/esbuild.cjs +53 -1
  9. package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
  10. package/dist/auto-instrumentations/bundler/next.cjs +53 -1
  11. package/dist/auto-instrumentations/bundler/next.mjs +3 -3
  12. package/dist/auto-instrumentations/bundler/rollup.cjs +53 -1
  13. package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
  14. package/dist/auto-instrumentations/bundler/vite.cjs +53 -1
  15. package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
  16. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +53 -1
  17. package/dist/auto-instrumentations/bundler/webpack.cjs +53 -1
  18. package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
  19. package/dist/auto-instrumentations/{chunk-TKRPRPGD.mjs → chunk-EXY7QCJD.mjs} +5 -2
  20. package/dist/auto-instrumentations/{chunk-T6J4C7LX.mjs → chunk-KIMLYPRW.mjs} +1 -1
  21. package/dist/auto-instrumentations/{chunk-BRQX23KL.mjs → chunk-YXLNSAMJ.mjs} +51 -0
  22. package/dist/auto-instrumentations/hook.mjs +149 -20
  23. package/dist/auto-instrumentations/index.cjs +52 -0
  24. package/dist/auto-instrumentations/index.d.mts +3 -1
  25. package/dist/auto-instrumentations/index.d.ts +3 -1
  26. package/dist/auto-instrumentations/index.mjs +3 -1
  27. package/dist/browser.d.mts +11 -13
  28. package/dist/browser.d.ts +11 -13
  29. package/dist/browser.js +1098 -205
  30. package/dist/browser.mjs +1098 -205
  31. package/dist/{chunk-KMGUTPB7.mjs → chunk-36IPYKMG.mjs} +20 -1
  32. package/dist/{chunk-MWVVR5LR.js → chunk-B6ZQIAK3.js} +1506 -822
  33. package/dist/{chunk-BFGIH2ZJ.js → chunk-CDIKAHDZ.js} +21 -2
  34. package/dist/{chunk-ZG2O3XVF.mjs → chunk-RBXD2KYN.mjs} +719 -35
  35. package/dist/cli.js +737 -37
  36. package/dist/edge-light.d.mts +1 -1
  37. package/dist/edge-light.d.ts +1 -1
  38. package/dist/edge-light.js +1098 -205
  39. package/dist/edge-light.mjs +1098 -205
  40. package/dist/index.d.mts +11 -13
  41. package/dist/index.d.ts +11 -13
  42. package/dist/index.js +786 -593
  43. package/dist/index.mjs +346 -153
  44. package/dist/instrumentation/index.d.mts +3 -11
  45. package/dist/instrumentation/index.d.ts +3 -11
  46. package/dist/instrumentation/index.js +788 -183
  47. package/dist/instrumentation/index.mjs +788 -183
  48. package/dist/vitest-evals-reporter.js +16 -16
  49. package/dist/vitest-evals-reporter.mjs +2 -2
  50. package/dist/workerd.d.mts +1 -1
  51. package/dist/workerd.d.ts +1 -1
  52. package/dist/workerd.js +1098 -205
  53. package/dist/workerd.mjs +1098 -205
  54. package/package.json +1 -1
@@ -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;
@@ -15945,8 +16006,6 @@ function filterSerializableOptions(options) {
15945
16006
  "additionalDirectories",
15946
16007
  "permissionMode",
15947
16008
  "debug",
15948
- "apiKey",
15949
- "apiKeySource",
15950
16009
  "agentName",
15951
16010
  "instructions"
15952
16011
  ];
@@ -27144,6 +27203,446 @@ function isBraintrustHandler(handler) {
27144
27203
  return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
27145
27204
  }
27146
27205
 
27206
+ // src/instrumentation/plugins/langsmith-channels.ts
27207
+ var langSmithChannels = defineChannels("langsmith", {
27208
+ createRun: channel({
27209
+ channelName: "Client.createRun",
27210
+ kind: "async"
27211
+ }),
27212
+ updateRun: channel({
27213
+ channelName: "Client.updateRun",
27214
+ kind: "async"
27215
+ }),
27216
+ batchIngestRuns: channel({
27217
+ channelName: "Client.batchIngestRuns",
27218
+ kind: "async"
27219
+ })
27220
+ });
27221
+
27222
+ // src/instrumentation/plugins/langsmith-plugin.ts
27223
+ var MAX_COMPLETED_RUNS = 1e4;
27224
+ var BLOCKED_METADATA_KEYS = /* @__PURE__ */ new Set([
27225
+ "__proto__",
27226
+ "constructor",
27227
+ "prototype",
27228
+ "usage_metadata"
27229
+ ]);
27230
+ var BLOCKED_METADATA_PREFIXES = ["__pregel_", "langgraph_", "lc_"];
27231
+ var LLM_SETTING_KEYS = [
27232
+ "temperature",
27233
+ "top_p",
27234
+ "max_tokens",
27235
+ "frequency_penalty",
27236
+ "presence_penalty",
27237
+ "stop",
27238
+ "response_format"
27239
+ ];
27240
+ var LangSmithPlugin = class extends BasePlugin {
27241
+ activeRuns = /* @__PURE__ */ new Map();
27242
+ completedRuns = new LRUCache({
27243
+ max: MAX_COMPLETED_RUNS
27244
+ });
27245
+ skipLangChainRuns;
27246
+ constructor(options = {}) {
27247
+ super();
27248
+ this.skipLangChainRuns = options.skipLangChainRuns ?? true;
27249
+ }
27250
+ onEnable() {
27251
+ const createChannel = langSmithChannels.createRun.tracingChannel();
27252
+ const createHandlers = {
27253
+ start: (event) => {
27254
+ this.containLifecycleFailure("createRun", () => {
27255
+ this.processCreate(event.arguments[0]);
27256
+ });
27257
+ }
27258
+ };
27259
+ createChannel.subscribe(createHandlers);
27260
+ this.unsubscribers.push(() => createChannel.unsubscribe(createHandlers));
27261
+ const updateChannel = langSmithChannels.updateRun.tracingChannel();
27262
+ const updateHandlers = {
27263
+ start: (event) => {
27264
+ this.containLifecycleFailure("updateRun", () => {
27265
+ this.processUpdate(event.arguments[0], event.arguments[1]);
27266
+ });
27267
+ }
27268
+ };
27269
+ updateChannel.subscribe(updateHandlers);
27270
+ this.unsubscribers.push(() => updateChannel.unsubscribe(updateHandlers));
27271
+ const batchChannel = langSmithChannels.batchIngestRuns.tracingChannel();
27272
+ const batchHandlers = {
27273
+ start: (event) => {
27274
+ this.containLifecycleFailure("batchIngestRuns", () => {
27275
+ this.processBatch(event.arguments[0]);
27276
+ });
27277
+ }
27278
+ };
27279
+ batchChannel.subscribe(batchHandlers);
27280
+ this.unsubscribers.push(() => batchChannel.unsubscribe(batchHandlers));
27281
+ }
27282
+ onDisable() {
27283
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
27284
+ for (const { span } of this.activeRuns.values()) {
27285
+ span.end();
27286
+ }
27287
+ this.activeRuns.clear();
27288
+ this.completedRuns.clear();
27289
+ }
27290
+ processBatch(batch) {
27291
+ if (!isRecord2(batch)) {
27292
+ return;
27293
+ }
27294
+ const creates = ownValue(batch, "runCreates");
27295
+ if (Array.isArray(creates)) {
27296
+ const parentFirst = [...creates].sort((left, right) => {
27297
+ const leftId = stringValue2(ownValue(left, "id"));
27298
+ const rightId = stringValue2(ownValue(right, "id"));
27299
+ const leftParent = stringValue2(ownValue(left, "parent_run_id"));
27300
+ const rightParent = stringValue2(ownValue(right, "parent_run_id"));
27301
+ if (leftParent && leftParent === rightId) {
27302
+ return 1;
27303
+ }
27304
+ if (rightParent && rightParent === leftId) {
27305
+ return -1;
27306
+ }
27307
+ return dottedOrderDepth(left) - dottedOrderDepth(right);
27308
+ });
27309
+ for (const run of parentFirst) {
27310
+ this.containLifecycleFailure("batchIngestRuns create", () => {
27311
+ this.processCreate(run);
27312
+ });
27313
+ }
27314
+ }
27315
+ const updates = ownValue(batch, "runUpdates");
27316
+ if (Array.isArray(updates)) {
27317
+ for (const run of updates) {
27318
+ this.containLifecycleFailure("batchIngestRuns update", () => {
27319
+ this.processUpdate(stringValue2(ownValue(run, "id")) ?? "", run);
27320
+ });
27321
+ }
27322
+ }
27323
+ }
27324
+ processCreate(run) {
27325
+ const id = stringValue2(ownValue(run, "id"));
27326
+ if (!id || this.completedRuns.get(id)) {
27327
+ return;
27328
+ }
27329
+ if (this.shouldSkipLangChainRun(run)) {
27330
+ this.completedRuns.set(id, true);
27331
+ return;
27332
+ }
27333
+ const active = this.activeRuns.get(id);
27334
+ if (active) {
27335
+ const previous = active.run;
27336
+ active.run = mergeRuns(previous, run);
27337
+ this.logRun(
27338
+ active.span,
27339
+ active.run,
27340
+ previous,
27341
+ timestampSeconds(ownValue(active.run, "end_time")) !== void 0 || errorMessage(ownValue(active.run, "error")) !== void 0
27342
+ );
27343
+ this.endIfComplete(id, active, active.run);
27344
+ return;
27345
+ }
27346
+ const span = this.startRunSpan(id, run);
27347
+ const activeRun = { run, span };
27348
+ this.activeRuns.set(id, activeRun);
27349
+ this.logRun(
27350
+ span,
27351
+ run,
27352
+ void 0,
27353
+ timestampSeconds(ownValue(run, "end_time")) !== void 0 || errorMessage(ownValue(run, "error")) !== void 0
27354
+ );
27355
+ this.endIfComplete(id, activeRun, run);
27356
+ }
27357
+ processUpdate(explicitId, run) {
27358
+ const id = stringValue2(explicitId) ?? stringValue2(ownValue(run, "id"));
27359
+ if (!id || this.completedRuns.get(id)) {
27360
+ return;
27361
+ }
27362
+ if (this.shouldSkipLangChainRun(run)) {
27363
+ const active2 = this.activeRuns.get(id);
27364
+ active2?.span.end();
27365
+ this.activeRuns.delete(id);
27366
+ this.completedRuns.set(id, true);
27367
+ return;
27368
+ }
27369
+ let active = this.activeRuns.get(id);
27370
+ if (!active) {
27371
+ const span = this.startRunSpan(id, run);
27372
+ active = { run, span };
27373
+ this.activeRuns.set(id, active);
27374
+ }
27375
+ const previous = active.run;
27376
+ active.run = mergeRuns(previous, run);
27377
+ this.logRun(active.span, active.run, previous, true);
27378
+ this.endIfComplete(id, active, active.run);
27379
+ }
27380
+ startRunSpan(id, run) {
27381
+ const traceId = stringValue2(ownValue(run, "trace_id")) ?? id;
27382
+ const parentId = stringValue2(ownValue(run, "parent_run_id")) ?? stringValue2(ownValue(ownValue(run, "parent_run"), "id"));
27383
+ const startTime = timestampSeconds(ownValue(run, "start_time"));
27384
+ return startSpan({
27385
+ name: stringValue2(ownValue(run, "name")) ?? "LangSmith run",
27386
+ spanId: id,
27387
+ parentSpanIds: {
27388
+ parentSpanIds: parentId ? [parentId] : [],
27389
+ rootSpanId: traceId
27390
+ },
27391
+ spanAttributes: {
27392
+ type: mapRunType(ownValue(run, "run_type"))
27393
+ },
27394
+ ...startTime === void 0 ? {} : { startTime },
27395
+ event: { id }
27396
+ });
27397
+ }
27398
+ logRun(span, run, previous, includeOutput) {
27399
+ const inputs = preferOwnValue(run, previous, "inputs");
27400
+ const outputs = preferOwnValue(run, previous, "outputs");
27401
+ const error = errorMessage(preferOwnValue(run, previous, "error"));
27402
+ const metadata = extractMetadata(run, previous);
27403
+ const tags = extractTags(preferOwnValue(run, previous, "tags"));
27404
+ const metrics = extractMetrics(run, previous);
27405
+ span.log({
27406
+ ...inputs === void 0 ? {} : { input: sanitizeLoggedValue(inputs) },
27407
+ ...includeOutput && outputs !== void 0 ? { output: sanitizeLoggedValue(outputs) } : {},
27408
+ ...error === void 0 ? {} : { error },
27409
+ ...metadata === void 0 ? {} : { metadata },
27410
+ ...tags === void 0 ? {} : { tags },
27411
+ ...Object.keys(metrics).length === 0 ? {} : { metrics }
27412
+ });
27413
+ }
27414
+ endIfComplete(id, active, run) {
27415
+ const endTime = timestampSeconds(ownValue(run, "end_time"));
27416
+ if (endTime === void 0 && errorMessage(ownValue(run, "error")) === void 0) {
27417
+ return;
27418
+ }
27419
+ active.span.end(endTime === void 0 ? void 0 : { endTime });
27420
+ this.activeRuns.delete(id);
27421
+ this.completedRuns.set(id, true);
27422
+ }
27423
+ shouldSkipLangChainRun(run) {
27424
+ if (!this.skipLangChainRuns) {
27425
+ return false;
27426
+ }
27427
+ const serialized = ownValue(run, "serialized");
27428
+ return isRecord2(serialized) && ownValue(serialized, "lc") === 1;
27429
+ }
27430
+ containLifecycleFailure(operation, fn) {
27431
+ try {
27432
+ fn();
27433
+ } catch (error) {
27434
+ debugLogger.error(
27435
+ `Failed to process LangSmith ${operation} instrumentation:`,
27436
+ error
27437
+ );
27438
+ }
27439
+ }
27440
+ };
27441
+ function ownValue(value, key) {
27442
+ if (!isRecord2(value)) {
27443
+ return void 0;
27444
+ }
27445
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
27446
+ return descriptor && "value" in descriptor ? descriptor.value : void 0;
27447
+ }
27448
+ function preferOwnValue(current, previous, key) {
27449
+ const currentDescriptor = isRecord2(current) ? Object.getOwnPropertyDescriptor(current, key) : void 0;
27450
+ if (currentDescriptor && "value" in currentDescriptor) {
27451
+ return currentDescriptor.value;
27452
+ }
27453
+ return ownValue(previous, key);
27454
+ }
27455
+ function mergeRuns(previous, current) {
27456
+ const entries = /* @__PURE__ */ new Map();
27457
+ for (const value of [previous, current]) {
27458
+ if (!isRecord2(value)) {
27459
+ continue;
27460
+ }
27461
+ for (const [key, descriptor] of Object.entries(
27462
+ Object.getOwnPropertyDescriptors(value)
27463
+ )) {
27464
+ if (descriptor.enumerable && "value" in descriptor) {
27465
+ entries.set(key, descriptor.value);
27466
+ }
27467
+ }
27468
+ }
27469
+ return Object.fromEntries(entries);
27470
+ }
27471
+ function isRecord2(value) {
27472
+ return typeof value === "object" && value !== null && !Array.isArray(value);
27473
+ }
27474
+ function stringValue2(value) {
27475
+ return typeof value === "string" && value.length > 0 ? value : void 0;
27476
+ }
27477
+ function timestampSeconds(value) {
27478
+ if (value instanceof Date) {
27479
+ const timestamp = value.getTime();
27480
+ return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
27481
+ }
27482
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
27483
+ return value > 1e10 ? value / 1e3 : value;
27484
+ }
27485
+ if (typeof value === "string") {
27486
+ const timestamp = Date.parse(value);
27487
+ return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
27488
+ }
27489
+ return void 0;
27490
+ }
27491
+ function dottedOrderDepth(run) {
27492
+ const dottedOrder = stringValue2(ownValue(run, "dotted_order"));
27493
+ return dottedOrder ? dottedOrder.split(".").length : Number.MAX_SAFE_INTEGER;
27494
+ }
27495
+ function mapRunType(runType) {
27496
+ switch (runType) {
27497
+ case "llm":
27498
+ case "embedding":
27499
+ return "llm" /* LLM */;
27500
+ case "tool":
27501
+ case "retriever":
27502
+ return "tool" /* TOOL */;
27503
+ default:
27504
+ return "task" /* TASK */;
27505
+ }
27506
+ }
27507
+ function extractMetadata(run, previous) {
27508
+ const extra = preferOwnValue(run, previous, "extra");
27509
+ const rawMetadata = ownValue(extra, "metadata");
27510
+ if (!isRecord2(rawMetadata)) {
27511
+ return void 0;
27512
+ }
27513
+ const metadata = {};
27514
+ for (const [key, descriptor] of Object.entries(
27515
+ Object.getOwnPropertyDescriptors(rawMetadata)
27516
+ )) {
27517
+ 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}`)) {
27518
+ continue;
27519
+ }
27520
+ const normalizedKey = key === "ls_provider" ? "provider" : key === "ls_model_name" ? "model" : key.startsWith("ls_") ? key.slice(3) : key;
27521
+ const sanitized = sanitizeLoggedValue(descriptor.value);
27522
+ if (sanitized !== void 0) {
27523
+ metadata[normalizedKey] = sanitized;
27524
+ }
27525
+ }
27526
+ return Object.keys(metadata).length === 0 ? void 0 : metadata;
27527
+ }
27528
+ function extractTags(value) {
27529
+ if (!Array.isArray(value)) {
27530
+ return void 0;
27531
+ }
27532
+ const tags = value.filter(
27533
+ (tag) => typeof tag === "string" && tag.length > 0
27534
+ );
27535
+ return tags.length > 0 ? tags : void 0;
27536
+ }
27537
+ function extractMetrics(run, previous) {
27538
+ const outputs = preferOwnValue(run, previous, "outputs");
27539
+ const extra = preferOwnValue(run, previous, "extra");
27540
+ const metadata = ownValue(extra, "metadata");
27541
+ const usage = ownValue(outputs, "usage_metadata") ?? ownValue(metadata, "usage_metadata");
27542
+ const metrics = {};
27543
+ assignFirstMetric(metrics, "prompt_tokens", usage, [
27544
+ "input_tokens",
27545
+ "prompt_tokens"
27546
+ ]);
27547
+ assignFirstMetric(metrics, "completion_tokens", usage, [
27548
+ "output_tokens",
27549
+ "completion_tokens"
27550
+ ]);
27551
+ assignFirstMetric(metrics, "tokens", usage, ["total_tokens", "tokens"]);
27552
+ const inputTokenDetails = ownValue(usage, "input_token_details");
27553
+ assignFirstMetric(metrics, "prompt_cached_tokens", inputTokenDetails, [
27554
+ "cache_read",
27555
+ "cached_tokens"
27556
+ ]);
27557
+ if (metrics.prompt_cached_tokens === void 0) {
27558
+ assignFirstMetric(metrics, "prompt_cached_tokens", usage, [
27559
+ "cache_read_input_tokens",
27560
+ "prompt_cached_tokens"
27561
+ ]);
27562
+ }
27563
+ assignFirstMetric(
27564
+ metrics,
27565
+ "prompt_cache_creation_tokens",
27566
+ inputTokenDetails,
27567
+ ["cache_creation"]
27568
+ );
27569
+ if (metrics.prompt_cache_creation_tokens === void 0) {
27570
+ assignFirstMetric(metrics, "prompt_cache_creation_tokens", usage, [
27571
+ "cache_creation_input_tokens",
27572
+ "prompt_cache_creation_tokens"
27573
+ ]);
27574
+ }
27575
+ if (metrics.tokens === void 0 && (metrics.prompt_tokens !== void 0 || metrics.completion_tokens !== void 0)) {
27576
+ metrics.tokens = (metrics.prompt_tokens ?? 0) + (metrics.completion_tokens ?? 0);
27577
+ }
27578
+ const startTime = timestampSeconds(
27579
+ preferOwnValue(run, previous, "start_time")
27580
+ );
27581
+ const events = preferOwnValue(run, previous, "events");
27582
+ if (startTime !== void 0 && Array.isArray(events)) {
27583
+ for (const event of events) {
27584
+ if (ownValue(event, "name") !== "new_token") {
27585
+ continue;
27586
+ }
27587
+ const eventTime3 = timestampSeconds(ownValue(event, "time"));
27588
+ if (eventTime3 !== void 0 && eventTime3 >= startTime) {
27589
+ metrics.time_to_first_token = eventTime3 - startTime;
27590
+ }
27591
+ break;
27592
+ }
27593
+ }
27594
+ return metrics;
27595
+ }
27596
+ function assignFirstMetric(metrics, target, source, keys) {
27597
+ for (const key of keys) {
27598
+ const value = ownValue(source, key);
27599
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
27600
+ metrics[target] = value;
27601
+ return;
27602
+ }
27603
+ }
27604
+ }
27605
+ function errorMessage(value) {
27606
+ if (typeof value === "string") {
27607
+ return value;
27608
+ }
27609
+ if (value instanceof Error) {
27610
+ return value.message;
27611
+ }
27612
+ return void 0;
27613
+ }
27614
+ function sanitizeLoggedValue(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
27615
+ if (value === null || typeof value === "string" || typeof value === "boolean") {
27616
+ return value;
27617
+ }
27618
+ if (typeof value === "number") {
27619
+ return Number.isFinite(value) ? value : void 0;
27620
+ }
27621
+ if (value instanceof Date) {
27622
+ return Number.isFinite(value.getTime()) ? value.toISOString() : void 0;
27623
+ }
27624
+ if (typeof value !== "object" || depth >= 20) {
27625
+ return void 0;
27626
+ }
27627
+ if (seen.has(value)) {
27628
+ return "[Circular]";
27629
+ }
27630
+ seen.add(value);
27631
+ if (Array.isArray(value)) {
27632
+ return value.map((item) => sanitizeLoggedValue(item, seen, depth + 1));
27633
+ }
27634
+ const entries = [];
27635
+ for (const [key, descriptor] of Object.entries(
27636
+ Object.getOwnPropertyDescriptors(value)
27637
+ )) {
27638
+ if (!descriptor.enumerable || !("value" in descriptor) || BLOCKED_METADATA_KEYS.has(key)) {
27639
+ continue;
27640
+ }
27641
+ entries.push([key, sanitizeLoggedValue(descriptor.value, seen, depth + 1)]);
27642
+ }
27643
+ return Object.fromEntries(entries);
27644
+ }
27645
+
27147
27646
  // src/instrumentation/plugins/pi-coding-agent-channels.ts
27148
27647
  var piCodingAgentChannels = defineChannels(
27149
27648
  "@earendil-works/pi-coding-agent",
@@ -27523,11 +28022,11 @@ function patchAssistantMessageStream(stream, promptState, llmState) {
27523
28022
  function recordPiAssistantMessageEvent(promptState, llmState, event) {
27524
28023
  recordFirstTokenMetric(llmState, event);
27525
28024
  const message = "message" in event ? event.message : void 0;
27526
- const errorMessage = "error" in event ? event.error : void 0;
28025
+ const errorMessage2 = "error" in event ? event.error : void 0;
27527
28026
  if (event.type === "done" && isPiAssistantMessage(message)) {
27528
28027
  finishPiLlmSpan(promptState, llmState, message);
27529
- } else if (event.type === "error" && isPiAssistantMessage(errorMessage)) {
27530
- finishPiLlmSpan(promptState, llmState, errorMessage);
28028
+ } else if (event.type === "error" && isPiAssistantMessage(errorMessage2)) {
28029
+ finishPiLlmSpan(promptState, llmState, errorMessage2);
27531
28030
  }
27532
28031
  }
27533
28032
  function recordFirstTokenMetric(state, event) {
@@ -28045,6 +28544,7 @@ var strandsAgentSDKChannels = defineChannels("@strands-agents/sdk", {
28045
28544
  });
28046
28545
 
28047
28546
  // src/instrumentation/plugins/strands-agent-sdk-plugin.ts
28547
+ var MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES = 32;
28048
28548
  var StrandsAgentSDKPlugin = class extends BasePlugin {
28049
28549
  activeChildParents = /* @__PURE__ */ new WeakMap();
28050
28550
  onEnable() {
@@ -28189,11 +28689,16 @@ function startAgentStream(event, activeChildParents) {
28189
28689
  ...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
28190
28690
  };
28191
28691
  const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
28692
+ const attachmentCache = createStrandsAttachmentCache();
28693
+ const input = processStrandsInputAttachments(
28694
+ event.arguments[0],
28695
+ attachmentCache
28696
+ );
28192
28697
  const span = parentSpan ? withCurrent(
28193
28698
  parentSpan,
28194
28699
  () => startSpan({
28195
28700
  event: {
28196
- input: event.arguments[0],
28701
+ input,
28197
28702
  metadata
28198
28703
  },
28199
28704
  name: formatAgentSpanName(agent),
@@ -28201,7 +28706,7 @@ function startAgentStream(event, activeChildParents) {
28201
28706
  })
28202
28707
  ) : startSpan({
28203
28708
  event: {
28204
- input: event.arguments[0],
28709
+ input,
28205
28710
  metadata
28206
28711
  },
28207
28712
  name: formatAgentSpanName(agent),
@@ -28209,6 +28714,7 @@ function startAgentStream(event, activeChildParents) {
28209
28714
  });
28210
28715
  return {
28211
28716
  activeTools: /* @__PURE__ */ new Map(),
28717
+ attachmentCache,
28212
28718
  finalized: false,
28213
28719
  metadata,
28214
28720
  span,
@@ -28224,11 +28730,12 @@ function startMultiAgentStream(event, operation, activeChildParents) {
28224
28730
  ...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
28225
28731
  };
28226
28732
  const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
28733
+ const input = processStrandsInputAttachments(event.arguments[0]);
28227
28734
  const span = parentSpan ? withCurrent(
28228
28735
  parentSpan,
28229
28736
  () => startSpan({
28230
28737
  event: {
28231
- input: event.arguments[0],
28738
+ input,
28232
28739
  metadata
28233
28740
  },
28234
28741
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -28236,7 +28743,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
28236
28743
  })
28237
28744
  ) : startSpan({
28238
28745
  event: {
28239
- input: event.arguments[0],
28746
+ input,
28240
28747
  metadata
28241
28748
  },
28242
28749
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -28345,7 +28852,10 @@ function startModelSpan(state, event) {
28345
28852
  state.span,
28346
28853
  () => startSpan({
28347
28854
  event: {
28348
- input: Array.isArray(event.agent?.messages) ? event.agent.messages : void 0,
28855
+ input: Array.isArray(event.agent?.messages) ? processStrandsInputAttachments(
28856
+ event.agent.messages,
28857
+ state.attachmentCache
28858
+ ) : void 0,
28349
28859
  metadata
28350
28860
  },
28351
28861
  name: formatModelSpanName(model),
@@ -28559,6 +29069,7 @@ function finalizeAgentStream(state, error, output) {
28559
29069
  ...output !== void 0 ? { output } : {}
28560
29070
  });
28561
29071
  state.span.end();
29072
+ state.attachmentCache.strings.clear();
28562
29073
  }
28563
29074
  function finalizeMultiAgentStream(state, activeChildParents, error, output) {
28564
29075
  if (state.finalized) {
@@ -28705,6 +29216,166 @@ function extractNodeResultOutput(result) {
28705
29216
  }
28706
29217
  return result;
28707
29218
  }
29219
+ var STRANDS_MEDIA_TYPES = {
29220
+ png: "image/png",
29221
+ jpg: "image/jpeg",
29222
+ jpeg: "image/jpeg",
29223
+ gif: "image/gif",
29224
+ webp: "image/webp",
29225
+ mkv: "video/x-matroska",
29226
+ mov: "video/quicktime",
29227
+ mp4: "video/mp4",
29228
+ webm: "video/webm",
29229
+ flv: "video/x-flv",
29230
+ mpeg: "video/mpeg",
29231
+ mpg: "video/mpeg",
29232
+ wmv: "video/x-ms-wmv",
29233
+ "3gp": "video/3gpp",
29234
+ pdf: "application/pdf",
29235
+ csv: "text/csv",
29236
+ doc: "application/msword",
29237
+ docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
29238
+ xls: "application/vnd.ms-excel",
29239
+ xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
29240
+ html: "text/html",
29241
+ txt: "text/plain",
29242
+ md: "text/markdown",
29243
+ json: "application/json",
29244
+ xml: "application/xml"
29245
+ };
29246
+ function createStrandsAttachmentCache() {
29247
+ return {
29248
+ objects: /* @__PURE__ */ new WeakMap(),
29249
+ strings: new LRUCache({
29250
+ max: MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES
29251
+ })
29252
+ };
29253
+ }
29254
+ function processStrandsInputAttachments(input, cache = createStrandsAttachmentCache()) {
29255
+ try {
29256
+ return processStrandsInputNode(input, cache);
29257
+ } catch (error) {
29258
+ logInstrumentationError5("Strands Agent SDK input attachments", error);
29259
+ return input;
29260
+ }
29261
+ }
29262
+ function processStrandsInputNode(value, cache) {
29263
+ if (value instanceof BaseAttachment) {
29264
+ return value;
29265
+ }
29266
+ if (Array.isArray(value)) {
29267
+ return value.map((child) => processStrandsInputNode(child, cache));
29268
+ }
29269
+ if (!isObject(value)) {
29270
+ return value;
29271
+ }
29272
+ const directMedia = processDirectStrandsMediaBlock(value, cache);
29273
+ if (directMedia !== void 0) {
29274
+ return directMedia;
29275
+ }
29276
+ const wrappedMedia = processWrappedStrandsMediaBlock(value, cache);
29277
+ if (wrappedMedia !== void 0) {
29278
+ return wrappedMedia;
29279
+ }
29280
+ if (value.type === "message" && Array.isArray(value.content)) {
29281
+ return {
29282
+ role: value.role,
29283
+ content: value.content.map(
29284
+ (child) => processStrandsInputNode(child, cache)
29285
+ ),
29286
+ ...value.metadata !== void 0 ? { metadata: value.metadata } : {}
29287
+ };
29288
+ }
29289
+ if (typeof value.toJSON === "function") {
29290
+ return processStrandsInputNode(value.toJSON(), cache);
29291
+ }
29292
+ return Object.fromEntries(
29293
+ Object.entries(value).map(([key, child]) => [
29294
+ key,
29295
+ processStrandsInputNode(child, cache)
29296
+ ])
29297
+ );
29298
+ }
29299
+ function processDirectStrandsMediaBlock(block, cache) {
29300
+ if (!isStrandsMediaBlock(block)) {
29301
+ return void 0;
29302
+ }
29303
+ const mediaKey = block.type === "imageBlock" ? "image" : block.type === "videoBlock" ? "video" : "document";
29304
+ return createStrandsMediaAttachment(mediaKey, block, cache);
29305
+ }
29306
+ function isStrandsMediaBlock(block) {
29307
+ return (block.type === "imageBlock" || block.type === "videoBlock" || block.type === "documentBlock") && typeof block.format === "string" && isObject(block.source);
29308
+ }
29309
+ function processWrappedStrandsMediaBlock(block, cache) {
29310
+ for (const mediaKey of ["image", "video", "document"]) {
29311
+ const media = block[mediaKey];
29312
+ if (!Object.hasOwn(block, mediaKey) || !isObject(media)) {
29313
+ continue;
29314
+ }
29315
+ const processed = createStrandsMediaAttachment(mediaKey, media, cache);
29316
+ if (processed !== void 0) {
29317
+ return processed;
29318
+ }
29319
+ }
29320
+ return void 0;
29321
+ }
29322
+ function createStrandsMediaAttachment(mediaKey, media, cache) {
29323
+ const format = media.format;
29324
+ const source = media.source;
29325
+ if (typeof format !== "string" || !isObject(source) || !Object.hasOwn(source, "bytes")) {
29326
+ return void 0;
29327
+ }
29328
+ const contentType = STRANDS_MEDIA_TYPES[format.toLowerCase()];
29329
+ if (!contentType) {
29330
+ return void 0;
29331
+ }
29332
+ const filename = mediaKey === "document" && typeof media.name === "string" && media.name.length > 0 ? media.name : `${mediaKey}.${format.toLowerCase()}`;
29333
+ const attachment = getOrCreateStrandsAttachment(
29334
+ source.bytes,
29335
+ filename,
29336
+ contentType,
29337
+ cache
29338
+ );
29339
+ if (!attachment) {
29340
+ return void 0;
29341
+ }
29342
+ const { type: _type, ...serializedMedia } = media;
29343
+ const { type: _sourceType, ...serializedSource } = source;
29344
+ return {
29345
+ [mediaKey]: {
29346
+ ...serializedMedia,
29347
+ source: {
29348
+ ...serializedSource,
29349
+ bytes: attachment
29350
+ }
29351
+ }
29352
+ };
29353
+ }
29354
+ function getOrCreateStrandsAttachment(data, filename, contentType, cache) {
29355
+ const key = `${contentType}\0${filename}`;
29356
+ const attachments = typeof data === "string" ? cache.strings.get(data) : isObject(data) ? cache.objects.get(data) : void 0;
29357
+ const cached = attachments?.get(key);
29358
+ if (cached) {
29359
+ return cached;
29360
+ }
29361
+ const blob = convertDataToBlob(data, contentType);
29362
+ if (!blob) {
29363
+ return void 0;
29364
+ }
29365
+ const attachment = new Attachment({
29366
+ data: blob,
29367
+ filename,
29368
+ contentType
29369
+ });
29370
+ const updatedAttachments = attachments ?? /* @__PURE__ */ new Map();
29371
+ updatedAttachments.set(key, attachment);
29372
+ if (typeof data === "string") {
29373
+ cache.strings.set(data, updatedAttachments);
29374
+ } else if (isObject(data)) {
29375
+ cache.objects.set(data, updatedAttachments);
29376
+ }
29377
+ return attachment;
29378
+ }
28708
29379
  function normalizeContentBlocks(blocks) {
28709
29380
  const text = blocks.map((block) => typeof block.text === "string" ? block.text : void 0).filter((part) => Boolean(part)).join("");
28710
29381
  return text.length > 0 ? text : blocks;
@@ -28834,6 +29505,7 @@ var BraintrustPlugin = class extends BasePlugin {
28834
29505
  gitHubCopilotPlugin = null;
28835
29506
  fluePlugin = null;
28836
29507
  langChainPlugin = null;
29508
+ langSmithPlugin = null;
28837
29509
  piCodingAgentPlugin = null;
28838
29510
  strandsAgentSDKPlugin = null;
28839
29511
  constructor(config = {}) {
@@ -28930,6 +29602,12 @@ var BraintrustPlugin = class extends BasePlugin {
28930
29602
  this.langChainPlugin = new LangChainPlugin();
28931
29603
  this.langChainPlugin.enable();
28932
29604
  }
29605
+ if (integrations.langsmith !== false) {
29606
+ this.langSmithPlugin = new LangSmithPlugin({
29607
+ skipLangChainRuns: integrations.langchain !== false
29608
+ });
29609
+ this.langSmithPlugin.enable();
29610
+ }
28933
29611
  }
28934
29612
  onDisable() {
28935
29613
  if (this.openaiPlugin) {
@@ -29020,6 +29698,10 @@ var BraintrustPlugin = class extends BasePlugin {
29020
29698
  this.langChainPlugin.disable();
29021
29699
  this.langChainPlugin = null;
29022
29700
  }
29701
+ if (this.langSmithPlugin) {
29702
+ this.langSmithPlugin.disable();
29703
+ this.langSmithPlugin = null;
29704
+ }
29023
29705
  }
29024
29706
  };
29025
29707
 
@@ -29098,9 +29780,6 @@ var EveBridge = class {
29098
29780
  this.state = state;
29099
29781
  }
29100
29782
  eventQueuesBySession = /* @__PURE__ */ new Map();
29101
- sessionsById = new LRUCache({
29102
- max: MAX_EVE_CACHE_ENTRIES
29103
- });
29104
29783
  completedToolKeys = new LRUCache({
29105
29784
  max: MAX_EVE_CACHE_ENTRIES
29106
29785
  });
@@ -29267,7 +29946,7 @@ var EveBridge = class {
29267
29946
  async handleEvent(event, ctx, hookMetadata) {
29268
29947
  switch (event.type) {
29269
29948
  case "session.started":
29270
- await this.handleSessionStarted(event, ctx, hookMetadata);
29949
+ this.handleSessionStarted(event, ctx, hookMetadata);
29271
29950
  return true;
29272
29951
  case "turn.started":
29273
29952
  await this.handleTurnStarted(event, ctx, hookMetadata);
@@ -29303,22 +29982,22 @@ var EveBridge = class {
29303
29982
  this.handleStepFailed(event, ctx);
29304
29983
  return true;
29305
29984
  case "turn.completed":
29306
- await this.handleTurnCompleted(event, ctx);
29985
+ this.handleTurnCompleted(event, ctx);
29307
29986
  return true;
29308
29987
  case "turn.failed":
29309
- await this.handleTurnFailed(event, ctx);
29988
+ this.handleTurnFailed(event, ctx);
29310
29989
  return true;
29311
29990
  case "session.failed":
29312
- await this.handleSessionFailed(event, ctx);
29991
+ this.handleSessionFailed(event, ctx);
29313
29992
  return true;
29314
29993
  case "session.completed":
29315
- await this.handleSessionCompleted(event, ctx);
29994
+ this.handleSessionCompleted(event, ctx);
29316
29995
  return true;
29317
29996
  default:
29318
29997
  return false;
29319
29998
  }
29320
29999
  }
29321
- async handleSessionStarted(event, ctx, hookMetadata) {
30000
+ handleSessionStarted(event, ctx, hookMetadata) {
29322
30001
  const sessionId = sessionIdFromContext(ctx);
29323
30002
  if (!sessionId) {
29324
30003
  return;
@@ -29334,7 +30013,6 @@ var EveBridge = class {
29334
30013
  metadata: { ...normalized.metadata, ...metadata }
29335
30014
  };
29336
30015
  });
29337
- await this.ensureSession(sessionId, ctx, metadata, eventTime2(event));
29338
30016
  for (const [key, turn] of this.turnsByKey) {
29339
30017
  if (!key.startsWith(`${sessionId}:`)) {
29340
30018
  continue;
@@ -29352,21 +30030,19 @@ var EveBridge = class {
29352
30030
  if (!sessionId) {
29353
30031
  return;
29354
30032
  }
29355
- const session = await this.ensureSession(
29356
- sessionId,
29357
- ctx,
29358
- hookMetadata ?? {},
29359
- eventTime2(event)
29360
- );
29361
30033
  const key = turnKey2(sessionId, event.data.turnId);
29362
- const metadata = { ...session.metadata };
30034
+ const metadata = {
30035
+ ...readEveTraceState(this.state).metadata,
30036
+ ...hookMetadata ?? {},
30037
+ "eve.session_id": sessionId
30038
+ };
29363
30039
  const existing = this.turnsByKey.get(key);
29364
30040
  if (existing) {
29365
30041
  existing.metadata = { ...existing.metadata, ...metadata };
29366
30042
  existing.span.log({ metadata: existing.metadata });
29367
30043
  return;
29368
30044
  }
29369
- const span = await this.startTurnSpan(session, event, metadata);
30045
+ const span = await this.startTurnSpan(sessionId, event, ctx, metadata);
29370
30046
  span.log({ metadata });
29371
30047
  this.turnsByKey.set(key, {
29372
30048
  key,
@@ -29404,10 +30080,7 @@ var EveBridge = class {
29404
30080
  this.markStepEnded(event.data.turnId, event.data.stepIndex);
29405
30081
  }
29406
30082
  const stepOrdinal = this.stepOrdinal(event);
29407
- const metadata = {
29408
- ...turn.metadata,
29409
- ...this.sessionsById.get(sessionId)?.metadata ?? {}
29410
- };
30083
+ const metadata = { ...turn.metadata };
29411
30084
  const input = consumeCapturedEveModelInput(
29412
30085
  this.state,
29413
30086
  sessionId,
@@ -29502,6 +30175,28 @@ var EveBridge = class {
29502
30175
  if (!step) {
29503
30176
  return;
29504
30177
  }
30178
+ const toolCallsById = /* @__PURE__ */ new Map();
30179
+ if (Array.isArray(step.output) && isObject(step.output[0])) {
30180
+ const message = step.output[0]["message"];
30181
+ if (isObject(message) && Array.isArray(message["tool_calls"])) {
30182
+ for (const toolCall of message["tool_calls"]) {
30183
+ if (isObject(toolCall) && typeof toolCall["id"] === "string") {
30184
+ toolCallsById.set(toolCall["id"], toolCall);
30185
+ }
30186
+ }
30187
+ }
30188
+ }
30189
+ for (const action of traceActions) {
30190
+ const name = action.kind === "tool-call" ? action.toolName : action.subagentName ?? action.name ?? "agent";
30191
+ toolCallsById.set(action.callId, {
30192
+ function: {
30193
+ arguments: JSON.stringify(action.input),
30194
+ name
30195
+ },
30196
+ id: action.callId,
30197
+ type: "function"
30198
+ });
30199
+ }
29505
30200
  step.output = [
29506
30201
  {
29507
30202
  finish_reason: "tool_calls",
@@ -29509,17 +30204,7 @@ var EveBridge = class {
29509
30204
  message: {
29510
30205
  content: null,
29511
30206
  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
- })
30207
+ tool_calls: [...toolCallsById.values()]
29523
30208
  }
29524
30209
  }
29525
30210
  ];
@@ -29766,17 +30451,11 @@ var EveBridge = class {
29766
30451
  )
29767
30452
  });
29768
30453
  }
29769
- async handleSessionFailed(event, ctx) {
30454
+ handleSessionFailed(event, ctx) {
29770
30455
  const sessionId = event.data.sessionId || sessionIdFromContext(ctx);
29771
30456
  if (!sessionId) {
29772
30457
  return;
29773
30458
  }
29774
- const session = await this.ensureSession(
29775
- sessionId,
29776
- ctx,
29777
- {},
29778
- eventTime2(event)
29779
- );
29780
30459
  const error = errorFromMessage(
29781
30460
  event.data.message,
29782
30461
  event.data.code,
@@ -29793,29 +30472,20 @@ var EveBridge = class {
29793
30472
  }
29794
30473
  for (const [key, tool] of this.toolsByCallKey) {
29795
30474
  if (key.startsWith(`${sessionId}:`)) {
29796
- const endTime2 = eventTime2(event);
30475
+ const endTime = eventTime2(event);
29797
30476
  if (!tool.endedByTurn) {
29798
30477
  tool.span.log({ metadata: tool.metadata });
29799
- tool.span.end(endTime2 === void 0 ? void 0 : { endTime: endTime2 });
30478
+ tool.span.end(endTime === void 0 ? void 0 : { endTime });
29800
30479
  tool.endedByTurn = true;
29801
30480
  }
29802
30481
  }
29803
30482
  }
29804
- session.span.log({ error });
29805
- const endTime = eventTime2(event);
29806
- session.span.end(endTime === void 0 ? void 0 : { endTime });
29807
30483
  }
29808
- async handleSessionCompleted(event, ctx) {
30484
+ handleSessionCompleted(event, ctx) {
29809
30485
  const sessionId = sessionIdFromContext(ctx);
29810
30486
  if (!sessionId) {
29811
30487
  return;
29812
30488
  }
29813
- const session = await this.ensureSession(
29814
- sessionId,
29815
- ctx,
29816
- {},
29817
- eventTime2(event)
29818
- );
29819
30489
  for (const [key, turn] of this.turnsByKey) {
29820
30490
  if (!key.startsWith(`${sessionId}:`)) {
29821
30491
  continue;
@@ -29826,82 +30496,29 @@ var EveBridge = class {
29826
30496
  }
29827
30497
  for (const [key, tool] of this.toolsByCallKey) {
29828
30498
  if (key.startsWith(`${sessionId}:`) && !tool.endedByTurn) {
29829
- const endTime2 = eventTime2(event);
30499
+ const endTime = eventTime2(event);
29830
30500
  tool.span.log({ metadata: tool.metadata });
29831
- tool.span.end(endTime2 === void 0 ? void 0 : { endTime: endTime2 });
30501
+ tool.span.end(endTime === void 0 ? void 0 : { endTime });
29832
30502
  tool.endedByTurn = true;
29833
30503
  }
29834
30504
  }
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
30505
  }
29887
30506
  async ensureTurn(event, ctx, hookMetadata) {
29888
30507
  const sessionId = sessionIdFromContext(ctx);
29889
30508
  if (!sessionId) {
29890
30509
  return void 0;
29891
30510
  }
29892
- const session = await this.ensureSession(
29893
- sessionId,
29894
- ctx,
29895
- hookMetadata ?? {},
29896
- eventTime2(event)
29897
- );
29898
30511
  const key = turnKey2(sessionId, event.data.turnId);
29899
30512
  const existing = this.turnsByKey.get(key);
29900
30513
  if (existing) {
29901
30514
  return existing;
29902
30515
  }
29903
- const metadata = { ...session.metadata };
29904
- const span = await this.startTurnSpan(session, event, metadata);
30516
+ const metadata = {
30517
+ ...readEveTraceState(this.state).metadata,
30518
+ ...hookMetadata ?? {},
30519
+ "eve.session_id": sessionId
30520
+ };
30521
+ const span = await this.startTurnSpan(sessionId, event, ctx, metadata);
29905
30522
  span.log({ metadata });
29906
30523
  const state = {
29907
30524
  key,
@@ -30088,22 +30705,35 @@ var EveBridge = class {
30088
30705
  this.toolsByCallKey.set(toolKey3(sessionId, result.callId), state);
30089
30706
  return state;
30090
30707
  }
30091
- async startTurnSpan(session, event, metadata) {
30092
- const { rowId: eventId, spanId } = await generateEveIds(
30093
- "turn",
30094
- session.sessionId,
30095
- event.data.turnId
30096
- );
30708
+ async startTurnSpan(sessionId, event, ctx, metadata) {
30709
+ const session = isObject(ctx) ? ctx["session"] : void 0;
30710
+ const parent = isObject(session) ? session["parent"] : void 0;
30711
+ const parentTurn = isObject(parent) ? parent["turn"] : void 0;
30712
+ const parentLineage = isObject(parent) && typeof parent["callId"] === "string" && typeof parent["sessionId"] === "string" && isObject(parentTurn) && typeof parentTurn["id"] === "string" ? {
30713
+ callId: parent["callId"],
30714
+ sessionId: parent["sessionId"],
30715
+ turnId: parentTurn["id"]
30716
+ } : void 0;
30717
+ const [{ rowId: eventId, spanId }, rootSpanId, parentSpanId] = await Promise.all([
30718
+ generateEveIds("turn", sessionId, event.data.turnId),
30719
+ deterministicEveId(
30720
+ "eve:root",
30721
+ parentLineage?.sessionId ?? sessionId,
30722
+ parentLineage?.turnId ?? event.data.turnId
30723
+ ),
30724
+ parentLineage ? deterministicEveId(
30725
+ "eve:subagent",
30726
+ parentLineage.sessionId,
30727
+ parentLineage.callId
30728
+ ) : Promise.resolve(void 0)
30729
+ ]);
30097
30730
  return await this.startEveSpan({
30098
30731
  event: {
30099
30732
  id: eventId,
30100
30733
  metadata
30101
30734
  },
30102
30735
  name: "eve.turn",
30103
- parentSpanIds: {
30104
- rootSpanId: session.span.rootSpanId,
30105
- spanId: session.span.spanId
30106
- },
30736
+ parentSpanIds: parentSpanId ? { rootSpanId, spanId: parentSpanId } : { parentSpanIds: [], rootSpanId },
30107
30737
  spanAttributes: { type: "task" /* TASK */ },
30108
30738
  spanId,
30109
30739
  startTime: eventTime2(event)
@@ -30164,7 +30794,6 @@ var EveBridge = class {
30164
30794
  }
30165
30795
  cleanupSession(sessionId) {
30166
30796
  const keyPrefix = `${sessionId}:`;
30167
- this.sessionsById.delete(sessionId);
30168
30797
  for (const key of this.turnsByKey.keys()) {
30169
30798
  if (key.startsWith(keyPrefix)) {
30170
30799
  this.turnsByKey.delete(key);
@@ -30355,7 +30984,7 @@ function modelMetadataFromRuntime(runtime) {
30355
30984
  return {};
30356
30985
  }
30357
30986
  const modelId = runtime["modelId"];
30358
- return typeof modelId === "string" ? modelMetadataFromModelId(modelId) : {};
30987
+ return typeof modelId === "string" && !modelId.trim().startsWith("dynamic:") ? modelMetadataFromModelId(modelId) : {};
30359
30988
  }
30360
30989
  function modelMetadataFromModelId(modelId) {
30361
30990
  const normalized = modelId.trim();
@@ -30388,26 +31017,6 @@ function toolMetadataFromTurn(turn) {
30388
31017
  const { model: _model, provider: _provider, ...metadata } = turn.metadata;
30389
31018
  return metadata;
30390
31019
  }
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
31020
  function isToolCallAction(action) {
30412
31021
  return isObject(action) && action["kind"] === "tool-call" && typeof action["callId"] === "string" && typeof action["toolName"] === "string" && isObject(action["input"]);
30413
31022
  }
@@ -30463,9 +31072,6 @@ function turnKey2(sessionId, turnId) {
30463
31072
  function toolKey3(sessionId, callId) {
30464
31073
  return `${sessionId}:${callId}`;
30465
31074
  }
30466
- async function rootSpanIdForSession(sessionId) {
30467
- return deterministicEveId("eve:root", sessionId);
30468
- }
30469
31075
  async function generateEveIds(kind, ...parts) {
30470
31076
  const [rowId, spanId] = await Promise.all([
30471
31077
  deterministicEveId(`eve:row:${kind}`, ...parts),
@@ -30473,9 +31079,6 @@ async function generateEveIds(kind, ...parts) {
30473
31079
  ]);
30474
31080
  return { rowId, spanId };
30475
31081
  }
30476
- async function spanIdForSubagent(sessionId, callId) {
30477
- return deterministicEveId("eve:subagent", sessionId, callId);
30478
- }
30479
31082
  async function deterministicEveId(...parts) {
30480
31083
  const data = new TextEncoder().encode(
30481
31084
  parts.map((part) => `${part.length}:${part}`).join("\0")
@@ -30547,7 +31150,8 @@ var envIntegrationAliases = {
30547
31150
  langchain: "langchain",
30548
31151
  "langchain-js": "langchain",
30549
31152
  "@langchain": "langchain",
30550
- langgraph: "langgraph"
31153
+ langgraph: "langgraph",
31154
+ langsmith: "langsmith"
30551
31155
  };
30552
31156
  function getDefaultInstrumentationIntegrations() {
30553
31157
  return {
@@ -30578,6 +31182,7 @@ function getDefaultInstrumentationIntegrations() {
30578
31182
  gitHubCopilot: true,
30579
31183
  langchain: true,
30580
31184
  langgraph: true,
31185
+ langsmith: true,
30581
31186
  piCodingAgent: true,
30582
31187
  strandsAgentSDK: true
30583
31188
  };