@raindrop-ai/ai-sdk 0.1.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import { AsyncLocalStorage } from 'async_hooks';
2
2
 
3
- // ../core/dist/chunk-Y5LUB7OE.js
3
+ // ../core/dist/chunk-QNWZIOOY.js
4
4
  function normalizeFeatureFlags(input) {
5
5
  if (Array.isArray(input)) {
6
6
  return Object.fromEntries(input.map((name) => [name, "true"]));
@@ -443,19 +443,52 @@ function projectIdHeaders(projectId) {
443
443
  var SHUTDOWN_DEADLINE_MS = 1e4;
444
444
  var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
445
445
  function mergePatches(target, source) {
446
- var _a, _b, _c, _d, _e, _f;
446
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
447
447
  const out = { ...target, ...source };
448
448
  if (target.properties || source.properties) {
449
449
  out.properties = { ...(_a = target.properties) != null ? _a : {}, ...(_b = source.properties) != null ? _b : {} };
450
450
  }
451
+ if (target.usage || source.usage) {
452
+ out.usage = { ...(_c = target.usage) != null ? _c : {} };
453
+ if (((_d = source.usage) == null ? void 0 : _d.promptTokens) !== void 0) {
454
+ out.usage.promptTokens = source.usage.promptTokens;
455
+ }
456
+ if (((_e = source.usage) == null ? void 0 : _e.completionTokens) !== void 0) {
457
+ out.usage.completionTokens = source.usage.completionTokens;
458
+ }
459
+ }
460
+ if (source.error === void 0) {
461
+ out.error = target.error;
462
+ }
451
463
  if (target.featureFlags || source.featureFlags) {
452
- out.featureFlags = { ...(_c = target.featureFlags) != null ? _c : {}, ...(_d = source.featureFlags) != null ? _d : {} };
464
+ out.featureFlags = { ...(_f = target.featureFlags) != null ? _f : {}, ...(_g = source.featureFlags) != null ? _g : {} };
453
465
  }
454
466
  if (target.attachments || source.attachments) {
455
- out.attachments = [...(_e = target.attachments) != null ? _e : [], ...(_f = source.attachments) != null ? _f : []];
467
+ out.attachments = [...(_h = target.attachments) != null ? _h : [], ...(_i = source.attachments) != null ? _i : []];
456
468
  }
457
469
  return out;
458
470
  }
471
+ function isErrorLike(value) {
472
+ return value !== null && typeof value === "object";
473
+ }
474
+ function eventTelemetryProperties(patch) {
475
+ var _a, _b;
476
+ const properties = {};
477
+ if (((_a = patch.usage) == null ? void 0 : _a.promptTokens) !== void 0 && Number.isFinite(patch.usage.promptTokens)) {
478
+ properties["ai.usage.prompt_tokens"] = patch.usage.promptTokens;
479
+ }
480
+ if (((_b = patch.usage) == null ? void 0 : _b.completionTokens) !== void 0 && Number.isFinite(patch.usage.completionTokens)) {
481
+ properties["ai.usage.completion_tokens"] = patch.usage.completionTokens;
482
+ }
483
+ if (patch.error !== void 0 && patch.error !== null) {
484
+ const constructorName = patch.error instanceof Error && patch.error.constructor !== Error ? patch.error.constructor.name : void 0;
485
+ const errorType = patch.error instanceof Error ? patch.error.name && patch.error.name !== "Error" ? patch.error.name : constructorName || patch.error.name || "Error" : isErrorLike(patch.error) && typeof patch.error.name === "string" && patch.error.name.length > 0 ? patch.error.name : "Error";
486
+ const errorMessage = patch.error instanceof Error ? patch.error.message : isErrorLike(patch.error) && typeof patch.error.message === "string" ? patch.error.message : String(patch.error);
487
+ properties["error.type"] = errorType;
488
+ properties["error.message"] = errorMessage;
489
+ }
490
+ return properties;
491
+ }
459
492
  var EventShipper = class {
460
493
  constructor(opts) {
461
494
  this.buffers = /* @__PURE__ */ new Map();
@@ -704,6 +737,11 @@ var EventShipper = class {
704
737
  return;
705
738
  }
706
739
  const { wizardSession, ...restProperties } = (_e = accumulated.properties) != null ? _e : {};
740
+ let telemetryProperties = {};
741
+ try {
742
+ telemetryProperties = eventTelemetryProperties(accumulated);
743
+ } catch (e) {
744
+ }
707
745
  const convoId = (_f = accumulated.convoId) != null ? _f : sticky.convoId;
708
746
  const isPending = (_h = (_g = accumulated.isPending) != null ? _g : sticky.isPending) != null ? _h : true;
709
747
  const payload = {
@@ -713,12 +751,13 @@ var EventShipper = class {
713
751
  timestamp: (_i = accumulated.timestamp) != null ? _i : (/* @__PURE__ */ new Date()).toISOString(),
714
752
  ai_data: {
715
753
  input: accumulated.input,
716
- output: accumulated.output,
754
+ output: accumulated.error !== void 0 && accumulated.error !== null ? void 0 : accumulated.output,
717
755
  model: accumulated.model,
718
756
  convo_id: convoId
719
757
  },
720
758
  properties: {
721
759
  ...restProperties,
760
+ ...telemetryProperties,
722
761
  ...wizardSession ? { "raindrop.wizardSession": wizardSession } : {},
723
762
  $context: this.context
724
763
  },
@@ -787,6 +826,193 @@ var EventShipper = class {
787
826
  }
788
827
  }
789
828
  };
829
+ var MODEL_USAGE_ATTRIBUTES = {
830
+ providerName: "gen_ai.provider.name",
831
+ requestModel: "gen_ai.request.model",
832
+ responseModel: "gen_ai.response.model",
833
+ inputTokens: "gen_ai.usage.input_tokens",
834
+ outputTokens: "gen_ai.usage.output_tokens",
835
+ reasoningTokens: "gen_ai.usage.reasoning_tokens",
836
+ cacheReadInputTokens: "gen_ai.usage.cache_read_input_tokens",
837
+ cacheWriteInputTokens: "gen_ai.usage.cache_write_input_tokens",
838
+ nonCachedInputTokens: "raindrop.usage.input_tokens.non_cached",
839
+ nonReasoningOutputTokens: "raindrop.usage.output_tokens.non_reasoning",
840
+ reasoningOutputTokens: "raindrop.usage.output_tokens.reasoning",
841
+ cacheReadTokens: "raindrop.usage.input_tokens.cache_read",
842
+ cacheWriteTokens: "raindrop.usage.input_tokens.cache_write"
843
+ };
844
+ var MODEL_PROVIDER_NAMES = [
845
+ ["google.vertex", "google-vertex"],
846
+ ["vertex.anthropic", "google-vertex"],
847
+ ["amazon-bedrock", "amazon-bedrock"],
848
+ ["bedrock", "amazon-bedrock"],
849
+ ["anthropic", "anthropic"],
850
+ ["openai", "openai"],
851
+ ["google", "google"],
852
+ ["azure", "azure"],
853
+ ["openrouter", "openrouter"]
854
+ ];
855
+ function canonicalModelProvider(provider) {
856
+ var _a;
857
+ const normalizedProvider = provider.trim().toLowerCase();
858
+ if (normalizedProvider === "gateway") return "vercel";
859
+ const match = MODEL_PROVIDER_NAMES.find(
860
+ ([family]) => normalizedProvider === family || normalizedProvider.startsWith(`${family}.`)
861
+ );
862
+ return (_a = match == null ? void 0 : match[1]) != null ? _a : provider;
863
+ }
864
+ function tokenCount(value) {
865
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
866
+ }
867
+ function exclusiveTokens({
868
+ explicit,
869
+ total,
870
+ parts,
871
+ semantics
872
+ }) {
873
+ if (explicit !== void 0) return explicit;
874
+ if (total === void 0) return void 0;
875
+ if (semantics === "exclusive") return total;
876
+ const observedParts = parts.filter((part) => part !== void 0 && part > 0);
877
+ if (semantics === void 0 && observedParts.length > 0) return void 0;
878
+ const exclusive = total - observedParts.reduce((sum, part) => sum + part, 0);
879
+ return exclusive >= 0 ? exclusive : void 0;
880
+ }
881
+ function buildModelUsageAttributes(usage) {
882
+ const inputTokens = tokenCount(usage.inputTokens);
883
+ const outputTokens = tokenCount(usage.outputTokens);
884
+ const explicitNonCachedInputTokens = tokenCount(usage.nonCachedInputTokens);
885
+ const explicitNonReasoningOutputTokens = tokenCount(usage.nonReasoningOutputTokens);
886
+ const reasoningTokens = tokenCount(usage.reasoningTokens);
887
+ const cacheReadInputTokens = tokenCount(usage.cacheReadInputTokens);
888
+ const cacheWriteInputTokens = tokenCount(usage.cacheWriteInputTokens);
889
+ const nonCachedInputTokens = exclusiveTokens({
890
+ explicit: explicitNonCachedInputTokens,
891
+ total: inputTokens,
892
+ parts: [cacheReadInputTokens, cacheWriteInputTokens],
893
+ semantics: usage.inputTokenSemantics
894
+ });
895
+ const nonReasoningOutputTokens = exclusiveTokens({
896
+ explicit: explicitNonReasoningOutputTokens,
897
+ total: outputTokens,
898
+ parts: [reasoningTokens],
899
+ semantics: usage.outputTokenSemantics
900
+ });
901
+ const exclusivePoolAttributes = nonCachedInputTokens !== void 0 && nonReasoningOutputTokens !== void 0 ? [
902
+ // backend consumes this complete raindrop.* set as one atomic billing-pool contract.
903
+ attrInt(MODEL_USAGE_ATTRIBUTES.nonCachedInputTokens, nonCachedInputTokens),
904
+ attrInt(MODEL_USAGE_ATTRIBUTES.nonReasoningOutputTokens, nonReasoningOutputTokens),
905
+ attrInt(MODEL_USAGE_ATTRIBUTES.reasoningOutputTokens, reasoningTokens),
906
+ attrInt(MODEL_USAGE_ATTRIBUTES.cacheReadTokens, cacheReadInputTokens),
907
+ attrInt(MODEL_USAGE_ATTRIBUTES.cacheWriteTokens, cacheWriteInputTokens)
908
+ ] : [];
909
+ return [
910
+ attrInt(MODEL_USAGE_ATTRIBUTES.inputTokens, inputTokens),
911
+ attrInt(MODEL_USAGE_ATTRIBUTES.outputTokens, outputTokens),
912
+ attrInt(MODEL_USAGE_ATTRIBUTES.reasoningTokens, reasoningTokens),
913
+ attrInt(MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens, cacheReadInputTokens),
914
+ attrInt(MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens, cacheWriteInputTokens),
915
+ ...exclusivePoolAttributes
916
+ ].filter((attribute) => attribute !== void 0);
917
+ }
918
+ var STRING_ALIASES = {
919
+ [MODEL_USAGE_ATTRIBUTES.requestModel]: ["ai.model.id", "ai.model"]
920
+ };
921
+ var NUMBER_ALIASES = {
922
+ [MODEL_USAGE_ATTRIBUTES.inputTokens]: [
923
+ "gen_ai.usage.prompt_tokens",
924
+ "ai.usage.prompt_tokens",
925
+ "ai.usage.promptTokens",
926
+ "ai.usage.input_tokens",
927
+ "ai.usage.inputTokens"
928
+ ],
929
+ [MODEL_USAGE_ATTRIBUTES.outputTokens]: [
930
+ "gen_ai.usage.completion_tokens",
931
+ "ai.usage.completion_tokens",
932
+ "ai.usage.completionTokens",
933
+ "ai.usage.output_tokens",
934
+ "ai.usage.outputTokens"
935
+ ],
936
+ [MODEL_USAGE_ATTRIBUTES.reasoningTokens]: [
937
+ "gen_ai.usage.reasoning.output_tokens",
938
+ "ai.usage.reasoningTokens",
939
+ "ai.usage.thoughts_tokens"
940
+ ],
941
+ [MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens]: [
942
+ "gen_ai.usage.cache_read_tokens",
943
+ "gen_ai.usage.cache_read.input_tokens",
944
+ "ai.usage.cachedInputTokens",
945
+ "ai.usage.cached_tokens",
946
+ "ai.usage.cache_read_tokens",
947
+ "ai.usage.cache_read_input_tokens",
948
+ "ai.usage.cacheReadInputTokens"
949
+ ],
950
+ [MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens]: [
951
+ "gen_ai.usage.cache_creation_input_tokens",
952
+ "gen_ai.usage.cache_creation.input_tokens",
953
+ "ai.usage.cacheWriteInputTokens",
954
+ "ai.usage.cache_creation_input_tokens",
955
+ "ai.usage.cacheCreationInputTokens"
956
+ ]
957
+ };
958
+ function hasAttribute(attributes, key) {
959
+ return attributes.some((attribute) => attribute.key === key);
960
+ }
961
+ function findStringAttribute(attributes, keys) {
962
+ return attributes.find(
963
+ (attribute) => keys.includes(attribute.key) && typeof attribute.value.stringValue === "string" && attribute.value.stringValue.length > 0
964
+ );
965
+ }
966
+ function findNumberAttribute(attributes, keys) {
967
+ return attributes.find((attribute) => {
968
+ if (!keys.includes(attribute.key)) return false;
969
+ if (typeof attribute.value.doubleValue === "number" && Number.isSafeInteger(attribute.value.doubleValue) && attribute.value.doubleValue >= 0) {
970
+ return true;
971
+ }
972
+ const intValue = attribute.value.intValue;
973
+ return integerValue(intValue) !== void 0;
974
+ });
975
+ }
976
+ function integerValue(value) {
977
+ if (typeof value === "number") {
978
+ return Number.isSafeInteger(value) && value >= 0 ? value : void 0;
979
+ }
980
+ if (typeof value !== "string") return void 0;
981
+ const parsed = Number(value);
982
+ return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : void 0;
983
+ }
984
+ function appendAlias(attributes, target, source) {
985
+ if (!source || hasAttribute(attributes, target)) return attributes;
986
+ return [...attributes, { key: target, value: { ...source.value } }];
987
+ }
988
+ function appendProviderAlias(attributes) {
989
+ if (hasAttribute(attributes, MODEL_USAGE_ATTRIBUTES.providerName)) return attributes;
990
+ const source = findStringAttribute(attributes, ["gen_ai.system", "ai.model.provider"]);
991
+ if (!(source == null ? void 0 : source.value.stringValue)) return attributes;
992
+ const attribute = attrString(
993
+ MODEL_USAGE_ATTRIBUTES.providerName,
994
+ canonicalModelProvider(source.value.stringValue)
995
+ );
996
+ return attribute ? [...attributes, attribute] : attributes;
997
+ }
998
+ function normalizeModelUsageSpan(span) {
999
+ const original = span.attributes;
1000
+ if (!original || original.length === 0) return span;
1001
+ const responseModel = findStringAttribute(original, [
1002
+ MODEL_USAGE_ATTRIBUTES.responseModel,
1003
+ "ai.response.model"
1004
+ ]);
1005
+ if (!responseModel) return span;
1006
+ let attributes = appendAlias(original, MODEL_USAGE_ATTRIBUTES.responseModel, responseModel);
1007
+ attributes = appendProviderAlias(attributes);
1008
+ for (const [target, aliases] of Object.entries(STRING_ALIASES)) {
1009
+ attributes = appendAlias(attributes, target, findStringAttribute(attributes, aliases));
1010
+ }
1011
+ for (const [target, aliases] of Object.entries(NUMBER_ALIASES)) {
1012
+ attributes = appendAlias(attributes, target, findNumberAttribute(attributes, aliases));
1013
+ }
1014
+ return attributes === original ? span : { ...span, attributes };
1015
+ }
790
1016
  var DEFAULT_SECRET_KEY_NAMES = [
791
1017
  "apikey",
792
1018
  "apisecret",
@@ -876,6 +1102,13 @@ function redactJsonAttributeValue(key, value) {
876
1102
  if (scrubbedJson === json) return void 0;
877
1103
  return { stringValue: scrubbedJson };
878
1104
  }
1105
+ function identityAttrs(args) {
1106
+ return [
1107
+ attrString("ai.telemetry.metadata.raindrop.ai.userId", args.userId),
1108
+ attrString("ai.telemetry.metadata.raindrop.convoId", args.convoId),
1109
+ attrString("ai.telemetry.metadata.raindrop.eventName", args.eventName)
1110
+ ];
1111
+ }
879
1112
  function applyOtelSpanAttributeLimit(limit) {
880
1113
  var _a, _b;
881
1114
  try {
@@ -980,6 +1213,10 @@ var TraceShipper = class {
980
1213
  return null;
981
1214
  }
982
1215
  }
1216
+ try {
1217
+ current = normalizeModelUsageSpan(current);
1218
+ } catch (e) {
1219
+ }
983
1220
  if (!this.disableDefaultRedaction) {
984
1221
  current = defaultTransformSpan(current);
985
1222
  }
@@ -1000,6 +1237,7 @@ var TraceShipper = class {
1000
1237
  const started = (_a = args.startTimeUnixNano) != null ? _a : nowUnixNanoString();
1001
1238
  const attrs = [
1002
1239
  attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
1240
+ ...identityAttrs(args),
1003
1241
  attrString("ai.operationId", args.operationId)
1004
1242
  ];
1005
1243
  if ((_b = args.attributes) == null ? void 0 : _b.length) attrs.push(...args.attributes);
@@ -1055,7 +1293,8 @@ var TraceShipper = class {
1055
1293
  var _a;
1056
1294
  const ids = createSpanIds(args.parent);
1057
1295
  const attrs = [
1058
- attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId)
1296
+ attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
1297
+ ...identityAttrs(args)
1059
1298
  ];
1060
1299
  if ((_a = args.attributes) == null ? void 0 : _a.length) attrs.push(...args.attributes);
1061
1300
  const otlp = buildOtlpSpan({
@@ -2012,6 +2251,15 @@ function attrsFromHeaders(headers) {
2012
2251
  if (!isRecord(headers)) return [];
2013
2252
  return Object.entries(headers).filter(([, v]) => typeof v === "string").map(([k, v]) => attrString(`ai.request.headers.${k}`, v));
2014
2253
  }
2254
+ function attrsFromModelProvider(provider) {
2255
+ if (typeof provider !== "string" || provider.length === 0) return [];
2256
+ const providerName = canonicalModelProvider(provider);
2257
+ return [
2258
+ attrString("ai.model.provider", provider),
2259
+ attrString(MODEL_USAGE_ATTRIBUTES.providerName, providerName),
2260
+ attrString("gen_ai.system", provider)
2261
+ ];
2262
+ }
2015
2263
  function attrsFromSettings(args) {
2016
2264
  if (!isRecord(args)) return [];
2017
2265
  const result = [];
@@ -2194,6 +2442,126 @@ function runWithParentToolContext(ctx, fn) {
2194
2442
  return getStorage2().run(ctx, fn);
2195
2443
  }
2196
2444
 
2445
+ // src/internal/usage.ts
2446
+ function firstTokenCount(...values) {
2447
+ for (const value of values) {
2448
+ if (typeof value === "number" && Number.isSafeInteger(value) && value >= 0) {
2449
+ return value;
2450
+ }
2451
+ }
2452
+ return void 0;
2453
+ }
2454
+ function flatUsageSemantics(provider) {
2455
+ const normalizedProvider = typeof provider === "string" ? provider.trim().toLowerCase() : void 0;
2456
+ if (normalizedProvider === "anthropic" || (normalizedProvider == null ? void 0 : normalizedProvider.startsWith("anthropic.")) || normalizedProvider === "vertex.anthropic" || (normalizedProvider == null ? void 0 : normalizedProvider.startsWith("vertex.anthropic."))) {
2457
+ return {
2458
+ inputTokenSemantics: "exclusive",
2459
+ outputTokenSemantics: "total"
2460
+ };
2461
+ }
2462
+ if (normalizedProvider === "openai" || (normalizedProvider == null ? void 0 : normalizedProvider.startsWith("openai.")) || normalizedProvider === "azure" || (normalizedProvider == null ? void 0 : normalizedProvider.startsWith("azure."))) {
2463
+ return {
2464
+ inputTokenSemantics: "total",
2465
+ outputTokenSemantics: "total"
2466
+ };
2467
+ }
2468
+ if (normalizedProvider === "google" || (normalizedProvider == null ? void 0 : normalizedProvider.startsWith("google."))) {
2469
+ return {
2470
+ inputTokenSemantics: "total",
2471
+ // Google v5 reports candidate output and thoughts separately.
2472
+ outputTokenSemantics: "exclusive"
2473
+ };
2474
+ }
2475
+ return {};
2476
+ }
2477
+ var CACHE_WRITE_METADATA_KEYS = [
2478
+ ["anthropic", "cacheCreationInputTokens"],
2479
+ ["openai", "cacheWriteTokens"],
2480
+ ["bedrock", "cacheWriteInputTokens"]
2481
+ ];
2482
+ function cacheWriteTokensFromProviderMetadata(providerMetadata) {
2483
+ if (!isRecord(providerMetadata)) return void 0;
2484
+ return firstTokenCount(
2485
+ ...CACHE_WRITE_METADATA_KEYS.flatMap(([namespace, key]) => {
2486
+ const scope = providerMetadata[namespace];
2487
+ if (!isRecord(scope)) return [];
2488
+ const usage = scope["usage"];
2489
+ return [scope[key], isRecord(usage) ? usage[key] : void 0];
2490
+ })
2491
+ );
2492
+ }
2493
+ function extractUsageMetricsFromUsage(usage, provider, providerMetadata) {
2494
+ if (!isRecord(usage)) return {};
2495
+ const inputTokenValue = usage["inputTokens"];
2496
+ const outputTokenValue = usage["outputTokens"];
2497
+ const inputTokenDetails = usage["inputTokenDetails"];
2498
+ const outputTokenDetails = usage["outputTokenDetails"];
2499
+ const hasStructuredUsage = isRecord(inputTokenValue) || isRecord(outputTokenValue) || isRecord(inputTokenDetails) || isRecord(outputTokenDetails);
2500
+ const inputTokens = firstTokenCount(
2501
+ isRecord(inputTokenValue) ? inputTokenValue["total"] : void 0,
2502
+ inputTokenValue,
2503
+ usage["promptTokens"],
2504
+ usage["prompt_tokens"]
2505
+ );
2506
+ const outputTokens = firstTokenCount(
2507
+ isRecord(outputTokenValue) ? outputTokenValue["total"] : void 0,
2508
+ outputTokenValue,
2509
+ usage["completionTokens"],
2510
+ usage["completion_tokens"]
2511
+ );
2512
+ const reasoningTokens = firstTokenCount(
2513
+ isRecord(outputTokenValue) ? outputTokenValue["reasoning"] : void 0,
2514
+ isRecord(outputTokenDetails) ? outputTokenDetails["reasoningTokens"] : void 0,
2515
+ usage["reasoningTokens"],
2516
+ usage["completionReasoningTokens"],
2517
+ usage["completion_reasoning_tokens"],
2518
+ usage["reasoning_tokens"],
2519
+ usage["thinkingTokens"],
2520
+ usage["thinking_tokens"]
2521
+ );
2522
+ const cacheReadInputTokens = firstTokenCount(
2523
+ isRecord(inputTokenValue) ? inputTokenValue["cacheRead"] : void 0,
2524
+ isRecord(inputTokenDetails) ? inputTokenDetails["cacheReadTokens"] : void 0,
2525
+ usage["cachedInputTokens"],
2526
+ usage["promptCachedTokens"],
2527
+ usage["prompt_cached_tokens"]
2528
+ );
2529
+ const cacheWriteInputTokens = firstTokenCount(
2530
+ isRecord(inputTokenValue) ? inputTokenValue["cacheWrite"] : void 0,
2531
+ isRecord(inputTokenDetails) ? inputTokenDetails["cacheWriteTokens"] : void 0,
2532
+ usage["cacheWriteInputTokens"],
2533
+ usage["cacheCreationInputTokens"],
2534
+ usage["cache_creation_input_tokens"],
2535
+ cacheWriteTokensFromProviderMetadata(providerMetadata)
2536
+ );
2537
+ const nonCachedInputTokens = firstTokenCount(
2538
+ isRecord(inputTokenValue) ? inputTokenValue["noCache"] : void 0,
2539
+ isRecord(inputTokenDetails) ? inputTokenDetails["noCacheTokens"] : void 0
2540
+ );
2541
+ const nonReasoningOutputTokens = firstTokenCount(
2542
+ isRecord(outputTokenValue) ? outputTokenValue["text"] : void 0,
2543
+ isRecord(outputTokenDetails) ? outputTokenDetails["textTokens"] : void 0
2544
+ );
2545
+ const totalTokens = firstTokenCount(
2546
+ usage["totalTokens"],
2547
+ usage["tokens"],
2548
+ usage["total_tokens"],
2549
+ inputTokens !== void 0 && outputTokens !== void 0 ? inputTokens + outputTokens : void 0
2550
+ );
2551
+ return {
2552
+ inputTokens,
2553
+ outputTokens,
2554
+ totalTokens,
2555
+ nonCachedInputTokens,
2556
+ nonReasoningOutputTokens,
2557
+ reasoningTokens,
2558
+ cacheReadInputTokens,
2559
+ cachedInputTokens: cacheReadInputTokens,
2560
+ cacheWriteInputTokens,
2561
+ ...hasStructuredUsage ? {} : flatUsageSemantics(provider)
2562
+ };
2563
+ }
2564
+
2197
2565
  // src/internal/raindrop-telemetry-integration.ts
2198
2566
  function hasUnresolvedToolApproval(event) {
2199
2567
  var _a;
@@ -2250,7 +2618,7 @@ var RaindropTelemetryIntegration = class {
2250
2618
  };
2251
2619
  // ── onStart ─────────────────────────────────────────────────────────────
2252
2620
  this.onStart = (event) => {
2253
- var _a, _b, _c, _d, _e;
2621
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2254
2622
  if (event.isEnabled === false) return;
2255
2623
  const isEmbed = event.operationId === "ai.embed" || event.operationId === "ai.embedMany";
2256
2624
  const recordInputs = event.recordInputs !== false;
@@ -2260,15 +2628,20 @@ var RaindropTelemetryIntegration = class {
2260
2628
  const callContextMetadata = getCurrentRaindropCallMetadata();
2261
2629
  const metadata = eventMetadata2 != null ? eventMetadata2 : callContextMetadata == null ? void 0 : callContextMetadata.rawMetadata;
2262
2630
  const callMeta = this.extractRaindropMetadata(metadata);
2631
+ const identity = {
2632
+ userId: (_b = callMeta.userId) != null ? _b : (_a = this.defaultContext) == null ? void 0 : _a.userId,
2633
+ convoId: (_d = callMeta.convoId) != null ? _d : (_c = this.defaultContext) == null ? void 0 : _c.convoId,
2634
+ eventName: (_f = callMeta.eventName) != null ? _f : (_e = this.defaultContext) == null ? void 0 : _e.eventName
2635
+ };
2263
2636
  const inherited = getContextManager().getParentSpanIds();
2264
2637
  const eventIdGenerated = (metadata == null ? void 0 : metadata["raindrop.internal.eventIdGenerated"]) === "true" || (metadata == null ? void 0 : metadata["raindrop.internal.eventIdGenerated"]) === true || (callContextMetadata == null ? void 0 : callContextMetadata.eventIdGenerated) === true;
2265
2638
  const explicitEventId = callMeta.eventId && !eventIdGenerated ? callMeta.eventId : void 0;
2266
- const eventId = (_d = (_c = (_b = explicitEventId != null ? explicitEventId : (_a = this.defaultContext) == null ? void 0 : _a.eventId) != null ? _b : inherited == null ? void 0 : inherited.eventId) != null ? _c : callMeta.eventId) != null ? _d : randomUUID();
2639
+ const eventId = (_j = (_i = (_h = explicitEventId != null ? explicitEventId : (_g = this.defaultContext) == null ? void 0 : _g.eventId) != null ? _h : inherited == null ? void 0 : inherited.eventId) != null ? _i : callMeta.eventId) != null ? _j : randomUUID();
2267
2640
  const inheritedParent = inherited && inherited.eventId === eventId ? { traceIdB64: inherited.traceIdB64, spanIdB64: inherited.spanIdB64 } : void 0;
2268
2641
  const { operationName, resourceName } = opName(event.operationId, functionId);
2269
2642
  const parentToolContext = !isEmbed && this.subagentWrapping ? getCurrentParentToolContext() : void 0;
2270
2643
  const metadataSubagentName = !isEmbed && this.subagentWrapping && parentToolContext === void 0 ? typeof (metadata == null ? void 0 : metadata["eve.subagent.name"]) === "string" ? metadata["eve.subagent.name"] : typeof (metadata == null ? void 0 : metadata["ash.subagent.name"]) === "string" ? metadata["ash.subagent.name"] : void 0 : void 0;
2271
- const subagentName = (_e = parentToolContext == null ? void 0 : parentToolContext.toolName) != null ? _e : metadataSubagentName;
2644
+ const subagentName = (_k = parentToolContext == null ? void 0 : parentToolContext.toolName) != null ? _k : metadataSubagentName;
2272
2645
  let subagentToolCallSpan;
2273
2646
  let rootParentOverride;
2274
2647
  if (subagentName && this.sendTraces) {
@@ -2281,6 +2654,7 @@ var RaindropTelemetryIntegration = class {
2281
2654
  name: subagentName,
2282
2655
  parent: inheritedParent,
2283
2656
  eventId,
2657
+ ...identity,
2284
2658
  operationId: "ai.toolCall",
2285
2659
  attributes: [
2286
2660
  attrString("operation.name", "ai.toolCall"),
@@ -2297,6 +2671,7 @@ var RaindropTelemetryIntegration = class {
2297
2671
  name: "agent.subagent",
2298
2672
  parent: subagentParentRef,
2299
2673
  eventId,
2674
+ ...identity,
2300
2675
  operationId: "agent.subagent",
2301
2676
  attributes: [
2302
2677
  attrString("operation.name", "agent.subagent"),
@@ -2324,6 +2699,7 @@ var RaindropTelemetryIntegration = class {
2324
2699
  name: event.operationId,
2325
2700
  parent: rootParentOverride != null ? rootParentOverride : inheritedParent,
2326
2701
  eventId,
2702
+ ...identity,
2327
2703
  operationId: event.operationId,
2328
2704
  attributes: [
2329
2705
  attrString("operation.name", operationName),
@@ -2331,13 +2707,14 @@ var RaindropTelemetryIntegration = class {
2331
2707
  attrString("ai.telemetry.functionId", functionId),
2332
2708
  attrString("ai.model.provider", event.provider),
2333
2709
  attrString("ai.model.id", event.modelId),
2334
- // Filter out raindrop.eventId from metadata attrs since TraceShipper
2335
- // already sets it via the eventId arg. Without this, eventMetadata()'s
2336
- // auto-generated ID would duplicate and override the resolved one.
2710
+ // Filter out identity keys (eventId/userId/convoId/eventName) from
2711
+ // metadata attrs since TraceShipper already stamps them via dedicated
2712
+ // args. Without this, eventMetadata()'s auto-generated ID would
2713
+ // duplicate and override the resolved one.
2337
2714
  ...attrsFromTelemetryMetadata(
2338
2715
  metadata ? Object.fromEntries(
2339
2716
  Object.entries(metadata).filter(
2340
- ([k]) => k !== "raindrop.eventId" && k !== "raindrop.internal.eventIdGenerated"
2717
+ ([k]) => k !== "raindrop.eventId" && k !== "raindrop.internal.eventIdGenerated" && k !== "raindrop.userId" && k !== "raindrop.convoId" && k !== "raindrop.eventName"
2341
2718
  )
2342
2719
  ) : void 0
2343
2720
  ),
@@ -2349,10 +2726,13 @@ var RaindropTelemetryIntegration = class {
2349
2726
  this.callStates.set(event.callId, {
2350
2727
  operationId: event.operationId,
2351
2728
  eventId,
2729
+ identity,
2352
2730
  rootSpan,
2353
2731
  rootParent: rootSpan ? this.spanParentRef(rootSpan) : rootParentOverride != null ? rootParentOverride : inheritedParent,
2354
2732
  stepSpan: void 0,
2355
2733
  stepParent: void 0,
2734
+ stepProvider: void 0,
2735
+ stepModelId: void 0,
2356
2736
  toolSpans: /* @__PURE__ */ new Map(),
2357
2737
  embedSpans: /* @__PURE__ */ new Map(),
2358
2738
  parentContextToolCallIds: /* @__PURE__ */ new Set(),
@@ -2400,20 +2780,22 @@ var RaindropTelemetryIntegration = class {
2400
2780
  name: stepOperationId,
2401
2781
  parent: state.rootParent,
2402
2782
  eventId: state.eventId,
2783
+ ...state.identity,
2403
2784
  operationId: stepOperationId,
2404
2785
  attributes: [
2405
2786
  attrString("operation.name", operationName),
2406
2787
  attrString("resource.name", resourceName),
2407
2788
  attrString("ai.telemetry.functionId", state.functionId),
2408
- attrString("ai.model.provider", event.provider),
2789
+ ...attrsFromModelProvider(event.provider),
2409
2790
  attrString("ai.model.id", event.modelId),
2410
- attrString("gen_ai.system", event.provider),
2411
- attrString("gen_ai.request.model", event.modelId),
2791
+ attrString(MODEL_USAGE_ATTRIBUTES.requestModel, event.modelId),
2412
2792
  ...inputAttrs
2413
2793
  ]
2414
2794
  });
2415
2795
  state.stepSpan = stepSpan;
2416
2796
  state.stepParent = this.spanParentRef(stepSpan);
2797
+ state.stepProvider = event.provider;
2798
+ state.stepModelId = event.modelId;
2417
2799
  };
2418
2800
  this.onToolExecutionStart = (event) => this.toolExecutionStart(event);
2419
2801
  this.onToolExecutionEnd = (event) => this.toolExecutionEnd(event);
@@ -2464,23 +2846,24 @@ var RaindropTelemetryIntegration = class {
2464
2846
  var _a, _b, _c, _d, _e, _f, _g, _h, _i;
2465
2847
  const state = this.getState(event.callId);
2466
2848
  if (!(state == null ? void 0 : state.stepSpan)) return;
2849
+ const responseModelId = (_b = (_a = event.response) == null ? void 0 : _a.modelId) != null ? _b : state.stepModelId;
2467
2850
  const outputAttrs = [];
2468
2851
  if (state.recordOutputs) {
2469
2852
  outputAttrs.push(
2470
2853
  attrString("ai.response.finishReason", event.finishReason),
2471
- attrString("ai.response.text", capText2((_a = event.text) != null ? _a : void 0)),
2472
- attrString("ai.response.id", (_b = event.response) == null ? void 0 : _b.id),
2473
- attrString("ai.response.model", (_c = event.response) == null ? void 0 : _c.modelId),
2854
+ attrString("ai.response.text", capText2((_c = event.text) != null ? _c : void 0)),
2855
+ attrString("ai.response.id", (_d = event.response) == null ? void 0 : _d.id),
2856
+ attrString("ai.response.model", responseModelId),
2474
2857
  attrString(
2475
2858
  "ai.response.timestamp",
2476
- ((_d = event.response) == null ? void 0 : _d.timestamp) instanceof Date ? event.response.timestamp.toISOString() : (_e = event.response) == null ? void 0 : _e.timestamp
2859
+ ((_e = event.response) == null ? void 0 : _e.timestamp) instanceof Date ? event.response.timestamp.toISOString() : (_f = event.response) == null ? void 0 : _f.timestamp
2477
2860
  ),
2478
2861
  attrString(
2479
2862
  "ai.response.providerMetadata",
2480
2863
  event.providerMetadata ? safeJsonWithUint8(event.providerMetadata) : void 0
2481
2864
  )
2482
2865
  );
2483
- if (((_f = event.toolCalls) == null ? void 0 : _f.length) > 0) {
2866
+ if (((_g = event.toolCalls) == null ? void 0 : _g.length) > 0) {
2484
2867
  outputAttrs.push(
2485
2868
  attrString(
2486
2869
  "ai.response.toolCalls",
@@ -2494,7 +2877,7 @@ var RaindropTelemetryIntegration = class {
2494
2877
  )
2495
2878
  );
2496
2879
  }
2497
- if (((_g = event.reasoning) == null ? void 0 : _g.length) > 0) {
2880
+ if (((_h = event.reasoning) == null ? void 0 : _h.length) > 0) {
2498
2881
  const reasoningText = event.reasoning.filter((part) => "text" in part).map((part) => part.text).join("\n");
2499
2882
  if (reasoningText) {
2500
2883
  outputAttrs.push(attrString("ai.response.reasoning", capText2(reasoningText)));
@@ -2503,25 +2886,31 @@ var RaindropTelemetryIntegration = class {
2503
2886
  }
2504
2887
  outputAttrs.push(
2505
2888
  attrStringArray("gen_ai.response.finish_reasons", [event.finishReason]),
2506
- attrString("gen_ai.response.id", (_h = event.response) == null ? void 0 : _h.id),
2507
- attrString("gen_ai.response.model", (_i = event.response) == null ? void 0 : _i.modelId)
2889
+ attrString("gen_ai.response.id", (_i = event.response) == null ? void 0 : _i.id),
2890
+ attrString(MODEL_USAGE_ATTRIBUTES.responseModel, responseModelId)
2508
2891
  );
2509
2892
  const usage = event.usage;
2510
2893
  if (usage) {
2894
+ const usageMetrics = extractUsageMetricsFromUsage(
2895
+ usage,
2896
+ state.stepProvider,
2897
+ event.providerMetadata
2898
+ );
2511
2899
  outputAttrs.push(
2512
- attrInt("ai.usage.inputTokens", usage.inputTokens),
2513
- attrInt("ai.usage.outputTokens", usage.outputTokens),
2514
- attrInt("ai.usage.totalTokens", usage.totalTokens),
2515
- attrInt("ai.usage.reasoningTokens", usage.reasoningTokens),
2516
- attrInt("ai.usage.cachedInputTokens", usage.cachedInputTokens),
2517
- attrInt("gen_ai.usage.input_tokens", usage.inputTokens),
2518
- attrInt("gen_ai.usage.output_tokens", usage.outputTokens)
2900
+ attrInt("ai.usage.inputTokens", usageMetrics.inputTokens),
2901
+ attrInt("ai.usage.outputTokens", usageMetrics.outputTokens),
2902
+ attrInt("ai.usage.totalTokens", usageMetrics.totalTokens),
2903
+ attrInt("ai.usage.reasoningTokens", usageMetrics.reasoningTokens),
2904
+ attrInt("ai.usage.cachedInputTokens", usageMetrics.cachedInputTokens),
2905
+ ...buildModelUsageAttributes(usageMetrics)
2519
2906
  );
2520
2907
  }
2521
2908
  this.emitProviderExecutedToolSpans(event, state);
2522
2909
  this.traceShipper.endSpan(state.stepSpan, { attributes: outputAttrs });
2523
2910
  state.stepSpan = void 0;
2524
2911
  state.stepParent = void 0;
2912
+ state.stepProvider = void 0;
2913
+ state.stepModelId = void 0;
2525
2914
  };
2526
2915
  // ── onEmbedStart ────────────────────────────────────────────────────────
2527
2916
  this.onEmbedStart = (event) => {
@@ -2533,6 +2922,7 @@ var RaindropTelemetryIntegration = class {
2533
2922
  name: event.operationId,
2534
2923
  parent: state.rootParent,
2535
2924
  eventId: state.eventId,
2925
+ ...state.identity,
2536
2926
  operationId: event.operationId,
2537
2927
  attributes: [
2538
2928
  attrString("operation.name", operationName),
@@ -2595,6 +2985,8 @@ var RaindropTelemetryIntegration = class {
2595
2985
  const actualError = (_a = event.error) != null ? _a : error;
2596
2986
  if (state.stepSpan) {
2597
2987
  this.traceShipper.endSpan(state.stepSpan, { error: actualError });
2988
+ state.stepProvider = void 0;
2989
+ state.stepModelId = void 0;
2598
2990
  }
2599
2991
  for (const embedSpan of state.embedSpans.values()) {
2600
2992
  this.traceShipper.endSpan(embedSpan, { error: actualError });
@@ -2638,6 +3030,8 @@ var RaindropTelemetryIntegration = class {
2638
3030
  this.traceShipper.endSpan(state.stepSpan, { attributes: [abortedAttr] });
2639
3031
  state.stepSpan = void 0;
2640
3032
  state.stepParent = void 0;
3033
+ state.stepProvider = void 0;
3034
+ state.stepModelId = void 0;
2641
3035
  }
2642
3036
  for (const embedSpan of state.embedSpans.values()) {
2643
3037
  this.traceShipper.endSpan(embedSpan, { attributes: [abortedAttr] });
@@ -2799,6 +3193,7 @@ var RaindropTelemetryIntegration = class {
2799
3193
  name: "ai.toolCall",
2800
3194
  parent: state.stepParent,
2801
3195
  eventId: state.eventId,
3196
+ ...state.identity,
2802
3197
  operationId: "ai.toolCall",
2803
3198
  attributes: [
2804
3199
  attrString("operation.name", operationName),
@@ -2876,6 +3271,7 @@ var RaindropTelemetryIntegration = class {
2876
3271
  name: "ai.toolCall",
2877
3272
  parent: state.stepParent,
2878
3273
  eventId: state.eventId,
3274
+ ...state.identity,
2879
3275
  operationId: "ai.toolCall",
2880
3276
  attributes: [
2881
3277
  attrString("operation.name", operationName),
@@ -2935,12 +3331,13 @@ var RaindropTelemetryIntegration = class {
2935
3331
  }
2936
3332
  const usage = (_d = event.totalUsage) != null ? _d : event.usage;
2937
3333
  if (usage) {
3334
+ const usageMetrics = extractUsageMetricsFromUsage(usage);
2938
3335
  outputAttrs.push(
2939
- attrInt("ai.usage.inputTokens", usage.inputTokens),
2940
- attrInt("ai.usage.outputTokens", usage.outputTokens),
2941
- attrInt("ai.usage.totalTokens", usage.totalTokens),
2942
- attrInt("ai.usage.reasoningTokens", usage.reasoningTokens),
2943
- attrInt("ai.usage.cachedInputTokens", usage.cachedInputTokens)
3336
+ attrInt("ai.usage.inputTokens", usageMetrics.inputTokens),
3337
+ attrInt("ai.usage.outputTokens", usageMetrics.outputTokens),
3338
+ attrInt("ai.usage.totalTokens", usageMetrics.totalTokens),
3339
+ attrInt("ai.usage.reasoningTokens", usageMetrics.reasoningTokens),
3340
+ attrInt("ai.usage.cachedInputTokens", usageMetrics.cachedInputTokens)
2944
3341
  );
2945
3342
  }
2946
3343
  outputAttrs.push(attrInt("ai.toolCall.count", state.toolCallCount));
@@ -3380,14 +3777,6 @@ function runWithParentSpanContextSync(ctx, fn) {
3380
3777
  function isAsyncIterable(value) {
3381
3778
  return value !== null && typeof value === "object" && Symbol.asyncIterator in value;
3382
3779
  }
3383
- function firstFiniteNumber(...values) {
3384
- for (const value of values) {
3385
- if (typeof value === "number" && Number.isFinite(value)) {
3386
- return value;
3387
- }
3388
- }
3389
- return void 0;
3390
- }
3391
3780
  function resolveUsageRecord(result) {
3392
3781
  if (!isRecord(result)) return void 0;
3393
3782
  let usage;
@@ -3403,50 +3792,7 @@ function resolveUsageRecord(result) {
3403
3792
  return isRecord(usage) ? usage : void 0;
3404
3793
  }
3405
3794
  function extractUsageMetrics(result) {
3406
- const usage = resolveUsageRecord(result);
3407
- if (!usage) return {};
3408
- const inputTokenValue = usage["inputTokens"];
3409
- const outputTokenValue = usage["outputTokens"];
3410
- const inputTokens = firstFiniteNumber(
3411
- isRecord(inputTokenValue) ? inputTokenValue["total"] : void 0,
3412
- inputTokenValue,
3413
- usage["promptTokens"],
3414
- usage["prompt_tokens"]
3415
- );
3416
- const outputTokens = firstFiniteNumber(
3417
- isRecord(outputTokenValue) ? outputTokenValue["total"] : void 0,
3418
- outputTokenValue,
3419
- usage["completionTokens"],
3420
- usage["completion_tokens"]
3421
- );
3422
- const totalTokens = firstFiniteNumber(
3423
- usage["totalTokens"],
3424
- usage["tokens"],
3425
- usage["total_tokens"],
3426
- inputTokens !== void 0 && outputTokens !== void 0 ? inputTokens + outputTokens : void 0
3427
- );
3428
- const reasoningTokens = firstFiniteNumber(
3429
- isRecord(outputTokenValue) ? outputTokenValue["reasoning"] : void 0,
3430
- usage["reasoningTokens"],
3431
- usage["completionReasoningTokens"],
3432
- usage["completion_reasoning_tokens"],
3433
- usage["reasoning_tokens"],
3434
- usage["thinkingTokens"],
3435
- usage["thinking_tokens"]
3436
- );
3437
- const cachedInputTokens = firstFiniteNumber(
3438
- isRecord(inputTokenValue) ? inputTokenValue["cacheRead"] : void 0,
3439
- usage["cachedInputTokens"],
3440
- usage["promptCachedTokens"],
3441
- usage["prompt_cached_tokens"]
3442
- );
3443
- return {
3444
- inputTokens,
3445
- outputTokens,
3446
- totalTokens,
3447
- reasoningTokens,
3448
- cachedInputTokens
3449
- };
3795
+ return extractUsageMetricsFromUsage(resolveUsageRecord(result));
3450
3796
  }
3451
3797
  function isObjectOperation(operation) {
3452
3798
  return operation === "generateObject" || operation === "streamObject";
@@ -3530,6 +3876,9 @@ function teeStreamObjectBaseStream(result) {
3530
3876
  } catch (e) {
3531
3877
  }
3532
3878
  }
3879
+ function identityFromContext(ctx) {
3880
+ return { userId: ctx.userId, convoId: ctx.convoId, eventName: ctx.eventName };
3881
+ }
3533
3882
  function setupOperation(params) {
3534
3883
  var _a, _b, _c;
3535
3884
  const {
@@ -3561,6 +3910,7 @@ function setupOperation(params) {
3561
3910
  name: outerOperationId,
3562
3911
  parent: inheritedParent,
3563
3912
  eventId,
3913
+ ...identityFromContext(mergedCtx),
3564
3914
  operationId: outerOperationId,
3565
3915
  attributes: [
3566
3916
  attrString("operation.name", operationName),
@@ -3569,9 +3919,6 @@ function setupOperation(params) {
3569
3919
  attrString("ai.model.provider", modelInfoFromArgs.provider),
3570
3920
  attrString("ai.model.id", modelInfoFromArgs.modelId),
3571
3921
  attrString("ai.telemetry.metadata.raindrop.eventId", eventId),
3572
- attrString("ai.telemetry.metadata.raindrop.eventName", mergedCtx.eventName),
3573
- attrString("ai.telemetry.metadata.raindrop.ai.userId", mergedCtx.userId),
3574
- attrString("ai.telemetry.metadata.raindrop.convoId", mergedCtx.convoId),
3575
3922
  ...attrsFromTelemetryMetadata(telemetry == null ? void 0 : telemetry.metadata),
3576
3923
  ...attrsFromHeaders(isRecord(arg) ? arg["headers"] : void 0),
3577
3924
  ...attrsFromSettings(arg),
@@ -3661,6 +4008,7 @@ function createFinalize(params) {
3661
4008
  responseMessages,
3662
4009
  rootSpan: setup.rootSpan,
3663
4010
  eventId: setup.eventId,
4011
+ ...identityFromContext(setup.ctx),
3664
4012
  telemetry: setup.telemetry,
3665
4013
  toolCalls: setup.toolCalls,
3666
4014
  traceShipper,
@@ -3699,6 +4047,11 @@ function createFinalize(params) {
3699
4047
  input,
3700
4048
  output,
3701
4049
  model: finalModel,
4050
+ usage: {
4051
+ promptTokens: usage == null ? void 0 : usage.inputTokens,
4052
+ completionTokens: usage == null ? void 0 : usage.outputTokens
4053
+ },
4054
+ error,
3702
4055
  properties: patch.properties,
3703
4056
  featureFlags: patch.featureFlags,
3704
4057
  attachments: patch.attachments,
@@ -3733,6 +4086,7 @@ function startToolSpan(toolCall, rootSpan, ctx, startTimeUnixNano) {
3733
4086
  name: "ai.toolCall",
3734
4087
  parent: { traceIdB64: rootSpan.ids.traceIdB64, spanIdB64: rootSpan.ids.spanIdB64 },
3735
4088
  eventId: ctx.eventId,
4089
+ ...identityFromContext(ctx),
3736
4090
  operationId: "ai.toolCall",
3737
4091
  attributes: [
3738
4092
  attrString("operation.name", operationName),
@@ -3770,6 +4124,9 @@ function emitTranscriptToolCallSpans(params) {
3770
4124
  }
3771
4125
  const ctx = {
3772
4126
  eventId: params.eventId,
4127
+ userId: params.userId,
4128
+ convoId: params.convoId,
4129
+ eventName: params.eventName,
3773
4130
  telemetry: params.telemetry,
3774
4131
  traceShipper: params.traceShipper
3775
4132
  };
@@ -4149,6 +4506,7 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
4149
4506
  name: outerOperationId,
4150
4507
  parent: inheritedParent,
4151
4508
  eventId,
4509
+ ...identityFromContext(ctx),
4152
4510
  operationId: outerOperationId,
4153
4511
  attributes: [
4154
4512
  attrString("operation.name", operationName),
@@ -4157,9 +4515,6 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
4157
4515
  attrString("ai.model.provider", modelInfoFromArgs.provider),
4158
4516
  attrString("ai.model.id", modelInfoFromArgs.modelId),
4159
4517
  attrString("ai.telemetry.metadata.raindrop.eventId", eventId),
4160
- attrString("ai.telemetry.metadata.raindrop.eventName", ctx.eventName),
4161
- attrString("ai.telemetry.metadata.raindrop.ai.userId", ctx.userId),
4162
- attrString("ai.telemetry.metadata.raindrop.convoId", ctx.convoId),
4163
4518
  ...attrsFromTelemetryMetadata(telemetry == null ? void 0 : telemetry.metadata),
4164
4519
  ...attrsFromHeaders(mergedArgs["headers"]),
4165
4520
  ...attrsFromSettings(mergedArgs),
@@ -4224,6 +4579,7 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
4224
4579
  responseMessages,
4225
4580
  rootSpan,
4226
4581
  eventId,
4582
+ ...identityFromContext(ctx),
4227
4583
  telemetry,
4228
4584
  toolCalls,
4229
4585
  traceShipper: deps.traceShipper,
@@ -4276,6 +4632,11 @@ function wrapAgentGenerate(generate, instance, agentSettings, className, aiSDK,
4276
4632
  input,
4277
4633
  output,
4278
4634
  model: finalModel,
4635
+ usage: {
4636
+ promptTokens: usage == null ? void 0 : usage.inputTokens,
4637
+ completionTokens: usage == null ? void 0 : usage.outputTokens
4638
+ },
4639
+ error,
4279
4640
  properties: patch.properties,
4280
4641
  featureFlags: patch.featureFlags,
4281
4642
  attachments: patch.attachments,
@@ -4359,6 +4720,7 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
4359
4720
  name: outerOperationId,
4360
4721
  parent: inheritedParent,
4361
4722
  eventId,
4723
+ ...identityFromContext(ctx),
4362
4724
  operationId: outerOperationId,
4363
4725
  attributes: [
4364
4726
  attrString("operation.name", operationName),
@@ -4367,9 +4729,6 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
4367
4729
  attrString("ai.model.provider", modelInfoFromArgs.provider),
4368
4730
  attrString("ai.model.id", modelInfoFromArgs.modelId),
4369
4731
  attrString("ai.telemetry.metadata.raindrop.eventId", eventId),
4370
- attrString("ai.telemetry.metadata.raindrop.eventName", ctx.eventName),
4371
- attrString("ai.telemetry.metadata.raindrop.ai.userId", ctx.userId),
4372
- attrString("ai.telemetry.metadata.raindrop.convoId", ctx.convoId),
4373
4732
  ...attrsFromTelemetryMetadata(telemetry == null ? void 0 : telemetry.metadata),
4374
4733
  ...attrsFromHeaders(mergedArgs["headers"]),
4375
4734
  ...attrsFromSettings(mergedArgs),
@@ -4434,6 +4793,7 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
4434
4793
  responseMessages,
4435
4794
  rootSpan,
4436
4795
  eventId,
4796
+ ...identityFromContext(ctx),
4437
4797
  telemetry,
4438
4798
  toolCalls,
4439
4799
  traceShipper: deps.traceShipper,
@@ -4486,6 +4846,11 @@ function wrapAgentStream(stream, instance, agentSettings, className, aiSDK, deps
4486
4846
  input,
4487
4847
  output,
4488
4848
  model: finalModel,
4849
+ usage: {
4850
+ promptTokens: usage == null ? void 0 : usage.inputTokens,
4851
+ completionTokens: usage == null ? void 0 : usage.outputTokens
4852
+ },
4853
+ error,
4489
4854
  properties: patch.properties,
4490
4855
  featureFlags: patch.featureFlags,
4491
4856
  attachments: patch.attachments,
@@ -4583,6 +4948,7 @@ function wrapToolExecute(name, tool, ctx, toolCalls) {
4583
4948
  name: "ai.toolCall",
4584
4949
  parent,
4585
4950
  eventId: ctx.eventId,
4951
+ ...identityFromContext(ctx.context),
4586
4952
  operationId: "ai.toolCall",
4587
4953
  attributes: [
4588
4954
  attrString("operation.name", operationName),
@@ -4817,8 +5183,13 @@ function wrapModel(args, aiSDK, outerOperationId, ctx) {
4817
5183
  ended = true;
4818
5184
  const msToFirstChunk = firstChunkMs !== void 0 ? firstChunkMs - startMs : void 0;
4819
5185
  const msToFinish = finishMs !== void 0 ? finishMs - startMs : void 0;
4820
- const inputTokens = extractNestedTokens(usage, "inputTokens");
4821
- const outputTokens = extractNestedTokens(usage, "outputTokens");
5186
+ const usageMetrics = extractUsageMetricsFromUsage(
5187
+ usage,
5188
+ modelInfo.provider,
5189
+ providerMetadata
5190
+ );
5191
+ const finalResponseModelId = responseModelId != null ? responseModelId : modelInfo.modelId;
5192
+ const { inputTokens, outputTokens } = usageMetrics;
4822
5193
  const avgOutTokensPerSecond = msToFinish && outputTokens !== void 0 && msToFinish > 0 ? 1e3 * outputTokens / msToFinish : void 0;
4823
5194
  ctx.traceShipper.endSpan(span, {
4824
5195
  attributes: [
@@ -4830,7 +5201,7 @@ function wrapModel(args, aiSDK, outerOperationId, ctx) {
4830
5201
  safeJsonWithUint8(toolCallsLocal.length ? toolCallsLocal : void 0)
4831
5202
  ),
4832
5203
  attrString("ai.response.id", responseId),
4833
- attrString("ai.response.model", responseModelId),
5204
+ attrString("ai.response.model", finalResponseModelId),
4834
5205
  attrString("ai.response.timestamp", responseTimestampIso),
4835
5206
  attrString(
4836
5207
  "ai.response.providerMetadata",
@@ -4841,9 +5212,8 @@ function wrapModel(args, aiSDK, outerOperationId, ctx) {
4841
5212
  attrInt("ai.usage.outputTokens", outputTokens),
4842
5213
  ...finishReason ? [attrStringArray("gen_ai.response.finish_reasons", [finishReason])] : [],
4843
5214
  attrString("gen_ai.response.id", responseId),
4844
- attrString("gen_ai.response.model", responseModelId),
4845
- attrInt("gen_ai.usage.input_tokens", inputTokens),
4846
- attrInt("gen_ai.usage.output_tokens", outputTokens),
5215
+ attrString(MODEL_USAGE_ATTRIBUTES.responseModel, finalResponseModelId),
5216
+ ...buildModelUsageAttributes(usageMetrics),
4847
5217
  ...msToFirstChunk !== void 0 ? [attrInt("ai.stream.msToFirstChunk", msToFirstChunk)] : [],
4848
5218
  ...msToFinish !== void 0 ? [attrInt("ai.stream.msToFinish", msToFinish)] : [],
4849
5219
  ...avgOutTokensPerSecond !== void 0 ? [attrDouble("ai.stream.avgOutputTokensPerSecond", avgOutTokensPerSecond)] : [],
@@ -4943,20 +5313,20 @@ function startDoGenerateSpan(operationId, options, modelInfo, parent, ctx) {
4943
5313
  name: operationId,
4944
5314
  parent,
4945
5315
  eventId: ctx.eventId,
5316
+ ...identityFromContext(ctx.context),
4946
5317
  operationId,
4947
5318
  attributes: [
4948
5319
  attrString("operation.name", operationName),
4949
5320
  attrString("resource.name", resourceName),
4950
5321
  attrString("ai.telemetry.functionId", (_b = ctx.telemetry) == null ? void 0 : _b.functionId),
4951
- attrString("ai.model.provider", modelInfo.provider),
5322
+ ...attrsFromModelProvider(modelInfo.provider),
4952
5323
  attrString("ai.model.id", modelInfo.modelId),
4953
5324
  ...((_c = ctx.telemetry) == null ? void 0 : _c.recordInputs) === false ? [] : [
4954
5325
  attrString("ai.prompt.messages", promptJson),
4955
5326
  attrStringArray("ai.prompt.tools", toolsJson),
4956
5327
  attrString("ai.prompt.toolChoice", toolChoiceJson)
4957
5328
  ],
4958
- attrString("gen_ai.system", modelInfo.provider),
4959
- attrString("gen_ai.request.model", modelInfo.modelId),
5329
+ attrString(MODEL_USAGE_ATTRIBUTES.requestModel, modelInfo.modelId),
4960
5330
  ...attrsFromGenAiRequest(options),
4961
5331
  attrProviderOptions(options)
4962
5332
  ]
@@ -4989,8 +5359,12 @@ function endDoGenerateSpan(span, result, modelInfo, ctx) {
4989
5359
  } else {
4990
5360
  responseTimestampIso = (/* @__PURE__ */ new Date()).toISOString();
4991
5361
  }
4992
- const inputTokens = extractNestedTokens(usage, "inputTokens");
4993
- const outputTokens = extractNestedTokens(usage, "outputTokens");
5362
+ const usageMetrics = extractUsageMetricsFromUsage(
5363
+ usage,
5364
+ modelInfo.provider,
5365
+ providerMetadata
5366
+ );
5367
+ const { inputTokens, outputTokens } = usageMetrics;
4994
5368
  ctx.traceShipper.endSpan(span, {
4995
5369
  attributes: [
4996
5370
  ...((_a = ctx.telemetry) == null ? void 0 : _a.recordOutputs) === false ? [] : [
@@ -5009,9 +5383,8 @@ function endDoGenerateSpan(span, result, modelInfo, ctx) {
5009
5383
  attrInt("ai.usage.completionTokens", outputTokens),
5010
5384
  ...finishReason ? [attrStringArray("gen_ai.response.finish_reasons", [finishReason])] : [],
5011
5385
  attrString("gen_ai.response.id", responseId),
5012
- attrString("gen_ai.response.model", responseModelId),
5013
- attrInt("gen_ai.usage.input_tokens", inputTokens),
5014
- attrInt("gen_ai.usage.output_tokens", outputTokens)
5386
+ attrString(MODEL_USAGE_ATTRIBUTES.responseModel, responseModelId),
5387
+ ...buildModelUsageAttributes(usageMetrics)
5015
5388
  ]
5016
5389
  });
5017
5390
  }
@@ -5026,20 +5399,20 @@ function startDoStreamSpan(operationId, options, modelInfo, parent, ctx) {
5026
5399
  name: operationId,
5027
5400
  parent,
5028
5401
  eventId: ctx.eventId,
5402
+ ...identityFromContext(ctx.context),
5029
5403
  operationId,
5030
5404
  attributes: [
5031
5405
  attrString("operation.name", operationName),
5032
5406
  attrString("resource.name", resourceName),
5033
5407
  attrString("ai.telemetry.functionId", (_b = ctx.telemetry) == null ? void 0 : _b.functionId),
5034
- attrString("ai.model.provider", modelInfo.provider),
5408
+ ...attrsFromModelProvider(modelInfo.provider),
5035
5409
  attrString("ai.model.id", modelInfo.modelId),
5036
5410
  ...((_c = ctx.telemetry) == null ? void 0 : _c.recordInputs) === false ? [] : [
5037
5411
  attrString("ai.prompt.messages", promptJson),
5038
5412
  attrStringArray("ai.prompt.tools", toolsJson),
5039
5413
  attrString("ai.prompt.toolChoice", toolChoiceJson)
5040
5414
  ],
5041
- attrString("gen_ai.system", modelInfo.provider),
5042
- attrString("gen_ai.request.model", modelInfo.modelId),
5415
+ attrString(MODEL_USAGE_ATTRIBUTES.requestModel, modelInfo.modelId),
5043
5416
  ...attrsFromGenAiRequest(options),
5044
5417
  attrProviderOptions(options)
5045
5418
  ]
@@ -5104,18 +5477,11 @@ function mergeAttachments(...groups) {
5104
5477
  }
5105
5478
  return merged.length ? merged : void 0;
5106
5479
  }
5107
- function extractNestedTokens(usage, key) {
5108
- if (!isRecord(usage)) return void 0;
5109
- const val = usage[key];
5110
- if (typeof val === "number") return val;
5111
- if (isRecord(val) && typeof val["total"] === "number") return val["total"];
5112
- return void 0;
5113
- }
5114
5480
 
5115
5481
  // package.json
5116
5482
  var package_default = {
5117
5483
  name: "@raindrop-ai/ai-sdk",
5118
- version: "0.1.1"};
5484
+ version: "0.2.1"};
5119
5485
 
5120
5486
  // src/internal/version.ts
5121
5487
  var libraryName = package_default.name;
@@ -5321,6 +5687,9 @@ function createRaindropAISDK(opts) {
5321
5687
  const internal = traceShipper.startSpan({
5322
5688
  name: args.name,
5323
5689
  eventId: args.eventId,
5690
+ userId: args.userId,
5691
+ convoId: args.convoId,
5692
+ eventName: args.eventName,
5324
5693
  parent,
5325
5694
  operationId: args.operationId,
5326
5695
  attributes: attrs
@@ -5355,6 +5724,9 @@ function createRaindropAISDK(opts) {
5355
5724
  const internal = traceShipper.startSpan({
5356
5725
  name: args.name,
5357
5726
  eventId: args.eventId,
5727
+ userId: args.userId,
5728
+ convoId: args.convoId,
5729
+ eventName: args.eventName,
5358
5730
  parent,
5359
5731
  operationId: args.operationId,
5360
5732
  attributes: startAttrs,