@raindrop-ai/pi-agent 0.0.4 → 0.0.5

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,14 @@ type EventShipperOptions = {
84
83
  * Pass `null` to opt out of all mirroring (including auto-detect).
85
84
  */
86
85
  localDebuggerUrl?: string | null;
86
+ /**
87
+ * Per-field character cap applied to event input/output BEFORE buffering
88
+ * or serialization, so oversized payloads cost the cap — not the payload —
89
+ * on the calling code path. Truncated fields end with
90
+ * `...[truncated by raindrop]` and never exceed the cap, marker included.
91
+ * Defaults to 1,000,000 (matching the Python SDK).
92
+ */
93
+ maxTextFieldChars?: number;
87
94
  };
88
95
  declare class EventShipper {
89
96
  private baseUrl;
@@ -99,11 +106,39 @@ declare class EventShipper {
99
106
  private sticky;
100
107
  private timers;
101
108
  private inFlight;
109
+ private maxTextFieldCharsOpt;
110
+ /**
111
+ * Epoch ms deadline while `shutdown()` is draining; undefined otherwise.
112
+ * Checked before every POST issued during the final flush.
113
+ */
114
+ private shutdownDeadlineAt;
115
+ /**
116
+ * Set once `shutdown()` begins and never cleared. Sends issued after the
117
+ * drain window (stragglers, or flush work the deadline abandoned
118
+ * mid-drain) run as a single short attempt instead of regaining the full
119
+ * retry schedule.
120
+ */
121
+ private hasShutdown;
102
122
  /** URL of the local debugger / Workshop daemon, when one is reachable. */
103
123
  private localDebuggerUrl;
104
124
  constructor(opts: EventShipperOptions);
105
125
  isDebugEnabled(): boolean;
106
126
  private authHeaders;
127
+ /**
128
+ * Build the retry/timeout options for one POST, honoring the shutdown
129
+ * deadline. Returns `null` when the shutdown drain window is exhausted —
130
+ * the caller must drop the payload (with a rate-limited warning) instead
131
+ * of issuing a request that could outlive process exit.
132
+ *
133
+ * Checked fresh on EVERY send, so a shutdown that begins while the flush
134
+ * path is mid-drain takes effect immediately: no further retries, and the
135
+ * per-attempt timeout is clamped to the remaining window. After
136
+ * `shutdown()` returns (deadline cleared, `hasShutdown` still set),
137
+ * sends — late callers, or flush work the deadline abandoned mid-drain —
138
+ * run as a single short attempt rather than regaining the full retry
139
+ * schedule.
140
+ */
141
+ private requestOpts;
107
142
  patch(eventId: string, patch: Patch): Promise<void>;
108
143
  finish(eventId: string, patch: {
109
144
  output?: string;
@@ -115,6 +150,7 @@ declare class EventShipper {
115
150
  shutdown(): Promise<void>;
116
151
  trackSignal(signal: SignalInput): Promise<void>;
117
152
  identify(users: IdentifyInput | IdentifyInput[]): Promise<void>;
153
+ private warnShutdownDrop;
118
154
  private flushOne;
119
155
  }
120
156
  /**
@@ -193,6 +229,15 @@ type TraceShipperOptions = {
193
229
  * still want some redaction in that case.
194
230
  */
195
231
  disableDefaultRedaction?: boolean;
232
+ /**
233
+ * Per-attribute character cap applied to every span attribute string value
234
+ * right before the span enters a ship path, so a multi-MB prompt/tool
235
+ * payload can never make the batch `JSON.stringify` (which runs on the
236
+ * event loop) cost seconds. Truncated values end with
237
+ * `...[truncated by raindrop]` and never exceed the cap, marker included.
238
+ * Defaults to 1,000,000 (matching the Python SDK).
239
+ */
240
+ maxTextFieldChars?: number;
196
241
  };
197
242
  declare class TraceShipper {
198
243
  private baseUrl;
@@ -214,7 +259,32 @@ declare class TraceShipper {
214
259
  private localDebuggerUrl;
215
260
  private transformSpanHook;
216
261
  private disableDefaultRedaction;
262
+ private maxTextFieldCharsOpt;
263
+ /**
264
+ * Epoch ms deadline while `shutdown()` is draining; undefined otherwise.
265
+ * Checked before every batch POST issued during the final flush.
266
+ */
267
+ private shutdownDeadlineAt;
268
+ /**
269
+ * Set once `shutdown()` begins and never cleared. Sends issued after the
270
+ * drain window (stragglers, or flush work the deadline abandoned
271
+ * mid-drain) run as a single short attempt instead of regaining the full
272
+ * retry schedule.
273
+ */
274
+ private hasShutdown;
217
275
  constructor(opts: TraceShipperOptions);
276
+ /**
277
+ * Cap every string attribute value on the span. O(#attributes) length
278
+ * checks; only oversized values pay a slice. Runs AFTER the redaction
279
+ * pipeline so the default secret-scrub still sees parseable JSON in
280
+ * `ai.request.providerOptions` / `ai.response.providerMetadata` (capping
281
+ * first could cut a JSON blob mid-way, fail the parse, and ship secrets
282
+ * in the surviving prefix).
283
+ *
284
+ * A stricter `OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT` env var is honored
285
+ * for span content, matching the Python SDK and the OTel SDK convention.
286
+ */
287
+ private capSpanAttributes;
218
288
  /**
219
289
  * Apply the user `transformSpan` hook (if any) followed by the default
220
290
  * redactor (unless disabled). Returns either the (possibly new) span to
@@ -264,6 +334,8 @@ declare class TraceShipper {
264
334
  }): void;
265
335
  enqueue(span: OtlpSpan): void;
266
336
  flush(): Promise<void>;
337
+ /** See EventShipper.requestOpts — same shutdown-budget semantics. */
338
+ private requestOpts;
267
339
  shutdown(): Promise<void>;
268
340
  }
269
341
 
@@ -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,14 @@ type EventShipperOptions = {
84
83
  * Pass `null` to opt out of all mirroring (including auto-detect).
85
84
  */
86
85
  localDebuggerUrl?: string | null;
86
+ /**
87
+ * Per-field character cap applied to event input/output BEFORE buffering
88
+ * or serialization, so oversized payloads cost the cap — not the payload —
89
+ * on the calling code path. Truncated fields end with
90
+ * `...[truncated by raindrop]` and never exceed the cap, marker included.
91
+ * Defaults to 1,000,000 (matching the Python SDK).
92
+ */
93
+ maxTextFieldChars?: number;
87
94
  };
88
95
  declare class EventShipper {
89
96
  private baseUrl;
@@ -99,11 +106,39 @@ declare class EventShipper {
99
106
  private sticky;
100
107
  private timers;
101
108
  private inFlight;
109
+ private maxTextFieldCharsOpt;
110
+ /**
111
+ * Epoch ms deadline while `shutdown()` is draining; undefined otherwise.
112
+ * Checked before every POST issued during the final flush.
113
+ */
114
+ private shutdownDeadlineAt;
115
+ /**
116
+ * Set once `shutdown()` begins and never cleared. Sends issued after the
117
+ * drain window (stragglers, or flush work the deadline abandoned
118
+ * mid-drain) run as a single short attempt instead of regaining the full
119
+ * retry schedule.
120
+ */
121
+ private hasShutdown;
102
122
  /** URL of the local debugger / Workshop daemon, when one is reachable. */
103
123
  private localDebuggerUrl;
104
124
  constructor(opts: EventShipperOptions);
105
125
  isDebugEnabled(): boolean;
106
126
  private authHeaders;
127
+ /**
128
+ * Build the retry/timeout options for one POST, honoring the shutdown
129
+ * deadline. Returns `null` when the shutdown drain window is exhausted —
130
+ * the caller must drop the payload (with a rate-limited warning) instead
131
+ * of issuing a request that could outlive process exit.
132
+ *
133
+ * Checked fresh on EVERY send, so a shutdown that begins while the flush
134
+ * path is mid-drain takes effect immediately: no further retries, and the
135
+ * per-attempt timeout is clamped to the remaining window. After
136
+ * `shutdown()` returns (deadline cleared, `hasShutdown` still set),
137
+ * sends — late callers, or flush work the deadline abandoned mid-drain —
138
+ * run as a single short attempt rather than regaining the full retry
139
+ * schedule.
140
+ */
141
+ private requestOpts;
107
142
  patch(eventId: string, patch: Patch): Promise<void>;
108
143
  finish(eventId: string, patch: {
109
144
  output?: string;
@@ -115,6 +150,7 @@ declare class EventShipper {
115
150
  shutdown(): Promise<void>;
116
151
  trackSignal(signal: SignalInput): Promise<void>;
117
152
  identify(users: IdentifyInput | IdentifyInput[]): Promise<void>;
153
+ private warnShutdownDrop;
118
154
  private flushOne;
119
155
  }
120
156
  /**
@@ -193,6 +229,15 @@ type TraceShipperOptions = {
193
229
  * still want some redaction in that case.
194
230
  */
195
231
  disableDefaultRedaction?: boolean;
232
+ /**
233
+ * Per-attribute character cap applied to every span attribute string value
234
+ * right before the span enters a ship path, so a multi-MB prompt/tool
235
+ * payload can never make the batch `JSON.stringify` (which runs on the
236
+ * event loop) cost seconds. Truncated values end with
237
+ * `...[truncated by raindrop]` and never exceed the cap, marker included.
238
+ * Defaults to 1,000,000 (matching the Python SDK).
239
+ */
240
+ maxTextFieldChars?: number;
196
241
  };
197
242
  declare class TraceShipper {
198
243
  private baseUrl;
@@ -214,7 +259,32 @@ declare class TraceShipper {
214
259
  private localDebuggerUrl;
215
260
  private transformSpanHook;
216
261
  private disableDefaultRedaction;
262
+ private maxTextFieldCharsOpt;
263
+ /**
264
+ * Epoch ms deadline while `shutdown()` is draining; undefined otherwise.
265
+ * Checked before every batch POST issued during the final flush.
266
+ */
267
+ private shutdownDeadlineAt;
268
+ /**
269
+ * Set once `shutdown()` begins and never cleared. Sends issued after the
270
+ * drain window (stragglers, or flush work the deadline abandoned
271
+ * mid-drain) run as a single short attempt instead of regaining the full
272
+ * retry schedule.
273
+ */
274
+ private hasShutdown;
217
275
  constructor(opts: TraceShipperOptions);
276
+ /**
277
+ * Cap every string attribute value on the span. O(#attributes) length
278
+ * checks; only oversized values pay a slice. Runs AFTER the redaction
279
+ * pipeline so the default secret-scrub still sees parseable JSON in
280
+ * `ai.request.providerOptions` / `ai.response.providerMetadata` (capping
281
+ * first could cut a JSON blob mid-way, fail the parse, and ship secrets
282
+ * in the surviving prefix).
283
+ *
284
+ * A stricter `OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT` env var is honored
285
+ * for span content, matching the Python SDK and the OTel SDK convention.
286
+ */
287
+ private capSpanAttributes;
218
288
  /**
219
289
  * Apply the user `transformSpan` hook (if any) followed by the default
220
290
  * redactor (unless disabled). Returns either the (possibly new) span to
@@ -264,6 +334,8 @@ declare class TraceShipper {
264
334
  }): void;
265
335
  enqueue(span: OtlpSpan): void;
266
336
  flush(): Promise<void>;
337
+ /** See EventShipper.requestOpts — same shutdown-budget semantics. */
338
+ private requestOpts;
267
339
  shutdown(): Promise<void>;
268
340
  }
269
341
 
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-CRPiWjXE.cjs';
3
3
 
4
4
  /**
5
5
  * Options for the Raindrop Pi Agent client.
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-CRPiWjXE.js';
3
3
 
4
4
  /**
5
5
  * Options for the Raindrop Pi Agent client.
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-2NGOEVWI.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")
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.5",
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.3"
63
63
  },
64
64
  "tsup": {
65
65
  "entry": [