@raindrop-ai/pi-agent 0.0.10 → 0.1.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,4 +1,4 @@
1
- // ../core/dist/chunk-267IXHO5.js
1
+ // ../core/dist/chunk-YUIXRQWN.js
2
2
  function getCrypto() {
3
3
  const c = globalThis.crypto;
4
4
  return c;
@@ -56,6 +56,20 @@ function base64Encode(bytes) {
56
56
  function generateId() {
57
57
  return randomUUID();
58
58
  }
59
+ var HANDOFF_ATTRIBUTE_SUFFIXES = {
60
+ mode: "raindrop.handoff.mode",
61
+ childEventId: "raindrop.handoff.childEventId",
62
+ parentEventId: "raindrop.handoff.parentEventId",
63
+ parentSpanId: "raindrop.handoff.parentSpanId",
64
+ name: "raindrop.handoff.name",
65
+ terminal: "raindrop.handoff.terminal",
66
+ agentRole: "raindrop.agent.role"
67
+ };
68
+ var HANDOFF_TERMINAL_PROPERTY_KEY = HANDOFF_ATTRIBUTE_SUFFIXES.terminal;
69
+ var TRACEPARENT_HEADER = "traceparent";
70
+ var BAGGAGE_HEADER = "baggage";
71
+ var HANDOFF_HEADER = "x-raindrop-handoff";
72
+ var UNRESOLVED_CARRIER_WARNING = `[raindrop] resume: headers were supplied but no hand-off carrier was found on them (searched ${HANDOFF_HEADER}, ${TRACEPARENT_HEADER}, ${BAGGAGE_HEADER}). This run reports as an UNLINKED event, and the launcher that dispatched it will stay on "queued" forever because nothing ever references its child. Passing headers means a parent handed off, so no carrier on them is almost certainly a defect: a gateway or proxy stripping ${HANDOFF_HEADER}, a middleware overwriting ${BAGGAGE_HEADER}, a request forwarded without its headers, or a hand-built carrier whose field names do not match. Send every header the launcher's dispatch returned. Logged once per process; pass no headers for a directly-invoked sub-agent to silence it.`;
59
73
  function runWithTracingSuppressed(fn) {
60
74
  const hook = globalThis.RAINDROP_SUPPRESS_TRACING;
61
75
  if (typeof hook !== "function") return fn();
@@ -391,19 +405,52 @@ function projectIdHeaders(projectId) {
391
405
  var SHUTDOWN_DEADLINE_MS = 1e4;
392
406
  var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
393
407
  function mergePatches(target, source) {
394
- var _a, _b, _c, _d, _e, _f;
408
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
395
409
  const out = { ...target, ...source };
396
410
  if (target.properties || source.properties) {
397
411
  out.properties = { ...(_a = target.properties) != null ? _a : {}, ...(_b = source.properties) != null ? _b : {} };
398
412
  }
413
+ if (target.usage || source.usage) {
414
+ out.usage = { ...(_c = target.usage) != null ? _c : {} };
415
+ if (((_d = source.usage) == null ? void 0 : _d.promptTokens) !== void 0) {
416
+ out.usage.promptTokens = source.usage.promptTokens;
417
+ }
418
+ if (((_e = source.usage) == null ? void 0 : _e.completionTokens) !== void 0) {
419
+ out.usage.completionTokens = source.usage.completionTokens;
420
+ }
421
+ }
422
+ if (source.error === void 0) {
423
+ out.error = target.error;
424
+ }
399
425
  if (target.featureFlags || source.featureFlags) {
400
- out.featureFlags = { ...(_c = target.featureFlags) != null ? _c : {}, ...(_d = source.featureFlags) != null ? _d : {} };
426
+ out.featureFlags = { ...(_f = target.featureFlags) != null ? _f : {}, ...(_g = source.featureFlags) != null ? _g : {} };
401
427
  }
402
428
  if (target.attachments || source.attachments) {
403
- out.attachments = [...(_e = target.attachments) != null ? _e : [], ...(_f = source.attachments) != null ? _f : []];
429
+ out.attachments = [...(_h = target.attachments) != null ? _h : [], ...(_i = source.attachments) != null ? _i : []];
404
430
  }
405
431
  return out;
406
432
  }
433
+ function isErrorLike(value) {
434
+ return value !== null && typeof value === "object";
435
+ }
436
+ function eventTelemetryProperties(patch) {
437
+ var _a, _b;
438
+ const properties = {};
439
+ if (((_a = patch.usage) == null ? void 0 : _a.promptTokens) !== void 0 && Number.isFinite(patch.usage.promptTokens)) {
440
+ properties["ai.usage.prompt_tokens"] = patch.usage.promptTokens;
441
+ }
442
+ if (((_b = patch.usage) == null ? void 0 : _b.completionTokens) !== void 0 && Number.isFinite(patch.usage.completionTokens)) {
443
+ properties["ai.usage.completion_tokens"] = patch.usage.completionTokens;
444
+ }
445
+ if (patch.error !== void 0 && patch.error !== null) {
446
+ const constructorName = patch.error instanceof Error && patch.error.constructor !== Error ? patch.error.constructor.name : void 0;
447
+ 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";
448
+ const errorMessage = patch.error instanceof Error ? patch.error.message : isErrorLike(patch.error) && typeof patch.error.message === "string" ? patch.error.message : String(patch.error);
449
+ properties["error.type"] = errorType;
450
+ properties["error.message"] = errorMessage;
451
+ }
452
+ return properties;
453
+ }
407
454
  var EventShipper = class {
408
455
  constructor(opts) {
409
456
  this.buffers = /* @__PURE__ */ new Map();
@@ -652,6 +699,11 @@ var EventShipper = class {
652
699
  return;
653
700
  }
654
701
  const { wizardSession, ...restProperties } = (_e = accumulated.properties) != null ? _e : {};
702
+ let telemetryProperties = {};
703
+ try {
704
+ telemetryProperties = eventTelemetryProperties(accumulated);
705
+ } catch (e) {
706
+ }
655
707
  const convoId = (_f = accumulated.convoId) != null ? _f : sticky.convoId;
656
708
  const isPending = (_h = (_g = accumulated.isPending) != null ? _g : sticky.isPending) != null ? _h : true;
657
709
  const payload = {
@@ -661,12 +713,13 @@ var EventShipper = class {
661
713
  timestamp: (_i = accumulated.timestamp) != null ? _i : (/* @__PURE__ */ new Date()).toISOString(),
662
714
  ai_data: {
663
715
  input: accumulated.input,
664
- output: accumulated.output,
716
+ output: accumulated.error !== void 0 && accumulated.error !== null ? void 0 : accumulated.output,
665
717
  model: accumulated.model,
666
718
  convo_id: convoId
667
719
  },
668
720
  properties: {
669
721
  ...restProperties,
722
+ ...telemetryProperties,
670
723
  ...wizardSession ? { "raindrop.wizardSession": wizardSession } : {},
671
724
  $context: this.context
672
725
  },
@@ -735,6 +788,194 @@ var EventShipper = class {
735
788
  }
736
789
  }
737
790
  };
791
+ var MODEL_USAGE_ATTRIBUTES = {
792
+ providerName: "gen_ai.provider.name",
793
+ requestModel: "gen_ai.request.model",
794
+ responseModel: "gen_ai.response.model",
795
+ inputTokens: "gen_ai.usage.input_tokens",
796
+ outputTokens: "gen_ai.usage.output_tokens",
797
+ reasoningTokens: "gen_ai.usage.reasoning_tokens",
798
+ cacheReadInputTokens: "gen_ai.usage.cache_read_input_tokens",
799
+ cacheWriteInputTokens: "gen_ai.usage.cache_write_input_tokens",
800
+ nonCachedInputTokens: "raindrop.usage.input_tokens.non_cached",
801
+ nonReasoningOutputTokens: "raindrop.usage.output_tokens.non_reasoning",
802
+ totalOutputTokens: "raindrop.usage.output_tokens.total",
803
+ reasoningOutputTokens: "raindrop.usage.output_tokens.reasoning",
804
+ cacheReadTokens: "raindrop.usage.input_tokens.cache_read",
805
+ cacheWriteTokens: "raindrop.usage.input_tokens.cache_write"
806
+ };
807
+ var MODEL_PROVIDER_NAMES = [
808
+ ["google.vertex", "google-vertex"],
809
+ ["vertex.anthropic", "google-vertex"],
810
+ ["amazon-bedrock", "amazon-bedrock"],
811
+ ["bedrock", "amazon-bedrock"],
812
+ ["anthropic", "anthropic"],
813
+ ["openai", "openai"],
814
+ ["google", "google"],
815
+ ["azure", "azure"],
816
+ ["openrouter", "openrouter"]
817
+ ];
818
+ function canonicalModelProvider(provider) {
819
+ var _a;
820
+ const normalizedProvider = provider.trim().toLowerCase();
821
+ if (normalizedProvider === "gateway") return "vercel";
822
+ const match = MODEL_PROVIDER_NAMES.find(
823
+ ([family]) => normalizedProvider === family || normalizedProvider.startsWith(`${family}.`)
824
+ );
825
+ return (_a = match == null ? void 0 : match[1]) != null ? _a : provider;
826
+ }
827
+ function tokenCount(value) {
828
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
829
+ }
830
+ function exclusiveTokens({
831
+ explicit,
832
+ total,
833
+ parts,
834
+ semantics
835
+ }) {
836
+ if (explicit !== void 0) return explicit;
837
+ if (total === void 0) return void 0;
838
+ if (semantics === "exclusive") return total;
839
+ const observedParts = parts.filter((part) => part !== void 0 && part > 0);
840
+ if (semantics === void 0 && observedParts.length > 0) return void 0;
841
+ const exclusive = total - observedParts.reduce((sum, part) => sum + part, 0);
842
+ return exclusive >= 0 ? exclusive : void 0;
843
+ }
844
+ function buildModelUsageAttributes(usage) {
845
+ const inputTokens = tokenCount(usage.inputTokens);
846
+ const outputTokens = tokenCount(usage.outputTokens);
847
+ const explicitNonCachedInputTokens = tokenCount(usage.nonCachedInputTokens);
848
+ const explicitNonReasoningOutputTokens = tokenCount(usage.nonReasoningOutputTokens);
849
+ const reasoningTokens = tokenCount(usage.reasoningTokens);
850
+ const cacheReadInputTokens = tokenCount(usage.cacheReadInputTokens);
851
+ const cacheWriteInputTokens = tokenCount(usage.cacheWriteInputTokens);
852
+ const nonCachedInputTokens = exclusiveTokens({
853
+ explicit: explicitNonCachedInputTokens,
854
+ total: inputTokens,
855
+ parts: [cacheReadInputTokens, cacheWriteInputTokens],
856
+ semantics: usage.inputTokenSemantics
857
+ });
858
+ const nonReasoningOutputTokens = exclusiveTokens({
859
+ explicit: explicitNonReasoningOutputTokens,
860
+ total: outputTokens,
861
+ parts: [reasoningTokens],
862
+ semantics: usage.outputTokenSemantics
863
+ });
864
+ const exclusivePoolAttributes = nonCachedInputTokens !== void 0 && nonReasoningOutputTokens !== void 0 ? [
865
+ // backend consumes this complete raindrop.* set as one atomic billing-pool contract.
866
+ attrInt(MODEL_USAGE_ATTRIBUTES.nonCachedInputTokens, nonCachedInputTokens),
867
+ attrInt(MODEL_USAGE_ATTRIBUTES.nonReasoningOutputTokens, nonReasoningOutputTokens),
868
+ attrInt(MODEL_USAGE_ATTRIBUTES.reasoningOutputTokens, reasoningTokens),
869
+ attrInt(MODEL_USAGE_ATTRIBUTES.cacheReadTokens, cacheReadInputTokens),
870
+ attrInt(MODEL_USAGE_ATTRIBUTES.cacheWriteTokens, cacheWriteInputTokens)
871
+ ] : [];
872
+ return [
873
+ attrInt(MODEL_USAGE_ATTRIBUTES.inputTokens, inputTokens),
874
+ attrInt(MODEL_USAGE_ATTRIBUTES.outputTokens, outputTokens),
875
+ attrInt(MODEL_USAGE_ATTRIBUTES.reasoningTokens, reasoningTokens),
876
+ attrInt(MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens, cacheReadInputTokens),
877
+ attrInt(MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens, cacheWriteInputTokens),
878
+ ...exclusivePoolAttributes
879
+ ].filter((attribute) => attribute !== void 0);
880
+ }
881
+ var STRING_ALIASES = {
882
+ [MODEL_USAGE_ATTRIBUTES.requestModel]: ["ai.model.id", "ai.model"]
883
+ };
884
+ var NUMBER_ALIASES = {
885
+ [MODEL_USAGE_ATTRIBUTES.inputTokens]: [
886
+ "gen_ai.usage.prompt_tokens",
887
+ "ai.usage.prompt_tokens",
888
+ "ai.usage.promptTokens",
889
+ "ai.usage.input_tokens",
890
+ "ai.usage.inputTokens"
891
+ ],
892
+ [MODEL_USAGE_ATTRIBUTES.outputTokens]: [
893
+ "gen_ai.usage.completion_tokens",
894
+ "ai.usage.completion_tokens",
895
+ "ai.usage.completionTokens",
896
+ "ai.usage.output_tokens",
897
+ "ai.usage.outputTokens"
898
+ ],
899
+ [MODEL_USAGE_ATTRIBUTES.reasoningTokens]: [
900
+ "gen_ai.usage.reasoning.output_tokens",
901
+ "ai.usage.reasoningTokens",
902
+ "ai.usage.thoughts_tokens"
903
+ ],
904
+ [MODEL_USAGE_ATTRIBUTES.cacheReadInputTokens]: [
905
+ "gen_ai.usage.cache_read_tokens",
906
+ "gen_ai.usage.cache_read.input_tokens",
907
+ "ai.usage.cachedInputTokens",
908
+ "ai.usage.cached_tokens",
909
+ "ai.usage.cache_read_tokens",
910
+ "ai.usage.cache_read_input_tokens",
911
+ "ai.usage.cacheReadInputTokens"
912
+ ],
913
+ [MODEL_USAGE_ATTRIBUTES.cacheWriteInputTokens]: [
914
+ "gen_ai.usage.cache_creation_input_tokens",
915
+ "gen_ai.usage.cache_creation.input_tokens",
916
+ "ai.usage.cacheWriteInputTokens",
917
+ "ai.usage.cache_creation_input_tokens",
918
+ "ai.usage.cacheCreationInputTokens"
919
+ ]
920
+ };
921
+ function hasAttribute(attributes, key) {
922
+ return attributes.some((attribute) => attribute.key === key);
923
+ }
924
+ function findStringAttribute(attributes, keys) {
925
+ return attributes.find(
926
+ (attribute) => keys.includes(attribute.key) && typeof attribute.value.stringValue === "string" && attribute.value.stringValue.length > 0
927
+ );
928
+ }
929
+ function findNumberAttribute(attributes, keys) {
930
+ return attributes.find((attribute) => {
931
+ if (!keys.includes(attribute.key)) return false;
932
+ if (typeof attribute.value.doubleValue === "number" && Number.isSafeInteger(attribute.value.doubleValue) && attribute.value.doubleValue >= 0) {
933
+ return true;
934
+ }
935
+ const intValue = attribute.value.intValue;
936
+ return integerValue(intValue) !== void 0;
937
+ });
938
+ }
939
+ function integerValue(value) {
940
+ if (typeof value === "number") {
941
+ return Number.isSafeInteger(value) && value >= 0 ? value : void 0;
942
+ }
943
+ if (typeof value !== "string") return void 0;
944
+ const parsed = Number(value);
945
+ return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : void 0;
946
+ }
947
+ function appendAlias(attributes, target, source) {
948
+ if (!source || hasAttribute(attributes, target)) return attributes;
949
+ return [...attributes, { key: target, value: { ...source.value } }];
950
+ }
951
+ function appendProviderAlias(attributes) {
952
+ if (hasAttribute(attributes, MODEL_USAGE_ATTRIBUTES.providerName)) return attributes;
953
+ const source = findStringAttribute(attributes, ["gen_ai.system", "ai.model.provider"]);
954
+ if (!(source == null ? void 0 : source.value.stringValue)) return attributes;
955
+ const attribute = attrString(
956
+ MODEL_USAGE_ATTRIBUTES.providerName,
957
+ canonicalModelProvider(source.value.stringValue)
958
+ );
959
+ return attribute ? [...attributes, attribute] : attributes;
960
+ }
961
+ function normalizeModelUsageSpan(span) {
962
+ const original = span.attributes;
963
+ if (!original || original.length === 0) return span;
964
+ const responseModel = findStringAttribute(original, [
965
+ MODEL_USAGE_ATTRIBUTES.responseModel,
966
+ "ai.response.model"
967
+ ]);
968
+ if (!responseModel) return span;
969
+ let attributes = appendAlias(original, MODEL_USAGE_ATTRIBUTES.responseModel, responseModel);
970
+ attributes = appendProviderAlias(attributes);
971
+ for (const [target, aliases] of Object.entries(STRING_ALIASES)) {
972
+ attributes = appendAlias(attributes, target, findStringAttribute(attributes, aliases));
973
+ }
974
+ for (const [target, aliases] of Object.entries(NUMBER_ALIASES)) {
975
+ attributes = appendAlias(attributes, target, findNumberAttribute(attributes, aliases));
976
+ }
977
+ return attributes === original ? span : { ...span, attributes };
978
+ }
738
979
  var DEFAULT_SECRET_KEY_NAMES = [
739
980
  "apikey",
740
981
  "apisecret",
@@ -824,6 +1065,13 @@ function redactJsonAttributeValue(key, value) {
824
1065
  if (scrubbedJson === json) return void 0;
825
1066
  return { stringValue: scrubbedJson };
826
1067
  }
1068
+ function identityAttrs(args) {
1069
+ return [
1070
+ attrString("ai.telemetry.metadata.raindrop.ai.userId", args.userId),
1071
+ attrString("ai.telemetry.metadata.raindrop.convoId", args.convoId),
1072
+ attrString("ai.telemetry.metadata.raindrop.eventName", args.eventName)
1073
+ ];
1074
+ }
827
1075
  function applyOtelSpanAttributeLimit(limit) {
828
1076
  var _a, _b;
829
1077
  try {
@@ -928,6 +1176,10 @@ var TraceShipper = class {
928
1176
  return null;
929
1177
  }
930
1178
  }
1179
+ try {
1180
+ current = normalizeModelUsageSpan(current);
1181
+ } catch (e) {
1182
+ }
931
1183
  if (!this.disableDefaultRedaction) {
932
1184
  current = defaultTransformSpan(current);
933
1185
  }
@@ -948,6 +1200,7 @@ var TraceShipper = class {
948
1200
  const started = (_a = args.startTimeUnixNano) != null ? _a : nowUnixNanoString();
949
1201
  const attrs = [
950
1202
  attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
1203
+ ...identityAttrs(args),
951
1204
  attrString("ai.operationId", args.operationId)
952
1205
  ];
953
1206
  if ((_b = args.attributes) == null ? void 0 : _b.length) attrs.push(...args.attributes);
@@ -1003,7 +1256,8 @@ var TraceShipper = class {
1003
1256
  var _a;
1004
1257
  const ids = createSpanIds(args.parent);
1005
1258
  const attrs = [
1006
- attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId)
1259
+ attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
1260
+ ...identityAttrs(args)
1007
1261
  ];
1008
1262
  if ((_a = args.attributes) == null ? void 0 : _a.length) attrs.push(...args.attributes);
1009
1263
  const otlp = buildOtlpSpan({
@@ -1171,7 +1425,7 @@ installTracingSuppressionHook();
1171
1425
  // package.json
1172
1426
  var package_default = {
1173
1427
  name: "@raindrop-ai/pi-agent",
1174
- version: "0.0.10",
1428
+ version: "0.1.1",
1175
1429
  description: "Raindrop observability for Pi Agent \u2014 automatic tracing via subscriber or pi-coding-agent extension",
1176
1430
  type: "module",
1177
1431
  license: "MIT",
@@ -1326,9 +1580,22 @@ function extractTokenUsage(message) {
1326
1580
  return {
1327
1581
  input: usage.input,
1328
1582
  output: usage.output,
1329
- ...typeof usage.cacheRead === "number" && usage.cacheRead > 0 ? { cacheRead: usage.cacheRead } : {}
1583
+ cacheRead: typeof usage.cacheRead === "number" ? usage.cacheRead : 0,
1584
+ cacheWrite: typeof usage.cacheWrite === "number" ? usage.cacheWrite : 0
1330
1585
  };
1331
1586
  }
1587
+ function modelSpendSpanAttributes(input) {
1588
+ const providerAttr = input.provider ? attrString("gen_ai.provider.name", canonicalModelProvider(input.provider)) : void 0;
1589
+ const usageAttrs = input.usage ? buildModelUsageAttributes({
1590
+ inputTokens: input.usage.input,
1591
+ outputTokens: input.usage.output,
1592
+ cacheReadInputTokens: input.usage.cacheRead,
1593
+ cacheWriteInputTokens: input.usage.cacheWrite,
1594
+ reasoningTokens: 0,
1595
+ inputTokenSemantics: "exclusive"
1596
+ }) : [];
1597
+ return providerAttr ? [providerAttr, ...usageAttrs] : usageAttrs;
1598
+ }
1332
1599
  function extractAssistantText(message) {
1333
1600
  if (!("role" in message) || message.role !== "assistant") return void 0;
1334
1601
  if (!Array.isArray(message.content)) return void 0;
@@ -1482,6 +1749,7 @@ export {
1482
1749
  extractUserText,
1483
1750
  extractModelName,
1484
1751
  extractTokenUsage,
1752
+ modelSpendSpanAttributes,
1485
1753
  extractAssistantText,
1486
1754
  extractToolCallIds,
1487
1755
  formatToolSpanName,