braintrust 3.21.0 → 3.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +47 -0
  2. package/dev/dist/index.d.mts +1030 -1
  3. package/dev/dist/index.d.ts +1030 -1
  4. package/dev/dist/index.js +1429 -663
  5. package/dev/dist/index.mjs +811 -45
  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 +224 -31
  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 +3273 -93
  28. package/dist/browser.d.ts +3273 -93
  29. package/dist/browser.js +2495 -63
  30. package/dist/browser.mjs +2495 -63
  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-FY7DAKA5.js → chunk-FZWPFCVE.js} +1590 -832
  34. package/dist/{chunk-O2P765XK.mjs → chunk-IXL4PMY4.mjs} +802 -44
  35. package/dist/cli.js +816 -47
  36. package/dist/edge-light.d.mts +1 -1
  37. package/dist/edge-light.d.ts +1 -1
  38. package/dist/edge-light.js +2495 -63
  39. package/dist/edge-light.mjs +2495 -63
  40. package/dist/index.d.mts +3273 -93
  41. package/dist/index.d.ts +3273 -93
  42. package/dist/index.js +2078 -416
  43. package/dist/index.mjs +1664 -2
  44. package/dist/instrumentation/index.d.mts +912 -2
  45. package/dist/instrumentation/index.d.ts +912 -2
  46. package/dist/instrumentation/index.js +2202 -42
  47. package/dist/instrumentation/index.mjs +2200 -42
  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 +2495 -63
  53. package/dist/workerd.mjs +2495 -63
  54. package/package.json +5 -2
