@sentry/junior 0.7.0 → 0.9.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.
@@ -1,6 +1,3 @@
1
- // src/chat/observability.ts
2
- import * as Sentry2 from "@sentry/nextjs";
3
-
4
1
  // src/chat/logging.ts
5
2
  import { AsyncLocalStorage } from "async_hooks";
6
3
  import * as Sentry from "@sentry/nextjs";
@@ -9,8 +6,7 @@ var SECRETS_RE = [
9
6
  /\b(sk-[A-Za-z0-9_-]{20,})\b/g,
10
7
  /\b(xox[baprs]-[A-Za-z0-9-]{10,})\b/g,
11
8
  /\bBearer\s+([A-Za-z0-9._\-+=]{20,})\b/gi,
12
- /\b[A-Z0-9_]+(?:KEY|TOKEN|SECRET|PASSWORD|PASSWD)\s*[=:]\s*([^\s"']{8,})/gi,
13
- /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]+?-----END [A-Z ]*PRIVATE KEY-----/g
9
+ /\b[A-Z0-9_]+(?:KEY|TOKEN|SECRET|PASSWORD|PASSWD)\s*[=:]\s*([^\s"']{8,})/gi
14
10
  ];
15
11
  var LEGACY_KEY_MAP = {
16
12
  error: "error.message",
@@ -55,21 +51,42 @@ var ANSI = {
55
51
  var CONSOLE_PRIORITY_KEYS = [
56
52
  "app.conversation.id",
57
53
  "app.turn.id",
58
- "app.agent.id",
59
54
  "event.name",
60
55
  "error.message",
61
56
  "messaging.message.id",
57
+ "app.trace_id",
58
+ "app.span_id",
59
+ "app.agent.id",
62
60
  "messaging.message.conversation_id",
63
61
  "messaging.destination.name",
64
- "enduser.id",
65
62
  "app.run.id",
66
- "app.message.kind",
67
- "app.trace_id",
68
- "app.span_id"
63
+ "app.message.kind"
69
64
  ];
70
65
  var CONSOLE_PRIORITY_INDEX = new Map(
71
66
  CONSOLE_PRIORITY_KEYS.map((key, index) => [key, index])
72
67
  );
68
+ var CONSOLE_ALWAYS_HIDDEN_KEYS = /* @__PURE__ */ new Set([
69
+ "app.assistant.username",
70
+ "app.platform",
71
+ "enduser.id",
72
+ "enduser.pseudo_id",
73
+ "http.request.method",
74
+ "messaging.system",
75
+ "url.full",
76
+ "url.path",
77
+ "user_agent.original"
78
+ ]);
79
+ var CONSOLE_DROP_WHEN_COUNTED_KEYS = /* @__PURE__ */ new Set([
80
+ "app.capability.names",
81
+ "app.capability.providers",
82
+ "app.config.keys"
83
+ ]);
84
+ var CONSOLE_PREVIEW_KEYS = /* @__PURE__ */ new Set([
85
+ "gen_ai.input.messages",
86
+ "gen_ai.output.messages",
87
+ "gen_ai.tool.call.arguments",
88
+ "gen_ai.tool.call.result"
89
+ ]);
73
90
  function getSentryEnvironment() {
74
91
  return (process.env.SENTRY_ENVIRONMENT ?? process.env.NEXT_PUBLIC_SENTRY_ENVIRONMENT ?? process.env.VERCEL_ENV ?? process.env.NODE_ENV ?? "").trim().toLowerCase();
75
92
  }
@@ -82,16 +99,73 @@ function shouldEmitConsole(level) {
82
99
  }
83
100
  return getSentryEnvironment() !== "production";
84
101
  }
102
+ function findNextBlankLineBoundary(input, start) {
103
+ const lfBoundary = input.indexOf("\n\n", start);
104
+ const crlfBoundary = input.indexOf("\r\n\r\n", start);
105
+ if (lfBoundary === -1 && crlfBoundary === -1) {
106
+ return null;
107
+ }
108
+ if (lfBoundary === -1) {
109
+ return { start: crlfBoundary, end: crlfBoundary + 4 };
110
+ }
111
+ if (crlfBoundary === -1 || lfBoundary < crlfBoundary) {
112
+ return { start: lfBoundary, end: lfBoundary + 2 };
113
+ }
114
+ return { start: crlfBoundary, end: crlfBoundary + 4 };
115
+ }
116
+ function redactPrivateKeyBlocks(input) {
117
+ const beginPrefix = "-----BEGIN ";
118
+ const footerMarker = "-----";
119
+ let cursor = 0;
120
+ let output = "";
121
+ while (cursor < input.length) {
122
+ const begin = input.indexOf(beginPrefix, cursor);
123
+ if (begin === -1) {
124
+ output += input.slice(cursor);
125
+ break;
126
+ }
127
+ const labelStart = begin + beginPrefix.length;
128
+ const labelEnd = input.indexOf(footerMarker, labelStart);
129
+ if (labelEnd === -1) {
130
+ output += input.slice(cursor);
131
+ break;
132
+ }
133
+ const label = input.slice(labelStart, labelEnd);
134
+ if (!label.endsWith("PRIVATE KEY")) {
135
+ output += input.slice(cursor, labelEnd + footerMarker.length);
136
+ cursor = labelEnd + footerMarker.length;
137
+ continue;
138
+ }
139
+ const header = input.slice(begin, labelEnd + footerMarker.length);
140
+ const footer = `-----END ${label}-----`;
141
+ const footerStart = input.indexOf(footer, labelEnd + footerMarker.length);
142
+ if (footerStart === -1) {
143
+ const resumeBoundary = findNextBlankLineBoundary(
144
+ input,
145
+ labelEnd + footerMarker.length
146
+ );
147
+ output += input.slice(cursor, begin);
148
+ output += `${header}
149
+ ...redacted...`;
150
+ if (!resumeBoundary) {
151
+ break;
152
+ }
153
+ output += input.slice(resumeBoundary.start, resumeBoundary.end);
154
+ cursor = resumeBoundary.end;
155
+ continue;
156
+ }
157
+ output += input.slice(cursor, begin);
158
+ output += `${header}
159
+ ...redacted...
160
+ ${footer}`;
161
+ cursor = footerStart + footer.length;
162
+ }
163
+ return output;
164
+ }
85
165
  function redactSecrets(input) {
86
- let out = input;
166
+ let out = redactPrivateKeyBlocks(input);
87
167
  for (const pattern of SECRETS_RE) {
88
168
  out = out.replace(pattern, (full, token) => {
89
- if (full.includes("PRIVATE KEY")) {
90
- const lines = full.trim().split("\n");
91
- return lines.length >= 2 ? `${lines[0]}
92
- ...redacted...
93
- ${lines[lines.length - 1]}` : "***PRIVATE KEY***";
94
- }
95
169
  if (typeof token !== "string") {
96
170
  return "***";
97
171
  }
@@ -268,7 +342,77 @@ function formatConsoleValue(value) {
268
342
  }
269
343
  return quoteConsoleValue(value);
270
344
  }
271
- function formatConsoleLine(level, body, attributes) {
345
+ function shouldShowConsoleDestinationName(eventName) {
346
+ return /^(app_home_|oauth_|queue_|slash_command_|slack_|webhook_)/.test(
347
+ eventName
348
+ );
349
+ }
350
+ function shouldShowConsoleModel(level, eventName) {
351
+ if (level === "warn" || level === "error") {
352
+ return true;
353
+ }
354
+ return eventName.startsWith("ai_") || eventName.startsWith("assistant_") || eventName === "agent_turn_started" || eventName === "agent_turn_completed" || eventName === "agent_turn_provider_error";
355
+ }
356
+ function shouldHideConsoleAttribute(level, eventName, key, attributes) {
357
+ if (CONSOLE_ALWAYS_HIDDEN_KEYS.has(key)) {
358
+ return true;
359
+ }
360
+ if (CONSOLE_DROP_WHEN_COUNTED_KEYS.has(key)) {
361
+ return true;
362
+ }
363
+ if (key === "app.agent.id" && attributes[key] === attributes["app.turn.id"]) {
364
+ return true;
365
+ }
366
+ if (key === "messaging.message.conversation_id" && attributes[key] === attributes["app.conversation.id"]) {
367
+ return true;
368
+ }
369
+ if (key === "app.message.id" && attributes[key] === attributes["messaging.message.id"]) {
370
+ return true;
371
+ }
372
+ if (key === "messaging.destination.name" && !shouldShowConsoleDestinationName(eventName)) {
373
+ return true;
374
+ }
375
+ if (key === "gen_ai.request.model" && !shouldShowConsoleModel(level, eventName)) {
376
+ return true;
377
+ }
378
+ if (key === "gen_ai.provider.name" && eventName.startsWith("agent_tool_call_") && level !== "warn" && level !== "error") {
379
+ return true;
380
+ }
381
+ if (key === "gen_ai.operation.name" && eventName.startsWith("agent_tool_call_")) {
382
+ return true;
383
+ }
384
+ return false;
385
+ }
386
+ function summarizeConsoleString(value, maxChars) {
387
+ const collapsed = value.replace(/\s+/g, " ").trim();
388
+ if (collapsed.length <= maxChars) {
389
+ return collapsed;
390
+ }
391
+ return `${collapsed.slice(0, maxChars)}... [${collapsed.length} chars]`;
392
+ }
393
+ function projectConsoleValue(level, key, value) {
394
+ if ((level === "debug" || level === "info") && CONSOLE_PREVIEW_KEYS.has(key) && typeof value === "string") {
395
+ return summarizeConsoleString(
396
+ value,
397
+ key === "gen_ai.tool.call.result" ? 220 : 140
398
+ );
399
+ }
400
+ return value;
401
+ }
402
+ function projectConsoleAttributes(level, eventName, attributes) {
403
+ const projected = {};
404
+ for (const [key, value] of Object.entries(attributes)) {
405
+ if (shouldHideConsoleAttribute(level, eventName, key, attributes)) {
406
+ continue;
407
+ }
408
+ const nextValue = projectConsoleValue(level, key, value);
409
+ if (nextValue !== void 0) {
410
+ projected[key] = nextValue;
411
+ }
412
+ }
413
+ return projected;
414
+ }
415
+ function formatConsoleLine(level, eventName, body, attributes) {
272
416
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
273
417
  const useColor = process.env.NODE_ENV === "development" && Boolean(process.stdout?.isTTY);
274
418
  const levelColor = consoleLevelColor(level);
@@ -276,27 +420,34 @@ function formatConsoleLine(level, body, attributes) {
276
420
  const parts = [
277
421
  `${colorize(timestamp, ANSI.gray)} ${colorize(formatConsoleLevel(level), levelColor)} ${body}`
278
422
  ];
279
- const sortedAttributes = Object.entries(attributes).sort(([left], [right]) => {
280
- const leftRank = CONSOLE_PRIORITY_INDEX.get(left);
281
- const rightRank = CONSOLE_PRIORITY_INDEX.get(right);
282
- if (leftRank !== void 0 || rightRank !== void 0) {
283
- if (leftRank === void 0) return 1;
284
- if (rightRank === void 0) return -1;
285
- return leftRank - rightRank;
423
+ const projectedAttributes = projectConsoleAttributes(
424
+ level,
425
+ eventName,
426
+ attributes
427
+ );
428
+ const sortedAttributes = Object.entries(projectedAttributes).sort(
429
+ ([left], [right]) => {
430
+ const leftRank = CONSOLE_PRIORITY_INDEX.get(left);
431
+ const rightRank = CONSOLE_PRIORITY_INDEX.get(right);
432
+ if (leftRank !== void 0 || rightRank !== void 0) {
433
+ if (leftRank === void 0) return 1;
434
+ if (rightRank === void 0) return -1;
435
+ return leftRank - rightRank;
436
+ }
437
+ return left.localeCompare(right);
286
438
  }
287
- return left.localeCompare(right);
288
- });
439
+ );
289
440
  for (const [key, value] of sortedAttributes) {
290
441
  const rendered = `${colorize(key, ANSI.cyan)}=${colorize(formatConsoleValue(value), ANSI.faint)}`;
291
442
  parts.push(rendered);
292
443
  }
293
444
  return parts.join(" ");
294
445
  }
295
- function emitConsole(level, _eventName, body, attributes) {
446
+ function emitConsole(level, eventName, body, attributes) {
296
447
  if (!shouldEmitConsole(level)) {
297
448
  return;
298
449
  }
299
- const line = formatConsoleLine(level, body, attributes);
450
+ const line = formatConsoleLine(level, eventName, body, attributes);
300
451
  if (level === "error") {
301
452
  console.error(line);
302
453
  return;
@@ -316,14 +467,10 @@ function emit(level, eventName, attrs = {}, body) {
316
467
  const traceAttributes = getTraceCorrelationAttributes();
317
468
  const normalizedEventName = toSnakeCase(eventName);
318
469
  const message = body ? redactSecrets(body) : normalizedEventName;
319
- const attributes = mergeAttributes(
320
- contextAttributes,
321
- traceAttributes,
322
- {
323
- "event.name": normalizedEventName,
324
- ...attrs
325
- }
326
- );
470
+ const attributes = mergeAttributes(contextAttributes, traceAttributes, {
471
+ "event.name": normalizedEventName,
472
+ ...attrs
473
+ });
327
474
  for (const sink of logRecordSinks) {
328
475
  try {
329
476
  sink({
@@ -353,20 +500,27 @@ var log = {
353
500
  },
354
501
  exception(eventName, error, attrs = {}, body) {
355
502
  const normalizedError = error instanceof Error ? error : new Error(String(error));
356
- emit("error", eventName, {
357
- ...attrs,
358
- "error.type": normalizedError.name,
359
- "error.message": normalizedError.message,
360
- "exception.type": normalizedError.name,
361
- "exception.message": normalizedError.message,
362
- "exception.stacktrace": normalizedError.stack
363
- }, body ?? normalizedError.message);
503
+ emit(
504
+ "error",
505
+ eventName,
506
+ {
507
+ ...attrs,
508
+ "error.type": normalizedError.name,
509
+ "error.message": normalizedError.message,
510
+ "exception.type": normalizedError.name,
511
+ "exception.message": normalizedError.message,
512
+ "exception.stacktrace": normalizedError.stack
513
+ },
514
+ body ?? normalizedError.message
515
+ );
364
516
  let eventId;
365
517
  const sentryWithScope = Sentry.withScope;
366
518
  const sentryCaptureException = Sentry.captureException;
367
519
  if (typeof sentryWithScope === "function" && typeof sentryCaptureException === "function") {
368
520
  sentryWithScope((scope) => {
369
- for (const [key, value] of Object.entries(mergeAttributes(contextStorage.getStore(), attrs))) {
521
+ for (const [key, value] of Object.entries(
522
+ mergeAttributes(contextStorage.getStore(), attrs)
523
+ )) {
370
524
  scope.setExtra(key, value);
371
525
  }
372
526
  eventId = sentryCaptureException(normalizedError);
@@ -380,11 +534,17 @@ var log = {
380
534
  }
381
535
  };
382
536
  function withLogContext(context, callback) {
383
- const next = mergeAttributes(contextStorage.getStore(), contextToAttributes(context));
537
+ const next = mergeAttributes(
538
+ contextStorage.getStore(),
539
+ contextToAttributes(context)
540
+ );
384
541
  return contextStorage.run(next, callback);
385
542
  }
386
543
  function setLogContext(context) {
387
- const merged = mergeAttributes(contextStorage.getStore(), contextToAttributes(context));
544
+ const merged = mergeAttributes(
545
+ contextStorage.getStore(),
546
+ contextToAttributes(context)
547
+ );
388
548
  contextStorage.enterWith(merged);
389
549
  }
390
550
  function createLogContextFromRequest(request, context = {}) {
@@ -401,7 +561,9 @@ function createLogContextFromRequest(request, context = {}) {
401
561
  function toSpanAttributes(context) {
402
562
  const attrs = contextToAttributes(context);
403
563
  return Object.fromEntries(
404
- Object.entries(attrs).filter(([, value]) => typeof value === "string" && value.length > 0)
564
+ Object.entries(attrs).filter(
565
+ ([, value]) => typeof value === "string" && value.length > 0
566
+ )
405
567
  );
406
568
  }
407
569
  function setSentryTagsFromContext(context) {
@@ -412,11 +574,12 @@ function setSentryTagsFromContext(context) {
412
574
  }
413
575
  }
414
576
  if (context.slackUserId) {
415
- Sentry.setUser({ id: context.slackUserId, username: context.slackUserName });
577
+ Sentry.setUser({
578
+ id: context.slackUserId,
579
+ username: context.slackUserName
580
+ });
416
581
  }
417
582
  }
418
-
419
- // src/chat/observability.ts
420
583
  function toSpanAttributeValue(value) {
421
584
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
422
585
  return value;
@@ -424,38 +587,28 @@ function toSpanAttributeValue(value) {
424
587
  if (!Array.isArray(value)) {
425
588
  return void 0;
426
589
  }
427
- const sanitized = value.filter((entry) => typeof entry === "string");
590
+ const sanitized = value.filter(
591
+ (entry) => typeof entry === "string"
592
+ );
428
593
  return sanitized.length > 0 ? sanitized : void 0;
429
594
  }
430
- function toContextAndAttributes(context, attributes) {
431
- return {
432
- ...toSpanAttributes(context),
433
- ...attributes
434
- };
435
- }
436
- function logWithLevel(level, eventName, attributes = {}, body) {
437
- if (level === "info") {
438
- log.info(eventName, attributes, body);
439
- return;
440
- }
441
- if (level === "warn") {
442
- log.warn(eventName, attributes, body);
443
- return;
444
- }
445
- log.error(eventName, attributes, body);
446
- }
447
595
  function logInfo(eventName, context = {}, attributes = {}, body) {
448
- logWithLevel("info", eventName, toContextAndAttributes(context, attributes), body);
596
+ log.info(eventName, { ...toSpanAttributes(context), ...attributes }, body);
449
597
  }
450
598
  function logWarn(eventName, context = {}, attributes = {}, body) {
451
- logWithLevel("warn", eventName, toContextAndAttributes(context, attributes), body);
599
+ log.warn(eventName, { ...toSpanAttributes(context), ...attributes }, body);
452
600
  }
453
601
  function logError(eventName, context = {}, attributes = {}, body) {
454
- logWithLevel("error", eventName, toContextAndAttributes(context, attributes), body);
602
+ log.error(eventName, { ...toSpanAttributes(context), ...attributes }, body);
455
603
  }
456
604
  function logException(error, eventName, context = {}, attributes = {}, body) {
457
605
  const normalizedError = error instanceof Error ? error : new Error(String(error));
458
- return log.exception(eventName, normalizedError, toContextAndAttributes(context, attributes), body);
606
+ return log.exception(
607
+ eventName,
608
+ normalizedError,
609
+ { ...toSpanAttributes(context), ...attributes },
610
+ body
611
+ );
459
612
  }
460
613
  function setTags(context = {}) {
461
614
  setLogContext(context);
@@ -477,7 +630,7 @@ async function withSpan(name, op, context, callback, attributes = {}) {
477
630
  }
478
631
  return withLogContext(
479
632
  context,
480
- () => Sentry2.startSpan(
633
+ () => Sentry.startSpan(
481
634
  {
482
635
  name,
483
636
  op,
@@ -491,7 +644,7 @@ async function withSpan(name, op, context, callback, attributes = {}) {
491
644
  );
492
645
  }
493
646
  function setSpanAttributes(attributes) {
494
- const sentry = Sentry2;
647
+ const sentry = Sentry;
495
648
  const span = sentry.getActiveSpan?.();
496
649
  if (!span) {
497
650
  return;
@@ -508,7 +661,7 @@ function setSpanAttributes(attributes) {
508
661
  }
509
662
  }
510
663
  function setSpanStatus(status) {
511
- const sentry = Sentry2;
664
+ const sentry = Sentry;
512
665
  const span = sentry.getActiveSpan?.();
513
666
  if (!span) {
514
667
  return;
@@ -523,7 +676,7 @@ function toOptionalString(value) {
523
676
  return typeof value === "string" && value.trim() ? value : void 0;
524
677
  }
525
678
  function getActiveTraceId() {
526
- const sentry = Sentry2;
679
+ const sentry = Sentry;
527
680
  if (typeof sentry.getActiveSpan !== "function" || typeof sentry.spanToJSON !== "function") {
528
681
  return void 0;
529
682
  }
@@ -550,6 +703,148 @@ function resolveErrorReference(eventId) {
550
703
  ...eventId ? { eventId } : {}
551
704
  };
552
705
  }
706
+ var GEN_AI_DEFAULT_MAX_ATTRIBUTE_CHARS = 12e3;
707
+ var GEN_AI_MAX_STRING_CHARS = 2e3;
708
+ var GEN_AI_MAX_ARRAY_ITEMS = 50;
709
+ var GEN_AI_MAX_OBJECT_KEYS = 50;
710
+ function truncateGenAiString(value, maxChars) {
711
+ return value.length > maxChars ? `${value.slice(0, maxChars)}...` : value;
712
+ }
713
+ function sanitizeGenAiValue(value, seen, depth, keyName) {
714
+ if (value === null || value === void 0) {
715
+ return void 0;
716
+ }
717
+ if (typeof value === "string") {
718
+ const shouldTreatAsBlob = (keyName === "data" || keyName === "base64" || keyName?.endsWith("_base64") === true) && value.length > 256;
719
+ if (shouldTreatAsBlob) {
720
+ return `[omitted:${value.length}]`;
721
+ }
722
+ return truncateGenAiString(value, GEN_AI_MAX_STRING_CHARS);
723
+ }
724
+ if (typeof value === "number") {
725
+ return Number.isFinite(value) ? value : void 0;
726
+ }
727
+ if (typeof value === "boolean") {
728
+ return value;
729
+ }
730
+ if (depth >= 8) {
731
+ return "[depth_limit]";
732
+ }
733
+ if (Array.isArray(value)) {
734
+ return value.slice(0, GEN_AI_MAX_ARRAY_ITEMS).map((entry) => sanitizeGenAiValue(entry, seen, depth + 1)).filter((entry) => entry !== void 0);
735
+ }
736
+ if (typeof value !== "object") {
737
+ return String(value);
738
+ }
739
+ if (seen.has(value)) {
740
+ return "[circular]";
741
+ }
742
+ seen.add(value);
743
+ const record = value;
744
+ const out = {};
745
+ for (const [key, entryValue] of Object.entries(record).slice(
746
+ 0,
747
+ GEN_AI_MAX_OBJECT_KEYS
748
+ )) {
749
+ const sanitized = sanitizeGenAiValue(entryValue, seen, depth + 1, key);
750
+ if (sanitized !== void 0) {
751
+ out[key] = sanitized;
752
+ }
753
+ }
754
+ return out;
755
+ }
756
+ function serializeGenAiAttribute(value, maxChars = GEN_AI_DEFAULT_MAX_ATTRIBUTE_CHARS) {
757
+ const sanitized = sanitizeGenAiValue(value, /* @__PURE__ */ new WeakSet(), 0);
758
+ if (sanitized === void 0) {
759
+ return void 0;
760
+ }
761
+ const serialized = typeof sanitized === "string" ? sanitized : JSON.stringify(sanitized);
762
+ if (!serialized) {
763
+ return void 0;
764
+ }
765
+ return truncateGenAiString(serialized, maxChars);
766
+ }
767
+ function asRecord(value) {
768
+ return value && typeof value === "object" ? value : void 0;
769
+ }
770
+ function toFiniteTokenCount(value) {
771
+ if (typeof value !== "number" || !Number.isFinite(value)) {
772
+ return void 0;
773
+ }
774
+ const rounded = Math.floor(value);
775
+ return rounded >= 0 ? rounded : void 0;
776
+ }
777
+ function readTokenCount(root, keys) {
778
+ for (const key of keys) {
779
+ const value = toFiniteTokenCount(root[key]);
780
+ if (value !== void 0) {
781
+ return value;
782
+ }
783
+ }
784
+ return void 0;
785
+ }
786
+ function collectUsageRoots(source) {
787
+ const sourceRecord = asRecord(source);
788
+ if (!sourceRecord) {
789
+ return [];
790
+ }
791
+ const roots = [sourceRecord];
792
+ const usage = asRecord(sourceRecord.usage);
793
+ if (usage) {
794
+ roots.push(usage);
795
+ }
796
+ const tokenUsage = asRecord(sourceRecord.tokenUsage);
797
+ if (tokenUsage) {
798
+ roots.push(tokenUsage);
799
+ }
800
+ const providerMetadata = asRecord(sourceRecord.providerMetadata);
801
+ if (providerMetadata) {
802
+ roots.push(providerMetadata);
803
+ const providerUsage = asRecord(providerMetadata.usage);
804
+ if (providerUsage) {
805
+ roots.push(providerUsage);
806
+ }
807
+ }
808
+ const response = asRecord(sourceRecord.response);
809
+ if (response) {
810
+ roots.push(response);
811
+ const responseUsage = asRecord(response.usage);
812
+ if (responseUsage) {
813
+ roots.push(responseUsage);
814
+ }
815
+ }
816
+ return roots;
817
+ }
818
+ function extractGenAiUsageAttributes(...sources) {
819
+ const roots = sources.flatMap((source) => collectUsageRoots(source));
820
+ if (roots.length === 0) {
821
+ return {};
822
+ }
823
+ const inputTokens = roots.map(
824
+ (root) => readTokenCount(root, [
825
+ "input_tokens",
826
+ "inputTokens",
827
+ "prompt_tokens",
828
+ "promptTokens",
829
+ "inputTokenCount",
830
+ "promptTokenCount"
831
+ ])
832
+ ).find((value) => value !== void 0) ?? void 0;
833
+ const outputTokens = roots.map(
834
+ (root) => readTokenCount(root, [
835
+ "output_tokens",
836
+ "outputTokens",
837
+ "completion_tokens",
838
+ "completionTokens",
839
+ "outputTokenCount",
840
+ "completionTokenCount"
841
+ ])
842
+ ).find((value) => value !== void 0) ?? void 0;
843
+ return {
844
+ ...inputTokens !== void 0 ? { "gen_ai.usage.input_tokens": inputTokens } : {},
845
+ ...outputTokens !== void 0 ? { "gen_ai.usage.output_tokens": outputTokens } : {}
846
+ };
847
+ }
553
848
 
554
849
  export {
555
850
  logInfo,
@@ -563,5 +858,7 @@ export {
563
858
  setSpanAttributes,
564
859
  setSpanStatus,
565
860
  toOptionalString,
566
- resolveErrorReference
861
+ resolveErrorReference,
862
+ serializeGenAiAttribute,
863
+ extractGenAiUsageAttributes
567
864
  };
package/dist/cli/check.js CHANGED
@@ -1,9 +1,11 @@
1
1
  import {
2
2
  parseSkillFile
3
- } from "../chunk-KT5HARSN.js";
3
+ } from "../chunk-VM3CPAZF.js";
4
4
  import {
5
5
  parsePluginManifest
6
- } from "../chunk-VW26MOSO.js";
6
+ } from "../chunk-ZBWWHP6Q.js";
7
+ import "../chunk-KCLEEKYX.js";
8
+ import "../chunk-ZW4OVKF5.js";
7
9
 
8
10
  // src/cli/check.ts
9
11
  import fs from "fs/promises";
@@ -1,13 +1,14 @@
1
1
  import {
2
2
  disconnectStateAdapter,
3
+ resolveRuntimeDependencySnapshot
4
+ } from "../chunk-IJVZEV3K.js";
5
+ import {
3
6
  getPluginProviders,
4
7
  getPluginRuntimeDependencies,
5
- getPluginRuntimePostinstall,
6
- resolveRuntimeDependencySnapshot
7
- } from "../chunk-RKOO42TW.js";
8
- import "../chunk-Z5E25LRN.js";
9
- import "../chunk-PY4AI2GZ.js";
10
- import "../chunk-VW26MOSO.js";
8
+ getPluginRuntimePostinstall
9
+ } from "../chunk-ZBWWHP6Q.js";
10
+ import "../chunk-KCLEEKYX.js";
11
+ import "../chunk-ZW4OVKF5.js";
11
12
 
12
13
  // src/cli/snapshot-warmup.ts
13
14
  var DEFAULT_RUNTIME = "node22";
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  POST
3
- } from "../chunk-56WI5Q7P.js";
4
- import "../chunk-JRKU55W5.js";
5
- import "../chunk-KT5HARSN.js";
6
- import "../chunk-RKOO42TW.js";
7
- import "../chunk-Z5E25LRN.js";
8
- import "../chunk-PY4AI2GZ.js";
9
- import "../chunk-VW26MOSO.js";
3
+ } from "../chunk-4G2LA7RO.js";
4
+ import "../chunk-DIMXJUSL.js";
5
+ import "../chunk-VM3CPAZF.js";
6
+ import "../chunk-IJVZEV3K.js";
7
+ import "../chunk-ZBWWHP6Q.js";
8
+ import "../chunk-KCLEEKYX.js";
9
+ import "../chunk-ZW4OVKF5.js";
10
10
  export {
11
11
  POST
12
12
  };
@@ -6,6 +6,7 @@ type RouteContext = {
6
6
  *
7
7
  * Supported routes:
8
8
  * - `api/health`
9
+ * - `api/oauth/callback/mcp/:provider`
9
10
  * - `api/oauth/callback/:provider`
10
11
  */
11
12
  declare function GET(request: Request, context: RouteContext): Promise<Response>;