@raindrop-ai/pi-agent 0.0.4 → 0.0.6

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.
@@ -35,7 +35,6 @@ type SpanIds = {
35
35
  spanIdB64: string;
36
36
  parentSpanIdB64?: string;
37
37
  };
38
-
39
38
  type Attachment = {
40
39
  type: string;
41
40
  role: string;
@@ -84,6 +83,21 @@ type EventShipperOptions = {
84
83
  * Pass `null` to opt out of all mirroring (including auto-detect).
85
84
  */
86
85
  localDebuggerUrl?: string | null;
86
+ /**
87
+ * Optional project slug. When set, every outbound cloud request includes an
88
+ * `X-Raindrop-Project-Id: <projectId>` header. Empty / whitespace-only
89
+ * values are ignored. Slug format is validated on construction but never
90
+ * throws — the backend returns 400 on invalid values.
91
+ */
92
+ projectId?: string;
93
+ /**
94
+ * Per-field character cap applied to event input/output BEFORE buffering
95
+ * or serialization, so oversized payloads cost the cap — not the payload —
96
+ * on the calling code path. Truncated fields end with
97
+ * `...[truncated by raindrop]` and never exceed the cap, marker included.
98
+ * Defaults to 1,000,000 (matching the Python SDK).
99
+ */
100
+ maxTextFieldChars?: number;
87
101
  };
88
102
  declare class EventShipper {
89
103
  private baseUrl;
@@ -94,16 +108,46 @@ declare class EventShipper {
94
108
  private sdkName;
95
109
  private prefix;
96
110
  private defaultEventName;
111
+ private projectId;
97
112
  private context;
98
113
  private buffers;
99
114
  private sticky;
100
115
  private timers;
101
116
  private inFlight;
117
+ private maxTextFieldCharsOpt;
118
+ /**
119
+ * Epoch ms deadline while `shutdown()` is draining; undefined otherwise.
120
+ * Checked before every POST issued during the final flush.
121
+ */
122
+ private shutdownDeadlineAt;
123
+ /**
124
+ * Set once `shutdown()` begins and never cleared. Sends issued after the
125
+ * drain window (stragglers, or flush work the deadline abandoned
126
+ * mid-drain) run as a single short attempt instead of regaining the full
127
+ * retry schedule.
128
+ */
129
+ private hasShutdown;
102
130
  /** URL of the local debugger / Workshop daemon, when one is reachable. */
103
131
  private localDebuggerUrl;
104
132
  constructor(opts: EventShipperOptions);
105
133
  isDebugEnabled(): boolean;
106
134
  private authHeaders;
135
+ private requestHeaders;
136
+ /**
137
+ * Build the retry/timeout options for one POST, honoring the shutdown
138
+ * deadline. Returns `null` when the shutdown drain window is exhausted —
139
+ * the caller must drop the payload (with a rate-limited warning) instead
140
+ * of issuing a request that could outlive process exit.
141
+ *
142
+ * Checked fresh on EVERY send, so a shutdown that begins while the flush
143
+ * path is mid-drain takes effect immediately: no further retries, and the
144
+ * per-attempt timeout is clamped to the remaining window. After
145
+ * `shutdown()` returns (deadline cleared, `hasShutdown` still set),
146
+ * sends — late callers, or flush work the deadline abandoned mid-drain —
147
+ * run as a single short attempt rather than regaining the full retry
148
+ * schedule.
149
+ */
150
+ private requestOpts;
107
151
  patch(eventId: string, patch: Patch): Promise<void>;
108
152
  finish(eventId: string, patch: {
109
153
  output?: string;
@@ -115,6 +159,7 @@ declare class EventShipper {
115
159
  shutdown(): Promise<void>;
116
160
  trackSignal(signal: SignalInput): Promise<void>;
117
161
  identify(users: IdentifyInput | IdentifyInput[]): Promise<void>;
162
+ private warnShutdownDrop;
118
163
  private flushOne;
119
164
  }
120
165
  /**
@@ -159,6 +204,13 @@ type TraceShipperOptions = {
159
204
  * Pass `null` to opt out of all mirroring (including auto-detect).
160
205
  */
161
206
  localDebuggerUrl?: string | null;
207
+ /**
208
+ * Optional project slug. When set, every OTLP trace export includes an
209
+ * `X-Raindrop-Project-Id: <projectId>` header. Empty / whitespace-only
210
+ * values are ignored. Slug format is validated on construction but never
211
+ * throws — the backend returns 400 on invalid values.
212
+ */
213
+ projectId?: string;
162
214
  /**
163
215
  * Per-span hook that fires for every OTLP span right before the span is
164
216
  * shipped (both to the Raindrop API and to a local debugger). Lets callers
@@ -193,6 +245,15 @@ type TraceShipperOptions = {
193
245
  * still want some redaction in that case.
194
246
  */
195
247
  disableDefaultRedaction?: boolean;
248
+ /**
249
+ * Per-attribute character cap applied to every span attribute string value
250
+ * right before the span enters a ship path, so a multi-MB prompt/tool
251
+ * payload can never make the batch `JSON.stringify` (which runs on the
252
+ * event loop) cost seconds. Truncated values end with
253
+ * `...[truncated by raindrop]` and never exceed the cap, marker included.
254
+ * Defaults to 1,000,000 (matching the Python SDK).
255
+ */
256
+ maxTextFieldChars?: number;
196
257
  };
197
258
  declare class TraceShipper {
198
259
  private baseUrl;
@@ -207,6 +268,7 @@ declare class TraceShipper {
207
268
  private flushIntervalMs;
208
269
  private maxBatchSize;
209
270
  private maxQueueSize;
271
+ private projectId;
210
272
  private queue;
211
273
  private timer;
212
274
  private inFlight;
@@ -214,7 +276,32 @@ declare class TraceShipper {
214
276
  private localDebuggerUrl;
215
277
  private transformSpanHook;
216
278
  private disableDefaultRedaction;
279
+ private maxTextFieldCharsOpt;
280
+ /**
281
+ * Epoch ms deadline while `shutdown()` is draining; undefined otherwise.
282
+ * Checked before every batch POST issued during the final flush.
283
+ */
284
+ private shutdownDeadlineAt;
285
+ /**
286
+ * Set once `shutdown()` begins and never cleared. Sends issued after the
287
+ * drain window (stragglers, or flush work the deadline abandoned
288
+ * mid-drain) run as a single short attempt instead of regaining the full
289
+ * retry schedule.
290
+ */
291
+ private hasShutdown;
217
292
  constructor(opts: TraceShipperOptions);
293
+ /**
294
+ * Cap every string attribute value on the span. O(#attributes) length
295
+ * checks; only oversized values pay a slice. Runs AFTER the redaction
296
+ * pipeline so the default secret-scrub still sees parseable JSON in
297
+ * `ai.request.providerOptions` / `ai.response.providerMetadata` (capping
298
+ * first could cut a JSON blob mid-way, fail the parse, and ship secrets
299
+ * in the surviving prefix).
300
+ *
301
+ * A stricter `OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT` env var is honored
302
+ * for span content, matching the Python SDK and the OTel SDK convention.
303
+ */
304
+ private capSpanAttributes;
218
305
  /**
219
306
  * Apply the user `transformSpan` hook (if any) followed by the default
220
307
  * redactor (unless disabled). Returns either the (possibly new) span to
@@ -232,6 +319,7 @@ declare class TraceShipper {
232
319
  private redactSpan;
233
320
  isDebugEnabled(): boolean;
234
321
  private authHeaders;
322
+ private requestHeaders;
235
323
  startSpan(args: {
236
324
  name: string;
237
325
  parent?: {
@@ -264,6 +352,8 @@ declare class TraceShipper {
264
352
  }): void;
265
353
  enqueue(span: OtlpSpan): void;
266
354
  flush(): Promise<void>;
355
+ /** See EventShipper.requestOpts — same shutdown-budget semantics. */
356
+ private requestOpts;
267
357
  shutdown(): Promise<void>;
268
358
  }
269
359
 
@@ -35,7 +35,6 @@ type SpanIds = {
35
35
  spanIdB64: string;
36
36
  parentSpanIdB64?: string;
37
37
  };
38
-
39
38
  type Attachment = {
40
39
  type: string;
41
40
  role: string;
@@ -84,6 +83,21 @@ type EventShipperOptions = {
84
83
  * Pass `null` to opt out of all mirroring (including auto-detect).
85
84
  */
86
85
  localDebuggerUrl?: string | null;
86
+ /**
87
+ * Optional project slug. When set, every outbound cloud request includes an
88
+ * `X-Raindrop-Project-Id: <projectId>` header. Empty / whitespace-only
89
+ * values are ignored. Slug format is validated on construction but never
90
+ * throws — the backend returns 400 on invalid values.
91
+ */
92
+ projectId?: string;
93
+ /**
94
+ * Per-field character cap applied to event input/output BEFORE buffering
95
+ * or serialization, so oversized payloads cost the cap — not the payload —
96
+ * on the calling code path. Truncated fields end with
97
+ * `...[truncated by raindrop]` and never exceed the cap, marker included.
98
+ * Defaults to 1,000,000 (matching the Python SDK).
99
+ */
100
+ maxTextFieldChars?: number;
87
101
  };
88
102
  declare class EventShipper {
89
103
  private baseUrl;
@@ -94,16 +108,46 @@ declare class EventShipper {
94
108
  private sdkName;
95
109
  private prefix;
96
110
  private defaultEventName;
111
+ private projectId;
97
112
  private context;
98
113
  private buffers;
99
114
  private sticky;
100
115
  private timers;
101
116
  private inFlight;
117
+ private maxTextFieldCharsOpt;
118
+ /**
119
+ * Epoch ms deadline while `shutdown()` is draining; undefined otherwise.
120
+ * Checked before every POST issued during the final flush.
121
+ */
122
+ private shutdownDeadlineAt;
123
+ /**
124
+ * Set once `shutdown()` begins and never cleared. Sends issued after the
125
+ * drain window (stragglers, or flush work the deadline abandoned
126
+ * mid-drain) run as a single short attempt instead of regaining the full
127
+ * retry schedule.
128
+ */
129
+ private hasShutdown;
102
130
  /** URL of the local debugger / Workshop daemon, when one is reachable. */
103
131
  private localDebuggerUrl;
104
132
  constructor(opts: EventShipperOptions);
105
133
  isDebugEnabled(): boolean;
106
134
  private authHeaders;
135
+ private requestHeaders;
136
+ /**
137
+ * Build the retry/timeout options for one POST, honoring the shutdown
138
+ * deadline. Returns `null` when the shutdown drain window is exhausted —
139
+ * the caller must drop the payload (with a rate-limited warning) instead
140
+ * of issuing a request that could outlive process exit.
141
+ *
142
+ * Checked fresh on EVERY send, so a shutdown that begins while the flush
143
+ * path is mid-drain takes effect immediately: no further retries, and the
144
+ * per-attempt timeout is clamped to the remaining window. After
145
+ * `shutdown()` returns (deadline cleared, `hasShutdown` still set),
146
+ * sends — late callers, or flush work the deadline abandoned mid-drain —
147
+ * run as a single short attempt rather than regaining the full retry
148
+ * schedule.
149
+ */
150
+ private requestOpts;
107
151
  patch(eventId: string, patch: Patch): Promise<void>;
108
152
  finish(eventId: string, patch: {
109
153
  output?: string;
@@ -115,6 +159,7 @@ declare class EventShipper {
115
159
  shutdown(): Promise<void>;
116
160
  trackSignal(signal: SignalInput): Promise<void>;
117
161
  identify(users: IdentifyInput | IdentifyInput[]): Promise<void>;
162
+ private warnShutdownDrop;
118
163
  private flushOne;
119
164
  }
120
165
  /**
@@ -159,6 +204,13 @@ type TraceShipperOptions = {
159
204
  * Pass `null` to opt out of all mirroring (including auto-detect).
160
205
  */
161
206
  localDebuggerUrl?: string | null;
207
+ /**
208
+ * Optional project slug. When set, every OTLP trace export includes an
209
+ * `X-Raindrop-Project-Id: <projectId>` header. Empty / whitespace-only
210
+ * values are ignored. Slug format is validated on construction but never
211
+ * throws — the backend returns 400 on invalid values.
212
+ */
213
+ projectId?: string;
162
214
  /**
163
215
  * Per-span hook that fires for every OTLP span right before the span is
164
216
  * shipped (both to the Raindrop API and to a local debugger). Lets callers
@@ -193,6 +245,15 @@ type TraceShipperOptions = {
193
245
  * still want some redaction in that case.
194
246
  */
195
247
  disableDefaultRedaction?: boolean;
248
+ /**
249
+ * Per-attribute character cap applied to every span attribute string value
250
+ * right before the span enters a ship path, so a multi-MB prompt/tool
251
+ * payload can never make the batch `JSON.stringify` (which runs on the
252
+ * event loop) cost seconds. Truncated values end with
253
+ * `...[truncated by raindrop]` and never exceed the cap, marker included.
254
+ * Defaults to 1,000,000 (matching the Python SDK).
255
+ */
256
+ maxTextFieldChars?: number;
196
257
  };
197
258
  declare class TraceShipper {
198
259
  private baseUrl;
@@ -207,6 +268,7 @@ declare class TraceShipper {
207
268
  private flushIntervalMs;
208
269
  private maxBatchSize;
209
270
  private maxQueueSize;
271
+ private projectId;
210
272
  private queue;
211
273
  private timer;
212
274
  private inFlight;
@@ -214,7 +276,32 @@ declare class TraceShipper {
214
276
  private localDebuggerUrl;
215
277
  private transformSpanHook;
216
278
  private disableDefaultRedaction;
279
+ private maxTextFieldCharsOpt;
280
+ /**
281
+ * Epoch ms deadline while `shutdown()` is draining; undefined otherwise.
282
+ * Checked before every batch POST issued during the final flush.
283
+ */
284
+ private shutdownDeadlineAt;
285
+ /**
286
+ * Set once `shutdown()` begins and never cleared. Sends issued after the
287
+ * drain window (stragglers, or flush work the deadline abandoned
288
+ * mid-drain) run as a single short attempt instead of regaining the full
289
+ * retry schedule.
290
+ */
291
+ private hasShutdown;
217
292
  constructor(opts: TraceShipperOptions);
293
+ /**
294
+ * Cap every string attribute value on the span. O(#attributes) length
295
+ * checks; only oversized values pay a slice. Runs AFTER the redaction
296
+ * pipeline so the default secret-scrub still sees parseable JSON in
297
+ * `ai.request.providerOptions` / `ai.response.providerMetadata` (capping
298
+ * first could cut a JSON blob mid-way, fail the parse, and ship secrets
299
+ * in the surviving prefix).
300
+ *
301
+ * A stricter `OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT` env var is honored
302
+ * for span content, matching the Python SDK and the OTel SDK convention.
303
+ */
304
+ private capSpanAttributes;
218
305
  /**
219
306
  * Apply the user `transformSpan` hook (if any) followed by the default
220
307
  * redactor (unless disabled). Returns either the (possibly new) span to
@@ -232,6 +319,7 @@ declare class TraceShipper {
232
319
  private redactSpan;
233
320
  isDebugEnabled(): boolean;
234
321
  private authHeaders;
322
+ private requestHeaders;
235
323
  startSpan(args: {
236
324
  name: string;
237
325
  parent?: {
@@ -264,6 +352,8 @@ declare class TraceShipper {
264
352
  }): void;
265
353
  enqueue(span: OtlpSpan): void;
266
354
  flush(): Promise<void>;
355
+ /** See EventShipper.requestOpts — same shutdown-budget semantics. */
356
+ private requestOpts;
267
357
  shutdown(): Promise<void>;
268
358
  }
269
359
 
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-Cxs_NTx0.cjs';
2
+ import { A as Attachment } from './index.d-D0J2tEXx.cjs';
3
3
 
4
4
  /**
5
5
  * Options for the Raindrop Pi Agent client.
@@ -12,6 +12,12 @@ interface RaindropPiAgentOptions {
12
12
  writeKey?: string;
13
13
  /** API endpoint URL (defaults to production) */
14
14
  endpoint?: string;
15
+ /**
16
+ * Optional Raindrop project slug. When set, every outbound cloud request
17
+ * carries an `X-Raindrop-Project-Id` header. Unset → no header (the project
18
+ * resolves to `default` server-side; byte-identical to prior behavior).
19
+ */
20
+ projectId?: string;
15
21
  /** Default user ID for all events */
16
22
  userId?: string;
17
23
  /** Default conversation ID to group related events */
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-Cxs_NTx0.js';
2
+ import { A as Attachment } from './index.d-D0J2tEXx.js';
3
3
 
4
4
  /**
5
5
  * Options for the Raindrop Pi Agent client.
@@ -12,6 +12,12 @@ interface RaindropPiAgentOptions {
12
12
  writeKey?: string;
13
13
  /** API endpoint URL (defaults to production) */
14
14
  endpoint?: string;
15
+ /**
16
+ * Optional Raindrop project slug. When set, every outbound cloud request
17
+ * carries an `X-Raindrop-Project-Id` header. Unset → no header (the project
18
+ * resolves to `default` server-side; byte-identical to prior behavior).
19
+ */
20
+ projectId?: string;
15
21
  /** Default user ID for all events */
16
22
  userId?: string;
17
23
  /** Default conversation ID to group related events */
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ import {
3
3
  TraceShipper,
4
4
  attrInt,
5
5
  attrString,
6
+ capText,
6
7
  extractAssistantText,
7
8
  extractModelName,
8
9
  extractTokenUsage,
@@ -16,7 +17,7 @@ import {
16
17
  resolveLocalDebuggerBaseUrl,
17
18
  safeStringify,
18
19
  truncate
19
- } from "./chunk-EWIO36KH.js";
20
+ } from "./chunk-5F37XTG6.js";
20
21
 
21
22
  // src/internal/subscriber.ts
22
23
  function createSubscriber(agent, eventShipper, traceShipper, defaultOptions, options, debug) {
@@ -105,9 +106,10 @@ function createSubscriber(agent, eventShipper, traceShipper, defaultOptions, opt
105
106
  if (!currentRun) return;
106
107
  const userText = extractUserText(message);
107
108
  if (userText !== void 0) {
108
- currentRun.currentInput = userText;
109
+ const cappedInput = capText(userText);
110
+ currentRun.currentInput = cappedInput;
109
111
  if (eventShipper) {
110
- eventShipper.patch(currentRun.eventId, { input: userText }).catch(() => {
112
+ eventShipper.patch(currentRun.eventId, { input: cappedInput }).catch(() => {
111
113
  });
112
114
  }
113
115
  return;
@@ -276,7 +278,7 @@ function createSubscriber(agent, eventShipper, traceShipper, defaultOptions, opt
276
278
  traceShipper.endSpan(run.currentTurnSpan);
277
279
  run.currentTurnSpan = void 0;
278
280
  }
279
- const outputText = run.outputParts.join("");
281
+ const outputText = capText(run.outputParts.join(""));
280
282
  if (traceShipper && run.rootSpan) {
281
283
  const rootAttrs = [
282
284
  attrString("ai.operationId", "generateText")
@@ -394,6 +396,7 @@ function createRaindropPiAgent(opts) {
394
396
  enabled: true,
395
397
  debug: ((_e = opts.events) == null ? void 0 : _e.debug) === true || envDebug,
396
398
  partialFlushMs: (_f = opts.events) == null ? void 0 : _f.partialFlushMs,
399
+ projectId: opts.projectId,
397
400
  localDebuggerUrl: opts.localWorkshopUrl
398
401
  }) : null;
399
402
  const traceShipper = tracesEnabled && (hasWriteKey || opts.endpoint || hasLocalDestination) ? new TraceShipper({
@@ -405,6 +408,7 @@ function createRaindropPiAgent(opts) {
405
408
  flushIntervalMs: (_i = opts.traces) == null ? void 0 : _i.flushIntervalMs,
406
409
  maxBatchSize: (_j = opts.traces) == null ? void 0 : _j.maxBatchSize,
407
410
  maxQueueSize: (_k = opts.traces) == null ? void 0 : _k.maxQueueSize,
411
+ projectId: opts.projectId,
408
412
  localDebuggerUrl: opts.localWorkshopUrl
409
413
  }) : null;
410
414
  const defaultOptions = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raindrop-ai/pi-agent",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
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",
@@ -59,7 +59,7 @@
59
59
  "tsup": "^8.5.1",
60
60
  "typescript": "^5.7.3",
61
61
  "vitest": "^2.1.9",
62
- "@raindrop-ai/core": "0.0.2"
62
+ "@raindrop-ai/core": "0.0.4"
63
63
  },
64
64
  "tsup": {
65
65
  "entry": [