package/dist/browser.js CHANGED
@@ -93,6 +93,8 @@ __export(browser_exports, {
93
93
  addAzureBlobHeaders: () => addAzureBlobHeaders,
94
94
  agentAssertionScorer: () => agentAssertionScorer,
95
95
  braintrustAISDKTelemetry: () => braintrustAISDKTelemetry,
96
+ braintrustEveHook: () => braintrustEveHook,
97
+ braintrustEveInstrumentation: () => braintrustEveInstrumentation,
96
98
  braintrustFlueInstrumentation: () => braintrustFlueInstrumentation,
97
99
  braintrustFlueObserver: () => braintrustFlueObserver,
98
100
  braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
@@ -183,6 +185,9 @@ __export(browser_exports, {
183
185
  wrapGoogleGenAI: () => wrapGoogleGenAI,
184
186
  wrapGroq: () => wrapGroq,
185
187
  wrapHuggingFace: () => wrapHuggingFace,
188
+ wrapLangSmithClient: () => wrapLangSmithClient,
189
+ wrapLangSmithRunTrees: () => wrapLangSmithRunTrees,
190
+ wrapLangSmithTraceable: () => wrapLangSmithTraceable,
186
191
  wrapMastraAgent: () => wrapMastraAgent,
187
192
  wrapMistral: () => wrapMistral,
188
193
  wrapOpenAI: () => wrapOpenAI,
@@ -2387,19 +2392,30 @@ var CallEvent = import_v36.z.union([
2387
2392
  var ChatCompletionContentPartTextWithTitle = import_v36.z.object({
2388
2393
  text: import_v36.z.string().default(""),
2389
2394
  type: import_v36.z.literal("text"),
2390
- cache_control: import_v36.z.object({ type: import_v36.z.literal("ephemeral") }).optional()
2395
+ cache_control: import_v36.z.object({
2396
+ type: import_v36.z.literal("ephemeral"),
2397
+ ttl: import_v36.z.enum(["5m", "1h"]).optional()
2398
+ }).optional()
2391
2399
  });
2392
2400
  var ChatCompletionContentPartImageWithTitle = import_v36.z.object({
2393
2401
  image_url: import_v36.z.object({
2394
2402
  url: import_v36.z.string(),
2395
2403
  detail: import_v36.z.union([import_v36.z.literal("auto"), import_v36.z.literal("low"), import_v36.z.literal("high")]).optional()
2396
2404
  }),
2397
- type: import_v36.z.literal("image_url")
2405
+ type: import_v36.z.literal("image_url"),
2406
+ cache_control: import_v36.z.object({
2407
+ type: import_v36.z.literal("ephemeral"),
2408
+ ttl: import_v36.z.enum(["5m", "1h"]).optional()
2409
+ }).optional()
2398
2410
  });
2399
2411
  var ChatCompletionContentPartFileFile = import_v36.z.object({ file_data: import_v36.z.string(), filename: import_v36.z.string(), file_id: import_v36.z.string() }).partial();
2400
2412
  var ChatCompletionContentPartFileWithTitle = import_v36.z.object({
2401
2413
  file: ChatCompletionContentPartFileFile,
2402
- type: import_v36.z.literal("file")
2414
+ type: import_v36.z.literal("file"),
2415
+ cache_control: import_v36.z.object({
2416
+ type: import_v36.z.literal("ephemeral"),
2417
+ ttl: import_v36.z.enum(["5m", "1h"]).optional()
2418
+ }).optional()
2403
2419
  });
2404
2420
  var ChatCompletionContentPart = import_v36.z.union([
2405
2421
  ChatCompletionContentPartTextWithTitle,
@@ -2409,7 +2425,10 @@ var ChatCompletionContentPart = import_v36.z.union([
2409
2425
  var ChatCompletionContentPartText = import_v36.z.object({
2410
2426
  text: import_v36.z.string().default(""),
2411
2427
  type: import_v36.z.literal("text"),
2412
- cache_control: import_v36.z.object({ type: import_v36.z.literal("ephemeral") }).optional()
2428
+ cache_control: import_v36.z.object({
2429
+ type: import_v36.z.literal("ephemeral"),
2430
+ ttl: import_v36.z.enum(["5m", "1h"]).optional()
2431
+ }).optional()
2413
2432
  });
2414
2433
  var ChatCompletionMessageToolCall = import_v36.z.object({
2415
2434
  id: import_v36.z.string(),
@@ -4444,7 +4463,7 @@ var DiskCache = class {
4444
4463
  }
4445
4464
  };
4446
4465
 
4447
- // src/prompt-cache/lru-cache.ts
4466
+ // src/lru-cache.ts
4448
4467
  var LRUCache = class {
4449
4468
  cache;
4450
4469
  maxSize;
@@ -4460,13 +4479,23 @@ var LRUCache = class {
4460
4479
  * @returns The cached value if found, undefined otherwise.
4461
4480
  */
4462
4481
  get(key) {
4463
- const value = this.cache.get(key);
4464
- if (value === void 0) {
4482
+ const entry = this.cache.get(key);
4483
+ if (entry === void 0) {
4465
4484
  return void 0;
4466
4485
  }
4467
4486
  this.cache.delete(key);
4468
- this.cache.set(key, value);
4469
- return value;
4487
+ this.cache.set(key, entry);
4488
+ return entry.value;
4489
+ }
4490
+ /**
4491
+ * Checks whether a key exists and marks it as most recently used.
4492
+ */
4493
+ has(key) {
4494
+ if (!this.cache.has(key)) {
4495
+ return false;
4496
+ }
4497
+ this.get(key);
4498
+ return true;
4470
4499
  }
4471
4500
  /**
4472
4501
  * Stores a value in the cache.
@@ -4483,7 +4512,38 @@ var LRUCache = class {
4483
4512
  const first = this.cache.keys().next().value;
4484
4513
  this.cache.delete(first);
4485
4514
  }
4486
- this.cache.set(key, value);
4515
+ this.cache.set(key, { value });
4516
+ }
4517
+ /**
4518
+ * Removes an item from the cache.
4519
+ */
4520
+ delete(key) {
4521
+ return this.cache.delete(key);
4522
+ }
4523
+ /**
4524
+ * Iterates over cache entries from least to most recently used.
4525
+ */
4526
+ *entries() {
4527
+ for (const [key, entry] of this.cache) {
4528
+ yield [key, entry.value];
4529
+ }
4530
+ }
4531
+ /**
4532
+ * Iterates over cache keys from least to most recently used.
4533
+ */
4534
+ keys() {
4535
+ return this.cache.keys();
4536
+ }
4537
+ /**
4538
+ * Iterates over cache values from least to most recently used.
4539
+ */
4540
+ *values() {
4541
+ for (const entry of this.cache.values()) {
4542
+ yield entry.value;
4543
+ }
4544
+ }
4545
+ [Symbol.iterator]() {
4546
+ return this.entries();
4487
4547
  }
4488
4548
  /**
4489
4549
  * Removes all items from the cache.
@@ -5041,6 +5101,9 @@ function applyMaskingToField(maskingFunction, data, fieldName) {
5041
5101
  return `ERROR: Failed to mask field '${fieldName}' - ${errorType}`;
5042
5102
  }
5043
5103
  }
5104
+ var INITIAL_SPAN_WRITE_AS_MERGE = /* @__PURE__ */ Symbol(
5105
+ "braintrust.initial-span-write-as-merge"
5106
+ );
5044
5107
  var BRAINTRUST_CURRENT_SPAN_STORE = /* @__PURE__ */ Symbol.for(
5045
5108
  "braintrust.currentSpanStore"
5046
5109
  );
@@ -5642,25 +5705,46 @@ var HTTPConnection = class _HTTPConnection {
5642
5705
  })
5643
5706
  );
5644
5707
  }
5645
- async post(path, params, config) {
5708
+ async post(path, params, config, retries = 0) {
5646
5709
  const { headers, ...rest } = config || {};
5647
5710
  const this_fetch = this.fetch;
5648
5711
  const this_base_url = this.base_url;
5649
5712
  const this_headers = this.headers;
5650
- return await checkResponse(
5651
- await this_fetch(_urljoin(this_base_url, path), {
5652
- method: "POST",
5653
- headers: {
5654
- Accept: "application/json",
5655
- "Content-Type": "application/json",
5656
- ...this_headers,
5657
- ...headers
5658
- },
5659
- body: typeof params === "string" ? params : params ? JSON.stringify(params) : void 0,
5660
- keepalive: true,
5661
- ...rest
5662
- })
5663
- );
5713
+ const tries = retries + 1;
5714
+ for (let i = 0; i < tries; i++) {
5715
+ try {
5716
+ return await checkResponse(
5717
+ await this_fetch(_urljoin(this_base_url, path), {
5718
+ method: "POST",
5719
+ headers: {
5720
+ Accept: "application/json",
5721
+ "Content-Type": "application/json",
5722
+ ...this_headers,
5723
+ ...headers
5724
+ },
5725
+ body: typeof params === "string" ? params : params ? JSON.stringify(params) : void 0,
5726
+ keepalive: true,
5727
+ ...rest
5728
+ })
5729
+ );
5730
+ } catch (error) {
5731
+ if (config?.signal?.aborted) {
5732
+ throw getAbortReason(config.signal);
5733
+ }
5734
+ if (i === tries - 1 || !isRetryableHTTPError(error)) {
5735
+ throw error;
5736
+ }
5737
+ debugLogger.debug(
5738
+ `Retrying API request ${path} after ${formatHTTPError(error)}`
5739
+ );
5740
+ const sleepTimeMs = HTTP_RETRY_BASE_SLEEP_TIME_S * 1e3 * 2 ** i + Math.random() * HTTP_RETRY_JITTER_MS;
5741
+ debugLogger.info(
5742
+ `Sleeping for ${sleepTimeMs}ms before retrying API request`
5743
+ );
5744
+ await waitForRetry(sleepTimeMs, config?.signal);
5745
+ }
5746
+ }
5747
+ throw new Error("Unexpected retry state");
5664
5748
  }
5665
5749
  async get_json(object_type, args = void 0, retries = 0) {
5666
5750
  const tries = retries + 1;
@@ -6757,6 +6841,45 @@ var TestBackgroundLogger = class {
6757
6841
  };
6758
6842
  var BACKGROUND_LOGGER_BASE_SLEEP_TIME_S = 1;
6759
6843
  var HTTP_RETRY_BASE_SLEEP_TIME_S = 1;
6844
+ var HTTP_RETRY_JITTER_MS = 200;
6845
+ var BTQL_HTTP_RETRIES = 3;
6846
+ var RETRYABLE_HTTP_STATUS_CODES = /* @__PURE__ */ new Set([500, 502, 503, 504]);
6847
+ function isRetryableHTTPError(error) {
6848
+ return !(error instanceof FailedHTTPResponse) || RETRYABLE_HTTP_STATUS_CODES.has(error.status);
6849
+ }
6850
+ function formatHTTPError(error) {
6851
+ if (error instanceof FailedHTTPResponse) {
6852
+ return `${error.status} ${error.text}`;
6853
+ }
6854
+ return error instanceof Error ? error.message : String(error);
6855
+ }
6856
+ function getAbortReason(signal) {
6857
+ return signal.reason ?? new Error("Request aborted");
6858
+ }
6859
+ async function waitForRetry(delayMs, signal) {
6860
+ if (!signal) {
6861
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
6862
+ return;
6863
+ }
6864
+ if (signal.aborted) {
6865
+ throw getAbortReason(signal);
6866
+ }
6867
+ await new Promise((resolve, reject2) => {
6868
+ const onAbort = () => {
6869
+ clearTimeout(timeout);
6870
+ signal.removeEventListener("abort", onAbort);
6871
+ reject2(getAbortReason(signal));
6872
+ };
6873
+ const timeout = setTimeout(() => {
6874
+ signal.removeEventListener("abort", onAbort);
6875
+ resolve();
6876
+ }, delayMs);
6877
+ signal.addEventListener("abort", onAbort, { once: true });
6878
+ if (signal.aborted) {
6879
+ onAbort();
6880
+ }
6881
+ });
6882
+ }
6760
6883
  var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
6761
6884
  apiConn;
6762
6885
  queue;
@@ -8495,15 +8618,15 @@ function parentSpanIdsUsable(spanId, rootSpanId) {
8495
8618
  return Boolean(spanId) && Boolean(rootSpanId);
8496
8619
  }
8497
8620
  function logError(span, error) {
8498
- let errorMessage = "<error>";
8621
+ let errorMessage2 = "<error>";
8499
8622
  let stackTrace = "";
8500
8623
  if (error instanceof Error) {
8501
- errorMessage = error.message;
8624
+ errorMessage2 = error.message;
8502
8625
  stackTrace = error.stack || "";
8503
8626
  } else {
8504
- errorMessage = String(error);
8627
+ errorMessage2 = String(error);
8505
8628
  }
8506
- span.log({ error: `${errorMessage}
8629
+ span.log({ error: `${errorMessage2}
8507
8630
 
8508
8631
  ${stackTrace}` });
8509
8632
  }
@@ -8691,6 +8814,12 @@ var traceable = wrapTraced;
8691
8814
  function startSpan(args) {
8692
8815
  return startSpanAndIsLogger(args).span;
8693
8816
  }
8817
+ function _internalStartSpanWithInitialMerge(args) {
8818
+ return startSpanAndIsLogger({
8819
+ ...args,
8820
+ [INITIAL_SPAN_WRITE_AS_MERGE]: true
8821
+ }).span;
8822
+ }
8694
8823
  async function flush(options) {
8695
8824
  const state = options?.state ?? _globalState;
8696
8825
  return await state.bgLogger().flush();
@@ -9084,7 +9213,8 @@ var ObjectFetcher = class {
9084
9213
  version: this.pinnedVersion
9085
9214
  } : {}
9086
9215
  },
9087
- { headers: { "Accept-Encoding": "gzip" } }
9216
+ { headers: { "Accept-Encoding": "gzip" } },
9217
+ BTQL_HTTP_RETRIES
9088
9218
  );
9089
9219
  const respJson = await resp.json();
9090
9220
  const mutate = this.mutateRecord;
@@ -9601,7 +9731,7 @@ var SpanImpl = class _SpanImpl {
9601
9731
  this._spanId = resolvedIds.spanId;
9602
9732
  this._rootSpanId = resolvedIds.rootSpanId;
9603
9733
  this._spanParents = resolvedIds.spanParents;
9604
- this.isMerge = false;
9734
+ this.isMerge = args[INITIAL_SPAN_WRITE_AS_MERGE] === true;
9605
9735
  this.logInternal({ event, internalData });
9606
9736
  this.isMerge = true;
9607
9737
  }
@@ -10808,7 +10938,8 @@ async function getPromptVersions(projectId, promptId) {
10808
10938
  use_columnstore: false,
10809
10939
  brainstore_realtime: true
10810
10940
  },
10811
- { headers: { "Accept-Encoding": "gzip" } }
10941
+ { headers: { "Accept-Encoding": "gzip" } },
10942
+ BTQL_HTTP_RETRIES
10812
10943
  );
10813
10944
  if (!response.ok) {
10814
10945
  throw new Error(
@@ -29269,6 +29400,446 @@ function isBraintrustHandler(handler) {
29269
29400
  return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
29270
29401
  }
29271
29402
 
29403
+ // src/instrumentation/plugins/langsmith-channels.ts
29404
+ var langSmithChannels = defineChannels("langsmith", {
29405
+ createRun: channel({
29406
+ channelName: "Client.createRun",
29407
+ kind: "async"
29408
+ }),
29409
+ updateRun: channel({
29410
+ channelName: "Client.updateRun",
29411
+ kind: "async"
29412
+ }),
29413
+ batchIngestRuns: channel({
29414
+ channelName: "Client.batchIngestRuns",
29415
+ kind: "async"
29416
+ })
29417
+ });
29418
+
29419
+ // src/instrumentation/plugins/langsmith-plugin.ts
29420
+ var MAX_COMPLETED_RUNS = 1e4;
29421
+ var BLOCKED_METADATA_KEYS = /* @__PURE__ */ new Set([
29422
+ "__proto__",
29423
+ "constructor",
29424
+ "prototype",
29425
+ "usage_metadata"
29426
+ ]);
29427
+ var BLOCKED_METADATA_PREFIXES = ["__pregel_", "langgraph_", "lc_"];
29428
+ var LLM_SETTING_KEYS = [
29429
+ "temperature",
29430
+ "top_p",
29431
+ "max_tokens",
29432
+ "frequency_penalty",
29433
+ "presence_penalty",
29434
+ "stop",
29435
+ "response_format"
29436
+ ];
29437
+ var LangSmithPlugin = class extends BasePlugin {
29438
+ activeRuns = /* @__PURE__ */ new Map();
29439
+ completedRuns = new LRUCache({
29440
+ max: MAX_COMPLETED_RUNS
29441
+ });
29442
+ skipLangChainRuns;
29443
+ constructor(options = {}) {
29444
+ super();
29445
+ this.skipLangChainRuns = options.skipLangChainRuns ?? true;
29446
+ }
29447
+ onEnable() {
29448
+ const createChannel = langSmithChannels.createRun.tracingChannel();
29449
+ const createHandlers = {
29450
+ start: (event) => {
29451
+ this.containLifecycleFailure("createRun", () => {
29452
+ this.processCreate(event.arguments[0]);
29453
+ });
29454
+ }
29455
+ };
29456
+ createChannel.subscribe(createHandlers);
29457
+ this.unsubscribers.push(() => createChannel.unsubscribe(createHandlers));
29458
+ const updateChannel = langSmithChannels.updateRun.tracingChannel();
29459
+ const updateHandlers = {
29460
+ start: (event) => {
29461
+ this.containLifecycleFailure("updateRun", () => {
29462
+ this.processUpdate(event.arguments[0], event.arguments[1]);
29463
+ });
29464
+ }
29465
+ };
29466
+ updateChannel.subscribe(updateHandlers);
29467
+ this.unsubscribers.push(() => updateChannel.unsubscribe(updateHandlers));
29468
+ const batchChannel = langSmithChannels.batchIngestRuns.tracingChannel();
29469
+ const batchHandlers = {
29470
+ start: (event) => {
29471
+ this.containLifecycleFailure("batchIngestRuns", () => {
29472
+ this.processBatch(event.arguments[0]);
29473
+ });
29474
+ }
29475
+ };
29476
+ batchChannel.subscribe(batchHandlers);
29477
+ this.unsubscribers.push(() => batchChannel.unsubscribe(batchHandlers));
29478
+ }
29479
+ onDisable() {
29480
+ this.unsubscribers = unsubscribeAll(this.unsubscribers);
29481
+ for (const { span } of this.activeRuns.values()) {
29482
+ span.end();
29483
+ }
29484
+ this.activeRuns.clear();
29485
+ this.completedRuns.clear();
29486
+ }
29487
+ processBatch(batch) {
29488
+ if (!isRecord2(batch)) {
29489
+ return;
29490
+ }
29491
+ const creates = ownValue(batch, "runCreates");
29492
+ if (Array.isArray(creates)) {
29493
+ const parentFirst = [...creates].sort((left, right) => {
29494
+ const leftId = stringValue2(ownValue(left, "id"));
29495
+ const rightId = stringValue2(ownValue(right, "id"));
29496
+ const leftParent = stringValue2(ownValue(left, "parent_run_id"));
29497
+ const rightParent = stringValue2(ownValue(right, "parent_run_id"));
29498
+ if (leftParent && leftParent === rightId) {
29499
+ return 1;
29500
+ }
29501
+ if (rightParent && rightParent === leftId) {
29502
+ return -1;
29503
+ }
29504
+ return dottedOrderDepth(left) - dottedOrderDepth(right);
29505
+ });
29506
+ for (const run of parentFirst) {
29507
+ this.containLifecycleFailure("batchIngestRuns create", () => {
29508
+ this.processCreate(run);
29509
+ });
29510
+ }
29511
+ }
29512
+ const updates = ownValue(batch, "runUpdates");
29513
+ if (Array.isArray(updates)) {
29514
+ for (const run of updates) {
29515
+ this.containLifecycleFailure("batchIngestRuns update", () => {
29516
+ this.processUpdate(stringValue2(ownValue(run, "id")) ?? "", run);
29517
+ });
29518
+ }
29519
+ }
29520
+ }
29521
+ processCreate(run) {
29522
+ const id = stringValue2(ownValue(run, "id"));
29523
+ if (!id || this.completedRuns.get(id)) {
29524
+ return;
29525
+ }
29526
+ if (this.shouldSkipLangChainRun(run)) {
29527
+ this.completedRuns.set(id, true);
29528
+ return;
29529
+ }
29530
+ const active = this.activeRuns.get(id);
29531
+ if (active) {
29532
+ const previous = active.run;
29533
+ active.run = mergeRuns(previous, run);
29534
+ this.logRun(
29535
+ active.span,
29536
+ active.run,
29537
+ previous,
29538
+ timestampSeconds(ownValue(active.run, "end_time")) !== void 0 || errorMessage(ownValue(active.run, "error")) !== void 0
29539
+ );
29540
+ this.endIfComplete(id, active, active.run);
29541
+ return;
29542
+ }
29543
+ const span = this.startRunSpan(id, run);
29544
+ const activeRun = { run, span };
29545
+ this.activeRuns.set(id, activeRun);
29546
+ this.logRun(
29547
+ span,
29548
+ run,
29549
+ void 0,
29550
+ timestampSeconds(ownValue(run, "end_time")) !== void 0 || errorMessage(ownValue(run, "error")) !== void 0
29551
+ );
29552
+ this.endIfComplete(id, activeRun, run);
29553
+ }
29554
+ processUpdate(explicitId, run) {
29555
+ const id = stringValue2(explicitId) ?? stringValue2(ownValue(run, "id"));
29556
+ if (!id || this.completedRuns.get(id)) {
29557
+ return;
29558
+ }
29559
+ if (this.shouldSkipLangChainRun(run)) {
29560
+ const active2 = this.activeRuns.get(id);
29561
+ active2?.span.end();
29562
+ this.activeRuns.delete(id);
29563
+ this.completedRuns.set(id, true);
29564
+ return;
29565
+ }
29566
+ let active = this.activeRuns.get(id);
29567
+ if (!active) {
29568
+ const span = this.startRunSpan(id, run);
29569
+ active = { run, span };
29570
+ this.activeRuns.set(id, active);
29571
+ }
29572
+ const previous = active.run;
29573
+ active.run = mergeRuns(previous, run);
29574
+ this.logRun(active.span, active.run, previous, true);
29575
+ this.endIfComplete(id, active, active.run);
29576
+ }
29577
+ startRunSpan(id, run) {
29578
+ const traceId = stringValue2(ownValue(run, "trace_id")) ?? id;
29579
+ const parentId = stringValue2(ownValue(run, "parent_run_id")) ?? stringValue2(ownValue(ownValue(run, "parent_run"), "id"));
29580
+ const startTime = timestampSeconds(ownValue(run, "start_time"));
29581
+ return startSpan({
29582
+ name: stringValue2(ownValue(run, "name")) ?? "LangSmith run",
29583
+ spanId: id,
29584
+ parentSpanIds: {
29585
+ parentSpanIds: parentId ? [parentId] : [],
29586
+ rootSpanId: traceId
29587
+ },
29588
+ spanAttributes: {
29589
+ type: mapRunType(ownValue(run, "run_type"))
29590
+ },
29591
+ ...startTime === void 0 ? {} : { startTime },
29592
+ event: { id }
29593
+ });
29594
+ }
29595
+ logRun(span, run, previous, includeOutput) {
29596
+ const inputs = preferOwnValue(run, previous, "inputs");
29597
+ const outputs = preferOwnValue(run, previous, "outputs");
29598
+ const error = errorMessage(preferOwnValue(run, previous, "error"));
29599
+ const metadata = extractMetadata(run, previous);
29600
+ const tags = extractTags(preferOwnValue(run, previous, "tags"));
29601
+ const metrics = extractMetrics(run, previous);
29602
+ span.log({
29603
+ ...inputs === void 0 ? {} : { input: sanitizeLoggedValue(inputs) },
29604
+ ...includeOutput && outputs !== void 0 ? { output: sanitizeLoggedValue(outputs) } : {},
29605
+ ...error === void 0 ? {} : { error },
29606
+ ...metadata === void 0 ? {} : { metadata },
29607
+ ...tags === void 0 ? {} : { tags },
29608
+ ...Object.keys(metrics).length === 0 ? {} : { metrics }
29609
+ });
29610
+ }
29611
+ endIfComplete(id, active, run) {
29612
+ const endTime = timestampSeconds(ownValue(run, "end_time"));
29613
+ if (endTime === void 0 && errorMessage(ownValue(run, "error")) === void 0) {
29614
+ return;
29615
+ }
29616
+ active.span.end(endTime === void 0 ? void 0 : { endTime });
29617
+ this.activeRuns.delete(id);
29618
+ this.completedRuns.set(id, true);
29619
+ }
29620
+ shouldSkipLangChainRun(run) {
29621
+ if (!this.skipLangChainRuns) {
29622
+ return false;
29623
+ }
29624
+ const serialized = ownValue(run, "serialized");
29625
+ return isRecord2(serialized) && ownValue(serialized, "lc") === 1;
29626
+ }
29627
+ containLifecycleFailure(operation, fn) {
29628
+ try {
29629
+ fn();
29630
+ } catch (error) {
29631
+ debugLogger.error(
29632
+ `Failed to process LangSmith ${operation} instrumentation:`,
29633
+ error
29634
+ );
29635
+ }
29636
+ }
29637
+ };
29638
+ function ownValue(value, key) {
29639
+ if (!isRecord2(value)) {
29640
+ return void 0;
29641
+ }
29642
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
29643
+ return descriptor && "value" in descriptor ? descriptor.value : void 0;
29644
+ }
29645
+ function preferOwnValue(current, previous, key) {
29646
+ const currentDescriptor = isRecord2(current) ? Object.getOwnPropertyDescriptor(current, key) : void 0;
29647
+ if (currentDescriptor && "value" in currentDescriptor) {
29648
+ return currentDescriptor.value;
29649
+ }
29650
+ return ownValue(previous, key);
29651
+ }
29652
+ function mergeRuns(previous, current) {
29653
+ const entries = /* @__PURE__ */ new Map();
29654
+ for (const value of [previous, current]) {
29655
+ if (!isRecord2(value)) {
29656
+ continue;
29657
+ }
29658
+ for (const [key, descriptor] of Object.entries(
29659
+ Object.getOwnPropertyDescriptors(value)
29660
+ )) {
29661
+ if (descriptor.enumerable && "value" in descriptor) {
29662
+ entries.set(key, descriptor.value);
29663
+ }
29664
+ }
29665
+ }
29666
+ return Object.fromEntries(entries);
29667
+ }
29668
+ function isRecord2(value) {
29669
+ return typeof value === "object" && value !== null && !Array.isArray(value);
29670
+ }
29671
+ function stringValue2(value) {
29672
+ return typeof value === "string" && value.length > 0 ? value : void 0;
29673
+ }
29674
+ function timestampSeconds(value) {
29675
+ if (value instanceof Date) {
29676
+ const timestamp = value.getTime();
29677
+ return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
29678
+ }
29679
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
29680
+ return value > 1e10 ? value / 1e3 : value;
29681
+ }
29682
+ if (typeof value === "string") {
29683
+ const timestamp = Date.parse(value);
29684
+ return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
29685
+ }
29686
+ return void 0;
29687
+ }
29688
+ function dottedOrderDepth(run) {
29689
+ const dottedOrder = stringValue2(ownValue(run, "dotted_order"));
29690
+ return dottedOrder ? dottedOrder.split(".").length : Number.MAX_SAFE_INTEGER;
29691
+ }
29692
+ function mapRunType(runType) {
29693
+ switch (runType) {
29694
+ case "llm":
29695
+ case "embedding":
29696
+ return "llm" /* LLM */;
29697
+ case "tool":
29698
+ case "retriever":
29699
+ return "tool" /* TOOL */;
29700
+ default:
29701
+ return "task" /* TASK */;
29702
+ }
29703
+ }
29704
+ function extractMetadata(run, previous) {
29705
+ const extra = preferOwnValue(run, previous, "extra");
29706
+ const rawMetadata = ownValue(extra, "metadata");
29707
+ if (!isRecord2(rawMetadata)) {
29708
+ return void 0;
29709
+ }
29710
+ const metadata = {};
29711
+ for (const [key, descriptor] of Object.entries(
29712
+ Object.getOwnPropertyDescriptors(rawMetadata)
29713
+ )) {
29714
+ 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}`)) {
29715
+ continue;
29716
+ }
29717
+ const normalizedKey = key === "ls_provider" ? "provider" : key === "ls_model_name" ? "model" : key.startsWith("ls_") ? key.slice(3) : key;
29718
+ const sanitized = sanitizeLoggedValue(descriptor.value);
29719
+ if (sanitized !== void 0) {
29720
+ metadata[normalizedKey] = sanitized;
29721
+ }
29722
+ }
29723
+ return Object.keys(metadata).length === 0 ? void 0 : metadata;
29724
+ }
29725
+ function extractTags(value) {
29726
+ if (!Array.isArray(value)) {
29727
+ return void 0;
29728
+ }
29729
+ const tags = value.filter(
29730
+ (tag) => typeof tag === "string" && tag.length > 0
29731
+ );
29732
+ return tags.length > 0 ? tags : void 0;
29733
+ }
29734
+ function extractMetrics(run, previous) {
29735
+ const outputs = preferOwnValue(run, previous, "outputs");
29736
+ const extra = preferOwnValue(run, previous, "extra");
29737
+ const metadata = ownValue(extra, "metadata");
29738
+ const usage = ownValue(outputs, "usage_metadata") ?? ownValue(metadata, "usage_metadata");
29739
+ const metrics = {};
29740
+ assignFirstMetric(metrics, "prompt_tokens", usage, [
29741
+ "input_tokens",
29742
+ "prompt_tokens"
29743
+ ]);
29744
+ assignFirstMetric(metrics, "completion_tokens", usage, [
29745
+ "output_tokens",
29746
+ "completion_tokens"
29747
+ ]);
29748
+ assignFirstMetric(metrics, "tokens", usage, ["total_tokens", "tokens"]);
29749
+ const inputTokenDetails = ownValue(usage, "input_token_details");
29750
+ assignFirstMetric(metrics, "prompt_cached_tokens", inputTokenDetails, [
29751
+ "cache_read",
29752
+ "cached_tokens"
29753
+ ]);
29754
+ if (metrics.prompt_cached_tokens === void 0) {
29755
+ assignFirstMetric(metrics, "prompt_cached_tokens", usage, [
29756
+ "cache_read_input_tokens",
29757
+ "prompt_cached_tokens"
29758
+ ]);
29759
+ }
29760
+ assignFirstMetric(
29761
+ metrics,
29762
+ "prompt_cache_creation_tokens",
29763
+ inputTokenDetails,
29764
+ ["cache_creation"]
29765
+ );
29766
+ if (metrics.prompt_cache_creation_tokens === void 0) {
29767
+ assignFirstMetric(metrics, "prompt_cache_creation_tokens", usage, [
29768
+ "cache_creation_input_tokens",
29769
+ "prompt_cache_creation_tokens"
29770
+ ]);
29771
+ }
29772
+ if (metrics.tokens === void 0 && (metrics.prompt_tokens !== void 0 || metrics.completion_tokens !== void 0)) {
29773
+ metrics.tokens = (metrics.prompt_tokens ?? 0) + (metrics.completion_tokens ?? 0);
29774
+ }
29775
+ const startTime = timestampSeconds(
29776
+ preferOwnValue(run, previous, "start_time")
29777
+ );
29778
+ const events = preferOwnValue(run, previous, "events");
29779
+ if (startTime !== void 0 && Array.isArray(events)) {
29780
+ for (const event of events) {
29781
+ if (ownValue(event, "name") !== "new_token") {
29782
+ continue;
29783
+ }
29784
+ const eventTime3 = timestampSeconds(ownValue(event, "time"));
29785
+ if (eventTime3 !== void 0 && eventTime3 >= startTime) {
29786
+ metrics.time_to_first_token = eventTime3 - startTime;
29787
+ }
29788
+ break;
29789
+ }
29790
+ }
29791
+ return metrics;
29792
+ }
29793
+ function assignFirstMetric(metrics, target, source, keys) {
29794
+ for (const key of keys) {
29795
+ const value = ownValue(source, key);
29796
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
29797
+ metrics[target] = value;
29798
+ return;
29799
+ }
29800
+ }
29801
+ }
29802
+ function errorMessage(value) {
29803
+ if (typeof value === "string") {
29804
+ return value;
29805
+ }
29806
+ if (value instanceof Error) {
29807
+ return value.message;
29808
+ }
29809
+ return void 0;
29810
+ }
29811
+ function sanitizeLoggedValue(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
29812
+ if (value === null || typeof value === "string" || typeof value === "boolean") {
29813
+ return value;
29814
+ }
29815
+ if (typeof value === "number") {
29816
+ return Number.isFinite(value) ? value : void 0;
29817
+ }
29818
+ if (value instanceof Date) {
29819
+ return Number.isFinite(value.getTime()) ? value.toISOString() : void 0;
29820
+ }
29821
+ if (typeof value !== "object" || depth >= 20) {
29822
+ return void 0;
29823
+ }
29824
+ if (seen.has(value)) {
29825
+ return "[Circular]";
29826
+ }
29827
+ seen.add(value);
29828
+ if (Array.isArray(value)) {
29829
+ return value.map((item) => sanitizeLoggedValue(item, seen, depth + 1));
29830
+ }
29831
+ const entries = [];
29832
+ for (const [key, descriptor] of Object.entries(
29833
+ Object.getOwnPropertyDescriptors(value)
29834
+ )) {
29835
+ if (!descriptor.enumerable || !("value" in descriptor) || BLOCKED_METADATA_KEYS.has(key)) {
29836
+ continue;
29837
+ }
29838
+ entries.push([key, sanitizeLoggedValue(descriptor.value, seen, depth + 1)]);
29839
+ }
29840
+ return Object.fromEntries(entries);
29841
+ }
29842
+
29272
29843
  // src/instrumentation/plugins/pi-coding-agent-channels.ts
29273
29844
  var piCodingAgentChannels = defineChannels(
29274
29845
  "@earendil-works/pi-coding-agent",
@@ -29648,11 +30219,11 @@ function patchAssistantMessageStream(stream, promptState, llmState) {
29648
30219
  function recordPiAssistantMessageEvent(promptState, llmState, event) {
29649
30220
  recordFirstTokenMetric(llmState, event);
29650
30221
  const message = "message" in event ? event.message : void 0;
29651
- const errorMessage = "error" in event ? event.error : void 0;
30222
+ const errorMessage2 = "error" in event ? event.error : void 0;
29652
30223
  if (event.type === "done" && isPiAssistantMessage(message)) {
29653
30224
  finishPiLlmSpan(promptState, llmState, message);
29654
- } else if (event.type === "error" && isPiAssistantMessage(errorMessage)) {
29655
- finishPiLlmSpan(promptState, llmState, errorMessage);
30225
+ } else if (event.type === "error" && isPiAssistantMessage(errorMessage2)) {
30226
+ finishPiLlmSpan(promptState, llmState, errorMessage2);
29656
30227
  }
29657
30228
  }
29658
30229
  function recordFirstTokenMetric(state, event) {
@@ -30170,6 +30741,7 @@ var strandsAgentSDKChannels = defineChannels("@strands-agents/sdk", {
30170
30741
  });
30171
30742
 
30172
30743
  // src/instrumentation/plugins/strands-agent-sdk-plugin.ts
30744
+ var MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES = 32;
30173
30745
  var StrandsAgentSDKPlugin = class extends BasePlugin {
30174
30746
  activeChildParents = /* @__PURE__ */ new WeakMap();
30175
30747
  onEnable() {
@@ -30314,11 +30886,16 @@ function startAgentStream(event, activeChildParents) {
30314
30886
  ...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
30315
30887
  };
30316
30888
  const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
30889
+ const attachmentCache = createStrandsAttachmentCache();
30890
+ const input = processStrandsInputAttachments(
30891
+ event.arguments[0],
30892
+ attachmentCache
30893
+ );
30317
30894
  const span = parentSpan ? withCurrent(
30318
30895
  parentSpan,
30319
30896
  () => startSpan({
30320
30897
  event: {
30321
- input: event.arguments[0],
30898
+ input,
30322
30899
  metadata
30323
30900
  },
30324
30901
  name: formatAgentSpanName(agent),
@@ -30326,7 +30903,7 @@ function startAgentStream(event, activeChildParents) {
30326
30903
  })
30327
30904
  ) : startSpan({
30328
30905
  event: {
30329
- input: event.arguments[0],
30906
+ input,
30330
30907
  metadata
30331
30908
  },
30332
30909
  name: formatAgentSpanName(agent),
@@ -30334,6 +30911,7 @@ function startAgentStream(event, activeChildParents) {
30334
30911
  });
30335
30912
  return {
30336
30913
  activeTools: /* @__PURE__ */ new Map(),
30914
+ attachmentCache,
30337
30915
  finalized: false,
30338
30916
  metadata,
30339
30917
  span,
@@ -30349,11 +30927,12 @@ function startMultiAgentStream(event, operation, activeChildParents) {
30349
30927
  ...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
30350
30928
  };
30351
30929
  const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
30930
+ const input = processStrandsInputAttachments(event.arguments[0]);
30352
30931
  const span = parentSpan ? withCurrent(
30353
30932
  parentSpan,
30354
30933
  () => startSpan({
30355
30934
  event: {
30356
- input: event.arguments[0],
30935
+ input,
30357
30936
  metadata
30358
30937
  },
30359
30938
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -30361,7 +30940,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
30361
30940
  })
30362
30941
  ) : startSpan({
30363
30942
  event: {
30364
- input: event.arguments[0],
30943
+ input,
30365
30944
  metadata
30366
30945
  },
30367
30946
  name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
@@ -30470,7 +31049,10 @@ function startModelSpan(state, event) {
30470
31049
  state.span,
30471
31050
  () => startSpan({
30472
31051
  event: {
30473
- input: Array.isArray(event.agent?.messages) ? event.agent.messages : void 0,
31052
+ input: Array.isArray(event.agent?.messages) ? processStrandsInputAttachments(
31053
+ event.agent.messages,
31054
+ state.attachmentCache
31055
+ ) : void 0,
30474
31056
  metadata
30475
31057
  },
30476
31058
  name: formatModelSpanName(model),
@@ -30684,6 +31266,7 @@ function finalizeAgentStream(state, error, output) {
30684
31266
  ...output !== void 0 ? { output } : {}
30685
31267
  });
30686
31268
  state.span.end();
31269
+ state.attachmentCache.strings.clear();
30687
31270
  }
30688
31271
  function finalizeMultiAgentStream(state, activeChildParents, error, output) {
30689
31272
  if (state.finalized) {
@@ -30830,6 +31413,166 @@ function extractNodeResultOutput(result) {
30830
31413
  }
30831
31414
  return result;
30832
31415
  }
31416
+ var STRANDS_MEDIA_TYPES = {
31417
+ png: "image/png",
31418
+ jpg: "image/jpeg",
31419
+ jpeg: "image/jpeg",
31420
+ gif: "image/gif",
31421
+ webp: "image/webp",
31422
+ mkv: "video/x-matroska",
31423
+ mov: "video/quicktime",
31424
+ mp4: "video/mp4",
31425
+ webm: "video/webm",
31426
+ flv: "video/x-flv",
31427
+ mpeg: "video/mpeg",
31428
+ mpg: "video/mpeg",
31429
+ wmv: "video/x-ms-wmv",
31430
+ "3gp": "video/3gpp",
31431
+ pdf: "application/pdf",
31432
+ csv: "text/csv",
31433
+ doc: "application/msword",
31434
+ docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
31435
+ xls: "application/vnd.ms-excel",
31436
+ xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
31437
+ html: "text/html",
31438
+ txt: "text/plain",
31439
+ md: "text/markdown",
31440
+ json: "application/json",
31441
+ xml: "application/xml"
31442
+ };
31443
+ function createStrandsAttachmentCache() {
31444
+ return {
31445
+ objects: /* @__PURE__ */ new WeakMap(),
31446
+ strings: new LRUCache({
31447
+ max: MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES
31448
+ })
31449
+ };
31450
+ }
31451
+ function processStrandsInputAttachments(input, cache = createStrandsAttachmentCache()) {
31452
+ try {
31453
+ return processStrandsInputNode(input, cache);
31454
+ } catch (error) {
31455
+ logInstrumentationError5("Strands Agent SDK input attachments", error);
31456
+ return input;
31457
+ }
31458
+ }
31459
+ function processStrandsInputNode(value, cache) {
31460
+ if (value instanceof BaseAttachment) {
31461
+ return value;
31462
+ }
31463
+ if (Array.isArray(value)) {
31464
+ return value.map((child) => processStrandsInputNode(child, cache));
31465
+ }
31466
+ if (!isObject(value)) {
31467
+ return value;
31468
+ }
31469
+ const directMedia = processDirectStrandsMediaBlock(value, cache);
31470
+ if (directMedia !== void 0) {
31471
+ return directMedia;
31472
+ }
31473
+ const wrappedMedia = processWrappedStrandsMediaBlock(value, cache);
31474
+ if (wrappedMedia !== void 0) {
31475
+ return wrappedMedia;
31476
+ }
31477
+ if (value.type === "message" && Array.isArray(value.content)) {
31478
+ return {
31479
+ role: value.role,
31480
+ content: value.content.map(
31481
+ (child) => processStrandsInputNode(child, cache)
31482
+ ),
31483
+ ...value.metadata !== void 0 ? { metadata: value.metadata } : {}
31484
+ };
31485
+ }
31486
+ if (typeof value.toJSON === "function") {
31487
+ return processStrandsInputNode(value.toJSON(), cache);
31488
+ }
31489
+ return Object.fromEntries(
31490
+ Object.entries(value).map(([key, child]) => [
31491
+ key,
31492
+ processStrandsInputNode(child, cache)
31493
+ ])
31494
+ );
31495
+ }
31496
+ function processDirectStrandsMediaBlock(block, cache) {
31497
+ if (!isStrandsMediaBlock(block)) {
31498
+ return void 0;
31499
+ }
31500
+ const mediaKey = block.type === "imageBlock" ? "image" : block.type === "videoBlock" ? "video" : "document";
31501
+ return createStrandsMediaAttachment(mediaKey, block, cache);
31502
+ }
31503
+ function isStrandsMediaBlock(block) {
31504
+ return (block.type === "imageBlock" || block.type === "videoBlock" || block.type === "documentBlock") && typeof block.format === "string" && isObject(block.source);
31505
+ }
31506
+ function processWrappedStrandsMediaBlock(block, cache) {
31507
+ for (const mediaKey of ["image", "video", "document"]) {
31508
+ const media = block[mediaKey];
31509
+ if (!Object.hasOwn(block, mediaKey) || !isObject(media)) {
31510
+ continue;
31511
+ }
31512
+ const processed = createStrandsMediaAttachment(mediaKey, media, cache);
31513
+ if (processed !== void 0) {
31514
+ return processed;
31515
+ }
31516
+ }
31517
+ return void 0;
31518
+ }
31519
+ function createStrandsMediaAttachment(mediaKey, media, cache) {
31520
+ const format = media.format;
31521
+ const source = media.source;
31522
+ if (typeof format !== "string" || !isObject(source) || !Object.hasOwn(source, "bytes")) {
31523
+ return void 0;
31524
+ }
31525
+ const contentType = STRANDS_MEDIA_TYPES[format.toLowerCase()];
31526
+ if (!contentType) {
31527
+ return void 0;
31528
+ }
31529
+ const filename = mediaKey === "document" && typeof media.name === "string" && media.name.length > 0 ? media.name : `${mediaKey}.${format.toLowerCase()}`;
31530
+ const attachment = getOrCreateStrandsAttachment(
31531
+ source.bytes,
31532
+ filename,
31533
+ contentType,
31534
+ cache
31535
+ );
31536
+ if (!attachment) {
31537
+ return void 0;
31538
+ }
31539
+ const { type: _type, ...serializedMedia } = media;
31540
+ const { type: _sourceType, ...serializedSource } = source;
31541
+ return {
31542
+ [mediaKey]: {
31543
+ ...serializedMedia,
31544
+ source: {
31545
+ ...serializedSource,
31546
+ bytes: attachment
31547
+ }
31548
+ }
31549
+ };
31550
+ }
31551
+ function getOrCreateStrandsAttachment(data, filename, contentType, cache) {
31552
+ const key = `${contentType}\0${filename}`;
31553
+ const attachments = typeof data === "string" ? cache.strings.get(data) : isObject(data) ? cache.objects.get(data) : void 0;
31554
+ const cached = attachments?.get(key);
31555
+ if (cached) {
31556
+ return cached;
31557
+ }
31558
+ const blob = convertDataToBlob(data, contentType);
31559
+ if (!blob) {
31560
+ return void 0;
31561
+ }
31562
+ const attachment = new Attachment({
31563
+ data: blob,
31564
+ filename,
31565
+ contentType
31566
+ });
31567
+ const updatedAttachments = attachments ?? /* @__PURE__ */ new Map();
31568
+ updatedAttachments.set(key, attachment);
31569
+ if (typeof data === "string") {
31570
+ cache.strings.set(data, updatedAttachments);
31571
+ } else if (isObject(data)) {
31572
+ cache.objects.set(data, updatedAttachments);
31573
+ }
31574
+ return attachment;
31575
+ }
30833
31576
  function normalizeContentBlocks(blocks) {
30834
31577
  const text = blocks.map((block) => typeof block.text === "string" ? block.text : void 0).filter((part) => Boolean(part)).join("");
30835
31578
  return text.length > 0 ? text : blocks;
@@ -30959,6 +31702,7 @@ var BraintrustPlugin = class extends BasePlugin {
30959
31702
  gitHubCopilotPlugin = null;
30960
31703
  fluePlugin = null;
30961
31704
  langChainPlugin = null;
31705
+ langSmithPlugin = null;
30962
31706
  piCodingAgentPlugin = null;
30963
31707
  strandsAgentSDKPlugin = null;
30964
31708
  constructor(config = {}) {
@@ -31055,6 +31799,12 @@ var BraintrustPlugin = class extends BasePlugin {
31055
31799
  this.langChainPlugin = new LangChainPlugin();
31056
31800
  this.langChainPlugin.enable();
31057
31801
  }
31802
+ if (integrations.langsmith !== false) {
31803
+ this.langSmithPlugin = new LangSmithPlugin({
31804
+ skipLangChainRuns: integrations.langchain !== false
31805
+ });
31806
+ this.langSmithPlugin.enable();
31807
+ }
31058
31808
  }
31059
31809
  onDisable() {
31060
31810
  if (this.openaiPlugin) {
@@ -31145,6 +31895,10 @@ var BraintrustPlugin = class extends BasePlugin {
31145
31895
  this.langChainPlugin.disable();
31146
31896
  this.langChainPlugin = null;
31147
31897
  }
31898
+ if (this.langSmithPlugin) {
31899
+ this.langSmithPlugin.disable();
31900
+ this.langSmithPlugin = null;
31901
+ }
31148
31902
  }
31149
31903
  };
31150
31904
 
@@ -31209,7 +31963,8 @@ var envIntegrationAliases = {
31209
31963
  langchain: "langchain",
31210
31964
  "langchain-js": "langchain",
31211
31965
  "@langchain": "langchain",
31212
- langgraph: "langgraph"
31966
+ langgraph: "langgraph",
31967
+ langsmith: "langsmith"
31213
31968
  };
31214
31969
  function getDefaultInstrumentationIntegrations() {
31215
31970
  return {
@@ -31240,6 +31995,7 @@ function getDefaultInstrumentationIntegrations() {
31240
31995
  gitHubCopilot: true,
31241
31996
  langchain: true,
31242
31997
  langgraph: true,
31998
+ langsmith: true,
31243
31999
  piCodingAgent: true,
31244
32000
  strandsAgentSDK: true
31245
32001
  };
@@ -31545,6 +32301,8 @@ __export(exports_exports, {
31545
32301
  addAzureBlobHeaders: () => addAzureBlobHeaders,
31546
32302
  agentAssertionScorer: () => agentAssertionScorer,
31547
32303
  braintrustAISDKTelemetry: () => braintrustAISDKTelemetry,
32304
+ braintrustEveHook: () => braintrustEveHook,
32305
+ braintrustEveInstrumentation: () => braintrustEveInstrumentation,
31548
32306
  braintrustFlueInstrumentation: () => braintrustFlueInstrumentation,
31549
32307
  braintrustFlueObserver: () => braintrustFlueObserver,
31550
32308
  braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
@@ -31634,6 +32392,9 @@ __export(exports_exports, {
31634
32392
  wrapGoogleGenAI: () => wrapGoogleGenAI,
31635
32393
  wrapGroq: () => wrapGroq,
31636
32394
  wrapHuggingFace: () => wrapHuggingFace,
32395
+ wrapLangSmithClient: () => wrapLangSmithClient,
32396
+ wrapLangSmithRunTrees: () => wrapLangSmithRunTrees,
32397
+ wrapLangSmithTraceable: () => wrapLangSmithTraceable,
31637
32398
  wrapMastraAgent: () => wrapMastraAgent,
31638
32399
  wrapMistral: () => wrapMistral,
31639
32400
  wrapOpenAI: () => wrapOpenAI,
@@ -33045,6 +33806,1390 @@ function BraintrustMiddleware(config = {}) {
33045
33806
  };
33046
33807
  }
33047
33808
 
33809
+ // src/instrumentation/plugins/eve-plugin.ts
33810
+ var EVE_TRACE_STATE_KEY = "braintrust.eve.tracing";
33811
+ var MAX_EVE_CACHE_ENTRIES = 1e4;
33812
+ var MAX_STORED_LLM_INPUTS = 100;
33813
+ var MAX_STORED_SPAN_REFERENCES = 1e4;
33814
+ var MAX_STORED_STEP_STARTS = 1e4;
33815
+ function braintrustEveHook(options) {
33816
+ const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
33817
+ const bridge = new EveBridge(state);
33818
+ return {
33819
+ events: {
33820
+ "*": async (event, ctx) => {
33821
+ await bridge.handle(event, ctx, options.metadata);
33822
+ }
33823
+ }
33824
+ };
33825
+ }
33826
+ function braintrustEveInstrumentation(options) {
33827
+ const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
33828
+ return {
33829
+ events: {
33830
+ "step.started": (input) => {
33831
+ try {
33832
+ captureEveModelInput(state, input);
33833
+ } catch (error) {
33834
+ debugLogger.warn("Error in Eve LLM input capture:", error);
33835
+ }
33836
+ }
33837
+ },
33838
+ recordInputs: false,
33839
+ recordOutputs: false,
33840
+ setup: options.setup
33841
+ };
33842
+ }
33843
+ function isEveHandleMessageStreamEvent(event) {
33844
+ return isObject(event) && typeof event["type"] === "string";
33845
+ }
33846
+ var ResumedEveSpan = class {
33847
+ constructor(reference) {
33848
+ this.reference = reference;
33849
+ this.endTime = reference.endTime;
33850
+ }
33851
+ endTime;
33852
+ get rootSpanId() {
33853
+ return this.reference.rootSpanId;
33854
+ }
33855
+ get spanId() {
33856
+ return this.reference.spanId;
33857
+ }
33858
+ log(event) {
33859
+ const metrics = {
33860
+ ...this.reference.startEvent?.metrics,
33861
+ ...this.endTime === void 0 ? {} : { end: this.endTime },
33862
+ ...event.metrics
33863
+ };
33864
+ updateSpan({
33865
+ exported: this.reference.exported,
33866
+ ...this.reference.startEvent,
33867
+ ...event,
33868
+ ...Object.keys(metrics).length > 0 ? { metrics } : {}
33869
+ });
33870
+ }
33871
+ end(args) {
33872
+ if (this.endTime === void 0) {
33873
+ this.endTime = args?.endTime ?? getCurrentUnixTimestamp();
33874
+ this.log({ metrics: { end: this.endTime } });
33875
+ }
33876
+ return this.endTime;
33877
+ }
33878
+ };
33879
+ var EveBridge = class {
33880
+ constructor(state) {
33881
+ this.state = state;
33882
+ }
33883
+ eventQueuesBySession = /* @__PURE__ */ new Map();
33884
+ completedToolKeys = new LRUCache({
33885
+ max: MAX_EVE_CACHE_ENTRIES
33886
+ });
33887
+ toolsByCallKey = new LRUCache({
33888
+ max: MAX_EVE_CACHE_ENTRIES
33889
+ });
33890
+ turnsByKey = new LRUCache({
33891
+ max: MAX_EVE_CACHE_ENTRIES
33892
+ });
33893
+ async startEveSpan(args) {
33894
+ const rowId = args?.event?.id;
33895
+ const reference = typeof rowId === "string" && readEveTraceState(this.state).spanReferences.find(
33896
+ (candidate) => candidate.rowId === rowId
33897
+ );
33898
+ if (reference) {
33899
+ return new ResumedEveSpan(reference);
33900
+ }
33901
+ const startTime = args?.startTime ?? getCurrentUnixTimestamp();
33902
+ const parentSpanIds = args?.parentSpanIds;
33903
+ const startEvent = {
33904
+ created: (/* @__PURE__ */ new Date()).toISOString(),
33905
+ metrics: { start: startTime },
33906
+ span_attributes: {
33907
+ ...args?.name ? { name: args.name } : {},
33908
+ ...args?.type ? { type: args.type } : {},
33909
+ ...args?.spanAttributes
33910
+ },
33911
+ span_parents: parentSpanIds ? "spanId" in parentSpanIds ? [parentSpanIds.spanId] : parentSpanIds.parentSpanIds : []
33912
+ };
33913
+ const span = withCurrent(
33914
+ NOOP_SPAN,
33915
+ () => _internalStartSpanWithInitialMerge({ ...args, startTime })
33916
+ );
33917
+ if (typeof rowId !== "string") {
33918
+ return span;
33919
+ }
33920
+ try {
33921
+ const exported = await span.export();
33922
+ const reference2 = {
33923
+ exported,
33924
+ rootSpanId: span.rootSpanId,
33925
+ rowId,
33926
+ spanId: span.spanId,
33927
+ startEvent
33928
+ };
33929
+ this.state.update((current) => {
33930
+ const normalized = normalizeEveTraceState(current);
33931
+ return normalized.spanReferences.some(
33932
+ (candidate) => candidate.rowId === rowId
33933
+ ) ? normalized : {
33934
+ ...normalized,
33935
+ spanReferences: [...normalized.spanReferences, reference2].slice(
33936
+ -MAX_STORED_SPAN_REFERENCES
33937
+ )
33938
+ };
33939
+ });
33940
+ } catch (error) {
33941
+ debugLogger.warn("Error exporting Eve span for resumption:", error);
33942
+ }
33943
+ return span;
33944
+ }
33945
+ async startEveChildSpan(parent, args) {
33946
+ return await this.startEveSpan({
33947
+ ...args,
33948
+ parentSpanIds: {
33949
+ rootSpanId: parent.rootSpanId,
33950
+ spanId: parent.spanId
33951
+ }
33952
+ });
33953
+ }
33954
+ stepOrdinal(event) {
33955
+ let ordinal = 0;
33956
+ this.state.update((current) => {
33957
+ const state = normalizeEveTraceState(current);
33958
+ const previous = state.stepStarts.filter(
33959
+ (entry) => entry.turnId === event.data.turnId && entry.stepIndex === event.data.stepIndex
33960
+ ).at(-1);
33961
+ if (previous?.open) {
33962
+ ordinal = previous.ordinal;
33963
+ return state;
33964
+ }
33965
+ ordinal = state.stepStarts.filter(
33966
+ (entry) => entry.turnId === event.data.turnId
33967
+ ).length;
33968
+ return {
33969
+ ...state,
33970
+ stepStarts: [
33971
+ ...state.stepStarts,
33972
+ {
33973
+ open: true,
33974
+ ordinal,
33975
+ stepIndex: event.data.stepIndex,
33976
+ turnId: event.data.turnId
33977
+ }
33978
+ ].slice(-MAX_STORED_STEP_STARTS)
33979
+ };
33980
+ });
33981
+ return ordinal;
33982
+ }
33983
+ markStepEnded(turnId, stepIndex) {
33984
+ this.state.update((current) => {
33985
+ const state = normalizeEveTraceState(current);
33986
+ let index = -1;
33987
+ for (let i = state.stepStarts.length - 1; i >= 0; i--) {
33988
+ const entry = state.stepStarts[i];
33989
+ if (entry?.turnId === turnId && entry.stepIndex === stepIndex) {
33990
+ index = i;
33991
+ break;
33992
+ }
33993
+ }
33994
+ if (index < 0 || !state.stepStarts[index]?.open) {
33995
+ return state;
33996
+ }
33997
+ return {
33998
+ ...state,
33999
+ stepStarts: state.stepStarts.map(
34000
+ (entry, entryIndex) => entryIndex === index ? { ...entry, open: false } : entry
34001
+ )
34002
+ };
34003
+ });
34004
+ }
34005
+ async handle(event, ctx, hookMetadata) {
34006
+ if (!isEveHandleMessageStreamEvent(event)) {
34007
+ return;
34008
+ }
34009
+ const run = async () => {
34010
+ try {
34011
+ if (!await this.handleEvent(event, ctx, hookMetadata)) {
34012
+ return;
34013
+ }
34014
+ if (event.type === "session.failed") {
34015
+ const sessionId2 = event.data.sessionId || sessionIdFromContext(ctx);
34016
+ await this.flushInstrumentation();
34017
+ if (sessionId2) {
34018
+ this.cleanupSession(sessionId2);
34019
+ }
34020
+ } else if (event.type === "session.completed") {
34021
+ const sessionId2 = sessionIdFromContext(ctx);
34022
+ await this.flushInstrumentation();
34023
+ if (sessionId2) {
34024
+ this.cleanupSession(sessionId2);
34025
+ }
34026
+ }
34027
+ } catch (error) {
34028
+ debugLogger.warn("Error in Eve hook instrumentation:", error);
34029
+ }
34030
+ };
34031
+ const sessionId = event.type === "session.failed" ? event.data.sessionId || sessionIdFromContext(ctx) : sessionIdFromContext(ctx);
34032
+ if (!sessionId) {
34033
+ await run();
34034
+ return;
34035
+ }
34036
+ const previous = this.eventQueuesBySession.get(sessionId);
34037
+ const queued = previous ? previous.then(run) : run();
34038
+ this.eventQueuesBySession.set(sessionId, queued);
34039
+ try {
34040
+ await queued;
34041
+ } finally {
34042
+ if (this.eventQueuesBySession.get(sessionId) === queued) {
34043
+ this.eventQueuesBySession.delete(sessionId);
34044
+ }
34045
+ }
34046
+ }
34047
+ async handleEvent(event, ctx, hookMetadata) {
34048
+ switch (event.type) {
34049
+ case "session.started":
34050
+ this.handleSessionStarted(event, ctx, hookMetadata);
34051
+ return true;
34052
+ case "turn.started":
34053
+ await this.handleTurnStarted(event, ctx, hookMetadata);
34054
+ return true;
34055
+ case "message.received":
34056
+ await this.handleMessageReceived(event, ctx, hookMetadata);
34057
+ return true;
34058
+ case "step.started":
34059
+ await this.handleStepStarted(event, ctx, hookMetadata);
34060
+ return true;
34061
+ case "message.completed":
34062
+ this.handleMessageCompleted(event, ctx);
34063
+ return true;
34064
+ case "result.completed":
34065
+ this.handleResultCompleted(event, ctx);
34066
+ return true;
34067
+ case "actions.requested":
34068
+ await this.handleActionsRequested(event, ctx, hookMetadata);
34069
+ return true;
34070
+ case "action.result":
34071
+ await this.handleActionResult(event, ctx, hookMetadata);
34072
+ return true;
34073
+ case "subagent.called":
34074
+ await this.handleSubagentCalled(event, ctx, hookMetadata);
34075
+ return true;
34076
+ case "subagent.completed":
34077
+ await this.handleSubagentCompleted(event, ctx, hookMetadata);
34078
+ return true;
34079
+ case "step.completed":
34080
+ this.handleStepCompleted(event, ctx);
34081
+ return true;
34082
+ case "step.failed":
34083
+ this.handleStepFailed(event, ctx);
34084
+ return true;
34085
+ case "turn.completed":
34086
+ this.handleTurnCompleted(event, ctx);
34087
+ return true;
34088
+ case "turn.failed":
34089
+ this.handleTurnFailed(event, ctx);
34090
+ return true;
34091
+ case "session.failed":
34092
+ this.handleSessionFailed(event, ctx);
34093
+ return true;
34094
+ case "session.completed":
34095
+ this.handleSessionCompleted(event, ctx);
34096
+ return true;
34097
+ default:
34098
+ return false;
34099
+ }
34100
+ }
34101
+ handleSessionStarted(event, ctx, hookMetadata) {
34102
+ const sessionId = sessionIdFromContext(ctx);
34103
+ if (!sessionId) {
34104
+ return;
34105
+ }
34106
+ const metadata = {
34107
+ ...hookMetadata ?? {},
34108
+ ...modelMetadataFromRuntime(event.data.runtime)
34109
+ };
34110
+ this.state.update((current) => {
34111
+ const normalized = normalizeEveTraceState(current);
34112
+ return {
34113
+ ...normalized,
34114
+ metadata: { ...normalized.metadata, ...metadata }
34115
+ };
34116
+ });
34117
+ for (const [key, turn] of this.turnsByKey) {
34118
+ if (!key.startsWith(`${sessionId}:`)) {
34119
+ continue;
34120
+ }
34121
+ turn.metadata = { ...turn.metadata, ...metadata };
34122
+ turn.span.log({ metadata: turn.metadata });
34123
+ for (const step of turn.stepsByIndex.values()) {
34124
+ step.metadata = { ...step.metadata, ...metadata };
34125
+ step.span.log({ metadata: step.metadata });
34126
+ }
34127
+ }
34128
+ }
34129
+ async handleTurnStarted(event, ctx, hookMetadata) {
34130
+ const sessionId = sessionIdFromContext(ctx);
34131
+ if (!sessionId) {
34132
+ return;
34133
+ }
34134
+ const key = turnKey2(sessionId, event.data.turnId);
34135
+ const metadata = {
34136
+ ...readEveTraceState(this.state).metadata,
34137
+ ...hookMetadata ?? {},
34138
+ "eve.session_id": sessionId
34139
+ };
34140
+ const existing = this.turnsByKey.get(key);
34141
+ if (existing) {
34142
+ existing.metadata = { ...existing.metadata, ...metadata };
34143
+ existing.span.log({ metadata: existing.metadata });
34144
+ return;
34145
+ }
34146
+ const span = await this.startTurnSpan(sessionId, event, ctx, metadata);
34147
+ span.log({ metadata });
34148
+ this.turnsByKey.set(key, {
34149
+ key,
34150
+ metadata,
34151
+ metrics: {},
34152
+ span,
34153
+ stepsByIndex: /* @__PURE__ */ new Map(),
34154
+ turnId: event.data.turnId
34155
+ });
34156
+ }
34157
+ async handleMessageReceived(event, ctx, hookMetadata) {
34158
+ const turn = await this.ensureTurn(event, ctx, hookMetadata);
34159
+ if (!turn) {
34160
+ return;
34161
+ }
34162
+ const input = [{ content: event.data.message, role: "user" }];
34163
+ turn.span.log({ input });
34164
+ }
34165
+ async handleStepStarted(event, ctx, hookMetadata) {
34166
+ const turn = await this.ensureTurn(event, ctx, hookMetadata);
34167
+ const sessionId = sessionIdFromContext(ctx);
34168
+ if (!turn || !sessionId) {
34169
+ return;
34170
+ }
34171
+ const existing = turn.stepsByIndex.get(event.data.stepIndex);
34172
+ if (existing) {
34173
+ existing.span.log({
34174
+ ...existing.input !== void 0 ? { input: existing.input } : {},
34175
+ metadata: existing.metadata,
34176
+ metrics: existing.metrics,
34177
+ output: existing.output
34178
+ });
34179
+ const endTime = eventTime2(event);
34180
+ existing.span.end(endTime === void 0 ? void 0 : { endTime });
34181
+ this.markStepEnded(event.data.turnId, event.data.stepIndex);
34182
+ }
34183
+ const stepOrdinal = this.stepOrdinal(event);
34184
+ const metadata = { ...turn.metadata };
34185
+ const input = consumeCapturedEveModelInput(
34186
+ this.state,
34187
+ sessionId,
34188
+ event.data.turnId,
34189
+ event.data.stepIndex
34190
+ );
34191
+ const { rowId: eventId, spanId } = await generateEveIds(
34192
+ "step",
34193
+ sessionId,
34194
+ event.data.turnId,
34195
+ String(stepOrdinal)
34196
+ );
34197
+ const span = await this.startEveChildSpan(turn.span, {
34198
+ event: {
34199
+ id: eventId,
34200
+ ...input !== void 0 ? { input } : {},
34201
+ metadata
34202
+ },
34203
+ name: "eve.step",
34204
+ spanAttributes: { type: "llm" /* LLM */ },
34205
+ spanId,
34206
+ startTime: eventTime2(event)
34207
+ });
34208
+ span.log({ ...input !== void 0 ? { input } : {}, metadata });
34209
+ turn.stepsByIndex.set(event.data.stepIndex, {
34210
+ ...input !== void 0 ? { input } : {},
34211
+ metadata,
34212
+ metrics: {},
34213
+ span
34214
+ });
34215
+ }
34216
+ handleMessageCompleted(event, ctx) {
34217
+ const step = this.stepForEvent(event, ctx);
34218
+ if (!step) {
34219
+ return;
34220
+ }
34221
+ const existingMessage = Array.isArray(step.output) && isObject(step.output[0]) ? step.output[0].message : void 0;
34222
+ const existingToolCalls = isObject(existingMessage) ? existingMessage.tool_calls : void 0;
34223
+ step.output = [
34224
+ {
34225
+ finish_reason: normalizedFinishReason(event.data.finishReason),
34226
+ index: 0,
34227
+ message: {
34228
+ content: event.data.message,
34229
+ role: "assistant",
34230
+ ...Array.isArray(existingToolCalls) ? { tool_calls: existingToolCalls } : {}
34231
+ }
34232
+ }
34233
+ ];
34234
+ const turn = this.turnForEvent(event, ctx);
34235
+ if (turn && event.data.finishReason !== "tool-calls") {
34236
+ turn.output = event.data.message;
34237
+ }
34238
+ }
34239
+ handleResultCompleted(event, ctx) {
34240
+ const step = this.stepForEvent(event, ctx);
34241
+ if (step) {
34242
+ step.output = [
34243
+ {
34244
+ finish_reason: "stop",
34245
+ index: 0,
34246
+ message: {
34247
+ content: event.data.result,
34248
+ role: "assistant"
34249
+ }
34250
+ }
34251
+ ];
34252
+ }
34253
+ const turn = this.turnForEvent(event, ctx);
34254
+ if (turn) {
34255
+ turn.output = event.data.result;
34256
+ }
34257
+ }
34258
+ async handleActionsRequested(event, ctx, hookMetadata) {
34259
+ const turn = await this.ensureTurn(event, ctx, hookMetadata);
34260
+ const sessionId = sessionIdFromContext(ctx);
34261
+ if (!turn || !sessionId) {
34262
+ return;
34263
+ }
34264
+ const traceActions = event.data.actions.filter(isTraceableActionRequest);
34265
+ if (traceActions.length === 0) {
34266
+ return;
34267
+ }
34268
+ for (const action of traceActions) {
34269
+ if (isToolCallAction(action)) {
34270
+ await this.startRequestedTool(event, turn, sessionId, action);
34271
+ } else if (isLocalSubagentCallAction(action)) {
34272
+ await this.startRequestedSubagent(event, turn, sessionId, action);
34273
+ }
34274
+ }
34275
+ const step = turn.stepsByIndex.get(event.data.stepIndex);
34276
+ if (!step) {
34277
+ return;
34278
+ }
34279
+ const toolCallsById = /* @__PURE__ */ new Map();
34280
+ if (Array.isArray(step.output) && isObject(step.output[0])) {
34281
+ const message = step.output[0]["message"];
34282
+ if (isObject(message) && Array.isArray(message["tool_calls"])) {
34283
+ for (const toolCall of message["tool_calls"]) {
34284
+ if (isObject(toolCall) && typeof toolCall["id"] === "string") {
34285
+ toolCallsById.set(toolCall["id"], toolCall);
34286
+ }
34287
+ }
34288
+ }
34289
+ }
34290
+ for (const action of traceActions) {
34291
+ const name = action.kind === "tool-call" ? action.toolName : action.subagentName ?? action.name ?? "agent";
34292
+ toolCallsById.set(action.callId, {
34293
+ function: {
34294
+ arguments: JSON.stringify(action.input),
34295
+ name
34296
+ },
34297
+ id: action.callId,
34298
+ type: "function"
34299
+ });
34300
+ }
34301
+ step.output = [
34302
+ {
34303
+ finish_reason: "tool_calls",
34304
+ index: 0,
34305
+ message: {
34306
+ content: null,
34307
+ role: "assistant",
34308
+ tool_calls: [...toolCallsById.values()]
34309
+ }
34310
+ }
34311
+ ];
34312
+ step.span.log({ metadata: step.metadata, output: step.output });
34313
+ }
34314
+ async handleActionResult(event, ctx, hookMetadata) {
34315
+ if (isToolResult(event.data.result)) {
34316
+ await this.handleToolResult(event, ctx, event.data.result, hookMetadata);
34317
+ return;
34318
+ }
34319
+ if (isSubagentResult(event.data.result)) {
34320
+ await this.handleSubagentResult(
34321
+ event,
34322
+ ctx,
34323
+ event.data.result,
34324
+ hookMetadata
34325
+ );
34326
+ }
34327
+ }
34328
+ async handleToolResult(event, ctx, result, hookMetadata) {
34329
+ const sessionId = sessionIdFromContext(ctx);
34330
+ if (!sessionId) {
34331
+ return;
34332
+ }
34333
+ const key = toolKey3(sessionId, result.callId);
34334
+ if (this.completedToolKeys.has(key)) {
34335
+ return;
34336
+ }
34337
+ const tool = this.toolsByCallKey.get(key) ?? await this.startSyntheticTool(event, ctx, result, hookMetadata);
34338
+ if (!tool) {
34339
+ return;
34340
+ }
34341
+ const failed = event.data.status === "failed" || result.isError === true || event.data.error !== void 0;
34342
+ tool.span.log({
34343
+ ...failed ? {
34344
+ error: actionResultError(event.data.error, result.output)
34345
+ } : {},
34346
+ metadata: tool.metadata,
34347
+ output: result.output
34348
+ });
34349
+ const endTime = eventTime2(event);
34350
+ tool.span.end(endTime === void 0 ? void 0 : { endTime });
34351
+ this.toolsByCallKey.delete(key);
34352
+ this.completedToolKeys.set(key, true);
34353
+ }
34354
+ async handleSubagentCalled(event, ctx, hookMetadata) {
34355
+ if (event.data.remote?.url) {
34356
+ return;
34357
+ }
34358
+ const turn = await this.ensureTurn(event, ctx, hookMetadata);
34359
+ const sessionId = sessionIdFromContext(ctx);
34360
+ if (!turn || !sessionId) {
34361
+ return;
34362
+ }
34363
+ const key = toolKey3(sessionId, event.data.callId);
34364
+ const metadata = toolMetadataFromTurn(turn);
34365
+ const existing = this.toolsByCallKey.get(key);
34366
+ if (existing) {
34367
+ existing.metadata = { ...existing.metadata, ...metadata };
34368
+ existing.span.log({ metadata: existing.metadata });
34369
+ return;
34370
+ }
34371
+ if (this.completedToolKeys.has(key)) {
34372
+ return;
34373
+ }
34374
+ const { rowId: eventId, spanId } = await generateEveIds(
34375
+ "subagent",
34376
+ sessionId,
34377
+ event.data.callId
34378
+ );
34379
+ const pending = this.toolsByCallKey.get(key);
34380
+ if (pending || this.completedToolKeys.has(key)) {
34381
+ if (pending) {
34382
+ pending.metadata = { ...pending.metadata, ...metadata };
34383
+ pending.span.log({ metadata: pending.metadata });
34384
+ }
34385
+ return;
34386
+ }
34387
+ const span = await this.startEveChildSpan(turn.span, {
34388
+ event: {
34389
+ id: eventId,
34390
+ metadata
34391
+ },
34392
+ name: event.data.toolName ?? event.data.name,
34393
+ spanAttributes: { type: "tool" /* TOOL */ },
34394
+ spanId,
34395
+ startTime: eventTime2(event)
34396
+ });
34397
+ span.log({ metadata });
34398
+ this.toolsByCallKey.set(key, {
34399
+ metadata,
34400
+ span,
34401
+ turnKey: turnKey2(sessionId, event.data.turnId)
34402
+ });
34403
+ }
34404
+ async handleSubagentCompleted(event, ctx, hookMetadata) {
34405
+ const sessionId = sessionIdFromContext(ctx);
34406
+ if (!sessionId) {
34407
+ return;
34408
+ }
34409
+ const key = toolKey3(sessionId, event.data.callId);
34410
+ if (this.completedToolKeys.has(key)) {
34411
+ return;
34412
+ }
34413
+ const subagent = this.toolsByCallKey.get(key) ?? await this.startSyntheticSubagent(event, ctx, hookMetadata);
34414
+ if (!subagent) {
34415
+ return;
34416
+ }
34417
+ subagent.span.log({
34418
+ ...event.data.status === "failed" ? {
34419
+ error: actionResultError(event.data.error, event.data.output)
34420
+ } : {},
34421
+ metadata: subagent.metadata,
34422
+ ...event.data.output !== void 0 ? { output: event.data.output } : {}
34423
+ });
34424
+ const endTime = eventTime2(event);
34425
+ const recordedEndTime = subagent.span.end(
34426
+ endTime === void 0 ? void 0 : { endTime }
34427
+ );
34428
+ this.state.update((current) => {
34429
+ const normalized = normalizeEveTraceState(current);
34430
+ return {
34431
+ ...normalized,
34432
+ spanReferences: normalized.spanReferences.map(
34433
+ (reference) => reference.spanId === subagent.span.spanId ? { ...reference, endTime: recordedEndTime } : reference
34434
+ )
34435
+ };
34436
+ });
34437
+ }
34438
+ async handleSubagentResult(event, ctx, result, hookMetadata) {
34439
+ const sessionId = sessionIdFromContext(ctx);
34440
+ if (!sessionId) {
34441
+ return;
34442
+ }
34443
+ const key = toolKey3(sessionId, result.callId);
34444
+ if (this.completedToolKeys.has(key)) {
34445
+ return;
34446
+ }
34447
+ const subagent = this.toolsByCallKey.get(key) ?? await this.startSyntheticSubagentResult(
34448
+ event,
34449
+ ctx,
34450
+ result,
34451
+ hookMetadata
34452
+ );
34453
+ if (!subagent) {
34454
+ return;
34455
+ }
34456
+ const isError = event.data.status === "failed" || result.isError === true || event.data.error !== void 0;
34457
+ subagent.span.log({
34458
+ ...isError ? {
34459
+ error: actionResultError(event.data.error, result.output)
34460
+ } : {},
34461
+ metadata: subagent.metadata,
34462
+ output: result.output
34463
+ });
34464
+ const endTime = eventTime2(event);
34465
+ subagent.span.end(endTime === void 0 ? void 0 : { endTime });
34466
+ this.toolsByCallKey.delete(key);
34467
+ this.completedToolKeys.set(key, true);
34468
+ }
34469
+ handleStepCompleted(event, ctx) {
34470
+ const step = this.stepForEvent(event, ctx);
34471
+ if (!step) {
34472
+ return;
34473
+ }
34474
+ const usage = event.data.usage;
34475
+ const inputTokens = typeof usage?.inputTokens === "number" && Number.isFinite(usage.inputTokens) && usage.inputTokens >= 0 ? usage.inputTokens : void 0;
34476
+ const outputTokens = typeof usage?.outputTokens === "number" && Number.isFinite(usage.outputTokens) && usage.outputTokens >= 0 ? usage.outputTokens : void 0;
34477
+ const cacheReadTokens = typeof usage?.cacheReadTokens === "number" && Number.isFinite(usage.cacheReadTokens) && usage.cacheReadTokens >= 0 ? usage.cacheReadTokens : void 0;
34478
+ const cacheWriteTokens = typeof usage?.cacheWriteTokens === "number" && Number.isFinite(usage.cacheWriteTokens) && usage.cacheWriteTokens >= 0 ? usage.cacheWriteTokens : void 0;
34479
+ const costUsd = typeof usage?.costUsd === "number" && Number.isFinite(usage.costUsd) && usage.costUsd >= 0 ? usage.costUsd : void 0;
34480
+ const total = inputTokens !== void 0 && outputTokens !== void 0 ? inputTokens + outputTokens : void 0;
34481
+ const metrics = {
34482
+ ...inputTokens !== void 0 ? { prompt_tokens: inputTokens } : {},
34483
+ ...outputTokens !== void 0 ? { completion_tokens: outputTokens } : {},
34484
+ ...total !== void 0 ? { tokens: total } : {},
34485
+ ...cacheReadTokens !== void 0 ? { prompt_cached_tokens: cacheReadTokens } : {},
34486
+ ...cacheWriteTokens !== void 0 ? { prompt_cache_creation_tokens: cacheWriteTokens } : {},
34487
+ ...costUsd !== void 0 ? { estimated_cost: costUsd } : {}
34488
+ };
34489
+ step.metrics = { ...step.metrics, ...metrics };
34490
+ if (Array.isArray(step.output) && isObject(step.output[0])) {
34491
+ const finishReason = step.output[0].finish_reason;
34492
+ if (typeof finishReason !== "string") {
34493
+ step.output[0].finish_reason = normalizedFinishReason(
34494
+ event.data.finishReason
34495
+ );
34496
+ }
34497
+ }
34498
+ step.span.log({
34499
+ ...step.input !== void 0 ? { input: step.input } : {},
34500
+ metadata: step.metadata,
34501
+ metrics,
34502
+ output: step.output
34503
+ });
34504
+ const endTime = eventTime2(event);
34505
+ step.span.end(endTime === void 0 ? void 0 : { endTime });
34506
+ const turn = this.turnForEvent(event, ctx);
34507
+ if (turn) {
34508
+ for (const [key, value] of Object.entries(metrics)) {
34509
+ turn.metrics[key] = (turn.metrics[key] ?? 0) + value;
34510
+ }
34511
+ turn.stepsByIndex.delete(event.data.stepIndex);
34512
+ }
34513
+ this.markStepEnded(event.data.turnId, event.data.stepIndex);
34514
+ }
34515
+ handleStepFailed(event, ctx) {
34516
+ const step = this.stepForEvent(event, ctx);
34517
+ if (step) {
34518
+ step.span.log({
34519
+ error: errorFromMessage(
34520
+ event.data.message,
34521
+ event.data.code,
34522
+ event.data.details
34523
+ )
34524
+ });
34525
+ const endTime = eventTime2(event);
34526
+ step.span.end(endTime === void 0 ? void 0 : { endTime });
34527
+ }
34528
+ const turn = this.turnForEvent(event, ctx);
34529
+ turn?.stepsByIndex.delete(event.data.stepIndex);
34530
+ this.markStepEnded(event.data.turnId, event.data.stepIndex);
34531
+ }
34532
+ handleTurnCompleted(event, ctx) {
34533
+ const turn = this.turnForEvent(event, ctx);
34534
+ if (!turn) {
34535
+ return;
34536
+ }
34537
+ this.finalizeTurn(turn, {
34538
+ endTime: eventTime2(event)
34539
+ });
34540
+ }
34541
+ handleTurnFailed(event, ctx) {
34542
+ const turn = this.turnForEvent(event, ctx);
34543
+ if (!turn) {
34544
+ return;
34545
+ }
34546
+ this.finalizeTurn(turn, {
34547
+ endTime: eventTime2(event),
34548
+ error: errorFromMessage(
34549
+ event.data.message,
34550
+ event.data.code,
34551
+ event.data.details
34552
+ )
34553
+ });
34554
+ }
34555
+ handleSessionFailed(event, ctx) {
34556
+ const sessionId = event.data.sessionId || sessionIdFromContext(ctx);
34557
+ if (!sessionId) {
34558
+ return;
34559
+ }
34560
+ const error = errorFromMessage(
34561
+ event.data.message,
34562
+ event.data.code,
34563
+ event.data.details
34564
+ );
34565
+ for (const [key, turn] of this.turnsByKey) {
34566
+ if (!key.startsWith(`${sessionId}:`)) {
34567
+ continue;
34568
+ }
34569
+ this.finalizeTurn(turn, {
34570
+ endTime: eventTime2(event),
34571
+ error
34572
+ });
34573
+ }
34574
+ for (const [key, tool] of this.toolsByCallKey) {
34575
+ if (key.startsWith(`${sessionId}:`)) {
34576
+ const endTime = eventTime2(event);
34577
+ if (!tool.endedByTurn) {
34578
+ tool.span.log({ metadata: tool.metadata });
34579
+ tool.span.end(endTime === void 0 ? void 0 : { endTime });
34580
+ tool.endedByTurn = true;
34581
+ }
34582
+ }
34583
+ }
34584
+ }
34585
+ handleSessionCompleted(event, ctx) {
34586
+ const sessionId = sessionIdFromContext(ctx);
34587
+ if (!sessionId) {
34588
+ return;
34589
+ }
34590
+ for (const [key, turn] of this.turnsByKey) {
34591
+ if (!key.startsWith(`${sessionId}:`)) {
34592
+ continue;
34593
+ }
34594
+ this.finalizeTurn(turn, {
34595
+ endTime: eventTime2(event)
34596
+ });
34597
+ }
34598
+ for (const [key, tool] of this.toolsByCallKey) {
34599
+ if (key.startsWith(`${sessionId}:`) && !tool.endedByTurn) {
34600
+ const endTime = eventTime2(event);
34601
+ tool.span.log({ metadata: tool.metadata });
34602
+ tool.span.end(endTime === void 0 ? void 0 : { endTime });
34603
+ tool.endedByTurn = true;
34604
+ }
34605
+ }
34606
+ }
34607
+ async ensureTurn(event, ctx, hookMetadata) {
34608
+ const sessionId = sessionIdFromContext(ctx);
34609
+ if (!sessionId) {
34610
+ return void 0;
34611
+ }
34612
+ const key = turnKey2(sessionId, event.data.turnId);
34613
+ const existing = this.turnsByKey.get(key);
34614
+ if (existing) {
34615
+ return existing;
34616
+ }
34617
+ const metadata = {
34618
+ ...readEveTraceState(this.state).metadata,
34619
+ ...hookMetadata ?? {},
34620
+ "eve.session_id": sessionId
34621
+ };
34622
+ const span = await this.startTurnSpan(sessionId, event, ctx, metadata);
34623
+ span.log({ metadata });
34624
+ const state = {
34625
+ key,
34626
+ metadata,
34627
+ metrics: {},
34628
+ span,
34629
+ stepsByIndex: /* @__PURE__ */ new Map(),
34630
+ turnId: event.data.turnId
34631
+ };
34632
+ this.turnsByKey.set(key, state);
34633
+ return state;
34634
+ }
34635
+ async startRequestedTool(event, turn, sessionId, action) {
34636
+ const key = toolKey3(sessionId, action.callId);
34637
+ if (this.toolsByCallKey.has(key) || this.completedToolKeys.has(key)) {
34638
+ return;
34639
+ }
34640
+ const metadata = toolMetadataFromTurn(turn);
34641
+ const { rowId: eventId, spanId } = await generateEveIds(
34642
+ "tool",
34643
+ sessionId,
34644
+ event.data.turnId,
34645
+ action.callId
34646
+ );
34647
+ if (this.toolsByCallKey.has(key) || this.completedToolKeys.has(key)) {
34648
+ return;
34649
+ }
34650
+ const span = await this.startEveChildSpan(turn.span, {
34651
+ event: {
34652
+ id: eventId,
34653
+ input: action.input,
34654
+ metadata
34655
+ },
34656
+ name: action.toolName,
34657
+ spanAttributes: { type: "tool" /* TOOL */ },
34658
+ spanId,
34659
+ startTime: eventTime2(event)
34660
+ });
34661
+ span.log({ input: action.input, metadata });
34662
+ this.toolsByCallKey.set(key, {
34663
+ metadata,
34664
+ span,
34665
+ turnKey: turnKey2(sessionId, event.data.turnId)
34666
+ });
34667
+ }
34668
+ async startRequestedSubagent(event, turn, sessionId, action) {
34669
+ const key = toolKey3(sessionId, action.callId);
34670
+ if (this.toolsByCallKey.has(key) || this.completedToolKeys.has(key)) {
34671
+ return;
34672
+ }
34673
+ const name = action.subagentName ?? action.name ?? "agent";
34674
+ const metadata = toolMetadataFromTurn(turn);
34675
+ const { rowId: eventId, spanId } = await generateEveIds(
34676
+ "subagent",
34677
+ sessionId,
34678
+ action.callId
34679
+ );
34680
+ if (this.toolsByCallKey.has(key) || this.completedToolKeys.has(key)) {
34681
+ return;
34682
+ }
34683
+ const span = await this.startEveChildSpan(turn.span, {
34684
+ event: {
34685
+ id: eventId,
34686
+ input: action.input,
34687
+ metadata
34688
+ },
34689
+ name,
34690
+ spanAttributes: { type: "tool" /* TOOL */ },
34691
+ spanId,
34692
+ startTime: eventTime2(event)
34693
+ });
34694
+ span.log({ input: action.input, metadata });
34695
+ this.toolsByCallKey.set(key, {
34696
+ metadata,
34697
+ span,
34698
+ turnKey: turnKey2(sessionId, event.data.turnId)
34699
+ });
34700
+ }
34701
+ async startSyntheticTool(event, ctx, result, hookMetadata) {
34702
+ const turn = await this.ensureTurn(event, ctx, hookMetadata);
34703
+ const sessionId = sessionIdFromContext(ctx);
34704
+ if (!turn || !sessionId) {
34705
+ return void 0;
34706
+ }
34707
+ const metadata = toolMetadataFromTurn(turn);
34708
+ const { rowId: eventId, spanId } = await generateEveIds(
34709
+ "tool",
34710
+ sessionId,
34711
+ event.data.turnId,
34712
+ result.callId
34713
+ );
34714
+ const existing = this.toolsByCallKey.get(toolKey3(sessionId, result.callId));
34715
+ if (existing) {
34716
+ return existing;
34717
+ }
34718
+ const span = await this.startEveChildSpan(turn.span, {
34719
+ event: {
34720
+ id: eventId,
34721
+ metadata
34722
+ },
34723
+ name: result.toolName,
34724
+ spanAttributes: { type: "tool" /* TOOL */ },
34725
+ spanId,
34726
+ startTime: eventTime2(event)
34727
+ });
34728
+ span.log({ metadata });
34729
+ const state = {
34730
+ metadata,
34731
+ span,
34732
+ turnKey: turnKey2(sessionId, event.data.turnId)
34733
+ };
34734
+ this.toolsByCallKey.set(toolKey3(sessionId, result.callId), state);
34735
+ return state;
34736
+ }
34737
+ async startSyntheticSubagent(event, ctx, hookMetadata) {
34738
+ const turn = await this.ensureTurn(event, ctx, hookMetadata);
34739
+ const sessionId = sessionIdFromContext(ctx);
34740
+ if (!turn || !sessionId) {
34741
+ return void 0;
34742
+ }
34743
+ const metadata = toolMetadataFromTurn(turn);
34744
+ const { rowId: eventId, spanId } = await generateEveIds(
34745
+ "subagent",
34746
+ sessionId,
34747
+ event.data.callId
34748
+ );
34749
+ const existing = this.toolsByCallKey.get(
34750
+ toolKey3(sessionId, event.data.callId)
34751
+ );
34752
+ if (existing) {
34753
+ return existing;
34754
+ }
34755
+ const span = await this.startEveChildSpan(turn.span, {
34756
+ event: {
34757
+ id: eventId,
34758
+ metadata
34759
+ },
34760
+ name: event.data.subagentName,
34761
+ spanAttributes: { type: "tool" /* TOOL */ },
34762
+ spanId,
34763
+ startTime: eventTime2(event)
34764
+ });
34765
+ span.log({ metadata });
34766
+ const state = {
34767
+ metadata,
34768
+ span,
34769
+ turnKey: turnKey2(sessionId, event.data.turnId)
34770
+ };
34771
+ this.toolsByCallKey.set(toolKey3(sessionId, event.data.callId), state);
34772
+ return state;
34773
+ }
34774
+ async startSyntheticSubagentResult(event, ctx, result, hookMetadata) {
34775
+ const turn = await this.ensureTurn(event, ctx, hookMetadata);
34776
+ const sessionId = sessionIdFromContext(ctx);
34777
+ if (!turn || !sessionId) {
34778
+ return void 0;
34779
+ }
34780
+ const metadata = toolMetadataFromTurn(turn);
34781
+ const { rowId: eventId, spanId } = await generateEveIds(
34782
+ "subagent",
34783
+ sessionId,
34784
+ result.callId
34785
+ );
34786
+ const existing = this.toolsByCallKey.get(toolKey3(sessionId, result.callId));
34787
+ if (existing) {
34788
+ return existing;
34789
+ }
34790
+ const span = await this.startEveChildSpan(turn.span, {
34791
+ event: {
34792
+ id: eventId,
34793
+ metadata
34794
+ },
34795
+ name: result.subagentName,
34796
+ spanAttributes: { type: "tool" /* TOOL */ },
34797
+ spanId,
34798
+ startTime: eventTime2(event)
34799
+ });
34800
+ span.log({ metadata });
34801
+ const state = {
34802
+ metadata,
34803
+ span,
34804
+ turnKey: turnKey2(sessionId, event.data.turnId)
34805
+ };
34806
+ this.toolsByCallKey.set(toolKey3(sessionId, result.callId), state);
34807
+ return state;
34808
+ }
34809
+ async startTurnSpan(sessionId, event, ctx, metadata) {
34810
+ const session = isObject(ctx) ? ctx["session"] : void 0;
34811
+ const parent = isObject(session) ? session["parent"] : void 0;
34812
+ const parentTurn = isObject(parent) ? parent["turn"] : void 0;
34813
+ const parentLineage = isObject(parent) && typeof parent["callId"] === "string" && typeof parent["sessionId"] === "string" && isObject(parentTurn) && typeof parentTurn["id"] === "string" ? {
34814
+ callId: parent["callId"],
34815
+ sessionId: parent["sessionId"],
34816
+ turnId: parentTurn["id"]
34817
+ } : void 0;
34818
+ const [{ rowId: eventId, spanId }, rootSpanId, parentSpanId] = await Promise.all([
34819
+ generateEveIds("turn", sessionId, event.data.turnId),
34820
+ deterministicEveId(
34821
+ "eve:root",
34822
+ parentLineage?.sessionId ?? sessionId,
34823
+ parentLineage?.turnId ?? event.data.turnId
34824
+ ),
34825
+ parentLineage ? deterministicEveId(
34826
+ "eve:subagent",
34827
+ parentLineage.sessionId,
34828
+ parentLineage.callId
34829
+ ) : Promise.resolve(void 0)
34830
+ ]);
34831
+ return await this.startEveSpan({
34832
+ event: {
34833
+ id: eventId,
34834
+ metadata
34835
+ },
34836
+ name: "eve.turn",
34837
+ parentSpanIds: parentSpanId ? { rootSpanId, spanId: parentSpanId } : { parentSpanIds: [], rootSpanId },
34838
+ spanAttributes: { type: "task" /* TASK */ },
34839
+ spanId,
34840
+ startTime: eventTime2(event)
34841
+ });
34842
+ }
34843
+ turnForEvent(event, ctx) {
34844
+ const sessionId = sessionIdFromContext(ctx);
34845
+ return sessionId ? this.turnsByKey.get(turnKey2(sessionId, event.data.turnId)) : void 0;
34846
+ }
34847
+ stepForEvent(event, ctx) {
34848
+ return this.turnForEvent(event, ctx)?.stepsByIndex.get(
34849
+ event.data.stepIndex
34850
+ );
34851
+ }
34852
+ finalizeTurn(turn, args) {
34853
+ const { endTime } = args;
34854
+ for (const step of turn.stepsByIndex.values()) {
34855
+ step.span.log({
34856
+ ...step.input !== void 0 ? { input: step.input } : {},
34857
+ metadata: step.metadata,
34858
+ metrics: step.metrics,
34859
+ output: step.output
34860
+ });
34861
+ step.span.end(endTime === void 0 ? void 0 : { endTime });
34862
+ }
34863
+ turn.stepsByIndex.clear();
34864
+ for (const tool of this.toolsByCallKey.values()) {
34865
+ if (tool.turnKey !== turn.key) {
34866
+ continue;
34867
+ }
34868
+ if (tool.endedByTurn) {
34869
+ continue;
34870
+ }
34871
+ tool.span.log({ metadata: tool.metadata });
34872
+ tool.span.end(endTime === void 0 ? void 0 : { endTime });
34873
+ tool.endedByTurn = true;
34874
+ }
34875
+ if (args.error) {
34876
+ turn.span.log({ error: args.error });
34877
+ } else {
34878
+ turn.span.log({
34879
+ metadata: turn.metadata,
34880
+ metrics: turn.metrics,
34881
+ output: turn.output
34882
+ });
34883
+ }
34884
+ turn.span.end(endTime === void 0 ? void 0 : { endTime });
34885
+ this.turnsByKey.delete(turn.key);
34886
+ this.state.update((current) => {
34887
+ const normalized = normalizeEveTraceState(current);
34888
+ return {
34889
+ ...normalized,
34890
+ stepStarts: normalized.stepStarts.filter(
34891
+ (entry) => entry.turnId !== turn.turnId
34892
+ )
34893
+ };
34894
+ });
34895
+ }
34896
+ cleanupSession(sessionId) {
34897
+ const keyPrefix = `${sessionId}:`;
34898
+ for (const key of this.turnsByKey.keys()) {
34899
+ if (key.startsWith(keyPrefix)) {
34900
+ this.turnsByKey.delete(key);
34901
+ }
34902
+ }
34903
+ for (const key of this.toolsByCallKey.keys()) {
34904
+ if (key.startsWith(keyPrefix)) {
34905
+ this.toolsByCallKey.delete(key);
34906
+ }
34907
+ }
34908
+ for (const key of this.completedToolKeys.keys()) {
34909
+ if (key.startsWith(keyPrefix)) {
34910
+ this.completedToolKeys.delete(key);
34911
+ }
34912
+ }
34913
+ this.state.update(() => emptyEveTraceState());
34914
+ }
34915
+ async flushInstrumentation() {
34916
+ try {
34917
+ await flush();
34918
+ return true;
34919
+ } catch (error) {
34920
+ debugLogger.warn("Error in Eve flush instrumentation:", error);
34921
+ return false;
34922
+ }
34923
+ }
34924
+ };
34925
+ function emptyEveTraceState() {
34926
+ return {
34927
+ llmInputs: [],
34928
+ metadata: {},
34929
+ spanReferences: [],
34930
+ stepStarts: []
34931
+ };
34932
+ }
34933
+ function normalizeEveTraceState(state) {
34934
+ if (!isObject(state)) {
34935
+ return emptyEveTraceState();
34936
+ }
34937
+ const metadata = isObject(state["metadata"]) ? state["metadata"] : {};
34938
+ const spanReferences = Array.isArray(state["spanReferences"]) ? state["spanReferences"].flatMap((entry) => {
34939
+ if (!isObject(entry)) {
34940
+ return [];
34941
+ }
34942
+ const exported = entry["exported"];
34943
+ const endTime = entry["endTime"];
34944
+ const rootSpanId = entry["rootSpanId"];
34945
+ const rowId = entry["rowId"];
34946
+ const spanId = entry["spanId"];
34947
+ const startEvent = entry["startEvent"];
34948
+ const startEventCreated = isObject(startEvent) ? startEvent["created"] : void 0;
34949
+ const startEventMetrics = isObject(startEvent) ? startEvent["metrics"] : void 0;
34950
+ const startEventSpanAttributes = isObject(startEvent) ? startEvent["span_attributes"] : void 0;
34951
+ const startEventSpanParents = isObject(startEvent) ? startEvent["span_parents"] : void 0;
34952
+ const normalizedStartEvent = typeof startEventCreated === "string" && isObject(startEventMetrics) && typeof startEventMetrics["start"] === "number" && Number.isFinite(startEventMetrics["start"]) && isObject(startEventSpanAttributes) && Array.isArray(startEventSpanParents) && startEventSpanParents.every(
34953
+ (parent) => typeof parent === "string"
34954
+ ) ? {
34955
+ created: startEventCreated,
34956
+ metrics: { start: startEventMetrics["start"] },
34957
+ span_attributes: { ...startEventSpanAttributes },
34958
+ span_parents: [...startEventSpanParents]
34959
+ } : void 0;
34960
+ return typeof exported === "string" && typeof rootSpanId === "string" && typeof rowId === "string" && typeof spanId === "string" ? [
34961
+ {
34962
+ ...typeof endTime === "number" && Number.isFinite(endTime) ? { endTime } : {},
34963
+ exported,
34964
+ rootSpanId,
34965
+ rowId,
34966
+ spanId,
34967
+ ...normalizedStartEvent ? { startEvent: normalizedStartEvent } : {}
34968
+ }
34969
+ ] : [];
34970
+ }).slice(-MAX_STORED_SPAN_REFERENCES) : [];
34971
+ const llmInputs = Array.isArray(state["llmInputs"]) ? state["llmInputs"].flatMap((entry) => {
34972
+ if (!isObject(entry)) {
34973
+ return [];
34974
+ }
34975
+ const key = entry["key"];
34976
+ const input = entry["input"];
34977
+ return typeof key === "string" && isCapturedModelInput(input) ? [{ input, key }] : [];
34978
+ }).slice(-MAX_STORED_LLM_INPUTS) : [];
34979
+ const stepStarts = Array.isArray(state["stepStarts"]) ? state["stepStarts"].flatMap((entry) => {
34980
+ if (!isObject(entry)) {
34981
+ return [];
34982
+ }
34983
+ const ordinal = entry["ordinal"];
34984
+ const open = entry["open"];
34985
+ const stepIndex = entry["stepIndex"];
34986
+ const turnId = entry["turnId"];
34987
+ return typeof ordinal === "number" && Number.isInteger(ordinal) && ordinal >= 0 && typeof open === "boolean" && typeof stepIndex === "number" && Number.isInteger(stepIndex) && typeof turnId === "string" ? [{ open, ordinal, stepIndex, turnId }] : [];
34988
+ }).slice(-MAX_STORED_STEP_STARTS) : [];
34989
+ return { llmInputs, metadata: { ...metadata }, spanReferences, stepStarts };
34990
+ }
34991
+ function readEveTraceState(state) {
34992
+ try {
34993
+ return normalizeEveTraceState(state.get());
34994
+ } catch {
34995
+ return emptyEveTraceState();
34996
+ }
34997
+ }
34998
+ function captureEveModelInput(state, input) {
34999
+ if (!isObject(input)) {
35000
+ return;
35001
+ }
35002
+ const session = input["session"];
35003
+ const turn = input["turn"];
35004
+ const step = input["step"];
35005
+ if (!isObject(session) || !isObject(turn) || !isObject(step)) {
35006
+ return;
35007
+ }
35008
+ const sessionId = session["id"];
35009
+ const turnId = turn["id"];
35010
+ const stepIndex = step["index"];
35011
+ if (typeof sessionId !== "string" || typeof turnId !== "string" || typeof stepIndex !== "number" || !Number.isInteger(stepIndex)) {
35012
+ return;
35013
+ }
35014
+ const captured = capturedModelInput(input["modelInput"]);
35015
+ if (!captured) {
35016
+ return;
35017
+ }
35018
+ const key = llmInputKey(sessionId, turnId, stepIndex);
35019
+ state.update((current) => {
35020
+ const normalized = normalizeEveTraceState(current);
35021
+ const llmInputs = [...normalized.llmInputs, { input: captured, key }];
35022
+ return {
35023
+ ...normalized,
35024
+ llmInputs: llmInputs.slice(-MAX_STORED_LLM_INPUTS)
35025
+ };
35026
+ });
35027
+ }
35028
+ function consumeCapturedEveModelInput(state, sessionId, turnId, stepIndex) {
35029
+ try {
35030
+ const key = llmInputKey(sessionId, turnId, stepIndex);
35031
+ let input;
35032
+ state.update((current) => {
35033
+ const normalized = normalizeEveTraceState(current);
35034
+ const index = normalized.llmInputs.findIndex(
35035
+ (candidate) => candidate.key === key
35036
+ );
35037
+ if (index < 0) {
35038
+ return normalized;
35039
+ }
35040
+ input = normalized.llmInputs[index]?.input;
35041
+ return {
35042
+ ...normalized,
35043
+ llmInputs: normalized.llmInputs.filter(
35044
+ (_, candidateIndex) => candidateIndex !== index
35045
+ )
35046
+ };
35047
+ });
35048
+ return input;
35049
+ } catch (error) {
35050
+ debugLogger.warn("Error in Eve LLM input consumption:", error);
35051
+ return void 0;
35052
+ }
35053
+ }
35054
+ function capturedModelInput(modelInput) {
35055
+ if (!isObject(modelInput)) {
35056
+ return void 0;
35057
+ }
35058
+ const messages = modelInput["messages"];
35059
+ if (!Array.isArray(messages)) {
35060
+ return void 0;
35061
+ }
35062
+ const instructions = modelInput["instructions"];
35063
+ const value = [
35064
+ ...instructions !== void 0 ? [{ content: instructions, role: "system" }] : [],
35065
+ ...messages
35066
+ ];
35067
+ try {
35068
+ const cloned = JSON.parse(JSON.stringify(value));
35069
+ if (!Array.isArray(cloned)) {
35070
+ return void 0;
35071
+ }
35072
+ return cloned;
35073
+ } catch {
35074
+ return void 0;
35075
+ }
35076
+ }
35077
+ function isCapturedModelInput(input) {
35078
+ return Array.isArray(input);
35079
+ }
35080
+ function llmInputKey(sessionId, turnId, stepIndex) {
35081
+ return `${sessionId}\0${turnId}\0${stepIndex}`;
35082
+ }
35083
+ function modelMetadataFromRuntime(runtime) {
35084
+ if (!isObject(runtime)) {
35085
+ return {};
35086
+ }
35087
+ const modelId = runtime["modelId"];
35088
+ return typeof modelId === "string" && !modelId.trim().startsWith("dynamic:") ? modelMetadataFromModelId(modelId) : {};
35089
+ }
35090
+ function modelMetadataFromModelId(modelId) {
35091
+ const normalized = modelId.trim();
35092
+ if (!normalized) {
35093
+ return {};
35094
+ }
35095
+ const slashIndex = normalized.indexOf("/");
35096
+ if (slashIndex > 0 && slashIndex < normalized.length - 1) {
35097
+ return {
35098
+ model: normalized.slice(slashIndex + 1),
35099
+ provider: normalized.slice(0, slashIndex)
35100
+ };
35101
+ }
35102
+ return {
35103
+ model: normalized
35104
+ };
35105
+ }
35106
+ function sessionIdFromContext(ctx) {
35107
+ if (!isObject(ctx)) {
35108
+ return void 0;
35109
+ }
35110
+ const session = ctx["session"];
35111
+ if (!isObject(session)) {
35112
+ return void 0;
35113
+ }
35114
+ const id = session["id"];
35115
+ return typeof id === "string" ? id : void 0;
35116
+ }
35117
+ function toolMetadataFromTurn(turn) {
35118
+ const { model: _model, provider: _provider, ...metadata } = turn.metadata;
35119
+ return metadata;
35120
+ }
35121
+ function isToolCallAction(action) {
35122
+ return isObject(action) && action["kind"] === "tool-call" && typeof action["callId"] === "string" && typeof action["toolName"] === "string" && isObject(action["input"]);
35123
+ }
35124
+ function isLocalSubagentCallAction(action) {
35125
+ return isObject(action) && action["kind"] === "subagent-call" && typeof action["callId"] === "string" && isObject(action["input"]);
35126
+ }
35127
+ function isTraceableActionRequest(action) {
35128
+ return isToolCallAction(action) || isLocalSubagentCallAction(action);
35129
+ }
35130
+ function isToolResult(result) {
35131
+ return isObject(result) && result["kind"] === "tool-result" && typeof result["callId"] === "string" && typeof result["toolName"] === "string";
35132
+ }
35133
+ function isSubagentResult(result) {
35134
+ return isObject(result) && result["kind"] === "subagent-result" && typeof result["callId"] === "string" && typeof result["subagentName"] === "string";
35135
+ }
35136
+ function normalizedFinishReason(finishReason) {
35137
+ switch (finishReason) {
35138
+ case "content-filter":
35139
+ return "content_filter";
35140
+ case "tool-calls":
35141
+ return "tool_calls";
35142
+ default:
35143
+ return finishReason;
35144
+ }
35145
+ }
35146
+ function errorFromMessage(message, code, details) {
35147
+ const error = new Error(`${code}: ${message}`);
35148
+ if (details !== void 0) {
35149
+ error.cause = details;
35150
+ }
35151
+ return error;
35152
+ }
35153
+ function actionResultError(error, output) {
35154
+ if (error) {
35155
+ return errorFromMessage(error.message, error.code);
35156
+ }
35157
+ const result = new Error("Eve action failed");
35158
+ if (output !== void 0) {
35159
+ result.cause = output;
35160
+ }
35161
+ return result;
35162
+ }
35163
+ function eventTime2(event) {
35164
+ if (!event.meta?.at) {
35165
+ return void 0;
35166
+ }
35167
+ const timestamp = Date.parse(event.meta.at);
35168
+ return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
35169
+ }
35170
+ function turnKey2(sessionId, turnId) {
35171
+ return `${sessionId}:${turnId}`;
35172
+ }
35173
+ function toolKey3(sessionId, callId) {
35174
+ return `${sessionId}:${callId}`;
35175
+ }
35176
+ async function generateEveIds(kind, ...parts) {
35177
+ const [rowId, spanId] = await Promise.all([
35178
+ deterministicEveId(`eve:row:${kind}`, ...parts),
35179
+ deterministicEveId(`eve:${kind}`, ...parts)
35180
+ ]);
35181
+ return { rowId, spanId };
35182
+ }
35183
+ async function deterministicEveId(...parts) {
35184
+ const data = new TextEncoder().encode(
35185
+ parts.map((part) => `${part.length}:${part}`).join("\0")
35186
+ );
35187
+ const digest = await globalThis.crypto.subtle.digest("SHA-256", data);
35188
+ const bytes = Array.from(new Uint8Array(digest, 0, 16));
35189
+ const hex = bytes.map((byte) => byte.toString(16).padStart(2, "0")).join("");
35190
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
35191
+ }
35192
+
33048
35193
  // src/typed-instrumentation-helpers.ts
33049
35194
  var TypedApplyProxy = Proxy;
33050
35195
 
@@ -33207,6 +35352,15 @@ function modelMetrics(attributes) {
33207
35352
  }
33208
35353
  return Object.keys(out).length > 0 ? out : void 0;
33209
35354
  }
35355
+ function timeToFirstTokenSeconds(attributes, spanStartSeconds) {
35356
+ if (!isObject(attributes)) return void 0;
35357
+ if (spanStartSeconds === void 0) return void 0;
35358
+ const raw = attributes.completionStartTime;
35359
+ const completionStart = raw instanceof Date || typeof raw === "string" || typeof raw === "number" ? epochSeconds(raw) : void 0;
35360
+ if (completionStart === void 0) return void 0;
35361
+ const ttft = completionStart - spanStartSeconds;
35362
+ return Number.isFinite(ttft) && ttft >= 0 ? ttft : void 0;
35363
+ }
33210
35364
  function buildMetadata(exported) {
33211
35365
  const out = {};
33212
35366
  if (exported.entityId !== void 0) out.entity_id = exported.entityId;
@@ -33276,7 +35430,13 @@ var BraintrustObservabilityExporter = class {
33276
35430
  const args = {
33277
35431
  name: exported.name,
33278
35432
  spanAttributes: { type: spanTypeFor(exported.type) },
33279
- startTime: epochSeconds(exported.startTime)
35433
+ startTime: epochSeconds(exported.startTime),
35434
+ // Use the Mastra span id as the Braintrust row id so that
35435
+ // `logFeedback({ id: <mastra span id> })` (and Mastra's score events)
35436
+ // attach to the right row. Without this, `SpanImpl` auto-generates a
35437
+ // row id (`this._id = eventId ?? idGenerator.getSpanId()`) that no
35438
+ // external caller could know.
35439
+ event: { id: exported.id }
33280
35440
  };
33281
35441
  const parentRecord = exported.parentSpanId ? this.spans.get(exported.parentSpanId) : void 0;
33282
35442
  if (!this.capturedParent) {
@@ -33325,8 +35485,15 @@ var BraintrustObservabilityExporter = class {
33325
35485
  event.metadata = metadata;
33326
35486
  }
33327
35487
  const metrics = modelMetrics(exported.attributes);
33328
- if (metrics) {
33329
- event.metrics = metrics;
35488
+ const ttft = timeToFirstTokenSeconds(
35489
+ exported.attributes,
35490
+ epochSeconds(exported.startTime)
35491
+ );
35492
+ if (metrics || ttft !== void 0) {
35493
+ event.metrics = {
35494
+ ...metrics ?? {},
35495
+ ...ttft !== void 0 ? { time_to_first_token: ttft } : {}
35496
+ };
33330
35497
  }
33331
35498
  if (Object.keys(event).length > 0) {
33332
35499
  record.span.log(event);
@@ -34205,17 +36372,17 @@ function wrapGenkit(genkit) {
34205
36372
  console.warn("Unsupported Genkit object. Not wrapping.");
34206
36373
  return genkit;
34207
36374
  }
34208
- function isRecord2(value) {
36375
+ function isRecord3(value) {
34209
36376
  return typeof value === "object" && value !== null;
34210
36377
  }
34211
36378
  function isPropertyBag(value) {
34212
- return isRecord2(value) || typeof value === "function";
36379
+ return isRecord3(value) || typeof value === "function";
34213
36380
  }
34214
36381
  function hasFunction(value, methodName) {
34215
36382
  return isPropertyBag(value) && methodName in value && typeof value[methodName] === "function";
34216
36383
  }
34217
36384
  function isGenkitInstance(value) {
34218
- return isRecord2(value) && (hasFunction(value, "generate") || hasFunction(value, "generateStream") || hasFunction(value, "defineFlow") || hasFunction(value, "defineTool"));
36385
+ return isRecord3(value) && (hasFunction(value, "generate") || hasFunction(value, "generateStream") || hasFunction(value, "defineFlow") || hasFunction(value, "defineTool"));
34219
36386
  }
34220
36387
  function isGenkitModule(value) {
34221
36388
  return hasFunction(value, "genkit");
@@ -34269,7 +36436,7 @@ function patchGenkitRegistry(instance) {
34269
36436
  patchGenkitRegistryConstructor(registry2);
34270
36437
  }
34271
36438
  function patchGenkitRegistryLookup(registry2) {
34272
- if (!isRecord2(registry2) || hasRegistryPatchedFlag(registry2) || !hasFunction(registry2, "lookupAction")) {
36439
+ if (!isRecord3(registry2) || hasRegistryPatchedFlag(registry2) || !hasFunction(registry2, "lookupAction")) {
34273
36440
  return;
34274
36441
  }
34275
36442
  const originalLookupAction = registry2.lookupAction;
@@ -34295,7 +36462,7 @@ function patchGenkitRegistryLookup(registry2) {
34295
36462
  }
34296
36463
  }
34297
36464
  function patchGenkitRegistryConstructor(registry2) {
34298
- if (!isRecord2(registry2)) {
36465
+ if (!isRecord3(registry2)) {
34299
36466
  return;
34300
36467
  }
34301
36468
  const constructor = registry2.constructor;
@@ -34311,7 +36478,7 @@ function patchGenkitRegistryConstructor(registry2) {
34311
36478
  configurable: true,
34312
36479
  value: (...args) => {
34313
36480
  const childRegistry = originalWithParent.apply(constructor, args);
34314
- if (args.some((arg) => isRecord2(arg) && hasRegistryPatchedFlag(arg))) {
36481
+ if (args.some((arg) => isRecord3(arg) && hasRegistryPatchedFlag(arg))) {
34315
36482
  patchGenkitRegistryLookup(childRegistry);
34316
36483
  patchGenkitRegistryConstructor(childRegistry);
34317
36484
  }
@@ -34410,7 +36577,7 @@ function hasRegistryConstructorPatchedFlag(value) {
34410
36577
  );
34411
36578
  }
34412
36579
  function isPromiseLike2(value) {
34413
- return isRecord2(value) && "then" in value && typeof value.then === "function";
36580
+ return isRecord3(value) && "then" in value && typeof value.then === "function";
34414
36581
  }
34415
36582
 
34416
36583
  // src/wrappers/huggingface.ts
@@ -34773,14 +36940,14 @@ function wrapMistral(mistral) {
34773
36940
  console.warn("Unsupported Mistral library. Not wrapping.");
34774
36941
  return mistral;
34775
36942
  }
34776
- function isRecord3(value) {
36943
+ function isRecord4(value) {
34777
36944
  return typeof value === "object" && value !== null;
34778
36945
  }
34779
36946
  function hasFunction3(value, methodName) {
34780
- return isRecord3(value) && methodName in value && typeof value[methodName] === "function";
36947
+ return isRecord4(value) && methodName in value && typeof value[methodName] === "function";
34781
36948
  }
34782
36949
  function isSupportedMistralClient(value) {
34783
- if (!isRecord3(value)) {
36950
+ if (!isRecord4(value)) {
34784
36951
  return false;
34785
36952
  }
34786
36953
  return value.chat !== void 0 && hasChat(value.chat) || value.embeddings !== void 0 && hasEmbeddings(value.embeddings) || value.fim !== void 0 && hasFim(value.fim) || value.agents !== void 0 && hasAgents(value.agents) || value.classifiers !== void 0 && hasClassifiers(value.classifiers);
@@ -34964,14 +37131,14 @@ function wrapCohere(cohere) {
34964
37131
  return cohere;
34965
37132
  }
34966
37133
  var cohereProxyCache = /* @__PURE__ */ new WeakMap();
34967
- function isRecord4(value) {
37134
+ function isRecord5(value) {
34968
37135
  return typeof value === "object" && value !== null;
34969
37136
  }
34970
37137
  function hasFunction4(value, methodName) {
34971
- return isRecord4(value) && methodName in value && typeof value[methodName] === "function";
37138
+ return isRecord5(value) && methodName in value && typeof value[methodName] === "function";
34972
37139
  }
34973
37140
  function isSupportedCohereClient(value) {
34974
- if (!isRecord4(value)) {
37141
+ if (!isRecord5(value)) {
34975
37142
  return false;
34976
37143
  }
34977
37144
  return hasFunction4(value, "chat") || hasFunction4(value, "chatStream") || hasFunction4(value, "embed") || hasFunction4(value, "rerank");
@@ -35031,20 +37198,20 @@ function wrapGroq(groq) {
35031
37198
  console.warn("Unsupported Groq library. Not wrapping.");
35032
37199
  return groq;
35033
37200
  }
35034
- function isRecord5(value) {
37201
+ function isRecord6(value) {
35035
37202
  return typeof value === "object" && value !== null;
35036
37203
  }
35037
37204
  function hasFunction5(value, methodName) {
35038
- return isRecord5(value) && methodName in value && typeof value[methodName] === "function";
37205
+ return isRecord6(value) && methodName in value && typeof value[methodName] === "function";
35039
37206
  }
35040
37207
  function hasChat2(value) {
35041
- return isRecord5(value) && isRecord5(value.completions) && hasFunction5(value.completions, "create");
37208
+ return isRecord6(value) && isRecord6(value.completions) && hasFunction5(value.completions, "create");
35042
37209
  }
35043
37210
  function hasEmbeddings2(value) {
35044
37211
  return hasFunction5(value, "create");
35045
37212
  }
35046
37213
  function isSupportedGroqClient(value) {
35047
- return isRecord5(value) && (value.chat !== void 0 && hasChat2(value.chat) || value.embeddings !== void 0 && hasEmbeddings2(value.embeddings));
37214
+ return isRecord6(value) && (value.chat !== void 0 && hasChat2(value.chat) || value.embeddings !== void 0 && hasEmbeddings2(value.embeddings));
35048
37215
  }
35049
37216
  function groqProxy(groq) {
35050
37217
  const privateMethodWorkaroundCache = /* @__PURE__ */ new WeakMap();
@@ -35127,11 +37294,11 @@ var BEDROCK_RUNTIME_OPERATION_METHODS = /* @__PURE__ */ new Set([
35127
37294
  "invokeModelWithBidirectionalStream",
35128
37295
  "invokeModelWithResponseStream"
35129
37296
  ]);
35130
- function isRecord6(value) {
37297
+ function isRecord7(value) {
35131
37298
  return typeof value === "object" && value !== null;
35132
37299
  }
35133
37300
  function isSupportedBedrockRuntimeClient(value) {
35134
- return isRecord6(value) && typeof value.send === "function";
37301
+ return isRecord7(value) && typeof value.send === "function";
35135
37302
  }
35136
37303
  function bedrockRuntimeProxy(client) {
35137
37304
  const cached = bedrockRuntimeProxyCache.get(client);
@@ -35250,6 +37417,271 @@ function wrappedResumeSession(client) {
35250
37417
  );
35251
37418
  }
35252
37419
 
37420
+ // src/wrappers/langsmith.ts
37421
+ var WRAPPED_CLIENT_CLASS = /* @__PURE__ */ Symbol.for(
37422
+ "braintrust.langsmith.wrapped-client-class"
37423
+ );
37424
+ var WRAPPED_CLIENT_INSTANCE = /* @__PURE__ */ Symbol.for(
37425
+ "braintrust.langsmith.wrapped-client-instance"
37426
+ );
37427
+ var WRAPPED_CLIENT_NAMESPACE = /* @__PURE__ */ Symbol.for(
37428
+ "braintrust.langsmith.wrapped-client-namespace"
37429
+ );
37430
+ var WRAPPED_RUN_TREE_CLASS = /* @__PURE__ */ Symbol.for(
37431
+ "braintrust.langsmith.wrapped-run-tree-class"
37432
+ );
37433
+ var WRAPPED_RUN_TREE_INSTANCE = /* @__PURE__ */ Symbol.for(
37434
+ "braintrust.langsmith.wrapped-run-tree-instance"
37435
+ );
37436
+ var WRAPPED_RUN_TREES_NAMESPACE = /* @__PURE__ */ Symbol.for(
37437
+ "braintrust.langsmith.wrapped-run-trees-namespace"
37438
+ );
37439
+ var WRAPPED_TRACEABLE = /* @__PURE__ */ Symbol.for("braintrust.langsmith.wrapped-traceable");
37440
+ var WRAPPED_TRACEABLE_NAMESPACE = /* @__PURE__ */ Symbol.for(
37441
+ "braintrust.langsmith.wrapped-traceable-namespace"
37442
+ );
37443
+ function wrapLangSmithTraceable(namespace) {
37444
+ return wrapNamespaceExport(
37445
+ namespace,
37446
+ "traceable",
37447
+ WRAPPED_TRACEABLE_NAMESPACE,
37448
+ (value) => wrapTraceable(value)
37449
+ );
37450
+ }
37451
+ function wrapLangSmithRunTrees(namespace) {
37452
+ return wrapNamespaceExport(
37453
+ namespace,
37454
+ "RunTree",
37455
+ WRAPPED_RUN_TREES_NAMESPACE,
37456
+ (value) => wrapRunTreeClass(value)
37457
+ );
37458
+ }
37459
+ function wrapLangSmithClient(namespace) {
37460
+ return wrapNamespaceExport(
37461
+ namespace,
37462
+ "Client",
37463
+ WRAPPED_CLIENT_NAMESPACE,
37464
+ (value) => wrapClientClass(value)
37465
+ );
37466
+ }
37467
+ function wrapNamespaceExport(namespace, exportName, marker, wrap2) {
37468
+ if (!namespace || typeof namespace !== "object") {
37469
+ return namespace;
37470
+ }
37471
+ const candidate = namespace;
37472
+ if (candidate[marker] === true) {
37473
+ return namespace;
37474
+ }
37475
+ if (typeof candidate[exportName] !== "function") {
37476
+ console.warn(
37477
+ `Unsupported LangSmith ${exportName} namespace. Not wrapping.`
37478
+ );
37479
+ return namespace;
37480
+ }
37481
+ const target = isModuleNamespace5(namespace) ? Object.setPrototypeOf({}, namespace) : candidate;
37482
+ const moduleNamespace = target !== candidate;
37483
+ let wrappedExport;
37484
+ return new Proxy(target, {
37485
+ get(target2, prop, receiver) {
37486
+ if (prop === marker) {
37487
+ return true;
37488
+ }
37489
+ const value = Reflect.get(target2, prop, receiver);
37490
+ if (prop !== exportName || typeof value !== "function") {
37491
+ return value;
37492
+ }
37493
+ wrappedExport ??= wrap2(value);
37494
+ return wrappedExport;
37495
+ },
37496
+ getOwnPropertyDescriptor(target2, prop) {
37497
+ const descriptor = Reflect.getOwnPropertyDescriptor(target2, prop);
37498
+ if (descriptor || !moduleNamespace) {
37499
+ return descriptor;
37500
+ }
37501
+ const namespaceDescriptor = Reflect.getOwnPropertyDescriptor(
37502
+ candidate,
37503
+ prop
37504
+ );
37505
+ return namespaceDescriptor ? { ...namespaceDescriptor, configurable: true } : void 0;
37506
+ },
37507
+ has(target2, prop) {
37508
+ return Reflect.has(target2, prop) || moduleNamespace && prop in candidate;
37509
+ },
37510
+ ownKeys(target2) {
37511
+ return moduleNamespace ? Reflect.ownKeys(candidate) : Reflect.ownKeys(target2);
37512
+ }
37513
+ });
37514
+ }
37515
+ function isModuleNamespace5(value) {
37516
+ if (!value || typeof value !== "object") {
37517
+ return false;
37518
+ }
37519
+ if (value.constructor?.name === "Module") {
37520
+ return true;
37521
+ }
37522
+ const firstKey = Object.keys(value)[0];
37523
+ if (!firstKey) {
37524
+ return false;
37525
+ }
37526
+ const descriptor = Object.getOwnPropertyDescriptor(value, firstKey);
37527
+ return descriptor ? !descriptor.configurable && !descriptor.writable : false;
37528
+ }
37529
+ function wrapTraceable(traceable2) {
37530
+ if (traceable2[WRAPPED_TRACEABLE]) {
37531
+ return traceable2;
37532
+ }
37533
+ return new Proxy(traceable2, {
37534
+ get(target, prop, receiver) {
37535
+ if (prop === WRAPPED_TRACEABLE) {
37536
+ return true;
37537
+ }
37538
+ return Reflect.get(target, prop, receiver);
37539
+ },
37540
+ apply(target, thisArg, argArray) {
37541
+ const [fn, rawConfig] = argArray;
37542
+ const config = rawConfig && typeof rawConfig === "object" ? rawConfig : void 0;
37543
+ const originalOnEnd = config?.on_end;
37544
+ const wrappedConfig = {
37545
+ ...config,
37546
+ on_end(runTree) {
37547
+ publishRunUpdate(runTree);
37548
+ if (originalOnEnd) {
37549
+ Reflect.apply(originalOnEnd, config, [runTree]);
37550
+ }
37551
+ }
37552
+ };
37553
+ return Reflect.apply(target, thisArg, [fn, wrappedConfig]);
37554
+ }
37555
+ });
37556
+ }
37557
+ function wrapRunTreeClass(RunTree) {
37558
+ if (RunTree[WRAPPED_RUN_TREE_CLASS]) {
37559
+ return RunTree;
37560
+ }
37561
+ return new Proxy(RunTree, {
37562
+ get(target, prop, receiver) {
37563
+ if (prop === WRAPPED_RUN_TREE_CLASS) {
37564
+ return true;
37565
+ }
37566
+ const value = Reflect.get(target, prop, receiver);
37567
+ return typeof value === "function" ? value.bind(target) : value;
37568
+ },
37569
+ construct(target, args, newTarget) {
37570
+ return wrapRunTreeInstance(Reflect.construct(target, args, newTarget));
37571
+ }
37572
+ });
37573
+ }
37574
+ function wrapRunTreeInstance(runTree) {
37575
+ if (runTree[WRAPPED_RUN_TREE_INSTANCE]) {
37576
+ return runTree;
37577
+ }
37578
+ return new Proxy(runTree, {
37579
+ get(target, prop, receiver) {
37580
+ if (prop === WRAPPED_RUN_TREE_INSTANCE) {
37581
+ return true;
37582
+ }
37583
+ const value = Reflect.get(target, prop, receiver);
37584
+ if (typeof value !== "function") {
37585
+ return value;
37586
+ }
37587
+ let wrapped;
37588
+ if (prop === "createChild") {
37589
+ wrapped = (...args) => wrapRunTreeInstance(Reflect.apply(value, target, args));
37590
+ } else if (prop === "postRun") {
37591
+ const method = value;
37592
+ wrapped = (...args) => langSmithChannels.createRun.tracePromise(
37593
+ () => Reflect.apply(method, target, args),
37594
+ { arguments: [target] }
37595
+ );
37596
+ } else if (prop === "patchRun") {
37597
+ const method = value;
37598
+ wrapped = (...args) => langSmithChannels.updateRun.tracePromise(
37599
+ () => Reflect.apply(method, target, args),
37600
+ {
37601
+ arguments: [
37602
+ typeof target.id === "string" ? target.id : "",
37603
+ target
37604
+ ]
37605
+ }
37606
+ );
37607
+ } else {
37608
+ wrapped = value.bind(target);
37609
+ }
37610
+ return wrapped;
37611
+ }
37612
+ });
37613
+ }
37614
+ function wrapClientClass(Client) {
37615
+ if (Client[WRAPPED_CLIENT_CLASS]) {
37616
+ return Client;
37617
+ }
37618
+ return new Proxy(Client, {
37619
+ get(target, prop, receiver) {
37620
+ if (prop === WRAPPED_CLIENT_CLASS) {
37621
+ return true;
37622
+ }
37623
+ const value = Reflect.get(target, prop, receiver);
37624
+ return typeof value === "function" ? value.bind(target) : value;
37625
+ },
37626
+ construct(target, args, newTarget) {
37627
+ return wrapClientInstance(Reflect.construct(target, args, newTarget));
37628
+ }
37629
+ });
37630
+ }
37631
+ function wrapClientInstance(client) {
37632
+ if (client[WRAPPED_CLIENT_INSTANCE]) {
37633
+ return client;
37634
+ }
37635
+ return new Proxy(client, {
37636
+ get(target, prop, receiver) {
37637
+ if (prop === WRAPPED_CLIENT_INSTANCE) {
37638
+ return true;
37639
+ }
37640
+ const value = Reflect.get(target, prop, receiver);
37641
+ if (typeof value !== "function") {
37642
+ return value;
37643
+ }
37644
+ let wrapped;
37645
+ if (prop === "createRun") {
37646
+ const method = value;
37647
+ wrapped = (...args) => langSmithChannels.createRun.tracePromise(
37648
+ () => Reflect.apply(method, target, args),
37649
+ { arguments: args }
37650
+ );
37651
+ } else if (prop === "updateRun") {
37652
+ const method = value;
37653
+ wrapped = (...args) => langSmithChannels.updateRun.tracePromise(
37654
+ () => Reflect.apply(method, target, args),
37655
+ { arguments: args }
37656
+ );
37657
+ } else if (prop === "batchIngestRuns") {
37658
+ const method = value;
37659
+ wrapped = (...args) => langSmithChannels.batchIngestRuns.tracePromise(
37660
+ () => Reflect.apply(method, target, args),
37661
+ { arguments: args }
37662
+ );
37663
+ } else {
37664
+ wrapped = value.bind(target);
37665
+ }
37666
+ return wrapped;
37667
+ }
37668
+ });
37669
+ }
37670
+ function publishRunUpdate(runTree) {
37671
+ if (!runTree || typeof runTree.id !== "string" || !runTree.id) {
37672
+ return;
37673
+ }
37674
+ try {
37675
+ void langSmithChannels.updateRun.tracePromise(() => Promise.resolve(void 0), {
37676
+ arguments: [runTree.id, runTree]
37677
+ }).catch((error) => {
37678
+ debugLogger.error("LangSmith traceable instrumentation failed:", error);
37679
+ });
37680
+ } catch (error) {
37681
+ debugLogger.error("LangSmith traceable instrumentation failed:", error);
37682
+ }
37683
+ }
37684
+
35253
37685
  // src/wrappers/vitest/context-manager.ts
35254
37686
  var VitestContextManager = class {
35255
37687
  /**