@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.
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-DBLTz2Nz.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-DBLTz2Nz.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
@@ -13,21 +13,35 @@ import {
13
13
  getHostname,
14
14
  getUsername,
15
15
  libraryVersion,
16
+ modelSpendSpanAttributes,
16
17
  randomUUID,
17
18
  resolveLocalDebuggerBaseUrl,
18
19
  safeStringify,
19
20
  truncate
20
- } from "./chunk-GXL5WZE5.js";
21
+ } from "./chunk-GTKXT2J5.js";
21
22
 
22
23
  // src/internal/subscriber.ts
24
+ function pushAttr(attrs, attr) {
25
+ if (attr) attrs.push(attr);
26
+ }
27
+ function resolveEventId(source) {
28
+ if (typeof source !== "function") return randomUUID();
29
+ try {
30
+ const id = source();
31
+ return typeof id === "string" && id.trim() !== "" ? id : randomUUID();
32
+ } catch (e) {
33
+ return randomUUID();
34
+ }
35
+ }
23
36
  function createSubscriber(agent, eventShipper, traceShipper, defaultOptions, options, debug) {
24
- var _a, _b, _c, _d, _e;
37
+ var _a, _b, _c, _d, _e, _f;
25
38
  const userId = (_a = options.userId) != null ? _a : defaultOptions.userId;
26
39
  const convoId = (_b = options.convoId) != null ? _b : defaultOptions.convoId;
27
40
  const eventName = (_c = options.eventName) != null ? _c : defaultOptions.eventName;
41
+ const eventIdSource = (_d = options.eventId) != null ? _d : defaultOptions.eventId;
28
42
  const properties = {
29
- ...(_d = defaultOptions.properties) != null ? _d : {},
30
- ...(_e = options.properties) != null ? _e : {}
43
+ ...(_e = defaultOptions.properties) != null ? _e : {},
44
+ ...(_f = options.properties) != null ? _f : {}
31
45
  };
32
46
  let currentRun;
33
47
  function log(msg) {
@@ -58,7 +72,7 @@ function createSubscriber(agent, eventShipper, traceShipper, defaultOptions, opt
58
72
  }
59
73
  currentRun = void 0;
60
74
  }
61
- const eventId = randomUUID();
75
+ const eventId = resolveEventId(eventIdSource);
62
76
  const rootSpan = traceShipper ? traceShipper.startSpan({
63
77
  name: "ai.event",
64
78
  eventId,
@@ -127,41 +141,30 @@ function createSubscriber(agent, eventShipper, traceShipper, defaultOptions, opt
127
141
  if (usage) {
128
142
  currentRun.totalInputTokens += usage.input;
129
143
  currentRun.totalOutputTokens += usage.output;
130
- if (usage.cacheRead) currentRun.totalCacheReadTokens += usage.cacheRead;
144
+ if (usage.cacheRead > 0) currentRun.totalCacheReadTokens += usage.cacheRead;
131
145
  }
132
146
  if (!traceShipper || !currentRun.currentTurnSpan) return;
133
147
  const rawProvider = provider;
134
148
  const rawModelId = bareModel;
135
149
  const stopReason = "stopReason" in message && typeof message.stopReason === "string" ? message.stopReason : void 0;
136
- const llmAttrs = [
137
- attrString("ai.operationId", "generateText")
138
- ];
150
+ const llmAttrs = [];
151
+ pushAttr(llmAttrs, attrString("ai.operationId", "generateText"));
139
152
  if (rawProvider) {
140
- llmAttrs.push(attrString("gen_ai.system", rawProvider));
153
+ pushAttr(llmAttrs, attrString("gen_ai.system", rawProvider));
141
154
  }
142
155
  if (rawModelId) {
143
- llmAttrs.push(
144
- attrString("gen_ai.response.model", rawModelId),
145
- attrString("gen_ai.request.model", rawModelId)
146
- );
147
- }
148
- if (usage) {
149
- llmAttrs.push(
150
- attrInt("gen_ai.usage.input_tokens", usage.input),
151
- attrInt("gen_ai.usage.output_tokens", usage.output)
152
- );
153
- if (usage.cacheRead) {
154
- llmAttrs.push(attrInt("gen_ai.usage.cache_read_tokens", usage.cacheRead));
155
- }
156
+ pushAttr(llmAttrs, attrString("gen_ai.response.model", rawModelId));
157
+ pushAttr(llmAttrs, attrString("gen_ai.request.model", rawModelId));
156
158
  }
159
+ llmAttrs.push(...modelSpendSpanAttributes({ provider: rawProvider, usage }));
157
160
  if (assistantText) {
158
- llmAttrs.push(attrString("ai.response.text", truncate(assistantText)));
161
+ pushAttr(llmAttrs, attrString("ai.response.text", truncate(assistantText)));
159
162
  }
160
163
  if (currentRun.currentInput) {
161
- llmAttrs.push(attrString("ai.prompt", truncate(currentRun.currentInput)));
164
+ pushAttr(llmAttrs, attrString("ai.prompt", truncate(currentRun.currentInput)));
162
165
  }
163
166
  if (stopReason) {
164
- llmAttrs.push(attrString("ai.stop_reason", stopReason));
167
+ pushAttr(llmAttrs, attrString("ai.stop_reason", stopReason));
165
168
  }
166
169
  const llmSpan = traceShipper.startSpan({
167
170
  name: model != null ? model : "llm",
@@ -170,6 +173,13 @@ function createSubscriber(agent, eventShipper, traceShipper, defaultOptions, opt
170
173
  attributes: llmAttrs
171
174
  });
172
175
  const errorForSpan = stopReason === "error" || stopReason === "aborted" ? "errorMessage" in message && typeof message.errorMessage === "string" ? message.errorMessage : `Assistant ${stopReason}` : void 0;
176
+ if (errorForSpan) {
177
+ const assistantError = new Error(errorForSpan);
178
+ assistantError.name = stopReason === "aborted" ? "AbortError" : "PiAgentError";
179
+ currentRun.error = assistantError;
180
+ } else {
181
+ currentRun.error = void 0;
182
+ }
173
183
  traceShipper.endSpan(llmSpan, errorForSpan ? { error: errorForSpan } : void 0);
174
184
  const toolCallIds = extractToolCallIds(message);
175
185
  for (const tcId of toolCallIds) {
@@ -256,9 +266,9 @@ function createSubscriber(agent, eventShipper, traceShipper, defaultOptions, opt
256
266
  if (!traceShipper || !toolSpan) return;
257
267
  const endAttrs = [];
258
268
  const argsStr = truncate(safeStringify(args));
259
- if (argsStr) endAttrs.push(attrString("ai.toolCall.args", argsStr));
269
+ if (argsStr) pushAttr(endAttrs, attrString("ai.toolCall.args", argsStr));
260
270
  const resultStr = truncate(safeStringify(result));
261
- if (resultStr) endAttrs.push(attrString("ai.toolCall.result", resultStr));
271
+ if (resultStr) pushAttr(endAttrs, attrString("ai.toolCall.result", resultStr));
262
272
  traceShipper.endSpan(toolSpan, {
263
273
  attributes: endAttrs,
264
274
  ...isError ? { error: `Tool "${toolName}" failed` } : {}
@@ -285,42 +295,44 @@ function createSubscriber(agent, eventShipper, traceShipper, defaultOptions, opt
285
295
  }
286
296
  const outputText = capText(run.outputParts.join(""));
287
297
  if (traceShipper && run.rootSpan) {
288
- const rootAttrs = [
289
- attrString("ai.operationId", "generateText")
290
- ];
298
+ const rootAttrs = [];
299
+ pushAttr(rootAttrs, attrString("ai.operationId", "generateText"));
291
300
  if (run.lastModel) {
292
301
  run.rootSpan.name = run.lastProvider ? `${run.lastProvider}/${run.lastModel}` : run.lastModel;
293
- rootAttrs.push(attrString("gen_ai.response.model", run.lastModel));
302
+ pushAttr(rootAttrs, attrString("gen_ai.response.model", run.lastModel));
294
303
  }
295
304
  if (run.currentInput) {
296
- rootAttrs.push(attrString("ai.prompt", truncate(run.currentInput)));
305
+ pushAttr(rootAttrs, attrString("ai.prompt", truncate(run.currentInput)));
297
306
  }
298
307
  if (outputText) {
299
- rootAttrs.push(attrString("ai.response.text", truncate(outputText)));
308
+ pushAttr(rootAttrs, attrString("ai.response.text", truncate(outputText)));
300
309
  }
301
310
  if (run.totalInputTokens > 0) {
302
- rootAttrs.push(attrInt("gen_ai.usage.input_tokens", run.totalInputTokens));
311
+ pushAttr(rootAttrs, attrInt("gen_ai.usage.input_tokens", run.totalInputTokens));
303
312
  }
304
313
  if (run.totalOutputTokens > 0) {
305
- rootAttrs.push(attrInt("gen_ai.usage.output_tokens", run.totalOutputTokens));
314
+ pushAttr(rootAttrs, attrInt("gen_ai.usage.output_tokens", run.totalOutputTokens));
306
315
  }
307
316
  if (run.totalCacheReadTokens > 0) {
308
- rootAttrs.push(attrInt("gen_ai.usage.cache_read_tokens", run.totalCacheReadTokens));
317
+ pushAttr(rootAttrs, attrInt("gen_ai.usage.cache_read_tokens", run.totalCacheReadTokens));
309
318
  }
310
- rootAttrs.push(attrInt("ai.total_turns", run.turnNumber));
319
+ pushAttr(rootAttrs, attrInt("ai.total_turns", run.turnNumber));
311
320
  traceShipper.endSpan(run.rootSpan, { attributes: rootAttrs });
312
321
  }
313
322
  if (eventShipper) {
314
323
  eventShipper.finish(run.eventId, {
315
324
  userId: userId != null ? userId : "anonymous",
316
325
  model: run.lastModel || void 0,
317
- output: outputText || void 0,
326
+ output: run.error ? void 0 : outputText || void 0,
327
+ usage: {
328
+ promptTokens: run.totalInputTokens > 0 ? run.totalInputTokens : void 0,
329
+ completionTokens: run.totalOutputTokens > 0 ? run.totalOutputTokens : void 0
330
+ },
331
+ error: run.error,
318
332
  properties: {
319
333
  ...properties,
320
334
  sdk_version: libraryVersion,
321
335
  ...run.lastProvider ? { "ai.provider": run.lastProvider } : {},
322
- ...run.totalInputTokens > 0 ? { "ai.usage.prompt_tokens": run.totalInputTokens } : {},
323
- ...run.totalOutputTokens > 0 ? { "ai.usage.completion_tokens": run.totalOutputTokens } : {},
324
336
  ...run.totalCacheReadTokens > 0 ? { "ai.usage.cache_read_tokens": run.totalCacheReadTokens } : {}
325
337
  }
326
338
  }).catch(() => {
@@ -421,6 +433,7 @@ function createRaindropPiAgent(opts) {
421
433
  userId: opts.userId,
422
434
  convoId: opts.convoId,
423
435
  eventName: opts.eventName,
436
+ eventId: opts.eventId,
424
437
  properties: opts.properties
425
438
  };
426
439
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raindrop-ai/pi-agent",
3
- "version": "0.0.10",
3
+ "version": "0.1.1",
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.1.2"
57
+ "@raindrop-ai/core": "0.2.0"
58
58
  },
59
59
  "tsup": {
60
60
  "entry": [