@raindrop-ai/pi-agent 0.0.9 → 0.1.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,4 +1,4 @@
1
- // ../core/dist/chunk-WKRW55KX.js
1
+ // ../core/dist/chunk-QTUH3BHZ.js
2
2
  function getCrypto() {
3
3
  const c = globalThis.crypto;
4
4
  return c;
@@ -54,7 +54,7 @@ function base64Encode(bytes) {
54
54
  return out;
55
55
  }
56
56
  function generateId() {
57
- return base64Encode(randomBytes(12)).replace(/[+/=]/g, "").slice(0, 16);
57
+ return randomUUID();
58
58
  }
59
59
  function runWithTracingSuppressed(fn) {
60
60
  const hook = globalThis.RAINDROP_SUPPRESS_TRACING;
@@ -391,16 +391,52 @@ function projectIdHeaders(projectId) {
391
391
  var SHUTDOWN_DEADLINE_MS = 1e4;
392
392
  var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
393
393
  function mergePatches(target, source) {
394
- var _a, _b, _c, _d;
394
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
395
395
  const out = { ...target, ...source };
396
396
  if (target.properties || source.properties) {
397
397
  out.properties = { ...(_a = target.properties) != null ? _a : {}, ...(_b = source.properties) != null ? _b : {} };
398
398
  }
399
+ if (target.usage || source.usage) {
400
+ out.usage = { ...(_c = target.usage) != null ? _c : {} };
401
+ if (((_d = source.usage) == null ? void 0 : _d.promptTokens) !== void 0) {
402
+ out.usage.promptTokens = source.usage.promptTokens;
403
+ }
404
+ if (((_e = source.usage) == null ? void 0 : _e.completionTokens) !== void 0) {
405
+ out.usage.completionTokens = source.usage.completionTokens;
406
+ }
407
+ }
408
+ if (source.error === void 0) {
409
+ out.error = target.error;
410
+ }
411
+ if (target.featureFlags || source.featureFlags) {
412
+ out.featureFlags = { ...(_f = target.featureFlags) != null ? _f : {}, ...(_g = source.featureFlags) != null ? _g : {} };
413
+ }
399
414
  if (target.attachments || source.attachments) {
400
- out.attachments = [...(_c = target.attachments) != null ? _c : [], ...(_d = source.attachments) != null ? _d : []];
415
+ out.attachments = [...(_h = target.attachments) != null ? _h : [], ...(_i = source.attachments) != null ? _i : []];
401
416
  }
402
417
  return out;
403
418
  }
419
+ function isErrorLike(value) {
420
+ return value !== null && typeof value === "object";
421
+ }
422
+ function eventTelemetryProperties(patch) {
423
+ var _a, _b;
424
+ const properties = {};
425
+ if (((_a = patch.usage) == null ? void 0 : _a.promptTokens) !== void 0 && Number.isFinite(patch.usage.promptTokens)) {
426
+ properties["ai.usage.prompt_tokens"] = patch.usage.promptTokens;
427
+ }
428
+ if (((_b = patch.usage) == null ? void 0 : _b.completionTokens) !== void 0 && Number.isFinite(patch.usage.completionTokens)) {
429
+ properties["ai.usage.completion_tokens"] = patch.usage.completionTokens;
430
+ }
431
+ if (patch.error !== void 0 && patch.error !== null) {
432
+ const constructorName = patch.error instanceof Error && patch.error.constructor !== Error ? patch.error.constructor.name : void 0;
433
+ 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";
434
+ const errorMessage = patch.error instanceof Error ? patch.error.message : isErrorLike(patch.error) && typeof patch.error.message === "string" ? patch.error.message : String(patch.error);
435
+ properties["error.type"] = errorType;
436
+ properties["error.message"] = errorMessage;
437
+ }
438
+ return properties;
439
+ }
404
440
  var EventShipper = class {
405
441
  constructor(opts) {
406
442
  this.buffers = /* @__PURE__ */ new Map();
@@ -649,6 +685,11 @@ var EventShipper = class {
649
685
  return;
650
686
  }
651
687
  const { wizardSession, ...restProperties } = (_e = accumulated.properties) != null ? _e : {};
688
+ let telemetryProperties = {};
689
+ try {
690
+ telemetryProperties = eventTelemetryProperties(accumulated);
691
+ } catch (e) {
692
+ }
652
693
  const convoId = (_f = accumulated.convoId) != null ? _f : sticky.convoId;
653
694
  const isPending = (_h = (_g = accumulated.isPending) != null ? _g : sticky.isPending) != null ? _h : true;
654
695
  const payload = {
@@ -658,15 +699,17 @@ var EventShipper = class {
658
699
  timestamp: (_i = accumulated.timestamp) != null ? _i : (/* @__PURE__ */ new Date()).toISOString(),
659
700
  ai_data: {
660
701
  input: accumulated.input,
661
- output: accumulated.output,
702
+ output: accumulated.error !== void 0 && accumulated.error !== null ? void 0 : accumulated.output,
662
703
  model: accumulated.model,
663
704
  convo_id: convoId
664
705
  },
665
706
  properties: {
666
707
  ...restProperties,
708
+ ...telemetryProperties,
667
709
  ...wizardSession ? { "raindrop.wizardSession": wizardSession } : {},
668
710
  $context: this.context
669
711
  },
712
+ ...accumulated.featureFlags && Object.keys(accumulated.featureFlags).length > 0 ? { feature_flags: accumulated.featureFlags } : {},
670
713
  attachments: accumulated.attachments,
671
714
  is_pending: isPending
672
715
  };
@@ -820,6 +863,13 @@ function redactJsonAttributeValue(key, value) {
820
863
  if (scrubbedJson === json) return void 0;
821
864
  return { stringValue: scrubbedJson };
822
865
  }
866
+ function identityAttrs(args) {
867
+ return [
868
+ attrString("ai.telemetry.metadata.raindrop.ai.userId", args.userId),
869
+ attrString("ai.telemetry.metadata.raindrop.convoId", args.convoId),
870
+ attrString("ai.telemetry.metadata.raindrop.eventName", args.eventName)
871
+ ];
872
+ }
823
873
  function applyOtelSpanAttributeLimit(limit) {
824
874
  var _a, _b;
825
875
  try {
@@ -944,6 +994,7 @@ var TraceShipper = class {
944
994
  const started = (_a = args.startTimeUnixNano) != null ? _a : nowUnixNanoString();
945
995
  const attrs = [
946
996
  attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
997
+ ...identityAttrs(args),
947
998
  attrString("ai.operationId", args.operationId)
948
999
  ];
949
1000
  if ((_b = args.attributes) == null ? void 0 : _b.length) attrs.push(...args.attributes);
@@ -999,7 +1050,8 @@ var TraceShipper = class {
999
1050
  var _a;
1000
1051
  const ids = createSpanIds(args.parent);
1001
1052
  const attrs = [
1002
- attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId)
1053
+ attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
1054
+ ...identityAttrs(args)
1003
1055
  ];
1004
1056
  if ((_a = args.attributes) == null ? void 0 : _a.length) attrs.push(...args.attributes);
1005
1057
  const otlp = buildOtlpSpan({
@@ -1167,7 +1219,7 @@ installTracingSuppressionHook();
1167
1219
  // package.json
1168
1220
  var package_default = {
1169
1221
  name: "@raindrop-ai/pi-agent",
1170
- version: "0.0.9",
1222
+ version: "0.1.0",
1171
1223
  description: "Raindrop observability for Pi Agent \u2014 automatic tracing via subscriber or pi-coding-agent extension",
1172
1224
  type: "module",
1173
1225
  license: "MIT",
@@ -25,7 +25,7 @@ __export(extension_exports, {
25
25
  });
26
26
  module.exports = __toCommonJS(extension_exports);
27
27
 
28
- // ../core/dist/chunk-WKRW55KX.js
28
+ // ../core/dist/chunk-QTUH3BHZ.js
29
29
  function getCrypto() {
30
30
  const c = globalThis.crypto;
31
31
  return c;
@@ -40,6 +40,17 @@ function randomBytes(length) {
40
40
  for (let i = 0; i < out.length; i++) out[i] = Math.floor(Math.random() * 256);
41
41
  return out;
42
42
  }
43
+ function randomUUID() {
44
+ const cryptoObj = getCrypto();
45
+ if (cryptoObj && typeof cryptoObj.randomUUID === "function") {
46
+ return cryptoObj.randomUUID();
47
+ }
48
+ const b = randomBytes(16);
49
+ b[6] = b[6] & 15 | 64;
50
+ b[8] = b[8] & 63 | 128;
51
+ const hex = [...b].map((x) => x.toString(16).padStart(2, "0")).join("");
52
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
53
+ }
43
54
  function base64Encode(bytes) {
44
55
  const maybeBuffer = globalThis.Buffer;
45
56
  if (maybeBuffer) {
@@ -70,7 +81,7 @@ function base64Encode(bytes) {
70
81
  return out;
71
82
  }
72
83
  function generateId() {
73
- return base64Encode(randomBytes(12)).replace(/[+/=]/g, "").slice(0, 16);
84
+ return randomUUID();
74
85
  }
75
86
  function runWithTracingSuppressed(fn) {
76
87
  const hook = globalThis.RAINDROP_SUPPRESS_TRACING;
@@ -407,16 +418,52 @@ function projectIdHeaders(projectId) {
407
418
  var SHUTDOWN_DEADLINE_MS = 1e4;
408
419
  var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
409
420
  function mergePatches(target, source) {
410
- var _a, _b, _c, _d;
421
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
411
422
  const out = { ...target, ...source };
412
423
  if (target.properties || source.properties) {
413
424
  out.properties = { ...(_a = target.properties) != null ? _a : {}, ...(_b = source.properties) != null ? _b : {} };
414
425
  }
426
+ if (target.usage || source.usage) {
427
+ out.usage = { ...(_c = target.usage) != null ? _c : {} };
428
+ if (((_d = source.usage) == null ? void 0 : _d.promptTokens) !== void 0) {
429
+ out.usage.promptTokens = source.usage.promptTokens;
430
+ }
431
+ if (((_e = source.usage) == null ? void 0 : _e.completionTokens) !== void 0) {
432
+ out.usage.completionTokens = source.usage.completionTokens;
433
+ }
434
+ }
435
+ if (source.error === void 0) {
436
+ out.error = target.error;
437
+ }
438
+ if (target.featureFlags || source.featureFlags) {
439
+ out.featureFlags = { ...(_f = target.featureFlags) != null ? _f : {}, ...(_g = source.featureFlags) != null ? _g : {} };
440
+ }
415
441
  if (target.attachments || source.attachments) {
416
- out.attachments = [...(_c = target.attachments) != null ? _c : [], ...(_d = source.attachments) != null ? _d : []];
442
+ out.attachments = [...(_h = target.attachments) != null ? _h : [], ...(_i = source.attachments) != null ? _i : []];
417
443
  }
418
444
  return out;
419
445
  }
446
+ function isErrorLike(value) {
447
+ return value !== null && typeof value === "object";
448
+ }
449
+ function eventTelemetryProperties(patch) {
450
+ var _a, _b;
451
+ const properties = {};
452
+ if (((_a = patch.usage) == null ? void 0 : _a.promptTokens) !== void 0 && Number.isFinite(patch.usage.promptTokens)) {
453
+ properties["ai.usage.prompt_tokens"] = patch.usage.promptTokens;
454
+ }
455
+ if (((_b = patch.usage) == null ? void 0 : _b.completionTokens) !== void 0 && Number.isFinite(patch.usage.completionTokens)) {
456
+ properties["ai.usage.completion_tokens"] = patch.usage.completionTokens;
457
+ }
458
+ if (patch.error !== void 0 && patch.error !== null) {
459
+ const constructorName = patch.error instanceof Error && patch.error.constructor !== Error ? patch.error.constructor.name : void 0;
460
+ 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";
461
+ const errorMessage = patch.error instanceof Error ? patch.error.message : isErrorLike(patch.error) && typeof patch.error.message === "string" ? patch.error.message : String(patch.error);
462
+ properties["error.type"] = errorType;
463
+ properties["error.message"] = errorMessage;
464
+ }
465
+ return properties;
466
+ }
420
467
  var EventShipper = class {
421
468
  constructor(opts) {
422
469
  this.buffers = /* @__PURE__ */ new Map();
@@ -665,6 +712,11 @@ var EventShipper = class {
665
712
  return;
666
713
  }
667
714
  const { wizardSession, ...restProperties } = (_e = accumulated.properties) != null ? _e : {};
715
+ let telemetryProperties = {};
716
+ try {
717
+ telemetryProperties = eventTelemetryProperties(accumulated);
718
+ } catch (e) {
719
+ }
668
720
  const convoId = (_f = accumulated.convoId) != null ? _f : sticky.convoId;
669
721
  const isPending = (_h = (_g = accumulated.isPending) != null ? _g : sticky.isPending) != null ? _h : true;
670
722
  const payload = {
@@ -674,15 +726,17 @@ var EventShipper = class {
674
726
  timestamp: (_i = accumulated.timestamp) != null ? _i : (/* @__PURE__ */ new Date()).toISOString(),
675
727
  ai_data: {
676
728
  input: accumulated.input,
677
- output: accumulated.output,
729
+ output: accumulated.error !== void 0 && accumulated.error !== null ? void 0 : accumulated.output,
678
730
  model: accumulated.model,
679
731
  convo_id: convoId
680
732
  },
681
733
  properties: {
682
734
  ...restProperties,
735
+ ...telemetryProperties,
683
736
  ...wizardSession ? { "raindrop.wizardSession": wizardSession } : {},
684
737
  $context: this.context
685
738
  },
739
+ ...accumulated.featureFlags && Object.keys(accumulated.featureFlags).length > 0 ? { feature_flags: accumulated.featureFlags } : {},
686
740
  attachments: accumulated.attachments,
687
741
  is_pending: isPending
688
742
  };
@@ -836,6 +890,13 @@ function redactJsonAttributeValue(key, value) {
836
890
  if (scrubbedJson === json) return void 0;
837
891
  return { stringValue: scrubbedJson };
838
892
  }
893
+ function identityAttrs(args) {
894
+ return [
895
+ attrString("ai.telemetry.metadata.raindrop.ai.userId", args.userId),
896
+ attrString("ai.telemetry.metadata.raindrop.convoId", args.convoId),
897
+ attrString("ai.telemetry.metadata.raindrop.eventName", args.eventName)
898
+ ];
899
+ }
839
900
  function applyOtelSpanAttributeLimit(limit) {
840
901
  var _a, _b;
841
902
  try {
@@ -960,6 +1021,7 @@ var TraceShipper = class {
960
1021
  const started = (_a = args.startTimeUnixNano) != null ? _a : nowUnixNanoString();
961
1022
  const attrs = [
962
1023
  attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
1024
+ ...identityAttrs(args),
963
1025
  attrString("ai.operationId", args.operationId)
964
1026
  ];
965
1027
  if ((_b = args.attributes) == null ? void 0 : _b.length) attrs.push(...args.attributes);
@@ -1015,7 +1077,8 @@ var TraceShipper = class {
1015
1077
  var _a;
1016
1078
  const ids = createSpanIds(args.parent);
1017
1079
  const attrs = [
1018
- attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId)
1080
+ attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
1081
+ ...identityAttrs(args)
1019
1082
  ];
1020
1083
  if ((_a = args.attributes) == null ? void 0 : _a.length) attrs.push(...args.attributes);
1021
1084
  const otlp = buildOtlpSpan({
@@ -1238,7 +1301,7 @@ function resolveLocalWorkshopUrl(fileValue) {
1238
1301
  // package.json
1239
1302
  var package_default = {
1240
1303
  name: "@raindrop-ai/pi-agent",
1241
- version: "0.0.9",
1304
+ version: "0.1.0",
1242
1305
  description: "Raindrop observability for Pi Agent \u2014 automatic tracing via subscriber or pi-coding-agent extension",
1243
1306
  type: "module",
1244
1307
  license: "MIT",
@@ -1563,7 +1626,9 @@ function getAssistantError(message) {
1563
1626
  var _a;
1564
1627
  if (message.role !== "assistant") return void 0;
1565
1628
  if (message.stopReason !== "error" && message.stopReason !== "aborted") return void 0;
1566
- return (_a = message.errorMessage) != null ? _a : `Assistant ${message.stopReason}`;
1629
+ const error = new Error((_a = message.errorMessage) != null ? _a : `Assistant ${message.stopReason}`);
1630
+ error.name = message.stopReason === "aborted" ? "AbortError" : "PiAgentError";
1631
+ return error;
1567
1632
  }
1568
1633
  function getState(stateRef, ctx) {
1569
1634
  const sessionId = ctx.sessionManager.getSessionId();
@@ -1756,13 +1821,17 @@ function registerTracing(pi, config, eventShipper, traceShipper) {
1756
1821
  state.currentRootSpan = void 0;
1757
1822
  await eventShipper.finish((_h = state.currentEventRequestId) != null ? _h : state.currentEventId, {
1758
1823
  userId: getUserId(state, config.eventMetadata),
1759
- model: modelName,
1760
- ...outputText.trim() ? { output: outputText } : {},
1824
+ ...modelId ? { model: modelId } : {},
1825
+ ...!errorForSpan && outputText.trim() ? { output: outputText } : {},
1826
+ usage: {
1827
+ promptTokens: state.totalInputTokens > 0 ? state.totalInputTokens : void 0,
1828
+ completionTokens: state.totalOutputTokens > 0 ? state.totalOutputTokens : void 0
1829
+ },
1830
+ error: errorForSpan,
1761
1831
  properties: {
1762
1832
  sdk_version: libraryVersion,
1763
1833
  stop_reason: message.stopReason,
1764
- ...state.totalInputTokens > 0 ? { "ai.usage.prompt_tokens": state.totalInputTokens } : {},
1765
- ...state.totalOutputTokens > 0 ? { "ai.usage.completion_tokens": state.totalOutputTokens } : {},
1834
+ ...provider ? { "ai.provider": provider } : {},
1766
1835
  ...state.totalCacheReadTokens > 0 ? { "ai.usage.cache_read_tokens": state.totalCacheReadTokens } : {}
1767
1836
  }
1768
1837
  });
@@ -1,5 +1,5 @@
1
1
  import { ExtensionAPI } from '@earendil-works/pi-coding-agent';
2
- import { E as EventShipper$1, T as TraceShipper$1, O as OtlpSpan } from './index.d-CSO1bDLs.cjs';
2
+ import { E as EventShipper$1, T as TraceShipper$1, O as OtlpSpan } from './index.d-DPYV95P7.cjs';
3
3
 
4
4
  interface EventMetadata {
5
5
  userId?: string;
@@ -1,5 +1,5 @@
1
1
  import { ExtensionAPI } from '@earendil-works/pi-coding-agent';
2
- import { E as EventShipper$1, T as TraceShipper$1, O as OtlpSpan } from './index.d-CSO1bDLs.js';
2
+ import { E as EventShipper$1, T as TraceShipper$1, O as OtlpSpan } from './index.d-DPYV95P7.js';
3
3
 
4
4
  interface EventMetadata {
5
5
  userId?: string;
package/dist/extension.js CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  resolveLocalDebuggerBaseUrl,
15
15
  safeStringify,
16
16
  truncate
17
- } from "./chunk-TEXLELWC.js";
17
+ } from "./chunk-XQJ6G4YA.js";
18
18
 
19
19
  // src/internal/config.ts
20
20
  import { existsSync, readFileSync } from "fs";
@@ -141,7 +141,9 @@ function getAssistantError(message) {
141
141
  var _a;
142
142
  if (message.role !== "assistant") return void 0;
143
143
  if (message.stopReason !== "error" && message.stopReason !== "aborted") return void 0;
144
- return (_a = message.errorMessage) != null ? _a : `Assistant ${message.stopReason}`;
144
+ const error = new Error((_a = message.errorMessage) != null ? _a : `Assistant ${message.stopReason}`);
145
+ error.name = message.stopReason === "aborted" ? "AbortError" : "PiAgentError";
146
+ return error;
145
147
  }
146
148
  function getState(stateRef, ctx) {
147
149
  const sessionId = ctx.sessionManager.getSessionId();
@@ -334,13 +336,17 @@ function registerTracing(pi, config, eventShipper, traceShipper) {
334
336
  state.currentRootSpan = void 0;
335
337
  await eventShipper.finish((_h = state.currentEventRequestId) != null ? _h : state.currentEventId, {
336
338
  userId: getUserId(state, config.eventMetadata),
337
- model: modelName,
338
- ...outputText.trim() ? { output: outputText } : {},
339
+ ...modelId ? { model: modelId } : {},
340
+ ...!errorForSpan && outputText.trim() ? { output: outputText } : {},
341
+ usage: {
342
+ promptTokens: state.totalInputTokens > 0 ? state.totalInputTokens : void 0,
343
+ completionTokens: state.totalOutputTokens > 0 ? state.totalOutputTokens : void 0
344
+ },
345
+ error: errorForSpan,
339
346
  properties: {
340
347
  sdk_version: libraryVersion,
341
348
  stop_reason: message.stopReason,
342
- ...state.totalInputTokens > 0 ? { "ai.usage.prompt_tokens": state.totalInputTokens } : {},
343
- ...state.totalOutputTokens > 0 ? { "ai.usage.completion_tokens": state.totalOutputTokens } : {},
349
+ ...provider ? { "ai.provider": provider } : {},
344
350
  ...state.totalCacheReadTokens > 0 ? { "ai.usage.cache_read_tokens": state.totalCacheReadTokens } : {}
345
351
  }
346
352
  });
package/dist/index.cjs CHANGED
@@ -24,7 +24,7 @@ __export(index_exports, {
24
24
  });
25
25
  module.exports = __toCommonJS(index_exports);
26
26
 
27
- // ../core/dist/chunk-WKRW55KX.js
27
+ // ../core/dist/chunk-QTUH3BHZ.js
28
28
  function getCrypto() {
29
29
  const c = globalThis.crypto;
30
30
  return c;
@@ -414,16 +414,52 @@ function projectIdHeaders(projectId) {
414
414
  var SHUTDOWN_DEADLINE_MS = 1e4;
415
415
  var POST_SHUTDOWN_TIMEOUT_MS = 5e3;
416
416
  function mergePatches(target, source) {
417
- var _a, _b, _c, _d;
417
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
418
418
  const out = { ...target, ...source };
419
419
  if (target.properties || source.properties) {
420
420
  out.properties = { ...(_a = target.properties) != null ? _a : {}, ...(_b = source.properties) != null ? _b : {} };
421
421
  }
422
+ if (target.usage || source.usage) {
423
+ out.usage = { ...(_c = target.usage) != null ? _c : {} };
424
+ if (((_d = source.usage) == null ? void 0 : _d.promptTokens) !== void 0) {
425
+ out.usage.promptTokens = source.usage.promptTokens;
426
+ }
427
+ if (((_e = source.usage) == null ? void 0 : _e.completionTokens) !== void 0) {
428
+ out.usage.completionTokens = source.usage.completionTokens;
429
+ }
430
+ }
431
+ if (source.error === void 0) {
432
+ out.error = target.error;
433
+ }
434
+ if (target.featureFlags || source.featureFlags) {
435
+ out.featureFlags = { ...(_f = target.featureFlags) != null ? _f : {}, ...(_g = source.featureFlags) != null ? _g : {} };
436
+ }
422
437
  if (target.attachments || source.attachments) {
423
- out.attachments = [...(_c = target.attachments) != null ? _c : [], ...(_d = source.attachments) != null ? _d : []];
438
+ out.attachments = [...(_h = target.attachments) != null ? _h : [], ...(_i = source.attachments) != null ? _i : []];
424
439
  }
425
440
  return out;
426
441
  }
442
+ function isErrorLike(value) {
443
+ return value !== null && typeof value === "object";
444
+ }
445
+ function eventTelemetryProperties(patch) {
446
+ var _a, _b;
447
+ const properties = {};
448
+ if (((_a = patch.usage) == null ? void 0 : _a.promptTokens) !== void 0 && Number.isFinite(patch.usage.promptTokens)) {
449
+ properties["ai.usage.prompt_tokens"] = patch.usage.promptTokens;
450
+ }
451
+ if (((_b = patch.usage) == null ? void 0 : _b.completionTokens) !== void 0 && Number.isFinite(patch.usage.completionTokens)) {
452
+ properties["ai.usage.completion_tokens"] = patch.usage.completionTokens;
453
+ }
454
+ if (patch.error !== void 0 && patch.error !== null) {
455
+ const constructorName = patch.error instanceof Error && patch.error.constructor !== Error ? patch.error.constructor.name : void 0;
456
+ 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";
457
+ const errorMessage = patch.error instanceof Error ? patch.error.message : isErrorLike(patch.error) && typeof patch.error.message === "string" ? patch.error.message : String(patch.error);
458
+ properties["error.type"] = errorType;
459
+ properties["error.message"] = errorMessage;
460
+ }
461
+ return properties;
462
+ }
427
463
  var EventShipper = class {
428
464
  constructor(opts) {
429
465
  this.buffers = /* @__PURE__ */ new Map();
@@ -672,6 +708,11 @@ var EventShipper = class {
672
708
  return;
673
709
  }
674
710
  const { wizardSession, ...restProperties } = (_e = accumulated.properties) != null ? _e : {};
711
+ let telemetryProperties = {};
712
+ try {
713
+ telemetryProperties = eventTelemetryProperties(accumulated);
714
+ } catch (e) {
715
+ }
675
716
  const convoId = (_f = accumulated.convoId) != null ? _f : sticky.convoId;
676
717
  const isPending = (_h = (_g = accumulated.isPending) != null ? _g : sticky.isPending) != null ? _h : true;
677
718
  const payload = {
@@ -681,15 +722,17 @@ var EventShipper = class {
681
722
  timestamp: (_i = accumulated.timestamp) != null ? _i : (/* @__PURE__ */ new Date()).toISOString(),
682
723
  ai_data: {
683
724
  input: accumulated.input,
684
- output: accumulated.output,
725
+ output: accumulated.error !== void 0 && accumulated.error !== null ? void 0 : accumulated.output,
685
726
  model: accumulated.model,
686
727
  convo_id: convoId
687
728
  },
688
729
  properties: {
689
730
  ...restProperties,
731
+ ...telemetryProperties,
690
732
  ...wizardSession ? { "raindrop.wizardSession": wizardSession } : {},
691
733
  $context: this.context
692
734
  },
735
+ ...accumulated.featureFlags && Object.keys(accumulated.featureFlags).length > 0 ? { feature_flags: accumulated.featureFlags } : {},
693
736
  attachments: accumulated.attachments,
694
737
  is_pending: isPending
695
738
  };
@@ -843,6 +886,13 @@ function redactJsonAttributeValue(key, value) {
843
886
  if (scrubbedJson === json) return void 0;
844
887
  return { stringValue: scrubbedJson };
845
888
  }
889
+ function identityAttrs(args) {
890
+ return [
891
+ attrString("ai.telemetry.metadata.raindrop.ai.userId", args.userId),
892
+ attrString("ai.telemetry.metadata.raindrop.convoId", args.convoId),
893
+ attrString("ai.telemetry.metadata.raindrop.eventName", args.eventName)
894
+ ];
895
+ }
846
896
  function applyOtelSpanAttributeLimit(limit) {
847
897
  var _a, _b;
848
898
  try {
@@ -967,6 +1017,7 @@ var TraceShipper = class {
967
1017
  const started = (_a = args.startTimeUnixNano) != null ? _a : nowUnixNanoString();
968
1018
  const attrs = [
969
1019
  attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
1020
+ ...identityAttrs(args),
970
1021
  attrString("ai.operationId", args.operationId)
971
1022
  ];
972
1023
  if ((_b = args.attributes) == null ? void 0 : _b.length) attrs.push(...args.attributes);
@@ -1022,7 +1073,8 @@ var TraceShipper = class {
1022
1073
  var _a;
1023
1074
  const ids = createSpanIds(args.parent);
1024
1075
  const attrs = [
1025
- attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId)
1076
+ attrString("ai.telemetry.metadata.raindrop.eventId", args.eventId),
1077
+ ...identityAttrs(args)
1026
1078
  ];
1027
1079
  if ((_a = args.attributes) == null ? void 0 : _a.length) attrs.push(...args.attributes);
1028
1080
  const otlp = buildOtlpSpan({
@@ -1190,7 +1242,7 @@ installTracingSuppressionHook();
1190
1242
  // package.json
1191
1243
  var package_default = {
1192
1244
  name: "@raindrop-ai/pi-agent",
1193
- version: "0.0.9",
1245
+ version: "0.1.0",
1194
1246
  description: "Raindrop observability for Pi Agent \u2014 automatic tracing via subscriber or pi-coding-agent extension",
1195
1247
  type: "module",
1196
1248
  license: "MIT",
@@ -1489,14 +1541,24 @@ function getUsername() {
1489
1541
  }
1490
1542
 
1491
1543
  // src/internal/subscriber.ts
1544
+ function resolveEventId(source) {
1545
+ if (typeof source !== "function") return randomUUID();
1546
+ try {
1547
+ const id = source();
1548
+ return typeof id === "string" && id.trim() !== "" ? id : randomUUID();
1549
+ } catch (e) {
1550
+ return randomUUID();
1551
+ }
1552
+ }
1492
1553
  function createSubscriber(agent, eventShipper, traceShipper, defaultOptions, options, debug) {
1493
- var _a, _b, _c, _d, _e;
1554
+ var _a, _b, _c, _d, _e, _f;
1494
1555
  const userId = (_a = options.userId) != null ? _a : defaultOptions.userId;
1495
1556
  const convoId = (_b = options.convoId) != null ? _b : defaultOptions.convoId;
1496
1557
  const eventName = (_c = options.eventName) != null ? _c : defaultOptions.eventName;
1558
+ const eventIdSource = (_d = options.eventId) != null ? _d : defaultOptions.eventId;
1497
1559
  const properties = {
1498
- ...(_d = defaultOptions.properties) != null ? _d : {},
1499
- ...(_e = options.properties) != null ? _e : {}
1560
+ ...(_e = defaultOptions.properties) != null ? _e : {},
1561
+ ...(_f = options.properties) != null ? _f : {}
1500
1562
  };
1501
1563
  let currentRun;
1502
1564
  function log(msg) {
@@ -1527,7 +1589,7 @@ function createSubscriber(agent, eventShipper, traceShipper, defaultOptions, opt
1527
1589
  }
1528
1590
  currentRun = void 0;
1529
1591
  }
1530
- const eventId = randomUUID();
1592
+ const eventId = resolveEventId(eventIdSource);
1531
1593
  const rootSpan = traceShipper ? traceShipper.startSpan({
1532
1594
  name: "ai.event",
1533
1595
  eventId,
@@ -1585,17 +1647,22 @@ function createSubscriber(agent, eventShipper, traceShipper, defaultOptions, opt
1585
1647
  }
1586
1648
  if (!("role" in message) || message.role !== "assistant") return;
1587
1649
  const model = extractModelName(message);
1650
+ const provider = "provider" in message && typeof message.provider === "string" ? message.provider : void 0;
1651
+ const bareModel = typeof message.model === "string" ? message.model : void 0;
1588
1652
  const usage = extractTokenUsage(message);
1589
1653
  const assistantText = extractAssistantText(message);
1590
- if (model) currentRun.lastModel = model;
1654
+ if (bareModel) {
1655
+ currentRun.lastModel = bareModel;
1656
+ currentRun.lastProvider = provider;
1657
+ }
1591
1658
  if (usage) {
1592
1659
  currentRun.totalInputTokens += usage.input;
1593
1660
  currentRun.totalOutputTokens += usage.output;
1594
1661
  if (usage.cacheRead) currentRun.totalCacheReadTokens += usage.cacheRead;
1595
1662
  }
1596
1663
  if (!traceShipper || !currentRun.currentTurnSpan) return;
1597
- const rawProvider = "provider" in message && typeof message.provider === "string" ? message.provider : void 0;
1598
- const rawModelId = typeof message.model === "string" ? message.model : void 0;
1664
+ const rawProvider = provider;
1665
+ const rawModelId = bareModel;
1599
1666
  const stopReason = "stopReason" in message && typeof message.stopReason === "string" ? message.stopReason : void 0;
1600
1667
  const llmAttrs = [
1601
1668
  attrString("ai.operationId", "generateText")
@@ -1634,6 +1701,13 @@ function createSubscriber(agent, eventShipper, traceShipper, defaultOptions, opt
1634
1701
  attributes: llmAttrs
1635
1702
  });
1636
1703
  const errorForSpan = stopReason === "error" || stopReason === "aborted" ? "errorMessage" in message && typeof message.errorMessage === "string" ? message.errorMessage : `Assistant ${stopReason}` : void 0;
1704
+ if (errorForSpan) {
1705
+ const assistantError = new Error(errorForSpan);
1706
+ assistantError.name = stopReason === "aborted" ? "AbortError" : "PiAgentError";
1707
+ currentRun.error = assistantError;
1708
+ } else {
1709
+ currentRun.error = void 0;
1710
+ }
1637
1711
  traceShipper.endSpan(llmSpan, errorForSpan ? { error: errorForSpan } : void 0);
1638
1712
  const toolCallIds = extractToolCallIds(message);
1639
1713
  for (const tcId of toolCallIds) {
@@ -1753,7 +1827,7 @@ function createSubscriber(agent, eventShipper, traceShipper, defaultOptions, opt
1753
1827
  attrString("ai.operationId", "generateText")
1754
1828
  ];
1755
1829
  if (run.lastModel) {
1756
- run.rootSpan.name = run.lastModel;
1830
+ run.rootSpan.name = run.lastProvider ? `${run.lastProvider}/${run.lastModel}` : run.lastModel;
1757
1831
  rootAttrs.push(attrString("gen_ai.response.model", run.lastModel));
1758
1832
  }
1759
1833
  if (run.currentInput) {
@@ -1778,12 +1852,16 @@ function createSubscriber(agent, eventShipper, traceShipper, defaultOptions, opt
1778
1852
  eventShipper.finish(run.eventId, {
1779
1853
  userId: userId != null ? userId : "anonymous",
1780
1854
  model: run.lastModel || void 0,
1781
- output: outputText || void 0,
1855
+ output: run.error ? void 0 : outputText || void 0,
1856
+ usage: {
1857
+ promptTokens: run.totalInputTokens > 0 ? run.totalInputTokens : void 0,
1858
+ completionTokens: run.totalOutputTokens > 0 ? run.totalOutputTokens : void 0
1859
+ },
1860
+ error: run.error,
1782
1861
  properties: {
1783
1862
  ...properties,
1784
1863
  sdk_version: libraryVersion,
1785
- ...run.totalInputTokens > 0 ? { "ai.usage.prompt_tokens": run.totalInputTokens } : {},
1786
- ...run.totalOutputTokens > 0 ? { "ai.usage.completion_tokens": run.totalOutputTokens } : {},
1864
+ ...run.lastProvider ? { "ai.provider": run.lastProvider } : {},
1787
1865
  ...run.totalCacheReadTokens > 0 ? { "ai.usage.cache_read_tokens": run.totalCacheReadTokens } : {}
1788
1866
  }
1789
1867
  }).catch(() => {
@@ -1884,6 +1962,7 @@ function createRaindropPiAgent(opts) {
1884
1962
  userId: opts.userId,
1885
1963
  convoId: opts.convoId,
1886
1964
  eventName: opts.eventName,
1965
+ eventId: opts.eventId,
1887
1966
  properties: opts.properties
1888
1967
  };
1889
1968
  return {
@@ -45,6 +45,10 @@ type IdentifyInput = {
45
45
  userId: string;
46
46
  traits?: Record<string, unknown>;
47
47
  };
48
+ type EventUsage = {
49
+ promptTokens?: number;
50
+ completionTokens?: number;
51
+ };
48
52
  type Patch = {
49
53
  eventName?: string;
50
54
  userId?: string;
@@ -52,7 +56,10 @@ type Patch = {
52
56
  input?: string;
53
57
  output?: string;
54
58
  model?: string;
59
+ usage?: EventUsage;
60
+ error?: unknown;
55
61
  properties?: Record<string, unknown>;
62
+ featureFlags?: Record<string, string>;
56
63
  attachments?: Attachment[];
57
64
  isPending?: boolean;
58
65
  timestamp?: string;
@@ -149,12 +156,7 @@ declare class EventShipper {
149
156
  */
150
157
  private requestOpts;
151
158
  patch(eventId: string, patch: Patch): Promise<void>;
152
- finish(eventId: string, patch: {
153
- output?: string;
154
- model?: string;
155
- properties?: Record<string, unknown>;
156
- userId?: string;
157
- }): Promise<void>;
159
+ finish(eventId: string, patch: Pick<Patch, "output" | "model" | "usage" | "error" | "properties" | "featureFlags" | "userId">): Promise<void>;
158
160
  flush(): Promise<void>;
159
161
  shutdown(): Promise<void>;
160
162
  trackSignal(signal: SignalInput): Promise<void>;
@@ -327,6 +329,9 @@ declare class TraceShipper {
327
329
  spanIdB64: string;
328
330
  };
329
331
  eventId: string;
332
+ userId?: string;
333
+ convoId?: string;
334
+ eventName?: string;
330
335
  operationId?: string;
331
336
  attributes?: Array<OtlpKeyValue | undefined>;
332
337
  startTimeUnixNano?: string;
@@ -345,6 +350,9 @@ declare class TraceShipper {
345
350
  spanIdB64: string;
346
351
  };
347
352
  eventId: string;
353
+ userId?: string;
354
+ convoId?: string;
355
+ eventName?: string;
348
356
  startTimeUnixNano: string;
349
357
  endTimeUnixNano: string;
350
358
  attributes?: Array<OtlpKeyValue | undefined>;
@@ -45,6 +45,10 @@ type IdentifyInput = {
45
45
  userId: string;
46
46
  traits?: Record<string, unknown>;
47
47
  };
48
+ type EventUsage = {
49
+ promptTokens?: number;
50
+ completionTokens?: number;
51
+ };
48
52
  type Patch = {
49
53
  eventName?: string;
50
54
  userId?: string;
@@ -52,7 +56,10 @@ type Patch = {
52
56
  input?: string;
53
57
  output?: string;
54
58
  model?: string;
59
+ usage?: EventUsage;
60
+ error?: unknown;
55
61
  properties?: Record<string, unknown>;
62
+ featureFlags?: Record<string, string>;
56
63
  attachments?: Attachment[];
57
64
  isPending?: boolean;
58
65
  timestamp?: string;
@@ -149,12 +156,7 @@ declare class EventShipper {
149
156
  */
150
157
  private requestOpts;
151
158
  patch(eventId: string, patch: Patch): Promise<void>;
152
- finish(eventId: string, patch: {
153
- output?: string;
154
- model?: string;
155
- properties?: Record<string, unknown>;
156
- userId?: string;
157
- }): Promise<void>;
159
+ finish(eventId: string, patch: Pick<Patch, "output" | "model" | "usage" | "error" | "properties" | "featureFlags" | "userId">): Promise<void>;
158
160
  flush(): Promise<void>;
159
161
  shutdown(): Promise<void>;
160
162
  trackSignal(signal: SignalInput): Promise<void>;
@@ -327,6 +329,9 @@ declare class TraceShipper {
327
329
  spanIdB64: string;
328
330
  };
329
331
  eventId: string;
332
+ userId?: string;
333
+ convoId?: string;
334
+ eventName?: string;
330
335
  operationId?: string;
331
336
  attributes?: Array<OtlpKeyValue | undefined>;
332
337
  startTimeUnixNano?: string;
@@ -345,6 +350,9 @@ declare class TraceShipper {
345
350
  spanIdB64: string;
346
351
  };
347
352
  eventId: string;
353
+ userId?: string;
354
+ convoId?: string;
355
+ eventName?: string;
348
356
  startTimeUnixNano: string;
349
357
  endTimeUnixNano: string;
350
358
  attributes?: Array<OtlpKeyValue | undefined>;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Agent } from '@earendil-works/pi-agent-core';
2
- import { A as Attachment } from './index.d-CSO1bDLs.cjs';
2
+ import { A as Attachment } from './index.d-DPYV95P7.cjs';
3
3
 
4
4
  /**
5
5
  * Options for the Raindrop Pi Agent client.
@@ -24,6 +24,15 @@ interface RaindropPiAgentOptions {
24
24
  convoId?: string;
25
25
  /** Default event name (default: "pi_agent_prompt") */
26
26
  eventName?: string;
27
+ /**
28
+ * Per-run event id source. Invoked once per agent run to mint that run's
29
+ * event id (reused for the run's Raindrop event and every linked span). A
30
+ * static string is intentionally not accepted: a long-lived client runs many
31
+ * agent runs, and a fixed id would collide across them. Absent / throwing /
32
+ * non-string / empty results fall back to a random UUID, so a caller's id
33
+ * source never crashes telemetry.
34
+ */
35
+ eventId?: () => string;
27
36
  /** Default properties attached to every event */
28
37
  properties?: Record<string, unknown>;
29
38
  /**
@@ -69,6 +78,8 @@ interface PiAgentSubscribeOptions {
69
78
  convoId?: string;
70
79
  /** Event name override */
71
80
  eventName?: string;
81
+ /** Per-run event id source override (see RaindropPiAgentOptions.eventId) */
82
+ eventId?: () => string;
72
83
  /** Additional properties */
73
84
  properties?: Record<string, unknown>;
74
85
  }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Agent } from '@earendil-works/pi-agent-core';
2
- import { A as Attachment } from './index.d-CSO1bDLs.js';
2
+ import { A as Attachment } from './index.d-DPYV95P7.js';
3
3
 
4
4
  /**
5
5
  * Options for the Raindrop Pi Agent client.
@@ -24,6 +24,15 @@ interface RaindropPiAgentOptions {
24
24
  convoId?: string;
25
25
  /** Default event name (default: "pi_agent_prompt") */
26
26
  eventName?: string;
27
+ /**
28
+ * Per-run event id source. Invoked once per agent run to mint that run's
29
+ * event id (reused for the run's Raindrop event and every linked span). A
30
+ * static string is intentionally not accepted: a long-lived client runs many
31
+ * agent runs, and a fixed id would collide across them. Absent / throwing /
32
+ * non-string / empty results fall back to a random UUID, so a caller's id
33
+ * source never crashes telemetry.
34
+ */
35
+ eventId?: () => string;
27
36
  /** Default properties attached to every event */
28
37
  properties?: Record<string, unknown>;
29
38
  /**
@@ -69,6 +78,8 @@ interface PiAgentSubscribeOptions {
69
78
  convoId?: string;
70
79
  /** Event name override */
71
80
  eventName?: string;
81
+ /** Per-run event id source override (see RaindropPiAgentOptions.eventId) */
82
+ eventId?: () => string;
72
83
  /** Additional properties */
73
84
  properties?: Record<string, unknown>;
74
85
  }
package/dist/index.js CHANGED
@@ -17,17 +17,27 @@ import {
17
17
  resolveLocalDebuggerBaseUrl,
18
18
  safeStringify,
19
19
  truncate
20
- } from "./chunk-TEXLELWC.js";
20
+ } from "./chunk-XQJ6G4YA.js";
21
21
 
22
22
  // src/internal/subscriber.ts
23
+ function resolveEventId(source) {
24
+ if (typeof source !== "function") return randomUUID();
25
+ try {
26
+ const id = source();
27
+ return typeof id === "string" && id.trim() !== "" ? id : randomUUID();
28
+ } catch (e) {
29
+ return randomUUID();
30
+ }
31
+ }
23
32
  function createSubscriber(agent, eventShipper, traceShipper, defaultOptions, options, debug) {
24
- var _a, _b, _c, _d, _e;
33
+ var _a, _b, _c, _d, _e, _f;
25
34
  const userId = (_a = options.userId) != null ? _a : defaultOptions.userId;
26
35
  const convoId = (_b = options.convoId) != null ? _b : defaultOptions.convoId;
27
36
  const eventName = (_c = options.eventName) != null ? _c : defaultOptions.eventName;
37
+ const eventIdSource = (_d = options.eventId) != null ? _d : defaultOptions.eventId;
28
38
  const properties = {
29
- ...(_d = defaultOptions.properties) != null ? _d : {},
30
- ...(_e = options.properties) != null ? _e : {}
39
+ ...(_e = defaultOptions.properties) != null ? _e : {},
40
+ ...(_f = options.properties) != null ? _f : {}
31
41
  };
32
42
  let currentRun;
33
43
  function log(msg) {
@@ -58,7 +68,7 @@ function createSubscriber(agent, eventShipper, traceShipper, defaultOptions, opt
58
68
  }
59
69
  currentRun = void 0;
60
70
  }
61
- const eventId = randomUUID();
71
+ const eventId = resolveEventId(eventIdSource);
62
72
  const rootSpan = traceShipper ? traceShipper.startSpan({
63
73
  name: "ai.event",
64
74
  eventId,
@@ -116,17 +126,22 @@ function createSubscriber(agent, eventShipper, traceShipper, defaultOptions, opt
116
126
  }
117
127
  if (!("role" in message) || message.role !== "assistant") return;
118
128
  const model = extractModelName(message);
129
+ const provider = "provider" in message && typeof message.provider === "string" ? message.provider : void 0;
130
+ const bareModel = typeof message.model === "string" ? message.model : void 0;
119
131
  const usage = extractTokenUsage(message);
120
132
  const assistantText = extractAssistantText(message);
121
- if (model) currentRun.lastModel = model;
133
+ if (bareModel) {
134
+ currentRun.lastModel = bareModel;
135
+ currentRun.lastProvider = provider;
136
+ }
122
137
  if (usage) {
123
138
  currentRun.totalInputTokens += usage.input;
124
139
  currentRun.totalOutputTokens += usage.output;
125
140
  if (usage.cacheRead) currentRun.totalCacheReadTokens += usage.cacheRead;
126
141
  }
127
142
  if (!traceShipper || !currentRun.currentTurnSpan) return;
128
- const rawProvider = "provider" in message && typeof message.provider === "string" ? message.provider : void 0;
129
- const rawModelId = typeof message.model === "string" ? message.model : void 0;
143
+ const rawProvider = provider;
144
+ const rawModelId = bareModel;
130
145
  const stopReason = "stopReason" in message && typeof message.stopReason === "string" ? message.stopReason : void 0;
131
146
  const llmAttrs = [
132
147
  attrString("ai.operationId", "generateText")
@@ -165,6 +180,13 @@ function createSubscriber(agent, eventShipper, traceShipper, defaultOptions, opt
165
180
  attributes: llmAttrs
166
181
  });
167
182
  const errorForSpan = stopReason === "error" || stopReason === "aborted" ? "errorMessage" in message && typeof message.errorMessage === "string" ? message.errorMessage : `Assistant ${stopReason}` : void 0;
183
+ if (errorForSpan) {
184
+ const assistantError = new Error(errorForSpan);
185
+ assistantError.name = stopReason === "aborted" ? "AbortError" : "PiAgentError";
186
+ currentRun.error = assistantError;
187
+ } else {
188
+ currentRun.error = void 0;
189
+ }
168
190
  traceShipper.endSpan(llmSpan, errorForSpan ? { error: errorForSpan } : void 0);
169
191
  const toolCallIds = extractToolCallIds(message);
170
192
  for (const tcId of toolCallIds) {
@@ -284,7 +306,7 @@ function createSubscriber(agent, eventShipper, traceShipper, defaultOptions, opt
284
306
  attrString("ai.operationId", "generateText")
285
307
  ];
286
308
  if (run.lastModel) {
287
- run.rootSpan.name = run.lastModel;
309
+ run.rootSpan.name = run.lastProvider ? `${run.lastProvider}/${run.lastModel}` : run.lastModel;
288
310
  rootAttrs.push(attrString("gen_ai.response.model", run.lastModel));
289
311
  }
290
312
  if (run.currentInput) {
@@ -309,12 +331,16 @@ function createSubscriber(agent, eventShipper, traceShipper, defaultOptions, opt
309
331
  eventShipper.finish(run.eventId, {
310
332
  userId: userId != null ? userId : "anonymous",
311
333
  model: run.lastModel || void 0,
312
- output: outputText || void 0,
334
+ output: run.error ? void 0 : outputText || void 0,
335
+ usage: {
336
+ promptTokens: run.totalInputTokens > 0 ? run.totalInputTokens : void 0,
337
+ completionTokens: run.totalOutputTokens > 0 ? run.totalOutputTokens : void 0
338
+ },
339
+ error: run.error,
313
340
  properties: {
314
341
  ...properties,
315
342
  sdk_version: libraryVersion,
316
- ...run.totalInputTokens > 0 ? { "ai.usage.prompt_tokens": run.totalInputTokens } : {},
317
- ...run.totalOutputTokens > 0 ? { "ai.usage.completion_tokens": run.totalOutputTokens } : {},
343
+ ...run.lastProvider ? { "ai.provider": run.lastProvider } : {},
318
344
  ...run.totalCacheReadTokens > 0 ? { "ai.usage.cache_read_tokens": run.totalCacheReadTokens } : {}
319
345
  }
320
346
  }).catch(() => {
@@ -415,6 +441,7 @@ function createRaindropPiAgent(opts) {
415
441
  userId: opts.userId,
416
442
  convoId: opts.convoId,
417
443
  eventName: opts.eventName,
444
+ eventId: opts.eventId,
418
445
  properties: opts.properties
419
446
  };
420
447
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raindrop-ai/pi-agent",
3
- "version": "0.0.9",
3
+ "version": "0.1.0",
4
4
  "description": "Raindrop observability for Pi Agent — automatic tracing via subscriber or pi-coding-agent extension",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -54,7 +54,7 @@
54
54
  "tsup": "^8.5.1",
55
55
  "typescript": "^5.7.3",
56
56
  "vitest": "^2.1.9",
57
- "@raindrop-ai/core": "0.0.5"
57
+ "@raindrop-ai/core": "0.1.3"
58
58
  },
59
59
  "tsup": {
60
60
  "entry": [